| README.md | ||
АСО-Контроль — Mobile
Мобильное приложение инспектора: с ним человек выходит на борт, считывает RFID-метки аварийно-спасательного оборудования и сразу видит, чего не хватает, что просрочено и что неисправно.
Приложение — тонкий клиент. Вся бизнес-логика (сравнение факта с эталоном, расчёт статусов, отправка заявок инженерам) живёт на бэкенде. Задача мобилки — собрать коды меток из доступного источника, отправить их и понятно показать ответ сервера.
Платформа и фреймворк не зафиксированы. Нужно: работа с NFC телефона, работа с внешним ридером по Bluetooth LE, HTTP-клиент, локальное хранение токена. Это умеют и нативные Android/iOS, и кроссплатформенные решения. Выбирайте по тому, с чем справится команда, и фиксируйте выбор в этом README. Основная целевая платформа — Android (внешние UHF-ридеры в практике почти всегда Android).
Решения, принятые по проекту
| Вопрос | Решение |
|---|---|
| Источники меток | Три: NFC телефона, внешний ридер по BLE, ручной ввод кода. За одним общим интерфейсом + мок-источник для демо. |
| Офлайн-режим | Нет. Приложение работает только при наличии сети. Без связи осмотр не начинается — это должно быть честно показано пользователю, а не выглядеть как зависание. |
| Роли | Инспектор и Администратор. Инженеров в приложении нет — заявка уходит им через бэкенд во внешнюю систему. |
| Админские функции | Приложение показывает админу расширенные экраны (справочники, привязка меток, пользователи), но полноценное управление парком — задача будущей веб-панели. |
Что означает «только онлайн» на практике
Это главный риск сценария: в самолёте сети может не быть. Поэтому:
- состояние сети видно в интерфейсе постоянно, а не только в момент ошибки;
- при обрыве связи во время осмотра приложение не теряет контекст: сессия осмотра живёт на сервере, после восстановления сети экран продолжается с того же места;
- отправка считываний идёт батчами с ретраями, с показом «не отправлено: N»;
- все изменяющие запросы уходят с
Idempotency-Key, чтобы повтор после обрыва не создал дубль осмотра или заявки.
Что должно делать приложение
1. Вход и сессия
- Экран входа по логину/паролю, токен в защищённом хранилище устройства (Keystore / Keychain), не в обычных настройках.
- Автопродление токена, выход по истечении, кнопка «Выйти».
- Интерфейс подстраивается под роль, пришедшую с сервера. Роль не хранится локально как источник правды — проверка прав всё равно на бэкенде.
2. Слой источников метки — ключевая абстракция
Один интерфейс TagSource с четырьмя реализациями:
| Источник | Назначение |
|---|---|
NfcTagSource |
встроенный NFC телефона. Дистанция сантиметры — подходит для точечной проверки единицы, не для обхода салона. |
BleReaderTagSource |
внешний UHF-ридер по Bluetooth LE: сопряжение, подключение, поток считываний, уровень заряда, отключение. Основной режим для массового осмотра. |
ManualTagSource |
ручной ввод кода метки: метка не читается, оторвана, повреждена. |
MockTagSource |
генерирует коды из заранее заданного набора. Нужен обязательно — чтобы разрабатывать и показывать приложение без железа. |
Требования к слою:
- Экраны осмотра работают с интерфейсом, а не с конкретным ридером: смена модели ридера не должна затрагивать UI.
- Переключение источника на ходу, без перезапуска осмотра.
- Дедупликация: одна и та же метка, прочитанная ридером десять раз за секунду, — это одно считывание.
- Каждое считывание несёт
source(nfc/ble_reader/manual/mock) — сервер сохраняет это для аудита. - Выбор мок-источника — через настройки сборки или скрытый экран отладки, а не доступной кнопкой в боевом интерфейсе.
3. Процесс осмотра — главный сценарий
- Инспектор выбирает борт.
- Приложение начинает осмотр на сервере и получает эталонный перечень.
- Экран осмотра показывает перечень: что ещё не найдено, что найдено, что проблемное. Прогресс виден цифрой и полосой.
- Инспектор обходит салон, метки считываются и уходят батчами на сервер.
- Каждое считывание отражается в списке: найдено / не из перечня / просрочено / неисправно / метка неизвестна.
- Чего ридер не нашёл — инспектор помечает вручную: отсутствует или неисправно, с комментарием и фото.
- По неисправному или отсутствующему можно создать заявку инженерам.
- Закрытие осмотра → итоговый отчёт на экране.
4. Фото и комментарии
- Фото проблемной единицы с камеры, сжатие перед отправкой.
- Комментарий текстом. Голосовой ввод — опционально, если останется время.
5. Разбор и история
- История осмотров: свои и (для админа) все, с фильтрами.
- Карточка единицы оборудования: тип, место, сроки, статус, история.
- Список проблемных единиц по борту.
6. Экраны администратора
- Привязка RFID-метки к единице: считать метку → выбрать единицу → привязать.
- Справочники: типы АСО, борта, места установки — просмотр и базовое редактирование.
- Пользователи: создание, смена роли.
- Просмотр отправленных заявок инженерам и их статуса доставки.
Views (экраны)
| Экран | Что показывает / делает | Роль |
|---|---|---|
| Splash | проверка токена, проверка доступности сервера, маршрутизация | — |
| Login | логин, пароль, ошибки входа, адрес сервера (для dev) | — |
| Home / Борты | список ВС с бортовым номером и сводным статусом готовности, поиск, индикатор сети | И, А |
| Карточка борта | данные ВС, сводка проблем, кнопка «Начать осмотр», история осмотров | И, А |
| Выбор источника метки | NFC / внешний ридер / ручной ввод; статус подключения ридера, заряд | И, А |
| Сопряжение ридера | поиск BLE-устройств, подключение, проверка связи, переподключение | И, А |
| Осмотр: прогресс | перечень борта по местам установки, найдено/осталось, прогресс, индикатор неотправленных считываний | И, А |
| Осмотр: поток считываний | лента последних меток с вердиктом сервера, цветовая маркировка | И, А |
| Осмотр: карточка единицы | тип, серийный номер, место, сроки, статус; действия: отметить вручную, фото, комментарий, создать заявку | И, А |
| Осмотр: ручной ввод кода | ввод кода метки с клавиатуры, подсказка о формате, проверка через сервер | И, А |
| Осмотр: подтверждение закрытия | сводка перед закрытием: найдено N из M, проблемных K, что отсутствует | И, А |
| Итоговый отчёт осмотра | результат закрытого осмотра, список расхождений, поделиться/сохранить | И, А |
| Создание заявки | единица, причина, приоритет, комментарий, фото; подтверждение отправки | И, А |
| Заявки | список созданных заявок и статус доставки во внешнюю систему | И, А |
| История осмотров | список осмотров с фильтрами по борту, дате, инспектору | И, А |
| Карточка оборудования | полные данные единицы и её история: осмотры, обслуживание, смены метки | И, А |
| Поиск по метке | считать метку вне осмотра и узнать, что это и в каком состоянии | И, А |
| Срок истекает | список единиц с истекающими сроками, фильтр по дням | И, А |
| Админ: привязка меток | считать метку → выбрать единицу → привязать / отвязать | А |
| Админ: справочники | типы АСО, борта, места установки | А |
| Админ: эталонный перечень борта | просмотр и правка состава оборудования борта | А |
| Админ: пользователи | список, создание, смена роли, сброс пароля | А |
| Настройки | адрес сервера, язык, о приложении, выход | И, А |
| Отладка (dev-сборка) | включение мок-источника метки, лог запросов, набор тестовых меток | — |
| Нет сети | понятное состояние: что недоступно, кнопка «Повторить». Не экран-заглушка на весь экран, если осмотр уже идёт | — |
И — инспектор, А — администратор.
Требования к интерфейсу
- Приложением пользуются стоя, в салоне, иногда в перчатках: крупные элементы управления, минимум ввода текста, цель нажатия не меньше 48 dp.
- Статус единицы читается цветом и подписью/иконкой — не только цветом.
- Ни одно сетевое ожидание не выглядит как зависание: везде явная индикация.
- Ошибка сервера показывается человеческим текстом, а не кодом ответа.
- Весь интерфейс на русском; строки вынесены в ресурсы, а не вшиты в код.
Структура проекта
Ориентир. Смысл — чтобы работа с ридером, работа с API и экраны не были перемешаны: ридер должен подменяться моком, API — заглушкой, экраны — собираться без железа.
mobile/
├── README.md
├── .env.example # адрес API, флаги сборки
└── src/ (или app/, lib/)
├── app/ # точка входа, навигация, тема, DI
├── core/
│ ├── network/ # HTTP-клиент, токен, ретраи, Idempotency-Key
│ ├── storage/ # защищённое хранение токена
│ ├── connectivity/ # отслеживание сети
│ └── errors/ # маппинг ошибок сервера в сообщения
├── api/ # клиент бэкенда: модели и методы по эндпоинтам
├── tagsource/ # ⬅ ключевой модуль
│ ├── TagSource # общий интерфейс
│ ├── nfc/
│ ├── ble/ # драйвер внешнего ридера
│ ├── manual/
│ └── mock/
├── features/
│ ├── auth/
│ ├── aircraft/
│ ├── inspection/ # самый большой модуль: сессия, прогресс, лента
│ ├── equipment/
│ ├── requests/ # заявки инженерам
│ ├── reports/
│ └── admin/
├── ui/ # общие компоненты, цвета статусов, типографика
└── l10n/ # строки интерфейса
Тесты:
test/
├── unit/ # дедупликация считываний, маппинг ответов, состояние осмотра
└── integration/ # сценарий осмотра целиком на MockTagSource + заглушке API
Взаимодействие с бэкендом
Контракт — backend/openapi.json. Основные вызовы в порядке сценария:
| Шаг | Запрос |
|---|---|
| Вход | POST /auth/login, затем GET /auth/me |
| Список бортов | GET /aircraft |
| Карточка борта | GET /aircraft/{id}, GET /aircraft/{id}/status |
| Начать осмотр | POST /inspections → id сессии |
| Состояние осмотра | GET /inspections/{id} |
| Закрыть осмотр | POST /inspections/{id}/close |
| Отчёт | GET /inspections/{id}/report |
| Заявка инженерам | POST /maintenance-requests |
| Метка вне осмотра | GET /tags/lookup?code=... |
| Привязка метки (админ) | POST /tags/bind |
Правила:
- Приложение ничего не решает само: «просрочено», «не из перечня», «готовность борта» — всё это приходит с сервера. Дублировать правила на клиенте нельзя, иначе клиент и сервер разойдутся.
- Считывания отправляются батчами (по размеру или по таймеру, ~1–2 с), а не по одной метке на запрос.
- Изменяющие запросы — с
Idempotency-Key. - Адрес API — из конфигурации сборки, не вшит в код.
Задачи на разработку
Этап 1. Каркас
- Выбрать платформу и стек, зафиксировать в этом README.
- Создать проект, навигацию, тему, базовые компоненты.
- HTTP-клиент: базовый адрес из конфига, токен, обработка ошибок, ретраи.
- Отслеживание сети и единый индикатор состояния связи.
- Экран входа, защищённое хранение токена, выход.
Этап 2. Слой источников метки
- Интерфейс
TagSourceи общая модель считывания. MockTagSource— первым, чтобы дальше работать без железа.ManualTagSourceи экран ввода кода.NfcTagSourceна встроенном NFC.BleReaderTagSource: сопряжение, подключение, поток считываний, заряд, переподключение после разрыва.- Дедупликация и буферизация считываний, юнит-тесты.
- Экран выбора источника и экран сопряжения ридера.
Этап 3. Основной сценарий
- Список бортов и карточка борта.
- Старт осмотра, получение и отображение эталонного перечня.
- Экран прогресса: сгруппировано по местам установки, найдено/осталось.
- Лента считываний с вердиктами сервера.
- Отправка батчей, счётчик неотправленного, ретраи.
- Ручная отметка единицы: отсутствует / неисправно, комментарий.
- Фото проблемной единицы, сжатие и отправка.
- Закрытие осмотра и экран итогового отчёта.
- Поведение при потере сети посреди осмотра — отдельно проверить и отладить.
Этап 4. Заявки и история
- Создание заявки инженерам из осмотра и из карточки единицы.
- Список заявок и статус доставки.
- История осмотров с фильтрами.
- Карточка оборудования с историей.
- Поиск по метке вне осмотра.
- Список истекающих сроков.
Этап 5. Администратор
- Привязка и отвязка меток.
- Просмотр и правка справочников.
- Эталонный перечень борта.
- Пользователи и роли.
Этап 6. Качество и демо
- Экран отладки: включение мок-источника, набор тестовых меток.
- Юнит-тесты на состояние осмотра и дедупликацию.
- Интеграционный прогон сценария на моке.
- Проверка на реальном устройстве с реальным ридером.
- Сборка демо-APK, прогнанный сценарий для демо-дня: вход → борт → осмотр → нехватка → заявка → отчёт.
- README обновлён под фактическую реализацию.
Известные риски
| Риск | Что делаем |
|---|---|
| На борту нет сети, а приложение только онлайн | честная индикация, сессия на сервере, ретраи батчей; если станет блокером — обсуждать офлайн-режим как отдельное решение, а не допиливать на ходу |
| Внешний ридер недоступен к нужной дате | весь UI разрабатывается на MockTagSource, железо подключается последним |
| UHF-ридер ловит метки соседнего борта или склада | фильтрация по перечню борта на сервере, «лишние» метки показываются отдельной категорией, а не как ошибка |
| Метки на металле и в тесных отсеках читаются плохо | ручной ввод кода как полноценный путь, а не затычка |
| Контракт API меняется по ходу | openapi.yaml — единственный источник правды, изменения проговариваются с бэкендом до реализации |
Правила работы с репозиторием
- Ветки:
mainзащищена, работа вfeature/<кратко>,fix/<кратко>. - Merge в
mainтолько через PR и ревью. - Секреты и ключи подписи — не в репозиторий.
.envв.gitignore. - Новый экран — сразу со состояниями загрузки, ошибки и пустого списка.
- Меняется поведение — обновляется вики проекта.