ГлавнаяАкадемияМонтаж и пусконаладка контроллера → Именование топиков MQTT

Именование топиков MQTT

Урок 3 · Монтаж и пусконаладка контроллера · 10 мин · theory

Основы и структура топиков 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`

Здесь мы видим четыре уровня иерархии:

  • `myhome`: Корневой уровень, определяющий весь объект.
  • `living-room`: Уровень, обозначающий конкретное помещение.
  • `temperature-sensor`: Уровень, идентифицирующий устройство.
  • `temperature`: Уровень, уточняющий тип данных (параметр).
  • Создание продуманной иерархии с самого начала критически важно для:

    Символы подстановки (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`

    Для управления устройствами используется простой и надежный подход, разделяющий потоки команд и потоки состояний.

    Этот "командно-отчетный" цикл гарантирует, что система всегда знает реальное состояние устройства, а не то, которое она думает, что отправила.

    Примеры полных топиков

    Ниже приведены примеры применения стандарта для типового оборудования на объекте `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`) из таблицы выше.

  • Пользователь нажимает кнопку в интерфейсе. Панель управления (или мобильное приложение) формирует и отправляет MQTT-сообщение.
  • * Topic: `hi/lab-stand/living-area/main-light-01/set`

    * Payload: `"ON"` (или `1`, `true` - зависит от стандарта полезной нагрузки, который мы рассмотрим в следующих уроках).

  • Узел в Node-RED получает команду. Сценарий, подписанный на топик `.../set`, получает это сообщение. `msg.topic` будет содержать топик, а `msg.payload` — команду.
  • Логика исполняет команду. Узел `function` или `change` обрабатывает команду и передает ее на узел `hi-relay-control`, который физически замыкает реле `RL-01`.
  • Контроллер отправляет обратную связь. После успешного переключения реле, узел `hi-relay-control` (или связанная с ним логика) формирует сообщение о фактическом состоянии и публикует его.
  • * Topic: `hi/lab-stand/living-area/main-light-01/status`

    * Payload: `"ON"`

  • Интерфейс обновляется. Панель управления, подписанная на топик `.../status`, получает это сообщение и обновляет иконку лампочки, показывая, что свет действительно включен.
  • Этот замкнутый цикл "команда -> исполнение -> обратная связь" является основой надежной системы автоматизации. Если реле по какой-то причине не сработает (например, сбой питания на модуле расширения), `status`-топик не обновится, и пользователь увидит в интерфейсе, что команда не была выполнена.

    ---

    Работа с топиками в Node-RED: подписки и wildcards

    Node-RED предоставляет мощные и интуитивно понятные инструменты для работы с MQTT — узлы `mqtt in` (подписка) и `mqtt out` (публикация).

    Подписка на топики с помощью `mqtt in`

    Узел `mqtt in` позволяет вашим сценариям "слушать" сообщения из одного или нескольких MQTT-топиков.

    Настройка узла `mqtt in`:
  • Server: Выберите предварительно настроенный MQTT-брокер. Обычно это `localhost:1883`, так как брокер работает на самом контроллере HI.
  • Topic: Укажите топик для подписки. Здесь вы можете использовать как полный путь, так и пути с символами подстановки.
  • QoS: Уровень качества обслуживания (Quality of Service). Для большинства команд и состояний достаточно `QoS 1` (сообщение будет доставлено как минимум один раз).
  • Output: `a parsed JSON object` — очень полезная опция, если вы ожидаете, что в `payload` будет строка в формате JSON. Node-RED автоматически преобразует ее в JavaScript-объект.
  • Примеры использования: * `Topic`: `hi/lab-stand/living-area/main-light-01/set`

    * Этот узел будет получать только команды, предназначенные для включения/выключения основного света.

    * `Topic` с wildcard `+`: `hi/lab-stand/+/+/temperature`

    * Этот узел получит сообщения из топиков:

    * `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`

    * `Topic` с wildcard `#`: `hi/lab-stand/#`

    * ⚠️ Внимание: Используйте эту подписку только для отладки с помощью узла `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-брокер.

    Настройка узла:
  • Server: Аналогично `mqtt in`, выберите ваш брокер.
  • Topic: Укажите топик, в который нужно опубликовать сообщение. Чаще всего это поле оставляют пустым.
  • QoS, Retain: Настройте по необходимости. `Retain: true` означает, что брокер сохранит последнее сообщение в этом топике. Любой новый подписчик сразу же получит это "запомненное" значение. Это полезно для `status`-топиков.
  • Если поле `Topic` в настройках узла пустое, он будет использовать значение из `msg.topic` входящего сообщения. Это позволяет создавать динамические сценарии.

    Пример: ответ на команду
  • Узел `mqtt in` подписан на `hi/lab-stand/+/+/set`.
  • Он получает сообщение с `msg.topic = "hi/lab-stand/living-area/main-light-01/set"` и `msg.payload = "ON"`.
  • Логика включает реле.
  • Далее узел `change` создает новый `msg`:
  • * `set msg.topic` to `"hi/lab-stand/living-area/main-light-01/status"`

    * `set msg.payload` to `"ON"`

  • Этот новый `msg` подается на вход узла `mqtt out` (с пустым полем Topic), и тот публикует `payload` в `topic`, заданный в сообщении.
  • С помощью этой связки `mqtt in` и `mqtt out` вы можете реализовать любую логику для вашей системы автоматизации.

    ---

    Резюме и лучшие практики

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

    > ℹ️ Информация: В следующем модуле мы будем активно использовать созданную структуру топиков для интеграции Modbus-устройств через MQTT шлюз. Правильно настроенные топики позволят бесшовно "встроить" промышленные датчики и модули в общую экосистему умного дома.

    Ключевые принципы, которые необходимо запомнить:
  • Строго следуйте стандарту `hi/<объект>/<помещение>/<устройство>/<параметр>`. Единообразие и предсказуемость — ваши лучшие друзья при отладке и поддержке системы.
  • Разделяйте команды и состояния. Всегда используйте суффиксы `/set` для команд и `/status` (или его отсутствие) для обратной связи. Никогда не публикуйте команду в `status`-топик и наоборот.
  • Документируйте всё. Каждый используемый топик должен быть занесен в I/O Map вашего проекта. Этот документ — главный источник правды для всех, кто будет работать с системой.
  • Используйте осмысленные, но краткие имена. `living-room` лучше, чем `gostinaya_komnata_nomer_odin`. `main-light` лучше, чем `potolochnaya_lustra_v_centre`. Имена должны быть понятны, но не перегружены лишней информацией.
  • Тестируйте с помощью wildcards. Используйте MQTT-клиент (например, MQTT Explorer) и подписку на ветку `#` для мониторинга всех сообщений на объекте во время пусконаладки. Это самый быстрый способ найти ошибки в именовании или логике.
  • Итоговая проверка качества вашей работы проста: откройте I/O Map и посмотрите на список MQTT-топиков. Если вы или другой инженер можете, не заглядывая в сценарии Node-RED, понять, за что отвечает каждый топик и как им управлять — ваша работа выполнена профессионально.

    Что дальше

    В следующем уроке мы перейдем к тестированию. Мы разработаем план дымового тестирования (Smoke Test Plan) для проверки базовой работоспособности всех подключенных устройств и их взаимодействия через созданную нами структуру MQTT-топиков.