135 lines
12 KiB
Markdown
135 lines
12 KiB
Markdown
# NNNet
|
||
|
||
Проект для школьного офлайн-месседжера на базе **BLE P2P mesh-сети**.
|
||
|
||
## Цель
|
||
Создать систему общения между учениками и учителями без зависимости от интернета:
|
||
- обмен сообщениями в пределах школы;
|
||
- работа в условиях отсутствия Wi-Fi/мобильной сети;
|
||
- безопасное взаимодействие с базовой модерацией.
|
||
|
||
## Текущее состояние
|
||
- BLE discovery + advertising работают.
|
||
- Реализован минимальный GATT transport для обмена mesh-пакетами.
|
||
- Есть foreground service, Room-хранилище, ACK/retry очередь и UI в стиле Telegram.
|
||
- Реализованы главный экран со списком чатов, отдельный экран диалога, меню `три точки -> Настройки`, ручная проверка обновлений и опциональная автопроверка через `version.json`.
|
||
- В меню `три точки` доступны `Карта сети`, `Пакеты` и `Настройки`.
|
||
- Добавлены профили пользователей: `firstName`, `lastName`, `username`, описание, локальное редактирование профиля и поиск профиля по `username`, имени, фамилии, полному имени и `peerId`.
|
||
- Профили распространяются как mesh-пакеты и кэшируются узлами локально; по найденному `username` можно получить `peerId`, и наоборот по `peerId` в UI показывается связанный `@username`, если claim уже известен.
|
||
- Username оформлен как подписанный lease-claim на 14 дней: если владелец не появляется в сети 2 недели, username снова становится свободным.
|
||
- Добавлен recovery bundle для переноса профиля и права на username на новый телефон даже без доступа к старому устройству.
|
||
- Добавлена защита от захвата чужого `username`: активный claim другого владельца не принимается, а смена `peerId` без подписи владельца не даёт забрать профиль.
|
||
- В настройки добавлены диагностические режимы: карта сети и журнал исходящих, входящих и транзитных пакетов.
|
||
- Обновление приложения выполняется через APK во временном каталоге: проверка версии, скачивание, остановка mesh и запуск системной установки через `Intent`.
|
||
- При выключенном Bluetooth приложение запрашивает его включение перед запуском mesh.
|
||
- Публикация APK и сайта автоматизирована через `Makefile`.
|
||
- Проект и Android-приложение приведены к имени `NNNet`, пакет приложения: `pro.nnnteam.nnnet`.
|
||
|
||
## Стек
|
||
- Android приложение: **Kotlin**
|
||
- Сборка: **Gradle** + `Gradle Wrapper`
|
||
- Промо/лендинг сайт: **HTML + CSS + JS + Bootstrap + Bootstrap Icons**
|
||
|
||
## Концепция сети
|
||
- Устройства действуют как BLE-ноды.
|
||
- Сообщения передаются hop-by-hop (mesh-подход).
|
||
- Каждый пакет имеет `messageId`, `ttl`, `senderId`, `timestamp`.
|
||
- Узлы хранят кратковременный кэш, чтобы избегать дубликатов.
|
||
- Доставка подтверждается ACK-пакетами.
|
||
|
||
## Основные компоненты Android-приложения
|
||
1. **BLE Transport Layer**
|
||
- сканирование соседей;
|
||
- реклама (advertising) своего присутствия;
|
||
- установление BLE-соединений;
|
||
- отправка/приём фрагментированных пакетов.
|
||
|
||
2. **Mesh Routing Layer**
|
||
- пересылка пакетов с TTL;
|
||
- фильтрация дублей;
|
||
- политика повторных отправок.
|
||
|
||
3. **Messaging Layer**
|
||
- личные сообщения;
|
||
- список чатов и отдельный экран диалога;
|
||
- статусы доставки (queued/sent/relayed/delivered).
|
||
|
||
4. **Data Layer**
|
||
- локальное хранилище (Room);
|
||
- история сообщений, очередь исходящей доставки, каталог профилей и журнал пакетов.
|
||
|
||
5. **Security Layer**
|
||
- идентификация пользователя;
|
||
- шифрование сообщений (напр. E2E для приватных чатов);
|
||
- защита от подмены/повтора пакетов.
|
||
|
||
## Этапы разработки (Roadmap)
|
||
1. Подготовка Android-проекта на Kotlin + Gradle.
|
||
2. Реализация BLE-обнаружения и рекламы узлов.
|
||
3. Реализация протокола пакетов (формат, TTL, ACK, дедупликация).
|
||
4. Базовый mesh-relay между 3+ устройствами.
|
||
5. Экран чатов и отправка текстовых сообщений.
|
||
6. Локальная БД (Room) и история сообщений.
|
||
7. Минимальное шифрование и валидация пакетов.
|
||
8. Тестирование в школьном сценарии (коридоры/классы/этажи).
|
||
9. Создание сайта проекта с описанием и кнопкой скачивания APK.
|
||
10. Подготовка релиза и документации для пилотного запуска.
|
||
|
||
## Задачи (Backlog)
|
||
- [x] Инициализировать Android-проект (`app` модуль + базовый каркас репозитория).
|
||
- [ ] Добавить Android-модули `domain`, `data`, `mesh`.
|
||
- [x] Настроить `minSdk` и базовые BLE-permissions.
|
||
- [x] Добавить foreground service для фоновой mesh-работы.
|
||
- [x] Описать формат сетевого пакета (черновой JSON codec + модель пакета).
|
||
- [x] Реализовать базовый BLE bootstrap (scanner + advertiser + runtime permissions).
|
||
- [x] Реализовать минимальный GATT-обмен между BLE-узлами.
|
||
- [x] Реализовать очередь отправки + ретраи + ACK timeout.
|
||
- [x] Добавить защиту от дубликатов по `messageId` (in-memory cache, базово).
|
||
- [x] Реализовать mesh-forwarding с ограничением TTL (routing action layer, базово).
|
||
- [x] Добавить список чатов и базовый UI окна сообщений.
|
||
- [x] Перенести настройки в меню `три точки` и убрать debug-лог из пользовательского интерфейса.
|
||
- [x] Подключить Room и базовую схему хранения.
|
||
- [x] Реализовать базовую регистрацию пользователя (локальный профиль).
|
||
- [x] Добавить кэш профилей из mesh-сети и поиск по `username`.
|
||
- [x] Добавить поиск профилей по имени, фамилии, полному имени и `peerId`.
|
||
- [x] Добавить lease-механику для `username` с автоматическим освобождением через 14 дней неактивности.
|
||
- [x] Добавить перенос профиля на новый телефон через recovery bundle.
|
||
- [x] Добавить защиту от захвата чужого `username` и подмены `peerId` в профиле.
|
||
- [x] Добавить журнал исходящих, входящих и транзитных пакетов.
|
||
- [x] Добавить режим карты сети в настройках.
|
||
- [x] Добавить логирование сети и debug-экран маршрутов.
|
||
- [x] Добавить ручную проверку обновлений и опциональную автопроверку клиента.
|
||
- [ ] Добавить шифрование полезной нагрузки сообщений.
|
||
- [ ] Написать инструментальные тесты BLE-обмена.
|
||
- [x] Создать сайт (`index.html`, `styles.css`, `app.js`) на Bootstrap.
|
||
- [x] Добавить страницу скачивания APK и раздел документации.
|
||
- [x] Подготовить CI-сборку (Gitea Actions `assembleDebug`).
|
||
- [x] Собрать и опубликовать debug APK на сайте проекта.
|
||
|
||
## Предлагаемая структура репозитория
|
||
- `android/` — Android-приложение (Kotlin + Gradle)
|
||
- `website/` — сайт проекта (HTML/CSS/JS + Bootstrap)
|
||
- `docs/` — документация протокола и архитектуры
|
||
|
||
## Автоматизация
|
||
- `make client-build RELEASE_NOTES='- пункт 1\n- пункт 2'` — обновить `release-notes.txt`, увеличить версию, собрать `debug` APK и создать git-тег `vX.Y.Z`.
|
||
- `make client-tag` — создать git-тег для текущей версии вручную.
|
||
- `make client-publish` — опубликовать собранный APK на сайт и обновить `version.json`.
|
||
- `make publish RELEASE_NOTES='- пункт 1\n- пункт 2'` — обновить release notes, увеличить версию, собрать APK, опубликовать клиент и перезагрузить `nginx`.
|
||
- Вместо `RELEASE_NOTES` можно передать `RELEASE_NOTES_FILE=/path/to/file`.
|
||
- `make server-start|server-stop|server-restart|server-status|server-rebuild` — управление `nginx`.
|
||
|
||
## Лицензия
|
||
Проект использует лицензию `GPL-3.0`. См. [LICENSE](/home/dom4k/nnnet/LICENSE).
|
||
|
||
## Ближайший следующий шаг
|
||
Добавить шифрование payload и инструментальные тесты BLE-обмена между несколькими устройствами.
|
||
|
||
## Ограничения сети
|
||
- Выделенный хост для NNNet не нужен: сеть строится как P2P mesh между устройствами.
|
||
- Все узлы равноправны на уровне текущей архитектуры: каждое устройство может обнаруживать соседей, принимать и ретранслировать пакеты.
|
||
- Количество пользователей не бесконечно. Практический предел зависит от плотности устройств, качества BLE-эфира, числа одновременных соединений, частоты ретрансляции и ограничений батареи Android.
|
||
- Каталог профилей хранится распределённо: каждый узел кэширует увиденные профильные пакеты, поэтому поиск по `username` зависит от того, успел ли профиль распространиться по mesh.
|
||
- Право на `username` определяется не текущим `peerId`, а подписанным claim владельца. Это защищает имя от простого копирования `peerId` другим устройством.
|
||
- Для школы такая схема подходит как офлайн-сеть без интернета, но для больших нагрузок всё равно понадобятся дополнительные оптимизации маршрутизации, дедупликации и доставки.
|