Skip to content

MQTT (Phase Broker)

Альтернатива HTTP-heartbeat'у. Плата подписывается на MQTT-топик и получает команды push'ем с малой задержкой (десятки мс vs 15 сек у heartbeat'а).

Зачем

Задача HTTP heartbeat MQTT
Toggle реле с Алисы 0–15 сек задержка < 1 сек
Live-обновления состояния в UI 0–15 сек мгновенно
Управление с Home Assistant через cloud API напрямую к плате
Простой self-hosted клиент нужно писать REST-клиент стандартный MQTT-client

Минусы MQTT: ещё одно открытое соединение, TLS-handshake, keep-alive. На ESP8266 с активным mesh может упереться в RAM.

Архитектура

плата ─── mqtts://emqx.cloud.kavlev.ru:8883 ─── EMQX broker
                                                  ├── topic: kavlev/<project>/<uuid>/cmd  ← cloud команды
                                                  ├── topic: kavlev/<project>/<uuid>/state ← плата шлёт
                                                  ├── topic: kavlev/<project>/<uuid>/ack   ← ack команд
                                                  └── LWT:   kavlev/<project>/<uuid>/lwt   ← disconnected

Phase Broker — наше имя для EMQX-инстанса в облаке. EMQX 5.x, MQTT 5.0, TLS обязательный.

Шаг 1. Включить в облаке

Интеграции проектаMQTT → Включить.

Получите:

Параметр Пример
Broker host emqx.cloud.kavlev.ru
Broker port 8883 (mqtts)
TLS Required

Также автоматически создаются credentials для каждой платы проекта:

Параметр Что
Username device_<uuid>
Password Случайные 32 байта (видны один раз в UI)
ACL publish/subscribe только на kavlev/<project>/<uuid>/*

Шаг 2. Прописать на плате

В настройках MQTT платы (раздел появится когда MQTT включён в проекте):

Поле Значение
Broker URL mqtts://emqx.cloud.kavlev.ru:8883
Username device_<ваш_uuid>
Password Тот случайный, который выдало облако
CA cert Загрузить опционально (или использовать встроенный bundle)

После сохранения плата:

  1. Открывает TLS-соединение с брокером.
  2. Подписывается на kavlev/<project>/<uuid>/cmd.
  3. Публикует current state в kavlev/<project>/<uuid>/state (retained).
  4. Устанавливает LWT disconnected на kavlev/<project>/<uuid>/lwt (retained).

С этого момента команды идут push'ем. HTTP-heartbeat продолжает работать как fallback (на случай если MQTT отвалился).

Топики

Топик Direction Payload Retained
kavlev/<p>/<d>/state plate → cloud {devices: [...], tasks: [...], uptime_sec, fw_version} yes
kavlev/<p>/<d>/cmd cloud → plate {id: 44, type: "set_relay", payload: {...}, cmd_id: "xyz"} no
kavlev/<p>/<d>/ack plate → cloud {cmd_id: "xyz", id: 44, status: "applied"} no
kavlev/<p>/<d>/lwt broker → cloud disconnected yes

cmd_id — UUID команды, плата использует для дедупликации: если получит ту же команду повторно (например, после reconnect'а) — выполнит один раз.

Self-hosted клиент

Если хотите подключиться к плате напрямую (например, из Home Assistant):

Создать «virtual device» в проекте

В интеграцияхMQTT → + Создать клиент. Введите имя (home-assistant, например).

Получите credentials с ACL на kavlev/<project>/+/state (read-only на все state-топики проекта) и (опционально) kavlev/<project>/+/cmd (write).

Подключиться

# Home Assistant configuration.yaml
mqtt:
  broker: emqx.cloud.kavlev.ru
  port: 8883
  username: ha_client_xyz
  password: !secret kavlev_mqtt_password
  certificate: auto

sensor:
  - name: "Temperature kitchen"
    state_topic: "kavlev/<project>/<plate_uuid>/state"
    value_template: "{{ value_json.devices | selectattr('name', 'equalto', 'kitchen-temp') | map(attribute='value') | first }}"
    unit_of_measurement: "°C"

switch:
  - name: "Light kitchen"
    state_topic: "kavlev/<project>/<plate_uuid>/state"
    command_topic: "kavlev/<project>/<plate_uuid>/cmd"
    value_template: "{{ value_json.devices | selectattr('id', 'equalto', 5) | map(attribute='state') | first | string | upper }}"
    payload_on: '{"type":"set_relay","payload":{"device_id":5,"state":true},"cmd_id":"{{ as_timestamp(now()) }}"}'
    payload_off: '{"type":"set_relay","payload":{"device_id":5,"state":false},"cmd_id":"{{ as_timestamp(now()) }}"}'

Безопасность

  • TLS обязательный. Plain mqtt://1883 отключён на брокере.
  • Per-device credentials. Платы получают разные username/password. Утечка одного не компрометирует остальные.
  • ACL ограничивает каждую плату только своими топиками. Плата A не может публиковать в топик платы B.
  • Cloud-side aerobic checks. Каждое сообщение в /cmd-топике подписывается HMAC-SHA256 в payload — плата проверит подпись перед выполнением (защита если cloud-side скомпрометирован).

Что делать если MQTT отвалился

  • Плата продолжает работать через HTTP-heartbeat (fallback).
  • Через ~30 секунд плата попробует переподключиться к брокеру.
  • В RAM-логе будут видны MQTT-ошибки (TLS, auth, и т.д.).
  • В облаке статус платы — mqtt offline, http active.

Если MQTT не критичен — можно временно выключить его в настройках платы → плата перестанет тратить ресурсы на reconnect-попытки.

Лимиты

Параметр Значение
Max connections per project 50 (платы + клиенты)
Max msg size 256 КБ
QoS supported 0, 1 (не 2)
Retained on state topic да, последний state-снапшот
Subscriptions per plate 1 (только /cmd)