Готовая ESPHome-прошивка, которая превращает ESP32-плату в постоянный BLE-шлюз между радон-детектором Radex MR107ion (Quarta-Rad, quartarad.com) и вашим домом. Прибор перестаёт зависеть от приложения RadexM на телефоне — пока ESP32 стоит у розетки, данные текут 24/7 без облака изготовителя.
Radex MR107ion ─BLE READ-poll─► ESP32 ─Web UI v3─► браузер
│
├─► ESPHome API ─► Home Assistant
│
└─► Народмон (инфраструктура есть, ВЫКЛ по умолчанию)
Полная база знаний — в SKILL.md. Полная BLE-расшифровка — в
references/mr107ion.md.
В скилле — четыре YAML на одной кодовой базе. Различия: целевой ESP32-модуль, сценарий применения, Web UI layout.
| Прошивка | Целевая плата | Что особенного | Когда выбирать |
|---|---|---|---|
firmware/radex_gateway_s3.yaml (актуальная, 2026-06-17) |
ESP32-S3-DevKitC-1 (board: esp32-s3-devkitc-1, framework=arduino) |
BLE-клиент к 1×MR107ion, Web Server v3 + Basic Auth + sorting_groups (Data / Service), ESPHome API encryption, watchdog WiFi, Народмон-инфраструктура (switch ALWAYS_OFF, 4 протокола), USB-C, 4 параллельных BLE-слота | Готовый production-шлюз для одного MR107ion на новой плате S3 |
firmware/radex_gateway_s3_baseline.yaml |
ESP32-S3-DevKitC-1 | Чистый baseline без сенсоров (BLE/API/Web UI без логики опроса) — для проверки железа и OTA | Первая прошивка новой платы S3 (smoke-тест перед накатом полной прошивки) |
firmware/radex_gateway.yaml |
ESP32-DevKitC (WROOM-32 / WROVER), framework=esp-idf | v0.3.0-step8 (последний шаг — bluetooth_proxy закомментирован), BLE READ-poll 4 handle round-robin, две таблицы Web UI v3 («Данные» / «Сервис»), web_server.log: false против json:111 |
Старая плата ESP32-DevKitC, ESP-IDF |
firmware/radex_gateway_v2.yaml |
ESP32-DevKitC | Альтернатива на Web Server v2 (одна плоская таблица с тематическими префиксами 1.x / 2.x / 3.x / 4.x) |
Нужен «всё разом» без переключения групп |
Все прошивки слушают тот же протокол MR107ion (custom service FE651Y00-…, READ-poll
ATT-handle через бэкбон FE651700-…), различаются только UI / стек / HARD-правила.
Прошивка циклически опрашивает 4 BLE-handle прибора (round-robin, 4.3 с между read'ами, полный цикл ≈ 17.2 с) и публикует следующий набор сенсоров в Web UI:
| Метрика | Единицы | Источник на приборе | ESPHome sensor |
|---|---|---|---|
| Метрика | Единицы | Источник на приборе | ESPHome sensor |
| --- | --- | --- | --- |
| Радон последний | Bq/m³ | float32 LE @ handle 0x0049 (OAR_last) |
radon_bqm3 |
| Радон среднее (прибор) | Bq/m³ | float32 LE @ handle 0x0040 (OAR_sred) |
radon_avg_bqm3 |
| Радон среднее за час | Bq/m³ | sliding_window 60 × 60 c, filter_out: nan |
radon_avg_hour |
| Радон среднее за день | Bq/m³ | sliding_window 1440 × 60 c, filter_out: nan |
radon_avg_day |
| Температура | °C | int16 LE @ handle 0x0058 (temper_x10), декод ÷10 |
temperature_c |
| Влажность | % | uint8 @ handle 0x005E (humidity) |
humidity_pct |
| RSSI BLE | dBm | из advertise-пакетов (on_ble_advertise) |
rssi_radex |
Полная карта 15 характеристик сервиса FE651700-… (включая Sko_OAR_sred, OAR_min/max,
OAR_mov_avr, t_izm_last) — в разделе «Полная расшифровка BLE-протокола» ниже и в
references/mr107ion.md.
Радон — интегральная статистика по минутным окнам внутри прибора (ионизационная камера накапливает счёт за ≥1 мин). Поэтому period опроса 4.3 с — это плотность ради UI-плавности и точного скользящего окна на стороне ESPHome, а не из-за физики измерения. Для standalone-клиентов 30–60 с — разумный практичный дефолт.
| Прибор | Что измеряет | BLE | Готовая прошивка |
|---|---|---|---|
| Radex MR107ion | Радон в воздухе (Bq/m³, ионизационная камера) + температура + влажность | ✅ | firmware/radex_gateway_s3.yaml (актуальная) |
| Radex RD1212-BT | Гамма-фон (мощность дозы, Geiger-счётчик) | ✅ | планируется после реверса протокола |
| Radex One | Гамма-фон | ❌ USB-only | вне скилла (BLE-шлюз не применим) |
Линейка определяется через единое приложение производителя RadexM
(Android,
iOS). Все BLE-приборы
используют один шаблон GATT-сервисов (FE651Y00-…).
- ❌ Учётная запись Quarta-Rad / привязка к облаку
- ❌ Постоянно работающий смартфон рядом с прибором
- ❌ Pairing / bonding (Radex не требует)
- ❌ Платное ПО
| Что | Зачем |
|---|---|
| ESP32-S3-DevKitC-1 (актуальная плата) | мозг шлюза, $10, USB-C |
| USB Type-C кабель | прошивка и питание |
| Radex MR107ion с BLE | источник данных |
| Wi-Fi 2.4 ГГц + интернет | для Home Assistant / Web UI |
esphome 2026.5+ на ПК |
pip install esphome |
| Адрес BLE-прибора (MAC) | подсмотреть через RadexM или через Web UI после прошивки |
Здесь — короткая шпаргалка для тех, у кого уже стоит ESPHome и PlatformIO кэш прогрет. Полная пошаговая инструкция с нуля (требования к Windows/Linux/macOS, установка драйверов USB-Serial, Python 3.10–3.12, ESPHome, два пути установки — через Claude Code или через стандартный ESPHome Web Installer, troubleshooting на 10+ проблем) — в
INSTALL.md.
git clone https://github.com/Verter73/claude-skills.git
cd claude-skills\radex-esp32\firmware\
Copy-Item secrets.example.yaml secrets.yamlОткрыть secrets.yaml и заполнить:
wifi_ssid/wifi_password— домашняя Wi-Fi 2.4 GHz.ap_password— пароль captive-portal AP «radex-gw-s3 Fallback» (≥8 символов).api_encryption_key—openssl rand -base64 32.ota_password— длинный пароль для OTA.web_server_auth_user/web_server_auth_pass— для Basic Auth на/.radex_mac— можно оставить placeholder, MAC задаётся через Web UI после первой загрузки.
$esp = "$env:LOCALAPPDATA\Programs\Python\Python312\Scripts\esphome.exe"
$env:PYTHONIOENCODING = "utf-8"; $env:PYTHONUTF8 = "1"
& $esp compile radex_gateway_s3.yaml
& $esp upload radex_gateway_s3.yaml --device COM<N>Найти COM-порт:
Get-CimInstance Win32_PnPEntity | Where-Object { $_.Name -match 'CH340|CP210|FTDI|USB Serial' }USB-SERIAL CH340 / Silicon Labs CP210x / USB Serial Device.
Если WiFi не настроен — ESP поднимает AP «radex-gw-s3 Fallback» с паролем из
ap_password. С телефона подключиться → http://192.168.4.1/ → выбрать домашнюю
сеть → ввести пароль → Save. ESP перезагрузится.
http://radex-gw-s3.local/ (логин/пароль = web_server_auth_user/pass).
- Группа «Service» → запустить BLE-скан → найти строку
MR107ion-12AB, скопировать MAC. - Вставить в поле «MAC Radex» → «Применить MAC и перезагрузить».
- После рестарта в группе «Data» побегут радон/температура/влажность.
Settings → Devices & Services → Add Integration → ESPHome →
host radex-gw-s3.local (или IP), encryption key — тот, что в secrets.yaml.
ESPHome Web UI v3 в radex_gateway_s3.yaml рисует спарклайн на каждой карточке и
полноразмерный график при клике. Две тематические группы (sorting_groups):
| Карточка | Что показывает |
|---|---|
| Радон последний | свежий OAR_last от прибора, Bq/m³, обновляется ~ раз в 17 с (round-robin цикл) |
| Радон среднее прибор | OAR_sred от прибора (внутренняя статистика MR107ion), Bq/m³ |
| Радон среднее за час | sliding-window 60 × 60 c по OAR_last, считается на ESP, Bq/m³ |
| Радон среднее за день | sliding-window 1440 × 60 c по OAR_last, Bq/m³ |
| Температура | int16 LE / 10, °C |
| Влажность | uint8, % |
| Карточка | Что делает |
|---|---|
| BLE-сканер | кнопка «Start BLE scan» + список найденных приборов; используется при первой привязке MAC |
| MAC Radex | поле для ручного ввода MAC + кнопка «Применить MAC и перезагрузить» (MAC сохраняется в NVS) |
| BLE подключён | ON/OFF, статус GATT-сессии к прибору |
| BLE: коннекты / реконнекты | счётчики, для диагностики стабильности |
| RSSI BLE | сила сигнала прибора, dBm |
| Переподключиться к Radex | форсированный BLE-disconnect + новый коннект |
| Сбросить счётчики BLE | обнуляет коннекты/реконнекты |
| WiFi сигнал / SSID / BSSID / IP / MAC шлюза | диагностика сети |
| API подключён | статус ESPHome API (есть ли HA на той стороне) |
| Uptime | время с последнего ребута |
| Switch «Выгружать на Народмон» | главный выключатель (по умолчанию OFF, restore_mode: ALWAYS_OFF) |
| Select «Способ отправки» | 4 транспорта Народмона: HTTP GET / HTTP POST / HTTPS POST / JSON POST |
| Имена метрик RR1 / T1 / H1 | имена на стороне Народмона |
| Кнопка «Отправить на Народмон сейчас» | ручной триггер; работает только при ON |
| Reboot / Safe Mode / Factory reset | штатные кнопки управления платой |
В альтернативной прошивке radex_gateway_v2.yaml (Web Server v2) — одна плоская таблица с
тематическими префиксами 1.x (прибор) / 2.x (BLE+Сеть) / 3.x (Народмон) / 4.x
(Система); содержание то же.
┌────────────┐ BLE READ-poll ┌────────────────┐ HTTP/WiFi ┌──────────────┐
│ Radex │ ───────────────► │ ESP32-S3 │ ──────────► │ Браузер, │
│ MR107ion │ 4 handle │ -DevKitC-1 │ JSON + │ HA, │
│ (Quarta- │ каждые 4.3 с │ N16R8 │ Web UI v3 │ Python │
│ Rad) │ (~17.2 с цикл) │ (ESPHome, │ │ │
│ │ │ arduino) │ │ │
└────────────┘ └────────────────┘ └──────────────┘
│ I/O
▼
┌──────────────┐
│ Round-robin │
│ read pump │
│ 4 handle → │
│ 6 sensors + │
│ sliding-win │
│ hour/day │
└──────────────┘
│
│ опционально, ВЫКЛ по умолчанию
▼
┌──────────────┐
│ Народмон │
│ HTTP/HTTPS/ │
│ JSON, 600 с │
│ ALWAYS_OFF │
└──────────────┘
Никаких облаков. Никаких аккаунтов. Всё крутится в твоей локальной сети, исходники открыты, прошивка — твоя.
Полная карта BLE GATT + разбор всех 15 характеристик сервиса FE651700-… —
references/mr107ion.md.
Кратко: 2 custom-сервиса с базой FE651Y00-00B0-4240-BA50-05CA45BF8AAA, где Y=6 для
конфигурации и Y=7 для измерений. Опрос ATT Read (НЕ Notify), приложение RadexM в эфире
делает 5 184 read-request за 27 минут (≈ 3.2 req/с, по ~324 read'а на handle).
Самодокументированный протокол: каждая характеристика занимает 3 handle подряд
(Decl + Value + User Description 0x2901 с человекочитаемым именем ASCII-транслитом).
Короткий итог: ESP32-S3-DevKitC-1 N16R8 (16 МБ Flash + 8 МБ embedded octal PSRAM) +
framework: arduino — стабильная и рекомендованная конфигурация. Классический ESP32-DevKitC
v4 (WROOM-32 / 4 МБ flash / без PSRAM) + esp-idf работает только с web_server.log: false
и с зафиксированным bluetooth_proxy: # active: true (закомментирован) — каждая попытка
включить отладочный лог или вернуть btproxy ломает heap при первом же F5 в браузере.
Проверено серией инцидентов в этом проекте за июнь 2026:
Первая v0.3.0 после rebuild от bt-proxy baseline шла с web_server.log: true (упомянут в
комментарии, физически в YAML отсутствовал = default true). DevKitC при открытом браузере +
SSE Debug Log + параллельный http_request к Народмону уходил в каскады:
[E][json:111]: JSON document overflow
[W][component:522] web_server took a long time (73 ms)
min_free_heap пробивал ~12 КБ, Web UI грузился пустым. Лечение одной строкой:
web_server: log: false (v0.3.0-step5b, 2026-06-14). Зашито в radex_gateway.yaml как HARD
default для DevKitC.
web_server: version: 3 использует web-component lit-element; пустая sorting_group
(например, sg_re без сенсоров внутри) ломает рендеринг — карточки не появляются. Лечение:
не создавать пустые группы; если временно нет сущностей под группу — удалить блок целиком.
На esp-idf BLE-стек уважает свой собственный coex-балансер; ручные scan-параметры
interval: 600ms, window: 180ms (стабильные на arduino) ломают эту модель — WiFi-радио
недополучает воздух, STA_DISCONNECTED reason=15 (AUTH_EXPIRE) каждые несколько секунд.
HARD-правило по итогу: на esp-idf — 640ms / 32ms (~5 % duty) или вообще снять
scan_parameters. На S3 + arduino — не воспроизводится, оператор оставил scan-параметры
дефолтные.
ESP32-S3-DevKitC-1 N16R8 несёт 8 МБ embedded octal PSRAM. Запас heap на порядок больше,
чем на классическом DevKitC; json:111 при F5 не достигается. В radex_gateway_s3.yaml оставлен
web_server: log: true — Debug Log виджет работает. Условие отката (зашито в комментарий
YAML): любые ребуты / json:111 / OOM на S3 → вернуть log: false и не активировать заново,
без переспроса.
- ⭐ ESP32-S3-DevKitC-1 N16R8 →
radex_gateway_s3.yaml(arduino, log: true). Рекомендованная актуальная конфигурация. - Классический ESP32-DevKitC v4 (если уже на руках) →
radex_gateway.yaml(esp-idf, v0.3.0-step8, log: false,bluetooth_proxy: # active: trueзакомментирован). Стабилен в этой конфигурации; на esp-idf с другими настройками — нет. - Альтернативный UX на классике →
radex_gateway_v2.yaml(Web Server v2, одна плоская таблица с префиксами). - Smoke-тест железа на новой S3-плате до полной заливки →
radex_gateway_s3_baseline.yaml(минимальный набор: BLE/API/Web UI без логики опроса).
Цифры ниже — результат live HCI-capture 2026-06-12 (Android RadexM, btsnoop_hci, 27 мин, 46 840 пакетов) + ble-explorer sweep v0.1.4/v0.1.5 с реального прибора
MR107ion 0214. Подробности — вreferences/mr107ion.md.
| Параметр | Значение |
|---|---|
| Модель | MR107ion (новая ревизия MR107 с BLE) |
| advertising local_name | MR107ion 0214 (последние 4 цифры — ревизия) |
| Тип PDU | ADV_IND |
| Pairing / bonding | НЕ требуется |
| Handle range | Service UUID | Назначение |
|---|---|---|
0x0001–0x0009 |
0x1800 |
GAP (стандарт) |
0x000a–0x000d |
0x1801 |
GATT (стандарт) |
0x000e–0x0013 |
6E400001-B5A3-F393-E0A9-E50E24DCCA9E |
Nordic UART (NUS) — placeholder, не работает |
0x0014–0x0020 |
0x180a |
Device Information |
0x0021–0x003d |
FE651600-00B0-4240-BA50-05CA45BF8AAA |
Custom Config (R/W, 14 chars) |
0x003e–0x006b |
FE651700-00B0-4240-BA50-05CA45BF8AAA |
Custom Measurement (R, 15 chars) |
Основная работа — через два custom-сервиса с базой
FE651Y00-00B0-4240-BA50-05CA45BF8AAA, где Y=6 для конфигурации и Y=7 для
измерений.
Главная находка реверса. Приложение RadexM опрашивает прибор циклическими ATT Read, не подписывается на Notify. За 27-минутную HCI-сессию:
- Total ATT Read requests: 5 184 (≈ 3.2 req/sec средне).
- Каждый ключевой handle опрошен 324 раза (≈ 1 раз / 5 с per handle).
- Notify пакеты за сессию: 0. Прибор честно отвергает CCCD-write на NUS.
Это сильно отличается от RadonEye / AtomFast (push-only), но облегчает ESP32-port: не нужно ждать асинхронные Notify, можно поллить с любым удобным периодом.
Каждая характеристика сервиса FE651700-… занимает 3 последовательных handle:
- Decl (нечётный, начиная с
0x003F) — Properties + value_handle + 128-bit UUID с базойFE6517NN-00B0-4240-BA50-05CA45BF8AAA, гдеNN= 01, 02, 03 … 15 (hex). - Value (decl+1) — собственно данные (float32 LE / uint32 LE / uint16 LE / uint8).
- User Description (decl+2, UUID
0x2901) — человекочитаемое имя поля ASCII (транслит русского, почерк QuartaRad).
Сначала читаешь desc-handle → получаешь имя поля; потом читаешь value по offset −1.
| # | Decl | Value | Desc | Имя | Тип | Сырое значение | Декод | Смысл |
|---|---|---|---|---|---|---|---|---|
| 1 | 0x003F | 0x0040 | 0x0041 | OAR_sred |
float32 LE | 55 89 93 42 |
73.79 | Радон среднее, Bq/m³ |
| 2 | 0x0042 | 0x0043 | 0x0044 | Sko_OAR_sred |
float32 LE | A1 2A 39 41 |
11.572 | СКО среднего, Bq/m³ |
| 3 | 0x0045 | 0x0046 | 0x0047 | t_izm_last |
uint32 LE | 8B 58 00 00 |
22667 | Uptime / время посл. изм., сек (+1/сек) |
| 4 | 0x0048 | 0x0049 | 0x004A | OAR_last ⭐ |
float32 LE | 00 00 8A 42 |
69.0 | Радон последнее, Bq/m³ |
| 5 | 0x004B | 0x004C | 0x004D | OAR_mov_avr |
float32 LE | 55 55 92 42 |
73.17 | Скользящее среднее, Bq/m³ |
| 6 | 0x004E | 0x004F | 0x0050 | Qakk (trunc) |
uint16 LE | 61 00 |
97 | Имя обрезано до 4 байт; вероятно Qakkum_OAR |
| 7 | 0x0051 | 0x0052 | 0x0053 | OAR_min |
float32 LE | 7C 3B 47 42 |
49.81 | Радон минимум, Bq/m³ |
| 8 | 0x0054 | 0x0055 | 0x0056 | OAR_max |
float32 LE | 23 F7 99 42 |
76.98 | Радон максимум, Bq/m³ |
| 9 | 0x0057 | 0x0058 | 0x0059 | temper_x10 |
int16 LE *) | 0A 01 |
266 | Температура × 10 → 26.6 °C |
| 10 | 0x005A | 0x005B | 0x005C | preassure (sic) |
uint16 LE | 00 00 |
0 | Давление (нет датчика?) |
| 11 | 0x005D | 0x005E | 0x005F | humidity |
uint8 | 31 |
0x31 = 49 | Влажность, % |
| 12 | 0x0060 | 0x0061 | 0x0062 | quantity_izm |
uint16 LE | 04 00 |
4 | количество единиц измерения |
| 13 | 0x0063 | 0x0064 | 0x0065 | num_izmer |
uint16 LE | 03 00 |
3 | число измерений |
| 14 | 0x0066 | 0x0067 | 0x0068 | t_prepare |
uint16 LE | 00 00 |
0 | время подготовки, сек |
| 15 | 0x0069 | 0x006A | 0x006B | mis_psw |
uint16 LE | 80 00 |
128 | misc / status flags |
OAR_last(69.0) укладывается в диапазон min/max (49.81 / 76.98) и близко к среднему/скользящему (73.79 / 73.17) — все значения консистентны.temper_x10= 266 → 26.6 °C,humidity= 49 % — типовые комнатные условия.t_izm_lastрастёт на +1 в секунду (+25 за 25 c наблюдения) — uptime.
Достаточно 4 read'ов на цикл:
| Handle | Поле | Формат | Сенсор |
|---|---|---|---|
| 0x0049 | OAR_last | float32 LE | radon_bqm3 — главное значение |
| 0x0040 | OAR_sred | float32 LE | radon_avg_bqm3 |
| 0x0058 | temper_x10 | int16 LE / 10 *) | temperature_c |
| 0x005E | humidity | uint8 | humidity_pct |
Период опроса в прошивке скилла — 4.3 с round-robin на 4 хэндла (≈17.2 с на полный цикл). Радон — интегральная статистика по минутным окнам, поэтому для standalone-клиентов 30-60 с — разумный практичный дефолт. Приложение RadexM поллит ~5 Hz исключительно ради UI-плавности.
*) temper_x10 декодируется как int16 LE — super-set, корректно работает и
при uint16, и при int16 two's complement. Подробное обоснование — в
references/mr107ion.md.
База характеристик — FE6517NN-00B0-4240-BA50-05CA45BF8AAB (последний
байт AAB); номер характеристики NN стоит на позиции 17NN. Не путать с базой
сервиса Custom Measurement — FE651700-00B0-4240-BA50-05CA45BF8AAA
(последний байт AAA). У Quarta-Rad сервис и его характеристики оканчиваются
на разные байты — это видно во всех 15 char-UUID.
| NN | UUID характеристики | Поле |
|---|---|---|
01 |
FE651701-…AAB |
OAR_sred (handle 0x0040) |
04 |
FE651704-…AAB |
OAR_last (0x0049) ⭐ |
09 |
FE651709-…AAB |
temper_x10 (0x0058) |
11 |
FE651711-…AAB |
humidity (0x005E) |
Handle на ревизии 0214 совпал между двумя reset'ами, межревизионная стабильность не верифицирована. UUID — более устойчивый контракт: он зашит в прошивку прибора и переживает реорганизацию GATT-таблицы. При портировании на новую ревизию или другой Radex-прибор: пересобрать GATT-карту через
ble-explorer(0x2901descriptors) и проверить handle'ы; если расходятся — переключить ESPHome-конфиг на UUID-read.
CCCD-write на 0x0013 (NUS TX descriptor) приложение делает дважды при подключении
(value=0100 — subscribe Notify), оба запроса прибор молча игнорирует. NUS-сервис
у MR107ion декларирован только для совместимости с поиском в магазинах приложений,
фактически не работает.
В оперативной памяти ESP. Web UI v3 ESPHome хранит историю sensor'ов с момента последней
перезагрузки (~ час на типичную карточку). Если нужна постоянная история — подключи к Home
Assistant через ESPHome API (api_encryption_key уже сгенерирован в secrets.yaml).
HA подхватывает все entities автоматически.
Switch «Выгружать на Народмон» в прошивке создан, но ОБЯЗАН иметь
restore_mode: ALWAYS_OFF:
- platform: template
name: "Выгружать на Народмон"
id: narodmon_enabled
restore_mode: ALWAYS_OFF # ← HARD: после reboot/safe-mode/OTA всегда OFF
optimistic: trueПосле ребута, кратковременного отключения питания, safe-mode, factory_reset, OTA — switch всегда возвращается в OFF. Оператор не получит «сюрприза» включённой выгрузки в облако.
Select «Способ отправки» предлагает 4 транспорта (см. скилл
narodmon-iot):
HTTP GET—narodmon.ru/get?ID=<MAC>&RR1=<value>&T1=<value>&H1=<value>HTTP POST—narodmon.ru/post, form-urlencodedHTTPS POST— то же, но через mbedTLSJSON POST—narodmon.ru/json, application/json
Минимальный интервал на стороне сервера — 5 минут; короче = бан IP на час. В прошивке жёстко 600 с.
- ❌ Не публиковать
firmware.bin/firmware.factory.bin— бинарник содержит WiFi-SSID, WiFi-пароль, MAC прибора, OTA-пароль, API encryption key в plain ASCII. Только YAML +secrets.example.yamlс placeholder'ами. - ❌ Не убирать
restore_mode: ALWAYS_OFFсо switch Народмона (HARD 2026-06-17). - ❌ Не запускать
esphome logs --device COM<N>— DTR/RTS ребутает плату и обрывает BLE-сессию. Использовать OTA-logger (--device <hostname>.local) илиmode COM<N> DTR=OFF RTS=OFF+ Python-serial. - ❌ Не пытаться подписаться на Notify NUS (
6E400003-…) — это placeholder, никогда не шлёт Notify. Только READ-poll поFE651700-…. - ❌ Не путать MR107 (USB-only старый) и MR107ion (BLE-новый) — старые USB reverse-инструменты не подходят.
- ❌ Не использовать
web_server.log: trueна C3/S3 без явного решения оператора — SSE Debug Log при F5-шторме = json:111 overflow + near-OOM (корень фикса v0.3.0-step5b/6g). На S3 это исключение оператора оставлено какtrue— если пойдут ребуты, вернутьfalseбез переспроса.
| Плата | BLE central слотов | Сколько занимает эта прошивка |
|---|---|---|
| ESP32-DevKitC (Bluedroid) | 3 | 1 |
| ESP32-S3 | 4 (esp32_ble.max_connections: 4) |
1 |
Свободные слоты — под AtomFast и/или RadonEye на той же плате. Это укладывается
в концепцию единого BLE-шлюза (1 ESP32-S3 → несколько приборов через ble_client).
Параллельный публичный шлюз AtomFast — см. VibeEngineering-LLC/atomfast-esp32.
📋 Полная матрица совместимости плат, рекомендации по выбору железа и журнал инцидентов — в KNOWN_ISSUES.md. В частности — почему ESP32-C3 SuperMini не подходит для текущих YAML (инцидент INC-C3-001:
OSError: [Errno 28] No space left on device).
- Handle-based read привязан к ревизии 0214 MR107ion. На другой ревизии — заменить на UUID-read (медленнее, но устойчиво к смене handle-карты).
- MTU 23 (не растёт) — не критично, payload'ы влезают.
- Pseudo-NUS (
6E400001-…) объявлен прибором, но не шлёт Notify — не пытаться подписаться через CCCD. - Народмон-
selectимеет 4 опции. Минимальный интервал сервера — 5 мин; короче = бан IP на час. В прошивке жёстко 600 с. - Кэш ESPHome при правке только
secrets.yaml:esphome uploadможет залить старый кэшированныйfirmware.binбез пересборки. Лечение —esphome clean <yaml>передcompile/uploadвсегда после правки секретов.
radex-esp32/
├── README.md ← эта инструкция
├── SKILL.md ← обзор семейства + методология RE нового прибора
├── firmware/
│ ├── radex_gateway_s3.yaml ← АКТУАЛЬНАЯ (ESP32-S3-DevKitC-1)
│ ├── radex_gateway_s3_baseline.yaml ← baseline для S3 (smoke-тест)
│ ├── radex_gateway.yaml ← v0.3.0-step8 (ESP32-DevKitC, ESP-IDF, Web UI v3)
│ ├── radex_gateway_v2.yaml ← альтернатива (Web Server v2, плоский UI)
│ ├── secrets.example.yaml ← шаблон секретов
│ ├── CHANGELOG.md ← история версий
│ ├── include/ ← C-хедеры (BLE hooks)
│ ├── www/ ← кастом-CSS/JS для v2 (log_limit.css, reorder_v2.js)
│ └── archive/ ← старые YAML
└── references/
└── mr107ion.md ← полная GATT-таблица MR107ion (live HCI + ble-explorer sweep)
Подробная методология — в SKILL.md, раздел «Reverse-стратегия
для нового Radex-прибора». Кратко:
- Снять btsnoop HCI capture с Android RadexM (Developer options → Enable
Bluetooth HCI snoop log →
adb bugreport→FS/data/misc/bluetooth/logs/btsnoop_hci.log). - Прогнать через
scripts/parse_btsnoop_v2.pyили Wireshark. - Зафиксировать GATT-карту в
references/<model>.md. - Верифицировать на железе через скилл
ble-explorer(Web UI с GATT-enum + Notify capture). - Сделать копию
firmware/radex_gateway_s3.yaml, подменить UUID/handles и lambda-парсер под новый формат.
esp32-dev— общие практики разработки на ESP32 + ESPHome.ble-explorer— универсальный BLE-RE шлюз (GATT-enum, 0x2901, Notify capture).atomfast-esp32— соседний скилл по AtomFast (Notify-based γ-дозиметр), служит шаблоном для Народмон-выгрузки.radoneye-esp32— RadonEye Plus2 (тоже радон, но Notify, не READ-poll).narodmon-iot— протокол выгрузки на narodmon.ru.
Quarta-Rad / QuartaRad, Москва, RU.
Приложение производителя: RadexM Android · RadexM iOS.
MIT.