From 4df936a437a2e643fca724885b336b6bb3034bbd Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Thu, 2 May 2024 10:33:10 +0200 Subject: [PATCH] Fix for unfortunate prior CRLF coversion. --- wled00/mqtt.cpp | 394 ++++++++++++++++++++++++------------------------ 1 file changed, 197 insertions(+), 197 deletions(-) diff --git a/wled00/mqtt.cpp b/wled00/mqtt.cpp index 810291094..2e2e4a6bd 100644 --- a/wled00/mqtt.cpp +++ b/wled00/mqtt.cpp @@ -1,197 +1,197 @@ -#include "wled.h" - -/* - * MQTT communication protocol for home automation - */ - -#ifdef WLED_ENABLE_MQTT -#define MQTT_KEEP_ALIVE_TIME 60 // contact the MQTT broker every 60 seconds - -void parseMQTTBriPayload(char* payload) -{ - if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; stateUpdated(CALL_MODE_DIRECT_CHANGE);} - else if (strstr(payload, "T" ) || strstr(payload, "t" )) {toggleOnOff(); stateUpdated(CALL_MODE_DIRECT_CHANGE);} - else { - uint8_t in = strtoul(payload, NULL, 10); - if (in == 0 && bri > 0) briLast = bri; - bri = in; - stateUpdated(CALL_MODE_DIRECT_CHANGE); - } -} - - -void onMqttConnect(bool sessionPresent) -{ - //(re)subscribe to required topics - char subuf[38]; - - if (mqttDeviceTopic[0] != 0) { - strlcpy(subuf, mqttDeviceTopic, 33); - mqtt->subscribe(subuf, 0); - strcat_P(subuf, PSTR("/col")); - mqtt->subscribe(subuf, 0); - strlcpy(subuf, mqttDeviceTopic, 33); - strcat_P(subuf, PSTR("/api")); - mqtt->subscribe(subuf, 0); - } - - if (mqttGroupTopic[0] != 0) { - strlcpy(subuf, mqttGroupTopic, 33); - mqtt->subscribe(subuf, 0); - strcat_P(subuf, PSTR("/col")); - mqtt->subscribe(subuf, 0); - strlcpy(subuf, mqttGroupTopic, 33); - strcat_P(subuf, PSTR("/api")); - mqtt->subscribe(subuf, 0); - } - - usermods.onMqttConnect(sessionPresent); - - DEBUG_PRINTLN(F("MQTT ready")); - publishMqtt(); -} - - -void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { - static char *payloadStr; - - DEBUG_PRINT(F("MQTT msg: ")); - DEBUG_PRINTLN(topic); - - // paranoia check to avoid npe if no payload - if (payload==nullptr) { - DEBUG_PRINTLN(F("no payload -> leave")); - return; - } - - if (index == 0) { // start (1st partial packet or the only packet) - if (payloadStr) delete[] payloadStr; // fail-safe: release buffer - payloadStr = new char[total+1]; // allocate new buffer - } - if (payloadStr == nullptr) return; // buffer not allocated - - // copy (partial) packet to buffer and 0-terminate it if it is last packet - char* buff = payloadStr + index; - memcpy(buff, payload, len); - if (index + len >= total) { // at end - payloadStr[total] = '\0'; // terminate c style string - } else { - DEBUG_PRINTLN(F("MQTT partial packet received.")); - return; // process next packet - } - DEBUG_PRINTLN(payloadStr); - - size_t topicPrefixLen = strlen(mqttDeviceTopic); - if (strncmp(topic, mqttDeviceTopic, topicPrefixLen) == 0) { - topic += topicPrefixLen; - } else { - topicPrefixLen = strlen(mqttGroupTopic); - if (strncmp(topic, mqttGroupTopic, topicPrefixLen) == 0) { - topic += topicPrefixLen; - } else { - // Non-Wled Topic used here. Probably a usermod subscribed to this topic. - usermods.onMqttMessage(topic, payloadStr); - delete[] payloadStr; - payloadStr = nullptr; - return; - } - } - - //Prefix is stripped from the topic at this point - - if (strcmp_P(topic, PSTR("/col")) == 0) { - colorFromDecOrHexString(col, payloadStr); - colorUpdated(CALL_MODE_DIRECT_CHANGE); - } else if (strcmp_P(topic, PSTR("/api")) == 0) { - if (!requestJSONBufferLock(15)) { - delete[] payloadStr; - payloadStr = nullptr; - return; - } - if (payloadStr[0] == '{') { //JSON API - deserializeJson(*pDoc, payloadStr); - deserializeState(pDoc->as()); - } else { //HTTP API - String apireq = "win"; apireq += '&'; // reduce flash string usage - apireq += payloadStr; - handleSet(nullptr, apireq); - } - releaseJSONBufferLock(); - } else if (strlen(topic) != 0) { - // non standard topic, check with usermods - usermods.onMqttMessage(topic, payloadStr); - } else { - // topmost topic (just wled/MAC) - parseMQTTBriPayload(payloadStr); - } - delete[] payloadStr; - payloadStr = nullptr; -} - - -void publishMqtt() -{ - if (!WLED_MQTT_CONNECTED) return; - DEBUG_PRINTLN(F("Publish MQTT")); - - #ifndef USERMOD_SMARTNEST - char s[10]; - char subuf[48]; - - sprintf_P(s, PSTR("%u"), bri); - strlcpy(subuf, mqttDeviceTopic, 33); - strcat_P(subuf, PSTR("/g")); - mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263) - - sprintf_P(s, PSTR("#%06X"), (col[3] << 24) | (col[0] << 16) | (col[1] << 8) | (col[2])); - strlcpy(subuf, mqttDeviceTopic, 33); - strcat_P(subuf, PSTR("/c")); - mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263) - - strlcpy(subuf, mqttDeviceTopic, 33); - strcat_P(subuf, PSTR("/status")); - mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT - - char apires[1024]; // allocating 1024 bytes from stack can be risky - XML_response(nullptr, apires); - strlcpy(subuf, mqttDeviceTopic, 33); - strcat_P(subuf, PSTR("/v")); - mqtt->publish(subuf, 0, retainMqttMsg, apires); // optionally retain message (#2263) - #endif -} - - -//HA autodiscovery was removed in favor of the native integration in HA v0.102.0 - -bool initMqtt() -{ - if (!mqttEnabled || mqttServer[0] == 0 || !WLED_CONNECTED) return false; - - if (mqtt == nullptr) { - mqtt = new AsyncMqttClient(); - mqtt->onMessage(onMqttMessage); - mqtt->onConnect(onMqttConnect); - } - if (mqtt->connected()) return true; - - DEBUG_PRINTLN(F("Reconnecting MQTT")); - IPAddress mqttIP; - if (mqttIP.fromString(mqttServer)) //see if server is IP or domain - { - mqtt->setServer(mqttIP, mqttPort); - } else { - mqtt->setServer(mqttServer, mqttPort); - } - mqtt->setClientId(mqttClientID); - if (mqttUser[0] && mqttPass[0]) mqtt->setCredentials(mqttUser, mqttPass); - - #ifndef USERMOD_SMARTNEST - strlcpy(mqttStatusTopic, mqttDeviceTopic, 33); - strcat_P(mqttStatusTopic, PSTR("/status")); - mqtt->setWill(mqttStatusTopic, 0, true, "offline"); // LWT message - #endif - mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME); - mqtt->connect(); - return true; -} -#endif +#include "wled.h" + +/* + * MQTT communication protocol for home automation + */ + +#ifdef WLED_ENABLE_MQTT +#define MQTT_KEEP_ALIVE_TIME 60 // contact the MQTT broker every 60 seconds + +void parseMQTTBriPayload(char* payload) +{ + if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; stateUpdated(CALL_MODE_DIRECT_CHANGE);} + else if (strstr(payload, "T" ) || strstr(payload, "t" )) {toggleOnOff(); stateUpdated(CALL_MODE_DIRECT_CHANGE);} + else { + uint8_t in = strtoul(payload, NULL, 10); + if (in == 0 && bri > 0) briLast = bri; + bri = in; + stateUpdated(CALL_MODE_DIRECT_CHANGE); + } +} + + +void onMqttConnect(bool sessionPresent) +{ + //(re)subscribe to required topics + char subuf[38]; + + if (mqttDeviceTopic[0] != 0) { + strlcpy(subuf, mqttDeviceTopic, 33); + mqtt->subscribe(subuf, 0); + strcat_P(subuf, PSTR("/col")); + mqtt->subscribe(subuf, 0); + strlcpy(subuf, mqttDeviceTopic, 33); + strcat_P(subuf, PSTR("/api")); + mqtt->subscribe(subuf, 0); + } + + if (mqttGroupTopic[0] != 0) { + strlcpy(subuf, mqttGroupTopic, 33); + mqtt->subscribe(subuf, 0); + strcat_P(subuf, PSTR("/col")); + mqtt->subscribe(subuf, 0); + strlcpy(subuf, mqttGroupTopic, 33); + strcat_P(subuf, PSTR("/api")); + mqtt->subscribe(subuf, 0); + } + + usermods.onMqttConnect(sessionPresent); + + DEBUG_PRINTLN(F("MQTT ready")); + publishMqtt(); +} + + +void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { + static char *payloadStr; + + DEBUG_PRINT(F("MQTT msg: ")); + DEBUG_PRINTLN(topic); + + // paranoia check to avoid npe if no payload + if (payload==nullptr) { + DEBUG_PRINTLN(F("no payload -> leave")); + return; + } + + if (index == 0) { // start (1st partial packet or the only packet) + if (payloadStr) delete[] payloadStr; // fail-safe: release buffer + payloadStr = new char[total+1]; // allocate new buffer + } + if (payloadStr == nullptr) return; // buffer not allocated + + // copy (partial) packet to buffer and 0-terminate it if it is last packet + char* buff = payloadStr + index; + memcpy(buff, payload, len); + if (index + len >= total) { // at end + payloadStr[total] = '\0'; // terminate c style string + } else { + DEBUG_PRINTLN(F("MQTT partial packet received.")); + return; // process next packet + } + DEBUG_PRINTLN(payloadStr); + + size_t topicPrefixLen = strlen(mqttDeviceTopic); + if (strncmp(topic, mqttDeviceTopic, topicPrefixLen) == 0) { + topic += topicPrefixLen; + } else { + topicPrefixLen = strlen(mqttGroupTopic); + if (strncmp(topic, mqttGroupTopic, topicPrefixLen) == 0) { + topic += topicPrefixLen; + } else { + // Non-Wled Topic used here. Probably a usermod subscribed to this topic. + usermods.onMqttMessage(topic, payloadStr); + delete[] payloadStr; + payloadStr = nullptr; + return; + } + } + + //Prefix is stripped from the topic at this point + + if (strcmp_P(topic, PSTR("/col")) == 0) { + colorFromDecOrHexString(col, payloadStr); + colorUpdated(CALL_MODE_DIRECT_CHANGE); + } else if (strcmp_P(topic, PSTR("/api")) == 0) { + if (!requestJSONBufferLock(15)) { + delete[] payloadStr; + payloadStr = nullptr; + return; + } + if (payloadStr[0] == '{') { //JSON API + deserializeJson(*pDoc, payloadStr); + deserializeState(pDoc->as()); + } else { //HTTP API + String apireq = "win"; apireq += '&'; // reduce flash string usage + apireq += payloadStr; + handleSet(nullptr, apireq); + } + releaseJSONBufferLock(); + } else if (strlen(topic) != 0) { + // non standard topic, check with usermods + usermods.onMqttMessage(topic, payloadStr); + } else { + // topmost topic (just wled/MAC) + parseMQTTBriPayload(payloadStr); + } + delete[] payloadStr; + payloadStr = nullptr; +} + + +void publishMqtt() +{ + if (!WLED_MQTT_CONNECTED) return; + DEBUG_PRINTLN(F("Publish MQTT")); + + #ifndef USERMOD_SMARTNEST + char s[10]; + char subuf[48]; + + sprintf_P(s, PSTR("%u"), bri); + strlcpy(subuf, mqttDeviceTopic, 33); + strcat_P(subuf, PSTR("/g")); + mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263) + + sprintf_P(s, PSTR("#%06X"), (col[3] << 24) | (col[0] << 16) | (col[1] << 8) | (col[2])); + strlcpy(subuf, mqttDeviceTopic, 33); + strcat_P(subuf, PSTR("/c")); + mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263) + + strlcpy(subuf, mqttDeviceTopic, 33); + strcat_P(subuf, PSTR("/status")); + mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT + + char apires[1024]; // allocating 1024 bytes from stack can be risky + XML_response(nullptr, apires); + strlcpy(subuf, mqttDeviceTopic, 33); + strcat_P(subuf, PSTR("/v")); + mqtt->publish(subuf, 0, retainMqttMsg, apires); // optionally retain message (#2263) + #endif +} + + +//HA autodiscovery was removed in favor of the native integration in HA v0.102.0 + +bool initMqtt() +{ + if (!mqttEnabled || mqttServer[0] == 0 || !WLED_CONNECTED) return false; + + if (mqtt == nullptr) { + mqtt = new AsyncMqttClient(); + mqtt->onMessage(onMqttMessage); + mqtt->onConnect(onMqttConnect); + } + if (mqtt->connected()) return true; + + DEBUG_PRINTLN(F("Reconnecting MQTT")); + IPAddress mqttIP; + if (mqttIP.fromString(mqttServer)) //see if server is IP or domain + { + mqtt->setServer(mqttIP, mqttPort); + } else { + mqtt->setServer(mqttServer, mqttPort); + } + mqtt->setClientId(mqttClientID); + if (mqttUser[0] && mqttPass[0]) mqtt->setCredentials(mqttUser, mqttPass); + + #ifndef USERMOD_SMARTNEST + strlcpy(mqttStatusTopic, mqttDeviceTopic, 33); + strcat_P(mqttStatusTopic, PSTR("/status")); + mqtt->setWill(mqttStatusTopic, 0, true, "offline"); // LWT message + #endif + mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME); + mqtt->connect(); + return true; +} +#endif