From 850cda3c384c104fc46f2b29043d4e739e88c2a5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 25 Mar 2023 02:10:16 +0100 Subject: [PATCH] 0.5.106 * merged MI and debug message changes #804 * fixed MQTT autodiscover #794, #632 --- src/CHANGES.md | 4 + src/defines.h | 2 +- src/platformio.ini | 19 ++-- src/publisher/pubMqtt.h | 191 ++++++++++++++++++++++------------------ 4 files changed, 117 insertions(+), 99 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 4223ad99..70b87e0f 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,10 @@ (starting from release version `0.5.66`) +## 0.5.106 +* merged MI and debug message changes #804 +* fixed MQTT autodiscover #794, #632 + ## 0.5.105 * merged MI, thx @rejoe2 #788 * fixed reboot message #793 diff --git a/src/defines.h b/src/defines.h index dafcb9ec..d0c57264 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 105 +#define VERSION_PATCH 106 //------------------------------------- typedef struct { diff --git a/src/platformio.ini b/src/platformio.ini index 6d3f8d23..38e67c95 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -35,25 +35,20 @@ extra_scripts = lib_deps = https://github.com/yubox-node-org/ESPAsyncWebServer - nrf24/RF24 - paulstoffregen/Time + nrf24/RF24 @ ^1.4.5 + paulstoffregen/Time @ ^1.6.1 https://github.com/bertmelis/espMqttClient#v1.4.1 - bblanchon/ArduinoJson - https://github.com/JChristensen/Timezone - olikraus/U8g2 - zinggjm/GxEPD2@^1.5.0 - ;esp8266/DNSServer - ;esp8266/EEPROM - ;esp8266/ESP8266WiFi - ;esp8266/SPI - ;esp8266/Ticker + bblanchon/ArduinoJson @ ^6.21.0 + https://github.com/JChristensen/Timezone @ ^1.2.4 + olikraus/U8g2 @ ^2.34.16 + zinggjm/GxEPD2 @ ^1.5.0 [env:esp8266-release] platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = -D RELEASE +build_flags = -D RELEASE -Wl,-Map,output.map monitor_filters = ;default ; Remove typical terminal control codes from input ;time ; Add timestamp with milliseconds for each new line diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 73196918..a529d1fc 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -34,6 +34,12 @@ struct alarm_t { alarm_t(uint16_t c, uint32_t s, uint32_t e) : code(c), start(s), end(e) {} }; +typedef struct { + bool running; + uint8_t lastIvId; + uint8_t sub; +} discovery_t; + template class PubMqtt { public: @@ -55,6 +61,8 @@ class PubMqtt { mUtcTimestamp = utcTs; mIntervalTimeout = 1; + mDiscovery.running = false; + snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0)) @@ -82,6 +90,9 @@ class PubMqtt { mClient.loop(); yield(); #endif + + if(mDiscovery.running) + discoveryConfigLoop(); } @@ -210,92 +221,9 @@ class PubMqtt { void sendDiscoveryConfig(void) { DPRINTLN(DBG_VERBOSE, F("sendMqttDiscoveryConfig")); - - char topic[64], name[32], uniq_id[32]; - DynamicJsonDocument doc(256); - - uint8_t fldTotal[4] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC}; - const char* unitTotal[4] = {"W", "kWh", "Wh", "W"}; - - String node_mac = WiFi.macAddress().substring(12,14)+ WiFi.macAddress().substring(15,17); - String node_id = "AHOY_DTU_" + node_mac; - bool total = false; - - for (uint8_t id = 0; id < mSys->getNumInverters() ; id++) { - doc.clear(); - - if (total) // total become true at iv = NULL next cycle - continue; - - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL == iv) - total = true; - record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - - if (!total) { - doc[F("name")] = iv->config->name; - doc[F("ids")] = String(iv->config->serial.u64, HEX); - doc[F("mdl")] = iv->config->name; - } - else { - doc[F("name")] = node_id; - doc[F("ids")] = node_id; - doc[F("mdl")] = node_id; - } - - doc[F("cu")] = F("http://") + String(WiFi.localIP().toString()); - doc[F("mf")] = F("Hoymiles"); - JsonObject deviceObj = doc.as(); // deviceObj is only pointer!? - - for (uint8_t i = 0; i < ((!total) ? (rec->length) : (4) ) ; i++) { - const char *devCls, *stateCls; - if (!total) { - if (rec->assign[i].ch == CH0) - snprintf(name, 32, "%s %s", iv->config->name, iv->getFieldName(i, rec)); - else - snprintf(name, 32, "%s CH%d %s", iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec)); - snprintf(topic, 64, "/ch%d/%s", rec->assign[i].ch, iv->getFieldName(i, rec)); - snprintf(uniq_id, 32, "ch%d_%s", rec->assign[i].ch, iv->getFieldName(i, rec)); - - devCls = getFieldDeviceClass(rec->assign[i].fieldId); - stateCls = getFieldStateClass(rec->assign[i].fieldId); - } - - else { // total values - snprintf(name, 32, "Total %s", fields[fldTotal[i]]); - snprintf(topic, 64, "/%s", fields[fldTotal[i]]); - snprintf(uniq_id, 32, "total_%s", fields[fldTotal[i]]); - devCls = getFieldDeviceClass(fldTotal[i]); - stateCls = getFieldStateClass(fldTotal[i]); - } - - DynamicJsonDocument doc2(512); - doc2[F("name")] = name; - doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + ((!total) ? String(iv->config->name) : "total" ) + String(topic); - doc2[F("unit_of_meas")] = ((!total) ? (iv->getUnit(i,rec)) : (unitTotal[i])); - doc2[F("uniq_id")] = ((!total) ? (String(iv->config->serial.u64, HEX)) : (node_id)) + "_" + uniq_id; - doc2[F("dev")] = deviceObj; - if (!(String(stateCls) == String("total_increasing"))) - doc2[F("exp_aft")] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!? - if (devCls != NULL) - doc2[F("dev_cla")] = String(devCls); - if (stateCls != NULL) - doc2[F("stat_cla")] = String(stateCls); - - if (!total) - snprintf(topic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec)); - else // total values - snprintf(topic, 64, "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(),fields[fldTotal[i]]); - size_t size = measureJson(doc2) + 1; - char *buf = new char[size]; - memset(buf, 0, size); - serializeJson(doc2, buf, size); - publish(topic, buf, true, false); - delete[] buf; - } - - yield(); - } + mDiscovery.running = true; + mDiscovery.lastIvId = 0; + mDiscovery.sub = 0; } void setPowerLimitAck(Inverter<> *iv) { @@ -415,6 +343,95 @@ class PubMqtt { mRxCnt++; } + void discoveryConfigLoop(void) { + char topic[64], name[32], uniq_id[32], buf[350]; + DynamicJsonDocument doc(256); + + uint8_t fldTotal[4] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC}; + const char* unitTotal[4] = {"W", "kWh", "Wh", "W"}; + + String node_mac = WiFi.macAddress().substring(12,14)+ WiFi.macAddress().substring(15,17); + String node_id = "AHOY_DTU_" + node_mac; + bool total = (mDiscovery.lastIvId == MAX_NUM_INVERTERS); + + Inverter<> *iv = mSys->getInverterByPos(mDiscovery.lastIvId); + record_t<> *rec; + if (NULL != iv) + rec = iv->getRecordStruct(RealTimeRunData_Debug); + + if ((NULL != iv) || total) { + if (!total) { + doc[F("name")] = iv->config->name; + doc[F("ids")] = String(iv->config->serial.u64, HEX); + doc[F("mdl")] = iv->config->name; + } + else { + doc[F("name")] = node_id; + doc[F("ids")] = node_id; + doc[F("mdl")] = node_id; + } + + doc[F("cu")] = F("http://") + String(WiFi.localIP().toString()); + doc[F("mf")] = F("Hoymiles"); + JsonObject deviceObj = doc.as(); // deviceObj is only pointer!? + + const char *devCls, *stateCls; + if (!total) { + if (rec->assign[mDiscovery.sub].ch == CH0) + snprintf(name, 32, "%s %s", iv->config->name, iv->getFieldName(mDiscovery.sub, rec)); + else + snprintf(name, 32, "%s CH%d %s", iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec)); + snprintf(topic, 64, "/ch%d/%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec)); + snprintf(uniq_id, 32, "ch%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec)); + + devCls = getFieldDeviceClass(rec->assign[mDiscovery.sub].fieldId); + stateCls = getFieldStateClass(rec->assign[mDiscovery.sub].fieldId); + } + + else { // total values + snprintf(name, 32, "Total %s", fields[fldTotal[mDiscovery.sub]]); + snprintf(topic, 64, "/%s", fields[fldTotal[mDiscovery.sub]]); + snprintf(uniq_id, 32, "total_%s", fields[fldTotal[mDiscovery.sub]]); + devCls = getFieldDeviceClass(fldTotal[mDiscovery.sub]); + stateCls = getFieldStateClass(fldTotal[mDiscovery.sub]); + } + + DynamicJsonDocument doc2(512); + doc2[F("name")] = name; + doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + ((!total) ? String(iv->config->name) : "total" ) + String(topic); + doc2[F("unit_of_meas")] = ((!total) ? (iv->getUnit(mDiscovery.sub, rec)) : (unitTotal[mDiscovery.sub])); + doc2[F("uniq_id")] = ((!total) ? (String(iv->config->serial.u64, HEX)) : (node_id)) + "_" + uniq_id; + doc2[F("dev")] = deviceObj; + if (!(String(stateCls) == String("total_increasing"))) + doc2[F("exp_aft")] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!? + if (devCls != NULL) + doc2[F("dev_cla")] = String(devCls); + if (stateCls != NULL) + doc2[F("stat_cla")] = String(stateCls); + + if (!total) + snprintf(topic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec)); + else // total values + snprintf(topic, 64, "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(),fields[fldTotal[mDiscovery.sub]]); + size_t size = measureJson(doc2) + 1; + memset(buf, 0, size); + serializeJson(doc2, buf, size); + publish(topic, buf, true, false); + + if(++mDiscovery.sub == ((!total) ? (rec->length) : 4)) { + mDiscovery.sub = 0; + if(++mDiscovery.lastIvId == (MAX_NUM_INVERTERS + 1)) + mDiscovery.running = false; + } + } else { + mDiscovery.sub = 0; + if(++mDiscovery.lastIvId == (MAX_NUM_INVERTERS + 1)) + mDiscovery.running = false; + } + + yield(); + } + const char *getFieldDeviceClass(uint8_t fieldId) { uint8_t pos = 0; for (; pos < DEVICE_CLS_ASSIGN_LIST_LEN; pos++) { @@ -643,6 +660,8 @@ class PubMqtt { char mClientId[24]; // number of chars is limited to 23 up to v3.1 of MQTT // global buffer for mqtt topic. Used when publishing mqtt messages. char mTopic[MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1]; + + discovery_t mDiscovery; }; #endif /*__PUB_MQTT_H__*/