# Взаимодействие через MQTT
Помимо приложения, с устройством можно взаимодействовать через MQTT, в том числе интегрировать в систему умного дома:
- [WQTT](https://www.wqtt.ru/) - MQTT брокер + панель управления + навык для Алисы
- [Домовёнок Кузя](https://alexstar.ru/) - панель управления + навык для Алисы
- И некоторые другие

## Топики и обозначения
Посмотреть все топики устройства можно во вкладке **Инфо** приложения. Здесь используются обозначения:
- `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-топик:
```cpp
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)`.

## Пример
```cpp
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. По нажатию на кнопку отправляется фиксированная температура, в качестве примера.