Add HA MQTT

This commit is contained in:
T
2025-09-11 19:29:08 +02:00
parent f0c9056cdc
commit 82d7ec6a09
2 changed files with 142 additions and 9 deletions

View File

@@ -2,11 +2,38 @@
#include <Ethernet.h>
#include <SPI.h>
#include <TimerOne.h>
#include <PubSubClient.h>
// ---------------- MQTT Settings ------------------
const char *mqtt_server = "mqtt.chaospott.de"; // <<< anpassen!
const int mqtt_port = 1883;
const char *mqtt_client = "fooclock";
// Eindeutige ID für die Uhr in Home Assistant
const char *device_id = "fooclock_01";
// Topics für Home Assistant
const char *mqtt_command_topic = "fooclock/display/set"; // Topic zum Senden von Befehlen (ON/OFF)
const char *mqtt_state_topic = "fooclock/display/state"; // Topic zum Melden des Status (ON/OFF)
const char *mqtt_discovery_topic = "homeassistant/switch/fooclock/display/config"; // HA Auto-Discovery Topic
EthernetClient ethClient;
PubSubClient client(ethClient);
bool displayEnabled = true; // Steuerflag für Anzeige
// Forward declaration der neuen Funktionen
void publishState();
void publishDiscoveryMessage();
// -------------------------------------------------
#define _A 0
#define _B 1
#define _C 2
#define _D 3
#define _E 4
#define _F 5
#define _G 6
#define _H 7
#define _I 8
@@ -28,11 +55,11 @@
#define _Y 24
#define _Z 25
#define UP 1
#define DOWN 2
#define UP 1
#define DOWN 2
#define light_lvl_standard 60
#define light_lvl_risen 255
#define light_lvl_standard 60
#define light_lvl_risen 255
// ---------------------------------- Definition of Global Variables -------------------------- //
@@ -58,9 +85,9 @@ bool second_changed = false;
bool init_done = false;
bool transition_active = false;
bool swipe_active = false;
bool shrink_active = false; // Maybe we should move them to a single variable and set or unset bits inside the variable
bool shrink_active = false;
int cur_update = 0;
unsigned int shift_state = 0;
int shift_state = 0;
int update_counter = 0;
int spinner_pos = 0;
int animation = 0;
@@ -143,6 +170,92 @@ int today[7] = {
184, 220, 200, 200, 240, 0, 0 // Display "Hello"
};
// ---------------- MQTT Callback ------------------
void mqttCallback(char *topic, byte *payload, unsigned int length) {
payload[length] = '\0'; // String terminieren
String message = String((char *) payload);
Serial.print("Nachricht empfangen [");
Serial.print(topic);
Serial.print("] ");
Serial.println(message);
if (String(topic) == mqtt_command_topic) {
if (message == "ON") {
displayEnabled = true;
Serial.println("MQTT: Display eingeschaltet");
} else if (message == "OFF") {
displayEnabled = false;
Serial.println("MQTT: Display ausgeschaltet");
}
// Sende den neuen Status sofort zurück
publishState();
}
}
// ---------------- MQTT Publish State ------------------
void publishState() {
if (displayEnabled) {
client.publish(mqtt_state_topic, "ON", true); // true = retain message
} else {
client.publish(mqtt_state_topic, "OFF", true); // true = retain message
}
}
// ---------------- MQTT Publish Home Assistant Discovery Message ------------------
void publishDiscoveryMessage() {
// Use a fixed-size buffer to create the JSON payload. This is much more
// memory-efficient than using the Arduino String class for concatenation.
char discoveryPayload[400];
// Create the JSON payload using snprintf to prevent buffer overflows
snprintf(discoveryPayload, sizeof(discoveryPayload),
"{"
"\"name\":\"FooClock Display\","
"\"unique_id\":\"%s_display\","
"\"cmd_t\":\"%s\","
"\"stat_t\":\"%s\","
"\"pl_on\":\"ON\","
"\"pl_off\":\"OFF\","
"\"icon\":\"mdi:clock-digital\","
"\"device\":{"
"\"identifiers\":[\"%s\"],"
"\"name\":\"FooClock\","
"\"manufacturer\":\"DIY\""
"}"
"}",
device_id,
mqtt_command_topic,
mqtt_state_topic,
device_id
);
// Nachricht mit Retain-Flag publishen, damit HA sie auch nach einem Neustart findet
client.publish(mqtt_discovery_topic, discoveryPayload, true);
}
// ---------------- MQTT Reconnect ------------------
void reconnect() {
while (!client.connected()) {
Serial.print("MQTT Verbindung herstellen...");
if (client.connect(mqtt_client)) {
Serial.println("verbunden.");
// Sobald verbunden, Befehls-Topic abonnieren
client.subscribe(mqtt_command_topic);
// Discovery-Nachricht und initialen Status senden
publishDiscoveryMessage();
publishState();
} else {
Serial.print("Fehler, rc=");
Serial.print(client.state());
Serial.println(" -> neuer Versuch in 5s");
delay(5000);
}
}
}
// ----------------------------------- Setup Code ---------------------------------------------- //
void setup() {
pinMode(OutputEnable, OUTPUT);
@@ -164,10 +277,20 @@ void setup() {
setSyncProvider(getNtpTime);
update_counter = 0;
init_done = true;
// <<< MQTT init >>>
client.setServer(mqtt_server, mqtt_port);
client.setCallback(mqttCallback);
}
// -------------------------------------- Main Loop ------------------------------------------------- //
void loop() {
// <<< MQTT >>>
if (!client.connected()) {
reconnect();
}
client.loop();
time_t timestamp = now();
// Sync blinking with second change
if (cur_time != timestamp && !second_changed) {
@@ -216,7 +339,7 @@ void loop() {
shift_state = 0;
updateDate(timestamp);
animation = rand() % 6;
animation = (int) (rand() % 6);
}
// Blinkenfoo - comment to remove pulsating light
@@ -233,10 +356,19 @@ void loop() {
// ---------------------- Interrupt Handler (Timer1) ------------------- //
void updateDisplay() {
if (!displayEnabled) {
// Anzeige aus: alles dunkel
digitalWrite(latchPin, LOW);
for (int digitCount = 5; digitCount >= 0; digitCount--) {
shiftOut(dataPin, clockPin, MSBFIRST, 0);
}
digitalWrite(latchPin, HIGH);
return;
}
// take the latchPin low so
// the LEDs don't flicker while you're sending in bits:
digitalWrite(latchPin, LOW);
for (int digitCount = 5; digitCount >= 0; digitCount--) {
shiftOut(dataPin, clockPin, MSBFIRST, frame[digitCount]);
}
@@ -244,7 +376,6 @@ void updateDisplay() {
digitalWrite(latchPin, HIGH);
update_counter++;
if (update_counter == 1000) {
update_counter = 0;
}
@@ -256,6 +387,7 @@ void updateDisplay() {
}
}
// -------------------------------- Date Functions ---------------------- //
void updateDate(time_t t) {
today[0] = digits[(day(t) / 10)];