ГлавнаяАкадемияNode-RED: установка, flows, msg/JSON, отладка → Основы MQTT: Publish/Subscribe, брокер, топики, QoS

Основы MQTT: Publish/Subscribe, брокер, топики, QoS

Урок · Node-RED: установка, flows, msg/JSON, отладка · 30 мин · theory

Введение в MQTT и модель Publish/Subscribe

MQTT (Message Queuing Telemetry Transport) — это легковесный сетевой протокол обмена сообщениями, работающий поверх TCP/IP. Он спроектирован для использования в условиях ограниченной пропускной способности сети и на устройствах с малым объемом вычислительных ресурсов. Эти характеристики делают его идеальным решением для межмашинного взаимодействия (M2M) и Интернета Вещей (IoT), где тысячи датчиков и исполнительных устройств должны обмениваться данными надежно и эффективно. На контроллере платформы HI протокол MQTT является одной из ключевых технологий для построения распределенных систем автоматизации.

> ℹ️ Информация: MQTT был разработан инженерами IBM в конце 90-х годов для мониторинга состояния нефтепроводов в реальном времени. Задача стояла в том, чтобы надежно передавать небольшие объемы телеметрических данных по спутниковым каналам связи, которые отличались высокой стоимостью трафика и нестабильностью. Именно эти жесткие требования и определили ключевые преимущества протокола, которые сегодня востребованы в IoT.

Основное отличие MQTT от традиционных протоколов, таких как HTTP, заключается в его архитектурной модели — «Издатель/Подписчик» (Publish/Subscribe, или Pub/Sub). Давайте сравним ее с более привычной моделью «клиент-сервер».

В модели «клиент-сервер»:

  • Клиент инициирует соединение с сервером.
  • Клиент напрямую запрашивает у сервера конкретные данные.
  • Сервер отвечает на этот запрос, отправляя данные обратно клиенту.
  • Клиент и сервер должны знать о существовании друг друга (например, по IP-адресу). Связь между ними прямая и синхронная.
  • В модели «Издатель/Подписчик» (MQTT):

  • Издатель (Publisher) — устройство, которое генерирует данные (например, датчик температуры). Он отправляет сообщение в систему, не зная, кто его получит.
  • Подписчик (Subscriber) — устройство, которое заинтересовано в получении данных (например, логика управления климатом). Он заявляет о своем интересе к определенному типу данных, не зная, кто их поставляет.
  • Брокер (Broker) — центральный сервер-посредник, который принимает сообщения от всех издателей и доставляет их всем заинтересованным подписчикам.
  • Таким образом, издатели и подписчики полностью декаплированы (развязаны) друг от друга. Датчик температуры не имеет ни малейшего представления о том, кто использует его показания — панель визуализации, система отопления или облачный сервис для аналитики. Аналогично, система отопления не знает, какой именно датчик предоставляет ей данные о температуре. Эта развязка обеспечивается брокером.

    Преимущества модели Publish/Subscribe и протокола MQTT

    Использование такой архитектуры дает ряд фундаментальных преимуществ, критически важных для систем автоматизации:

    Для контроллеров HI, MQTT является нервной системой проекта, связывающей воедино логику Node-RED, физические входы/выходы, стороннее оборудование (например, по Modbus), пользовательские интерфейсы и облачные платформы.

    ---

    Архитектура MQTT: Брокер и Топики

    Теперь, когда мы поняли концепцию Pub/Sub, давайте детальнее разберем два ее ключевых элемента: брокера и механизм маршрутизации сообщений — топики.

    Роль MQTT-Брокера

    Брокер MQTT — это центральный сервер, который управляет всем процессом обмена сообщениями. Его можно представить как "почтовое отделение" вашей системы автоматизации.

    Его основные задачи:

  • Прием сообщений: Получать все сообщения, отправленные издателями.
  • Фильтрация и маршрутизация: Определять, кому из подписчиков предназначено каждое сообщение.
  • Доставка сообщений: Отправлять сообщения всем соответствующим подписчикам.
  • Управление подключениями: Отслеживать, какие клиенты в данный момент подключены к системе.
  • Аутентификация и авторизация (опционально): Проверять, имеют ли клиенты право подключаться, публиковать и подписываться на определенные данные.
  • На борту контроллера HI по умолчанию установлен и настроен один из самых популярных и надежных брокеров — Mosquitto. Это означает, что для организации обмена данными внутри одного объекта вам не требуется дополнительное серверное оборудование. Все клиенты — будь то потоки Node-RED, датчики, мобильные приложения или другие контроллеры в локальной сети — подключаются к этому встроенному брокеру.

    Топики: Адресная система MQTT

    Если брокер — это почтовое отделение, то топики (topics) — это почтовые адреса. Топик представляет собой строку в формате UTF-8, которая определяет "канал" или "категорию" для сообщения. Именно на основе топиков брокер решает, кому доставить сообщение.

    Топики имеют иерархическую структуру, уровни которой разделяются косой чертой (`/`). Это позволяет создавать логичную и понятную структуру данных в проекте.

    > 💡 Подсказка: Проектируйте структуру топиков заранее. Хорошая иерархия — залог масштабируемой и легко обслуживаемой системы. Рекомендуемая практика: `проект/местоположение/устройство/параметр`. Например: `my-home/floor1/living-room/light-group1/state`.

    Рассмотрим хороший пример структуры топиков для умного дома:

    Издатель, отправляя сообщение, указывает топик. Например, датчик температуры публикует значение `23.5` в топик `my-home/floor1/living-room/temperature`. Подписчик (например, Node-RED flow, управляющий кондиционером) подписывается на этот топик и немедленно получает сообщение, как только оно поступает на брокер.

    Шаблоны подписки (Wildcards)

    MQTT предоставляет мощный механизм для подписки сразу на несколько топиков с помощью шаблонов (wildcards). Их всего два:

    | Шаблон подписки | Примеры совпадающих топиков | Примеры несовпадающих топиков |

    | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |

    | `my-home/floor1/+/temperature` | `my-home/floor1/living-room/temperature`
    `my-home/floor1/kitchen/temperature` | `my-home/floor2/bedroom/temperature`
    `my-home/floor1/humidity` |

    | `my-home/+/living-room/light-main/#` | `my-home/floor1/living-room/light-main/state`
    `my-home/floor1/living-room/light-main/command`
    `my-home/floor2/living-room/light-main/state` | `my-home/floor1/kitchen/light/state` |

    | `my-home/security/#` | `my-home/security/main-door/status`
    `my-home/security/garage/motion-sensor`
    `my-home/security/alarm/state` | `my-home/floor1/temperature` |

    Использование шаблонов позволяет создавать гибкие системы мониторинга и логирования. Например, можно создать один поток в Node-RED, который подписывается на `my-home/#` и записывает абсолютно все сообщения системы в базу данных MySQL для последующего анализа.

    ---

    Практика: Публикация и подписка в Node-RED

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

    Обзор узлов `mqtt in` и `mqtt out`

    В стандартной палитре Node-RED есть два основных узла для работы с MQTT:

    Шаг 1: Настройка подключения к MQTT-брокеру

    Прежде чем использовать узлы, нам нужно настроить подключение к брокеру. Эта настройка создается один раз и затем используется во всех MQTT-узлах.

  • Перетащите на холст узел `mqtt out`.
  • Дважды щелкните по нему, чтобы открыть окно настроек.
  • В поле "Server" вы увидите выпадающий список. Выберите "Add new mqtt-broker..." и нажмите на иконку карандаша справа.
  • Откроется окно конфигурации узла `mqtt-broker`. Заполните поля на вкладке "Connection":
  • * Name: `HI Local Broker` (или любое понятное вам имя).

    * Server: `localhost` (можно также использовать `127.0.0.1`). Это указывает, что брокер запущен на самом контроллере.

    * Port: `1883`. Это стандартный порт для MQTT без шифрования.

  • Нажмите "Add" или "Update", чтобы сохранить конфигурацию брокера. Теперь вы вернулись в настройки узла `mqtt out`.
  • Шаг 2: Создание потока для публикации данных (Publisher)

    Создадим поток, который по нажатию кнопки будет отправлять JSON-объект в MQTT.

  • Возьмите узел `Inject` и перетащите его на холст.
  • Настройте `Inject`:
  • * Payload: выберите тип `JSON`.

    * В редактор JSON вставьте объект, соответствующий нашему стандартному контракту сообщений (как было рассмотрено в предыдущих уроках):

            {

    "value": true,

    "source": "manual-test-button",

    "ts": 1678886400000

    }

    > 💡 Подсказка: Вместо статичного `ts` можно использовать `timestamp` из узла `Inject`, который затем преобразуется в нужный формат в узле `Function`. Для нашего примера статического значения достаточно.

    * Topic: `home/test/light/command`

  • Соедините выход узла `Inject` со входом узла `mqtt out`.
  • Настройте узел `mqtt out`:
  • * Server: Убедитесь, что выбран `HI Local Broker @ localhost:1883`.

    * Topic: Оставьте это поле пустым. В этом случае узел будет использовать топик, заданный в `msg.topic` входящего сообщения. Это очень гибкая практика.

    * QoS: Оставьте `0 - at most once`.

    * Retain: Оставьте `false`.

    * Name: "Publish Test Command"

    Шаг 3: Создание потока для подписки (Subscriber)

    Теперь создадим поток, который будет слушать тот же топик и выводить полученные сообщения в панель отладки.

  • Перетащите на холст узел `mqtt in`.
  • Настройте `mqtt in`:
  • * Server: Выберите тот же `HI Local Broker @ localhost:1883`.

    * Topic: `home/test/light/command`.

    * QoS: `0 - at most once`.

    * Output: `a parsed JSON object`. Это очень удобная опция, которая автоматически преобразует входящую JSON-строку в JavaScript-объект в `msg.payload`.

    * Name: "Subscribe to Test Commands".

  • Возьмите узел `Debug` и соедините его с выходом узла `mqtt in`.
  • Настройте `Debug`:
  • * Output: выберите `complete msg object`, чтобы видеть не только `payload`, но и `topic`, `qos` и другие свойства.

    Шаг 4: Тестирование

    Ваш холст теперь должен выглядеть примерно так:

    // Поток публикации
    

    [Inject] ---> [mqtt out: "Publish Test Command"]

    // Поток подписки

    [mqtt in: "Subscribe to Test Commands"] ---> [Debug]

  • Нажмите кнопку Deploy. Под узлами MQTT должны появиться зеленые индикаторы "connected".
  • Перейдите в панель отладки (справа, иконка жука).
  • Нажмите на кнопку слева от узла `Inject`.
  • В панели отладки вы мгновенно увидите новое сообщение. Оно будет выглядеть примерно так:

    {
    

    "topic": "home/test/light/command",

    "payload": {

    "value": true,

    "source": "manual-test-button",

    "ts": 1678886400000

    },

    "qos": 0,

    "retain": false,

    "_msgid": "..."

    }

    Поздравляем! Вы только что реализовали полный цикл Publish/Subscribe. Узел `Inject` выступил в роли издателя, а узел `Debug` через `mqtt in` — в роли подписчика. Их коммуникация произошла асинхронно через брокер.

    ---

    Уровни качества обслуживания (QoS) и LWT

    Протокол MQTT был создан для работы в ненадежных сетях, поэтому в нем заложены механизмы, позволяющие управлять гарантией доставки сообщений. Эти механизмы называются уровнями качества обслуживания (Quality of Service, QoS).

    Выбор правильного QoS — это всегда компромисс между надежностью и накладными расходами (трафиком и загрузкой процессора).

    Три уровня QoS

    * Принцип: "Отправил и забыл". Клиент отправляет сообщение брокеру один раз. Никаких подтверждений не используется.

    * Гарантия: Нет гарантии доставки. Сообщение может быть потеряно, если произойдет разрыв соединения.

    * Накладные расходы: Минимальные. Самый быстрый уровень.

    * Когда использовать: Для частых, но не критически важных данных, потеря которых не страшна. Например, телеметрия с датчика температуры, отправляемая каждые 5 секунд. Если одно значение потеряется, через 5 секунд придет новое.

    * Принцип: "Гарантированная доставка". Брокер должен подтвердить получение сообщения от издателя (отправив пакет `PUBACK`). Если издатель не получает подтверждения за таймаут, он отправляет сообщение заново.

    * Гарантия: Сообщение будет доставлено как минимум один раз. В редких случаях (если `PUBACK` потерялся, но сообщение было доставлено) оно может быть доставлено повторно.

    * Накладные расходы: Средние. Требуется дополнительный обмен пакетами.

    * Когда использовать: Для команд и важных событий, потеря которых недопустима. Например, команда на включение реле света или открытие клапана воды. Повторное получение команды "включить" обычно не является проблемой. Это самый распространенный уровень QoS в системах автоматизации.

    * Принцип: "Гарантированная доставка без дубликатов". Используется 4-этапный квитирующий обмен (`PUBREC`, `PUBREL`, `PUBCOMP`) между издателем и брокером.

    * Гарантия: Сообщение будет доставлено ровно один раз.

    * Накладные расходы: Максимальные. Самый медленный и ресурсоемкий уровень.

    * Когда использовать: Только в самых критически важных системах, где дублирование сообщений так же недопустимо, как и их потеря. Например, в системах биллинга или финансовых транзакциях. В 99% задач умного дома или промышленной автоматизации этот уровень избыточен.

    > ⚠️ Внимание: Использование QoS 2 создает значительную нагрузку на сеть, процессор контроллера и брокер. Применяйте его только после тщательного анализа и в исключительных случаях, когда недопустима ни потеря, ни дублирование сообщений.

    Последнее завещание (Last Will and Testament, LWT)

    LWT — это мощная функция MQTT, позволяющая клиенту заранее определить сообщение, которое брокер опубликует от его имени в случае некорректного разрыва соединения (например, обрыв кабеля, сбой питания устройства, зависание ПО).

    Как это работает:

  • Клиент (например, контроллер насосной станции) подключается к брокеру.
  • В момент подключения он сообщает брокеру свое "завещание":
  • * LWT Topic: `devices/pump-station-1/status`

    * LWT Message: `offline`

    * LWT QoS: `1`

  • Если клиент корректно отключается (отправив команду `DISCONNECT`), LWT не срабатывает.
  • Если же соединение рвется неожиданно (пропадает пинг, истекает keep-alive таймер), брокер немедленно публикует сообщение `offline` в топик `devices/pump-station-1/status`.
  • Основной диспетчерский поток в Node-RED может быть подписан на топик `devices/+/status`. Получив сообщение `offline`, он может немедленно запустить аварийный сценарий: отправить уведомление оператору, переключиться на резервное оборудование и т.д. Таким образом, LWT является фундаментальным инструментом для построения отказоустойчивых систем и мониторинга доступности всех компонентов вашей IoT-инфраструктуры.

    ---

    Резюме и выводы

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

    > 📋 Ключевые понятия:

    > * MQTT: Легковесный протокол для M2M/IoT.

    > * Publish/Subscribe: Асинхронная модель обмена данными, decoupled.

    > * Брокер: Центральный сервер, маршрутизирующий сообщения.

    > * Клиент: Любое устройство или ПО, подключающееся к брокеру.

    > * Топик: Иерархический адрес для сообщений.

    > * QoS: Уровень гарантии доставки сообщения.

    > * LWT: Механизм для отслеживания нештатного отключения клиентов.

    Ключевой вывод заключается в том, что MQTT — это не просто протокол, а архитектурный паттерн. Он идеально подходит для событийно-ориентированной среды Node-RED, позволяя создавать гибкие, масштабируемые и отказоустойчивые решения. Устройства и логические блоки больше не связаны друг с другом напрямую; они общаются через общего посредника, публикуя события и подписываясь на интересующую информацию.

    Приступая к проектированию системы на базе MQTT, инженер должен принять два важнейших архитектурных решения:

  • Разработать иерархию топиков: Эта структура определяет информационную модель всего вашего объекта. Она должна быть логичной, расширяемой и понятной.
  • Выбрать адекватный уровень QoS для каждого потока данных: QoS 0 для частой телеметрии, QoS 1 для важных команд и событий. Это баланс между надежностью и производительностью.
  • Что дальше

    Мы рассмотрели основы, но у MQTT есть и более продвинутые функции, которые позволяют решать сложные задачи. В следующем уроке, `COURSE-06-M08-L02`, мы углубимся в следующие темы: