Добрый день, уважаемый читатель! Продолжаю серию статей про готовое и вполне законченное устройство на ESP32 и Espressif IoT Development Framework. В прошлых статьях серии я рассказывал про:
- Часть 1. Вводная: общее описание и возможности
- Часть 2. Перечень необходимых компонентов, схемы отдельных узлов, печатная плата
- Часть 3. Минимальный вариант: только телеметрия через MQTT брокер
Если вы не читали их, то рекомендую ознакомиться. В данной статье я приведу подробное (на мой взгляд, конечно) описание генерируемых устройством “стандартных” топиков.
Итак, если вы прошили микроконтроллер предлагаемой прошивкой, то получили на своем MQTT-брокере целый букет топиков, по большей части в JSON-формате. Теперь давайте разберемся, с чем это едят и для чего всё это нужно.
Почему JSON?
Для начала объясню, почему был выбран формат JSON.
Прошивка, в принципе, позволяет публиковать данные с сенсоров “напрямую” PLAIN, без оборачивания в JSON-формат (включить это можно с помощью макроса CONFIG_SENSOR_AS_PLAIN
, установив его значение в 1). Но, поскольку прошивка публикует для каждого сенсора сразу целый набор данных (значение, время изменения, экстремумы за разные периоды времени и т.д.), то это зачастую приводит к тому, что MQTT-клиент, да и сам брокер просто “захлебываются”, не справляясь с большим потоком данных. Кроме того, это ведёт к большему расходу кучи, так как приходится генерировать для всего этого отдельные топики. В итоге в своих устройствах я практически полностью отказался от публикации данных в “открытом” виде, исключением являются только топики обмена данными между устройствами.
Локальный и публичный брокеры
Как я уже писал в прошлой статье, прошивка поддерживает два брокера: основной и резервный. При этом каждый из них может быть локальным и публичным (облачным). Локальный брокер расположен “внутри” вашей локальной сети, а публичный – где-то в глобальной сети интернет. Топики для них могут различаться: например для локального брокера нет необходимости указывать локацию, а добавлять её к топику динамически в настройках моста “локальный <-> публичный”. Подробнее об этом можно почитать в самом конце статьи “MQTT брокер на роутере Keenetic“. Составные части топиков для локального брокера помечены как CONFIG_MQTTx_LOC_
, для публичных брокеров это будут, соответственно, CONFIG_MQTTx_PUB_
. Если вы не используете локальный брокер, вы можете не определять макросы CONFIG_MQTTx_LOC_
.
Схема генерации топиков
Большинство MQTT топиков программа формирует автоматически, из разных составных частей, определенных в файле конфигурации. Давайте рассмотрим эти части:
🔸PREFIX – общий префикс для топиков, определяется брокером. Большинство брокеров, работающих на mosquitto, не требует никаких префиксов в начале каждого топика. Но некоторые публичные брокеры, например clusterfly.ru или mqtt.by требуют указания имени пользователя в каждом топике, например: “/user_USERNAME/…”. Некоторые MQTT клиенты для Android требуют начинать топики с “/”. Вот для всех этих целей и предназначен префикс. Настраивается он с помощью параметров CONFIG_MQTT1_PUB_PREFIX
и CONFIG_MQTT1_LOC_PREFIX
(или CONFIG_MQTT2_PUB_PREFIX
и CONFIG_MQTT2_LOC_PREFIX
для резервного брокера).
🔸LOCATION – расположение устройства, или локация. Если PREFIX
не задан, то топики обычно начинаются именно с локации. Для локальных брокеров можно не указывать, но только если у вас одно расположение или если вы настроили автоматическое добавление локации в параметрах моста с локального брокера на публичный. Для указания LOCATION
используйте параметры CONFIG_MQTT1_PUB_LOCATION
и CONFIG_MQTT1_LOC_LOCATION
(или CONFIG_MQTT2_PUB_LOCATION
и CONFIG_MQTT2_LOC_LOCATION
для резервного брокера).
Применение <LOCATION>
дает ещё один не очевидный на первый взгляд плюс – позволяет разделить права на топики между разными пользователями на уровне брокера. Но в этой статье мы не будем пока касаться этой темы
🔸DEVICE – название устройства. Например это может быть конкретное место установки или функциональность устройства. По аналогии название настраивается с помощью макросов CONFIG_MQTT1_PUB_DEVICE
и CONFIG_MQTT1_LOC_DEVICE
.
Из этих составных частей формируется все топики по общему правилу: <PREFIX><LOCATION>/<DEVICE>/...
. Обратите внимание – между <PREFIX>
и <LOCATION>
нет символа-разделителя /
, а между <LOCATION>
и <DEVICE>
он есть. Поэтому в PREFIX
, если он необходим, нужно указать его, а в остальных частях указывать разделитель уже не нужно.
На примере ниже первый уровень иерархии – это локация, второй уровень – устройства. Но иногда нужно добавить дополнительный уровень для дополнительно детализации, в этом случае я просто добавляю его в <DEVICE>
, например “home/main“.
Думаю, теперь вам понятен принцип генерации топиков, можно переходить к их описанию
Системные топики
Устройство генерирует несколько “системных” топиков.
🔸<LOCATION>/<DEVICE>/status: cтатус устройства и одновременно LWT – Last Will and Testament, «последняя воля и завещание». Это один из немногих топиков, публикуемых в открытом виде (без JSON). Здесь может находиться следующая информация:
- Сразу после подключения к брокеру здесь публикуется значение “online” – это означает, что устройство доступно для управления
- Если подключение к устройству по какой-либо причине потеряно, брокер сам опубликует сюда значение “offline“. Это и есть LWT payload
- Когда устройство нормально работает, прошивка периодически (один раз в несколько минут) публикует сюда краткую системную информацию в виде трех строк.
- Первая строка – время наработки устройства с момента последнего запуска в формате ДНИ : ЧАСЫ : МИНУТЫ.
- Вторая строка – уровень сигнала WiFi.
- Третья строка: первая цифра – количество свободной кучи в %; затем идет количество зафиксированных ошибок выделения памяти; и в конце оставшийся объем свободных записей в разделе хранения параметров NVS.
🔸<LOCATION>/<DEVICE>/time – в этот топик в начале каждой минуты публикуется системное время и дата в различных форматах в виде JSON-пакета. Это позволяет организовать на MQTT-клиенте плитку с датой и временем. С настройками “по умолчанию” данные в топике выглядят так:
{ "time": "12:50", "date": "03.05.24", "weekday": "пт", "timeday": "12:50 пт", "datetime1": "12:50\n03.05.24", "datetime2": "12:50 пт\n03.05.24", "year": 2024, "month": 4, "day": 3, "hour": 12, "min": 50, "wday": 5, "yday": 123, "worktime": { "days": 12, "hours": 6, "minutes": 41 } }
🔸<LOCATION>/<DEVICE>/sysinfo – в этот топик периодически публикуется подробная системная информация, предназначенная по большей части для отладки устройства. Можно отключить с помощью макроса CONFIG_MQTT_SYSINFO_ENABLE
в файле конфигурации.
// EN: Allow periodic publication of system information // RU: Разрешить периодическую публикацию системной информации #define CONFIG_MQTT_SYSINFO_ENABLE 1 #define CONFIG_MQTT_SYSINFO_INTERVAL 1000*60*5 #define CONFIG_MQTT_SYSINFO_SYSTEM_FLAGS 1
Данные в этом топике выглядят примерно так:
{ "firmware": "20230826.120", "cpu_mhz": 240, "wifi": {"ssid": "k12iot", "rssi": -30, "ip": "192.168.2.51", "mask": "255.255.255.0", "gw": "192.168.2.1"}, "worktime": {"days": 16, "hours": 7, "minutes": 57}, "heap": {"total": 265.9, "errors": 0, "free": 130.2, "free_percents": 49, "free_min": 73.3, "free_min_percents": 27.5}, "nvs": {"total_entries": 30870, "used_entries": 814, "used_percents": 2.6, "free_entries": 30056, "free_percents": 97.4, "namespaces": 28}, "errors": {"general": 0, "heap": 0, "mqtt": 0, "telegram": 0, "smtp": 0, "site": 0, "thingspeak": 0, "openmon": 0, "narodmon": 0, "sensor0": 0, "sensor1": 0, "sensor2": 0, "sensor3": 0, "sensor4": 0, "sensor5": 0, "sensor6": 0, "sensor7": 0}, "sys_flags": {"ota": 0, "rtc_enabled": 0, "sntp_sync": 1, "silent_mode": 0, "wifi_sta_started": 1, "wifi_sta_connected": 1, "inet_availabled": 1, "mqtt1_enabled": 0, "mqtt2_enabled": 0, "mqtt_connected": 1, "mqtt_primary": 1, "mqtt_local": 1}, "wifi_flags": { "init_tcpip": 1, "init_low": 1, "sta_enabled": 1, "sta_started": 1, "sta_connected": 1, "sta_got_ip": 1, "disconnect_and_stop": 0, "disconnect_and_restore": 0} }
🔸<LOCATION>/<DEVICE>/tasklist – в этот топик периодически публикуется список задач с данными стека, также в JSON формате. Это позволяет подобрать оптимальный размер стека для каждой задачи. Можно включить или отключить с помощью макроса CONFIG_MQTT_TASKLIST_ENABLE
в файле конфигурации.
[ {"id": 3, "name": "esp_timer", "core": 0, "state": "running", "current_priority": 22, "base_priority": 22, "run_time_counter": 0, "stack_base": "3ffbeca0", "stack_minimum": 1776}, {"id": 6, "name": "IDLE", "core": 1, "state": "ready", "current_priority": 0, "base_priority": 0, "run_time_counter": 0, "stack_base": "3ffc0fac", "stack_minimum": 1700}, {"id": 5, "name": "IDLE", "core": 0, "state": "ready", "current_priority": 0, "base_priority": 0, "run_time_counter": 0, "stack_base": "3ffc06a8", "stack_minimum": 1704}, {"id": 17, "name": "alarm", "core": 1, "state": "blocked", "current_priority": 8, "base_priority": 8, "run_time_counter": 0, "stack_base": "3ffbbc84", "stack_minimum": 796}, {"id": 23, "name": "mqtt_task", "core": -1, "state": "blocked", "current_priority": 12, "base_priority": 12, "run_time_counter": 0, "stack_base": "3ffda3a8", "stack_minimum": 2024}, {"id": 8, "name": "led_system", "core": 1, "state": "blocked", "current_priority": 13, "base_priority": 13, "run_time_counter": 0, "stack_base": "3ffc9eb8", "stack_minimum": 408}, {"id": 22, "name": "pinger", "core": 1, "state": "blocked", "current_priority": 3, "base_priority": 3, "run_time_counter": 0, "stack_base": "3ffb68d8", "stack_minimum": 696}, {"id": 13, "name": "sensors", "core": 1, "state": "blocked", "current_priority": 6, "base_priority": 6, "run_time_counter": 0, "stack_base": "3ffb7710", "stack_minimum": 1232}, {"id": 19, "name": "tiT", "core": -1, "state": "blocked", "current_priority": 18, "base_priority": 18, "run_time_counter": 0, "stack_base": "3ffd1838", "stack_minimum": 1208}, {"id": 10, "name": "tg_send", "core": 1, "state": "blocked", "current_priority": 11, "base_priority": 11, "run_time_counter": 0, "stack_base": "3ffb3e65", "stack_minimum": 747}, {"id": 7, "name": "Tmr Svc", "core": 0, "state": "blocked", "current_priority": 1, "base_priority": 1, "run_time_counter": 0, "stack_base": "3ffc1a14", "stack_minimum": 1580}, {"id": 1, "name": "ipc0", "core": 0, "state": "blocked", "current_priority": 24, "base_priority": 24, "run_time_counter": 0, "stack_base": "3ffaf0a0", "stack_minimum": 448}, {"id": 12, "name": "buzzer", "core": 0, "state": "blocked", "current_priority": 14, "base_priority": 14, "run_time_counter": 0, "stack_base": "3ffb3844", "stack_minimum": 364}, {"id": 14, "name": "led_alarm", "core": 1, "state": "blocked", "current_priority": 13, "base_priority": 13, "run_time_counter": 0, "stack_base": "3ffcd018", "stack_minimum": 488}, {"id": 18, "name": "sys_evt", "core": 0, "state": "blocked", "current_priority": 20, "base_priority": 20, "run_time_counter": 0, "stack_base": "3ffd05b0", "stack_minimum": 1536}, {"id": 2, "name": "ipc1", "core": 1, "state": "blocked", "current_priority": 24, "base_priority": 24, "run_time_counter": 0, "stack_base": "3ffaf608", "stack_minimum": 472}, {"id": 9, "name": "re_events", "core": 0, "state": "blocked", "current_priority": 16, "base_priority": 16, "run_time_counter": 0, "stack_base": "3ffca8fc", "stack_minimum": 1812}, {"id": 11, "name": "http_send", "core": 1, "state": "blocked", "current_priority": 5, "base_priority": 5, "run_time_counter": 0, "stack_base": "3ffb528c", "stack_minimum": 1124}, {"id": 20, "name": "wifi", "core": 0, "state": "blocked", "current_priority": 23, "base_priority": 23, "run_time_counter": 0, "stack_base": "3ffd3484","stack_minimum": 4556}, {"id": 15, "name": "siren", "core": 1, "state": "blocked", "current_priority": 13, "base_priority": 13, "run_time_counter": 0, "stack_base": "3ffcd6cc", "stack_minimum": 516}, {"id": 16, "name": "flasher", "core": 1, "state": "blocked", "current_priority": 13, "base_priority": 13, "run_time_counter": 0, "stack_base": "3ffcdd24", "stack_minimum": 524} ]
Есть ещё два топика, которые работают только “на вход”, то есть через них можно что-то отправить на устройство, но их нельзя увидеть например через MQTT Explorer:
🔸<LOCATION>/<DEVICE>/system/ota – в этот топик вы должны отправить ссылку на прошивку (BIN-файл) для обновления “по воздуху” (ОТА). Подробнее об этом можно почитать тут.
🔸<LOCATION>/<DEVICE>/system/terminal – в этот топик можно отправлять служебные команды для выполнения каких-либо действий, например перезагрузки. Подробнее об этом можно почитать тут.
Топики настроек и параметров
Для удаленного управления параметрами устройства предусмотрен большой раздел <LOCATION>/<DEVICE>/config. Все параметры здесь публикуются в открытом виде, без JSON.
В прошивке поддерживается изменение параметров с подтверждением получения в “ответном” разделе <LOCATION>/<DEVICE>/confirm (включено по умолчанию). Это решает две задачи: клиент MQTT на смартфоне всегда знает последние актуальные настройки и мы всегда уверены, то изменение какого-либо параметра успешно “принято-понято” нашим устройством.
Как это работает:
В момент запуска и подключения к MQTT устройство публикует все известные ему параметры (которые хранятся в памяти NVS) в разделе <LOCATION>/<DEVICE>/confirm
.
Затем, при попытке изменения параметра мы должны отправить новое значение в <LOCATION>/<DEVICE>/config
. Получив эти данные, устройство проверяет значение, записывает его в хранилище NVS, и только после этого отправляет его обратно в <LOCATION>/<DEVICE>/confirm
. Клиент MQTT на смартфоне должен “откатить” отправленное значение, если не было получено подтверждение в течении некоторого времени.
Параметров много, “на все случаи жизни” даже в прошивке самой простой телеметрии / метеостанции:

Пример структуры топиков настроек
Давайте рассмотрим их поподробнее.
Я буду писать названия топиков “подтверждения” с confirm, но вы должны понимать, то для отправки данных на устройство нужно заменить на config.
🔸<LOCATION>/<DEVICE>/confirm/common/silent_mode – интервал времени суток “тихого режима”, когда отключаются встроенные светодиоды и (опционально) звуки, дабы не мешать сну. Указывать интервалы следует в формате Ч1:М1-Ч2:М2
.
Все параметры – интервалы указываются с точностью до минуты. Но при этом интервалы всегда отсчитываются с начала минуты, то есть 0 секунд каждой минуты.
🔸<LOCATION>/<DEVICE>/confirm/notifications – здесь собраны параметры, отвечающие за то, какие уведомления о проблемах вы будете получать от устройства.
Думаю, особые пояснения в данном случае нужны только под одному параметру: delay. Этот параметр отвечает за отложенные уведомления. Если на устройстве произошел какой-то сбой, то уведомление об этом сбое будет отправлено в чат только спустя указанное в delay количество секунд. Если в течение этого времени проблема самоликвидировалась, то и уведомления вы не получите. Это позволяет эффективно фильтровать кратковременные проблемы и отключения от сервисов. Поставьте 0 для немедленных уведомлений (полезно только для отладки).
🔸<LOCATION>/<DEVICE>/confirm/ping – параметры постоянного пинга серверов в интернете для контроля канала связи. Включается с помощью опции в файле конфигурации CONFIG_PINGER_ENABLE
. Параметров в этом разделе достаточно много, но изменять их требуется только в особо сложных случаях.
🔸<LOCATION>/<DEVICE>/confirm/sensors/<НАЗВАНИЕ_СЕНСОРА> – параметры сенсоров измерения различных физических величин. Для каждого сенсора доступны следующие параметры:
- offset – смещение значения. Может использоваться, если вы имеете образцовое средство измерения и хотите скорректировать измеренное до данных образцового
- filter_mode – режим фильтрации. На текущий момент может принимать три значения: 0 – фильтр отключен, 1 – среднее, 2 – медиана
- filter_size – размер буфера фильтра для filter_mode = 1 или 2
- delta_max – максимальное отклонение измеренного значения от предыдущего значения. Используется для сенсоров AHT10, у которых отсутствует CRC при передаче по шине, и невозможно как-то определить достоверность полученных данных. Из-за этого в некоторых случаях полученные данные могут скака аки тыгдымские кони. Вы можете задать максимальный лимит изменения за один период изменений, свыше которого полученное значение будет считаться “плохим” и отбрасываться.
🔸<LOCATION>/<DEVICE>/confirm/temp_control/<НАЗВАНИЕ_СЕНСОРА> – параметры контроля заданных диапазонов температуры. Контролировать можно не только температуры, правильнее было бы range_control, но так уж исторически сложилось…
- min – минимальное значение допустимого диапазона
- max – максимальное значение допустимого диапазона
- hysteresis – гистерезис, то есть разница между значениями перехода границы диапазона “туда” и “обратно”. Должен быть больше 0, чтобы не получать уведомления каждые несколько секунд на границах диапазонов
- notify – с помощью этого параметра можно включать и отключать уведомления в telegram
Топики сенсоров
Топики сенсоров генерируются по шаблону: <LOCATION>/<DEVICE>/<НАЗВАНИЕ_СЕНСОРА>
Сюда публикуется JSON пакет данных, содержащий все имеющиеся данные для всех измеряемых величин (например температура, давление и влажность). Выглядит это примерно так:
{ "status": "OK", "humidity": { "value": {"value": 39.83, "raw": 33, "time": "03.05.24 12:41", "tsv": "39.83%\n03|12:41"}, "extremums": { "entirely": { "min": {"value": 21.15, "raw": 21.15345, "time": "19.06.23 11:38", "tsv": "21.15%\n19|11:38"}, "max": {"value": 100, "raw": 99.999908, "time": "09.07.23 21:45", "tsv": "100.00%\n09|21:45"} }, "weekly": { "min": {"value": 33.66, "raw": 27.200001, "time": "30.04.24 14:51", "tsv": "33.66%\n30|14:51"}, "max": {"value": 94.87, "raw": 87.800003, "time": "30.04.24 04:43", "tsv": "94.87%\n30|04:43"} }, "daily": { "min": {"value": 37.59, "raw": 31.799999, "time": "03.05.24 12:10", "tsv": "37.59%\n03|12:10"}, "max": {"value": 90.89, "raw": 83.5, "time": "03.05.24 01:56", "tsv": "90.89%\n03|01:56"} } } }, "temperature": { "value": {"value": 6.32, "raw": 7.2, "time": "03.05.24 12:41", "tsv": "6.32°С\n03|12:41"}, "extremums": { "entirely": { "min": {"value": -22.68, "raw": -22.676277, "time": "09.12.23 07:23", "tsv": "-22.68°С\n09|07:23"}, "max": {"value": 43.45, "raw": 43.449593, "time": "06.08.23 11:05", "tsv": "43.45°С\n06|11:05"} }, "weekly": { "min": {"value": -1.12, "raw": 0.1, "time": "03.05.24 04:58", "tsv": "-1.12°С\n03|04:58"}, "max": {"value": 24.37, "raw": 25.6, "time": "30.04.24 14:11", "tsv": "24.37°С\n30|14:11"} }, "daily": { "min": {"value": -1.12, "raw": 0.1, "time": "03.05.24 04:58", "tsv": "-1.12°С\n03|04:58"}, "max": {"value": 7.39, "raw": 8.6, "time": "03.05.24 12:26", "tsv": "7.39°С\n03|12:26"} } } }, "display": "6.32°С\n39.83%" }
Корневой элемент JSON содержит поля:
- status – для информации о текущем состоянии сенсора
- display – смешанные многострочные данные с сенсора для отображения на одной плитке MQTT dashboard на смартфонах
- а также вложенные структуры JSON для каждого из измерительных элементов сенсора, в нашем случае это humidity и temperature.
Каждый элемент, в свою очередь также состоит из нескольких блоков информации:
- value – текущие (последние измеренные) данные
- extremums – зафиксированные экстремумы (минимумы и максимумы) за несколько периодов: entirely – всё время работы с момента его первого запуска; weekly – последняя неделя; daily – текущие сутки
Каждый из блоков содержит следующие поля:
- value – обработанное и отфильтрованное значение с учетом корректировки (смещения)
- raw – необработанное значение в том виде, а каком оно было получено непосредственно с сенсора
- time – время измерения
- tsv – обработанное значение, совмещенное с временем измерения в двух строках (для наглядности отображения)
Структура JSON не строго фиксированная, её можно корректировать в некоторых пределах:
Топики контроля диапазонов
В программе за контролем значений внутри заданных диапазонов (например температуры в помещении или инкубаторе) “занимается” определенный класс, которому выделен шаблон топиков:
<LOCATION>/<DEVICE>/temp_control/<НАЗВАНИЕ_СЕНСОРА>
Как и в предыдущих случаях, здесь также публикуется JSON-пакет, который содержит следующую информацию:
{ "status": 0, "value": 18.56237, "last_normal": "01.02.2024 12:05", "last_min": "01.02.2024 11:57", "last_max": "---" }
- status – состояние в цифровом виде: ошибка:-2; ниже нормы: -1; норма: 0; выше нормы: 1
- value – текущее значение
- last_normal – время, когда был зафиксирован последний переход к нормальному состоянию
- last_min – время, когда был зафиксирован переход ниже нижней границы
- last_max– время, когда был зафиксирован переход выше верхней границы
Этот класс может использоваться не только для контроля диапазонов температуры, но и например тока или напряжения.
Топики нагрузки
Если в составе устройства есть какая-либо программно-управляемая нагрузка, то устройство может публиковать состояние этой нагрузки: <LOCATION>/<DEVICE>/<НАГРУЗКА>
Публикуемая информация имеет следующую структуру:
{ "status": 0, "timestamp": {"on": "03.05.2024 07:28:23", "off": "03.05.2024 07:47:21"}, "durations": {"last": 1138, "total": 556347, "today": 29027, "yesterday": 46470, "week_curr": 76123, "week_prev": 0, "month_curr": 75497, "month_prev": 626, "period_curr": 76123, "period_prev": 0, "year_curr": 76123, "year_prev": 0}, "counters": {"total": 33, "today": 1, "yesterday": 5, "week_curr": 9, "week_prev": 0, "month_curr": 7, "month_prev": 2, "period_curr": 9, "period_prev": 0, "year_curr": 9, "year_prev": 0} }
- status – состояние нагрузки в текущий момент времени в цифровом виде: 0 – отключено; 1 – включено
- timestamp – время последнего включения и выключения нагрузки
- durations – длительность работы нагрузки в секундах за последний сеанс, текущий день, предыдущий день, неделю и т.д. Зная мощность нагрузки (если она примерно постоянная – вентилятор, котёл, лампа и т.д.), мы можем легко посчитать потребляемую мощность в кВт.
- counters – просто количество включений нагрузки за те же периоды. Не спрашивайте зачем – не знаю, путь будет
Разумеется, ваша прошивка может публиковать данные в какие-то другие топики. Вы можете проявить фантазию и реализовать ваши идеи. Но базовый набор строительных “кубиков” для сенсоров, диапазонов и нагрузок уже имеется, нужно только их правильно использовать. А как это сделать, я расскажу в следующих статьях.
Все статьи цикла “Термостат и ОПС”:
- Часть 1. Вводная: общее описание и возможности
- Часть 2. Перечень необходимых компонентов, схемы отдельных узлов, печатная плата
- Часть 3. Минимальный вариант: только телеметрия через MQTT брокер
- Часть 4. Описание генерируемых устройством MQTT-топиков
- Часть 5. Добавляем выгрузку данных на внешние сервисы
- Часть 6. Изменения в прошивке под требования на ESP-IDF 5.0.1
- Часть 7. Автоматический контроль диапазонов температуры
- Часть 8. Класс rSensor и как заменить сенсоры на другие из списка поддерживаемых
- Часть 9. Термостат и управление нагрузкой
- Часть 10. Охранно-пожарная и аварийная сигнализация
Прошивка K12 для ESP32 и ESP-IDF:
Дополнительные статьи, которые применимы к любым устройствам, запрограммированным с помощью тех же самых библиотек.
- Прошивка для ESP32 на основе ESP-IDF: описание модулей и библиотек
- Настройка Android-приложения MQTT Dash для работы с устройством
- rLoadControl: индикация состояния нагрузки на MQTT DASH
- Команды управления
💠 Полный архив статей вы найдете здесь
Пожалуйста, оцените статью:
-= Каталог статей (по разделам) =- -= Архив статей (подряд) =-