146 lines
5.0 KiB
C++
146 lines
5.0 KiB
C++
#include <queue>
|
|
#include <AsyncMqttClient.h>
|
|
#include <ArduinoJson.h>
|
|
#include "ha.h"
|
|
|
|
#define MQTT_HOST IPAddress(192, 168, 5, 11)
|
|
#define MQTT_PORT 1883
|
|
|
|
namespace Mqtt {
|
|
|
|
void publishConfig();
|
|
void publishCommand();
|
|
void publishBmp280();
|
|
void connect();
|
|
void disconnect();
|
|
Task tReConnect(5 * TASK_MINUTE, TASK_FOREVER, connect, &ts);
|
|
Task tPublishConfig(TASK_IMMEDIATE, TASK_ONCE, publishConfig, &ts);
|
|
Task tPublishBmp(5 * TASK_MINUTE, TASK_FOREVER, publishBmp280, &ts);
|
|
Task tPublishCommand(TASK_SECOND, TASK_FOREVER, publishCommand, &ts);
|
|
|
|
AsyncMqttClient client;
|
|
|
|
struct {
|
|
const char* topic = "esp_clock/sensor/ir/value";
|
|
std::queue<uint8_t> queue;
|
|
uint8_t getCurrent() {
|
|
return queue.empty() ? 0 : queue.front();
|
|
}
|
|
void push(uint8_t el) {
|
|
if (client.connected()) queue.push(el);
|
|
}
|
|
void pop() {
|
|
queue.pop();
|
|
}
|
|
} commands;
|
|
|
|
const char* bmpTopic = "homeassistant/sensor/esp_clock/state";
|
|
const char* restartTopic = "homeassistant/button/esp_clock/restart";
|
|
const char* ledTopic = "homeassistant/switch/esp_clock/led/set";
|
|
const char* hourFormatTopic = "homeassistant/switch/esp_clock/hour_format/set";
|
|
const char* espClockTopic = "homeassistant/+/esp_clock/#";
|
|
|
|
void connect() {
|
|
client.connect();
|
|
}
|
|
|
|
void disconnect() {
|
|
client.unsubscribe(espClockTopic);
|
|
client.disconnect();
|
|
}
|
|
|
|
Ha::Component components[] = {
|
|
Ha::TemperatureSensor{"Living room Temperature", "living_room_temperature", "homeassistant/sensor/esp_clock/temperature/config", bmpTopic},
|
|
Ha::PressureSensor{"Living room Pressure", "living_room_pressure", "homeassistant/sensor/esp_clock/pressure/config", bmpTopic},
|
|
Ha::AltitudeSensor{"Living room Altitude", "living_room_altitude", "homeassistant/sensor/esp_clock/altitude/config", bmpTopic},
|
|
Ha::Command{"Restart", "esp_clock_restart", "homeassistant/button/esp_clock/restart/config", restartTopic},
|
|
Ha::Command{"ESP Clock Led", "esp_clock_led", "homeassistant/switch/esp_clock/led/config", ledTopic},
|
|
Ha::Command{"ESP Clock Format 24h", "esp_clock_format_24h", "homeassistant/switch/esp_clock/hour_format/config", hourFormatTopic}
|
|
};
|
|
|
|
void publishComponentConfig(Ha::Component& component) {
|
|
StaticJsonDocument<JSON_SIZE> jsonDoc;
|
|
component.buildConfig(jsonDoc);
|
|
|
|
char message[JSON_SIZE];
|
|
serializeJson(jsonDoc, message);
|
|
|
|
client.publish(component.configTopic, 0, true, message);
|
|
}
|
|
|
|
void publishConfig() {
|
|
for (Ha::Component cmp : components) {
|
|
publishComponentConfig(cmp);
|
|
}
|
|
ts.deleteTask(tPublishConfig);
|
|
}
|
|
|
|
void publishBmp280() {
|
|
Bmp::data.readAll();
|
|
StaticJsonDocument<255> jsonDoc;
|
|
jsonDoc["temperature"] = Bmp::data.temp;
|
|
jsonDoc["pressure"] = Bmp::data.pressure;
|
|
jsonDoc["altitude"] = Bmp::data.altitude;
|
|
char message[255];
|
|
serializeJson(jsonDoc, message);
|
|
client.publish(bmpTopic, 0, true, message);
|
|
}
|
|
|
|
void publishCommand() {
|
|
if (uint8_t cmd = commands.getCurrent()) {
|
|
char message[32];
|
|
sprintf(message, "%X", cmd);
|
|
if (client.publish(commands.topic, 0, true, message) != 0) {
|
|
Serial.print(cmd, HEX);
|
|
Serial.println();
|
|
commands.queue.pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
if (String{ restartTopic }.equals(topic) && String { "PRESS" }.equals(msg)) {
|
|
ESP.restart();
|
|
}
|
|
if (String{ ledTopic }.equals(topic)) {
|
|
if (String{ "ON" }.equals(msg)) {
|
|
digitalWrite(LED_BUILTIN, LOW);
|
|
} else {
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
}
|
|
}
|
|
if (String{ hourFormatTopic }.equals(topic)) {
|
|
if (String{ "ON" }.equals(msg)) {
|
|
Display::hourFormat24 = true;
|
|
Display::drawTime();
|
|
} else {
|
|
Display::hourFormat24 = false;
|
|
Display::drawTime();
|
|
}
|
|
}
|
|
}
|
|
|
|
void setup() {
|
|
client.onConnect([](bool sessionPresent) {
|
|
tPublishConfig.enable();
|
|
tPublishBmp.enableIfNot();
|
|
tPublishCommand.enableDelayed();
|
|
client.subscribe(espClockTopic, 0);
|
|
tReConnect.disable();
|
|
Serial.println("Connected to MQTT");
|
|
});
|
|
client.onDisconnect([](AsyncMqttClientDisconnectReason reason) {
|
|
tReConnect.enableDelayed();
|
|
tPublishCommand.disable();
|
|
tPublishBmp.disable();
|
|
Serial.println("Disconnected from MQTT");
|
|
});
|
|
client.onMessage(onMessage);
|
|
client.setServer(MQTT_HOST, MQTT_PORT);
|
|
Serial.println("Connecting to MQTT...");
|
|
}
|
|
}
|