Skip to content

7. Умный дом, MQTT

AlexGyver edited this page Feb 25, 2024 · 1 revision

Взаимодействие через MQTT

Помимо приложения, с устройством можно взаимодействовать через MQTT, в том числе интегрировать в систему умного дома:

  • WQTT - MQTT брокер + панель управления + навык для Алисы
  • Домовёнок Кузя - панель управления + навык для Алисы
  • И некоторые другие

Топики и обозначения

Посмотреть все топики устройства можно во вкладке Инфо приложения. Здесь используются обозначения:

  • net - имя сети
  • device_id - id устройства. Генерируется библиотекой (или задаётся вручную)
  • client_id - id клиента. В приложении генерируется автоматически, а для запросов через MQTT его нужно указать вручную. Можно просто написать mqtt. Можно придумать что то более сложное для безопасности, если в программе идёт ручная обработка запросов Request и проверка соответствия ID клиента.
  • name - имя виджета

Топики для отправки

Установка значения

Отправить новое значение (в payload) для виджета можно на топик:

net/device_id/client_id/set/name

Запрос чтения

Для запроса значения нужно отправить пустое сообщение на топик:

net/device_id/client_id/read/name

Получив это сообщение, устройство ответит текущим значением на get-топик, значение виджета будет прочитано в билдере.

Топики для подписки

Получение значений (get-топик)

Для получения значений с виджета нужно подписаться на топик:

net/hub/device_id/get/name

Получение состояния

Для получения состояний устройства (включено/выключено) нужно подписаться на топик:

net/hub/device_id/status

Устройство отправит online при выходе на связь и offline при потере.

Отправка с устройства

Напрямую

В библиотеке есть метод sendGet(), отправляет значение указанного имени на get-топик:

sendGet(AnyText name, AnyValue value);
sendGet(AnyText name, double value, uint8_t dec);

Из билдера

Если нужно отправить значение с виджета - можно использовать sendGet(AnyText name). Функция вызовет билдер, прочитает значение с виджета и отправит на get-топик. Можно передать несколько имён виджетов списком через ;.

Также есть "невидимый" виджет, который нужен только для привязки переменной к имени виджета: он не отображается в ПУ, но может отправлять и получать значения по MQTT.

Авто get

Можно автоматически отправлять новое состояние на get-топик при изменении из приложения или MQTT set - sendGetAuto(bool state). По умолчанию функция отключена.

Состояние

Для отправки состояния вручную нужно вызвать sendStatus(bool state).

Пример

uint8_t bright;
float temp;

void build(gh::Builder& b) {
    // реальный виджет
    if (b.Slider_("bright", &bright).click()) {
        Serial.print("bright set to: ");
        Serial.println(b.build.value);
    }

    // dummy виджет температуры
    b.Dummy_("temp", &temp);

    // по нажатию на кнопку отправить температуру в mqtt
    if (b.Button().click()) hub.sendGet("temp", 123.45, 2);
}

void setup() {
    // ..........
    hub.sendGetAuto(true);  // для отправки в mqtt при действиях с приложения
}

void loop() {
    hub.tick();

    // раз в 5 секунд отправлять значение виджета temp
    static gh::Timer tmr(5000);
    if (tmr) {
        // задать случайное значение
        temp = random(100) / 10.0;

        // отправить из билдера
        hub.sendGet("temp");
    }
}

Например в wqtt добавляю новое устройство Лампочка.

Добавляю Органы управления, Яркость:

  • Топик управления: MyDevices/cb5bf63a/mqtt/set/bright
  • Топик состояния: MyDevices/hub/cb5bf63a/get/bright

Добавляю Датчик, Температура:

  • Топик: MyDevices/hub/cb5bf63a/get/temp

Настройки LWT:

  • LWT Topic: MyDevices/hub/cb5bf63a/status
  • LWT Online Message: online

Теперь установленная яркость прилетает в bright, ползунок яркости в приложении GyverHub и в wqtt двигаются синхронно. Каждые 5 секунд отправляется случайная температура из билдера dummy. По нажатию на кнопку отправляется фиксированная температура, в качестве примера.