154 lines
4.8 KiB
C++
154 lines
4.8 KiB
C++
#pragma once
|
|
|
|
#include <AsyncMqttClient.h>
|
|
#include <ArduinoJson.h>
|
|
#include "ha.h"
|
|
#include "bme.h"
|
|
#include "display.h"
|
|
|
|
#define MQTT_HOST IPAddress(192, 168, 5, 11)
|
|
#define MQTT_PORT 1883
|
|
|
|
namespace Mqtt {
|
|
|
|
void publishInit();
|
|
void publishBme280();
|
|
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::HumiditySensor{"Humidity", "humidity"},
|
|
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();
|
|
}
|
|
},
|
|
new Ha::Button{"Display sensor data", "display_sensor_data",
|
|
[](const char* msg) {
|
|
if (String { "PRESS" }.equals(msg) && !Display::tDisplaySensor.isEnabled()) {
|
|
Bme::data.readAll();
|
|
Display::tDisplaySensor.restart();
|
|
};
|
|
}
|
|
},
|
|
ledMqtt,
|
|
hourFormatMqtt,
|
|
brightnessMqtt
|
|
};
|
|
|
|
void publishComponentConfig(Ha::Component& component) {
|
|
StaticJsonDocument<JSON_SIZE> 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 publishBme280() {
|
|
StaticJsonDocument<255> jsonDoc;
|
|
jsonDoc["temperature"] = Bme::data.temp;
|
|
jsonDoc["humidity"] = Bme::data.humidity;
|
|
jsonDoc["pressure"] = Bme::data.pressure;
|
|
jsonDoc["altitude"] = Bme::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...");
|
|
}
|
|
}
|