MQTT: язык Интернета вещей
Что такое MQTT и почему он стал стандартом для IoT?
В предыдущих уроках мы рассмотрели протоколы, которые исторически использовались для связи устройств на объекте, такие как Modbus RTU и CAN. Они надежны и эффективны для локальных задач, но имеют ограничения при работе в глобальных сетях. MQTT (Message Queuing Telemetry Transport) — это протокол, созданный специально для эпохи «Интернета вещей» (IoT). Он работает поверх стека TCP/IP и использует совершенно иную модель взаимодействия, которая идеально подходит для распределенных систем с большим количеством устройств и потенциально ненадежными каналами связи.
> 💡 Подсказка: Модель Publish/Subscribe можно сравнить с подпиской на журнал. Вы подписываетесь на интересующую вас тему (topic), и почтальон (broker) доставляет вам свежий выпуск (message), как только он выходит. Вам не нужно постоянно спрашивать в редакции, не вышел ли новый номер.
Архитектура "Публикатор-Подписчик" (Publish/Subscribe)
В отличие от модели «запрос-ответ», используемой, например, в Modbus (где Master постоянно опрашивает Slave), MQTT построен на архитектуре «публикатор-подписчик» (Publish/Subscribe, или Pub/Sub). В этой модели устройства не общаются друг с другом напрямую. Вместо этого они общаются через центрального посредника.
📋 Ключевые понятия:
- Клиент (Client): Любое устройство или приложение, которое может подключаться к брокеру. Клиент может быть как публикатором (отправляет сообщения), так и подписчиком (получает сообщения), или и тем, и другим одновременно. Датчик температуры — типичный публикатор. Панель управления или сценарий автоматизации — типичный подписчик.
- Брокер (Broker): Центральный сервер, который действует как почтовая служба или диспетчер. Его задача — получать сообщения от публикаторов и доставлять их всем клиентам, которые подписаны на соответствующую тему. Брокер — это сердце всей MQTT-системы.
- Топик (Topic): Строковый идентификатор, который определяет "канал" или "тему" сообщения. Например, `home/living_room/temperature`. Публикаторы отправляют сообщения в определенный топик, а подписчики подписываются на топики, которые их интересуют.
Эта архитектура полностью разделяет (decouples) клиентов. Датчик, публикующий температуру, ничего не знает о том, кто будет использовать эти данные. Это может быть мобильное приложение, система климат-контроля и система сбора статистики одновременно. Они просто подписываются на один и тот же топик.
Преимущества MQTT
Благодаря этим качествам MQTT превратился из нишевого протокола для телеметрии в нефтегазовой отрасли (где он и был создан в конце 1990-х) в глобальный стандарт для миллионов IoT-устройств по всему миру — от умных лампочек до промышленных контроллеров и автомобилей.
---
MQTT-брокер: цифровой почтальон вашего умного дома
Как мы уже выяснили, брокер — это центральный узел всей MQTT-инфраструктуры. Он принимает на себя всю работу по управлению подписками и маршрутизации сообщений. На контроллере HI, работающем под управлением Debian, вы можете развернуть собственный MQTT-брокер, создав полностью автономную и независимую от облачных сервисов систему.
Роль и задачи брокера
- Прием сообщений: Получает сообщения от всех подключенных клиентов (публикаторов).
- Аутентификация и авторизация: Проверяет, имеет ли клиент право на подключение к брокеру и на публикацию/подписку на определенные топики.
- Фильтрация и доставка: Определяет, каким подписчикам необходимо доставить каждое конкретное сообщение на основе их подписок.
- Управление сессиями: Хранит информацию о подписках клиентов, в том числе для тех, кто временно находится не в сети (для доставки сообщений после восстановления связи).
Популярные реализации и установка Mosquitto
Существует множество реализаций MQTT-брокеров, но наиболее популярным для локальных установок является Mosquitto. Это легковесный, надежный и очень производительный брокер с открытым исходным кодом.
Для его установки на контроллер HI (или любую другую систему на базе Debian) достаточно выполнить одну команду:
sudo apt-get update
sudo apt-get install mosquitto mosquitto-clients -y
Пакет `mosquitto-clients` содержит полезные утилиты командной строки (`mosquitto_pub` и `mosquitto_sub`) для отладки и тестирования.
После установки брокер автоматически запустится как системный сервис и будет готов принимать подключения на стандартном порту `1883`.
Основы безопасности: аутентификация и контроль доступа
Запускать брокер в открытом виде, без пароля — крайне плохая практика даже в локальной сети. Любое устройство в сети сможет отправлять ложные команды и нарушать работу системы.
Сначала необходимо создать файл, в котором будут храниться имена пользователей и их зашифрованные пароли. Создадим пользователя `admin`:
sudo mosquitto_passwd -c /etc/mosquitto/passwd admin
Система дважды запросит пароль для нового пользователя.
Далее, нужно указать брокеру использовать этот файл для аутентификации. Создадим или отредактируем файл конфигурации `/etc/mosquitto/conf.d/default.conf` и добавим в него строки:
# Запретить анонимные подключения
allow_anonymous false
# Указать путь к файлу с паролями
password_file /etc/mosquitto/passwd
После сохранения файла конфигурации перезапустите сервис Mosquitto:
sudo systemctl restart mosquitto
Теперь для подключения к вашему брокеру любому клиенту потребуется указать логин `admin` и заданный вами пароль. Более сложные системы могут использовать списки контроля доступа (ACL, Access Control Lists), которые позволяют детально настроить, в какие топики каждый конкретный пользователь может публиковать (`write`) или из каких подписываться (`read`).
---
Топики, полезная нагрузка и QoS
Три фундаментальных понятия, определяющих, что, куда и насколько надежно передается в MQTT — это топик, полезная нагрузка и уровень качества обслуживания.
Структура и иерархия топиков
Топик — это не просто имя, это иерархический путь, похожий на структуру папок в файловой системе. Уровни иерархии разделяются косой чертой (`/`). Грамотное проектирование иерархии топиков — залог создания масштабируемой и понятной системы.
Рекомендуемая структура для проектов на платформе HI: `project/location/device_class/device_id/control_or_sensor`.
| Уровень | Пример | Описание |
| ----------------- | --------------- | ----------------------------------------- |
| Проект/Объект | `office` | Глобальный идентификатор объекта |
| Расположение | `floor-1/room-101` | Физическое расположение устройства |
| Класс устройства | `light` | Тип устройства (свет, розетка, датчик) |
| ID устройства | `main` | Уникальный идентификатор в своем классе |
| Контрол/Сенсор | `state` | Конкретный параметр или команда |
Пример полного топика: `office/floor-1/room-101/light/main/state`. Для отправки команды управления используется суффикс `/set`, например: `office/floor-1/room-101/light/main/set`.
Использование спецсимволов (Wildcards)
Подписчики могут использовать два специальных символа (wildcards) для подписки сразу на несколько топиков:
- `+` (плюс): заменяет один уровень иерархии.
- `#` (решетка): заменяет один или несколько уровней иерархии в конце топика.
Полезная нагрузка (Payload) и JSON
Полезная нагрузка (payload) — это сами данные, которые передаются в сообщении. MQTT не накладывает никаких ограничений на формат этих данных, это могут быть просто строки (`"ON"`, `"OFF"`), числа (`23.5`) или бинарные данные.Однако, как мы уже установили в наших стандартах проектирования, для создания надежных систем необходимо придерживаться контракта сообщения. Стандартом де-факто для передачи структурированных данных в MQTT является формат JSON.
Неправильно: отправлять просто `23.5`.
Правильно: отправлять структурированный JSON-объект.
{
"value": 23.5,
"unit": "C",
"ts": 1678886400000,
"source": "temp-sensor-room101"
}
Такой подход позволяет передавать не только само значение, но и метаданные: единицы измерения, временную метку, источник. Это делает систему гораздо более информативной и простой в отладке.
Уровни качества обслуживания (QoS)
MQTT предоставляет три уровня качества обслуживания (Quality of Service, QoS), которые позволяют выбрать компромисс между надежностью доставки и накладными расходами.
| Уровень | Название | Описание | Применение |
| ------- | ------------------------ | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| QoS 0 | At most once (Не более одного раза) | Сообщение отправляется один раз, доставка не подтверждается. "Отправил и забыл". Самый быстрый, но ненадежный. | Периодические данные с датчиков (температура). |
| QoS 1 | At least once (Не менее одного раза) | Сообщение гарантированно будет доставлено, но может прийти несколько раз (дубликаты) в случае сбоев сети. | Команды управления (включить/выключить свет). |
| QoS 2 | Exactly once (Ровно один раз) | Сообщение гарантированно будет доставлено ровно один раз. Самый надежный, но и самый медленный, требует 4 рукопожатий. | Критически важные транзакции (списание средств).|
> ⚠️ Внимание: Использование QoS 2 гарантирует доставку ровно один раз, но создает значительную нагрузку на сеть и устройства. В 99% сценариев домашней и офисной автоматизации достаточно QoS 0 (для телеметрии) или QoS 1 (для команд).
---
Практика: интеграция MQTT в Node-RED
Контроллер HI с его средой Node-RED является идеальным инструментом для работы с MQTT. В палитре Node-RED по умолчанию есть узлы для взаимодействия с MQTT-брокером.
Обзор узлов `mqtt in` и `mqtt out`
- `mqtt in`: Узел-подписчик. Он подписывается на указанный топик на брокере и создает новое сообщение в потоке Node-RED каждый раз, когда приходит сообщение в этот топик.
- `mqtt out`: Узел-публикатор. Он принимает сообщение из потока и публикует его `msg.payload` в указанный `msg.topic` на брокере.
Настройка подключения к MQTT-брокеру
Оба узла используют общий узел конфигурации "MQTT-Broker".
* Server: IP-адрес или доменное имя вашего брокера (например, `localhost` или `192.168.1.10`).
* Port: `1883` (стандартный порт).
* Client ID: Оставьте пустым, Node-RED сгенерирует уникальный ID.
* Username: `admin` (или ваш логин).
* Password: Ваш пароль.
Создание потока для управления виртуальной лампой
Создадим два простых потока, чтобы продемонстрировать принцип работы.
Поток 1: Публикация командыЭтот поток будет имитировать отправку команды на включение/выключение света.
{
"command": "ON",
"brightness": 100
}
{
"command": "OFF"
}
// Устанавливаем топик для команды
msg.topic = "home/kitchen/light/main/set";
// Передаем в payload только команду
msg.payload = msg.payload.command;
return msg;
Этот поток будет слушать команды и выводить их в отладочную консоль.
* Server: Выберите ваш настроенный брокер.
* Topic: `home/kitchen/light/main/set`
* QoS: `1`
* Output: `a parsed JSON object` (если вы отправляете JSON, но в нашем примере мы отправляем строку `ON`/`OFF`, поэтому лучше оставить `a string`).
Теперь, развернув (Deploy) этот проект, при нажатии на первый `inject` узел, в консоль отладки придет сообщение `"ON"`. При нажатии на второй — `"OFF"`. Мы создали систему, где отправитель и получатель ничего не знают друг о друге, а общаются через посредника — MQTT-брокера.
---
Пример: MQTT как "клей" для разных протоколов (на примере стороннего оборудования)
Одна из самых мощных функций MQTT — это возможность служить универсальным слоем (шиной данных) для объединения систем, работающих на совершенно разных физических протоколах. Эту концепцию хорошо иллюстрирует контроллер с MQTT-шлюзом, например сторонний контроллер Wiren Board. В системе HI устройства, приложения и панель также связаны между собой по MQTT через брокер домашнего сервера.
Концепция протокольного шлюза
Представьте типичный сценарий автоматизации:
- Контроллер установлен в электрощите.
- К его порту RS-485 подключена шина с несколькими устройствами: счетчик электроэнергии (например, WB-MAP12E), модуль реле (WB-MR6C) и настенный датчик CO2 (WB-MSW3).
- Все эти устройства общаются по протоколу Modbus RTU, который мы рассматривали в уроке `COURSE-01-M04-L02`.
Вручную опрашивать каждое устройство и парсить его регистры в Node-RED — это трудоемкая задача. Вместо этого на таком контроллере работает специальный сервис-шлюз (у Wiren Board он называется `wb-mqtt-serial`).
Автоматическая публикация данных в MQTT
Задача сервиса `wb-mqtt-serial` очень проста:
Пример со счетчиком электроэнергии
Допустим, у нас есть счетчик WB-MAP12E с Modbus-адресом `1`. Сервис `wb-mqtt-serial` автоматически создаст для него в MQTT-брокере целое дерево топиков:
- `devices/wb-map12e_1/controls/U_L1`: здесь будет публиковаться текущее напряжение на Фазе 1 (например, `231.5`).
- `devices/wb-map12e_1/controls/I_L1`: здесь будет публиковаться ток на Фазе 1 (например, `1.2`).
- `devices/wb-map12e_1/controls/P_L1`: здесь будет публиковаться активная мощность на Фазе 1 (например, `270`).
Теперь, чтобы получить значение напряжения, нашему сценарию в Node-RED не нужно ничего знать о Modbus, адресах регистров, типах данных и портах RS-485. Ему достаточно подписаться с помощью узла `mqtt in` на топик `devices/wb-map12e_1/controls/U_L1`.
Точно так же, чтобы включить реле на модуле WB-MR6C, достаточно отправить значение `1` в топик `devices/wb-mr6_15/controls/K1/on`. Сервис `wb-mqtt-serial` поймает это сообщение и отправит нужную Modbus-команду на шину RS-485.
Таким образом, MQTT становится универсальным "языком" внутри контроллера. Любое устройство, подключенное по любому физическому протоколу (Modbus, CAN, 1-Wire), через соответствующий сервис-шлюз представляет свои данные и команды в едином формате — через MQTT-топики. Это и есть главный принцип построения гибких и масштабируемых систем автоматизации.
---
Итоги: MQTT — нервная система современного умного дома
В этом уроке мы совершили глубокое погружение в самый важный протокол для «Интернета вещей». MQTT — это не просто технология, это философия построения распределенных систем.
Давайте закрепим ключевые概念:
- Архитектура Pub/Sub с Клиентами и центральным Брокером обеспечивает слабую связанность и асинхронность компонентов системы.
- Топик — это иерархический адрес сообщения, а Полезная нагрузка (Payload), в идеале в формате JSON, несет сами данные.
- Качество обслуживания (QoS) позволяет выбрать баланс между скоростью и надежностью доставки.
- На контроллере HI связка Mosquitto (брокер) и Node-RED (логика) позволяет строить мощные и гибкие сценарии.
- MQTT выступает в роли универсального клея, объединяя устройства с разными физическими интерфейсами (Modbus, CAN) в единое информационное пространство.
Благодаря своей гибкости, масштабируемости и эффективности, MQTT по праву можно назвать цифровой нервной системой современного умного дома или офиса, по которой бегут все сигналы — от простого нажатия кнопки до сложных команд управления климатом.
Что дальше
Мы рассмотрели основы MQTT, но у протокола есть и более продвинутые функции, которые делают его еще мощнее:
- Флаг `retain`: Позволяет брокеру хранить последнее сообщение в топике и немедленно отправлять его новым подписчикам.
- Last Will and Testament (LWT): "Последняя воля и завещание" клиента — специальное сообщение, которое брокер опубликует, если клиент внезапно оборвет связь.
- Шифрование TLS: Обеспечение безопасности и конфиденциальности данных при передаче через публичные сети.
Эти механизмы мы рассмотрим в более продвинутых курсах, посвященных построению отказоустойчивых и безопасных систем. В следующем уроке нашего модуля мы перейдем к беспроводным протоколам ближнего радиуса действия.