Коммерческие системы отслеживания присутствия стоят сотни долларов за комнату, привязывают к облаку вендора и перестают работать, как только падает интернет. Для домашней автоматизации, которой нужно знать, есть ли кто-то в гостиной или в гараже, эта зависимость абсурдна. Весь сенсорный слой — BLE-маяк и приёмник — помещается на двух микроконтроллерах за $12 каждый. Облако не добавляет ничего, кроме точки отказа и абонентской платы.
BLE.KZ — полная open-source экосистема ESP32 BLE трекера присутствия на базе ESPHome. Две прошивки — нода-маяк и трекер присутствия с e-ink дисплеем — плюс кроссплатформенное Flutter-приложение и Python CLI-монитор. Без облака, без интернета, без вендорлока. В этой статье разбираю архитектуру, два протокола маяков, кастомный драйвер e-ink дисплея, Flutter-приложение с семью каналами связи и запуск всего стека с нуля.
- Зачем локальный трекинг присутствия
- Архитектура: три независимых слоя
- BLE-нода маяка (ESP32-S3)
- CoreInk трекер присутствия (M5Stack CoreInk)
- Flutter-приложение
- Два протокола маяков в одной кодовой базе
- Эмуляция Minew MBM03
- Двойная реклама BTHome v2 + iBeacon
- Движок отслеживания присутствия
- NUS-консоль: 16 интерактивных BLE-команд
- Кастомный драйвер e-ink дисплея
- Flutter-приложение: семь каналов связи
- Пять экранов
- Железо: что нужно для сборки
- Три конфигурации развёртывания
- 1. Только маяк (ble-node-beacon-min.yaml)
- 2. Маяк + трекер (ble-node-standalone.yaml)
- 3. CoreInk трекер присутствия (coreink-presence.yaml)
- Python CLI-монитор
- Быстрый старт: от нуля до трекинга за 15 минут
- Интеграция с Home Assistant
- Модель безопасности
- Лицензия и коммерческое использование
- Часто задаваемые вопросы
- Нужны ли оба устройства, или можно начать с одного?
- Насколько точна оценка расстояния?
- Работает ли с ESPresense?
- Можно ли отслеживать несколько устройств одновременно?
- Какое время работы от батареи у CoreInk?
- Почему ESPHome, а не Arduino или ESP-IDF напрямую?
- Связанные проекты
- Исходный код и документация
Зачем локальный трекинг присутствия

Большинство решений для определения присутствия в экосистеме 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 отслеживаемого устройства |
mac | MAC-адрес целевого устройства |
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 трекера присутствия через все доступные каналы одновременно:
- SSE (Server-Sent Events) — потоковая передача данных сенсоров в реальном времени с нативного веб-сервера ESPHome, с автоматическим переподключением через экспоненциальный бэкофф от 1 до 30 секунд
- HTTP REST — управление устройством: переключение свитчей, регулировка числовых параметров, нажатие кнопок, изменение текстовых полей
- MQTT — обмен сообщениями publish/subscribe с автоматическим парсингом иерархии топиков
coreink-presence/# - Пассивное BLE-сканирование — фоновое обнаружение всех BLE-устройств в радиусе действия, отсортированных по уровню сигнала
- BLE GATT — прямое чтение сенсоров CoreInk (батарея, температура, влажность, давление) с автопереподключением и экспоненциальным бэкоффом от 2 до 30 секунд
- NUS-консоль — интерактивный канал BLE-команд с автопингом для поддержания соединения
- 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 N16R8 | BLE-нода маяка (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 минут
- Запроси доступ к репозиторию и склонируй его локально
- Скопируй
secrets.yaml.exampleвsecrets.yamlи заполни данные WiFi, адрес MQTT-брокера (опционально) и MAC целевого устройства - Прошей CoreInk:
esphome run coreink/coreink-presence.yaml - Прошей ноду-маяк:
esphome run ble-node/ble-node-standalone.yaml - Подключись к точке доступа CoreInk или найди его в сети через mDNS
- Открой веб-интерфейс и убедись, что целевое устройство отображается с RSSI-показаниями
- Установи 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. Репозиторий приватный — доступ предоставляется по запросу. Если хотите изучить кодовую базу, внести вклад или оценить проект для своих задач, напишите и опишите ваш кейс.
Если вы строите систему трекинга присутствия для коммерческого развёртывания или нужна кастомная интеграция, напишите для обсуждения лицензирования и технического консалтинга.


