Именование топиков MQTT
Основы и структура топиков MQTT
В экосистеме умного дома и промышленной автоматизации MQTT (Message Queuing Telemetry Transport) является основным протоколом для обмена данными между устройствами. Он легковесный, быстрый и надежный. Центральным элементом архитектуры MQTT является брокер — сервер, который принимает сообщения от одних устройств (издателей) и перенаправляет их другим (подписчикам). Маршрутизация этих сообщений происходит с помощью топиков (topics).
> 💡 Подсказка: Рассматривайте структуру топиков как файловую систему на вашем компьютере. Чем лучше она организована с самого начала, тем проще будет найти нужные данные и управлять устройствами в будущем. Путь `C:\Documents\Invoices\2023\Client_A.pdf` интуитивно понятен. Точно так же должен быть понятен и MQTT-топик.
Топик в MQTT — это иерархический путь в формате UTF-8 строки, который брокер использует для фильтрации и доставки сообщений. Издатель (например, датчик температуры) отправляет сообщение в конкретный топик, а подписчики (например, панель визуализации или логический сценарий в Node-RED), которые заинтересованы в этих данных, подписываются на этот топик и получают все сообщения, отправленные в него.Структура и уровни
Топики имеют иерархическую структуру, уровни которой разделяются косой чертой (`/`). Эта структура позволяет логически группировать устройства и данные.
Например, топик для датчика температуры в гостиной может выглядеть так:
`myhome/living-room/temperature-sensor/temperature`
Здесь мы видим четыре уровня иерархии:
Создание продуманной иерархии с самого начала критически важно для:
- Масштабируемости: При добавлении сотен устройств система остается управляемой.
- Отладки: Легко отследить источник данных или команды, просто взглянув на топик.
- Безопасности: Можно гибко настраивать права доступа (ACL — Access Control Lists) для пользователей или групп устройств к определенным веткам топиков.
- Поддержки: Новому инженеру будет проще разобраться в логике работы системы.
Символы подстановки (Wildcards)
MQTT предоставляет два мощных символа подстановки, которые позволяют подписчикам получать сообщения из нескольких топиков одновременно.
📋 Ключевые понятия:
- Одноуровневый символ (`+`): Заменяет ровно один уровень в иерархии топика.
- Многоуровневый символ (`#`): Заменяет один или несколько уровней в конце топика. Он должен быть последним символом в пути.
| Символ | Пример подписки | На какие топики сработает | На какие НЕ сработает |
| :----- | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------- |
| `+` | `myhome/+/temperature-sensor/temp` | `myhome/living-room/temperature-sensor/temp`
`myhome/kitchen/temperature-sensor/temp` | `myhome/temperature-sensor/temp` (пропущен уровень) |
| `#` | `myhome/living-room/#` | `myhome/living-room/temperature-sensor/temp`
`myhome/living-room/main-light/state`
`myhome/living-room/co2/value` | `myhome/kitchen/temperature-sensor/temp` (другой уровень) |
Использование wildcards — это основной инструмент для отладки и создания гибких сценариев, который мы подробно рассмотрим далее при работе в Node-RED.
---
Стандарт именования HI: `hi/<объект>/<помещение>/<устройство>/<параметр>`
Для обеспечения унификации проектов и простоты их поддержки, в экосистеме Home Intelligence принят строгий стандарт именования топиков. Отступление от этого стандарта в сертифицируемых проектах не допускается.
> ⚠️ Внимание: Используйте в именах топиков только латинские символы в нижнем регистре, цифры и дефисы (`-`). Пробелы, кириллица и спецсимволы (кроме разделителя `/`) могут привести к непредсказуемому поведению MQTT-брокера и создадут серьезные проблемы при интеграции со сторонними системами (например, голосовыми ассистентами или облачными сервисами).
Общая структура стандарта:
`hi/<объект>/<помещение>/<устройство>/<параметр_и_действие>`
Разберем каждый компонент подробно:
| Компонент | Описание | Примеры |
| :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------- |
| `hi` | Префикс, идентифицирующий все топики, относящиеся к экосистеме HI. Позволяет избежать конфликтов, если на одном брокере работают несколько систем. | `hi` (неизменяемый) |
| `<объект>` | Уникальный идентификатор объекта (здания, квартиры, офиса). Как правило, это краткое название или ID проекта. | `site-main`, `office-ekb-1`, `cottage-dmitrov` |
| `<помещение>` | Идентификатор комнаты, зоны или технического помещения (например, электрощитовой). Для зон, охватывающих несколько комнат, могут использоваться общие имена. | `living-room`, `kitchen`, `bedroom-1`, `corridor-floor-2`, `tech-room` |
| `<устройство>` | Уникальный ID устройства или логической группы. Это имя должно совпадать с маркировкой на самом устройстве и в I/O Map. | `temp-sensor-01`, `main-light`, `window-drive-west`, `water-meter-hot`, `dali-gw-01` |
| `<параметр_и_действие>` | Самая важная часть, определяющая, какие данные передаются и что с ними можно сделать. Состоит из названия параметра и суффикса действия. | `temperature`, `humidity`, `state`, `brightness`, `command` |
Суффиксы `/status` и `/set`
Для управления устройствами используется простой и надежный подход, разделяющий потоки команд и потоки состояний.
- `/status` (или без суффикса): Топик только для чтения. Устройство публикует в него свое текущее фактическое состояние. Например, датчик температуры публикует сюда показания, а реле — свое текущее состояние (включено или выключено). Сценарии и панели визуализации подписываются на этот топик.
- `/set`: Топик только для записи. Сценарии и панели визуализации публикуют в него команды для устройства. Устройство, получив команду из этого топика, выполняет действие и затем публикует свое новое фактическое состояние в топик `/status`.
Этот "командно-отчетный" цикл гарантирует, что система всегда знает реальное состояние устройства, а не то, которое она думает, что отправила.
Примеры полных топиков
Ниже приведены примеры применения стандарта для типового оборудования на объекте `site-main`.
// 1. Датчик температуры и влажности (ID: th-sens-01) в гостиной
// Публикует свои показания
hi/site-main/living-room/th-sens-01/temperature
hi/site-main/living-room/th-sens-01/humidity
// 2. Основная группа света (ID: main-light) в гостиной, управляемая реле
// Для отправки команды на включение/выключение
hi/site-main/living-room/main-light/set
// Для получения реального состояния реле (обратная связь)
hi/site-main/living-room/main-light/status
// 3. Диммируемый светильник (ID: spot-light-01) в спальне
// Команда на изменение яркости (0-100)
hi/site-main/bedroom-1/spot-light-01/brightness/set
// Команда на включение/выключение
hi/site-main/bedroom-1/spot-light-01/state/set
// Получение текущей яркости
hi/site-main/bedroom-1/spot-light-01/brightness/status
// Получение текущего состояния (вкл/выкл)
hi/site-main/bedroom-1/spot-light-01/state/status
// 4. Датчик протечки воды (ID: leak-sensor-kitchen) на кухне
// Публикует свое состояние (true - протечка, false - сухо)
hi/site-main/kitchen/leak-sensor-kitchen/state
Как видно из примеров, такая структура позволяет мгновенно понять назначение любого сообщения в системе.
---
Практика: Картирование I/O на топики MQTT
Теперь соединим физический мир (клеммы контроллера HI) с цифровым (топики MQTT). Этот процесс называется картированием (mapping) и является ключевым этапом пусконаладки. Результат этой работы должен быть зафиксирован в проектной документации.
> 🔗 Связанный материал: Данный раздел напрямую связан с концепциями, изложенными в уроке COURSE-03-M04-L01 "Что такое карта входов-выходов (I/O Map)". Убедитесь, что ваша I/O Map, созданная на предыдущих уроках, актуальна и готова к дополнению.
Основная задача — сопоставить каждый физический вход (UI) и выход (RELAY) контроллера с его уникальным MQTT-топиком в соответствии со стандартом HI. Это сопоставление является "мостом" между аппаратной частью и программной логикой, реализованной в Node-RED.
Обновление I/O Map
Возьмем созданную ранее I/O Map и добавим в нее новый, самый важный для программиста столбец — `MQTT Topic`.
Пример фрагмента I/O Map для учебного стенда (объект `lab-stand`):| Тип I/O | Клемма HI | ID Устройства | Помещение | Функция | MQTT Topic (`/set` и `/status`) |
| :------ | :-------- | :----------------- | :------------ | :-------------------------------- | :------------------------------------------------------------------------------------------------ |
| Вход | UI-01 | `temp-sens-01` | `living-area` | Датчик температуры DS18B20 | `hi/lab-stand/living-area/temp-sens-01/temperature` |
| Вход | UI-02 | `wall-switch-01` | `living-area` | Кнопка управления светом (сухой контакт) | `hi/lab-stand/living-area/wall-switch-01/state` |
| Вход | UI-05 | `leak-sens-01` | `tech-zone` | Датчик протечки | `hi/lab-stand/tech-zone/leak-sens-01/state` |
| Выход | RL-01 | `main-light-01` | `living-area` | Основной свет, группа 1 | `set`: `hi/lab-stand/living-area/main-light-01/set`
`status`: `hi/lab-stand/living-area/main-light-01/status` |
| Выход | RL-02 | `sockets-group-01` | `living-area` | Управляемые розетки | `set`: `hi/lab-stand/living-area/sockets-group-01/set`
`status`: `hi/lab-stand/living-area/sockets-group-01/status` |
| Выход | RL-08 | `water-valve-main` | `tech-zone` | Электроклапан перекрытия воды | `set`: `hi/lab-stand/tech-zone/water-valve-main/set`
`status`: `hi/lab-stand/tech-zone/water-valve-main/status` |
Пример рабочего цикла: управление светом
Рассмотрим управление светом (`main-light-01`) из таблицы выше.
* Topic: `hi/lab-stand/living-area/main-light-01/set`
* Payload: `"ON"` (или `1`, `true` - зависит от стандарта полезной нагрузки, который мы рассмотрим в следующих уроках).
* Topic: `hi/lab-stand/living-area/main-light-01/status`
* Payload: `"ON"`
Этот замкнутый цикл "команда -> исполнение -> обратная связь" является основой надежной системы автоматизации. Если реле по какой-то причине не сработает (например, сбой питания на модуле расширения), `status`-топик не обновится, и пользователь увидит в интерфейсе, что команда не была выполнена.
---
Работа с топиками в Node-RED: подписки и wildcards
Node-RED предоставляет мощные и интуитивно понятные инструменты для работы с MQTT — узлы `mqtt in` (подписка) и `mqtt out` (публикация).
Подписка на топики с помощью `mqtt in`
Узел `mqtt in` позволяет вашим сценариям "слушать" сообщения из одного или нескольких MQTT-топиков.
Настройка узла `mqtt in`:- Подписка на команду для конкретного реле:
* Этот узел будет получать только команды, предназначенные для включения/выключения основного света.
- Подписка на данные со всех датчиков температуры в здании:
* Этот узел получит сообщения из топиков:
* `hi/lab-stand/living-area/temp-sens-01/temperature`
* `hi/lab-stand/kitchen/temp-sens-02/temperature`
* `hi/lab-stand/bedroom-1/temp-sens-03/temperature`
- Подписка на все события на объекте (для отладки):
* ⚠️ Внимание: Используйте эту подписку только для отладки с помощью узла `debug`. В рабочих сценариях она может создавать избыточную нагрузку, так как будет ловить абсолютно все сообщения.
Фильтрация и маршрутизация по `msg.topic`
Когда вы используете wildcards, в один узел `mqtt in` приходят сообщения из разных топиков. Чтобы понять, от какого именно устройства пришло сообщение, нужно анализировать свойство `msg.topic`. Для этого идеально подходит узел `switch`.
Пример потока для логирования температуры:// ASCII-схема потока
+----------------------------------+
[mqtt in] ----------> | switch (по msg.topic) |
hi/lab-stand/+/+/temp | |-- (выход 1) --> [function: format for living-area] --> [DB]
| содержит 'living-area' |
| |-- (выход 2) --> [function: format for kitchen] -----> [DB]
| содержит 'kitchen' |
+----------------------------------+
В узле `switch`, настроенном на проверку `msg.topic`, вы можете создать правила "contains" (содержит), "ends with" (заканчивается на) и т.д., чтобы направить сообщение по нужной ветке сценария.
Публикация данных с помощью `mqtt out`
Узел `mqtt out` используется для отправки сообщений в MQTT-брокер.
Настройка узла:Если поле `Topic` в настройках узла пустое, он будет использовать значение из `msg.topic` входящего сообщения. Это позволяет создавать динамические сценарии.
Пример: ответ на команду* `set msg.topic` to `"hi/lab-stand/living-area/main-light-01/status"`
* `set msg.payload` to `"ON"`
С помощью этой связки `mqtt in` и `mqtt out` вы можете реализовать любую логику для вашей системы автоматизации.
---
Резюме и лучшие практики
Правильная структура топиков MQTT — это не просто рекомендация, а фундамент надежной и масштабируемой системы. В этом уроке мы рассмотрели стандарт именования HI и научились применять его на практике, связывая физические входы-выходы контроллера с их цифровыми представлениями.
> ℹ️ Информация: В следующем модуле мы будем активно использовать созданную структуру топиков для интеграции Modbus-устройств через MQTT шлюз. Правильно настроенные топики позволят бесшовно "встроить" промышленные датчики и модули в общую экосистему умного дома.
Ключевые принципы, которые необходимо запомнить:Итоговая проверка качества вашей работы проста: откройте I/O Map и посмотрите на список MQTT-топиков. Если вы или другой инженер можете, не заглядывая в сценарии Node-RED, понять, за что отвечает каждый топик и как им управлять — ваша работа выполнена профессионально.
Что дальше
В следующем уроке мы перейдем к тестированию. Мы разработаем план дымового тестирования (Smoke Test Plan) для проверки базовой работоспособности всех подключенных устройств и их взаимодействия через созданную нами структуру MQTT-топиков.