#pragma once #include #include #include "ha.h" #include "bmp.h" #include "display.h" #define MQTT_HOST IPAddress(192, 168, 5, 11) #define MQTT_PORT 1883 namespace Mqtt { void publishInit(); void publishBmp280(); void connect(); void disconnect(); Task tReConnect(5 * TASK_MINUTE, TASK_FOREVER, connect, &ts); Task tPublishInit(TASK_IMMEDIATE, TASK_ONCE, publishInit, &ts); AsyncMqttClient client; const char* espClockTopic = "homeassistant/+/esp_clock/#"; void connect() { client.connect(); } void disconnect() { client.unsubscribe(espClockTopic); client.disconnect(); } uint16_t publish(const char* topic, const char* message) { return client.publish(topic, 0, true, message); } Ha::Sensor* sensors[] = { new Ha::TemperatureSensor{"Temperature", "temperature"}, new Ha::PressureSensor{"Pressure", "pressure"}, new Ha::AltitudeSensor{"Altitude", "altitude"} }; Ha::Command* ledMqtt = (new Ha::Switch{"Led", "led", [](const char* msg) { String{ "ON" }.equals(msg) ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH); }, []() { publish(ledMqtt->stateTopic, digitalRead(LED_BUILTIN) ? "OFF" : "ON"); } })->withStateTopic(); Ha::Command* brightnessMqtt = (new Ha::Brightness{ "Brightness", "brightness", [](const char* msg) { Display::Brightness::set(String{ msg }.toInt()); }, []() { char message[32]; sprintf(message, "%u", Display::Brightness::current); publish(brightnessMqtt->stateTopic, message); } })->withStateTopic(); Ha::Command* hourFormatMqtt = (new Ha::Switch{"Format 24h", "format_24h", [](const char* msg) { String{ "ON" }.equals(msg) ? Display::changeHourFormat24(true) : Display::changeHourFormat24(false); }, []() { publish(hourFormatMqtt->stateTopic, Display::hourFormat24 ? "ON" : "OFF"); } })->withStateTopic(); Ha::Command* switches[] = { new Ha::Button{"Restart", "restart", [](const char* msg) { if (String { "PRESS" }.equals(msg)) ESP.restart(); } }, ledMqtt, hourFormatMqtt, brightnessMqtt }; void publishComponentConfig(Ha::Component& component) { StaticJsonDocument jsonDoc; component.buildConfig(jsonDoc); char message[JSON_SIZE]; serializeJson(jsonDoc, message); publish(component.configTopic, message); } void publishInit() { for (Ha::Component* cmp : sensors) { publishComponentConfig(*cmp); } for (Ha::Component* cmp : switches) { publishComponentConfig(*cmp); } ts.deleteTask(tPublishInit); } void publishBmp280() { StaticJsonDocument<255> jsonDoc; jsonDoc["temperature"] = Bmp::data.temp; jsonDoc["pressure"] = Bmp::data.pressure; jsonDoc["altitude"] = Bmp::data.altitude; char message[255]; serializeJson(jsonDoc, message); publish(Ha::Sensor::stateTopic, message); } void onMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { char msg[len + 1]; memcpy(msg, payload, len); msg[len] = 0; for (Ha::Command* cmd : switches) { if (String{ cmd->commandTopic }.equals(topic)) { cmd->f(msg); return; } } } void setup() { Display::Brightness::onChanged(brightnessMqtt->publishState); Display::onHourFormatChanged(hourFormatMqtt->publishState); client.onConnect([](bool sessionPresent) { tPublishInit.enable(); client.subscribe(espClockTopic, 0); tReConnect.disable(); Serial.println("Connected to MQTT"); }); client.onDisconnect([](AsyncMqttClientDisconnectReason reason) { tReConnect.enableDelayed(); Serial.println("Disconnected from MQTT"); }); client.onMessage(onMessage); client.setServer(MQTT_HOST, MQTT_PORT); Serial.println("Connecting to MQTT..."); } }