Files
ignis_app/README.md

147 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Ignis App
Мобильное приложение для управления умными лампами WiZ через self-hosted сервер [Ignis Core](https://git.akokos.ru/artem.kokos/ignis-core).
## Возможности
- **Мульти-дом** -- поддержка нескольких серверов Ignis (квартира, дача, друзья). Каждый дом -- отдельный сервер со своим URL и API-ключом.
- **Группы ламп** -- создание, удаление и управление. При создании группы есть product-валидация, автогенерация `ID`, предупреждение о конфликтах по устройствам и более честный перескан сети.
- **Управление освещением:**
- Включение/выключение
- Яркость 10--100% с шагом 10%
- Цветовая температура 2700--6500K с шагом 100K
- RGB-цвет через HSV-пикер
- Сцены (загружаются с сервера, отображаются с человекочитаемыми названиями)
- Таймер "включить на 4 часа"
- **Расписания** -- одноразовые таймеры с выбором даты/времени и повторяющиеся задачи с выбором дней недели. Просмотр, создание, валидация и отмена активных задач.
- **API-ключи** -- просмотр, создание, отзыв и повторная активация гостевых ключей для администраторов с отдельным UX для только что созданного ключа.
- **Статистика и лог событий** -- просмотр сводки по группам и последних событий сервера.
- **Геофенс и расстояния** -- live-дистанция до дома в UI и опциональное автовыключение света при уходе. Геофенс работает для текущего активного дома, показывает диагностический статус и использует cooldown/re-arm поведение.
- **Устойчивость к ошибкам** -- гранулярные состояния загрузки (`LoadState`), централизованная обработка сетевых сбоев, soft-ошибки при управлении ползунками без спама в UI.
## Стек
- Flutter 3.x / Dart
- Riverpod -- управление состоянием
- Dio -- HTTP-клиент
- SharedPreferences -- локальное хранение несекретных настроек
- Flutter Secure Storage -- безопасное хранение API-ключей
- Geolocator -- геолокация
- Workmanager -- периодические фоновые задачи
- Flutter Local Notifications -- локальные уведомления
## Структура проекта
```text
lib/
├── app/
│ ├── app_bootstrap.dart -- bootstrap приложения и навигация
│ ├── build_info.dart -- метаданные сборки (дата, git hash)
│ ├── error_message.dart -- форматирование ошибок API и сети
│ └── load_state.dart -- универсальный стейт загрузки (idle/loading/data/error)
├── main.dart -- точка входа, тема, роутер
├── models/
│ ├── api_key_info.dart -- типизированная модель API-ключа
│ ├── auth_info.dart -- информация об авторизации
│ ├── event_log_item.dart -- лог событий
│ ├── home_config.dart -- несекретная конфигурация сервера
│ ├── ignis_device.dart -- устройство умного дома
│ ├── ignis_group.dart -- группа устройств и её состояние
│ ├── ignis_scene.dart -- сцена освещения
│ ├── schedule_task.dart -- задача расписания
│ └── stats_summary.dart -- статистика
├── services/
│ ├── api_client.dart -- HTTP-клиент к Ignis Core API
│ ├── credentials_storage.dart -- безопасное хранение ключей
│ ├── geofence_worker.dart -- фоновая логика геофенса
│ └── settings_service.dart -- хранение списка "домов"
├── features/
│ ├── api_keys/providers/ -- управление гостевыми API-ключами
│ ├── auth/providers/ -- auth/me и auth-state
│ ├── groups/ -- валидация и логика форм групп
│ ├── homes/ -- дома, геолокация, geofence sync/runtime
│ ├── remote/providers/ -- polling групп, устройства, сцены, control errors
│ ├── schedules/ -- логика и providers расписаний
│ ├── shared/providers/ -- базовые core providers
│ └── stats/providers/ -- статистика и лог событий
├── providers/
│ └── providers.dart -- compatibility barrel для публичных provider-экспортов
├── screens/
│ ├── api_keys_screen.dart -- экран гостевых API-ключей
│ ├── event_log_screen.dart -- последние события сервера
│ ├── homes_screen.dart -- список домов, distance/geofence статус
│ ├── home_edit_screen.dart -- создание и редактирование дома
│ ├── remote_screen.dart -- основной экран управления светом
│ ├── group_edit_screen.dart -- создание группы с выбором устройств
│ ├── schedules_screen.dart -- создание и просмотр расписаний
│ └── stats_screen.dart -- статистика по командам
└── widgets/
├── build_info_text.dart -- лейбл с версией сборки
├── group_card.dart
├── load_error_view.dart -- универсальный виджет ошибок и retry
└── color_picker.dart
```
## Сборка
```bash
# Зависимости
flutter pub get
# Debug-запуск
flutter run
# Release APK (с пробросом build info)
flutter build apk --release --dart-define=IGNIS_BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" --dart-define=IGNIS_GIT_SHA="$(git rev-parse --short HEAD)"
```
APK: `build/app/outputs/flutter-apk/app-release.apk`
> Сейчас release APK подписывается debug-ключом из Flutter-шаблона. Для личной установки на телефон этого достаточно, для настоящего релиза подпись нужно заменить.
## Проверки
```bash
flutter analyze
flutter test
```
Текущий baseline зелёный: `flutter analyze`, `flutter test` и release APK сборка проходят штатно.
Дополнительно тестами уже прикрыты:
- typed parsing/load-state для основных backend-ответов;
- geofence distance/runtime логика;
- чистая логика форм расписаний и групп;
- provider-мутаторы для расписаний, таймера 4h и API-ключей;
- widget-сценарии форм домов, групп, расписаний и API-ключей;
- widget-сценарии `RemoteScreen`, `GroupCard` и error/retry-потоков.
Сейчас baseline клиента закрывается примерно `60` тестами и уже ловит regressions не только в helper-логике, но и в основных пользовательских сценариях.
## Настройка
При первом запуске приложение попросит добавить "дом" -- указать адрес сервера Ignis и API-ключ. После этого откроется пульт управления группами.
Если задать координаты дома, экран домов начнёт показывать расстояние до активного дома. Если дополнительно включить автовыключение при уходе и выдать Android фоновые разрешения на геолокацию и уведомления, приложение сможет в фоне выключать свет при удалении от текущего активного дома.
Для добавления второго дома: кнопка "домик" в левом верхнем углу пульта -> экран домов -> кнопка "+".
API-ключи хранятся отдельно от конфигурации домов в `flutter_secure_storage`. Старые ключи из `SharedPreferences` мигрируются автоматически.
## API
Приложение работает с [Ignis Core API](https://git.akokos.ru/artem.kokos/ignis-core) -- self-hosted бэкенд на FastAPI (контракт OpenAPI 3.1.0).
Авторизация происходит через заголовок `X-API-Key`.
Доменный слой на стороне клиента полностью типизирован.
## Текущие ограничения
- Целевая платформа сейчас Android.
- Release APK пока подписывается debug-ключом из Flutter-шаблона.
- Build info в APK показывает дату сборки и короткий git hash текущего `HEAD`. Если сборка делается поверх незакоммиченного рабочего дерева, hash будет от последнего коммита, а не от локальных незакоммиченных изменений.
- Android-specific поведение реального background execution, уведомлений, runtime permissions и OEM battery restrictions пока подтверждается в основном ручными проверками на устройстве, а не automated integration-тестами.
## Лицензия
Частный проект.