From 1103374abd0e919ba1f75830595c4d369d548a77 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Apr 2023 21:41:13 +0200 Subject: [PATCH 01/10] started to convert for and while loop to async loops --- src/publisher/pubMqtt.h | 117 ++++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 39 deletions(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index f9bf6f4d..7b766c92 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -34,13 +34,6 @@ 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; - uint8_t foundIvCnt; -} discovery_t; - template class PubMqtt { public: @@ -64,6 +57,7 @@ class PubMqtt { mIntervalTimeout = 1; mDiscovery.running = false; + mSendIvData.running = false; snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); @@ -93,6 +87,11 @@ class PubMqtt { yield(); #endif + if(mSendIvData.running) { + sendIvDataLoop(); + return; + } + if(mDiscovery.running) discoveryConfigLoop(); } @@ -107,13 +106,14 @@ class PubMqtt { return; // next try in a second } - if(0 == mCfgMqtt->interval) // no fixed interval, publish once new data were received (from inverter) - sendIvData(); + if(0 == mCfgMqtt->interval) { // no fixed interval, publish once new data were received (from inverter) + sendIvDataStart(); + } else { // send mqtt data in a fixed interval if(mIntervalTimeout == 0) { mIntervalTimeout = mCfgMqtt->interval; mSendList.push(RealTimeRunData_Debug); - sendIvData(); + sendIvDataStart(); } } } @@ -554,55 +554,65 @@ class PubMqtt { } } - void sendIvData() { + void sendIvDataStart() { + mSendIvData.RTRDataHasBeenSent = false; + memset(mSendIvData.total, 0, sizeof(float) * 4); + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL != iv) { + if (iv->config->enabled) { + mSendIvData.lastIvId = id; + mSendIvData.running = true; + mSendIvData.lastIvReached = false; + mSendIvData.sendTotals = false; + break; + } + } + } + } + + void sendIvDataLoop(void) { bool anyAvail = processIvStatus(); if (mLastAnyAvail != anyAvail) - mSendList.push(RealTimeRunData_Debug); // makes shure that total values are calculated + mSendList.push(RealTimeRunData_Debug); // makes sure that total values are calculated - if(mSendList.empty()) + if(mSendList.empty()) { + mSendIvData.running = false; return; + } - float total[4]; - bool RTRDataHasBeenSent = false; - while(!mSendList.empty()) { - memset(total, 0, sizeof(float) * 4); + //while(!mSendList.empty()) { uint8_t curInfoCmd = mSendList.front(); + if ((curInfoCmd != RealTimeRunData_Debug) || !mSendIvData.RTRDataHasBeenSent) { // send RTR Data only once + mSendIvData.sendTotals = (curInfoCmd == RealTimeRunData_Debug); - if ((curInfoCmd != RealTimeRunData_Debug) || !RTRDataHasBeenSent) { // send RTR Data only once - bool sendTotals = (curInfoCmd == RealTimeRunData_Debug); - - for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL == iv) - continue; // skip to next inverter - if (!iv->config->enabled) - continue; // skip to next inverter - + if(!mSendIvData.lastIvReached) { + Inverter<> *iv = mSys->getInverterByPos(mSendIvData.lastIvId); // send RTR Data only if status is available - if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[id])) + if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[mSendIvData.lastIvId])) sendData(iv, curInfoCmd); // calculate total values for RealTimeRunData_Debug - if (sendTotals) { + if (mSendIvData.sendTotals) { record_t<> *rec = iv->getRecordStruct(curInfoCmd); - sendTotals &= (iv->getLastTs(rec) > 0); - if (sendTotals) { + mSendIvData.sendTotals &= (iv->getLastTs(rec) > 0); + if (mSendIvData.sendTotals) { for (uint8_t i = 0; i < rec->length; i++) { if (CH0 == rec->assign[i].ch) { switch (rec->assign[i].fieldId) { case FLD_PAC: - total[0] += iv->getValue(i, rec); + mSendIvData.total[0] += iv->getValue(i, rec); break; case FLD_YT: - total[1] += iv->getValue(i, rec); + mSendIvData.total[1] += iv->getValue(i, rec); break; case FLD_YD: - total[2] += iv->getValue(i, rec); + mSendIvData.total[2] += iv->getValue(i, rec); break; case FLD_PDC: - total[3] += iv->getValue(i, rec); + mSendIvData.total[3] += iv->getValue(i, rec); break; } } @@ -610,9 +620,21 @@ class PubMqtt { } } yield(); + + // get next inverter + for (uint8_t id = mSendIvData.lastIvId; id < mSys->getNumInverters(); id++) { + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL != iv) { + if (iv->config->enabled) { + mSendIvData.lastIvId = id; + return; + } + } + } + mSendIvData.lastIvReached = true; } - if (sendTotals) { + if (mSendIvData.sendTotals) { uint8_t fieldId; for (uint8_t i = 0; i < 4; i++) { bool retained = true; @@ -634,20 +656,36 @@ class PubMqtt { break; } snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); - snprintf(mVal, 40, "%g", ah::round3(total[i])); + snprintf(mVal, 40, "%g", ah::round3(mSendIvData.total[i])); publish(mSubTopic, mVal, retained); } - RTRDataHasBeenSent = true; + mSendIvData.RTRDataHasBeenSent = true; yield(); } } mSendList.pop(); // remove from list once all inverters were processed - } + //} // end while mLastAnyAvail = anyAvail; } + typedef struct { + bool running; + uint8_t lastIvId; + bool lastIvReached; + bool sendTotals; + float total[4]; + bool RTRDataHasBeenSent; + } publish_t; + + typedef struct { + bool running; + uint8_t lastIvId; + uint8_t sub; + uint8_t foundIvCnt; + } discovery_t; + espMqttClient mClient; cfgMqtt_t *mCfgMqtt; #if defined(ESP8266) @@ -674,6 +712,7 @@ class PubMqtt { char mSubTopic[32 + MAX_NAME_LENGTH + 1]; char mVal[40]; discovery_t mDiscovery; + publish_t mSendIvData; }; #endif /*__PUB_MQTT_H__*/ From b6531180df6bea425fe0da0ea70fea13a055ffa3 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Apr 2023 21:56:25 +0200 Subject: [PATCH 02/10] 0.6.8 * fix #892 `zeroYieldDay` loop was not applied to all channels --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/hm/hmPayload.h | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index f4c89d23..0b0d3676 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.6.8 - 2023-04-19 +* fix #892 `zeroYieldDay` loop was not applied to all channels + ## 0.6.7 - 2023-04-13 * merge PR #883, improved store of settings and javascript, thx @tastendruecker123 * support `.` and `,` as floating point seperator in setup #881 diff --git a/src/defines.h b/src/defines.h index 1ace50df..4313ee71 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 7 +#define VERSION_PATCH 8 //------------------------------------- typedef struct { diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index b04ee8f3..29f380fa 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -74,8 +74,8 @@ class HmPayload { DPRINTLN(DBG_DEBUG, F("zeroYieldDay")); record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); uint8_t pos; - for(uint8_t ch = 0; ch < iv->channels; ch++) { - pos = iv->getPosByChFld(CH0, FLD_YD, rec); + for(uint8_t ch = 0; ch <= iv->channels; ch++) { + pos = iv->getPosByChFld(ch, FLD_YD, rec); iv->setValue(pos, rec, 0.0f); } } From 7e1f1cece4ba1fc4aee4698f7ac448f1ebaa5225 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Apr 2023 23:00:24 +0200 Subject: [PATCH 03/10] 0.6.9 release --- src/CHANGES.md | 52 +++++++++++++--------------------------------- src/defines.h | 2 +- src/platformio.ini | 4 ++-- 3 files changed, 18 insertions(+), 40 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 0b0d3676..ba8f2d25 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,37 +1,15 @@ -# Development Changes - -## 0.6.8 - 2023-04-19 -* fix #892 `zeroYieldDay` loop was not applied to all channels - -## 0.6.7 - 2023-04-13 -* merge PR #883, improved store of settings and javascript, thx @tastendruecker123 -* support `.` and `,` as floating point seperator in setup #881 - -## 0.6.6 - 2023-04-12 -* increased distance for `import` button in mobile view #879 -* changed `led_high_active` to `bool` #879 - -## 0.6.5 - 2023-04-11 -* fix #845 MqTT subscription for `ctrl/power/[IV-ID]` was missing -* merge PR #876, check JSON settings during read for existance -* **NOTE:** incompatible change: renamed `led_high_active` to `act_high`, maybe setting must be changed after update -* merge PR #861 do not send channel metric if channel is disabled - -## 0.6.4 - 2023-04-06 -* merge PR #846, improved NRF24 communication and MI, thx @beegee3 & @rejoe2 -* merge PR #859, fix burger menu height, thx @ThomasPohl - -## 0.6.3 - 2023-04-04 -* fix login, password length was not checked #852 -* merge PR #854 optimize browser caching, thx @tastendruecker123 #828 -* fix WiFi reconnect not working #851 -* updated issue templates #822 - -## 0.6.2 - 2023-04-04 -* fix login from multiple clients #819 -* fix login screen on small displays - -## 0.6.1 - 2023-04-01 -* merge LED fix - LED1 shows MqTT state, LED configureable active high/low #839 -* only publish new inverter data #826 -* potential fix of WiFi hostname during boot up #752 +Changelog v0.6.9 + +* LEDs are now configurable to show if 1st inverter is available and if MqTT is connected +* LED are configurable to active high or low +* improved MqTT +* fix WiFi hostname during boot up +* improved login: only one session at the same time is possible +* fix UI: login screen for small displays; burger menu height; small modifications for import button (in setup) +* improved WiFi reconnect +* optimized performance: browser caching was improved to reduce requests from ESP +* improved NRF24 communication for more stable data transmission +* added / fixed MqTT subscription `ctrl/power/[IV-ID]` +* improved save settings +* improved UI in setup: now `.` and `,` are allowed as floating point seperator +* fix zero yield day functionality diff --git a/src/defines.h b/src/defines.h index 4313ee71..93722b6c 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 8 +#define VERSION_PATCH 9 //------------------------------------- typedef struct { diff --git a/src/platformio.ini b/src/platformio.ini index 5d4c655d..7b627f73 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -38,9 +38,9 @@ lib_deps = nrf24/RF24 @ ^1.4.5 paulstoffregen/Time @ ^1.6.1 https://github.com/bertmelis/espMqttClient#v1.4.2 - bblanchon/ArduinoJson @ ^6.21.0 + bblanchon/ArduinoJson @ ^6.21.2 https://github.com/JChristensen/Timezone @ ^1.2.4 - olikraus/U8g2 @ ^2.34.16 + olikraus/U8g2 @ ^2.34.17 zinggjm/GxEPD2 @ ^1.5.0 From 05d1eb607e1d54906ecd8287e088b0829014de61 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Apr 2023 23:06:02 +0200 Subject: [PATCH 04/10] 0.6.8 try to fix esp32s3 build --- src/platformio.ini | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/platformio.ini b/src/platformio.ini index 5d4c655d..087efad3 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -16,17 +16,6 @@ include_dir = . framework = arduino board_build.filesystem = littlefs upload_speed = 921600 - -;build_flags = -; ;;;;; Possible Debug options ;;;;;; -; https://docs.platformio.org/en/latest/platforms/espressif8266.html#debug-level - ;-DDEBUG_ESP_PORT=Serial - ;-DDEBUG_ESP_CORE - ;-DDEBUG_ESP_WIFI - ;-DDEBUG_ESP_HTTP_CLIENT - ;-DDEBUG_ESP_HTTP_SERVER - ;-DDEBUG_ESP_OOM - monitor_speed = 115200 extra_scripts = @@ -95,7 +84,13 @@ platform = espressif8266 board = esp8285 board_build.ldscript = eagle.flash.1m64.ld board_build.f_cpu = 80000000L -build_flags = -DDEBUG_LEVEL=DBG_DEBUG -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_OOM -DDEBUG_ESP_PORT=Serial +build_flags = -DDEBUG_LEVEL=DBG_DEBUG + -DDEBUG_ESP_CORE + -DDEBUG_ESP_WIFI + -DDEBUG_ESP_HTTP_CLIENT + -DDEBUG_ESP_HTTP_SERVER + -DDEBUG_ESP_OOM + -DDEBUG_ESP_PORT=Serial build_type = debug monitor_filters = ;default ; Remove typical terminal control codes from input @@ -103,7 +98,7 @@ monitor_filters = log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory [env:esp32-wroom32-release] -platform = espressif32 +platform = espressif32@>=6.1.0 board = lolin_d32 build_flags = -D RELEASE -std=gnu++14 build_unflags = -std=gnu++11 @@ -114,9 +109,11 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-release-prometheus] -platform = espressif32 +platform = espressif32@>=6.1.0 board = lolin_d32 -build_flags = -D RELEASE -std=gnu++14 -DENABLE_PROMETHEUS_EP +build_flags = -D RELEASE + -std=gnu++14 + -DENABLE_PROMETHEUS_EP build_unflags = -std=gnu++11 monitor_filters = ;default ; Remove typical terminal control codes from input @@ -125,9 +122,16 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-debug] -platform = espressif32 +platform = espressif32@>=6.1.0 board = lolin_d32 -build_flags = -DDEBUG_LEVEL=DBG_DEBUG -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_OOM -DDEBUG_ESP_PORT=Serial -std=gnu++14 +build_flags = -DDEBUG_LEVEL=DBG_DEBUG + -DDEBUG_ESP_CORE + -DDEBUG_ESP_WIFI + -DDEBUG_ESP_HTTP_CLIENT + -DDEBUG_ESP_HTTP_SERVER + -DDEBUG_ESP_OOM + -DDEBUG_ESP_PORT=Serial + -std=gnu++14 build_unflags = -std=gnu++11 build_type = debug monitor_filters = @@ -136,7 +140,7 @@ monitor_filters = log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory [env:opendtufusionv1-release] -platform = espressif32 +platform = espressif32@>=6.1.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin upload_speed = 115200 From 15ec6a0608dd1ad7e754b7b291c99cc0f15c4e67 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Apr 2023 23:21:42 +0200 Subject: [PATCH 05/10] 0.6.9 release --- src/CHANGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index ba8f2d25..281dc784 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,7 +1,5 @@ Changelog v0.6.9 -* LEDs are now configurable to show if 1st inverter is available and if MqTT is connected -* LED are configurable to active high or low * improved MqTT * fix WiFi hostname during boot up * improved login: only one session at the same time is possible @@ -13,3 +11,5 @@ Changelog v0.6.9 * improved save settings * improved UI in setup: now `.` and `,` are allowed as floating point seperator * fix zero yield day functionality +* LEDs are now configurable to show if 1st inverter is available and if MqTT is connected +* LED are configurable to active high or low From c004c83bf92733cbef943c7a5199a156506cbef2 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 25 Apr 2023 22:50:23 +0200 Subject: [PATCH 06/10] added statemachine --- src/publisher/pubMqtt.h | 123 ++++++++-------------- src/publisher/pubMqttIvData.h | 187 ++++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+), 78 deletions(-) create mode 100644 src/publisher/pubMqttIvData.h diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 7b766c92..e2bb96f5 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -22,6 +22,7 @@ #include "../hm/hmSystem.h" #include "pubMqttDefs.h" +#include "pubMqttIvData.h" #define QOS_0 0 @@ -34,6 +35,13 @@ 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; + uint8_t foundIvCnt; +} discovery_t; + template class PubMqtt { public: @@ -56,8 +64,8 @@ class PubMqtt { mUtcTimestamp = utcTs; mIntervalTimeout = 1; + mSendIvData.setup(sys, utcTs); mDiscovery.running = false; - mSendIvData.running = false; snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); @@ -82,16 +90,13 @@ class PubMqtt { } void loop() { + mSendIvData.loop(); + #if defined(ESP8266) mClient.loop(); yield(); #endif - if(mSendIvData.running) { - sendIvDataLoop(); - return; - } - if(mDiscovery.running) discoveryConfigLoop(); } @@ -106,14 +111,13 @@ class PubMqtt { return; // next try in a second } - if(0 == mCfgMqtt->interval) { // no fixed interval, publish once new data were received (from inverter) - sendIvDataStart(); - } + if(0 == mCfgMqtt->interval) // no fixed interval, publish once new data were received (from inverter) + sendIvData(); else { // send mqtt data in a fixed interval if(mIntervalTimeout == 0) { mIntervalTimeout = mCfgMqtt->interval; mSendList.push(RealTimeRunData_Debug); - sendIvDataStart(); + sendIvData(); } } } @@ -554,65 +558,55 @@ class PubMqtt { } } - void sendIvDataStart() { - mSendIvData.RTRDataHasBeenSent = false; - memset(mSendIvData.total, 0, sizeof(float) * 4); - for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL != iv) { - if (iv->config->enabled) { - mSendIvData.lastIvId = id; - mSendIvData.running = true; - mSendIvData.lastIvReached = false; - mSendIvData.sendTotals = false; - break; - } - } - } - } - - void sendIvDataLoop(void) { + void sendIvData() { bool anyAvail = processIvStatus(); if (mLastAnyAvail != anyAvail) - mSendList.push(RealTimeRunData_Debug); // makes sure that total values are calculated + mSendList.push(RealTimeRunData_Debug); // makes shure that total values are calculated - if(mSendList.empty()) { - mSendIvData.running = false; + if(mSendList.empty()) return; - } + float total[4]; + bool RTRDataHasBeenSent = false; - //while(!mSendList.empty()) { + while(!mSendList.empty()) { + memset(total, 0, sizeof(float) * 4); uint8_t curInfoCmd = mSendList.front(); - if ((curInfoCmd != RealTimeRunData_Debug) || !mSendIvData.RTRDataHasBeenSent) { // send RTR Data only once - mSendIvData.sendTotals = (curInfoCmd == RealTimeRunData_Debug); - if(!mSendIvData.lastIvReached) { - Inverter<> *iv = mSys->getInverterByPos(mSendIvData.lastIvId); + if ((curInfoCmd != RealTimeRunData_Debug) || !RTRDataHasBeenSent) { // send RTR Data only once + bool sendTotals = (curInfoCmd == RealTimeRunData_Debug); + + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL == iv) + continue; // skip to next inverter + if (!iv->config->enabled) + continue; // skip to next inverter + // send RTR Data only if status is available - if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[mSendIvData.lastIvId])) + if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[id])) sendData(iv, curInfoCmd); // calculate total values for RealTimeRunData_Debug - if (mSendIvData.sendTotals) { + if (sendTotals) { record_t<> *rec = iv->getRecordStruct(curInfoCmd); - mSendIvData.sendTotals &= (iv->getLastTs(rec) > 0); - if (mSendIvData.sendTotals) { + sendTotals &= (iv->getLastTs(rec) > 0); + if (sendTotals) { for (uint8_t i = 0; i < rec->length; i++) { if (CH0 == rec->assign[i].ch) { switch (rec->assign[i].fieldId) { case FLD_PAC: - mSendIvData.total[0] += iv->getValue(i, rec); + total[0] += iv->getValue(i, rec); break; case FLD_YT: - mSendIvData.total[1] += iv->getValue(i, rec); + total[1] += iv->getValue(i, rec); break; case FLD_YD: - mSendIvData.total[2] += iv->getValue(i, rec); + total[2] += iv->getValue(i, rec); break; case FLD_PDC: - mSendIvData.total[3] += iv->getValue(i, rec); + total[3] += iv->getValue(i, rec); break; } } @@ -620,21 +614,9 @@ class PubMqtt { } } yield(); - - // get next inverter - for (uint8_t id = mSendIvData.lastIvId; id < mSys->getNumInverters(); id++) { - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL != iv) { - if (iv->config->enabled) { - mSendIvData.lastIvId = id; - return; - } - } - } - mSendIvData.lastIvReached = true; } - if (mSendIvData.sendTotals) { + if (sendTotals) { uint8_t fieldId; for (uint8_t i = 0; i < 4; i++) { bool retained = true; @@ -656,36 +638,20 @@ class PubMqtt { break; } snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); - snprintf(mVal, 40, "%g", ah::round3(mSendIvData.total[i])); + snprintf(mVal, 40, "%g", ah::round3(total[i])); publish(mSubTopic, mVal, retained); } - mSendIvData.RTRDataHasBeenSent = true; + RTRDataHasBeenSent = true; yield(); } } mSendList.pop(); // remove from list once all inverters were processed - //} // end while + } mLastAnyAvail = anyAvail; } - typedef struct { - bool running; - uint8_t lastIvId; - bool lastIvReached; - bool sendTotals; - float total[4]; - bool RTRDataHasBeenSent; - } publish_t; - - typedef struct { - bool running; - uint8_t lastIvId; - uint8_t sub; - uint8_t foundIvCnt; - } discovery_t; - espMqttClient mClient; cfgMqtt_t *mCfgMqtt; #if defined(ESP8266) @@ -693,6 +659,8 @@ class PubMqtt { #endif HMSYSTEM *mSys; + PubMqttIvData mSendIvData; + uint32_t *mUtcTimestamp; uint32_t mRxCnt, mTxCnt; std::queue mSendList; @@ -712,7 +680,6 @@ class PubMqtt { char mSubTopic[32 + MAX_NAME_LENGTH + 1]; char mVal[40]; discovery_t mDiscovery; - publish_t mSendIvData; }; #endif /*__PUB_MQTT_H__*/ diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h new file mode 100644 index 00000000..361ce307 --- /dev/null +++ b/src/publisher/pubMqttIvData.h @@ -0,0 +1,187 @@ +#ifndef __PUB_MQTT_IV_DATA_H__ +#define __PUB_MQTT_IV_DATA_H__ + +#include "../utils/dbg.h" +#include "../hm/hmSystem.h" +#include "pubMqttDefs.h" + +typedef std::function pubMqttPublisherType; + +template +class PubMqttIvData { + public: + void setup(HMSYSTEM *sys, uint32_t *utcTs) { + mSys = sys; + mUtcTimestamp = utcTs; + mState = IDLE; + + memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * 4); + + mTable[IDLE] = &PubMqttIvData::stateIdle; + mTable[START] = &PubMqttIvData::stateStart; + mTable[FIND_NXT_IV] = &PubMqttIvData::stateFindNxtIv; + mTable[SEND_DATA] = &PubMqttIvData::stateSend; + mTable[SEND_TOTALS] = &PubMqttIvData::stateSendTotals; + } + + void loop() { + (this->*mTable[mState])(); + yield(); + } + + bool start(uint8_t cmd) { + if(IDLE != mState) + return false; + + mCmd = cmd; + mState = START; + return true; + } + + void setPublishFunc(pubMqttPublisherType cb) { + mPublish = cb; + } + + private: + enum State {IDLE, START, FIND_NXT_IV, SEND_DATA, SEND_TOTALS, NUM_STATES}; + typedef void (PubMqttIvData::*StateFunction)(); + + void stateIdle() { + ; // nothing to do + } + + void stateStart() { + mLastIvId = 0; + mSendTotals = (RealTimeRunData_Debug == mCmd); + memset(mTotal, 0, sizeof(float) * 4); + + mState = FIND_NXT_IV; + } + + void stateFindNxtIv() { + bool found = false; + + for (; mLastIvId < mSys->getNumInverters(); mLastIvId++) { + mIv = mSys->getInverterByPos(mLastIvId); + if (NULL != mIv) { + if (mIv->config->enabled) { + found = true; + break; + } + } + } + + mPos = 0; + if(found) + mState = SEND_DATA; + else if(mSendTotals) + mState = SEND_TOTALS; + else + mState = IDLE; + } + + void stateSend() { + record_t<> *rec = mIv->getRecordStruct(mCmd); + uint32_t lastTs = mIv->getLastTs(rec); + bool pubData = (lastTs > 0); + if (mCmd == RealTimeRunData_Debug) + pubData &= (lastTs != mIvLastRTRpub[mIv->id]); + + if (pubData) { + mIvLastRTRpub[mIv->id] = lastTs; + //for (uint8_t i = 0; i < rec->length; i++) { + if(mPos < rec->length) { + bool retained = false; + if (mCmd == RealTimeRunData_Debug) { + switch (rec->assign[mPos].fieldId) { + case FLD_YT: + case FLD_YD: + if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing(*mUtcTimestamp))) { // avoids returns to 0 on restart + mPos++; + return; + } + retained = true; + break; + } + + // calculate total values for RealTimeRunData_Debug + if (CH0 == rec->assign[mPos].ch) { + switch (rec->assign[mPos].fieldId) { + case FLD_PAC: + mTotal[0] += mIv->getValue(mPos, rec); + break; + case FLD_YT: + mTotal[1] += mIv->getValue(mPos, rec); + break; + case FLD_YD: + mTotal[2] += mIv->getValue(mPos, rec); + break; + case FLD_PDC: + mTotal[3] += mIv->getValue(mPos, rec); + break; + } + } + } + + snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); + snprintf(mVal, 40, "%g", ah::round3(mIv->getValue(mPos, rec))); + mPublish(mSubTopic, mVal, retained); + mPos++; + } else + mState = FIND_NXT_IV; + } else + mState = FIND_NXT_IV; + } + + void stateSendTotals() { + uint8_t fieldId; + //for (uint8_t i = 0; i < 4; i++) { + if(mPos < 4) { + bool retained = true; + switch (mPos) { + default: + case 0: + fieldId = FLD_PAC; + retained = false; + break; + case 1: + fieldId = FLD_YT; + break; + case 2: + fieldId = FLD_YD; + break; + case 3: + fieldId = FLD_PDC; + retained = false; + break; + } + snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); + snprintf(mVal, 40, "%g", ah::round3(mTotal[mPos])); + mPublish(mSubTopic, mVal, retained); + mPos++; + } else + mState = IDLE; + + RTRDataHasBeenSent = true; + } + + HMSYSTEM *mSys; + uint32_t *mUtcTimestamp; + pubMqttPublisherType mPublish; + State mState; + StateFunction mTable[NUM_STATES]; + + uint8_t mCmd; + uint8_t mLastIvId; + bool mSendTotals; + float mTotal[4]; + + Inverter<> *mIv; + uint8_t mPos; + uint32_t mIvLastRTRpub[MAX_NUM_INVERTERS]; + + char mSubTopic[32 + MAX_NAME_LENGTH + 1]; + char mVal[40]; +}; + +#endif /*__PUB_MQTT_IV_DATA_H__*/ From 2108a13fa715cf4cb72e4e5719f70b3ed54c9a1c Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 27 Apr 2023 21:38:01 +0200 Subject: [PATCH 07/10] pub mqtt loop in extra class --- src/publisher/pubMqtt.h | 89 ++--------------------------------- src/publisher/pubMqttIvData.h | 37 +++++++++++---- 2 files changed, 33 insertions(+), 93 deletions(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index e2bb96f5..049554d7 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -64,7 +64,10 @@ class PubMqtt { mUtcTimestamp = utcTs; mIntervalTimeout = 1; - mSendIvData.setup(sys, utcTs); + mSendIvData.setup(sys, utcTs, &mSendList); + mSendIvData.setPublishFunc([this](const char *subTopic, const char *payload, bool retained) { + publish(subTopic, payload, retained); + }); mDiscovery.running = false; snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); @@ -566,89 +569,7 @@ class PubMqtt { if(mSendList.empty()) return; - float total[4]; - bool RTRDataHasBeenSent = false; - - while(!mSendList.empty()) { - memset(total, 0, sizeof(float) * 4); - uint8_t curInfoCmd = mSendList.front(); - - if ((curInfoCmd != RealTimeRunData_Debug) || !RTRDataHasBeenSent) { // send RTR Data only once - bool sendTotals = (curInfoCmd == RealTimeRunData_Debug); - - for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL == iv) - continue; // skip to next inverter - if (!iv->config->enabled) - continue; // skip to next inverter - - // send RTR Data only if status is available - if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[id])) - sendData(iv, curInfoCmd); - - // calculate total values for RealTimeRunData_Debug - if (sendTotals) { - record_t<> *rec = iv->getRecordStruct(curInfoCmd); - - sendTotals &= (iv->getLastTs(rec) > 0); - if (sendTotals) { - for (uint8_t i = 0; i < rec->length; i++) { - if (CH0 == rec->assign[i].ch) { - switch (rec->assign[i].fieldId) { - case FLD_PAC: - total[0] += iv->getValue(i, rec); - break; - case FLD_YT: - total[1] += iv->getValue(i, rec); - break; - case FLD_YD: - total[2] += iv->getValue(i, rec); - break; - case FLD_PDC: - total[3] += iv->getValue(i, rec); - break; - } - } - } - } - } - yield(); - } - - if (sendTotals) { - uint8_t fieldId; - for (uint8_t i = 0; i < 4; i++) { - bool retained = true; - switch (i) { - default: - case 0: - fieldId = FLD_PAC; - retained = false; - break; - case 1: - fieldId = FLD_YT; - break; - case 2: - fieldId = FLD_YD; - break; - case 3: - fieldId = FLD_PDC; - retained = false; - break; - } - snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); - snprintf(mVal, 40, "%g", ah::round3(total[i])); - publish(mSubTopic, mVal, retained); - } - RTRDataHasBeenSent = true; - yield(); - } - } - - mSendList.pop(); // remove from list once all inverters were processed - } - + mSendIvData.start(); mLastAnyAvail = anyAvail; } diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 361ce307..4c574118 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -1,3 +1,8 @@ +//----------------------------------------------------------------------------- +// 2023 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + #ifndef __PUB_MQTT_IV_DATA_H__ #define __PUB_MQTT_IV_DATA_H__ @@ -10,12 +15,14 @@ typedef std::function class PubMqttIvData { public: - void setup(HMSYSTEM *sys, uint32_t *utcTs) { + void setup(HMSYSTEM *sys, uint32_t *utcTs, std::queue *sendList) { mSys = sys; mUtcTimestamp = utcTs; + mSendList = sendList; mState = IDLE; memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * 4); + mRTRDataHasBeenSent = false; mTable[IDLE] = &PubMqttIvData::stateIdle; mTable[START] = &PubMqttIvData::stateStart; @@ -29,11 +36,11 @@ class PubMqttIvData { yield(); } - bool start(uint8_t cmd) { + bool start(void) { if(IDLE != mState) return false; - mCmd = cmd; + mRTRDataHasBeenSent = false; mState = START; return true; } @@ -52,10 +59,17 @@ class PubMqttIvData { void stateStart() { mLastIvId = 0; - mSendTotals = (RealTimeRunData_Debug == mCmd); - memset(mTotal, 0, sizeof(float) * 4); + if(!mSendList->empty()) { + mCmd = mSendList->front(); - mState = FIND_NXT_IV; + if((RealTimeRunData_Debug != mCmd) || !mRTRDataHasBeenSent) { + mSendTotals = (RealTimeRunData_Debug == mCmd); + memset(mTotal, 0, sizeof(float) * 4); + mState = FIND_NXT_IV; + } else + mSendList->pop(); + } else + mState = IDLE; } void stateFindNxtIv() { @@ -159,10 +173,12 @@ class PubMqttIvData { snprintf(mVal, 40, "%g", ah::round3(mTotal[mPos])); mPublish(mSubTopic, mVal, retained); mPos++; - } else - mState = IDLE; + } else { + mSendList->pop(); + mState = START; + } - RTRDataHasBeenSent = true; + mRTRDataHasBeenSent = true; } HMSYSTEM *mSys; @@ -179,9 +195,12 @@ class PubMqttIvData { Inverter<> *mIv; uint8_t mPos; uint32_t mIvLastRTRpub[MAX_NUM_INVERTERS]; + bool mRTRDataHasBeenSent; char mSubTopic[32 + MAX_NAME_LENGTH + 1]; char mVal[40]; + + std::queue *mSendList; }; #endif /*__PUB_MQTT_IV_DATA_H__*/ From 8ead358f4cd4602e00a7f6fc38df8118f2e4f928 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 27 Apr 2023 23:09:49 +0200 Subject: [PATCH 08/10] fix publish loop --- src/app.cpp | 4 +++- src/defines.h | 4 ++-- src/hm/hmPayload.h | 23 +++++++++++++++++++++++ src/publisher/pubMqttIvData.h | 8 ++++---- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index d2d87f50..c61c81aa 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -32,7 +32,7 @@ void app::setup() { mSys.enableDebug(); mSys.setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs, mConfig->nrf.pinSclk, mConfig->nrf.pinMosi, mConfig->nrf.pinMiso); -#if defined(AP_ONLY) + #if defined(AP_ONLY) mInnerLoopCb = std::bind(&app::loopStandard, this); #else mInnerLoopCb = std::bind(&app::loopWifi, this); @@ -171,6 +171,8 @@ void app::regularTickers(void) { if (mConfig->plugin.display.type != 0) everySec(std::bind(&DisplayType::tickerSecond, &mDisplay), "disp"); every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval, "uart"); + + // every([this]() {mPayload.simulation();}, 15, "simul"); } //----------------------------------------------------------------------------- diff --git a/src/defines.h b/src/defines.h index 93722b6c..7260d766 100644 --- a/src/defines.h +++ b/src/defines.h @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2023 Ahoy, https://www.mikrocontroller.net/topic/525778 +// 2023 Ahoy, https://ahoydtu.de // Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 9 +#define VERSION_PATCH 11 //------------------------------------- typedef struct { diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 29f380fa..0ec40d22 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -70,6 +70,29 @@ class HmPayload { } } + /*void simulation() { + uint8_t pay[] = { + 0x00, 0x01, 0x01, 0x24, 0x02, 0x28, 0x02, 0x33, + 0x06, 0x49, 0x06, 0x6a, 0x00, 0x05, 0x5f, 0x1b, + 0x00, 0x06, 0x66, 0x9a, 0x03, 0xfd, 0x04, 0x0b, + 0x01, 0x23, 0x02, 0x28, 0x02, 0x28, 0x06, 0x41, + 0x06, 0x43, 0x00, 0x05, 0xdc, 0x2c, 0x00, 0x06, + 0x2e, 0x3f, 0x04, 0x01, 0x03, 0xfb, 0x09, 0x78, + 0x13, 0x86, 0x18, 0x15, 0x00, 0xcf, 0x00, 0xfe, + 0x03, 0xe7, 0x01, 0x42, 0x00, 0x03 + }; + + Inverter<> *iv = mSys->getInverterByPos(0); + record_t<> *rec = iv->getRecordStruct(0x0b); + rec->ts = *mTimestamp; + for (uint8_t i = 0; i < rec->length; i++) { + iv->addValue(i, pay, rec); + yield(); + } + iv->doCalculations(); + notify(0x0b); + }*/ + void zeroYieldDay(Inverter<> *iv) { DPRINTLN(DBG_DEBUG, F("zeroYieldDay")); record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 4c574118..ba4cbbbf 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -85,6 +85,8 @@ class PubMqttIvData { } } + mLastIvId++; + mPos = 0; if(found) mState = SEND_DATA; @@ -102,8 +104,6 @@ class PubMqttIvData { pubData &= (lastTs != mIvLastRTRpub[mIv->id]); if (pubData) { - mIvLastRTRpub[mIv->id] = lastTs; - //for (uint8_t i = 0; i < rec->length; i++) { if(mPos < rec->length) { bool retained = false; if (mCmd == RealTimeRunData_Debug) { @@ -135,7 +135,8 @@ class PubMqttIvData { break; } } - } + } else + mIvLastRTRpub[mIv->id] = lastTs; snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); snprintf(mVal, 40, "%g", ah::round3(mIv->getValue(mPos, rec))); @@ -149,7 +150,6 @@ class PubMqttIvData { void stateSendTotals() { uint8_t fieldId; - //for (uint8_t i = 0; i < 4; i++) { if(mPos < 4) { bool retained = true; switch (mPos) { From ad9fda4e28ed0635cd5aca0431e9fc19a9837247 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 27 Apr 2023 23:14:29 +0200 Subject: [PATCH 09/10] 0.6.11 * added MqTT class for publishing all values in Arduino `loop` --- src/CHANGES.md | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 281dc784..a4d12226 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,15 +1,10 @@ -Changelog v0.6.9 +# Development Changes -* improved MqTT -* fix WiFi hostname during boot up -* improved login: only one session at the same time is possible -* fix UI: login screen for small displays; burger menu height; small modifications for import button (in setup) -* improved WiFi reconnect -* optimized performance: browser caching was improved to reduce requests from ESP -* improved NRF24 communication for more stable data transmission -* added / fixed MqTT subscription `ctrl/power/[IV-ID]` -* improved save settings -* improved UI in setup: now `.` and `,` are allowed as floating point seperator -* fix zero yield day functionality -* LEDs are now configurable to show if 1st inverter is available and if MqTT is connected -* LED are configurable to active high or low +## 0.6.11 - 2023-04-27 +* added MqTT class for publishing all values in Arduino `loop` + +## 0.6.10 - HMS +* Version available in `HMS` branch + +## 0.6.9 +* last Relaese From f67a68e852306fb16b7287231256432c42843de4 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 28 Apr 2023 23:43:00 +0200 Subject: [PATCH 10/10] 0.6.12 * improved MqTT * fix menu active item --- src/CHANGES.md | 4 ++++ src/defines.h | 2 +- src/publisher/pubMqttIvData.h | 6 ++++-- src/web/html/api.js | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index a4d12226..9f83f7e7 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.6.12 - 2023-04-28 +* improved MqTT +* fix menu active item + ## 0.6.11 - 2023-04-27 * added MqTT class for publishing all values in Arduino `loop` diff --git a/src/defines.h b/src/defines.h index 7260d766..cf9395d5 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 11 +#define VERSION_PATCH 12 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index ba4cbbbf..947cd2f4 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -92,8 +92,10 @@ class PubMqttIvData { mState = SEND_DATA; else if(mSendTotals) mState = SEND_TOTALS; - else - mState = IDLE; + else { + mSendList->pop(); + mState = START; + } } void stateSend() { diff --git a/src/web/html/api.js b/src/web/html/api.js index 13ca50b5..1dd5422e 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -78,7 +78,7 @@ function parseNav(obj) { if(i == 2) continue; var l = document.getElementById("nav"+i); - if(window.location.pathname == "/" + l.href.split('/').pop()) + if(window.location.pathname == "/" + l.href.substring(0, l.href.indexOf("?")).split('/').pop()) l.classList.add("active"); if(obj["menu_protEn"]) {