From e28c450e71fa024b6e66c3357e5c4d734d63c11c Mon Sep 17 00:00:00 2001 From: Marcel Walter Date: Fri, 16 Jan 2026 22:57:31 +0100 Subject: [PATCH] MQTT: add client code --- include/secrets.h_template | 4 ++ platformio.ini | 5 +- src/main.cpp | 115 ++++++++++++++++++++++++++++++++++++- 3 files changed, 120 insertions(+), 4 deletions(-) diff --git a/include/secrets.h_template b/include/secrets.h_template index 69ab21d..a6e730c 100644 --- a/include/secrets.h_template +++ b/include/secrets.h_template @@ -5,3 +5,7 @@ #define WIFI_SSID "Wifi_SSID" #define WIFI_PASSWORD "secretPassword" + +#define MQTT_SERVER "mqttserver.fritz.box" +#define MQTT_USER "user" +#define MQTT_PASSWORD "password" diff --git a/platformio.ini b/platformio.ini index f1d7cd8..ad99ccb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,8 +14,9 @@ board = esp32dev framework = arduino monitor_speed = 115200 lib_deps = - witnessmenow/UniversalTelegramBot @ ^1.3.0 - adafruit/Adafruit GFX Library @ 1.12.3 + witnessmenow/UniversalTelegramBot @ ~1.3.0 + adafruit/Adafruit GFX Library @ ~1.12.3 + knolleary/PubSubClient @ ~2.8 build_flags=-DTELEGRAM_DEBUG ; OTA update path: hostname is flipdottelegram.fritz.box upload_protocol = espota diff --git a/src/main.cpp b/src/main.cpp index 72028c2..09d9510 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "Telegram.h" #include "FlipDotDrv.h" @@ -12,6 +14,36 @@ String Text = ""; const char *const HOSTNAME = "flipdottelegram"; +/* ------------ MQTT variables -------------- */ +WiFiClient espClient; +PubSubClient mqtt(espClient); +#define FLIPDOT_AVAILABILITY_TOPIC "flipdotdisplay/available" +#define FLIPDOT_SWITCH_TOPIC "flipdotdisplay/switch" +#define FLIPDOT_TEXT_TOPIC "flipdotdisplay/text" +void mqttCallback(char *topic, unsigned char *message, unsigned int length); + +void publishOpen() +{ + mqtt.publish(FLIPDOT_SWITCH_TOPIC "/state", "open"); + + JsonDocument doc; + doc["value"] = Text; + char output[256]; + serializeJson(doc, output); + mqtt.publish(FLIPDOT_TEXT_TOPIC "/state", output); +} + +void publishClose() +{ + mqtt.publish(FLIPDOT_SWITCH_TOPIC "/state", "close"); + + JsonDocument doc; + doc["value"] = Text; + char output[256]; + serializeJson(doc, output); + mqtt.publish(FLIPDOT_TEXT_TOPIC "/state", output); +} + /* ------------ OTA section and variables -------------- */ bool OTAStarted; void onOTAStart() @@ -117,6 +149,10 @@ void setup() /* setup ArduinoOTA */ ArduinoOTA.setHostname(HOSTNAME); ArduinoOTA.onStart(onOTAStart); + + /* prepare MQTT client */ + mqtt.setServer(MQTT_SERVER, 1883); + mqtt.setCallback(mqttCallback); } void loop() @@ -165,6 +201,21 @@ void loop() lastTelegramRefresh = now; tele.cyclic(now); } + + /* handle MQTT transmissions */ + if (!mqtt.loop()) + { + Serial.println("MQTT not connected"); + + // try to connect to MQTT broker again + if (mqtt.connect(HOSTNAME, MQTT_USER, MQTT_PASSWORD, FLIPDOT_AVAILABILITY_TOPIC, 2, true, "offline")) + { + // publish availability message + mqtt.subscribe(FLIPDOT_SWITCH_TOPIC); + mqtt.subscribe(FLIPDOT_TEXT_TOPIC); + mqtt.publish(FLIPDOT_AVAILABILITY_TOPIC, "available"); + } + } } else { @@ -178,6 +229,8 @@ void loop() ArduinoOTA.end(); + mqtt.disconnect(); + oldWifiStatus = WiFi.status(); } } @@ -239,12 +292,12 @@ void loop() } /* function to write text onto the canvas - * + * * @param text - C string to be printed * @param background - boolean switch if the background should be transparent (false) or black (true) * @param x - position in X direction to write the Text, -1 centers the text * @param y - position in Y direction to write the Text, -1 centers the text - * + * * */ void displayText(const char *text, bool background, int16_t x, int16_t y) { @@ -291,6 +344,7 @@ void displayText(const char *text, bool background, int16_t x, int16_t y) String printOpen(String Args) { Text = "offen"; + publishOpen(); return Text; } @@ -298,6 +352,7 @@ String printOpen(String Args) String printClose(String Args) { Text = "leider zu"; + publishClose(); return Text; } @@ -308,6 +363,62 @@ String printText(String Args) Serial.print(Args); Serial.println("'"); Text = Args; + publishClose(); return Text; } + +void mqttCallback(char *topic, unsigned char *message, unsigned int length) +{ + String MessageString; + + /* Convert all char* to Strings for simpler handling */ + for (int i = 0; i < length; i++) + { + MessageString += message[i]; + } + String ToppicString(topic); + + /* if topic is the switch topic check for on, off, open, close */ + if (ToppicString == FLIPDOT_SWITCH_TOPIC) + { + Serial.println("Switch topic received: " + MessageString); + + if ((MessageString == "open") || + (MessageString == "on")) + { + printOpen(MessageString); + } + else if ((MessageString == "close") || + (MessageString == "off")) + { + printClose(MessageString); + } + } + + /* if topic is the text topic try deserializing the json text */ + if (ToppicString == FLIPDOT_TEXT_TOPIC) + { + Serial.println("Text topic received: " + MessageString); + JsonDocument doc; + if (deserializeJson(doc, (const char *)message, length) == DeserializationError::Ok) + { + MessageString = doc["value"] | String("none"); // the pipe operand tells the default value, if "value" is not existing + + if ((MessageString != "none")) + { + printText(MessageString); + } + else + { + Serial.print(FLIPDOT_TEXT_TOPIC); + Serial.println(" has no [\"value\"]!"); + } + } + else + { + Serial.print(FLIPDOT_TEXT_TOPIC); + Serial.println(" is no json!"); + } + } +}