ИТ

BLE.KZ: автономный ESP32 трекер присутствия с BLE-маяками и Flutter-приложением

Коммерческие системы отслеживания присутствия стоят сотни долларов за комнату, привязывают к облаку вендора и перестают работать, как только падает интернет. Для домашней автоматизации, которой нужно знать, есть ли кто-то в гостиной или в гараже, эта зависимость абсурдна. Весь сенсорный слой — BLE-маяк и приёмник — помещается на двух микроконтроллерах за $12 каждый. Облако не добавляет ничего, кроме точки отказа и абонентской платы.

BLE.KZ — полная open-source экосистема ESP32 BLE трекера присутствия на базе ESPHome. Две прошивки — нода-маяк и трекер присутствия с e-ink дисплеем — плюс кроссплатформенное Flutter-приложение и Python CLI-монитор. Без облака, без интернета, без вендорлока. В этой статье разбираю архитектуру, два протокола маяков, кастомный драйвер e-ink дисплея, Flutter-приложение с семью каналами связи и запуск всего стека с нуля.

Содержание
  1. Зачем локальный трекинг присутствия
  2. Архитектура: три независимых слоя
  3. BLE-нода маяка (ESP32-S3)
  4. CoreInk трекер присутствия (M5Stack CoreInk)
  5. Flutter-приложение
  6. Два протокола маяков в одной кодовой базе
  7. Эмуляция Minew MBM03
  8. Двойная реклама BTHome v2 + iBeacon
  9. Движок отслеживания присутствия
  10. NUS-консоль: 16 интерактивных BLE-команд
  11. Кастомный драйвер e-ink дисплея
  12. Flutter-приложение: семь каналов связи
  13. Пять экранов
  14. Железо: что нужно для сборки
  15. Три конфигурации развёртывания
  16. 1. Только маяк (ble-node-beacon-min.yaml)
  17. 2. Маяк + трекер (ble-node-standalone.yaml)
  18. 3. CoreInk трекер присутствия (coreink-presence.yaml)
  19. Python CLI-монитор
  20. Быстрый старт: от нуля до трекинга за 15 минут
  21. Интеграция с Home Assistant
  22. Модель безопасности
  23. Лицензия и коммерческое использование
  24. Часто задаваемые вопросы
  25. Нужны ли оба устройства, или можно начать с одного?
  26. Насколько точна оценка расстояния?
  27. Работает ли с ESPresense?
  28. Можно ли отслеживать несколько устройств одновременно?
  29. Какое время работы от батареи у CoreInk?
  30. Почему ESPHome, а не Arduino или ESP-IDF напрямую?
  31. Связанные проекты
  32. Исходный код и документация

Зачем локальный трекинг присутствия

ESP32 BLE трекер присутствия — архитектура экосистемы BLE.KZ

Большинство решений для определения присутствия в экосистеме Home Assistant полагаются на ноды ESPresense или room-assistant, которые пересылают BLE-данные MQTT-брокеру, а тот уже кормит облачный движок автоматизации. Это работает — пока не перезагрузится роутер, не упадёт MQTT-брокер или облачный сервис не задепрекейтит API. Каждая дополнительная зависимость — ещё один сценарий отказа.

ESP32 BLE трекер присутствия BLE.KZ подходит к задаче иначе. Каждая нода работает как автономная точка доступа WiFi. Трекер присутствия поднимает собственный веб-сервер, обрабатывает RSSI-данные локально и выводит результаты на e-ink экран — и всё это без единого пакета, покидающего локальную сеть. MQTT и интеграция с Home Assistant существуют как опциональные слои, а не обязательные. Система работает в подвале без интернета так же, как в полностью обвязанном умном доме.

Приватность — вторая причина. BLE-данные о присутствии — кто в какой комнате, когда пришёл, когда ушёл — именно та информация, которая не должна покидать твои стены. Локальная обработка означает: нет телеметрического эндпоинта, нет стороннего обработчика данных, нет формы согласия GDPR.

Архитектура: три независимых слоя

Система состоит из трёх слоёв, которые можно разворачивать независимо или вместе.

BLE-нода маяка (ESP32-S3)

ESP32-S3-DevKitC-1 (вариант N16R8: 16 МБ флеш, 8 МБ PSRAM) с прошивкой ESPHome. Транслирует BLE-маяковые фреймы — в формате Minew MBM03 или iBeacon — и опционально сканирует целевое устройство для отслеживания присутствия. Нода поднимает веб-сервер с полноценным UI для управления, отдаёт все параметры через HTTP REST и может работать в режиме автономной точки доступа WiFi без каких-либо внешних зависимостей.

CoreInk трекер присутствия (M5Stack CoreInk)

M5Stack CoreInk — ESP32 с 1,54-дюймовым e-ink дисплеем 200×200, датчиком температуры и влажности SHT3xD, барометрическим датчиком QMP6988, батареей и RTTTL-пьезо. Эта нода делает основную работу: BLE-сканирование с 94% рабочим циклом, оценка расстояния по RSSI, классификация зон, мониторинг окружающей среды и интерактивная BLE-консоль с 16 командами через Nordic UART Service (NUS). Дополнительно она транслирует собственные маяковые фреймы BTHome v2 + iBeacon с актуальными данными сенсоров, чтобы Home Assistant обнаруживал её автоматически.

Flutter-приложение

Кроссплатформенное мобильное приложение (iOS и Android) на Flutter с Riverpod. Подключается к обеим нодам одновременно через семь каналов связи — SSE, HTTP REST, MQTT, пассивное BLE-сканирование, BLE GATT, NUS-консоль и mDNS-обнаружение — и предоставляет дашборды в реальном времени, панели настройки, BLE-сканер и интерактивный NUS-терминал. Само приложение тоже может выступать BLE iBeacon-маяком через Android platform channel, превращая телефон в отслеживаемый источник присутствия.

Два протокола маяков в одной кодовой базе

BLE.KZ реализует два протокола маяков, каждый из которых рассчитан на свой интеграционный контекст.

Эмуляция Minew MBM03

BLE-нода эмулирует коммерческий маяк Minew MBM03 вплоть до уровня GATT-сервисов. Она чередует два рекламных фрейма каждые 3 секунды:

  • Фрейм A — DeviceInfo (ID производителя Minew 0x0639): аппаратная ревизия, версия прошивки, уровень батареи, температура, имя устройства и MAC-адрес в manufacturer-specific data
  • Фрейм B — iBeacon (ID Apple 0x004C): стандартный proximity UUID, major/minor значения и measured power для оценки расстояния

Эмуляция включает полноценный GATT-сервер с двумя сервисами: Device Information (0x180A) с шестью характеристиками и проприетарный сервис Minew (0xFFF0) с характеристиками записи и уведомления. Это означает совместимость с мобильным приложением BeaconSET+ — UUID, major, minor, TX power, интервал рекламы и имя устройства настраиваются по BLE, защищённые паролем. Реализация занимает 701 строку C++ в minew_beacon.h и обрабатывает 13 кодов команд протокола BeaconSET+.

Двойная реклама BTHome v2 + iBeacon

CoreInk-трекер использует другую стратегию. Вместо эмуляции коммерческого маяка он транслирует два стандартных фрейма:

  • Фрейм A — BTHome v2 (UUID 0xFCD2): температура (int16, разрешение 0,01 C), влажность (uint16, 0,01%), атмосферное давление (uint24, 0,01 гПа) и Unix-таймстамп (uint48). Home Assistant обнаруживает эти данные автоматически через интеграцию BTHome — без настройки
  • Фрейм B — iBeacon с тем же UUID, что и Minew-маяк, обеспечивая совместимость с ESPresense и другими iBeacon-трекерами в доме

Оба фрейма перестраиваются динамически при каждом считывании сенсоров, так что рекламные данные всегда отражают текущее состояние. Реализация двойного маяка — 274 строки C++ в coreink_ble_adv.h.

Движок отслеживания присутствия

CoreInk-нода запускает BLE-сканер с рабочим циклом 94% — окно сканирования 300 мс при интервале 320 мс. Это близко к теоретическому максимуму ESP32, при котором ещё остаётся время на обновление дисплея и чтение сенсоров.

Оценка расстояния использует модель затухания в свободном пространстве:

d = 10 ^ ((P_measured - RSSI) / (10 * N))

Где P_measured — калиброванный RSSI на расстоянии 1 метр (типично -59 дБм), RSSI — текущее измерение, а N — показатель затухания (2,0 для открытого пространства, до 3,5 для помещений со стенами и мебелью). Все три параметра настраиваются в реальном времени через веб-интерфейс, Flutter-приложение или NUS-консоль.

Трекер классифицирует целевое устройство по зонам присутствия на основе расчётного расстояния и сообщает о событиях появления/исчезновения с настраиваемым таймаутом (5 секунд по умолчанию). Оценка качества сигнала отфильтровывает многолучевые отражения и помехи. Сырой RSSI, отфильтрованное расстояние, назначение зоны и счётчик рекламных пакетов — всё это доступно как ESPHome-сенсоры через веб-сервер и нативный API Home Assistant.

NUS-консоль: 16 интерактивных BLE-команд

CoreInk-трекер предоставляет Nordic UART Service (NUS) через BLE — серийную консоль, к которой можно подключиться из любого BLE-терминала или из Flutter-приложения. 16 команд покрывают всё от диагностики до настройки:

КомандаОтвет
statusПолный статус устройства: RSSI, качество сигнала, расстояние, зона, MAC цели, напряжение батареи, аптайм
rssiТекущий RSSI отслеживаемого устройства
macMAC-адрес целевого устройства
batНапряжение и процент батареи
tempТемпература (SHT3xD)
humВлажность (SHT3xD)
pressureАтмосферное давление (QMP6988)
envВсе показания окружающей среды одной командой
timeТекущее время устройства
locИнформация о зоне/местоположении
wifiСтатус WiFi-соединения и сигнал
portПорт веб-сервера
sound on/offВключить/выключить звук событий
deghostЗапустить цикл дегостинга e-ink дисплея
restartПерезагрузить устройство
helpСписок всех доступных команд

Flutter-приложение автоматически пингует NUS-консоль каждые 30 секунд для поддержания BLE-соединения и разбирает структурированные ответы в UI. Можно вводить произвольные команды прямо во вкладке NUS-терминала — удобно для отладки проблем с сигналом без необходимости доставать ноутбук.

Кастомный драйвер e-ink дисплея

Ранние ревизии M5Stack CoreInk поставляются с e-ink панелью GDEW0154M09 (контроллер JD79653A), которая не поддерживается стандартным компонентом ESPHome waveshare_epaper. BLE.KZ включает кастомный ESPHome-компонент — полноценный SPI-драйвер с аппаратно-специфичной инициализацией, пятью LUT-таблицами (VCOM, WW, BW, WB, BB), портированными из LovyanGFX, и дифференциальным частичным обновлением, которое пропускает неизменившиеся области экрана.

Ключевые параметры дисплея: 200×200 пикселей, аппаратный SPI на 4 МГц, шины питания VDH=11V/VDL=-11V, PLL на 50 Гц, CDI=0x97. Драйвер включает последовательность дегостинга (полная заливка чёрным, затем белым), доступную через NUS-команду deghost — e-ink панели со временем накапливают остаточные изображения, и периодический дегостинг сохраняет чёткость дисплея.

Более новые ревизии CoreInk используют панель GDEY0154D67, которая работает со штатным компонентом waveshare_epaper. Кастомный драйвер нужен только для ранних ревизий, но кодовая база определяет и обрабатывает оба варианта.

Flutter-приложение: семь каналов связи

Приложение-компаньон — 3 400 строк Dart в 35 файлах — подключается к нодам ESP32 BLE трекера присутствия через все доступные каналы одновременно:

  1. SSE (Server-Sent Events) — потоковая передача данных сенсоров в реальном времени с нативного веб-сервера ESPHome, с автоматическим переподключением через экспоненциальный бэкофф от 1 до 30 секунд
  2. HTTP REST — управление устройством: переключение свитчей, регулировка числовых параметров, нажатие кнопок, изменение текстовых полей
  3. MQTT — обмен сообщениями publish/subscribe с автоматическим парсингом иерархии топиков coreink-presence/#
  4. Пассивное BLE-сканирование — фоновое обнаружение всех BLE-устройств в радиусе действия, отсортированных по уровню сигнала
  5. BLE GATT — прямое чтение сенсоров CoreInk (батарея, температура, влажность, давление) с автопереподключением и экспоненциальным бэкоффом от 2 до 30 секунд
  6. NUS-консоль — интерактивный канал BLE-команд с автопингом для поддержания соединения
  7. mDNS-обнаружение — автоматическое обнаружение устройств по типу сервиса _esphomelib._tcp, чтобы не вводить IP-адреса вручную

На Android приложение может выступать BLE iBeacon-передатчиком через нативный platform channel, превращая сам телефон в отслеживаемый маяк. Удобно для трекинга личного присутствия без отдельного аппаратного маяка.

Пять экранов

  • Главная — дашборд с двумя карточками устройств: статус соединения, зона присутствия, расстояние, батарея и температура
  • BLE-нода — три панели: статус отслеживаемого устройства (зона, качество сигнала, расстояние, счётчик рекламных пакетов), конфигурация маяка (8 ползунков для UUID, major, minor, TX power, интервал, имя), системная информация (аптайм, использование кучи, управление LED, перезагрузка)
  • CoreInk — четыре вкладки: BLE-радио, отслеживание присутствия (зона, ползунки настройки, переключатели), окружающая среда (карточки температуры/влажности/давления с индикатором батареи), NUS-консоль (быстрые команды, прокручиваемый лог, текстовое поле ввода)
  • BLE-сканер — живой список всех обнаруженных BLE-устройств, отсортированных по RSSI, с цветными бейджами типов
  • Настройки — конфигурация IP, MAC отслеживаемого устройства, учётные данные MQTT, mDNS, привязка устройств и просмотрщик отладочных логов

Навигация через GoRouter с 5-вкладочной нижней панелью. Управление состоянием — Riverpod: восемь провайдеров обрабатывают SSE-потоки, REST-запросы, MQTT-соединения, BLE GATT, NUS-консоль, конфигурацию устройств, мониторинг статуса соединения и хранение истории обнаружений.

Железо: что нужно для сборки

Минимальный набор ESP32 BLE трекера присутствия — одна нода-маяк — требует один ESP32-S3-DevKitC-1 и USB-кабель. Полный сетап с отслеживанием присутствия добавляет M5Stack CoreInk со встроенными сенсорами.

КомпонентРольЦена
ESP32-S3-DevKitC-1 N16R8BLE-нода маяка (16 МБ флеш, 8 МБ PSRAM)~$12
M5Stack CoreInkТрекер присутствия с e-ink дисплеем, SHT3xD, QMP6988, батареей, пьезо~$35
USB-C кабельПрошивка и питание~$3

Итого за ESP32 BLE трекер присутствия для одной комнаты: менее $50. Для сравнения: коммерческие BLE-сенсоры присутствия от Everything Presence или Aqara начинаются от $40 за датчик и требуют своих облачных экосистем или как минимум Zigbee-координатора.

Три конфигурации развёртывания

1. Только маяк (ble-node-beacon-min.yaml)

Минимальная конфигурация. ESP32-S3 транслирует фреймы Minew MBM03 + iBeacon и поднимает точку доступа WiFi. Без BLE-сканирования, без отслеживания — просто настраиваемый маяк. Подходит, если у тебя уже есть сеть ESPresense или room-assistant и нужен ещё один источник маяков.

2. Маяк + трекер (ble-node-standalone.yaml)

Полная конфигурация BLE-ноды. Транслирует маяковые фреймы и одновременно сканирует целевое устройство. Включает веб-сервер с отображением RSSI/расстояния в реальном времени, интеграцию MQTT и все параметры маяка через веб-интерфейс. Это самодостаточная версия — отслеживает присутствие без CoreInk и без Flutter-приложения.

3. CoreInk трекер присутствия (coreink-presence.yaml)

Рекомендуемая конфигурация ESP32 BLE трекера присутствия. Объединяет BLE-трекинг с 94% рабочим циклом, двойной маяк BTHome v2 + iBeacon, сенсоры окружающей среды, NUS-консоль, e-ink дисплей с обновлениями в реальном времени, интеграцию MQTT и RTTTL-оповещения пьезо. Это 3 100+ строк ESPHome YAML — полноценная, обкатанная конфигурация, прошедшая через 18 итераций.

Python CLI-монитор

Для headless-мониторинга или скриптинга tools/ble_monitor.py предоставляет интерфейс командной строки, который подключается к веб-серверу ESPHome через SSE (с фоллбэком на REST). Стримит данные сенсоров в реальном времени, выводит форматированные таблицы отслеживаемых устройств и может быть подключён к системам логирования или алертинга. Скрипт — 16 КБ самодостаточного Python без зависимостей, кроме стандартной библиотеки и requests.

Быстрый старт: от нуля до трекинга за 15 минут

  1. Запроси доступ к репозиторию и склонируй его локально
  2. Скопируй secrets.yaml.example в secrets.yaml и заполни данные WiFi, адрес MQTT-брокера (опционально) и MAC целевого устройства
  3. Прошей CoreInk: esphome run coreink/coreink-presence.yaml
  4. Прошей ноду-маяк: esphome run ble-node/ble-node-standalone.yaml
  5. Подключись к точке доступа CoreInk или найди его в сети через mDNS
  6. Открой веб-интерфейс и убедись, что целевое устройство отображается с RSSI-показаниями
  7. Установи Flutter-приложение: cd flutter_app && flutter run

ESP32 BLE трекер присутствия начнёт отображать данные на e-ink экране сразу после прошивки. Flutter-приложение обнаруживает ноды через mDNS — без настройки IP-адресов. Весь стек работает локально с первого запуска.

Интеграция с Home Assistant

Обе ноды отдают все сенсоры через нативный API ESPHome, который Home Assistant обнаруживает автоматически. BTHome v2 маяковые фреймы CoreInk также подхватываются интеграцией BTHome без какой-либо настройки. MQTT доступен как третий путь интеграции для сетапов, предпочитающих брокерную архитектуру.

На практике это означает, что можно строить автоматизации вроде «включи свет в коридоре, когда отслеживаемый телефон входит в зону Near» или «отправь уведомление, если отслеживаемое устройство пропадает более чем на 5 минут» — целиком в Home Assistant, используя зоны присутствия и значения расстояния, которые BLE.KZ предоставляет как нативные сенсоры.

Модель безопасности

BLE-рекламные данные передаются открытым текстом — так работают BLE-маяки, и шифрование на уровне рекламы сломало бы совместимость со всеми приёмниками. GATT-сервер на ноде-маяке требует аутентификацию паролем (протокол BeaconSET+) перед принятием изменений конфигурации. NUS-консоль на CoreInk использует физическую близость как границу доступа: нужно быть в радиусе BLE (~10 метров) для отправки команд.

Вся сетевая коммуникация остаётся в локальной сети. Веб-сервер работает по HTTP на LAN — если нужен HTTPS, поставь nginx reverse proxy. Никакие данные не покидают локальную сеть, если ты явно не настроишь MQTT на внешний брокер. OTA-обновления прошивки идут только по локальной сети.

Лицензия и коммерческое использование

BLE.KZ выпущен под PolyForm Noncommercial License 1.0.0. Бесплатно для хобби-проектов, исследований, образования и личной домашней автоматизации. Коммерческое использование — продажа устройств с этой прошивкой, предоставление как сервиса или интеграция в коммерческие продукты — требует отдельной лицензии. Пиши на code@ilia.ae для коммерческого лицензирования.

Авторство задокументировано SHA-256 хешами и OpenTimestamps blockchain-аттестацией в COPYRIGHT.md.

Часто задаваемые вопросы

Нужны ли оба устройства, или можно начать с одного?

Можно начать с любого. ESP32-S3 нода-маяк работает автономно как BLE-маяк и базовый трекер присутствия с веб-интерфейсом. CoreInk работает автономно как трекер присутствия с e-ink дисплеем. Flutter-приложение работает с любым из них или с обоими. Разворачивай то, что есть под рукой, добавляй второе потом.

Насколько точна оценка расстояния?

Оценка расстояния по RSSI сама по себе зашумлена — стены, мебель, тела людей и даже влажность влияют на распространение сигнала. В открытом пространстве на расстоянии до 5 метров точность в пределах 0,5-1 метра. Через стены точность падает до 2-3 метров. Система лучше всего работает для зонального определения присутствия (близко/далеко/отсутствует), а не для точного позиционирования. Настрой показатель затухания и measured power под свои условия.

Работает ли с ESPresense?

Да. iBeacon-фреймы и от BLE-ноды, и от CoreInk используют стандартный формат iBeacon, который ноды ESPresense обнаруживают и обрабатывают. Можно запускать маяки BLE.KZ параллельно с существующей сетью ESPresense. Фреймы BTHome v2 — бонус для Home Assistant, но ESPresense их игнорирует.

Можно ли отслеживать несколько устройств одновременно?

Текущая прошивка отслеживает одно целевое устройство на ноду. Для мульти-трекинга разверни несколько CoreInk-нод — по одной на комнату — и агрегируй данные в Home Assistant или через MQTT. BLE-сканер на каждой ноде видит все BLE-устройства в радиусе и показывает их в веб-интерфейсе и Flutter-приложении, но активный трекинг (с расчётом расстояния и зон) фокусируется на одном настроенном MAC-адресе.

Какое время работы от батареи у CoreInk?

При 94% рабочем цикле BLE-сканирования и активном WiFi время работы от батареи измеряется часами, а не днями. CoreInk рассчитан на стационарное развёртывание с питанием от USB. Батарея работает как UPS для кратковременных перебоев питания, а не как основной источник. Напряжение и процент батареи мониторятся и доступны через все каналы.

Почему ESPHome, а не Arduino или ESP-IDF напрямую?

ESPHome предоставляет всю инфраструктуру из коробки — управление WiFi, веб-сервер, OTA-обновления, API Home Assistant, клиент MQTT, фреймворк сенсоров, абстракция дисплея. Написать BLE-маяк на голом ESP-IDF — день работы; написать BLE-маяк с веб-интерфейсом, OTA, MQTT, интеграцией Home Assistant и драйвером дисплея на голом ESP-IDF — месяцы. Кастомные C++ компоненты (эмуляция маяка, драйвер e-ink) подключаются к компонентной архитектуре ESPHome и получают всю инфраструктуру бесплатно.

Связанные проекты

BLE.KZ — часть более широкой экосистемы проектов на ESP32 и IoT. Если вы работаете с e-ink дисплеями и ESPHome, проект M5Paper ESPHome дашборд покрывает аналогичный стек на большем экране. Для управления адресуемыми светодиодами с аппаратным контроллером — контроллер Roshni. А если в планах NFC-контроль доступа, контроллер доступа Aliro на ESP32 реализует стандарт Aliro на той же платформе ESP32-S3.

Исходный код и документация

Исходный код размещён на github.com/razqqm/ble.kz. Репозиторий приватный — доступ предоставляется по запросу. Если хотите изучить кодовую базу, внести вклад или оценить проект для своих задач, напишите и опишите ваш кейс.

Если вы строите систему трекинга присутствия для коммерческого развёртывания или нужна кастомная интеграция, напишите для обсуждения лицензирования и технического консалтинга.

Оцените статью