MQTT в Home Assistant: broker, topics, retained, QoS и почему устройства иногда «залипают»
MQTT часто используют для связи Home Assistant, Wiren Board, Node-RED, ESPHome и самодельных устройств. Но проблемы обычно начинаются не на уровне «подключилось или нет», а позже: старое retained-состояние возвращается после перезапуска, availability показывает неверный online, несколько устройств публикуют в одну тему, а высокий QoS применяют там, где он не нужен.
Что такое MQTT простыми словами
MQTT — лёгкий publish/subscribe протокол обмена сообщениями. Устройства не обязаны соединяться напрямую друг с другом. Они подключаются к broker и либо публикуют сообщения в topics, либо подписываются на них.
Например, счётчик публикует текущую мощность в topic house/power/total, а Home Assistant подписывается на него. При этом тот же topic одновременно может читать Node-RED, Grafana-bridge или другой контроллер.
Зачем нужен MQTT broker
Broker — центральная точка MQTT-обмена. Он принимает сообщения от publishers и доставляет их всем подходящим subscribers.
В домашней автоматизации broker часто выполняет несколько задач:
- связывает Home Assistant и внешние контроллеры;
- передаёт телеметрию датчиков и счётчиков;
- доставляет команды исполнительным устройствам;
- хранит retained messages;
- отслеживает соединения клиентов;
- реализует ACL и аутентификацию.
Один из самых распространённых broker — Eclipse Mosquitto. В Home Assistant OS его часто разворачивают как add-on, но broker может работать и на отдельном Linux-сервере, NAS или другом постоянно включённом устройстве.
Topics: как MQTT понимает, кому отправлять данные
Topic — строковый путь, по которому публикуется сообщение. Обычно структуру строят иерархически через символ /.
house/kitchen/temperature
house/kitchen/humidity
house/boiler/status
house/power/total
house/gate/state
Подписчик может слушать конкретный topic или использовать wildcard.
| Подписка | Что она получит |
|---|---|
house/kitchen/temperature | Только температуру кухни |
house/kitchen/+ | Все значения одним уровнем ниже kitchen |
house/# | Все topics внутри ветки house |
Что такое retained message и почему оно может «оживлять» старое состояние
Если publisher отправляет сообщение с флагом RETAIN, broker сохраняет последнее retained-сообщение для этой topic. Когда новый subscriber подпишется позже, broker сразу отправит ему сохранённое значение.
Это полезно для текущего состояния, но опасно для команд и кратковременных событий.
Где retained обычно полезен
- последнее известное состояние устройства;
- статическая конфигурация;
- MQTT Discovery messages;
- некоторые availability/status topics при правильной логике.
Где retained часто вреден
- команда «открыть ворота»;
- импульс «перезагрузить»;
- одноразовое событие кнопки;
- триггер сценария.
gate/open была опубликована с retain. После переподключения новый subscriber может получить старую команду снова. Для command topics retain обычно должен быть выключен, если протокол устройства явно не требует обратного.
Как удалить retained message
По MQTT 5 retained-сообщение удаляется публикацией сообщения с нулевой длиной payload в ту же topic с установленным RETAIN.
QoS 0, QoS 1 и QoS 2: какой выбрать
| QoS | Гарантия доставки | Практический сценарий |
|---|---|---|
| 0 | At most once | Частая телеметрия, где потеря одного значения некритична |
| 1 | At least once | Состояния и команды, где важнее доставка, чем возможный дубль |
| 2 | Exactly once на уровне протокола | Редкие специальные случаи; выше накладные расходы |
QoS 0
Сообщение отправляется без подтверждения доставки. Это самый лёгкий режим. Для температуры, мощности или RSSI, публикуемых каждые несколько секунд, потеря одного пакета обычно незаметна.
QoS 1
Broker/клиент подтверждает доставку. Сообщение может быть доставлено повторно, поэтому обработчик должен по возможности быть идемпотентным.
QoS 2
Использует более сложный четырёхшаговый обмен для исключения повторной доставки на уровне MQTT. В домашней автоматизации QoS 2 нужен редко.
LWT: как Home Assistant понимает, что устройство действительно offline
Last Will and Testament — сообщение, которое клиент заранее передаёт broker при подключении. Если соединение оборвётся некорректно, broker публикует Will Message за клиента.
Обычно используют отдельную availability topic:
device/boiler/availability = online
device/boiler/availability = offline
При штатном подключении устройство публикует online, а Will Message заранее настроено как offline.
Как MQTT интегрируется с Home Assistant
В Home Assistant есть официальная MQTT integration. После подключения к broker она может создавать MQTT sensors, switches, lights, binary sensors, climate entities и другие типы объектов.
У сущности обычно есть отдельные topics:
state_topic: house/pump/state
command_topic: house/pump/set
availability_topic: house/pump/availability
Такое разделение важно: state topic сообщает фактическое состояние, command topic принимает желаемое действие, availability topic показывает доступность.
MQTT Discovery: автоматическое создание сущностей
Home Assistant умеет автоматически создавать MQTT entities по специальным discovery topics. Устройство публикует конфигурацию, а Home Assistant создаёт сущность без ручного YAML.
homeassistant/sensor/boiler_temp/config
Discovery особенно удобно для устройств, которые должны автоматически добавляться после установки или перезапуска.
ESPHome: Native API или MQTT
ESPHome поддерживает оба подхода. Для обычного проекта Home Assistant чаще проще Native API: он обеспечивает прямую интеграцию, автоматическое появление сущностей и не требует отдельного broker.
| Сценарий | Что логичнее |
|---|---|
| ESPHome используется только с Home Assistant | Native API |
| Одни данные нужны нескольким системам | MQTT |
| Есть уже развитая MQTT-инфраструктура | MQTT |
| Нужно минимизировать число сервисов | Native API |
| Устройство должно жить независимо от HA | Локальная ESPHome automation + при необходимости MQTT |
MQTT не делает ESPHome автоматически надёжнее. Он добавляет ещё один компонент — broker, который тоже должен работать и быть доступен.
Как строить topics, чтобы система не превратилась в хаос
Для домашней системы удобно придерживаться стабильной структуры:
house/{zone}/{device}/{parameter}
house/kitchen/climate/temperature
house/boiler/controller/state
house/power/meter1/voltage_l1
house/gate/controller/availability
Полезные правила:
- не включать IP-адрес в topic, если он может измениться;
- использовать стабильный device ID;
- отделять state от command;
- отделять availability от обычного состояния;
- не смешивать единицы измерения внутри одной topic;
- не менять структуру topics без необходимости на работающем объекте;
- документировать topics для инженерных устройств.
Как защитить MQTT broker
Broker получает доступ ко многим состояниям и командам дома, поэтому его нельзя считать безобидным внутренним сервисом.
- не разрешайте anonymous access без явной необходимости;
- используйте отдельные учётные записи для разных сервисов;
- ограничивайте ACL по topics;
- не публикуйте порт broker напрямую в интернет;
- для удалённых площадок используйте VPN или защищённый канал;
- применяйте TLS там, где трафик выходит за пределы доверенного сегмента;
- не храните пароль broker открытым в публичных конфигурациях;
- обновляйте Mosquitto и клиентские библиотеки.
#, компрометация одной учётной записи может дать возможность отправлять команды множеству устройств. ACL должен соответствовать реальной роли клиента.
Как диагностировать MQTT, если Home Assistant показывает странное состояние
- 1
Подписаться на нужную ветку
Посмотреть реальные сообщения через MQTT Explorer или
mosquitto_sub. - 2
Проверить retained
Если значение появляется мгновенно после subscribe, выяснить, не retained ли оно.
- 3
Проверить state и command topics
Убедиться, что они не перепутаны.
- 4
Проверить availability
Посмотреть, кто публикует online/offline и есть ли LWT.
- 5
Проверить client ID
Два клиента с одинаковым Client Identifier могут выбивать друг друга из broker.
- 6
Проверить ACL
Клиент может подключаться, но не иметь права читать или публиковать нужную topic.
- 7
Проверить QoS и reconnect
Особенно если сообщения дублируются после потери связи.
mosquitto_sub -h 192.168.1.10 \
-u ha_debug \
-P 'PASSWORD' \
-v \
-t 'house/#'
Типичные ошибки MQTT в умном доме
Retain на командах
Старая команда может неожиданно прийти новому subscriber после подключения.
Один topic для state и command
Становится непонятно, где желаемое состояние, а где реальное.
QoS 2 везде
Усложняет обмен без реальной пользы для большинства домашних датчиков.
Нет LWT
Home Assistant продолжает считать устройство online после аварийного обрыва связи.
Одинаковый Client ID
Клиенты периодически отключают друг друга от broker.
Wildcard ACL
Одному устройству выдаются права на весь broker, хотя ему нужны 2–3 topics.
Broker без UPS
Кратковременное отключение питания рушит сразу все MQTT-зависимые интеграции.
Topics без документации
Через год непонятно, кто публикует значение и что сломается после переименования.
Частые вопросы
Нужен ли MQTT для Home Assistant?
Нет. Home Assistant имеет множество прямых интеграций. MQTT нужен только для устройств и систем, которые используют его или когда он удобен как общий транспорт между несколькими платформами.
Что такое retained message?
Последнее сообщение, которое broker сохраняет для topic и сразу отдаёт новым подписчикам. Полезно для состояния и discovery, но опасно для одноразовых команд.
Какой QoS использовать в умном доме?
Чаще всего QoS 0 для частой телеметрии и QoS 1 для важных состояний/команд. QoS 2 нужен редко.
Что такое LWT?
Last Will and Testament — заранее заданное сообщение, которое broker публикует, если клиент неожиданно теряет соединение. Обычно используется для offline availability.
Почему устройство в Home Assistant online, хотя оно выключено?
Частые причины: нет корректного LWT, availability topic не настроена или старое retained online осталось на broker.
Почему после перезапуска приходит старое значение?
Скорее всего, это retained message. Broker хранит его независимо от текущей MQTT-сессии и отправляет новому subscriber после подписки.
MQTT безопасен?
Может быть безопасным при нормальной аутентификации, ACL, TLS/VPN и отсутствии прямой публикации broker в интернет. Сам по себе протокол не компенсирует плохую сетевую конфигурацию.
Вывод
MQTT хорошо подходит для локальной автоматизации, когда нужно связать несколько независимых систем через простой publish/subscribe механизм. Но надёжность определяется не самим фактом использования Mosquitto, а дисциплиной topics, retained, QoS и availability.
Для большинства домашних проектов достаточно QoS 0/1, отдельных state и command topics, LWT для offline-состояния и минимального количества retained messages. Broker должен быть защищён, резервироваться по питанию и иметь понятные ACL.
Если MQTT используется только потому, что «так принято», а устройство уже имеет хорошую прямую интеграцию Home Assistant, дополнительный broker может быть лишним. Но для Wiren Board, Node-RED, внешних контроллеров и многосистемной архитектуры MQTT остаётся одним из самых полезных локальных интерфейсов.

