Приложение на Flutter для Android, которое следит за цветовым индикатором через камеру смартфона и поднимает тревогу при смене цвета — мелодией и уведомлением. Дополнительно умеет транслировать видео и статус на второй телефон или в браузер по локальной сети, без интернета.
Типичный сценарий: зелёная лампочка на оборудовании загорается красным — Color Watch замечает это и сразу сигналит. Подходит для наблюдения за серверной стойкой, котлом, 3D-принтером, зарядкой или любым прибором с цветовым индикатором, пока вы заняты другими делами.
- 🎥 Отслеживание смены цвета в реальном времени. Анализируется центральная зона кадра, цвет переводится в HSV — это устойчивее к перепадам освещения.
- 🔔 Звуковая и визуальная тревога при изменении: мелодия звонка + системное уведомление.
- ♾️ Режим 24/7 — фоновый foreground-сервис, наблюдение продолжается со свёрнутым приложением.
- 📡 Трансляция на второй телефон по локальной сети без интернета.
- 🪟 Плавающее окно на телефоне-зрителе — видео поверх других приложений.
- 💻 Веб-зритель — любой браузер на компьютере открывает страницу с видео и оповещениями, установка не требуется.
- 🌗 Тёмная и светлая темы с запоминанием выбора (есть режим «Система»).
- ⚙️ Экран настроек с историей: версия приложения, журнал смен цвета (и на камере, и у зрителя) и история подключений.
Один и тот же APK ставится на оба телефона, режим выбирается на старте:
| Режим | Что делает |
|---|---|
| Камера | Следит за цветом в центральной рамке, поднимает локальный HTTP-сервер и показывает адрес для подключения. |
| Зритель | Подключается к камере по адресу, показывает живое видео, опрашивает статус и сам сигналит при смене цвета. |
Интернет не нужен ни одному устройству — связь идёт напрямую внутри локальной сети телефона-камеры:
- На телефоне-камере включите точку доступа (hotspot).
- Второй телефон или компьютер подключите к этой точке доступа по Wi-Fi.
- В приложении на камере выберите Камера — она покажет адрес вида
http://192.168.43.1:8080. - На зрителе выберите Зритель, введите адрес и нажмите «Подключиться» (либо просто откройте адрес в браузере на компьютере).
Если есть общий Wi-Fi роутер, можно подключить оба устройства к нему — адрес будет другим, он тоже отображается на экране камеры.
- Камера стримит кадры, анализирует цвет центральной зоны (HSV) и параллельно
кодирует уменьшенный кадр в JPEG в фоновом изоляте (
compute+package:image). - Локальный HTTP-сервер (
package:shelf) раздаёт видео и статус другим устройствам (эндпоинты — в таблице ниже). - Зритель часто опрашивает
/frame(одиночные JPEG-кадры) и рисует их черезImage.memory, а раз в секунду —/status; при смене цвета проигрывает мелодию и шлёт уведомление. Покадровый опрос надёжнее MJPEG:Image.networkи часть браузеров не умеют показывать потокmultipart/x-mixed-replace.
| Эндпоинт | Назначение |
|---|---|
/ |
Веб-страница зрителя для браузера |
/frame |
Текущий кадр одной картинкой (JPEG) — основной способ показа видео |
/stream |
Устаревший MJPEG-поток (оставлен для совместимости) |
/status |
JSON с текущим цветом и временем последней смены |
Цвет классифицируется по оттенку (Hue): зелёный ≈ 90–160°, красный ≈ 0° и
345–360°. Пиксели с низкой насыщенностью или яркостью игнорируются, чтобы тусклый
или тёмный фон не давал ложных срабатываний. Пороги настраиваются в
lib/shared.dart (метод classify).
Телефон-камера раздаёт готовую страницу зрителя — отдельная программа для компьютера не нужна:
- Подключите компьютер к точке доступа камеры по Wi-Fi.
- Откройте в браузере адрес с экрана камеры (например
http://192.168.43.1:8080). - Нажмите «Включить звук и уведомления» — браузеры блокируют звук и уведомления до первого действия пользователя.
После этого браузер показывает живое видео и при смене цвета пищит (Web Audio) и
шлёт уведомление. Работает в любой ОС без установки. Сама страница —
assets/viewer.html.
В режиме «Зритель» после подключения доступна кнопка «Плавающее окно» — она выводит видеопоток поверх других приложений, чтобы видеть индикатор в углу экрана, занимаясь другими делами.
- При первом запуске Android попросит разрешение «Поверх других приложений»
(
SYSTEM_ALERT_WINDOW) — его нужно выдать вручную. - Окно перетаскивается пальцем, закрывается крестиком в углу.
- Overlay работает в отдельном Flutter-движке (ограничение платформы), поэтому
он не делит состояние с основным экраном, а сам подключается к камере и
опрашивает кадры
/frame. Адрес передаётся ему автоматически.
Сборка полностью автоматизирована через GitHub Actions — локальная установка инструментов не нужна:
- Запушьте изменения в ветку
mainилиmaster. - Во вкладке Actions автоматически запустится workflow Build APK.
- Откройте завершённый запуск → Artifacts → скачайте
color-watch-apk. - Установите
app-release.apkна оба телефона — режим выбирается в приложении.
Папка android/ намеренно не хранится в репозитории: workflow генерирует её
заново через flutter create при каждой сборке. Это гарантирует, что версии
Gradle/AGP/Kotlin всегда совпадают, и устраняет частую причину сбоев сборки.
Кастомный манифест, иконка и фиксированные версии накладываются поверх
сгенерированной обвязки.
lib/main.dart # стартовый экран выбора режима + подключение тем
lib/camera_page.dart # режим камеры: детект + HTTP-сервер + foreground-сервис
lib/viewer_page.dart # режим зрителя: видео + опрос статуса + плавающее окно
lib/overlay_view.dart # UI плавающего окна (отдельный Flutter-движок)
lib/settings_page.dart # экран настроек: тема, версия, история
lib/app_state.dart # контроллер темы и хранилище истории (shared_preferences)
lib/theme.dart # светлая/тёмная темы и переключатель
lib/shared.dart # классификатор цвета, статус-пилюля, мелодия + уведомления
assets/viewer.html # страница веб-зрителя для браузера
assets/alarm.mp3 # мелодия звонка
assets/icon.png # иконка приложения (генерится в иконки при сборке)
overrides/AndroidManifest.xml # разрешения + сервисы, накладывается в CI
.github/workflows/build.yml # сборка APK
| Компонент | Назначение |
|---|---|
| Flutter / Dart | Основной фреймворк и язык |
camera |
Доступ к камере и поток кадров |
image |
Кодирование кадров в JPEG |
shelf |
Локальный HTTP-сервер на камере |
http |
Запросы статуса со стороны зрителя |
flutter_local_notifications |
Системные уведомления |
audioplayers |
Воспроизведение мелодии |
flutter_foreground_task |
Фоновый сервис 24/7 |
flutter_overlay_window |
Плавающее окно поверх приложений |
network_info_plus |
Определение локального IP-адреса |
shared_preferences |
Хранение выбранной темы и истории |
package_info_plus |
Версия приложения на экране настроек |
flutter_launcher_icons |
Генерация иконки приложения при сборке |
- minSdk 21 — ставится на Android 5.0 и новее, включая Android 10.
- targetSdk 34 — зафиксирован в workflow: приложение работает на Android 16, но не попадает под самые строгие runtime-ограничения Android 15+ для foreground-сервисов.
- compileSdk оставлен таким, как ставит Flutter (CameraX 1.5 требует 35+).
- Для Android 14+ тип foreground-сервиса
cameraобъявлен вoverrides/AndroidManifest.xml— без этого сервис на новых Android не стартует. - Уведомления запрашиваются в runtime (требуется для Android 13+).
Нагрузка распределяется удачно: телефон-камера на более старом Android (где правила мягче) выполняет самую требовательную работу, а телефон-зритель на новом Android использует только сеть и уведомления.
- Освещение — главный источник ложных срабатываний. Пороги цветов почти всегда требуют подстройки под конкретную лампочку и условия.
- Фоновая работа ограничена системой Android и зависит от производителя: некоторые прошивки агрессивно завершают фоновые сервисы. Реалистичный режим 24/7 — телефон на зарядке и на подставке.
- Видео — это поток отдельных JPEG-кадров с опросом, а не полноценное видео реального времени; кадры уменьшены ради скорости.
- Связь требует общей локальной сети или точки доступа; совсем без сети устройства не найдут друг друга.
- Позиционирование — телефон-камеру нужно держать неподвижно, нацеленным на индикатор, желательно на подставке.
| Версия | Что добавлено |
|---|---|
| 1.0 | Отслеживание смены цвета через камеру + уведомление. Сборка APK через GitHub Actions. |
| 1.1 | Мелодия звонка при смене цвета. Режим работы 24/7 через foreground-сервис. |
| 1.2 | Трансляция видео и статуса на второй телефон. Режимы «Камера» и «Зритель». |
| 1.3 | Поддержка Android 10–16: фиксация targetSdk, явное объявление типа сервиса. |
| 1.4 | Вывод видео в плавающее окно поверх других приложений. |
| 1.5 | Веб-зритель для компьютера: страница с видео и оповещениями в браузере. |
| 1.6 | Тёмная/светлая тема, экран настроек с историей смен цвета и подключений, обновлённый интерфейс Material 3 и редизайн веб-зрителя. Покадровое видео (/frame) вместо MJPEG. |