From 1859e853a0d7f85a9ca62185c0884eea79931ff4 Mon Sep 17 00:00:00 2001 From: fx2 Date: Mon, 31 Oct 2022 07:38:34 +0100 Subject: [PATCH 001/431] add nokia 5110 display --- tools/esp8266/app.cpp | 138 ++++++++++++++++++++++++++++++++++- tools/esp8266/platformio.ini | 17 +++-- 2 files changed, 147 insertions(+), 8 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 31607c0f..86de4b5f 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -12,6 +12,7 @@ #include + //----------------------------------------------------------------------------- app::app() { Serial.begin(115200); @@ -27,14 +28,140 @@ app::app() { mShouldReboot = false; } +#define ENA_NOKIA +#ifdef ENA_NOKIA +// 114181866432 +U8G2_PCD8544_84X48_1_4W_HW_SPI u8g2(U8G2_R0,5,4,16); + +void ShowInfoText( const char *txt ) +{ + /* u8g2_font_open_iconic_embedded_2x_t 'D' + 'G' + 'J' */ + u8g2.clear(); + u8g2.firstPage(); + do{ + const char *e; + const char *p = txt; + int y=10; + u8g2.setFont(u8g2_font_5x8_tr); + while(1) + { + for(e=p+1; (*e && (*e != '\n')); e++); + size_t len=e-p; + u8g2.setCursor(2,y); + String res=((String)p).substring(0,len); + u8g2.print(res); + if ( !*e ) + break; + p=e+1; + y+=12; + } + u8g2.sendBuffer(); + } while( u8g2.nextPage() ); +} + +static unsigned char bmp_arrow[] U8X8_PROGMEM = { + B00000000, B00011100, B00011100, B00001110, B00001110, B11111110, B01111111, + B01110000, B01110000, B00110000, B00111000, B00011000, B01111111, B00111111, + B00011110, B00001110, B00000110, B00000000, B00000000, B00000000, B00000000 } ; + +void DataScreen( app* main, time_t ts ) +{ +static int extra = 0; + String timeStr = main->getDateTimeStr(ts).substring(2,22); + IPAddress ip = WiFi.localIP(); + float totalYield = 0.000, totalYieldToday = 0.000, totalActual = 0.0; + char fmtText[32]; + int ucnt=0; + + for (uint8_t id = 0; id < main->mSys->getNumInverters(); id++) + { + Inverter<> *iv = main->mSys->getInverterByPos(id); + if (NULL != iv) + { + uint8_t pos; + uint8_t list[] = {FLD_PAC, FLD_YT, FLD_YD}; + + if ( !iv->isAvailable(ts) ) + continue; + + ucnt++; + + for (uint8_t fld = 0; fld < 3; fld++) + { + pos = (iv->getPosByChFld(CH0, list[fld])); + + if(fld == 1){ + totalYield += iv->getValue(pos); + } + + if(fld == 2){ + totalYieldToday += iv->getValue(pos); + } + + if(fld == 0){ + totalActual += iv->getValue(pos); + } + } + } + } + + /* u8g2_font_open_iconic_embedded_2x_t 'D' + 'G' + 'J' */ + u8g2.clear(); + u8g2.firstPage(); + do{ + if(ucnt) + { + u8g2.drawXBMP(10,0,8,17,bmp_arrow); + u8g2.setFont(u8g2_font_logisoso16_tr); + u8g2.setCursor(25,16); + sprintf(fmtText,"%3.0f",totalActual); + u8g2.print(String(fmtText)+F(" W")); + u8g2.drawHLine(2,20,78); + u8g2.setFont(u8g2_font_5x8_tr); + u8g2.setCursor(5,29); + sprintf(fmtText,"%4.0f",totalYieldToday); + u8g2.print(F("today ")+String(fmtText)+F(" Wh")); + u8g2.setCursor(5,37); + sprintf(fmtText,"%.1f",totalYield); + u8g2.print(F("total ")+String(fmtText)+F(" kWh")); + } + else + { + u8g2.setFont(u8g2_font_logisoso16_tr); + u8g2.setCursor(30,30); + u8g2.print(F("off")); + u8g2.setFont(u8g2_font_5x8_tr); + } + if ( !(extra%20) ) + { + u8g2.setCursor(5,47); + u8g2.print(ip); + } + else + { + u8g2.setCursor(0,47); + u8g2.print(timeStr); + } + + u8g2.sendBuffer(); + } while( u8g2.nextPage() ); + extra++; +} +#endif + //----------------------------------------------------------------------------- void app::setup(uint32_t timeout) { DPRINTLN(DBG_VERBOSE, F("app::setup")); +#ifdef ENA_NOKIA + u8g2.begin(); + ShowInfoText("booting..."); +#endif mWifiSettingsValid = checkEEpCrc(ADDR_START, ADDR_WIFI_CRC, ADDR_WIFI_CRC); mSettingsValid = checkEEpCrc(ADDR_START_SETTINGS, ((ADDR_NEXT) - (ADDR_START_SETTINGS)), ADDR_SETTINGS_CRC); loadEEpconfig(); + //ShowInfoText("booting...\nwifi"); mWifi->setup(timeout, mWifiSettingsValid); #ifndef AP_ONLY @@ -44,6 +171,7 @@ void app::setup(uint32_t timeout) { mWebInst = new web(this, &mSysConfig, &mConfig, &mStat, mVersion); mWebInst->setup(); + //ShowInfoText("booting...\nwifi\n \ndone"); } //----------------------------------------------------------------------------- @@ -70,7 +198,15 @@ void app::loop(void) { mUtcTimestamp = mWifi->getNtpTime(); DPRINTLN(DBG_INFO, F("[NTP]: ") + getDateTimeStr(mUtcTimestamp) + F(" UTC")); } - +#ifdef ENA_NOKIA +static int lcnt=0; + if ( lcnt == 150000 ) + { + DataScreen(this, mTimestamp); + lcnt=0; + } + lcnt++; +#endif if (mFlagSendDiscoveryConfig) { mFlagSendDiscoveryConfig = false; sendMqttDiscoveryConfig(); diff --git a/tools/esp8266/platformio.ini b/tools/esp8266/platformio.ini index d9770802..226fa49b 100644 --- a/tools/esp8266/platformio.ini +++ b/tools/esp8266/platformio.ini @@ -32,16 +32,19 @@ extra_scripts = pre:html/convert.py lib_deps = - https://github.com/yubox-node-org/ESPAsyncWebServer + https://github.com/yubox-node-org/ESPAsyncWebServer nrf24/RF24 paulstoffregen/Time knolleary/PubSubClient bblanchon/ArduinoJson - ;esp8266/DNSServer - ;esp8266/EEPROM - ;esp8266/ESP8266WiFi - ;esp8266/SPI - ;esp8266/Ticker + olikraus/U8g2 + ;esp8266/DNSServer@1.1.0 + ;esp8266/EEPROM@^1.0 + ;esp8266/ESP8266HTTPUpdateServer@^1.0 + ;esp8266/ESP8266WebServer@^1.0 + ;esp8266/ESP8266WiFi@^1.0 + ;esp8266/SPI@1.0 + ;esp8266/Ticker@^1.0 [env:esp8266-release] platform = espressif8266 @@ -63,7 +66,7 @@ monitor_filters = ;default ; Remove typical terminal control codes from input time ; Add timestamp with milliseconds for each new line log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory - + [env:esp8266-1m-release] platform = espressif8266 board = esp8285 From 81fda86ef7628b6eb2b0d1c6088e514a52940189 Mon Sep 17 00:00:00 2001 From: fx2 Date: Mon, 31 Oct 2022 09:32:17 +0100 Subject: [PATCH 002/431] adapt main-changes fro nokia5110 functions --- tools/esp8266/app.cpp | 22 ++++++++++++---------- tools/esp8266/platformio.ini | 8 ++++---- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 86de4b5f..9240d36b 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -11,6 +11,7 @@ #include "app.h" #include +#include //----------------------------------------------------------------------------- @@ -64,42 +65,43 @@ static unsigned char bmp_arrow[] U8X8_PROGMEM = { B01110000, B01110000, B00110000, B00111000, B00011000, B01111111, B00111111, B00011110, B00001110, B00000110, B00000000, B00000000, B00000000, B00000000 } ; -void DataScreen( app* main, time_t ts ) +void DataScreen( app* mApp, time_t ts ) { static int extra = 0; - String timeStr = main->getDateTimeStr(ts).substring(2,22); + String timeStr = mApp->getDateTimeStr(ts).substring(2,22); IPAddress ip = WiFi.localIP(); float totalYield = 0.000, totalYieldToday = 0.000, totalActual = 0.0; char fmtText[32]; int ucnt=0; - for (uint8_t id = 0; id < main->mSys->getNumInverters(); id++) + for (uint8_t id = 0; id < mApp->mSys->getNumInverters(); id++) { - Inverter<> *iv = main->mSys->getInverterByPos(id); + Inverter<> *iv = mApp->mSys->getInverterByPos(id); if (NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); uint8_t pos; uint8_t list[] = {FLD_PAC, FLD_YT, FLD_YD}; - if ( !iv->isAvailable(ts) ) + if ( !iv->isProducing(ts,rec) ) continue; ucnt++; for (uint8_t fld = 0; fld < 3; fld++) { - pos = (iv->getPosByChFld(CH0, list[fld])); + pos = iv->getPosByChFld(CH0, list[fld],rec); if(fld == 1){ - totalYield += iv->getValue(pos); + totalYield += iv->getValue(pos,rec); } if(fld == 2){ - totalYieldToday += iv->getValue(pos); + totalYieldToday += iv->getValue(pos,rec); } if(fld == 0){ - totalActual += iv->getValue(pos); + totalActual += iv->getValue(pos,rec); } } } @@ -202,7 +204,7 @@ void app::loop(void) { static int lcnt=0; if ( lcnt == 150000 ) { - DataScreen(this, mTimestamp); + DataScreen(this, mUtcTimestamp); lcnt=0; } lcnt++; diff --git a/tools/esp8266/platformio.ini b/tools/esp8266/platformio.ini index 226fa49b..f3a7bf2e 100644 --- a/tools/esp8266/platformio.ini +++ b/tools/esp8266/platformio.ini @@ -50,7 +50,7 @@ lib_deps = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = -D RELEASE +build_flags = -D RELEASE -DU8X8_NO_HW_I2C monitor_filters = ;default ; Remove typical terminal control codes from input time ; Add timestamp with milliseconds for each new line @@ -60,7 +60,7 @@ monitor_filters = platform = espressif8266 board = esp12e 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 -DU8X8_NO_HW_I2C build_type = debug monitor_filters = ;default ; Remove typical terminal control codes from input @@ -72,7 +72,7 @@ platform = espressif8266 board = esp8285 board_build.ldscript = eagle.flash.1m64.ld board_build.f_cpu = 80000000L -build_flags = -D RELEASE +build_flags = -D RELEASE -DU8X8_NO_HW_I2C monitor_filters = ;default ; Remove typical terminal control codes from input time ; Add timestamp with milliseconds for each new line @@ -83,7 +83,7 @@ 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 -DU8X8_NO_HW_I2C build_type = debug monitor_filters = ;default ; Remove typical terminal control codes from input From 9e570a2bf20d0a039a2b5012f344201a9f5f7323 Mon Sep 17 00:00:00 2001 From: fx2 Date: Mon, 31 Oct 2022 11:00:16 +0100 Subject: [PATCH 003/431] a pcb for this setup --- .../JLCPCB_Gerber_PCB_ahoy-dtu_2022-10-31.zip | Bin 0 -> 45402 bytes tools/pcb-nokia5110/Nokia5110-LCD.jpg | Bin 0 -> 17913 bytes tools/pcb-nokia5110/readme.md | 13 +++++++++++++ 3 files changed, 13 insertions(+) create mode 100644 tools/pcb-nokia5110/JLCPCB_Gerber_PCB_ahoy-dtu_2022-10-31.zip create mode 100644 tools/pcb-nokia5110/Nokia5110-LCD.jpg create mode 100644 tools/pcb-nokia5110/readme.md diff --git a/tools/pcb-nokia5110/JLCPCB_Gerber_PCB_ahoy-dtu_2022-10-31.zip b/tools/pcb-nokia5110/JLCPCB_Gerber_PCB_ahoy-dtu_2022-10-31.zip new file mode 100644 index 0000000000000000000000000000000000000000..f19f68a6ce38a52a0a7717de2fd4ce2f2a28ca32 GIT binary patch literal 45402 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�!N{3q0(QSmP* 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 Date: Mon, 31 Oct 2022 11:12:38 +0100 Subject: [PATCH 004/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index 36cd8319..7f95f542 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -6,8 +6,8 @@ attached zip was created with easyeda. You can order easyly on jlcpcb.com. Attention: Be sure you have the right type of nokia-display-pcb ! Check pin-header-description (There are different versions avail)! -( check picture ) -PIN1: VCC -![img](https://github.com/gh-fx2/ahoy/tree/nokia5110/tools/pcb-nokia5110/Nokia5110-LCD.jpg) +( check picture : LIGHT (or BL) is placed between GND and VCC ) -You can use this PCB also without mounting a Nokia-display on backside ! \ No newline at end of file +![img](https://github.com/gh-fx2/ahoy/tools/nokia5110/tools/pcb-nokia5110/Nokia5110-LCD.jpg) + +You can use this PCB also without mounting a Nokia-display on backside ! From 12a60c21a04c0b2b57dd3d2bec5a78b7d5d68eef Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:13:20 +0100 Subject: [PATCH 005/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index 7f95f542..677c9934 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -8,6 +8,6 @@ Attention: Be sure you have the right type of nokia-display-pcb ! Check pin-header-description (There are different versions avail)! ( check picture : LIGHT (or BL) is placed between GND and VCC ) -![img](https://github.com/gh-fx2/ahoy/tools/nokia5110/tools/pcb-nokia5110/Nokia5110-LCD.jpg) +![img](https://github.com/gh-fx2/ahoy/tree/nokia5110/tools/pcb-nokia5110/Nokia5110-LCD.jpg) You can use this PCB also without mounting a Nokia-display on backside ! From fb1220f41cc1a5b5a830ee10a00fe493dbbf9356 Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:18:43 +0100 Subject: [PATCH 006/431] Add files via upload --- tools/pcb-nokia5110/Nokia5110-LCD2.jpg | Bin 0 -> 15019 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tools/pcb-nokia5110/Nokia5110-LCD2.jpg diff --git a/tools/pcb-nokia5110/Nokia5110-LCD2.jpg b/tools/pcb-nokia5110/Nokia5110-LCD2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..779c97d74f6aabca4bd6963a877713028292220f GIT binary patch literal 15019 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 Date: Mon, 31 Oct 2022 11:21:10 +0100 Subject: [PATCH 007/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index 677c9934..d91241fc 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -9,5 +9,8 @@ Check pin-header-description (There are different versions avail)! ( check picture : LIGHT (or BL) is placed between GND and VCC ) ![img](https://github.com/gh-fx2/ahoy/tree/nokia5110/tools/pcb-nokia5110/Nokia5110-LCD.jpg) +or +(Nokia5110-LCD2.jpg) + You can use this PCB also without mounting a Nokia-display on backside ! From 58833a8d23b2b9943062d96f6011ff917040fff7 Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:21:45 +0100 Subject: [PATCH 008/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index d91241fc..5043c0dc 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -10,7 +10,7 @@ Check pin-header-description (There are different versions avail)! ![img](https://github.com/gh-fx2/ahoy/tree/nokia5110/tools/pcb-nokia5110/Nokia5110-LCD.jpg) or -(Nokia5110-LCD2.jpg) +![img](Nokia5110-LCD2.jpg) You can use this PCB also without mounting a Nokia-display on backside ! From 60dbf56370b43cf6963bf8b7d0b2d6ec5a7a5e71 Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:22:09 +0100 Subject: [PATCH 009/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index 5043c0dc..ab68b932 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -8,9 +8,7 @@ Attention: Be sure you have the right type of nokia-display-pcb ! Check pin-header-description (There are different versions avail)! ( check picture : LIGHT (or BL) is placed between GND and VCC ) -![img](https://github.com/gh-fx2/ahoy/tree/nokia5110/tools/pcb-nokia5110/Nokia5110-LCD.jpg) -or -![img](Nokia5110-LCD2.jpg) +![img]Nokia5110-LCD.jpg) or ![img](Nokia5110-LCD2.jpg) You can use this PCB also without mounting a Nokia-display on backside ! From 5808dca7b726475030ceff2794dfe70295e96584 Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:22:24 +0100 Subject: [PATCH 010/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index ab68b932..6d20a859 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -8,7 +8,7 @@ Attention: Be sure you have the right type of nokia-display-pcb ! Check pin-header-description (There are different versions avail)! ( check picture : LIGHT (or BL) is placed between GND and VCC ) -![img]Nokia5110-LCD.jpg) or ![img](Nokia5110-LCD2.jpg) +![img](Nokia5110-LCD.jpg) or ![img](Nokia5110-LCD2.jpg) You can use this PCB also without mounting a Nokia-display on backside ! From 4d945f2ad4344d06e7f50cefe973f247c056fad7 Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:29:30 +0100 Subject: [PATCH 011/431] Add files via upload --- tools/pcb-nokia5110/PCB-V1.jpg | Bin 0 -> 185294 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tools/pcb-nokia5110/PCB-V1.jpg diff --git a/tools/pcb-nokia5110/PCB-V1.jpg b/tools/pcb-nokia5110/PCB-V1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fbf2345011b0bee4ef641fb0756096893a909e02 GIT binary patch literal 185294 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 p!JBjc2lZ2tC<#WyrforH6d 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 z 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 L4yu> Date: Mon, 31 Oct 2022 11:37:09 +0100 Subject: [PATCH 012/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index 6d20a859..6a3103f2 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -1,14 +1,23 @@ # PCB for Wemos D1 + Nokia5110-display + nRF24L01+ -Simple pcb to plug a nRF24L01+ together with a Wemos D1 Mini / Pro and a NOKIA5110-display (known as PCD8544). You can power this pcb via USB-interface of D1-mini. +Simple pcb to plug a nRF24L01+ together with a Wemos D1 Mini / Pro and a NOKIA5110-display (known as PCD8544). +One goal : You can power this pcb via USB-interface of D1-mini. attached zip was created with easyeda. You can order easyly on jlcpcb.com. -Attention: Be sure you have the right type of nokia-display-pcb ! +**Attention**: Be sure you have the right type of nokia-display-pcb ! Check pin-header-description (There are different versions avail)! ( check picture : LIGHT (or BL) is placed between GND and VCC ) ![img](Nokia5110-LCD.jpg) or ![img](Nokia5110-LCD2.jpg) +--- -You can use this PCB also without mounting a Nokia-display on backside ! +A picture of earlier version of pcb. + +![img](PCB-V1.jpg) + +D1-mini and NRF placed on front side, nokia display will soldered bottom. +You can use this PCB also without mounting a Nokia-display. + +Actual version of PCB has mounting holes and additional 5V/Gnd -pin access. From e34406527163f59a2fe56ba61b4bbdf106f87942 Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:38:11 +0100 Subject: [PATCH 013/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index 6a3103f2..d98a3d38 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -5,7 +5,8 @@ One goal : You can power this pcb via USB-interface of D1-mini. attached zip was created with easyeda. You can order easyly on jlcpcb.com. -**Attention**: Be sure you have the right type of nokia-display-pcb ! +###### __Attention__ +Be sure you have the right type of nokia-display-pcb ! Check pin-header-description (There are different versions avail)! ( check picture : LIGHT (or BL) is placed between GND and VCC ) From 453e6985359e0b365a4cc13c050a434cce088fd8 Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:39:43 +0100 Subject: [PATCH 014/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index d98a3d38..d85bc731 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -5,7 +5,7 @@ One goal : You can power this pcb via USB-interface of D1-mini. attached zip was created with easyeda. You can order easyly on jlcpcb.com. -###### __Attention__ +## Attention Be sure you have the right type of nokia-display-pcb ! Check pin-header-description (There are different versions avail)! ( check picture : LIGHT (or BL) is placed between GND and VCC ) From ef72fe9a40f091cbd57346885acb74d799da6974 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 31 Oct 2022 23:01:47 +0100 Subject: [PATCH 015/431] fix sync time from browser issue --- tools/esp8266/defines.h | 2 +- tools/esp8266/webApi.cpp | 27 ++++++++++++++------------- tools/esp8266/webApi.h | 6 +++--- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index 3acb352a..2f408e3e 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 28 +#define VERSION_PATCH 29 //------------------------------------- typedef struct { diff --git a/tools/esp8266/webApi.cpp b/tools/esp8266/webApi.cpp index 1c52e81f..f2fb8678 100644 --- a/tools/esp8266/webApi.cpp +++ b/tools/esp8266/webApi.cpp @@ -80,14 +80,15 @@ void webApi::onApiPostBody(AsyncWebServerRequest *request, uint8_t *data, size_t AsyncJsonResponse* response = new AsyncJsonResponse(false, 200); JsonObject root = response->getRoot(); - DeserializationError err = deserializeJson(json, (const char *)data); + DeserializationError err = deserializeJson(json, (const char *)data, len); + JsonObject obj = json.as(); root[F("success")] = (err) ? false : true; if(!err) { String path = request->url().substring(5); if(path == "ctrl") - root[F("success")] = setCtrl(json, root); + root[F("success")] = setCtrl(obj, root); else if(path == "setup") - root[F("success")] = setSetup(json, root); + root[F("success")] = setSetup(obj, root); else { root[F("success")] = false; root[F("error")] = "Path not found: " + path; @@ -400,21 +401,21 @@ void webApi::getRecord(JsonObject obj, record_t<> *rec) { //----------------------------------------------------------------------------- -bool webApi::setCtrl(DynamicJsonDocument jsonIn, JsonObject jsonOut) { +bool webApi::setCtrl(JsonObject jsonIn, JsonObject jsonOut) { uint8_t cmd = jsonIn[F("cmd")]; // Todo: num is the inverter number 0-3. For better display in DPRINTLN - uint8_t num = jsonIn[F("inverter")]; - uint8_t tx_request = jsonIn[F("tx_request")]; + uint8_t num = jsonIn[F("inverter")]; + uint8_t tx_request = jsonIn[F("tx_request")]; - if(TX_REQ_DEVCONTROL == tx_request) + if(TX_REQ_DEVCONTROL == tx_request) { DPRINTLN(DBG_INFO, F("devcontrol [") + String(num) + F("], cmd: 0x") + String(cmd, HEX)); - + Inverter<> *iv = getInverter(jsonIn, jsonOut); JsonArray payload = jsonIn[F("payload")].as(); - if(NULL != iv) + if(NULL != iv) { switch (cmd) { @@ -443,7 +444,7 @@ bool webApi::setCtrl(DynamicJsonDocument jsonIn, JsonObject jsonOut) { default: jsonOut["error"] = "unknown 'cmd' = " + String(cmd); return false; - } + } } else { return false; } @@ -458,8 +459,8 @@ bool webApi::setCtrl(DynamicJsonDocument jsonIn, JsonObject jsonOut) { //----------------------------------------------------------------------------- -bool webApi::setSetup(DynamicJsonDocument jsonIn, JsonObject jsonOut) { - if(F("scan_wifi")) +bool webApi::setSetup(JsonObject jsonIn, JsonObject jsonOut) { + if(F("scan_wifi") == jsonIn[F("cmd")]) mApp->scanAvailNetworks(); else if(F("set_time") == jsonIn[F("cmd")]) mApp->setTimestamp(jsonIn[F("ts")]); @@ -479,7 +480,7 @@ bool webApi::setSetup(DynamicJsonDocument jsonIn, JsonObject jsonOut) { //----------------------------------------------------------------------------- -Inverter<> *webApi::getInverter(DynamicJsonDocument jsonIn, JsonObject jsonOut) { +Inverter<> *webApi::getInverter(JsonObject jsonIn, JsonObject jsonOut) { uint8_t id = jsonIn[F("inverter")]; Inverter<> *iv = mApp->mSys->getInverterByPos(id); if(NULL == iv) diff --git a/tools/esp8266/webApi.h b/tools/esp8266/webApi.h index a45dcf8e..f44d1f3b 100644 --- a/tools/esp8266/webApi.h +++ b/tools/esp8266/webApi.h @@ -49,10 +49,10 @@ class webApi { void getLive(JsonObject obj); void getRecord(JsonObject obj, record_t<> *rec); - bool setCtrl(DynamicJsonDocument jsonIn, JsonObject jsonOut); - bool setSetup(DynamicJsonDocument jsonIn, JsonObject jsonOut); + bool setCtrl(JsonObject jsonIn, JsonObject jsonOut); + bool setSetup(JsonObject jsonIn, JsonObject jsonOut); - Inverter<> *getInverter(DynamicJsonDocument jsonIn, JsonObject jsonOut); + Inverter<> *getInverter(JsonObject jsonIn, JsonObject jsonOut); double round3(double value) { return (int)(value * 1000 + 0.5) / 1000.0; From 56b8096beddf6ec20012de9be8c2b5e91eb8ed1c Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 1 Nov 2022 01:22:39 +0100 Subject: [PATCH 016/431] updated mqtt counter --- tools/esp8266/mqtt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/esp8266/mqtt.h b/tools/esp8266/mqtt.h index 6f6e997e..1d687d77 100644 --- a/tools/esp8266/mqtt.h +++ b/tools/esp8266/mqtt.h @@ -53,7 +53,6 @@ class mqtt { char top[64]; snprintf(top, 64, "%s/%s", mCfg->topic, topic); sendMsg2(top, msg, false); - mTxCnt++; } void sendMsg2(const char *topic, const char *msg, boolean retained) { @@ -63,6 +62,7 @@ class mqtt { if(mClient->connected()) mClient->publish(topic, msg, retained); } + mTxCnt++; } bool isConnected(bool doRecon = false) { From 04b98c3537fc1a2848309e8a678d91ee20ba8ca3 Mon Sep 17 00:00:00 2001 From: fx2 Date: Tue, 1 Nov 2022 13:00:33 +0100 Subject: [PATCH 017/431] comment - second WR-num --- tools/esp8266/app.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 9240d36b..23a696e7 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -32,6 +32,7 @@ app::app() { #define ENA_NOKIA #ifdef ENA_NOKIA // 114181866432 +// 114181809192 U8G2_PCD8544_84X48_1_4W_HW_SPI u8g2(U8G2_R0,5,4,16); void ShowInfoText( const char *txt ) From 1ab4a9e7012e1faf9d117e32082a4b6da56d7f93 Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Tue, 1 Nov 2022 13:03:18 +0100 Subject: [PATCH 018/431] Add files via upload --- tools/pcb-nokia5110/1_Front.jpg | Bin 0 -> 143602 bytes tools/pcb-nokia5110/2_Bottom.jpg | Bin 0 -> 44150 bytes tools/pcb-nokia5110/3_booting.jpg | Bin 0 -> 237179 bytes tools/pcb-nokia5110/4_runIP.jpg | Bin 0 -> 291750 bytes tools/pcb-nokia5110/5_runTime.jpg | Bin 0 -> 258781 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tools/pcb-nokia5110/1_Front.jpg create mode 100644 tools/pcb-nokia5110/2_Bottom.jpg create mode 100644 tools/pcb-nokia5110/3_booting.jpg create mode 100644 tools/pcb-nokia5110/4_runIP.jpg create mode 100644 tools/pcb-nokia5110/5_runTime.jpg diff --git a/tools/pcb-nokia5110/1_Front.jpg b/tools/pcb-nokia5110/1_Front.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a7f8ece1d1c13bda645acb434725285b898a6000 GIT binary patch literal 143602 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 z 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

P4FN}>nz-}`F4Qvqc^(PezATgn!&9td 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 literal 0 HcmV?d00001 diff --git a/tools/pcb-nokia5110/2_Bottom.jpg b/tools/pcb-nokia5110/2_Bottom.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fa49c968825ed9669ba0694a9f74143c72639a59 GIT binary patch literal 44150 zcmbSz2_RHk{QsRXqcNq1EJe%E5RyuhUi;XMC_61AsfbChqX`1J?l~ zkw};me6Y?AY_RR>rHdn%1~b=%MuspQxvp-VPspdawziAhJmxxZUF@MZhLMHgOL%K2 z<1vi4GIF(tqYcw<-h5`i7g&Fc1b-8;0gIQcS!M0!=7RmS$o_)9Q0|RISU>Id;~VP1 zOV=#HFcK4PbC#@H9SQY7s9UXzT!rfUpsuwfWN|RmPe9##H82SEN2ooBs5hhfa=cE4 zDyFsC%fl9A(}Fs4d5?NfkNT33)ja6KhCZxd-b%nH`w{hERNsW^yzsTa8(xrv1D3Az z_JlJF{)SefcrK-q1VId-GC|xs6w$NKw*bP zU_5LwPLClQKp!aGx?Qtuq9xu$8eoHA)PFiVKN?|JzjO?1PwniKAMEUG&%rR2zcK9M z%5M4yA%^|(8QN33+gJxMY|vH=6J70Y3)+ieCEGDR|ui*bS?99PcbWzJLGm&TpM}JO7sjKu8;6V~_6v+S30e&3D}{V;VFng>p=V zq=At&NGckn&a0R%iZ~L|Lsub@Rp5rsckLL7+}VH)P$6Mth6)25_%x7E4V*9oXAa4U z&glZcFoux0(Bi|H1kr3t;%EU06{DC_p#>bAp~YZggR(GbK!uTfj69$v53oq|JPbypb3Dj=8$N(y7|jEtqtPIWpf6FV z7_uT}bD6K6N5=SC@suM%K4x~2xZ8aMb{GJLU~E!_-R*ddtmn!fFm%4Uv9n)1K%0&+ zGtJ90*o|Q(1{}OYw-kLSyDx1+=Y*z)ygFxjrf!X^g^)z2(VcHJu`>-^sV{^`pLw7v z4im}bfqCG%0%A8@FdIIStGkd$o(HQKF(Q9vtNe61Z6s?+HjtnQf*-P8i}ap)Yz+sbo(^z! zR3`b%8n)lC*ZEbtW`N^z5c>L)<8TfU8Ht0AP$+!Rgd4bp()>0W4);_&QnmE^>xNdd zOLxqt0dHplPn+I3lUjF?e34}B$pohpV$NN>sX1X_PZOreQD85PL&3Vd48zQ>u-L0H z=J36AE5sT`qjSvSI73ew4?KRWHjkl&(P%=}Qmyzn zofZR>@;{Y4vyb4NbW;Ti4N!!krZjtPt2kVjC~n;dM~eSB7Tx9)lg!8RtiTU~QiXhM z46>JJ2u?w=1`r5&xKM`ukC4nhKqtETVOHHEVLTI~-{51IR|BC^DjqY;ZZaG!j|wdw z7zsrJ=8*vha_aFa6R_*RomI6*$Xa~NIRWtz3dra#9}Xm1FglST{DII7+!(G%U7i%r zMog1WF@+FaQ%AGFMDgGX1T%043Jzu&T+M-zY|yBE3k@@H0EQV>b zGYCDBtN~{m4F-msl!x_DE)jcf9DudahcW2q=S3=n zRi7e+yaY}BS|JC+)$3-Pv)a`n2eY-qRFIc=)pOf{PGxCL1YNi}C9BPHCLmJ1}||BTOZQfgl4_e~f{m1*5V_xVLFB>H=#6!4(X`%z$F5C89%x7JLYu z$mr0wQ1NCxDh0V3Oq$5?|35KIa16)>qbCMo#36Dt!K+XqZ!vbp zy`G6*_Br5FI7#TeqYEPrG98(o0R5&KDATElK^$&a4rYS!`yePn(ID5Fi(3{`KRikZ zooHsrvl_gV-Bsy`3-D-Md&*YDS%_;xkrh=!t6njIae4xkz0VCnC|5FpxNq=(7`JGR zhml~CL|Go2I(jh9gj&d9yGxj1@*xg1;zfax_d`Ck_|RwD4I7l@VJaE8^Xe-m05gqp z_7A3D30APW!i!csp%I7~BEKuzl_w9Vko8Rr)W<BeB<*FQKIoF=JTc+yRU!SSZL zp;eDiUS)V&3N!fIIZFG`IY==y$kLo2AmB~3aLjggI@K)Pd^~+=)bEf2Af;11&0O_d zGTl#m#S?T?3T|nB-uG#~3wYZ_3j5snNGDtSg_)+i>jHrzjAY_zWEpZ)cXUsdga{?C zi>^n71S@$c+Y*pyWAgZi`~qutH>|N@LPp+t(8)&MEI83sTS-6**1}y(ajo)FU#*{;#P>2&1=EitM9W9Mv zPB9>$D42F+roXZJ4(P~Okay9l_C@6IGzcs!N;=ah_ix~d>EU}x3esEbj^ zlasF-y2YMPuynuPDX{ukuAUj-=#lSAtx^S`Rp@zAZNZfN zPMM~Mo`rYC{eL4thDS^Z>vz8hrJ5e979bC}2*asNs;NHng!Je}oSSm+VF@1mAFk3+ z2ei6Z@U%=|aoM{%-2s^Tm5%bv?qcJ638`xhcfiIDUbOiCiN!$+WyDp(vlk(J#=*#a z{`u-xO(4sVeeNvxG#>15XZGm~1s3=d8^&NLF8iElZumZgo`Ewc%ib!~@NuGZa6=$+ z1P=fU^IU4UcyUjx|8NBkWU5rM9+M4F)?AJ|ZogF+Jh}6C7iYy`s+Se2B02q+(uvft zZHLE}u=LdVSxi4qZai>=HWYxP6>8R`BI6wjBor(^_f233!wiaWdDbR@l4cWWN zMLV~j%|5ngT29y6hVW0E1d;VBO#F%#5^rL)bc4#Wq}0T`e4o5Ys1>w+lpV5-Bvi&R za&$MewcEEqSimzGUKB`FZ4@fTw2{26GrMLX;~>P`D+` ziiEv!SjxD!!u@q%AmUIwPGq_+~m|UD{^|QHD8FLz$9g)-7X| z9wub;Bm|B1x+H-1u}NAXM{##B;23bgA94;Ekc2%lXsi%l?|0GCVBy8-x`GPm$`rzR zu|1V)wm2$t5<>_pIB?M;6s)HSnIT=;C8$Zgaq&p5)lKz3M6oQj-u-IdB(zlwNj)n$ ze@Ec91Z5=C+*YgdyOoQudJBfA%6er4lU97bYyNE5VoDODmes3Q@y*Nrt;*3MtKZ|6i9tsFX z$v}WaV+ehAE%zAW%v)t^j}w?cDD*KM^y&>oNN4{dlwx{z*h6mot4szw)i6!_dsWvw z+2T-j&NL4Zpk2B?e8JOVuRMTy=^5mxEOQx)HPHU_&-V?Dy9k^43@z{RYp1Z-;fW+1 zN{FVU-XeBQ34oy}20406tKb)92I`q45#b3UwGUhiW7 zM--}dE)yOWLlx|h`mn=LPEzQ;qHNpYrk?4Cei{O8n{$8}nupIVJ>WozV#**vw(L=0 zGU!{hkWdSUyPY$23apKPwa=UcGr9qH!T3mwJQR--d}p-}(04fi7Rjkb}IriKqNR@XQCh#V8_hGBV} z-j)N}K8YN5QY=Bp^!^@WP3dWoi=$FG7*f`J%Seie;o?ZhPB>D&M^7KO>0b2Xj*G_X z@^Opgp|H7(!Ub*N8iiasjTxwG!+n?`dW%QaA~wnqagVaC$^#`QH>!bazHTT5LwgCk zb6_!NfCfVfr@#u4(?tP6*;VhV7zhDGhmTP$VNQWxuJTMUulaGXF@!Lv@W(RgncnzX z{4Ub23h2g7{r5d4LfDD~48(^IC`5&e3k|KkFqo!&b&CTT6dPgn)j>7D`Kvp2XlUwE z4u-L_;DB^XPwf%%WUY86H1{odR$C2^T3BxQCG^_^X&xw3-8dCGBCp~1@IMZ;eP3{w z`8`7jT!_bW(73z7IK3q4n#oAtlfy8nxTnT_5pQG<-RhL_tw!%53hjpwcvvd=pkSErzZ8moDE<)}#l}0-hus%~E|F0H zL(LufbsNR5hf#iL5|r~4qL`@UPGNu@XzmKDpa)-YQwZg%5XIm>Vghb`hk0Wr)t$YElnflE;qK!uMVi9@%)(cmX&YTaU-lkiLMLk7Pa1SS_c z84`iYz8_(9!|`iL*1Dnb3E&*+#T5LfR7LQU0S;Q@w6FpDlxc{G2~lI8!q8({qHd{hU@$NaSQoFuJPOa#AS%uT4gKbe0Cn;fjx})RXww@s z7|4>lwLH1j1E_VOFg9NZ7^nb-sR3jakOD1HO)wP)XZ!{qj`5hb9hFH1iP@P8EfO+} z7G`=R=gnrofY@$bZn0W=;PG4eH5kRPE{_RX<%1|taM=jwr6OYq@weFEhzk6S!wYbVR{w+|esmuvF!M8B7eELe1RZ zwIk1Ex*-gZnyxl~{0gHCEaY+}&~K|pAWNMwK05a(AfDO(5C$IAyRcI+I*sIH-=mcc^GL9H7&k8!qK~iU{@ZB7 zECc7@1n5F_B6)GV7$!ehY@i=9-Fm{4vz8lk*xonxhI(*7Ebz_zI)+v?VuvX3BG>;^ zw2pdU=e&;9d2yg8*~`t$Lj%=_@&hK6x4O@!SjHG63EIv^^K_4bhax#+E7imRwqvN^ z>c|yUIPmCC_$1+xAeSHcF9AnE2?lZ#f~b&}Jm!(Cb5(QuThk#p8hESMsMXY1p1-XR zJ;w*v=P)k9LMw0Tk&7nSHZHhMJVFqnyo8LUEU^5>jNCYGHdlpIuA83efUKmk7@2$s z8#-xTKc`wyoEw-Sj&Vsd9+qvcT8G@Q>QoP~7o-T3#PIBhPVmwm2Z8d*-aGoc<(bDB%ngM7UcEm4Un{JbuM|G)z-RXc;-)+ z{k~ZP6RX)aaYNaGuWjw%l{^efz*LNP*cz!hd26uO5Ug^{gbgn+f0EIj+!->?n4ZMDWq7+4n!$iJNOI0TP837p{S(*xp$yXhKx zI!>iE>wq2rTw$kpDhPz~2NY8TO@>F9Et7%}(~y<9Zg|dD`Sn&q>=v%Np6S5R_Q03;iKWe9Zx!Rgj#K{*eywGbx{X7|gz@090GJ9})JXk+mkNqN#mG=654k#+pPT`+ zmg=0sxFbW^880H)!Oucofv=kwex$MoXkbG6-)jnL=~^UGEZE+_8id5KJisLiaE=!> zr`>_z7?gt^URbTV1BXgAy;15Aw#s0O!;0af9LL)(p)n-^oWyZz(@?W!&?zjK@mUbL2of2&J<2>tp?sQ|7F?1Ko)K=J3ZR9Sw2*3_ z{4uN8n8BU2Vz@;Cru;~Q$p@`TcFx!ecIaxaY9sJepoT)?AT(4UAD~kg;x>3hIeBf& zuc^+3#m0L^Pkl2)h~)da76G_ z{L0%^MLYdh6S%w|bOs(ajr0uiFpe8Xi;VS8cd$0+lT%e3a@iE~c^t@eh!;H0a5R{z z@=yarGXtHeWDh)SIW!NQJa4p`L4_fVtAZ1qr0ⅇz2Nm5Xsf6&^Z_dHIO(Y^llx@ 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 TGtLY!Y+mPMH*Y-rIrIMjq3bbf literal 0 HcmV?d00001 diff --git a/tools/pcb-nokia5110/3_booting.jpg b/tools/pcb-nokia5110/3_booting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c7f96fd45393c1183436daa9adab763cd87c7616 GIT binary patch literal 237179 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

(IsVSF&?L0Vj^NNevJSb!au+fpCuXyRp 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 z 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�l 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

|0uJs2NsBId7KtxA{HxfDVJz1x@ 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%0DN%}k$v#PgBkm2+sbWp3)er~VL3P=3! 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 literal 0 HcmV?d00001 From 0d8189a911668625197c9724033cce969b99e3b0 Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Tue, 1 Nov 2022 13:08:26 +0100 Subject: [PATCH 019/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index d85bc731..24f28b3e 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -22,3 +22,20 @@ D1-mini and NRF placed on front side, nokia display will soldered bottom. You can use this PCB also without mounting a Nokia-display. Actual version of PCB has mounting holes and additional 5V/Gnd -pin access. + +## after soldering ... + +![img](1_Front.jpg) +NRF & Wemos on Front + +![img](2_Bottom.jpg) +Nokia Display soldered on bottom side + +![img](3_booting.jpg) +while booting (wait for wifi, 1st data, ...) + +![img](4_runIP.jpg) +1st screen show most interesting info and IP in bottom line + +![img](5_runTime.jpg) +this is the normal screen with time in bottom line (refresh all 5 seconds) From 7208f77968ec92bfd6e21d46697cb4646bea70b1 Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Tue, 1 Nov 2022 13:11:17 +0100 Subject: [PATCH 020/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index 24f28b3e..6b5a4e9d 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -39,3 +39,7 @@ while booting (wait for wifi, 1st data, ...) ![img](5_runTime.jpg) this is the normal screen with time in bottom line (refresh all 5 seconds) + +## next step + +Next step is creating a 3D printed case ... but this is a task for dark days in december. From e8aa683b8be90d5e9ea1a60495f240afd3970e2a Mon Sep 17 00:00:00 2001 From: fx2 <53297700+gh-fx2@users.noreply.github.com> Date: Tue, 1 Nov 2022 13:12:51 +0100 Subject: [PATCH 021/431] Update readme.md --- tools/pcb-nokia5110/readme.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/pcb-nokia5110/readme.md b/tools/pcb-nokia5110/readme.md index 6b5a4e9d..32c0ba81 100644 --- a/tools/pcb-nokia5110/readme.md +++ b/tools/pcb-nokia5110/readme.md @@ -40,6 +40,8 @@ while booting (wait for wifi, 1st data, ...) ![img](5_runTime.jpg) this is the normal screen with time in bottom line (refresh all 5 seconds) -## next step +## next step(s) + +* modbus communication interface +* 3D printed case ... but this is a task for dark days in december. -Next step is creating a 3D printed case ... but this is a task for dark days in december. From d3846b1fad931e0bac2c29163b659bad23ae84f8 Mon Sep 17 00:00:00 2001 From: fx2 Date: Wed, 2 Nov 2022 07:47:46 +0100 Subject: [PATCH 022/431] no NOKIA-code normal compilation (own task) --- tools/esp8266/app.cpp | 6 +++--- tools/esp8266/platformio.ini | 26 +++++++++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 23a696e7..46d00065 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -11,7 +11,9 @@ #include "app.h" #include +#ifdef ENA_NOKIA #include +#endif //----------------------------------------------------------------------------- @@ -29,10 +31,8 @@ app::app() { mShouldReboot = false; } -#define ENA_NOKIA #ifdef ENA_NOKIA -// 114181866432 -// 114181809192 + U8G2_PCD8544_84X48_1_4W_HW_SPI u8g2(U8G2_R0,5,4,16); void ShowInfoText( const char *txt ) diff --git a/tools/esp8266/platformio.ini b/tools/esp8266/platformio.ini index f3a7bf2e..5812edd4 100644 --- a/tools/esp8266/platformio.ini +++ b/tools/esp8266/platformio.ini @@ -37,7 +37,6 @@ lib_deps = paulstoffregen/Time knolleary/PubSubClient bblanchon/ArduinoJson - olikraus/U8g2 ;esp8266/DNSServer@1.1.0 ;esp8266/EEPROM@^1.0 ;esp8266/ESP8266HTTPUpdateServer@^1.0 @@ -50,7 +49,7 @@ lib_deps = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = -D RELEASE -DU8X8_NO_HW_I2C +build_flags = -D RELEASE monitor_filters = ;default ; Remove typical terminal control codes from input time ; Add timestamp with milliseconds for each new line @@ -60,7 +59,7 @@ monitor_filters = platform = espressif8266 board = esp12e 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 -DU8X8_NO_HW_I2C +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 @@ -72,7 +71,7 @@ platform = espressif8266 board = esp8285 board_build.ldscript = eagle.flash.1m64.ld board_build.f_cpu = 80000000L -build_flags = -D RELEASE -DU8X8_NO_HW_I2C +build_flags = -D RELEASE monitor_filters = ;default ; Remove typical terminal control codes from input time ; Add timestamp with milliseconds for each new line @@ -83,13 +82,30 @@ 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 -DU8X8_NO_HW_I2C +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 time ; Add timestamp with milliseconds for each new line log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory +[env:esp8266-nokia5110] +platform = espressif8266 +board = esp12e +board_build.f_cpu = 80000000L +build_flags = -D RELEASE -DU8X8_NO_HW_I2C -DENA_NOKIA +monitor_filters = + ;default ; Remove typical terminal control codes from input + time ; Add timestamp with milliseconds for each new line + ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory +lib_deps = + https://github.com/yubox-node-org/ESPAsyncWebServer + nrf24/RF24 + paulstoffregen/Time + knolleary/PubSubClient + bblanchon/ArduinoJson + olikraus/U8g2 + [env:esp32-wroom32-release] platform = espressif32 board = lolin_d32 From a5c0db95d3693b41a6b867a5a7ace0a927b7aa98 Mon Sep 17 00:00:00 2001 From: fx2 Date: Wed, 2 Nov 2022 13:24:32 +0100 Subject: [PATCH 023/431] unused lines removed (nokia5110) --- tools/esp8266/app.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 46d00065..9880b220 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -164,7 +164,6 @@ void app::setup(uint32_t timeout) { mSettingsValid = checkEEpCrc(ADDR_START_SETTINGS, ((ADDR_NEXT) - (ADDR_START_SETTINGS)), ADDR_SETTINGS_CRC); loadEEpconfig(); - //ShowInfoText("booting...\nwifi"); mWifi->setup(timeout, mWifiSettingsValid); #ifndef AP_ONLY @@ -174,7 +173,6 @@ void app::setup(uint32_t timeout) { mWebInst = new web(this, &mSysConfig, &mConfig, &mStat, mVersion); mWebInst->setup(); - //ShowInfoText("booting...\nwifi\n \ndone"); } //----------------------------------------------------------------------------- From 6a6d522d3be871c91643b62708f01bc5d253c1ec Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 2 Nov 2022 22:41:31 +0100 Subject: [PATCH 024/431] added login / logout prepared static IP storage and disable inverter IMPORTANT: new memory layout, your inverter settings will be lost --- tools/esp8266/app.cpp | 18 +++-- tools/esp8266/config.h | 5 ++ tools/esp8266/defines.h | 18 ++++- tools/esp8266/html/login.html | 42 +++++++++++ tools/esp8266/html/setup.html | 2 + tools/esp8266/html/style.css | 23 ++++++ tools/esp8266/html/system.html | 17 +++-- tools/esp8266/web.cpp | 129 ++++++++++++++++++++++++++++++--- tools/esp8266/web.h | 7 ++ tools/esp8266/webApi.cpp | 56 ++++++++++++-- tools/esp8266/webApi.h | 4 + 11 files changed, 290 insertions(+), 31 deletions(-) create mode 100644 tools/esp8266/html/login.html diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 31607c0f..834d9d40 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -44,6 +44,9 @@ void app::setup(uint32_t timeout) { mWebInst = new web(this, &mSysConfig, &mConfig, &mStat, mVersion); mWebInst->setup(); + mWebInst->setProtection(strlen(mConfig.password) != 0); + DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettingsValid) ? F("true") : F("false"))); + DPRINTLN(DBG_INFO, F("EEprom storage size: 0x") + String(ADDR_SETTINGS_CRC, HEX)); } //----------------------------------------------------------------------------- @@ -58,6 +61,13 @@ void app::loop(void) { mUptimeSecs++; if (0 != mUtcTimestamp) mUtcTimestamp++; + + mWebInst->tickSecond(); + + if (mShouldReboot) { + DPRINTLN(DBG_INFO, F("Rebooting...")); + ESP.restart(); + } } if (checkTicker(&mNtpRefreshTicker, mNtpRefreshInterval)) { @@ -76,11 +86,6 @@ void app::loop(void) { sendMqttDiscoveryConfig(); } - if (mShouldReboot) { - DPRINTLN(DBG_INFO, F("Rebooting...")); - ESP.restart(); - } - mSys->Radio.loop(); yield(); @@ -743,6 +748,9 @@ void app::loadDefaultConfig(void) { snprintf(mSysConfig.stationSsid, SSID_LEN, "%s", FB_WIFI_SSID); snprintf(mSysConfig.stationPwd, PWD_LEN, "%s", FB_WIFI_PWD); + // password + snprintf(mConfig.password, PWD_LEN, "%s", GUI_DEF_PASSWORD); + // nrf24 mConfig.sendInterval = SEND_INTERVAL; mConfig.maxRetransPerPyld = DEF_MAX_RETRANS_PER_PYLD; diff --git a/tools/esp8266/config.h b/tools/esp8266/config.h index 1a1555ce..f1ce5d8a 100644 --- a/tools/esp8266/config.h +++ b/tools/esp8266/config.h @@ -25,6 +25,11 @@ // If the next line is uncommented, Ahoy will stay in access point mode all the time //#define AP_ONLY +// protection of the GUI by password +#define GUI_DEF_PASSWORD "" + +// timeout for automatic logoff (20 minutes) +#define LOGOUT_TIMEOUT (20 * 60 * 60) //------------------------------------- // CONFIGURATION - COMPILE TIME diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index 2f408e3e..8ddbc7f2 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 29 +#define VERSION_PATCH 30 //------------------------------------- typedef struct { @@ -87,6 +87,7 @@ typedef enum { #define INV_CH_CH_NAME_LEN MAX_NUM_INVERTERS * MAX_NAME_LENGTH * 4 // (4 channels) #define INV_INTERVAL_LEN 2 // uint16_t #define INV_MAX_RTRY_LEN 1 // uint8_t +#define INV_ENABLED_LEN 1 // uint8_t #define CFG_SUN_LEN 9 // 2x float(4+4) + bool(1) @@ -112,6 +113,8 @@ typedef struct { #pragma pack(pop) // restore original alignment from stack +#pragma pack(push) // push current alignment to stack +#pragma pack(1) // set alignment to 1 byte boundary typedef struct { char deviceName[DEVNAME_LEN]; @@ -119,10 +122,15 @@ typedef struct { char stationSsid[SSID_LEN]; char stationPwd[PWD_LEN]; } sysConfig_t; +#pragma pack(pop) // restore original alignment from stack + #pragma pack(push) // push current alignment to stack #pragma pack(1) // set alignment to 1 byte boundary typedef struct { + // protection + char password[PWD_LEN]; + // nrf24 uint16_t sendInterval; uint8_t maxRetransPerPyld; @@ -150,6 +158,9 @@ typedef struct { uint16_t serialInterval; bool serialShowIv; bool serialDebug; + + // static ip placeholder + uint32_t staticIp[4]; } config_t; #pragma pack(pop) // restore original alignment from stack @@ -162,7 +173,7 @@ typedef struct { #define CFG_MQTT_LEN MQTT_ADDR_LEN + 2 + MQTT_USER_LEN + MQTT_PWD_LEN +MQTT_TOPIC_LEN -#define CFG_SYS_LEN DEVNAME_LEN + SSID_LEN + PWD_LEN + 1 +#define CFG_SYS_LEN DEVNAME_LEN + SSID_LEN + PWD_LEN #define CFG_LEN 7 + NTP_ADDR_LEN + 2 + CFG_MQTT_LEN + CFG_SUN_LEN + 4 + DISCLAIMER #define ADDR_START 0 @@ -179,8 +190,9 @@ typedef struct { #define ADDR_INV_CH_NAME ADDR_INV_CH_PWR + INV_CH_CH_PWR_LEN #define ADDR_INV_INTERVAL ADDR_INV_CH_NAME + INV_CH_CH_NAME_LEN #define ADDR_INV_MAX_RTRY ADDR_INV_INTERVAL + INV_INTERVAL_LEN +#define ADDR_INV_ENABLED ADDR_INV_MAX_RTRY + INV_MAX_RTRY_LEN -#define ADDR_NEXT ADDR_INV_MAX_RTRY + INV_INTERVAL_LEN +#define ADDR_NEXT ADDR_INV_MAX_RTRY + INV_ENABLED_LEN #define ADDR_SETTINGS_CRC ADDR_NEXT + 2 diff --git a/tools/esp8266/html/login.html b/tools/esp8266/html/login.html new file mode 100644 index 00000000..b8298e23 --- /dev/null +++ b/tools/esp8266/html/login.html @@ -0,0 +1,42 @@ + + + + Login + + + + + +

+ + + + diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index 44b7578a..04cdb8dd 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -36,6 +36,8 @@ Device Host Name + + diff --git a/tools/esp8266/html/style.css b/tools/esp8266/html/style.css index eab8da8a..81f01815 100644 --- a/tools/esp8266/html/style.css +++ b/tools/esp8266/html/style.css @@ -414,3 +414,26 @@ div.ModPwr, div.ModName { display: inline-block; margin-top: 15px; } + +#login { + width: 300px; + height: 200px; + border: 1px solid #ccc; + background-color: #eee; + position: absolute; + top: 50%; + left: 50%; + margin-top: -160px; + margin-left: -150px; +} + +#login .pad { + padding: 20px; +} + +#login .pad input { + width: 100%; + padding: 7px 0 7px 0; + border: 0px; + margin-bottom: 10px; +} diff --git a/tools/esp8266/html/system.html b/tools/esp8266/html/system.html index 8a2a8ccc..58daf80a 100644 --- a/tools/esp8266/html/system.html +++ b/tools/esp8266/html/system.html @@ -17,11 +17,7 @@
- +
From 04c18944e2a9cea2fe0021d990098a95cc6ca35c Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Thu, 17 Nov 2022 21:20:03 +0100 Subject: [PATCH 099/431] Increase MQTT LEN of ADDR,USER,PWD,TOPIC --- src/defines.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/defines.h b/src/defines.h index 36949daf..edbc4aed 100644 --- a/src/defines.h +++ b/src/defines.h @@ -85,9 +85,9 @@ union serial_u { #define DEVNAME_LEN 16 #define NTP_ADDR_LEN 32 // DNS Name -#define MQTT_ADDR_LEN 32 // DNS Name -#define MQTT_USER_LEN 16 -#define MQTT_PWD_LEN 32 +#define MQTT_ADDR_LEN 64 // DNS Name +#define MQTT_USER_LEN 64 +#define MQTT_PWD_LEN 64 #define MQTT_TOPIC_LEN 64 #define MQTT_MAX_PACKET_SIZE 384 From 9656e880b34900970a7165c31c98702880ea1167 Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Thu, 17 Nov 2022 21:37:03 +0100 Subject: [PATCH 100/431] remove maxlength="32" --- src/web/html/setup.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/html/setup.html b/src/web/html/setup.html index c86b7b4b..097234f5 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -127,7 +127,7 @@
MQTT - + From 0305c114cfa83eb03c75d2913868e8beb78df090 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 17 Nov 2022 22:15:50 +0100 Subject: [PATCH 101/431] improved system infos - not yet nice but informal --- src/web/html/api.js | 27 ------------------ src/web/html/system.html | 17 +++++++++++- src/web/webApi.cpp | 59 ++++++++++++++++++++++++++-------------- 3 files changed, 54 insertions(+), 49 deletions(-) diff --git a/src/web/html/api.js b/src/web/html/api.js index 3a8ad7f1..508a671d 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -31,32 +31,6 @@ function parseESP(obj) { document.getElementById("esp_type").innerHTML="Board: " + obj["esp_type"]; } -function parseSysInfo(obj) { - const data = ["sdk_version", "cpu_freq", "chip_revision", "chip_model", "chip_cores", "esp_type"]; - - var ul = document.getElementById("info"); - - if(!isNaN(obj["heap_total"])) { - document.getElementById("info").innerHTML = 'Heap: bytes ( bytes)'; - changeProgressbar("heap", obj["heap_used"], obj["heap_total"]); - } - - for (const [key, value] of Object.entries(obj)) { - if(!data.includes(key) || (typeof value == 'undefined')) continue; - var li = document.createElement("li"); - li.appendChild(document.createTextNode(key + ": " + value)); - ul.appendChild(li); - } -} - -function changeProgressbar(id, value, max) { - document.getElementById(id).value = value; - document.getElementById(id).max = max; - - document.getElementById("heap_used").textContent = value; - document.getElementById("heap_total").textContent = max; -} - function setHide(id, hide) { var elm = document.getElementById(id); if(hide) { @@ -67,7 +41,6 @@ function setHide(id, hide) { elm.classList.remove('hide'); } - function toggle(id) { var e = document.getElementById(id); if(!e.classList.contains("hide")) diff --git a/src/web/html/system.html b/src/web/html/system.html index a3219d6b..d8a473a2 100644 --- a/src/web/html/system.html +++ b/src/web/html/system.html @@ -18,7 +18,7 @@
-
+
    @@ -44,6 +44,21 @@ parseESP(obj); } + function parseSysInfo(obj) { + const data = ["sdk", "cpu_freq", "chip_revision", + "chip_model", "chip_cores", "esp_type", "mac", "wifi_rssi", + "flash_size", "sketch_used", "heap_total", "heap_free", "heap_frag", + "max_free_blk", "version", "core_version", "reboot_reason"]; + + var ul = document.getElementById("info"); + for (const [key, value] of Object.entries(obj)) { + if(!data.includes(key) || (typeof value == 'undefined')) continue; + var li = document.createElement("li"); + li.appendChild(document.createTextNode(key + ": " + value)); + ul.appendChild(li); + } + } + function parse(obj) { if(null != obj) { parseMenu(obj["menu"]); diff --git a/src/web/webApi.cpp b/src/web/webApi.cpp index f06b8bb0..e71aa511 100644 --- a/src/web/webApi.cpp +++ b/src/web/webApi.cpp @@ -142,30 +142,47 @@ void webApi::onDwnldSetup(AsyncWebServerRequest *request) { //----------------------------------------------------------------------------- void webApi::getSysInfo(JsonObject obj) { - obj[F("ssid")] = mConfig->sys.stationSsid; - obj[F("device_name")] = mConfig->sys.deviceName; - obj[F("version")] = String(mVersion); - obj[F("build")] = String(AUTO_GIT_HASH); - obj[F("ts_uptime")] = mApp->getUptime(); - obj[F("ts_now")] = mApp->getTimestamp(); - obj[F("ts_sunrise")] = mApp->getSunrise(); - obj[F("ts_sunset")] = mApp->getSunset(); - obj[F("ts_sun_upd")] = mApp->getLatestSunTimestamp(); - obj[F("wifi_rssi")] = WiFi.RSSI(); - obj[F("pwd_set")] = (strlen(mConfig->sys.adminPwd) > 0); - - obj[F("hostname")] = WiFi.getHostname(); - obj[F("sdk_version")] = ESP.getSdkVersion(); - obj[F("cpu_freq")] = ESP.getCpuFreqMHz(); + obj[F("ssid")] = mConfig->sys.stationSsid; + obj[F("device_name")] = mConfig->sys.deviceName; + obj[F("version")] = String(mVersion); + obj[F("build")] = String(AUTO_GIT_HASH); + obj[F("ts_uptime")] = mApp->getUptime(); + obj[F("ts_now")] = mApp->getTimestamp(); + obj[F("ts_sunrise")] = mApp->getSunrise(); + obj[F("ts_sunset")] = mApp->getSunset(); + obj[F("ts_sun_upd")] = mApp->getLatestSunTimestamp(); + obj[F("wifi_rssi")] = WiFi.RSSI(); + obj[F("mac")] = WiFi.macAddress(); + obj[F("hostname")] = WiFi.getHostname(); + obj[F("pwd_set")] = (strlen(mConfig->sys.adminPwd) > 0); + + obj[F("sdk")] = ESP.getSdkVersion(); + obj[F("cpu_freq")] = ESP.getCpuFreqMHz(); + obj[F("heap_free")] = ESP.getFreeHeap(); + obj[F("sketch_total")] = ESP.getFreeSketchSpace(); + obj[F("sketch_used")] = ESP.getSketchSize() / 1024; // in kb + #if defined(ESP32) obj[F("heap_total")] = ESP.getHeapSize(); - obj[F("heap_used")] = ESP.getHeapSize() - ESP.getFreeHeap(); - obj[F("chip_revision")] = ESP.getChipRevision(); - obj[F("chip_model")] = ESP.getChipModel(); - obj[F("chip_cores")] = ESP.getChipCores(); + obj[F("chip_revision")] = ESP.getChipRevision(); + obj[F("chip_model")] = ESP.getChipModel(); + obj[F("chip_cores")] = ESP.getChipCores(); + //obj[F("core_version")] = F("n/a"); + //obj[F("flash_size")] = F("n/a"); + //obj[F("heap_frag")] = F("n/a"); + //obj[F("max_free_blk")] = F("n/a"); + //obj[F("reboot_reason")] = F("n/a"); +#else + //obj[F("heap_total")] = F("n/a"); + //obj[F("chip_revision")] = F("n/a"); + //obj[F("chip_model")] = F("n/a"); + //obj[F("chip_cores")] = F("n/a"); + obj[F("core_version")] = ESP.getCoreVersion(); + obj[F("flash_size")] = ESP.getFlashChipRealSize() / 1024; // in kb + obj[F("heap_frag")] = ESP.getHeapFragmentation(); + obj[F("max_free_blk")] = ESP.getMaxFreeBlockSize(); + obj[F("reboot_reason")] = ESP.getResetReason(); #endif - obj[F("sketch_total")] = ESP.getFreeSketchSpace(); - obj[F("sketch_used")] = ESP.getSketchSize(); //obj[F("littlefs_total")] = LittleFS.totalBytes(); //obj[F("littlefs_used")] = LittleFS.usedBytes(); From c1eed6eef226a01faf6dfbe01251c1c29806fdb3 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 18 Nov 2022 12:03:09 +0100 Subject: [PATCH 102/431] fix #416 --- src/app.cpp | 1 + src/publisher/pubMqtt.h | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 10e60c92..a7cc64a3 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -42,6 +42,7 @@ void app::setup(uint32_t timeout) { mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset); mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1)); addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt)); + addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt)); } #endif setupLed(); diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index f3ff4eb1..629edf1c 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -67,6 +67,14 @@ class PubMqtt { sendIvData(); } + void tickerMinute() { + if(mAddressSet) { + char val[40]; + snprintf(val, 40, "%ld", millis() / 1000); + sendMsg("uptime", val); + } + } + void setCallback(MQTT_CALLBACK_SIGNATURE) { mClient->setCallback(callback); } @@ -218,13 +226,10 @@ class PubMqtt { return; isConnected(true); // really needed? See comment from HorstG-57 #176 - char topic[32 + MAX_NAME_LENGTH], val[32]; + char topic[32 + MAX_NAME_LENGTH], val[40]; float total[4]; bool sendTotal = false; bool totalIncomplete = false; - snprintf(val, 40, "%ld", millis() / 1000); - - sendMsg("uptime", val); sendMsg("wifi_rssi", String(WiFi.RSSI()).c_str()); From 4c52e9c30723fdf1224c3fc8a815daafc9f6eeb2 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 18 Nov 2022 13:15:32 +0100 Subject: [PATCH 103/431] mqtt improvement (sunrise, sunset, wifi rssi) --- src/app.cpp | 1 + src/publisher/pubMqtt.h | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index a7cc64a3..fcfee586 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -43,6 +43,7 @@ void app::setup(uint32_t timeout) { mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1)); addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt)); addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt)); + addListener(EVERY_HR, std::bind(&PubMqttType::tickerHour, &mMqtt)); } #endif setupLed(); diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 629edf1c..90f27d45 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -72,6 +72,15 @@ class PubMqtt { char val[40]; snprintf(val, 40, "%ld", millis() / 1000); sendMsg("uptime", val); + + sendMsg("wifi_rssi", String(WiFi.RSSI()).c_str()); + } + } + + void tickerHour() { + if(mAddressSet) { + sendMsg("sunrise", String(*mSunrise).c_str()); + sendMsg("sunset", String(*mSunset).c_str()); } } @@ -231,11 +240,6 @@ class PubMqtt { bool sendTotal = false; bool totalIncomplete = false; - sendMsg("wifi_rssi", String(WiFi.RSSI()).c_str()); - - sendMsg("sunrise", String(*mSunrise).c_str()); - sendMsg("sunset", String(*mSunset).c_str()); - while(!mSendList.empty()) { memset(total, 0, sizeof(float) * 4); for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { From 4f46106228ef38d7f436a3a480b4bbdad78ca698 Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Sat, 19 Nov 2022 20:15:54 +0100 Subject: [PATCH 104/431] Add NRF to system site + api --- src/.vscode/settings.json | 51 ++++++++++++++++++++++++++++++++++++++- src/app.cpp | 22 ++++++++++++----- src/hm/hmRadio.h | 16 +++++++++--- src/web/html/system.html | 24 ++++++++++++++++++ src/web/webApi.cpp | 10 ++++++++ 5 files changed, 112 insertions(+), 11 deletions(-) diff --git a/src/.vscode/settings.json b/src/.vscode/settings.json index 6af36bae..3b7ffafd 100644 --- a/src/.vscode/settings.json +++ b/src/.vscode/settings.json @@ -24,6 +24,55 @@ "typeinfo": "cpp", "string": "cpp", "istream": "cpp", - "ostream": "cpp" + "ostream": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "limits": "cpp", + "new": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp" }, } \ No newline at end of file diff --git a/src/app.cpp b/src/app.cpp index fcfee586..06fb3088 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -23,6 +23,7 @@ void app::setup(uint32_t timeout) { addListener(EVERY_12H, std::bind(&app::ntpUpdateTick, this)); resetSystem(); + mSettings.setup(); mSettings.getPtr(mConfig); DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false"))); @@ -33,19 +34,28 @@ void app::setup(uint32_t timeout) { mSys = new HmSystemType(); mSys->enableDebug(); mSys->setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); - mSys->addInverters(&mConfig->inst); - mPayload.setup(mSys); - mPayload.enableSerialDebug(mConfig->serial.debug); -#if !defined(AP_ONLY) - if (mConfig->mqtt.broker[0] > 0) { + if(mSys->Radio.isChipConnected()) + { + mSys->addInverters(&mConfig->inst); + + mPayload.setup(mSys); + mPayload.enableSerialDebug(mConfig->serial.debug); + } + else + { + DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); + } + + // when WiFi is in client mode, then enable mqtt broker + if (mConfig->mqtt.broker[0] > 0 && WiFi.getMode() == WIFI_STA) { mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset); mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1)); addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt)); addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt)); addListener(EVERY_HR, std::bind(&PubMqttType::tickerHour, &mMqtt)); } -#endif + setupLed(); mWeb = new web(this, mConfig, &mStat, mVersion); diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 4e1b749c..9061174a 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -99,7 +99,7 @@ class HmRadio { DPRINTLN(DBG_VERBOSE, F("hmRadio.h:setup")); pinMode(irq, INPUT_PULLUP); mBufCtrl = ctrl; - + uint32_t dtuSn = 0x87654321; uint32_t chipID = 0; // will be filled with last 3 bytes of MAC @@ -191,7 +191,7 @@ class HmRadio { uint8_t setDefaultChannels(void) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:setDefaultChannels")); mTxChIdx = 2; // Start TX with 40 - mRxChIdx = 0; // Start RX with 03 + mRxChIdx = 0; // Start RX with 03 return mRfChLst[mTxChIdx]; } @@ -212,7 +212,7 @@ class HmRadio { uint16_t crc = ah::crc16(&mTxBuf[10], cnt); mTxBuf[10 + cnt++] = (crc >> 8) & 0xff; mTxBuf[10 + cnt++] = (crc ) & 0xff; - + // crc over all mTxBuf[10 + cnt] = ah::crc8(mTxBuf, 10 + cnt); @@ -295,6 +295,14 @@ class HmRadio { return mNrf24.isChipConnected(); } + rf24_datarate_e getDataRate(void) { + return mNrf24.getDataRate(); + } + + bool isPVariant(void) { + return mNrf24.isPVariant(); + } + uint32_t mSendCnt; @@ -360,7 +368,7 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRfChLst[RF_CHANNELS]; - + uint8_t mRxChIdx; uint16_t mRxLoopCnt; diff --git a/src/web/html/system.html b/src/web/html/system.html index d8a473a2..c95d581a 100644 --- a/src/web/html/system.html +++ b/src/web/html/system.html @@ -19,6 +19,7 @@
      +
        @@ -59,11 +60,34 @@ } } + function parseRadio(obj) { + const pa = ["MIN", "LOW", "HIGH", "MAX"]; + const datarate = ["1 MBps", "2 MBps", "250 kbps"]; + + var ul = document.getElementById("radio"); + let data; + + var li = document.createElement("li"); + li.appendChild(document.createTextNode("nrf24l01" + (obj["isPVariant"] ? "+ " : "") + (obj["isconnected"] ? "is connected " : "is not connected "))); + ul.appendChild(li); + + if(obj["isconnected"]) { + var li = document.createElement("li"); + li.appendChild(document.createTextNode("Datarate: " + datarate[obj["DataRate"]])); + ul.appendChild(li); + + var li = document.createElement("li"); + li.appendChild(document.createTextNode("Power Level: " + pa[obj["power_level"]])); + ul.appendChild(li); + } + } + function parse(obj) { if(null != obj) { parseMenu(obj["menu"]); parseSys(obj["system"]); parseSysInfo(obj["system"]); + parseRadio(obj["system"]["radio"]); var e = document.getElementById("system"); e.innerHTML = obj["html"]; diff --git a/src/web/webApi.cpp b/src/web/webApi.cpp index e71aa511..a6b3b1d1 100644 --- a/src/web/webApi.cpp +++ b/src/web/webApi.cpp @@ -162,6 +162,9 @@ void webApi::getSysInfo(JsonObject obj) { obj[F("sketch_total")] = ESP.getFreeSketchSpace(); obj[F("sketch_used")] = ESP.getSketchSize() / 1024; // in kb + + getRadio(obj.createNestedObject(F("radio"))); + #if defined(ESP32) obj[F("heap_total")] = ESP.getHeapSize(); obj[F("chip_revision")] = ESP.getChipRevision(); @@ -306,6 +309,9 @@ void webApi::getPinout(JsonObject obj) { //----------------------------------------------------------------------------- void webApi::getRadio(JsonObject obj) { obj[F("power_level")] = mConfig->nrf.amplifierPower; + obj[F("isconnected")] = mApp->mSys->Radio.isChipConnected(); + obj[F("DataRate")] = mApp->mSys->Radio.getDataRate(); + obj[F("isPVariant")] = mApp->mSys->Radio.isPVariant(); } @@ -358,6 +364,7 @@ void webApi::getMenu(JsonObject obj) { void webApi::getIndex(JsonObject obj) { getMenu(obj.createNestedObject(F("menu"))); getSysInfo(obj.createNestedObject(F("system"))); + getRadio(obj.createNestedObject(F("radio"))); getStatistics(obj.createNestedObject(F("statistics"))); obj["refresh_interval"] = mConfig->nrf.sendInterval; @@ -380,6 +387,9 @@ void webApi::getIndex(JsonObject obj) { JsonArray warn = obj.createNestedArray(F("warnings")); if(!mApp->mSys->Radio.isChipConnected()) warn.add(F("your NRF24 module can't be reached, check the wiring and pinout")); + else if(!mApp->mSys->Radio.isPVariant()) + warn.add(F("your NRF24 module have not a plus(+), please check!")); + if(!mApp->mqttIsConnected()) warn.add(F("MQTT is not connected")); From 59b8baab418bcd1dbe04efd2f8292732f1ac3711 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 19 Nov 2022 23:53:26 +0100 Subject: [PATCH 105/431] release v0.5.41 --- src/defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/defines.h b/src/defines.h index 36949daf..16369764 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 40 +#define VERSION_PATCH 41 //------------------------------------- typedef struct { From 133fefe5e1b0d99e223814c9deb52813c95cb42d Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 19 Nov 2022 23:57:00 +0100 Subject: [PATCH 106/431] release v0.5.41 --- .github/workflows/compile_esp8266.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/compile_esp8266.yml b/.github/workflows/compile_esp8266.yml index cf61b1f9..0ced33db 100644 --- a/.github/workflows/compile_esp8266.yml +++ b/.github/workflows/compile_esp8266.yml @@ -4,10 +4,10 @@ on: push: branches: main paths: - - 'tools/esp8266/**' # build only when changes occur here - - '!tools/esp8266/README.md' - - '!tools/esp8266/CHANGES.md' - - '!tools/esp8266/User_Manual.md' + - 'src/**' # build only when changes occur here + - '!README.md' + - '!CHANGES.md' + - '!User_Manual.md' jobs: build: runs-on: ubuntu-latest @@ -48,8 +48,9 @@ jobs: - name: Convert HTML files working-directory: src/web/html run: python convert.py + - name: Run PlatformIO - run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release + run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release - name: Rename Binary files id: rename-binary-files @@ -64,17 +65,17 @@ jobs: prerelease: false release_name: ${{ steps.rename-binary-files.outputs.name }} tag_name: ${{ steps.rename-binary-files.outputs.name }} - body_path: tools/esp8266/CHANGES.md + body_path: CHANGES.md env: GITHUB_TOKEN: ${{ github.token }} - name: set-version uses: cschleiden/replace-tokens@v1 with: - files: tools/esp8266/User_Manual.md + files: User_Manual.md env: VERSION: ${{ steps.rename-binary-files.outputs.name }} - name: create-artifact - run: zip --junk-paths ${{ steps.rename-binary-files.outputs.name }}.zip tools/esp8266/.pio/build/out/* tools/esp8266/User_Manual.md + run: zip --junk-paths ${{ steps.rename-binary-files.outputs.name }}.zip src/.pio/build/out/* User_Manual.md - name: Upload Release id: upload-release From 49def93dab8fec4cdd3321eb830532cd7e9a923c Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 19 Nov 2022 23:58:52 +0100 Subject: [PATCH 107/431] release v0.5.41 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 52c5283d..df276ccb 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ List of approaches ## Quick Start with ESP8266 - [Go here ✨](Getting_Started.md#things-needed) +- [Our Website](https://ahoydtu.de) ## Success Stories From 9da3a1a3706cdb2a629a7ebe2111dad01ab69237 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 20 Nov 2022 00:01:02 +0100 Subject: [PATCH 108/431] release v0.5.41 --- src/app.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app.cpp b/src/app.cpp index fcfee586..5fc3d089 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -227,7 +227,6 @@ void app::resetSystem(void) { mRxTicker = 0; mSendLastIvId = 0; - mShowRebootRequest = false; memset(&mStat, 0, sizeof(statistics_t)); From 12ca78e4b16585f13e8b61f446a333f1b86839c8 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 20 Nov 2022 00:09:33 +0100 Subject: [PATCH 109/431] release v0.5.41 --- src/CHANGES.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/CHANGES.md diff --git a/src/CHANGES.md b/src/CHANGES.md new file mode 100644 index 00000000..4bf99ac5 --- /dev/null +++ b/src/CHANGES.md @@ -0,0 +1,13 @@ +# Changelog + +* fix browser sync NTP button +* added login feature (protect web ui) +* added static IP option +* improved initial boot - don't connect to `YOUR_WIFI_SSID` any more, directly boot into AP mode +* added status LED support +* improved MQTT handling (boot, periodic updates, no zero values any more) +* replaced deprecated workflow functions +* refactored code to make it more clearly +* added scheduler to register functions which need to be run each second / minute / ... +* changed settings to littlefs (-> no currupt settings in future on memory layout changes) +* added a lot of system infos to `System` page for support From e9b4c6bd00eaac70dba1fe25e7c011de6d17bec5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 20 Nov 2022 00:14:38 +0100 Subject: [PATCH 110/431] release v0.5.41 --- .github/workflows/compile_esp8266.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile_esp8266.yml b/.github/workflows/compile_esp8266.yml index 0ced33db..490ee17d 100644 --- a/.github/workflows/compile_esp8266.yml +++ b/.github/workflows/compile_esp8266.yml @@ -65,7 +65,7 @@ jobs: prerelease: false release_name: ${{ steps.rename-binary-files.outputs.name }} tag_name: ${{ steps.rename-binary-files.outputs.name }} - body_path: CHANGES.md + body_path: src/CHANGES.md env: GITHUB_TOKEN: ${{ github.token }} - name: set-version From fe21b86957b50b7dea9f84fba0c2f5090a185386 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 20 Nov 2022 00:25:04 +0100 Subject: [PATCH 111/431] release v0.5.41 --- .github/workflows/{compile_esp8266.yml => compile_release.yml} | 1 + 1 file changed, 1 insertion(+) rename .github/workflows/{compile_esp8266.yml => compile_release.yml} (98%) diff --git a/.github/workflows/compile_esp8266.yml b/.github/workflows/compile_release.yml similarity index 98% rename from .github/workflows/compile_esp8266.yml rename to .github/workflows/compile_release.yml index 490ee17d..6a541304 100644 --- a/.github/workflows/compile_esp8266.yml +++ b/.github/workflows/compile_release.yml @@ -5,6 +5,7 @@ on: branches: main paths: - 'src/**' # build only when changes occur here + - '.github/workflows/compile_release.yml' - '!README.md' - '!CHANGES.md' - '!User_Manual.md' From dec333fdf904a857fdf1873167803388a81af34e Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 20 Nov 2022 00:45:42 +0100 Subject: [PATCH 112/431] release v0.5.41 --- .github/workflows/compile_release.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/compile_release.yml b/.github/workflows/compile_release.yml index 6a541304..91ae35bf 100644 --- a/.github/workflows/compile_release.yml +++ b/.github/workflows/compile_release.yml @@ -69,14 +69,16 @@ jobs: body_path: src/CHANGES.md env: GITHUB_TOKEN: ${{ github.token }} - - name: set-version + + - name: Set Version uses: cschleiden/replace-tokens@v1 with: files: User_Manual.md env: VERSION: ${{ steps.rename-binary-files.outputs.name }} - - name: create-artifact - run: zip --junk-paths ${{ steps.rename-binary-files.outputs.name }}.zip src/.pio/build/out/* User_Manual.md + + - name: Create Artifact + run: zip --junk-paths ${{ steps.rename-binary-files.outputs.name }}.zip src/firmware/* User_Manual.md - name: Upload Release id: upload-release From 628398040c3ca44fac509ad78fe9f987743ab3fd Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Sun, 20 Nov 2022 13:51:22 +0100 Subject: [PATCH 113/431] update discord members --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index df276ccb..c378424c 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ List of approaches - [Getting the data into influxDB and visualize them in a Grafana Dashboard](https://grafana.com/grafana/dashboards/16850-pv-power-ahoy/) (thx @Carl) ## Support, Feedback, Information and Discussion -- [Discord Server (~ 300 Users)](https://discord.gg/WzhxEY62mB) +- [Discord Server (~ 1200 Users)](https://discord.gg/WzhxEY62mB) - [The root of development](https://www.mikrocontroller.net/topic/525778) ### Development From fce28a1b38d317b7621c5c3a4e3f23131f288623 Mon Sep 17 00:00:00 2001 From: joba-1 <32450554+joba-1@users.noreply.github.com> Date: Mon, 21 Nov 2022 15:18:42 +0100 Subject: [PATCH 114/431] Add TSOL-M800 to the list of supported devices in Getting_Started.md, with link to manual --- Getting_Started.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Getting_Started.md b/Getting_Started.md index 15985081..45e7f3c2 100644 --- a/Getting_Started.md +++ b/Getting_Started.md @@ -55,6 +55,7 @@ TSun Inverters: - TSOL-350 - TSOL-400 +- [TSOL-M800](http://de.tsun-ess.com/products/TSOL-M/User-Manual-TSOL-M350&M400&M800&M1600-EN-V1.0.pdf) - others may work as well (need to be verified). ## Things needed From 22715a1a4a94698dacbdb1509c4e69b59fd38d6c Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 21 Nov 2022 23:02:47 +0100 Subject: [PATCH 115/431] first draft version, callback and subscription not included --- src/app.cpp | 5 +- src/defines.h | 2 +- src/platformio.ini | 3 +- src/publisher/pubMqtt.h | 407 ++++++++++++++++++++++------------------ src/wifi/ahoywifi.cpp | 14 ++ src/wifi/ahoywifi.h | 4 + 6 files changed, 248 insertions(+), 187 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index fcfee586..65dc8f4b 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -27,6 +27,10 @@ void app::setup(uint32_t timeout) { mSettings.getPtr(mConfig); DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false"))); +#if !defined(AP_ONLY) + mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset); +#endif + mWifi = new ahoywifi(mConfig); mWifi->setup(timeout, mSettings.getValid()); @@ -39,7 +43,6 @@ void app::setup(uint32_t timeout) { mPayload.enableSerialDebug(mConfig->serial.debug); #if !defined(AP_ONLY) if (mConfig->mqtt.broker[0] > 0) { - mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset); mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1)); addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt)); addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt)); diff --git a/src/defines.h b/src/defines.h index 36949daf..ea772a5f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 40 +#define VERSION_PATCH 42 //------------------------------------- typedef struct { diff --git a/src/platformio.ini b/src/platformio.ini index ac38b9e8..0610c51d 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -36,7 +36,8 @@ lib_deps = https://github.com/yubox-node-org/ESPAsyncWebServer nrf24/RF24 paulstoffregen/Time - knolleary/PubSubClient + https://github.com/bertmelis/espMqttClient#v1.3.3 + ;knolleary/PubSubClient bblanchon/ArduinoJson ;esp8266/DNSServer ;esp8266/EEPROM diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 90f27d45..cd27d884 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -15,115 +15,94 @@ #include "../utils/dbg.h" #include "../utils/ahoyTimer.h" #include "../config/config.h" -#include +#include #include #include "../defines.h" #include "../hm/hmSystem.h" + +#define QOS_0 0 + +//https://bert.emelis.net/espMqttClient/ + template class PubMqtt { public: PubMqtt() { - mClient = new PubSubClient(mEspClient); - mAddressSet = false; - - mLastReconnect = 0; mTxCnt = 0; } ~PubMqtt() { } void setup(cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs, uint32_t *sunrise, uint32_t *sunset) { - DPRINTLN(DBG_VERBOSE, F("PubMqtt.h:setup")); - mAddressSet = true; - - mCfg_mqtt = cfg_mqtt; + mCfgMqtt = cfg_mqtt; mDevName = devName; + mVersion = version; mSys = sys; mUtcTimestamp = utcTs; mSunrise = sunrise; mSunset = sunset; - mClient->setServer(mCfg_mqtt->broker, mCfg_mqtt->port); - mClient->setBufferSize(MQTT_MAX_PACKET_SIZE); + mHWifiCon = WiFi.onStationModeGotIP(std::bind(&PubMqtt::onWifiConnect, this, std::placeholders::_1)); + mHWifiDiscon = WiFi.onStationModeDisconnected(std::bind(&PubMqtt::onWifiDisconnect, this, std::placeholders::_1)); - setCallback(std::bind(&PubMqtt::cbMqtt, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - sendMsg("version", version); - sendMsg("device", devName); - sendMsg("uptime", "0"); + if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0)) + mClient.setCredentials(mCfgMqtt->user, mCfgMqtt->pwd); + mClient.setClientId(mDevName); // TODO: add mac? + mClient.setServer(mCfgMqtt->broker, mCfgMqtt->port); + mClient.onConnect(std::bind(&PubMqtt::onConnect, this, std::placeholders::_1)); + mClient.onDisconnect(std::bind(&PubMqtt::onDisconnect, this, std::placeholders::_1)); + mClient.onSubscribe(std::bind(&PubMqtt::onSubscribe, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + mClient.onPublish(std::bind(&PubMqtt::onPublish, this, std::placeholders::_1)); + //mClient.setWill } void loop() { - if(mAddressSet) - mClient->loop(); + mClient.loop(); } void tickerSecond() { - if(mAddressSet) { - if(!mClient->connected()) - reconnect(); - } sendIvData(); } void tickerMinute() { - if(mAddressSet) { - char val[40]; - snprintf(val, 40, "%ld", millis() / 1000); - sendMsg("uptime", val); - - sendMsg("wifi_rssi", String(WiFi.RSSI()).c_str()); - } + char val[12]; + snprintf(val, 12, "%ld", millis() / 1000); + publish("uptime", val); + publish("wifi_rssi", String(WiFi.RSSI()).c_str()); } void tickerHour() { - if(mAddressSet) { - sendMsg("sunrise", String(*mSunrise).c_str()); - sendMsg("sunset", String(*mSunset).c_str()); - } + publish("sunrise", String(*mSunrise).c_str(), true); + publish("sunset", String(*mSunset).c_str(), true); } - void setCallback(MQTT_CALLBACK_SIGNATURE) { - mClient->setCallback(callback); + void publish(const char *subTopic, const char *payload, bool retained = false) { + char topic[MQTT_TOPIC_LEN + 2]; + snprintf(topic, (MQTT_TOPIC_LEN + 2), "%s/%s", mCfgMqtt->topic, subTopic); + mClient.publish(topic, QOS_0, retained, payload); + mTxCnt++; } - void sendMsg(const char *topic, const char *msg) { - //DPRINTLN(DBG_VERBOSE, F("mqtt.h:sendMsg")); - if(mAddressSet) { - char top[66]; - snprintf(top, 66, "%s/%s", mCfg_mqtt->topic, topic); - sendMsg2(top, msg, false); - } + void subscribe(const char *subTopic) { + char topic[MQTT_TOPIC_LEN + 20]; + snprintf(topic, (MQTT_TOPIC_LEN + 20), "%s/%s", mCfgMqtt->topic, subTopic); + mClient.subscribe(topic, QOS_0); } - void sendMsg2(const char *topic, const char *msg, boolean retained) { - if(mAddressSet) { - if(!mClient->connected()) - reconnect(); - if(mClient->connected()) - mClient->publish(topic, msg, retained); - mTxCnt++; - } + inline bool isConnected() { + return mClient.connected(); } - bool isConnected(bool doRecon = false) { - //DPRINTLN(DBG_VERBOSE, F("mqtt.h:isConnected")); - if(!mAddressSet) - return false; - if(doRecon && !mClient->connected()) - reconnect(); - return mClient->connected(); + inline uint32_t getTxCnt(void) { + return mTxCnt; } void payloadEventListener(uint8_t cmd) { mSendList.push(cmd); } - uint32_t getTxCnt(void) { - return mTxCnt; - } - void sendMqttDiscoveryConfig(const char *topic) { DPRINTLN(DBG_VERBOSE, F("sendMqttDiscoveryConfig")); @@ -165,8 +144,7 @@ class PubMqtt { doc["stat_cla"] = stateCls; serializeJson(doc, buffer); - sendMsg2(discoveryTopic, buffer, true); - // DPRINTLN(DBG_INFO, F("mqtt sent")); + publish(discoveryTopic, buffer, true); doc.clear(); } @@ -176,7 +154,69 @@ class PubMqtt { } private: - void reconnect(void) { + void onWifiConnect(const WiFiEventStationModeGotIP& event) { + DPRINTLN(DBG_VERBOSE, F("MQTT connecting")); + mClient.connect(); + } + + void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) { + DPRINTLN(DBG_WARN, F("TODO: MQTT reconnect!")); + } + + void onConnect(bool sessionPreset) { + DPRINTLN(DBG_INFO, F("MQTT connected")); + + publish("version", mVersion, true); + publish("device", mDevName, true); + publish("uptime", "0"); + + subscribe("devcontrol/#"); // TODO: register onMessage callback! + } + + void onDisconnect(espMqttClientTypes::DisconnectReason reason) { + DBGPRINT(F("MQTT disconnected, reason: ")); + switch (reason) { + case espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED: + DBGPRINTLN(F("TCP disconnect")); + break; + case espMqttClientTypes::DisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION: + DBGPRINTLN(F("wrong protocol version")); + break; + case espMqttClientTypes::DisconnectReason::MQTT_IDENTIFIER_REJECTED: + DBGPRINTLN(F("identifier rejected")); + break; + case espMqttClientTypes::DisconnectReason::MQTT_SERVER_UNAVAILABLE: + DBGPRINTLN(F("broker unavailable")); + break; + case espMqttClientTypes::DisconnectReason::MQTT_MALFORMED_CREDENTIALS: + DBGPRINTLN(F("malformed credentials")); + break; + case espMqttClientTypes::DisconnectReason::MQTT_NOT_AUTHORIZED: + DBGPRINTLN(F("not authorized")); + break; + default: + DBGPRINTLN(F("unknown")); + } + } + + void onSubscribe(uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* codes, size_t len) { + DPRINTLN(DBG_INFO, F("MQTT Subscribe")); + Serial.print(" packetId: "); + Serial.println(packetId); + for (size_t i = 0; i < len; ++i) { + Serial.print(" qos: "); + Serial.println(static_cast(codes[i])); + } + } + + void onPublish(uint16_t packetId) { + Serial.println("Publish acknowledged."); + Serial.print(" packetId: "); + Serial.println(packetId); + } + + + /*void reconnect(void) { DPRINTLN(DBG_DEBUG, F("mqtt.h:reconnect")); DPRINTLN(DBG_DEBUG, F("MQTT mClient->_state ") + String(mClient->state()) ); @@ -190,27 +230,27 @@ class PubMqtt { if(strlen(mDevName) > 0) { // der Server und der Port müssen neu gesetzt werden, // da ein MQTT_CONNECTION_LOST -3 die Werte zerstört hat. - mClient->setServer(mCfg_mqtt->broker, mCfg_mqtt->port); + mClient->setServer(mCfgMqtt->broker, mCfgMqtt->port); mClient->setBufferSize(MQTT_MAX_PACKET_SIZE); char lwt[MQTT_TOPIC_LEN + 7 ]; // "/uptime" --> + 7 byte - snprintf(lwt, MQTT_TOPIC_LEN + 7, "%s/uptime", mCfg_mqtt->topic); + snprintf(lwt, MQTT_TOPIC_LEN + 7, "%s/uptime", mCfgMqtt->topic); - if((strlen(mCfg_mqtt->user) > 0) && (strlen(mCfg_mqtt->pwd) > 0)) - resub = mClient->connect(mDevName, mCfg_mqtt->user, mCfg_mqtt->pwd, lwt, 0, false, "offline"); + if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0)) + resub = mClient->connect(mDevName, mCfgMqtt->user, mCfgMqtt->pwd, lwt, 0, false, "offline"); else resub = mClient->connect(mDevName, lwt, 0, false, "offline"); // ein Subscribe ist nur nach einem connect notwendig if(resub) { char topic[MQTT_TOPIC_LEN + 13 ]; // "/devcontrol/#" --> + 6 byte // ToDo: "/devcontrol/#" is hardcoded - snprintf(topic, MQTT_TOPIC_LEN + 13, "%s/devcontrol/#", mCfg_mqtt->topic); + snprintf(topic, MQTT_TOPIC_LEN + 13, "%s/devcontrol/#", mCfgMqtt->topic); DPRINTLN(DBG_INFO, F("subscribe to ") + String(topic)); mClient->subscribe(topic); // subscribe to mTopic + "/devcontrol/#" } } } - } + }*/ const char *getFieldDeviceClass(uint8_t fieldId) { uint8_t pos = 0; @@ -234,7 +274,6 @@ class PubMqtt { if(mSendList.empty()) return; - isConnected(true); // really needed? See comment from HorstG-57 #176 char topic[32 + MAX_NAME_LENGTH], val[40]; float total[4]; bool sendTotal = false; @@ -267,15 +306,15 @@ class PubMqtt { (status == MQTT_STATUS_AVAIL_NOT_PROD) ? "not " : "", (status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "" : "producing" ); - sendMsg(topic, val); + publish(topic, val); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name); snprintf(val, 40, "%d", status); - sendMsg(topic, val); + publish(topic, val); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name); snprintf(val, 40, "%i", iv->getLastTs(rec) * 1000); - sendMsg(topic, val); + publish(topic, val); } // data @@ -283,7 +322,7 @@ class PubMqtt { for (uint8_t i = 0; i < rec->length; i++) { snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); snprintf(val, 40, "%.3f", iv->getValue(i, rec)); - sendMsg(topic, val); + publish(topic, val); // calculate total values for RealTimeRunData_Debug if (mSendList.front() == RealTimeRunData_Debug) { @@ -332,127 +371,127 @@ class PubMqtt { } snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); snprintf(val, 40, "%.3f", total[i]); - sendMsg(topic, val); + publish(topic, val); } } } } - void cbMqtt(char *topic, byte *payload, unsigned int length) { - // callback handling on subscribed devcontrol topic - DPRINTLN(DBG_INFO, F("cbMqtt")); - // subcribed topics are mTopic + "/devcontrol/#" where # is / - // eg. mypvsolar/devcontrol/1/11 with payload "400" --> inverter 1 active power limit 400 Watt - const char *token = strtok(topic, "/"); - while (token != NULL) { - if (strcmp(token, "devcontrol") == 0) { - token = strtok(NULL, "/"); - uint8_t iv_id = std::stoi(token); - - if (iv_id >= 0 && iv_id <= MAX_NUM_INVERTERS) { - Inverter<> *iv = mSys->getInverterByPos(iv_id); - if (NULL != iv) { - if (!iv->devControlRequest) { // still pending - token = strtok(NULL, "/"); - - switch (std::stoi(token)) { - // Active Power Control - case ActivePowerContr: - token = strtok(NULL, "/"); // get ControlMode aka "PowerPF.Desc" in DTU-Pro Code from topic string - if (token == NULL) // default via mqtt ommit the LimitControlMode - iv->powerLimit[1] = AbsolutNonPersistent; - else - iv->powerLimit[1] = std::stoi(token); - if (length <= 5) { // if (std::stoi((char*)payload) > 0) more error handling powerlimit needed? - if (iv->powerLimit[1] >= AbsolutNonPersistent && iv->powerLimit[1] <= RelativPersistent) { - iv->devControlCmd = ActivePowerContr; - iv->powerLimit[0] = std::stoi(std::string((char *)payload, (unsigned int)length)); // THX to @silversurfer - /*if (iv->powerLimit[1] & 0x0001) - DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("%")); - else - DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W"));*/ - - DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + String(iv->powerLimit[1] & 0x0001) ? F("%") : F("W")); - } - iv->devControlRequest = true; - } else { - DPRINTLN(DBG_INFO, F("Invalid mqtt payload recevied: ") + String((char *)payload)); - } - break; - - // Turn On - case TurnOn: - iv->devControlCmd = TurnOn; - DPRINTLN(DBG_INFO, F("Turn on inverter ") + String(iv->id)); - iv->devControlRequest = true; - break; - - // Turn Off - case TurnOff: - iv->devControlCmd = TurnOff; - DPRINTLN(DBG_INFO, F("Turn off inverter ") + String(iv->id)); - iv->devControlRequest = true; - break; - - // Restart - case Restart: - iv->devControlCmd = Restart; - DPRINTLN(DBG_INFO, F("Restart inverter ") + String(iv->id)); - iv->devControlRequest = true; - break; - - // Reactive Power Control - case ReactivePowerContr: - iv->devControlCmd = ReactivePowerContr; - if (true) { // if (std::stoi((char*)payload) > 0) error handling powerlimit needed? - iv->devControlCmd = ReactivePowerContr; - iv->powerLimit[0] = std::stoi(std::string((char *)payload, (unsigned int)length)); - iv->powerLimit[1] = 0x0000; // if reactivepower limit is set via external interface --> set it temporay - DPRINTLN(DBG_DEBUG, F("Reactivepower limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W")); - iv->devControlRequest = true; - } - break; - - // Set Power Factor - case PFSet: - // iv->devControlCmd = PFSet; - // uint16_t power_factor = std::stoi(strtok(NULL, "/")); - DPRINTLN(DBG_INFO, F("Set Power Factor not implemented for inverter ") + String(iv->id)); - break; - - // CleanState lock & alarm - case CleanState_LockAndAlarm: - iv->devControlCmd = CleanState_LockAndAlarm; - DPRINTLN(DBG_INFO, F("CleanState lock & alarm for inverter ") + String(iv->id)); - iv->devControlRequest = true; - break; - - default: - DPRINTLN(DBG_INFO, "Not implemented"); - break; - } - } - } - } - break; - } - token = strtok(NULL, "/"); - } - DPRINTLN(DBG_INFO, F("app::cbMqtt finished")); - } +// void cbMqtt(char *topic, byte *payload, unsigned int length) { +// // callback handling on subscribed devcontrol topic +// DPRINTLN(DBG_INFO, F("cbMqtt")); +// // subcribed topics are mTopic + "/devcontrol/#" where # is / +// // eg. mypvsolar/devcontrol/1/11 with payload "400" --> inverter 1 active power limit 400 Watt +// const char *token = strtok(topic, "/"); +// while (token != NULL) { +// if (strcmp(token, "devcontrol") == 0) { +// token = strtok(NULL, "/"); +// uint8_t iv_id = std::stoi(token); +// +// if (iv_id >= 0 && iv_id <= MAX_NUM_INVERTERS) { +// Inverter<> *iv = mSys->getInverterByPos(iv_id); +// if (NULL != iv) { +// if (!iv->devControlRequest) { // still pending +// token = strtok(NULL, "/"); +// +// switch (std::stoi(token)) { +// // Active Power Control +// case ActivePowerContr: +// token = strtok(NULL, "/"); // get ControlMode aka "PowerPF.Desc" in DTU-Pro Code from topic string +// if (token == NULL) // default via mqtt ommit the LimitControlMode +// iv->powerLimit[1] = AbsolutNonPersistent; +// else +// iv->powerLimit[1] = std::stoi(token); +// if (length <= 5) { // if (std::stoi((char*)payload) > 0) more error handling powerlimit needed? +// if (iv->powerLimit[1] >= AbsolutNonPersistent && iv->powerLimit[1] <= RelativPersistent) { +// iv->devControlCmd = ActivePowerContr; +// iv->powerLimit[0] = std::stoi(std::string((char *)payload, (unsigned int)length)); // THX to @silversurfer +// /*if (iv->powerLimit[1] & 0x0001) +// DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("%")); +// else +// DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W"));*/ +// +// DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + String(iv->powerLimit[1] & 0x0001) ? F("%") : F("W")); +// } +// iv->devControlRequest = true; +// } else { +// DPRINTLN(DBG_INFO, F("Invalid mqtt payload recevied: ") + String((char *)payload)); +// } +// break; +// +// // Turn On +// case TurnOn: +// iv->devControlCmd = TurnOn; +// DPRINTLN(DBG_INFO, F("Turn on inverter ") + String(iv->id)); +// iv->devControlRequest = true; +// break; +// +// // Turn Off +// case TurnOff: +// iv->devControlCmd = TurnOff; +// DPRINTLN(DBG_INFO, F("Turn off inverter ") + String(iv->id)); +// iv->devControlRequest = true; +// break; +// +// // Restart +// case Restart: +// iv->devControlCmd = Restart; +// DPRINTLN(DBG_INFO, F("Restart inverter ") + String(iv->id)); +// iv->devControlRequest = true; +// break; +// +// // Reactive Power Control +// case ReactivePowerContr: +// iv->devControlCmd = ReactivePowerContr; +// if (true) { // if (std::stoi((char*)payload) > 0) error handling powerlimit needed? +// iv->devControlCmd = ReactivePowerContr; +// iv->powerLimit[0] = std::stoi(std::string((char *)payload, (unsigned int)length)); +// iv->powerLimit[1] = 0x0000; // if reactivepower limit is set via external interface --> set it temporay +// DPRINTLN(DBG_DEBUG, F("Reactivepower limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W")); +// iv->devControlRequest = true; +// } +// break; +// +// // Set Power Factor +// case PFSet: +// // iv->devControlCmd = PFSet; +// // uint16_t power_factor = std::stoi(strtok(NULL, "/")); +// DPRINTLN(DBG_INFO, F("Set Power Factor not implemented for inverter ") + String(iv->id)); +// break; +// +// // CleanState lock & alarm +// case CleanState_LockAndAlarm: +// iv->devControlCmd = CleanState_LockAndAlarm; +// DPRINTLN(DBG_INFO, F("CleanState lock & alarm for inverter ") + String(iv->id)); +// iv->devControlRequest = true; +// break; +// +// default: +// DPRINTLN(DBG_INFO, "Not implemented"); +// break; +// } +// } +// } +// } +// break; +// } +// token = strtok(NULL, "/"); +// } +// DPRINTLN(DBG_INFO, F("app::cbMqtt finished")); +// } + + espMqttClient mClient; + cfgMqtt_t *mCfgMqtt; + WiFiEventHandler mHWifiCon, mHWifiDiscon; uint32_t *mSunrise, *mSunset; - WiFiClient mEspClient; - PubSubClient *mClient; HMSYSTEM *mSys; uint32_t *mUtcTimestamp; - - bool mAddressSet; - cfgMqtt_t *mCfg_mqtt; - const char *mDevName; - uint32_t mLastReconnect; uint32_t mTxCnt; std::queue mSendList; + + const char *mDevName, *mVersion; + //uint32_t mLastReconnect; }; #endif /*__PUB_MQTT_H__*/ diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 1d684bbe..9b95d25b 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -32,6 +32,8 @@ ahoywifi::ahoywifi(settings_t *config) { //----------------------------------------------------------------------------- void ahoywifi::setup(uint32_t timeout, bool settingValid) { + //wifiConnectHandler = WiFi.onStationModeGotIP(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); + //wifiDisconnectHandler = WiFi.onStationModeDisconnected(std::bind(&ahoywifi::onDisconnect, this, std::placeholders::_1)); #ifdef FB_WIFI_OVERRIDDEN mStationWifiIsDef = false; @@ -287,3 +289,15 @@ void ahoywifi::sendNTPpacket(IPAddress& address) { mUdp->write(buf, NTP_PACKET_SIZE); mUdp->endPacket(); } + + +//----------------------------------------------------------------------------- +/*void ahoywifi::onConnect(const WiFiEventStationModeGotIP& event) { + Serial.println("Connected to Wi-Fi."); +} + + +//----------------------------------------------------------------------------- +void ahoywifi::onDisconnect(const WiFiEventStationModeDisconnected& event) { + Serial.println("Disconnected from Wi-Fi."); +}*/ diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index c2add85b..32ca5cec 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -33,11 +33,15 @@ class ahoywifi { private: void sendNTPpacket(IPAddress& address); + //void onConnect(const WiFiEventStationModeGotIP& event); + //void onDisconnect(const WiFiEventStationModeDisconnected& event); settings_t *mConfig; DNSServer *mDns; WiFiUDP *mUdp; // for time server + //WiFiEventHandler wifiConnectHandler; + //WiFiEventHandler wifiDisconnectHandler; uint32_t mWifiStationTimeout; uint32_t mNextTryTs; From 43af07716e03f20778d961166e89aff75154a8a8 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 22 Nov 2022 10:32:04 +0100 Subject: [PATCH 116/431] fix logout --- src/config/config.h | 2 +- src/defines.h | 2 +- src/web/web.cpp | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/config/config.h b/src/config/config.h index 70a36f58..2b5a0688 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -26,7 +26,7 @@ //#define AP_ONLY // timeout for automatic logoff (20 minutes) -#define LOGOUT_TIMEOUT (20 * 60 * 60) +#define LOGOUT_TIMEOUT (20 * 60) //------------------------------------- // CONFIGURATION - COMPILE TIME diff --git a/src/defines.h b/src/defines.h index 36949daf..ea772a5f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 40 +#define VERSION_PATCH 42 //------------------------------------- typedef struct { diff --git a/src/web/web.cpp b/src/web/web.cpp index 45be992e..3db382ef 100644 --- a/src/web/web.cpp +++ b/src/web/web.cpp @@ -107,8 +107,10 @@ void web::loop(void) { void web::tickSecond() { if(0 != mLogoutTimeout) { mLogoutTimeout -= 1; - if(0 == mLogoutTimeout) - mProtected = true; + if(0 == mLogoutTimeout) { + if(strlen(mConfig->sys.adminPwd) > 0) + mProtected = true; + } DPRINTLN(DBG_DEBUG, "auto logout in " + String(mLogoutTimeout)); } From 573bd31f0a4b5f9bfa032ac6eb3503ae03bc3c0b Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 23 Nov 2022 21:09:57 +0100 Subject: [PATCH 117/431] improved MQTT --- src/app.cpp | 12 ++- src/publisher/pubMqtt.h | 164 ++++++++++++++++++++++----------------- src/web/html/update.html | 6 -- 3 files changed, 102 insertions(+), 80 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 65dc8f4b..782ae853 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -27,6 +27,11 @@ void app::setup(uint32_t timeout) { mSettings.getPtr(mConfig); DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false"))); + mSys = new HmSystemType(); + mSys->enableDebug(); + mSys->setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); + mSys->addInverters(&mConfig->inst); + #if !defined(AP_ONLY) mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset); #endif @@ -34,10 +39,6 @@ void app::setup(uint32_t timeout) { mWifi = new ahoywifi(mConfig); mWifi->setup(timeout, mSettings.getValid()); - mSys = new HmSystemType(); - mSys->enableDebug(); - mSys->setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); - mSys->addInverters(&mConfig->inst); mPayload.setup(mSys); mPayload.enableSerialDebug(mConfig->serial.debug); @@ -222,6 +223,9 @@ void app::resetSystem(void) { mUtcTimestamp = 0; #endif + mSunrise = 0; + mSunset = 0; + mHeapStatCnt = 0; mSendTicker = 0xffff; diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index cd27d884..fb3d8669 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -29,7 +29,9 @@ template class PubMqtt { public: PubMqtt() { + mRxCnt = 0; mTxCnt = 0; + mEnReconnect = false; } ~PubMqtt() { } @@ -43,6 +45,8 @@ class PubMqtt { mSunrise = sunrise; mSunset = sunset; + snprintf(mLwtTopic, MQTT_TOPIC_LEN + 7, "%s/status", mCfgMqtt->topic); + mHWifiCon = WiFi.onStationModeGotIP(std::bind(&PubMqtt::onWifiConnect, this, std::placeholders::_1)); mHWifiDiscon = WiFi.onStationModeDisconnected(std::bind(&PubMqtt::onWifiDisconnect, this, std::placeholders::_1)); @@ -51,11 +55,10 @@ class PubMqtt { mClient.setCredentials(mCfgMqtt->user, mCfgMqtt->pwd); mClient.setClientId(mDevName); // TODO: add mac? mClient.setServer(mCfgMqtt->broker, mCfgMqtt->port); + mClient.setWill(mLwtTopic, QOS_0, true, mLwtOffline); mClient.onConnect(std::bind(&PubMqtt::onConnect, this, std::placeholders::_1)); mClient.onDisconnect(std::bind(&PubMqtt::onDisconnect, this, std::placeholders::_1)); - mClient.onSubscribe(std::bind(&PubMqtt::onSubscribe, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - mClient.onPublish(std::bind(&PubMqtt::onPublish, this, std::placeholders::_1)); - //mClient.setWill + mClient.onMessage(std::bind(&PubMqtt::onMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)); } void loop() { @@ -71,6 +74,11 @@ class PubMqtt { snprintf(val, 12, "%ld", millis() / 1000); publish("uptime", val); publish("wifi_rssi", String(WiFi.RSSI()).c_str()); + + if(!mClient.connected()) { + if(mEnReconnect) + mClient.connect(); + } } void tickerHour() { @@ -78,10 +86,13 @@ class PubMqtt { publish("sunset", String(*mSunset).c_str(), true); } - void publish(const char *subTopic, const char *payload, bool retained = false) { + void publish(const char *subTopic, const char *payload, bool retained = false, bool addTopic = true) { char topic[MQTT_TOPIC_LEN + 2]; snprintf(topic, (MQTT_TOPIC_LEN + 2), "%s/%s", mCfgMqtt->topic, subTopic); - mClient.publish(topic, QOS_0, retained, payload); + if(addTopic) + mClient.publish(topic, QOS_0, retained, payload); + else + mClient.publish(subTopic, QOS_0, retained, payload); mTxCnt++; } @@ -99,6 +110,10 @@ class PubMqtt { return mTxCnt; } + inline uint32_t getRxCnt(void) { + return mRxCnt; + } + void payloadEventListener(uint8_t cmd) { mSendList.push(cmd); } @@ -112,11 +127,11 @@ class PubMqtt { if (NULL != iv) { record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); DynamicJsonDocument deviceDoc(128); - deviceDoc["name"] = iv->config->name; - deviceDoc["ids"] = String(iv->config->serial.u64, HEX); - deviceDoc["cu"] = F("http://") + String(WiFi.localIP().toString()); - deviceDoc["mf"] = "Hoymiles"; - deviceDoc["mdl"] = iv->config->name; + deviceDoc[F("name")] = iv->config->name; + deviceDoc[F("ids")] = String(iv->config->serial.u64, HEX); + deviceDoc[F("cu")] = F("http://") + String(WiFi.localIP().toString()); + deviceDoc[F("mf")] = F("Hoymiles"); + deviceDoc[F("mdl")] = iv->config->name; JsonObject deviceObj = deviceDoc.as(); DynamicJsonDocument doc(384); @@ -132,19 +147,19 @@ class PubMqtt { const char *devCls = getFieldDeviceClass(rec->assign[i].fieldId); const char *stateCls = getFieldStateClass(rec->assign[i].fieldId); - doc["name"] = name; - doc["stat_t"] = stateTopic; - doc["unit_of_meas"] = iv->getUnit(i, rec); - doc["uniq_id"] = String(iv->config->serial.u64, HEX) + "_" + uniq_id; - doc["dev"] = deviceObj; - doc["exp_aft"] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!? + doc[F("name")] = name; + doc[F("stat_t")] = stateTopic; + doc[F("unit_of_meas")] = iv->getUnit(i, rec); + doc[F("uniq_id")] = String(iv->config->serial.u64, HEX) + "_" + uniq_id; + doc[F("dev")] = deviceObj; + doc[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) - doc["dev_cla"] = devCls; + doc[F("dev_cla")] = devCls; if (stateCls != NULL) - doc["stat_cla"] = stateCls; + doc[F("stat_cla")] = stateCls; serializeJson(doc, buffer); - publish(discoveryTopic, buffer, true); + publish(discoveryTopic, buffer, true, false); doc.clear(); } @@ -160,17 +175,22 @@ class PubMqtt { } void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) { - DPRINTLN(DBG_WARN, F("TODO: MQTT reconnect!")); + mEnReconnect = false; } void onConnect(bool sessionPreset) { DPRINTLN(DBG_INFO, F("MQTT connected")); + mEnReconnect = true; publish("version", mVersion, true); publish("device", mDevName, true); publish("uptime", "0"); - subscribe("devcontrol/#"); // TODO: register onMessage callback! + publish(mLwtTopic, mLwtOnline, true, false); + + subscribe("ctrl/#"); + subscribe("setup/#"); + subscribe("status/#"); } void onDisconnect(espMqttClientTypes::DisconnectReason reason) { @@ -199,58 +219,57 @@ class PubMqtt { } } - void onSubscribe(uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* codes, size_t len) { - DPRINTLN(DBG_INFO, F("MQTT Subscribe")); - Serial.print(" packetId: "); - Serial.println(packetId); - for (size_t i = 0; i < len; ++i) { - Serial.print(" qos: "); - Serial.println(static_cast(codes[i])); + void onMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) { + DPRINTLN(DBG_VERBOSE, F("MQTT got topic: ") + String(topic)); + char *tpc = new char[strlen(topic) + 1]; + uint8_t cnt = 0; + DynamicJsonDocument json(128); + JsonObject root = json.to(); + + strncpy(tpc, topic, strlen(topic) + 1); + if(len > 0) { + char *pyld = new char[len + 1]; + strncpy(pyld, (const char*)payload, len); + pyld[len] = '\0'; + root["val"] = atoi(pyld); + delete[] pyld; } - } - - void onPublish(uint16_t packetId) { - Serial.println("Publish acknowledged."); - Serial.print(" packetId: "); - Serial.println(packetId); - } - - /*void reconnect(void) { - DPRINTLN(DBG_DEBUG, F("mqtt.h:reconnect")); - DPRINTLN(DBG_DEBUG, F("MQTT mClient->_state ") + String(mClient->state()) ); - - #ifdef ESP8266 - DPRINTLN(DBG_DEBUG, F("WIFI mEspClient.status ") + String(mEspClient.status()) ); - #endif - - boolean resub = false; - if(!mClient->connected() && (millis() - mLastReconnect) > MQTT_RECONNECT_DELAY ) { - mLastReconnect = millis(); - if(strlen(mDevName) > 0) { - // der Server und der Port müssen neu gesetzt werden, - // da ein MQTT_CONNECTION_LOST -3 die Werte zerstört hat. - mClient->setServer(mCfgMqtt->broker, mCfgMqtt->port); - mClient->setBufferSize(MQTT_MAX_PACKET_SIZE); - - char lwt[MQTT_TOPIC_LEN + 7 ]; // "/uptime" --> + 7 byte - snprintf(lwt, MQTT_TOPIC_LEN + 7, "%s/uptime", mCfgMqtt->topic); - - if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0)) - resub = mClient->connect(mDevName, mCfgMqtt->user, mCfgMqtt->pwd, lwt, 0, false, "offline"); - else - resub = mClient->connect(mDevName, lwt, 0, false, "offline"); - // ein Subscribe ist nur nach einem connect notwendig - if(resub) { - char topic[MQTT_TOPIC_LEN + 13 ]; // "/devcontrol/#" --> + 6 byte - // ToDo: "/devcontrol/#" is hardcoded - snprintf(topic, MQTT_TOPIC_LEN + 13, "%s/devcontrol/#", mCfgMqtt->topic); - DPRINTLN(DBG_INFO, F("subscribe to ") + String(topic)); - mClient->subscribe(topic); // subscribe to mTopic + "/devcontrol/#" + char *p = strtok(tpc, "/"); + p = strtok(NULL, "/"); // remove mCfgMqtt->topic + while(NULL != p) { + if(0 == cnt) { + if(0 == strncmp(p, "ctrl", 4)) { + if(NULL != (p = strtok(NULL, "/"))) { + root[F("path")] = F("ctrl"); + root[F("cmd")] = p; + } + } else if(0 == strncmp(p, "setup", 5)) { + if(NULL != (p = strtok(NULL, "/"))) { + root[F("path")] = F("setup"); + root[F("setup")] = p; + } + } else if(0 == strncmp(p, "status", 6)) { + if(NULL != (p = strtok(NULL, "/"))) { + root[F("path")] = F("status"); + root[F("cmd")] = p; + } } } + else if(1 == cnt) { + root["id"] = atoi(p); + } + p = strtok(NULL, "/"); + cnt++; } - }*/ + delete[] tpc; + + char out[128]; + serializeJson(root, out, 128); + DPRINTLN(DBG_INFO, "json: " + String(out)); + + mRxCnt++; + } const char *getFieldDeviceClass(uint8_t fieldId) { uint8_t pos = 0; @@ -487,11 +506,16 @@ class PubMqtt { uint32_t *mSunrise, *mSunset; HMSYSTEM *mSys; uint32_t *mUtcTimestamp; - uint32_t mTxCnt; + uint32_t mRxCnt, mTxCnt; std::queue mSendList; + bool mEnReconnect; + + // last will topic and payload must be available trough lifetime of 'espMqttClient' + char mLwtTopic[MQTT_TOPIC_LEN+7]; + const char* mLwtOnline = "online"; + const char* mLwtOffline = "offline"; const char *mDevName, *mVersion; - //uint32_t mLastReconnect; }; #endif /*__PUB_MQTT_H__*/ diff --git a/src/web/html/update.html b/src/web/html/update.html index b4c0f924..ecc44275 100644 --- a/src/web/html/update.html +++ b/src/web/html/update.html @@ -18,12 +18,6 @@
        -
        - Make sure that you have noted all your settings before starting an update. New versions may have changed their memory layout which can break your existing settings.
        -
        - Download your settings (JSON file) -
        -

        From b1946df32f20805738fce0ce0c362ba67e6553f8 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 23 Nov 2022 23:57:15 +0100 Subject: [PATCH 118/431] updated REST API and MQTT to use the same functionality added heap as MQTT publish updated User_Manual.md to latest changes development build will have now always the same name because of static link from https://ahoydtu.de --- .github/workflows/compile_development.yml | 2 +- User_Manual.md | 236 +++++++++++----------- src/app.cpp | 16 +- src/app.h | 5 +- src/defines.h | 2 +- src/publisher/pubMqtt.h | 166 +++++---------- src/web/html/index.html | 2 +- src/web/html/serial.html | 47 ++--- src/web/html/setup.html | 6 +- src/web/web.cpp | 5 +- src/web/web.h | 2 + src/web/webApi.cpp | 115 +++++------ src/web/webApi.h | 4 +- 13 files changed, 265 insertions(+), 343 deletions(-) diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index 274a6c73..ec435880 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -68,7 +68,7 @@ jobs: - name: Create Artifact uses: actions/upload-artifact@v3 with: - name: ${{ steps.rename-binary-files.outputs.name }}_dev_build + name: ahoydtu_dev path: | src/firmware/* src/User_Manual.md diff --git a/User_Manual.md b/User_Manual.md index 3b51a3e1..8be2d62c 100644 --- a/User_Manual.md +++ b/User_Manual.md @@ -1,4 +1,4 @@ -# User Manual Ahoy DTU (on ESP8266) +# User Manual AhoyDTU (on ESP8266) Version #{VERSION}# ## Introduction See the repository [README.md](Getting_Started.md) @@ -9,9 +9,9 @@ In the initial case or after click "erase settings" the fields for the inverter Set at least the serial number and a name for each inverter, check "reboot after save" and click the "Save" button. -## MQTT Output -The ahoy dtu will publish on the following topics -`//ch0/#` +## MQTT Output +The AhoyDTU will publish on the following topics +`//ch0/#` | Topic | Example Value | Remarks | |---|---|---| @@ -34,7 +34,7 @@ The ahoy dtu will publish on the following topics |PowerLimit | 80.000|actual set point for power limit control AC active power in percent| |LastAlarmCode | 1.000| Last Alarm Code eg. "inverter start"| -`//ch/#` +`//ch/#` `` is in the range 1 to 4 depending on the inverter type @@ -47,7 +47,8 @@ The ahoy dtu will publish on the following topics |YieldTotal | 110.819 | Energy converted to AC since reset Watt hours per module/channel (measured on DC) | |Irradiation |5.65 | ratio DC Power over set maximum power per module/channel in percent | -## Active Power Limit via Setup Page +## Active Power Limit via Serial / Control Page +URL: `/serial` If you leave the field "Active Power Limit" empty during the setup and reboot the ahoy-dtu will set a value of 65535 in the setup. That is the value you have to fill in case you want to operate the inverter without a active power limit. If the value is 65535 or -1 after another reboot the value will be set automatically to "100" and in the drop-down menu "relative in percent persistent" will be set. Of course you can do this also by your self. @@ -68,117 +69,137 @@ after a power cycle of the inverter (P_DC=0 and P_AC=0 for at least 10 seconds) The user has to ensure correct settings. Remember that for the inverters of 3rd generation the relative active power limit is in the range of 2% up to 100%. Also an absolute active power limit below approx. 30 Watt seems to be not meanful because of the control capabilities and reactive power load. -## Active Power Limit via MQTT -The ahoy-dtu subscribes on the topic `/devcontrol/#` if the mqtt broker is set-up correctly. The default topic is `inverter/devcontrol/#`. +## Control via MQTT -To set the active power limit (controled value is the AC Power of the inverter) you have four options. (Only single phase inverters are actually in focus). +### Generic Information -| topic | payload | active power limit in | Condition | -| --------------------------------------------------------------- | ----------- | -------------------------------------------- | -------------- | -| /devcontrol//11 OR /devcontrol//11/0 | [0..65535] | Watt | not persistent | -| /devcontrol//11/256 | [0..65535] | Watt | persistent | -| /devcontrol//11/1 | [2..100] | % | not persistent | -| /devcontrol//11/257 | [2..100] | % | persistent | +The AhoyDTU subscribes on three topics `/ctrl/#`, `/setup` and `/status`. +👆 `` can be set on setup page, default is `inverter`. 👆 `` is the number of the specific inverter in the setup page. -* First inverter --> `` = 0 -* Second inverter --> `` = 1 -* ... - -### Developer Information MQTT Interface -`/devcontrol///` - -The implementation allows to set any of the available `` Commands: -```C -typedef enum { - TurnOn = 0, // 0x00 - TurnOff = 1, // 0x01 - Restart = 2, // 0x02 - Lock = 3, // 0x03 - Unlock = 4, // 0x04 - ActivePowerContr = 11, // 0x0b - ReactivePowerContr = 12, // 0x0c - PFSet = 13, // 0x0d - CleanState_LockAndAlarm = 20, // 0x14 - SelfInspection = 40, // 0x28, self-inspection of grid-connected protection files - Init = 0xff -} DevControlCmdType; + +### Inverter Power (On / Off) +`/ctrl/power/` with payload `1` for `ON` and `0` for `OFF` +Example: +`inverter/ctrl/power/0` `1` + + +### Inverter restart + +`/ctrl/restart/` +Example: +`inverter/ctrl/restart/0` + + +### Power Limit relative persistent [%] + +`/ctrl/limit_persistent_relative/` with a payload `[2 .. 100]` +Example: +`inverter/ctrl/limit_persistent_relative/0` `70` + + +### Power Limit absolute persistent [Watts] + +`/ctrl/limit_persistent_relative/` with a payload `[0 .. 65535]` +Example: +`inverter/ctrl/limit_persistent_relative/0` `600` + + +### Power Limit relative non persistent [%] + +`/ctrl/limit_nonpersistent_relative/` with a payload `[2 .. 100]` +Example: +`inverter/ctrl/limit_nonpersistent_relative/0` `70` + + +### Power Limit absolute non persistent [Watts] + +`/ctrl/limit_nonpersistent_relative/` with a payload `[0 .. 65535]` +Example: +`inverter/ctrl/limit_nonpersistent_relative/0` `600` + + +## Control via REST API + +### Generic Information + +The rest API works with *JSON* POST requests. All the following instructions must be sent to the `/api` endpoint of the AhoyDTU. + +👆 `` is the number of the specific inverter in the setup page. + +### Inverter Power (On / Off) + +```json +{ + "id": , + "cmd": "power", + "val": +} ``` -The MQTT payload will be set on first to bytes and ``, which is taken from the topic path will be set on the second two bytes if the corresponding DevControlCmdType supports 4 byte data. -See here the actual implementation to set the send buffer bytes. -```C -void sendControlPacket(uint64_t invId, uint8_t cmd, uint16_t *data) { - sendCmdPacket(invId, TX_REQ_DEVCONTROL, ALL_FRAMES, false); - int cnt = 0; - // cmd --> 0x0b => Type_ActivePowerContr, 0 on, 1 off, 2 restart, 12 reactive power, 13 power factor - mTxBuf[10] = cmd; - mTxBuf[10 + (++cnt)] = 0x00; - if (cmd >= ActivePowerContr && cmd <= PFSet){ - mTxBuf[10 + (++cnt)] = ((data[0] * 10) >> 8) & 0xff; // power limit || high byte from MQTT payload - mTxBuf[10 + (++cnt)] = ((data[0] * 10) ) & 0xff; // power limit || low byte from MQTT payload - mTxBuf[10 + (++cnt)] = ((data[1] ) >> 8) & 0xff; // high byte from MQTT topic value - mTxBuf[10 + (++cnt)] = ((data[1] ) ) & 0xff; // low byte from MQTT topic value - } - // crc control data - uint16_t crc = Hoymiles::crc16(&mTxBuf[10], cnt+1); - mTxBuf[10 + (++cnt)] = (crc >> 8) & 0xff; - mTxBuf[10 + (++cnt)] = (crc ) & 0xff; - // crc over all - cnt +=1; - mTxBuf[10 + cnt] = Hoymiles::crc8(mTxBuf, 10 + cnt); - - sendPacket(invId, mTxBuf, 10 + (++cnt), true); +The `` should be set to `1` for `ON` and `0` for `OFF` + + +### Inverter restart + +```json +{ + "id": , + "cmd": "restart" } ``` -So as example sending any payload on `inverter/devcontrol/0/1` will switch off the inverter. -## Active Power Limit via REST API -It is also implemented to set the power limit via REST API call. Therefore send a POST request to the endpoint /api. -The response will always be a json with {success:true} -The payload shall be a json formated string in the following manner +### Power Limit relative persistent [%] + ```json { - "inverter":, - "tx_request": , - "cmd": , - "payload": , - "payload2": + "id": , + "cmd": "limit_persistent_relative", + "val": } ``` -With the following value ranges +The `VALUE` represents a percent number in a range of `[2 .. 100]` -| Value | range | note | -| --------------------------- | ----------- | ------------------------------- | -| | 81 or 21 | integer uint8, (0x15 or 0x51) | -| | [0...255] | integer uint8, subcmds eg. 0x0b | -| | [0...65535] | uint16 | -| | [0...3] | integer uint8 | +### Power Limit absolute persistent [Watts] -Example to set the active power limit non persistent to 10% ```json { - "inverter":0, - "tx_request": 81, - "cmd": 11, - "payload": 10, - "payload2": 1 + "id": , + "cmd": "limit_persistent_absolute", + "val": } ``` -Example to set the active power limit persistent to 600Watt +The `VALUE` represents watts in a range of `[0 .. 65535]` + + +### Power Limit relative non persistent [%] + ```json { - "inverter":0, - "tx_request": 81, - "cmd": 11, - "payload": 600, - "payload2": 256 + "id": , + "cmd": "limit_nonpersistent_relative", + "val": } ``` +The `VALUE` represents a percent number in a range of `[2 .. 100]` -### Developer Information REST API + +### Power Limit absolute non persistent [Watts] + +```json +{ + "id": , + "cmd": "limit_nonpersistent_absolute", + "val": +} +``` +The `VALUE` represents watts in a range of `[0 .. 65535]` + + + +### Developer Information REST API (obsolete) In the same approach as for MQTT any other SubCmd and also MainCmd can be applied and the response payload can be observed in the serial logs. Eg. request the Alarm-Data from the Alarm-Index 5 from inverter 0 will look like this: ```json { @@ -190,38 +211,15 @@ In the same approach as for MQTT any other SubCmd and also MainCmd can be applie } ``` -## Zero Export Control -* You can use the mqtt topic `/devcontrol//11` with a number as payload (eg. 300 -> 300 Watt) to set the power limit to the published number in Watt. (In regular cases the inverter will use the new set point within one intervall period; to verify this see next bullet) -* You can check the inverter set point for the power limit control on the topic `//ch0/PowerLimit` 👆 This value is ALWAYS in percent of the maximum power limit of the inverter. In regular cases this value will be updated within approx. 15 seconds. (depends on request intervall) -* You can monitor the actual AC power by subscribing to the topic `//ch0/P_AC` 👆 This value is ALWAYS in Watt - -## Issues and Debuging for active power limit settings +## Zero Export Control (needs rework) +* You can use the mqtt topic `/devcontrol//11` with a number as payload (eg. 300 -> 300 Watt) to set the power limit to the published number in Watt. (In regular cases the inverter will use the new set point within one intervall period; to verify this see next bullet) +* You can check the inverter set point for the power limit control on the topic `//ch0/PowerLimit` 👆 This value is ALWAYS in percent of the maximum power limit of the inverter. In regular cases this value will be updated within approx. 15 seconds. (depends on request intervall) +* You can monitor the actual AC power by subscribing to the topic `//ch0/P_AC` 👆 This value is ALWAYS in Watt -Turn on the serial debugging in the setup. Try to have find out if the behavior is deterministic. That means can you reproduce the behavior. Be patient and wait on inverter reactions at least some minutes and beware that the DC-Power is sufficient. - -In case of issues please report: - -1. Version of firmware -2. The output of the serial debug esp. the TX messages starting with "0x51" and the RX messages starting with "0xD1" or "0xF1" -3. Which case you have tried: Setup-Page, MQTT, REST API and at what was shown on the "Visualization Page" at the Location "Limit" -4. The setting means payload, relative, absolute, persistent, not persistent (see tables above) - -**Developer Information General for Active Power Limit** - -⚡The following was verified by field tests and feedback from users - -Internally this values will be set for the second two bytes for MainCmd: 0x51 SubCmd: 0x0b --> DevControl set ActivePowerLimit -```C -typedef enum { - AbsolutNonPersistent = 0x0000, // 0 - RelativNonPersistent = 0x0001, // 1 - AbsolutPersistent = 0x0100, // 256 - RelativPersistent = 0x0101 // 257 -} PowerLimitControlType; -``` ## Firmware Version collection Gather user inverter information here to understand what differs between some inverters. +To get the information open the URL `/api/record/info` on your AhoyDTU. The information will only be present once the AhoyDTU was able to communicate with an inverter. | Name | Inverter Typ | Bootloader V. | FWVersion | FWBuild [YYYY] | FWBuild [MM-DD] | HWPartId | | | | ---------- | ------------ | ------------- | --------- | -------------- | --------------- | --------- | -------- | --------- | diff --git a/src/app.cpp b/src/app.cpp index 782ae853..e7b86283 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -12,6 +12,12 @@ #include #include "utils/sun.h" +//----------------------------------------------------------------------------- +app::app() : ah::Scheduler() { + mWeb = NULL; +} + + //----------------------------------------------------------------------------- void app::setup(uint32_t timeout) { Serial.begin(115200); @@ -39,7 +45,6 @@ void app::setup(uint32_t timeout) { mWifi = new ahoywifi(mConfig); mWifi->setup(timeout, mSettings.getValid()); - mPayload.setup(mSys); mPayload.enableSerialDebug(mConfig->serial.debug); #if !defined(AP_ONLY) @@ -48,6 +53,7 @@ void app::setup(uint32_t timeout) { addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt)); addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt)); addListener(EVERY_HR, std::bind(&PubMqttType::tickerHour, &mMqtt)); + mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); } #endif setupLed(); @@ -226,8 +232,6 @@ void app::resetSystem(void) { mSunrise = 0; mSunset = 0; - mHeapStatCnt = 0; - mSendTicker = 0xffff; mTicker = 0; @@ -240,6 +244,12 @@ void app::resetSystem(void) { memset(&mStat, 0, sizeof(statistics_t)); } +//----------------------------------------------------------------------------- +void app::mqttSubRxCb(JsonObject obj) { + if(NULL != mWeb) + mWeb->apiCtrlRequest(obj); +} + //----------------------------------------------------------------------------- void app::setupLed(void) { /** LED connection diagram diff --git a/src/app.h b/src/app.h index 0d5b49cb..038be0c4 100644 --- a/src/app.h +++ b/src/app.h @@ -43,7 +43,7 @@ class web; class app : public ah::Scheduler { public: - app() : ah::Scheduler() {} + app(); ~app() {} void setup(uint32_t timeout); @@ -140,7 +140,7 @@ class app : public ah::Scheduler { private: void resetSystem(void); - void setupMqtt(void); + void mqttSubRxCb(JsonObject obj); void setupLed(void); void updateLed(void); @@ -197,7 +197,6 @@ class app : public ah::Scheduler { } uint32_t mUptimeSecs; - uint8_t mHeapStatCnt; uint32_t mUtcTimestamp; bool mUpdateNtp; diff --git a/src/defines.h b/src/defines.h index ea772a5f..930e4243 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 42 +#define VERSION_PATCH 43 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index fb3d8669..2a42501a 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -3,6 +3,8 @@ // Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ //----------------------------------------------------------------------------- +// https://bert.emelis.net/espMqttClient/ + #ifndef __PUB_MQTT_H__ #define __PUB_MQTT_H__ @@ -20,10 +22,9 @@ #include "../defines.h" #include "../hm/hmSystem.h" - #define QOS_0 0 -//https://bert.emelis.net/espMqttClient/ +typedef std::function subscriptionCb; template class PubMqtt { @@ -32,6 +33,7 @@ class PubMqtt { mRxCnt = 0; mTxCnt = 0; mEnReconnect = false; + mSubscriptionCb = NULL; } ~PubMqtt() { } @@ -47,9 +49,12 @@ class PubMqtt { snprintf(mLwtTopic, MQTT_TOPIC_LEN + 7, "%s/status", mCfgMqtt->topic); + #if defined(ESP8266) mHWifiCon = WiFi.onStationModeGotIP(std::bind(&PubMqtt::onWifiConnect, this, std::placeholders::_1)); mHWifiDiscon = WiFi.onStationModeDisconnected(std::bind(&PubMqtt::onWifiDisconnect, this, std::placeholders::_1)); - + #else + WiFi.onEvent(std::bind(&PubMqtt::onWiFiEvent, this, std::placeholders::_1)); + #endif if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0)) mClient.setCredentials(mCfgMqtt->user, mCfgMqtt->pwd); @@ -62,7 +67,9 @@ class PubMqtt { } void loop() { + #if defined(ESP8266) mClient.loop(); + #endif } void tickerSecond() { @@ -74,6 +81,7 @@ class PubMqtt { snprintf(val, 12, "%ld", millis() / 1000); publish("uptime", val); publish("wifi_rssi", String(WiFi.RSSI()).c_str()); + publish("free_heap", String(ESP.getFreeHeap()).c_str()); if(!mClient.connected()) { if(mEnReconnect) @@ -102,6 +110,14 @@ class PubMqtt { mClient.subscribe(topic, QOS_0); } + void payloadEventListener(uint8_t cmd) { + mSendList.push(cmd); + } + + void setSubscriptionCb(subscriptionCb cb) { + mSubscriptionCb = cb; + } + inline bool isConnected() { return mClient.connected(); } @@ -114,10 +130,6 @@ class PubMqtt { return mRxCnt; } - void payloadEventListener(uint8_t cmd) { - mSendList.push(cmd); - } - void sendMqttDiscoveryConfig(const char *topic) { DPRINTLN(DBG_VERBOSE, F("sendMqttDiscoveryConfig")); @@ -169,6 +181,7 @@ class PubMqtt { } private: + #if defined(ESP8266) void onWifiConnect(const WiFiEventStationModeGotIP& event) { DPRINTLN(DBG_VERBOSE, F("MQTT connecting")); mClient.connect(); @@ -178,6 +191,24 @@ class PubMqtt { mEnReconnect = false; } + #else + void onWiFiEvent(WiFiEvent_t event) { + switch(event) { + case SYSTEM_EVENT_STA_GOT_IP: + DPRINTLN(DBG_VERBOSE, F("MQTT connecting")); + mClient.connect(); + break; + + case SYSTEM_EVENT_STA_DISCONNECTED: + mEnReconnect = false; + break; + + default: + break; + } + } + #endif + void onConnect(bool sessionPreset) { DPRINTLN(DBG_INFO, F("MQTT connected")); mEnReconnect = true; @@ -185,7 +216,6 @@ class PubMqtt { publish("version", mVersion, true); publish("device", mDevName, true); publish("uptime", "0"); - publish(mLwtTopic, mLwtOnline, true, false); subscribe("ctrl/#"); @@ -221,6 +251,9 @@ class PubMqtt { void onMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) { DPRINTLN(DBG_VERBOSE, F("MQTT got topic: ") + String(topic)); + if(NULL == mSubscriptionCb) + return; + char *tpc = new char[strlen(topic) + 1]; uint8_t cnt = 0; DynamicJsonDocument json(128); @@ -247,7 +280,7 @@ class PubMqtt { } else if(0 == strncmp(p, "setup", 5)) { if(NULL != (p = strtok(NULL, "/"))) { root[F("path")] = F("setup"); - root[F("setup")] = p; + root[F("cmd")] = p; } } else if(0 == strncmp(p, "status", 6)) { if(NULL != (p = strtok(NULL, "/"))) { @@ -257,16 +290,18 @@ class PubMqtt { } } else if(1 == cnt) { - root["id"] = atoi(p); + root[F("id")] = atoi(p); } p = strtok(NULL, "/"); cnt++; } delete[] tpc; - char out[128]; + /*char out[128]; serializeJson(root, out, 128); - DPRINTLN(DBG_INFO, "json: " + String(out)); + DPRINTLN(DBG_INFO, "json: " + String(out));*/ + if(NULL != mSubscriptionCb) + (mSubscriptionCb)(root); mRxCnt++; } @@ -396,112 +431,11 @@ class PubMqtt { } } -// void cbMqtt(char *topic, byte *payload, unsigned int length) { -// // callback handling on subscribed devcontrol topic -// DPRINTLN(DBG_INFO, F("cbMqtt")); -// // subcribed topics are mTopic + "/devcontrol/#" where # is / -// // eg. mypvsolar/devcontrol/1/11 with payload "400" --> inverter 1 active power limit 400 Watt -// const char *token = strtok(topic, "/"); -// while (token != NULL) { -// if (strcmp(token, "devcontrol") == 0) { -// token = strtok(NULL, "/"); -// uint8_t iv_id = std::stoi(token); -// -// if (iv_id >= 0 && iv_id <= MAX_NUM_INVERTERS) { -// Inverter<> *iv = mSys->getInverterByPos(iv_id); -// if (NULL != iv) { -// if (!iv->devControlRequest) { // still pending -// token = strtok(NULL, "/"); -// -// switch (std::stoi(token)) { -// // Active Power Control -// case ActivePowerContr: -// token = strtok(NULL, "/"); // get ControlMode aka "PowerPF.Desc" in DTU-Pro Code from topic string -// if (token == NULL) // default via mqtt ommit the LimitControlMode -// iv->powerLimit[1] = AbsolutNonPersistent; -// else -// iv->powerLimit[1] = std::stoi(token); -// if (length <= 5) { // if (std::stoi((char*)payload) > 0) more error handling powerlimit needed? -// if (iv->powerLimit[1] >= AbsolutNonPersistent && iv->powerLimit[1] <= RelativPersistent) { -// iv->devControlCmd = ActivePowerContr; -// iv->powerLimit[0] = std::stoi(std::string((char *)payload, (unsigned int)length)); // THX to @silversurfer -// /*if (iv->powerLimit[1] & 0x0001) -// DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("%")); -// else -// DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W"));*/ -// -// DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + String(iv->powerLimit[1] & 0x0001) ? F("%") : F("W")); -// } -// iv->devControlRequest = true; -// } else { -// DPRINTLN(DBG_INFO, F("Invalid mqtt payload recevied: ") + String((char *)payload)); -// } -// break; -// -// // Turn On -// case TurnOn: -// iv->devControlCmd = TurnOn; -// DPRINTLN(DBG_INFO, F("Turn on inverter ") + String(iv->id)); -// iv->devControlRequest = true; -// break; -// -// // Turn Off -// case TurnOff: -// iv->devControlCmd = TurnOff; -// DPRINTLN(DBG_INFO, F("Turn off inverter ") + String(iv->id)); -// iv->devControlRequest = true; -// break; -// -// // Restart -// case Restart: -// iv->devControlCmd = Restart; -// DPRINTLN(DBG_INFO, F("Restart inverter ") + String(iv->id)); -// iv->devControlRequest = true; -// break; -// -// // Reactive Power Control -// case ReactivePowerContr: -// iv->devControlCmd = ReactivePowerContr; -// if (true) { // if (std::stoi((char*)payload) > 0) error handling powerlimit needed? -// iv->devControlCmd = ReactivePowerContr; -// iv->powerLimit[0] = std::stoi(std::string((char *)payload, (unsigned int)length)); -// iv->powerLimit[1] = 0x0000; // if reactivepower limit is set via external interface --> set it temporay -// DPRINTLN(DBG_DEBUG, F("Reactivepower limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W")); -// iv->devControlRequest = true; -// } -// break; -// -// // Set Power Factor -// case PFSet: -// // iv->devControlCmd = PFSet; -// // uint16_t power_factor = std::stoi(strtok(NULL, "/")); -// DPRINTLN(DBG_INFO, F("Set Power Factor not implemented for inverter ") + String(iv->id)); -// break; -// -// // CleanState lock & alarm -// case CleanState_LockAndAlarm: -// iv->devControlCmd = CleanState_LockAndAlarm; -// DPRINTLN(DBG_INFO, F("CleanState lock & alarm for inverter ") + String(iv->id)); -// iv->devControlRequest = true; -// break; -// -// default: -// DPRINTLN(DBG_INFO, "Not implemented"); -// break; -// } -// } -// } -// } -// break; -// } -// token = strtok(NULL, "/"); -// } -// DPRINTLN(DBG_INFO, F("app::cbMqtt finished")); -// } - espMqttClient mClient; cfgMqtt_t *mCfgMqtt; + #if defined(ESP8266) WiFiEventHandler mHWifiCon, mHWifiDiscon; + #endif uint32_t *mSunrise, *mSunset; HMSYSTEM *mSys; @@ -509,12 +443,12 @@ class PubMqtt { uint32_t mRxCnt, mTxCnt; std::queue mSendList; bool mEnReconnect; + subscriptionCb mSubscriptionCb; // last will topic and payload must be available trough lifetime of 'espMqttClient' char mLwtTopic[MQTT_TOPIC_LEN+7]; const char* mLwtOnline = "online"; const char* mLwtOffline = "offline"; - const char *mDevName, *mVersion; }; diff --git a/src/web/html/index.html b/src/web/html/index.html index c2d25038..96c92feb 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -97,7 +97,7 @@ var date = new Date(); var obj = new Object(); obj.cmd = "set_time"; - obj.ts = parseInt(date.getTime() / 1000); + obj.val = parseInt(date.getTime() / 1000); getAjax("/api/setup", apiCb, "POST", JSON.stringify(obj)); } diff --git a/src/web/html/serial.html b/src/web/html/serial.html index b36d2350..c7e3dd8b 100644 --- a/src/web/html/serial.html +++ b/src/web/html/serial.html @@ -45,15 +45,15 @@


        - + - - - - - - + + + +
        @@ -152,7 +152,6 @@ } - // only for test function ctrlCb(obj) { var e = document.getElementById("result"); if(obj["success"]) @@ -169,44 +168,36 @@ const wrapper = document.getElementById('power'); wrapper.addEventListener('click', (event) => { - var power = event.target.value; var obj = new Object(); + obj.id = get_selected_iv(); + obj.cmd = "power"; - switch (power) - { + switch (event.target.value) { + default: case "Turn On": - obj.cmd = 0; + obj.val = 1; break; case "Turn Off": - obj.cmd = 1; + obj.val = 0; break; - default: - obj.cmd = 2; } - obj.inverter = get_selected_iv(); - obj.tx_request = 81; getAjax("/api/ctrl", ctrlCb, "POST", JSON.stringify(obj)); }); document.getElementById("sendpwrlim").addEventListener("click", function() { var val = parseInt(document.getElementsByName('pwrlimval')[0].value); - var ctrl = parseInt(document.getElementsByName('pwrlimcntrl')[0].value); - - if((ctrl == 1 || ctrl == 257) && val < 2) val = 2; + var cmd = document.getElementsByName('pwrlimctrl')[0].value; - if(isNaN(val) || isNaN(ctrl)) - { - var tmp = (isNaN(val)) ? "Value" : "Unit"; - document.getElementById("result").textContent = tmp + " is missing"; + if(isNaN(val)) { + document.getElementById("result").textContent = "value is missing"; return; } var obj = new Object(); - obj.inverter = get_selected_iv(); - obj.cmd = 11; - obj.tx_request = 81; - obj.payload = [val, ctrl]; + obj.id = get_selected_iv(); + obj.cmd = cmd; + obj.val = val; getAjax("/api/ctrl", ctrlCb, "POST", JSON.stringify(obj)); }); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index c86b7b4b..0a586849 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -50,7 +50,7 @@
        @@ -226,7 +226,7 @@ var date = new Date(); var obj = new Object(); obj.cmd = "set_time"; - obj.ts = parseInt(date.getTime() / 1000); + obj.val = parseInt(date.getTime() / 1000); getAjax("/api/setup", apiCbNtp, "POST", JSON.stringify(obj)); } @@ -234,7 +234,7 @@ var obj = new Object(); obj.cmd = "scan_wifi"; getAjax("/api/setup", apiCbWifi, "POST", JSON.stringify(obj)); - setTimeout(function() {getAjax('/api/setup/networks', listNetworks)}, 7000); + setTimeout(function() {getAjax('/api/setup/networks', listNetworks)}, 5000); } function syncTime() { diff --git a/src/web/web.cpp b/src/web/web.cpp index 3db382ef..d302eee3 100644 --- a/src/web/web.cpp +++ b/src/web/web.cpp @@ -648,9 +648,12 @@ void web::serialCb(String msg) { mSerialBufFill = 0; mEvts->send("webSerial, buffer overflow!", "serial", millis()); } - } +//----------------------------------------------------------------------------- +void web::apiCtrlRequest(JsonObject obj) { + mApi->ctrlRequest(obj); +} //----------------------------------------------------------------------------- #ifdef ENABLE_JSON_EP diff --git a/src/web/web.h b/src/web/web.h index 2c74faf5..849f1caa 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -40,6 +40,8 @@ class web { void serialCb(String msg); + void apiCtrlRequest(JsonObject obj); + private: void onConnect(AsyncEventSourceClient *client); diff --git a/src/web/webApi.cpp b/src/web/webApi.cpp index e71aa511..82a9efda 100644 --- a/src/web/webApi.cpp +++ b/src/web/webApi.cpp @@ -27,13 +27,26 @@ void webApi::setup(void) { mSrv->on("/api", HTTP_POST, std::bind(&webApi::onApiPost, this, std::placeholders::_1)).onBody( std::bind(&webApi::onApiPostBody, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); - mSrv->on("/get_setup", HTTP_GET, std::bind(&webApi::onDwnldSetup, this, std::placeholders::_1)); + mSrv->on("/get_setup", HTTP_GET, std::bind(&webApi::onDwnldSetup, this, std::placeholders::_1)); } //----------------------------------------------------------------------------- void webApi::loop(void) { } +//----------------------------------------------------------------------------- +void webApi::ctrlRequest(JsonObject obj) { + /*char out[128]; + serializeJson(obj, out, 128); + DPRINTLN(DBG_INFO, "webApi: " + String(out));*/ + DynamicJsonDocument json(128); + JsonObject dummy = json.to(); + if(obj[F("path")] == "ctrl") + setCtrl(obj, dummy); + else if(obj[F("path")] == "setup") + setSetup(obj, dummy); +} + //----------------------------------------------------------------------------- void webApi::onApi(AsyncWebServerRequest *request) { @@ -333,7 +346,7 @@ void webApi::getStaticIp(JsonObject obj) { void webApi::getMenu(JsonObject obj) { obj["name"][0] = "Live"; obj["link"][0] = "/live"; - obj["name"][1] = "Serial Console"; + obj["name"][1] = "Serial / Control"; obj["link"][1] = "/serial"; obj["name"][2] = "Settings"; obj["link"][2] = "/setup"; @@ -346,10 +359,14 @@ void webApi::getMenu(JsonObject obj) { obj["link"][6] = "/update"; obj["name"][7] = "System"; obj["link"][7] = "/system"; + obj["name"][8] = "-"; + obj["name"][9] = "Documentation"; + obj["link"][9] = "https://ahoydtu.de"; + obj["trgt"][9] = "_blank"; if(strlen(mConfig->sys.adminPwd) > 0) { - obj["name"][8] = "-"; - obj["name"][9] = "Logout"; - obj["link"][9] = "/logout"; + obj["name"][10] = "-"; + obj["name"][11] = "Logout"; + obj["link"][11] = "/logout"; } } @@ -494,72 +511,50 @@ void webApi::getRecord(JsonObject obj, record_t<> *rec) { //----------------------------------------------------------------------------- bool webApi::setCtrl(JsonObject jsonIn, JsonObject jsonOut) { - uint8_t cmd = jsonIn[F("cmd")]; - - // Todo: num is the inverter number 0-3. For better display in DPRINTLN - uint8_t num = jsonIn[F("inverter")]; - uint8_t tx_request = jsonIn[F("tx_request")]; - - if(TX_REQ_DEVCONTROL == tx_request) - { - DPRINTLN(DBG_INFO, F("devcontrol [") + String(num) + F("], cmd: 0x") + String(cmd, HEX)); - - Inverter<> *iv = getInverter(jsonIn, jsonOut); - JsonArray payload = jsonIn[F("payload")].as(); - - if(NULL != iv) - { - switch (cmd) - { - case TurnOn: - iv->devControlCmd = TurnOn; - iv->devControlRequest = true; - break; - case TurnOff: - iv->devControlCmd = TurnOff; - iv->devControlRequest = true; - break; - case CleanState_LockAndAlarm: - iv->devControlCmd = CleanState_LockAndAlarm; - iv->devControlRequest = true; - break; - case Restart: - iv->devControlCmd = Restart; - iv->devControlRequest = true; - break; - case ActivePowerContr: - iv->devControlCmd = ActivePowerContr; - iv->devControlRequest = true; - iv->powerLimit[0] = payload[0]; - iv->powerLimit[1] = payload[1]; - break; - default: - jsonOut["error"] = "unknown 'cmd' = " + String(cmd); - return false; - } - } else { - return false; - } + Inverter<> *iv = mApp->mSys->getInverterByPos(jsonIn[F("id")]); + if(NULL == iv) { + jsonOut[F("error")] = F("inverter index invalid: ") + jsonIn[F("id")].as(); + return false; + } + + if(F("power") == jsonIn[F("cmd")]) { + iv->devControlCmd = (jsonIn[F("val")] == 1) ? TurnOn : TurnOff; + iv->devControlRequest = true; + } else if(F("restart") == jsonIn[F("restart")]) { + iv->devControlCmd = Restart; + iv->devControlRequest = true; + } + else if(0 == strncmp("limit_", jsonIn[F("cmd")].as(), 6)) { + iv->powerLimit[0] = jsonIn["val"]; + if(F("limit_persistent_relative") == jsonIn[F("cmd")]) + iv->powerLimit[1] = RelativPersistent; + else if(F("limit_persistent_absolute") == jsonIn[F("cmd")]) + iv->powerLimit[1] = AbsolutPersistent; + else if(F("limit_nonpersistent_relative") == jsonIn[F("cmd")]) + iv->powerLimit[1] = RelativNonPersistent; + else if(F("limit_nonpersistent_absolute") == jsonIn[F("cmd")]) + iv->powerLimit[1] = AbsolutNonPersistent; + iv->devControlCmd = ActivePowerContr; + iv->devControlRequest = true; } else { - jsonOut[F("error")] = F("unknown 'tx_request'"); + jsonOut[F("error")] = F("unknown cmd: '") + jsonIn["cmd"].as() + "'"; return false; } return true; } - //----------------------------------------------------------------------------- bool webApi::setSetup(JsonObject jsonIn, JsonObject jsonOut) { if(F("scan_wifi") == jsonIn[F("cmd")]) mApp->scanAvailNetworks(); else if(F("set_time") == jsonIn[F("cmd")]) - mApp->setTimestamp(jsonIn[F("ts")]); + mApp->setTimestamp(jsonIn[F("val")]); else if(F("sync_ntp") == jsonIn[F("cmd")]) mApp->setTimestamp(0); // 0: update ntp flag else if(F("serial_utc_offset") == jsonIn[F("cmd")]) - mTimezoneOffset = jsonIn[F("ts")]; + mTimezoneOffset = jsonIn[F("val")]; else if(F("discovery_cfg") == jsonIn[F("cmd")]) mApp->mFlagSendDiscoveryConfig = true; // for homeassistant else { @@ -569,13 +564,3 @@ bool webApi::setSetup(JsonObject jsonIn, JsonObject jsonOut) { return true; } - - -//----------------------------------------------------------------------------- -Inverter<> *webApi::getInverter(JsonObject jsonIn, JsonObject jsonOut) { - uint8_t id = jsonIn[F("inverter")]; - Inverter<> *iv = mApp->mSys->getInverterByPos(id); - if(NULL == iv) - jsonOut[F("error")] = F("inverter index to high: ") + String(id); - return iv; -} diff --git a/src/web/webApi.h b/src/web/webApi.h index 873080d7..de37d9ba 100644 --- a/src/web/webApi.h +++ b/src/web/webApi.h @@ -25,6 +25,8 @@ class webApi { return mTimezoneOffset; } + void ctrlRequest(JsonObject obj); + private: void onApi(AsyncWebServerRequest *request); void onApiPost(AsyncWebServerRequest *request); @@ -57,8 +59,6 @@ class webApi { bool setCtrl(JsonObject jsonIn, JsonObject jsonOut); bool setSetup(JsonObject jsonIn, JsonObject jsonOut); - Inverter<> *getInverter(JsonObject jsonIn, JsonObject jsonOut); - double round3(double value) { return (int)(value * 1000 + 0.5) / 1000.0; } From 1c7746b73ff66dce5fe2e2483175fc2e1254699e Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 24 Nov 2022 00:00:38 +0100 Subject: [PATCH 119/431] User_Manual.md format --- User_Manual.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/User_Manual.md b/User_Manual.md index 8be2d62c..4f26a150 100644 --- a/User_Manual.md +++ b/User_Manual.md @@ -76,13 +76,20 @@ Also an absolute active power limit below approx. 30 Watt seems to be not meanfu The AhoyDTU subscribes on three topics `/ctrl/#`, `/setup` and `/status`. 👆 `` can be set on setup page, default is `inverter`. + 👆 `` is the number of the specific inverter in the setup page. ### Inverter Power (On / Off) -`/ctrl/power/` with payload `1` for `ON` and `0` for `OFF` +```mqtt +/ctrl/power/ +``` +with payload `1` for `ON` and `0` for `OFF` + Example: +```mqtt `inverter/ctrl/power/0` `1` +``` ### Inverter restart From f4c3aea9648f4c4014c34578152071746bfd1822 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 24 Nov 2022 00:04:07 +0100 Subject: [PATCH 120/431] update User_Manual.md --- User_Manual.md | 58 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/User_Manual.md b/User_Manual.md index 4f26a150..3556c1d1 100644 --- a/User_Manual.md +++ b/User_Manual.md @@ -84,48 +84,66 @@ The AhoyDTU subscribes on three topics `/ctrl/#`, `/setup` and `/ctrl/power/ ``` -with payload `1` for `ON` and `0` for `OFF` +with payload `1` = `ON` and `0` = `OFF` Example: ```mqtt -`inverter/ctrl/power/0` `1` +inverter/ctrl/power/0 1 ``` - ### Inverter restart - -`/ctrl/restart/` +```mqtt +/ctrl/restart/ +``` Example: -`inverter/ctrl/restart/0` - +```mqtt +inverter/ctrl/restart/0 +``` ### Power Limit relative persistent [%] -`/ctrl/limit_persistent_relative/` with a payload `[2 .. 100]` -Example: -`inverter/ctrl/limit_persistent_relative/0` `70` +```mqtt +/ctrl/limit_persistent_relative/ +``` +with a payload `[2 .. 100]` +Example: +```mqtt +inverter/ctrl/limit_persistent_relative/0 70 +``` ### Power Limit absolute persistent [Watts] +```mqtt +/ctrl/limit_persistent_relative/ +``` +with a payload `[0 .. 65535]` -`/ctrl/limit_persistent_relative/` with a payload `[0 .. 65535]` Example: -`inverter/ctrl/limit_persistent_relative/0` `600` - +```mqtt +inverter/ctrl/limit_persistent_relative/0 600 +``` ### Power Limit relative non persistent [%] +```mqtt +/ctrl/limit_nonpersistent_relative/ +``` +with a payload `[2 .. 100]` -`/ctrl/limit_nonpersistent_relative/` with a payload `[2 .. 100]` Example: -`inverter/ctrl/limit_nonpersistent_relative/0` `70` - +```mqtt +inverter/ctrl/limit_nonpersistent_relative/0 70 +``` ### Power Limit absolute non persistent [Watts] +```mqtt +/ctrl/limit_nonpersistent_relative/ +``` +with a payload `[0 .. 65535]` -`/ctrl/limit_nonpersistent_relative/` with a payload `[0 .. 65535]` Example: -`inverter/ctrl/limit_nonpersistent_relative/0` `600` - +```mqtt +inverter/ctrl/limit_nonpersistent_relative/0 600 +``` ## Control via REST API @@ -144,7 +162,7 @@ The rest API works with *JSON* POST requests. All the following instructions mus "val": } ``` -The `` should be set to `1` for `ON` and `0` for `OFF` +The `` should be set to `1` = `ON` and `0` = `OFF` ### Inverter restart From 0a5833e6ec299db994218d17d2f0bf2791b2070f Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 28 Nov 2022 17:58:02 +0100 Subject: [PATCH 121/431] improved mqtt removed wrong "inverter type can't be detected!" messages repaired NTP and static IP #459 MQTT status about availability and produce are retain messages now --- src/config/settings.h | 41 +++++++++++-------------------------- src/defines.h | 2 +- src/hm/hmSystem.h | 2 +- src/publisher/pubMqtt.h | 11 ++++++---- src/utils/helper.cpp | 29 ++++++++++++++++++++++++++ src/utils/helper.h | 19 +++++++++++++++++ src/web/html/index.html | 4 ++-- src/web/web.cpp | 45 +++++++++++++++++------------------------ src/web/web.h | 9 --------- src/web/webApi.cpp | 15 +++++++------- src/web/webApi.h | 6 ------ 11 files changed, 96 insertions(+), 87 deletions(-) create mode 100644 src/utils/helper.cpp create mode 100644 src/utils/helper.h diff --git a/src/config/settings.h b/src/config/settings.h index 376dea09..c37c19fa 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -10,6 +10,7 @@ #include #include #include "../utils/dbg.h" +#include "../utils/helper.h" #include "../defines.h" /** @@ -223,25 +224,6 @@ class settings { return saveSettings(); } - String ip2Str(uint8_t ip[]) { - return String(ip[0]) + F(".") - + String(ip[1]) + F(".") - + String(ip[2]) + F(".") - + String(ip[3]); - } - - void ip2Arr(uint8_t ip[], const char *ipStr) { - char *tmp = new char[strlen(ipStr)]; - strncpy(tmp, ipStr, strlen(ipStr)); - char *p = strtok(tmp, "."); - uint8_t i = 0; - while(NULL != p) { - ip[i++] = atoi(p); - p = strtok(NULL, "."); - } - delete[] tmp; - } - private: void loadDefaults(bool wifi = true) { DPRINTLN(DBG_INFO, F("loadDefaults")); @@ -288,25 +270,26 @@ class settings { void jsonWifi(JsonObject obj, bool set = false) { if(set) { + char buf[16]; obj[F("ssid")] = mCfg.sys.stationSsid; obj[F("pwd")] = mCfg.sys.stationPwd; obj[F("dev")] = mCfg.sys.deviceName; obj[F("adm")] = mCfg.sys.adminPwd; - obj[F("ip")] = ip2Str(mCfg.sys.ip.ip); - obj[F("mask")] = ip2Str(mCfg.sys.ip.mask); - obj[F("dns1")] = ip2Str(mCfg.sys.ip.dns1); - obj[F("dns2")] = ip2Str(mCfg.sys.ip.dns2); - obj[F("gtwy")] = ip2Str(mCfg.sys.ip.gateway); + ah::ip2Char(mCfg.sys.ip.ip, buf); obj[F("ip")] = String(buf); + ah::ip2Char(mCfg.sys.ip.mask, buf); obj[F("mask")] = String(buf); + ah::ip2Char(mCfg.sys.ip.dns1, buf); obj[F("dns1")] = String(buf); + ah::ip2Char(mCfg.sys.ip.dns2, buf); obj[F("dns2")] = String(buf); + ah::ip2Char(mCfg.sys.ip.gateway, buf); obj[F("gtwy")] = String(buf); } else { snprintf(mCfg.sys.stationSsid, SSID_LEN, "%s", obj[F("ssid")].as()); snprintf(mCfg.sys.stationPwd, PWD_LEN, "%s", obj[F("pwd")].as()); snprintf(mCfg.sys.deviceName, DEVNAME_LEN, "%s", obj[F("dev")].as()); snprintf(mCfg.sys.adminPwd, PWD_LEN, "%s", obj[F("adm")].as()); - ip2Arr(mCfg.sys.ip.ip, obj[F("ip")]); - ip2Arr(mCfg.sys.ip.mask, obj[F("mask")]); - ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")]); - ip2Arr(mCfg.sys.ip.dns2, obj[F("dns2")]); - ip2Arr(mCfg.sys.ip.gateway, obj[F("gtwy")]); + ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as()); + ah::ip2Arr(mCfg.sys.ip.mask, obj[F("mask")].as()); + ah::ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")].as()); + ah::ip2Arr(mCfg.sys.ip.dns2, obj[F("dns2")].as()); + ah::ip2Arr(mCfg.sys.ip.gateway, obj[F("gtwy")].as()); } } diff --git a/src/defines.h b/src/defines.h index 930e4243..62f2cc42 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 43 +#define VERSION_PATCH 44 //------------------------------------- typedef struct { diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 53b6e85d..5338d1a0 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -70,7 +70,7 @@ class HmSystem { break; } } - else + else if(p->config->serial.u64 != 0ULL) DPRINTLN(DBG_ERROR, F("inverter type can't be detected!")); p->init(); diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 2a42501a..89d8633b 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -111,7 +111,8 @@ class PubMqtt { } void payloadEventListener(uint8_t cmd) { - mSendList.push(cmd); + if(mClient.connected()) // prevent overflow if MQTT broker is not reachable but set + mSendList.push(cmd); } void setSubscriptionCb(subscriptionCb cb) { @@ -185,6 +186,7 @@ class PubMqtt { void onWifiConnect(const WiFiEventStationModeGotIP& event) { DPRINTLN(DBG_VERBOSE, F("MQTT connecting")); mClient.connect(); + mEnReconnect = true; } void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) { @@ -197,6 +199,7 @@ class PubMqtt { case SYSTEM_EVENT_STA_GOT_IP: DPRINTLN(DBG_VERBOSE, F("MQTT connecting")); mClient.connect(); + mEnReconnect = true; break; case SYSTEM_EVENT_STA_DISCONNECTED: @@ -360,15 +363,15 @@ class PubMqtt { (status == MQTT_STATUS_AVAIL_NOT_PROD) ? "not " : "", (status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "" : "producing" ); - publish(topic, val); + publish(topic, val, true); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name); snprintf(val, 40, "%d", status); - publish(topic, val); + publish(topic, val, true); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name); snprintf(val, 40, "%i", iv->getLastTs(rec) * 1000); - publish(topic, val); + publish(topic, val, true); } // data diff --git a/src/utils/helper.cpp b/src/utils/helper.cpp new file mode 100644 index 00000000..8108ca3e --- /dev/null +++ b/src/utils/helper.cpp @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------------- +// 2022 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#include "helper.h" + +namespace ah { + void ip2Arr(uint8_t ip[], const char *ipStr) { + memset(ip, 0, 4); + char *tmp = new char[strlen(ipStr)+1]; + strncpy(tmp, ipStr, strlen(ipStr)+1); + char *p = strtok(tmp, "."); + uint8_t i = 0; + while(NULL != p) { + ip[i++] = atoi(p); + p = strtok(NULL, "."); + } + delete[] tmp; + } + + // note: char *str needs to be at least 16 bytes long + void ip2Char(uint8_t ip[], char *str) { + if(0 == ip[0]) + str[0] = '\0'; + else + snprintf(str, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + } +} diff --git a/src/utils/helper.h b/src/utils/helper.h new file mode 100644 index 00000000..49351cc9 --- /dev/null +++ b/src/utils/helper.h @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// 2022 Ahoy, https://ahoydtu.de +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#ifndef __HELPER_H__ +#define __HELPER_H__ + +#include +#include +#include +#include + +namespace ah { + void ip2Arr(uint8_t ip[], const char *ipStr); + void ip2Char(uint8_t ip[], char *str); +} + +#endif /*__HELPER_H__*/ diff --git a/src/web/html/index.html b/src/web/html/index.html index 96c92feb..e0474c08 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -196,9 +196,9 @@ parseStat(obj["statistics"]); parseIv(obj["inverter"]); parseWarnInfo(obj["warnings"], obj["infos"]); - document.getElementById("refresh").innerHTML = obj["refresh_interval"]; + document.getElementById("refresh").innerHTML = 10; if(exeOnce) { - window.setInterval("getAjax('/api/index', parse)", obj["refresh_interval"] * 1000); + window.setInterval("getAjax('/api/index', parse)", 10000); exeOnce = false; } } diff --git a/src/web/web.cpp b/src/web/web.cpp index d302eee3..e7425e76 100644 --- a/src/web/web.cpp +++ b/src/web/web.cpp @@ -11,6 +11,7 @@ #include "web.h" #include "../utils/ahoyTimer.h" +#include "../utils/helper.h" #include "html/h/index_html.h" #include "html/h/login_html.h" @@ -343,28 +344,16 @@ void web::showSave(AsyncWebServerRequest *request) { // static ip - if(request->arg("ipAddr") != "") { - request->arg("ipAddr").toCharArray(buf, SSID_LEN); - ip2Arr(mConfig->sys.ip.ip, buf); - if(request->arg("ipMask") != "") { - request->arg("ipMask").toCharArray(buf, SSID_LEN); - ip2Arr(mConfig->sys.ip.mask, buf); - } - if(request->arg("ipDns1") != "") { - request->arg("ipDns1").toCharArray(buf, SSID_LEN); - ip2Arr(mConfig->sys.ip.dns1, buf); - } - if(request->arg("ipDns2") != "") { - request->arg("ipDns2").toCharArray(buf, SSID_LEN); - ip2Arr(mConfig->sys.ip.dns2, buf); - } - if(request->arg("ipGateway") != "") { - request->arg("ipGateway").toCharArray(buf, SSID_LEN); - ip2Arr(mConfig->sys.ip.gateway, buf); - } - } - else - memset(&mConfig->sys.ip.ip, 0, 4); + request->arg("ipAddr").toCharArray(buf, 20); + ah::ip2Arr(mConfig->sys.ip.ip, buf); + request->arg("ipMask").toCharArray(buf, 20); + ah::ip2Arr(mConfig->sys.ip.mask, buf); + request->arg("ipDns1").toCharArray(buf, 20); + ah::ip2Arr(mConfig->sys.ip.dns1, buf); + request->arg("ipDns2").toCharArray(buf, 20); + ah::ip2Arr(mConfig->sys.ip.dns2, buf); + request->arg("ipGateway").toCharArray(buf, 20); + ah::ip2Arr(mConfig->sys.ip.gateway, buf); // inverter @@ -437,12 +426,14 @@ void web::showSave(AsyncWebServerRequest *request) { String addr = request->arg("mqttAddr"); addr.trim(); addr.toCharArray(mConfig->mqtt.broker, MQTT_ADDR_LEN); - request->arg("mqttUser").toCharArray(mConfig->mqtt.user, MQTT_USER_LEN); - if(request->arg("mqttPwd") != "{PWD}") - request->arg("mqttPwd").toCharArray(mConfig->mqtt.pwd, MQTT_PWD_LEN); - request->arg("mqttTopic").toCharArray(mConfig->mqtt.topic, MQTT_TOPIC_LEN); - mConfig->mqtt.port = request->arg("mqttPort").toInt(); } + else + mConfig->mqtt.broker[0] = '\0'; + request->arg("mqttUser").toCharArray(mConfig->mqtt.user, MQTT_USER_LEN); + if(request->arg("mqttPwd") != "{PWD}") + request->arg("mqttPwd").toCharArray(mConfig->mqtt.pwd, MQTT_PWD_LEN); + request->arg("mqttTopic").toCharArray(mConfig->mqtt.topic, MQTT_TOPIC_LEN); + mConfig->mqtt.port = request->arg("mqttPort").toInt(); // serial console if(request->arg("serIntvl") != "") { diff --git a/src/web/web.h b/src/web/web.h index 849f1caa..7560e039 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -64,15 +64,6 @@ class web { void onSerial(AsyncWebServerRequest *request); void onSystem(AsyncWebServerRequest *request); - void ip2Arr(uint8_t ip[], char *ipStr) { - char *p = strtok(ipStr, "."); - uint8_t i = 0; - while(NULL != p) { - ip[i++] = atoi(p); - p = strtok(NULL, "."); - } - } - #ifdef ENABLE_JSON_EP void showJson(void); #endif diff --git a/src/web/webApi.cpp b/src/web/webApi.cpp index 82a9efda..4987e147 100644 --- a/src/web/webApi.cpp +++ b/src/web/webApi.cpp @@ -332,13 +332,12 @@ void webApi::getSerial(JsonObject obj) { //----------------------------------------------------------------------------- void webApi::getStaticIp(JsonObject obj) { - if(mConfig->sys.ip.ip[0] != 0) { - obj[F("ip")] = ip2String(mConfig->sys.ip.ip); - obj[F("mask")] = ip2String(mConfig->sys.ip.mask); - obj[F("dns1")] = ip2String(mConfig->sys.ip.dns1); - obj[F("dns2")] = ip2String(mConfig->sys.ip.dns2); - obj[F("gateway")] = ip2String(mConfig->sys.ip.gateway); - } + char buf[16]; + ah::ip2Char(mConfig->sys.ip.ip, buf); obj[F("ip")] = String(buf); + ah::ip2Char(mConfig->sys.ip.mask, buf); obj[F("mask")] = String(buf); + ah::ip2Char(mConfig->sys.ip.dns1, buf); obj[F("dns1")] = String(buf); + ah::ip2Char(mConfig->sys.ip.dns2, buf); obj[F("dns2")] = String(buf); + ah::ip2Char(mConfig->sys.ip.gateway, buf); obj[F("gateway")] = String(buf); } @@ -397,7 +396,7 @@ void webApi::getIndex(JsonObject obj) { JsonArray warn = obj.createNestedArray(F("warnings")); if(!mApp->mSys->Radio.isChipConnected()) warn.add(F("your NRF24 module can't be reached, check the wiring and pinout")); - if(!mApp->mqttIsConnected()) + if((!mApp->mqttIsConnected()) && (String(mConfig->mqtt.broker).length() > 0)) warn.add(F("MQTT is not connected")); JsonArray info = obj.createNestedArray(F("infos")); diff --git a/src/web/webApi.h b/src/web/webApi.h index de37d9ba..8b539e05 100644 --- a/src/web/webApi.h +++ b/src/web/webApi.h @@ -63,12 +63,6 @@ class webApi { return (int)(value * 1000 + 0.5) / 1000.0; } - String ip2String(uint8_t ip[]) { - char str[16]; - snprintf(str, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); - return String(str); - } - AsyncWebServer *mSrv; app *mApp; From e148f89d0cbfe486b4bdc4cc9b5b6ebaec5c1c3a Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Tue, 29 Nov 2022 08:31:15 +0100 Subject: [PATCH 122/431] RPI: fix sleep calculation by using the correct (utc) time --- tools/rpi/hoymiles/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index 18e3d95e..69bf1479 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -62,7 +62,7 @@ class SunsetHandler: tomorrow = now + timedelta(days=1) nextSunrise = self.suntimes.riseutc(tomorrow) self.nextSunset = self.suntimes.setutc(tomorrow) - time_to_sleep = int((nextSunrise - datetime.now()).total_seconds()) + time_to_sleep = int((nextSunrise - datetime.utcnow()).total_seconds()) logging.info (f'Waiting for sunrise at {nextSunrise} UTC ({time_to_sleep} seconds)') if time_to_sleep > 0: time.sleep(time_to_sleep) From f6f05525e30e11c7c1f323aeb7bed64201dbc9fc Mon Sep 17 00:00:00 2001 From: Sven Naumann <3747263+sVnsation@users.noreply.github.com> Date: Wed, 30 Nov 2022 21:03:54 +0100 Subject: [PATCH 123/431] compress firmware bin with gzip for ota allows smaller update files for ota update --- scripts/getVersion.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/getVersion.py b/scripts/getVersion.py index 2346966d..21406418 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -1,4 +1,6 @@ import os +import shutil +import gzip from datetime import date def genOtaBin(path): @@ -24,6 +26,11 @@ def genOtaBin(path): with open(path + "ota.bin", "wb") as f: f.write(bytearray(arr)) +# write gzip firmware file +def gzip_bin(bin_file, gzip_file): + with open(bin_file,"rb") as fp: + with gzip.open(gzip_file, "wb", compresslevel = 9) as f: + shutil.copyfileobj(fp, f) def readVersion(path, infile): f = open(path + infile, "r") @@ -48,16 +55,19 @@ def readVersion(path, infile): src = path + ".pio/build/esp8266-release/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) + gzip_bin(dst, dst + ".gz") versionout = version[:-1] + "_esp8266_1m_" + sha + ".bin" src = path + ".pio/build/esp8285-release/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) + gzip_bin(dst, dst + ".gz") versionout = version[:-1] + "_esp32_" + sha + ".bin" src = path + ".pio/build/esp32-wroom32-release/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) + gzip_bin(dst, dst + ".gz") # other ESP32 bin files src = path + ".pio/build/esp32-wroom32-release/" From 07d816b29d18f94e4c76d03c965be5eeb1bcb6bc Mon Sep 17 00:00:00 2001 From: Sven Naumann <3747263+sVnsation@users.noreply.github.com> Date: Thu, 1 Dec 2022 09:15:28 +0000 Subject: [PATCH 124/431] move round3 function to helper --- src/utils/helper.cpp | 4 ++++ src/utils/helper.h | 1 + src/web/webApi.cpp | 6 +++--- src/web/webApi.h | 4 ---- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/utils/helper.cpp b/src/utils/helper.cpp index 8108ca3e..9bae7bed 100644 --- a/src/utils/helper.cpp +++ b/src/utils/helper.cpp @@ -26,4 +26,8 @@ namespace ah { else snprintf(str, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); } + + double round3(double value) { + return (int)(value * 1000 + 0.5) / 1000.0; + } } diff --git a/src/utils/helper.h b/src/utils/helper.h index 49351cc9..1898ba7e 100644 --- a/src/utils/helper.h +++ b/src/utils/helper.h @@ -14,6 +14,7 @@ namespace ah { void ip2Arr(uint8_t ip[], const char *ipStr); void ip2Char(uint8_t ip[], char *str); + double round3(double value); } #endif /*__HELPER_H__*/ diff --git a/src/web/webApi.cpp b/src/web/webApi.cpp index 4987e147..b11637fa 100644 --- a/src/web/webApi.cpp +++ b/src/web/webApi.cpp @@ -448,7 +448,7 @@ void webApi::getLive(JsonObject obj) { JsonObject obj2 = invArr.createNestedObject(); obj2[F("name")] = String(iv->config->name); obj2[F("channels")] = iv->channels; - obj2[F("power_limit_read")] = round3(iv->actPowerLimit); + obj2[F("power_limit_read")] = ah::round3(iv->actPowerLimit); obj2[F("last_alarm")] = String(iv->lastAlarmMsg); obj2[F("ts_last_success")] = rec->ts; @@ -457,7 +457,7 @@ void webApi::getLive(JsonObject obj) { obj2[F("ch_names")][0] = "AC"; for (uint8_t fld = 0; fld < sizeof(list); fld++) { pos = (iv->getPosByChFld(CH0, list[fld], rec)); - ch0[fld] = (0xff != pos) ? round3(iv->getValue(pos, rec)) : 0.0; + ch0[fld] = (0xff != pos) ? ah::round3(iv->getValue(pos, rec)) : 0.0; obj[F("ch0_fld_units")][fld] = (0xff != pos) ? String(iv->getUnit(pos, rec)) : notAvail; obj[F("ch0_fld_names")][fld] = (0xff != pos) ? String(iv->getFieldName(pos, rec)) : notAvail; } @@ -474,7 +474,7 @@ void webApi::getLive(JsonObject obj) { case 4: pos = (iv->getPosByChFld(j, FLD_YT, rec)); break; case 5: pos = (iv->getPosByChFld(j, FLD_IRR, rec)); break; } - cur[k] = (0xff != pos) ? round3(iv->getValue(pos, rec)) : 0.0; + cur[k] = (0xff != pos) ? ah::round3(iv->getValue(pos, rec)) : 0.0; if(1 == j) { obj[F("fld_units")][k] = (0xff != pos) ? String(iv->getUnit(pos, rec)) : notAvail; obj[F("fld_names")][k] = (0xff != pos) ? String(iv->getFieldName(pos, rec)) : notAvail; diff --git a/src/web/webApi.h b/src/web/webApi.h index 8b539e05..04e16635 100644 --- a/src/web/webApi.h +++ b/src/web/webApi.h @@ -59,10 +59,6 @@ class webApi { bool setCtrl(JsonObject jsonIn, JsonObject jsonOut); bool setSetup(JsonObject jsonIn, JsonObject jsonOut); - double round3(double value) { - return (int)(value * 1000 + 0.5) / 1000.0; - } - AsyncWebServer *mSrv; app *mApp; From 08e417ee85b7c6a77ffc728545e1d0fc6fc00170 Mon Sep 17 00:00:00 2001 From: Sven Naumann <3747263+sVnsation@users.noreply.github.com> Date: Thu, 1 Dec 2022 09:34:38 +0000 Subject: [PATCH 125/431] mqtt avoid trailing zeroes --- src/publisher/pubMqtt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 89d8633b..91e6545e 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -378,7 +378,7 @@ class PubMqtt { if(iv->isAvailable(*mUtcTimestamp, rec)) { for (uint8_t i = 0; i < rec->length; i++) { snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); - snprintf(val, 40, "%.3f", iv->getValue(i, rec)); + snprintf(val, sizeof(val), "%g", ah::round3(iv->getValue(i, rec))); publish(topic, val); // calculate total values for RealTimeRunData_Debug @@ -427,7 +427,7 @@ class PubMqtt { break; } snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); - snprintf(val, 40, "%.3f", total[i]); + snprintf(val, sizeof(val), "%g", ah::round3(total[i])); publish(topic, val); } } From 28594aff4ff98b5953e9640ec7fda2a05314d55b Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 1 Dec 2022 14:56:18 +0100 Subject: [PATCH 126/431] partial fix #468 MQTT fix #466 calculation of sunrise and sunset fix #463 Webserial Timestamp fix --- src/defines.h | 2 +- src/publisher/pubMqtt.h | 26 ++++++++++++++++++-------- src/utils/sun.h | 4 ++-- src/web/html/serial.html | 2 +- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/defines.h b/src/defines.h index 62f2cc42..68b9c80a 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 44 +#define VERSION_PATCH 45 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 89d8633b..4862d77e 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -47,7 +47,7 @@ class PubMqtt { mSunrise = sunrise; mSunset = sunset; - snprintf(mLwtTopic, MQTT_TOPIC_LEN + 7, "%s/status", mCfgMqtt->topic); + snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); #if defined(ESP8266) mHWifiCon = WiFi.onStationModeGotIP(std::bind(&PubMqtt::onWifiConnect, this, std::placeholders::_1)); @@ -358,10 +358,10 @@ class PubMqtt { } snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->config->name); snprintf(val, 40, "%s%s%s%s", - (status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "not yet " : "", + (status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "not " : "", "available and ", (status == MQTT_STATUS_AVAIL_NOT_PROD) ? "not " : "", - (status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "" : "producing" + "producing" ); publish(topic, val, true); @@ -377,9 +377,19 @@ class PubMqtt { // data if(iv->isAvailable(*mUtcTimestamp, rec)) { for (uint8_t i = 0; i < rec->length; i++) { + bool retained = false; + if (mSendList.front() == RealTimeRunData_Debug) { + switch (rec->assign[i].fieldId) { + case FLD_YT: + case FLD_YD: + retained = true; + break; + } + } + snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); snprintf(val, 40, "%.3f", iv->getValue(i, rec)); - publish(topic, val); + publish(topic, val, retained); // calculate total values for RealTimeRunData_Debug if (mSendList.front() == RealTimeRunData_Debug) { @@ -428,7 +438,7 @@ class PubMqtt { } snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); snprintf(val, 40, "%.3f", total[i]); - publish(topic, val); + publish(topic, val, true); } } } @@ -449,9 +459,9 @@ class PubMqtt { subscriptionCb mSubscriptionCb; // last will topic and payload must be available trough lifetime of 'espMqttClient' - char mLwtTopic[MQTT_TOPIC_LEN+7]; - const char* mLwtOnline = "online"; - const char* mLwtOffline = "offline"; + char mLwtTopic[MQTT_TOPIC_LEN+5]; + const char* mLwtOnline = "connected"; + const char* mLwtOffline = "not connected"; const char *mDevName, *mVersion; }; diff --git a/src/utils/sun.h b/src/utils/sun.h index 476ad0ff..1036f9ec 100644 --- a/src/utils/sun.h +++ b/src/utils/sun.h @@ -11,7 +11,7 @@ namespace ah { // Source: https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth // Julian day since 1.1.2000 12:00 + correction 69.12s - double n_JulianDay = (utcTs + offset) / 86400 - 10957.0 + 0.0008; + double n_JulianDay = (utcTs + offset) / 86400 - 10957.0; // Mean solar time double J = n_JulianDay - lon / 360; // Solar mean anomaly @@ -25,7 +25,7 @@ namespace ah { // Declination of the sun double delta = ASIN(SIN(lambda) * SIN(23.44)); // Hour angle - double omega = ACOS(SIN(-0.83) - SIN(lat) * SIN(delta) / COS(lat) * COS(delta)); + double omega = ACOS((SIN(-0.83) - SIN(lat) * SIN(delta) / COS(lat) * COS(delta))); // Calculate sunrise and sunset double Jrise = Jtransit - omega / 360; double Jset = Jtransit + omega / 360; diff --git a/src/web/html/serial.html b/src/web/html/serial.html index c7e3dd8b..ccbd1156 100644 --- a/src/web/html/serial.html +++ b/src/web/html/serial.html @@ -120,7 +120,7 @@ // set time offset for serial console var obj = new Object(); obj.cmd = "serial_utc_offset"; - obj.ts = new Date().getTimezoneOffset() * -60; + obj.val = new Date().getTimezoneOffset() * -60; getAjax("/api/setup", null, "POST", JSON.stringify(obj)); } From 614af26cd9e768acbffa2cda46d4fba68003225d Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 2 Dec 2022 07:56:48 +0100 Subject: [PATCH 127/431] fix #466 --- src/defines.h | 2 +- src/utils/sun.h | 2 +- src/web/html/setup.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/defines.h b/src/defines.h index 68b9c80a..09665137 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 45 +#define VERSION_PATCH 46 //------------------------------------- typedef struct { diff --git a/src/utils/sun.h b/src/utils/sun.h index 1036f9ec..c6d078d4 100644 --- a/src/utils/sun.h +++ b/src/utils/sun.h @@ -25,7 +25,7 @@ namespace ah { // Declination of the sun double delta = ASIN(SIN(lambda) * SIN(23.44)); // Hour angle - double omega = ACOS((SIN(-0.83) - SIN(lat) * SIN(delta) / COS(lat) * COS(delta))); + double omega = ACOS((SIN(-0.83) - SIN(lat) * SIN(delta)) / (COS(lat) * COS(delta))); // Calculate sunrise and sunset double Jrise = Jtransit - omega / 360; double Jset = Jtransit + omega / 360; diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 0a586849..e5bf96f3 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -163,7 +163,7 @@
        - +

        Download your settings (JSON file) (only saved values) From 7c6ab6792bf7cc10972d66bc3ca6b8281985da2e Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 3 Dec 2022 02:06:20 +0100 Subject: [PATCH 128/431] fix #472 refactored ahoyWifi class completely -> now Ahoy opens an AP during boot. This will be closed once a station WiFi connection is established improved NTP after boot, will be synced immediately after successful WiFi connection --- src/app.cpp | 16 ++- src/app.h | 22 +--- src/config/settings.h | 2 +- src/hm/hmRadio.h | 9 +- src/utils/helper.cpp | 9 ++ src/utils/helper.h | 3 + src/web/web.cpp | 4 +- src/wifi/ahoywifi.cpp | 233 +++++++++++++++--------------------------- src/wifi/ahoywifi.h | 41 ++++---- 9 files changed, 132 insertions(+), 207 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index e7b86283..21bee17e 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -42,8 +42,7 @@ void app::setup(uint32_t timeout) { mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset); #endif - mWifi = new ahoywifi(mConfig); - mWifi->setup(timeout, mSettings.getValid()); + mWifi.setup(mConfig, &mUtcTimestamp); mPayload.setup(mSys); mPayload.enableSerialDebug(mConfig->serial.debug); @@ -72,6 +71,10 @@ void app::loop(void) { ah::Scheduler::loop(); + #if !defined(AP_ONLY) + mWifi.loop(); + #endif + mWeb->loop(); if (mFlagSendDiscoveryConfig) { @@ -198,19 +201,14 @@ void app::handleIntr(void) { mSys->Radio.handleIntr(); } -//----------------------------------------------------------------------------- -bool app::getWifiApActive(void) { - return mWifi->getApActive(); -} - //----------------------------------------------------------------------------- void app::scanAvailNetworks(void) { - mWifi->scanAvailNetworks(); + mWifi.scanAvailNetworks(); } //----------------------------------------------------------------------------- void app::getAvailNetworks(JsonObject obj) { - mWifi->getAvailNetworks(obj); + mWifi.getAvailNetworks(obj); } diff --git a/src/app.h b/src/app.h index 038be0c4..e2498815 100644 --- a/src/app.h +++ b/src/app.h @@ -84,15 +84,6 @@ class app : public ah::Scheduler { return ret; } - String getDateTimeStr(time_t t) { - char str[20]; - if(0 == t) - sprintf(str, "n/a"); - else - sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t)); - return String(str); - } - String getTimeStr(uint32_t offset = 0) { char str[10]; if(0 == mUtcTimestamp) @@ -155,25 +146,20 @@ class app : public ah::Scheduler { ESP.restart(); } - - if (mUpdateNtp) { mUpdateNtp = false; - mUtcTimestamp = mWifi->getNtpTime(); - DPRINTLN(DBG_INFO, F("[NTP]: ") + getDateTimeStr(mUtcTimestamp) + F(" UTC")); + mWifi.getNtpTime(); } } void minuteTick(void) { if(0 == mUtcTimestamp) { - if(!mWifi->getApActive()) - mUpdateNtp = true; + mUpdateNtp = true; } } void ntpUpdateTick(void) { - if (!mWifi->getApActive()) - mUpdateNtp = true; + mUpdateNtp = true; } void stats(void) { @@ -203,7 +189,7 @@ class app : public ah::Scheduler { bool mShowRebootRequest; - ahoywifi *mWifi; + ahoywifi mWifi; web *mWeb; PayloadType mPayload; PubSerialType mPubSerial; diff --git a/src/config/settings.h b/src/config/settings.h index c37c19fa..1895cd12 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -226,7 +226,7 @@ class settings { private: void loadDefaults(bool wifi = true) { - DPRINTLN(DBG_INFO, F("loadDefaults")); + DPRINTLN(DBG_VERBOSE, F("loadDefaults")); if(wifi) { snprintf(mCfg.sys.stationSsid, SSID_LEN, FB_WIFI_SSID); snprintf(mCfg.sys.stationPwd, PWD_LEN, FB_WIFI_PWD); diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 4e1b749c..efedfab1 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -139,14 +139,15 @@ class HmRadio { mNrf24.setPALevel(ampPwr & 0x03); mNrf24.startListening(); - DPRINTLN(DBG_INFO, F("Radio Config:")); - mNrf24.printPrettyDetails(); mTxCh = setDefaultChannels(); - if(!mNrf24.isChipConnected()) { - DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); + if(mNrf24.isChipConnected()) { + DPRINTLN(DBG_INFO, F("Radio Config:")); + mNrf24.printPrettyDetails(); } + else + DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); } void loop(void) { diff --git a/src/utils/helper.cpp b/src/utils/helper.cpp index 9bae7bed..5a9eaf22 100644 --- a/src/utils/helper.cpp +++ b/src/utils/helper.cpp @@ -30,4 +30,13 @@ namespace ah { double round3(double value) { return (int)(value * 1000 + 0.5) / 1000.0; } + + String getDateTimeStr(time_t t) { + char str[20]; + if(0 == t) + sprintf(str, "n/a"); + else + sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t)); + return String(str); + } } diff --git a/src/utils/helper.h b/src/utils/helper.h index 1898ba7e..1372fec8 100644 --- a/src/utils/helper.h +++ b/src/utils/helper.h @@ -6,15 +6,18 @@ #ifndef __HELPER_H__ #define __HELPER_H__ +#include #include #include #include #include +#include namespace ah { void ip2Arr(uint8_t ip[], const char *ipStr); void ip2Char(uint8_t ip[], char *str); double round3(double value); + String getDateTimeStr(time_t t); } #endif /*__HELPER_H__*/ diff --git a/src/web/web.cpp b/src/web/web.cpp index e7425e76..0ea3c307 100644 --- a/src/web/web.cpp +++ b/src/web/web.cpp @@ -664,10 +664,10 @@ void web::showJson(void) { snprintf(val, 25, "[%.3f, \"%s\"]", iv->getValue(i), iv->getUnit(i)); modJson += String(topic) + ": " + String(val) + F(",\n"); } - modJson += F("\t\"last_msg\": \"") + mMain->getDateTimeStr(iv->ts) + F("\"\n\t},\n"); + modJson += F("\t\"last_msg\": \"") + ah::getDateTimeStr(iv->ts) + F("\"\n\t},\n"); } } - modJson += F("\"json_ts\": \"") + String(mMain->getDateTimeStr(mMain->mTimestamp)) + F("\"\n}\n"); + modJson += F("\"json_ts\": \"") + String(ah::getDateTimeStr(mMain->mTimestamp)) + F("\"\n}\n"); mWeb->send(200, F("application/json"), modJson); } diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 9b95d25b..b6fbce73 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -16,144 +16,84 @@ //----------------------------------------------------------------------------- -ahoywifi::ahoywifi(settings_t *config) { - mConfig = config; - - mDns = new DNSServer(); - mUdp = new WiFiUDP(); - - mWifiStationTimeout = 10; - wifiWasEstablished = false; - mNextTryTs = 0; - mApLastTick = 0; - mApActive = false; +ahoywifi::ahoywifi() { + mCnt = 0; + mConnected = false; + mInitNtp = true; } //----------------------------------------------------------------------------- -void ahoywifi::setup(uint32_t timeout, bool settingValid) { - //wifiConnectHandler = WiFi.onStationModeGotIP(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); - //wifiDisconnectHandler = WiFi.onStationModeDisconnected(std::bind(&ahoywifi::onDisconnect, this, std::placeholders::_1)); - - #ifdef FB_WIFI_OVERRIDDEN - mStationWifiIsDef = false; - #else - mStationWifiIsDef = (strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) == 0); +void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp) { + char ipSta[16]; + mConfig = config; + mUtcTimestamp = utcTimestamp; + + #if !defined(FB_WIFI_OVERRIDDEN) + if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) != 0) + setupAp(); #endif - mWifiStationTimeout = timeout; - #ifndef AP_ONLY - if(false == mApActive) - mApActive = (mStationWifiIsDef) ? true : setupStation(mWifiStationTimeout); + #if !defined(AP_ONLY) + setupStation(); + ah::ip2Char(mConfig->sys.ip.ip, ipSta); #endif - if(!settingValid) { - DPRINTLN(DBG_WARN, F("your settings are not valid! check [IP]/setup")); - mApActive = true; - mApLastTick = millis(); - mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); - setupAp(WIFI_AP_SSID, WIFI_AP_PWD); - } - else { - DPRINTLN(DBG_INFO, F("\n\n----------------------------------------")); - DPRINTLN(DBG_INFO, F("Welcome to AHOY!")); - DPRINT(DBG_INFO, F("\npoint your browser to http://")); - if(mApActive) - DBGPRINTLN(F("192.168.4.1")); - else - DBGPRINTLN(WiFi.localIP().toString()); - DPRINTLN(DBG_INFO, F("to configure your device")); - DPRINTLN(DBG_INFO, F("----------------------------------------\n")); - } + + wifiConnectHandler = WiFi.onStationModeGotIP(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); + wifiDisconnectHandler = WiFi.onStationModeDisconnected(std::bind(&ahoywifi::onDisconnect, this, std::placeholders::_1)); } //----------------------------------------------------------------------------- -bool ahoywifi::loop(void) { - if(mApActive) { - mDns->processNextRequest(); -#ifndef AP_ONLY - if(ah::checkTicker(&mNextTryTs, (WIFI_AP_ACTIVE_TIME * 1000))) { - mApActive = (mStationWifiIsDef) ? true : setupStation(mWifiStationTimeout); - if(mApActive) { - if(strlen(WIFI_AP_PWD) < 8) - DPRINTLN(DBG_ERROR, F("password must be at least 8 characters long")); - mApLastTick = millis(); - mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); - setupAp(WIFI_AP_SSID, WIFI_AP_PWD); - } - } - else { - if(millis() - mApLastTick > 10000) { - mApLastTick = millis(); - uint8_t cnt = WiFi.softAPgetStationNum(); - if(cnt > 0) { - DPRINTLN(DBG_INFO, String(cnt) + F(" client connected (no timeout)")); - mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); - } - else { - DBGPRINT(F("AP will be closed in ")); - DBGPRINT(String((mNextTryTs - mApLastTick) / 1000)); - DBGPRINTLN(F(" seconds")); - } - } - } -#endif - } - - if((WiFi.status() != WL_CONNECTED) && wifiWasEstablished) { - if(!mApActive) { - DPRINTLN(DBG_INFO, "[WiFi]: Connection Lost"); - mApActive = (mStationWifiIsDef) ? true : setupStation(mWifiStationTimeout); +void ahoywifi::loop() { + #if !defined(AP_ONLY) + if(!mConnected) { + delay(100); + mCnt++; + if((mCnt % 50) == 0) + WiFi.disconnect(); + else if((mCnt % 60) == 0) { + WiFi.reconnect(); + mCnt = 0; } + } else if(mInitNtp) { + getNtpTime(); + mInitNtp = false; } + mCnt = 0; + #endif - return mApActive; } //----------------------------------------------------------------------------- -void ahoywifi::setupAp(const char *ssid, const char *pwd) { - DPRINTLN(DBG_VERBOSE, F("app::setupAp")); +void ahoywifi::setupAp(void) { + DPRINTLN(DBG_VERBOSE, F("wifi::setupAp")); IPAddress apIp(192, 168, 4, 1); - DBGPRINTLN(F("\n---------\nAhoy Info:")); + DBGPRINTLN(F("\n---------\nAhoyDTU Info:")); DBGPRINT(F("Version: ")); DBGPRINTLN(String(VERSION_MAJOR) + F(".") + String(VERSION_MINOR) + F(".") + String(VERSION_PATCH)); DBGPRINT(F("Github Hash: ")); DBGPRINTLN(String(AUTO_GIT_HASH)); DBGPRINT(F("\n---------\nAP MODE\nSSID: ")); - DBGPRINTLN(ssid); + DBGPRINTLN(WIFI_AP_SSID); DBGPRINT(F("PWD: ")); - DBGPRINTLN(pwd); - DBGPRINT(F("\nActive for: ")); - DBGPRINT(String(WIFI_AP_ACTIVE_TIME)); - DBGPRINTLN(F(" seconds")); + DBGPRINTLN(WIFI_AP_PWD); + DBGPRINTLN("IP Address: http://" + apIp.toString()); + DBGPRINTLN(F("---------\n")); - DBGPRINTLN("\nIp Address: " + apIp[0] + apIp[1] + apIp[2] + apIp[3]); - DBGPRINTLN(F("\n---------\n")); - - WiFi.mode(WIFI_AP); + WiFi.mode(WIFI_AP_STA); WiFi.softAPConfig(apIp, apIp, IPAddress(255, 255, 255, 0)); - WiFi.softAP(ssid, pwd); + WiFi.softAP(WIFI_AP_SSID, WIFI_AP_PWD); - mDns->start(53, "*", apIp); + mDns.start(53, "*", apIp); } //----------------------------------------------------------------------------- -bool ahoywifi::setupStation(uint32_t timeout) { - DPRINTLN(DBG_VERBOSE, F("app::setupStation")); - int32_t cnt; - bool startAp = false; - - if(timeout >= 3) - cnt = (timeout - 3) / 2 * 10; - else { - timeout = 1; - cnt = 1; - } - - WiFi.mode(WIFI_STA); +void ahoywifi::setupStation(void) { + DPRINTLN(DBG_VERBOSE, F("wifi::setupStation")); if(mConfig->sys.ip.ip[0] != 0) { IPAddress ip(mConfig->sys.ip.ip); IPAddress mask(mConfig->sys.ip.mask); @@ -167,45 +107,14 @@ bool ahoywifi::setupStation(uint32_t timeout) { if(String(mConfig->sys.deviceName) != "") WiFi.hostname(mConfig->sys.deviceName); - delay(2000); DBGPRINT(F("connect to network '")); DBGPRINT(mConfig->sys.stationSsid); DBGPRINTLN(F("' ...")); - while (WiFi.status() != WL_CONNECTED) { - delay(100); - if(cnt % 40 == 0) - DBGPRINTLN("."); - else - DBGPRINT("."); - - if(timeout > 0) { // limit == 0 -> no limit - if(--cnt <= 0) { - if(WiFi.status() != WL_CONNECTED) { - startAp = true; - WiFi.disconnect(); - } - delay(100); - break; - } - } - } - Serial.println("."); - - if(false == startAp) - wifiWasEstablished = true; - - delay(1000); - return startAp; } //----------------------------------------------------------------------------- -bool ahoywifi::getApActive(void) { - return mApActive; -} - -//----------------------------------------------------------------------------- -time_t ahoywifi::getNtpTime(void) { +void ahoywifi::getNtpTime(void) { //DPRINTLN(DBG_VERBOSE, F("wifi::getNtpTime")); time_t date = 0; IPAddress timeServer; @@ -213,16 +122,16 @@ time_t ahoywifi::getNtpTime(void) { uint8_t retry = 0; WiFi.hostByName(mConfig->ntp.addr, timeServer); - mUdp->begin(mConfig->ntp.port); + mUdp.begin(mConfig->ntp.port); sendNTPpacket(timeServer); while(retry++ < 5) { int wait = 150; while(--wait) { - if(NTP_PACKET_SIZE <= mUdp->parsePacket()) { + if(NTP_PACKET_SIZE <= mUdp.parsePacket()) { uint64_t secsSince1900; - mUdp->read(buf, NTP_PACKET_SIZE); + mUdp.read(buf, NTP_PACKET_SIZE); secsSince1900 = (buf[40] << 24); secsSince1900 |= (buf[41] << 16); secsSince1900 |= (buf[42] << 8); @@ -230,13 +139,14 @@ time_t ahoywifi::getNtpTime(void) { date = secsSince1900 - 2208988800UL; // UTC time break; - } - else + } else delay(10); } } - return date; + *mUtcTimestamp = date; + + DPRINTLN(DBG_INFO, F("[NTP]: ") + ah::getDateTimeStr(*mUtcTimestamp) + F(" UTC")); } @@ -285,19 +195,42 @@ void ahoywifi::sendNTPpacket(IPAddress& address) { buf[14] = 49; buf[15] = 52; - mUdp->beginPacket(address, 123); // NTP request, port 123 - mUdp->write(buf, NTP_PACKET_SIZE); - mUdp->endPacket(); + mUdp.beginPacket(address, 123); // NTP request, port 123 + mUdp.write(buf, NTP_PACKET_SIZE); + mUdp.endPacket(); } //----------------------------------------------------------------------------- -/*void ahoywifi::onConnect(const WiFiEventStationModeGotIP& event) { - Serial.println("Connected to Wi-Fi."); +void ahoywifi::onConnect(const WiFiEventStationModeGotIP& event) { + if(!mConnected) { + mConnected = true; + DBGPRINTLN(F("\n[WiFi] Connected")); + WiFi.mode(WIFI_STA); + WiFi.begin(); + DBGPRINTLN(F("[WiFi] AP disabled")); + mDns.stop(); + + welcome(WiFi.localIP().toString() + F(" (Station)")); + } } //----------------------------------------------------------------------------- void ahoywifi::onDisconnect(const WiFiEventStationModeDisconnected& event) { - Serial.println("Disconnected from Wi-Fi."); -}*/ + if(mConnected) { + mConnected = false; + DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); + } +} + + +//----------------------------------------------------------------------------- +void ahoywifi::welcome(String msg) { + DBGPRINTLN(F("\n\n--------------------------------")); + DBGPRINTLN(F("Welcome to AHOY!")); + DBGPRINT(F("\npoint your browser to http://")); + DBGPRINTLN(msg); + DBGPRINTLN(F("to configure your device")); + DBGPRINTLN(F("--------------------------------\n")); +} diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 32ca5cec..1cda6ab4 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -9,7 +9,6 @@ #include "../utils/dbg.h" #include #include -#include #include #include "ESPAsyncWebServer.h" @@ -19,36 +18,32 @@ class app; class ahoywifi { public: - ahoywifi(settings_t *config); - ~ahoywifi() {} - - void setup(uint32_t timeout, bool settingValid); - bool loop(void); - void setupAp(const char *ssid, const char *pwd); - bool setupStation(uint32_t timeout); - bool getApActive(void); - time_t getNtpTime(void); + ahoywifi(); + + void setup(settings_t *config, uint32_t *utcTimestamp); + void loop(void); + void getNtpTime(void); void scanAvailNetworks(void); void getAvailNetworks(JsonObject obj); private: + void setupAp(void); + void setupStation(void); void sendNTPpacket(IPAddress& address); - //void onConnect(const WiFiEventStationModeGotIP& event); - //void onDisconnect(const WiFiEventStationModeDisconnected& event); + void onConnect(const WiFiEventStationModeGotIP& event); + void onDisconnect(const WiFiEventStationModeDisconnected& event); + void welcome(String msg); settings_t *mConfig; - DNSServer *mDns; - WiFiUDP *mUdp; // for time server - //WiFiEventHandler wifiConnectHandler; - //WiFiEventHandler wifiDisconnectHandler; - - uint32_t mWifiStationTimeout; - uint32_t mNextTryTs; - uint32_t mApLastTick; - bool mApActive; - bool wifiWasEstablished; - bool mStationWifiIsDef; + DNSServer mDns; + WiFiUDP mUdp; // for time server + WiFiEventHandler wifiConnectHandler; + WiFiEventHandler wifiDisconnectHandler; + + bool mConnected, mInitNtp; + uint8_t mCnt; + uint32_t *mUtcTimestamp; }; #endif /*__AHOYWIFI_H__*/ From d11d3134f69de240d3f1e6f63c657dc69d973480 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 3 Dec 2022 02:44:25 +0100 Subject: [PATCH 129/431] fix ESP32 (also tested in hardware) --- src/defines.h | 2 +- src/publisher/pubMqtt.h | 2 +- src/wifi/ahoywifi.cpp | 71 ++++++++++++++++++++++++++++++----------- src/wifi/ahoywifi.h | 6 ++++ 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/src/defines.h b/src/defines.h index 09665137..229d583b 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 46 +#define VERSION_PATCH 47 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 43ef277a..0e3e8417 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -227,7 +227,7 @@ class PubMqtt { } void onDisconnect(espMqttClientTypes::DisconnectReason reason) { - DBGPRINT(F("MQTT disconnected, reason: ")); + DPRINT(DBG_INFO, F("MQTT disconnected, reason: ")); switch (reason) { case espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED: DBGPRINTLN(F("TCP disconnect")); diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index b6fbce73..82370031 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -38,8 +38,12 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp) { ah::ip2Char(mConfig->sys.ip.ip, ipSta); #endif + #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeGotIP(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); wifiDisconnectHandler = WiFi.onStationModeDisconnected(std::bind(&ahoywifi::onDisconnect, this, std::placeholders::_1)); + #else + WiFi.onEvent(std::bind(&ahoywifi::onWiFiEvent, this, std::placeholders::_1)); + #endif } @@ -146,7 +150,7 @@ void ahoywifi::getNtpTime(void) { *mUtcTimestamp = date; - DPRINTLN(DBG_INFO, F("[NTP]: ") + ah::getDateTimeStr(*mUtcTimestamp) + F(" UTC")); + DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(*mUtcTimestamp) + " UTC"); } @@ -202,27 +206,58 @@ void ahoywifi::sendNTPpacket(IPAddress& address) { //----------------------------------------------------------------------------- -void ahoywifi::onConnect(const WiFiEventStationModeGotIP& event) { - if(!mConnected) { - mConnected = true; - DBGPRINTLN(F("\n[WiFi] Connected")); - WiFi.mode(WIFI_STA); - WiFi.begin(); - DBGPRINTLN(F("[WiFi] AP disabled")); - mDns.stop(); - - welcome(WiFi.localIP().toString() + F(" (Station)")); +#if defined(ESP8266) + void ahoywifi::onConnect(const WiFiEventStationModeGotIP& event) { + if(!mConnected) { + mConnected = true; + DBGPRINTLN(F("\n[WiFi] Connected")); + WiFi.mode(WIFI_STA); + DBGPRINTLN(F("[WiFi] AP disabled")); + mDns.stop(); + + welcome(WiFi.localIP().toString() + F(" (Station)")); + } } -} -//----------------------------------------------------------------------------- -void ahoywifi::onDisconnect(const WiFiEventStationModeDisconnected& event) { - if(mConnected) { - mConnected = false; - DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); + //------------------------------------------------------------------------- + void ahoywifi::onDisconnect(const WiFiEventStationModeDisconnected& event) { + if(mConnected) { + mConnected = false; + DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); + } } -} + +#else + //------------------------------------------------------------------------- + void ahoywifi::onWiFiEvent(WiFiEvent_t event) { + switch(event) { + case SYSTEM_EVENT_STA_GOT_IP: + if(!mConnected) { + delay(1000); + mConnected = true; + DBGPRINTLN(F("\n[WiFi] Connected")); + welcome(WiFi.localIP().toString() + F(" (Station)")); + WiFi.mode(WIFI_STA); + WiFi.begin(); + DBGPRINTLN(F("[WiFi] AP disabled")); + mDns.stop(); + + } + break; + + case SYSTEM_EVENT_STA_DISCONNECTED: + if(mConnected) { + mConnected = false; + DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); + } + break; + + default: + break; + } + } +#endif //----------------------------------------------------------------------------- diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 1cda6ab4..767265c5 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -30,16 +30,22 @@ class ahoywifi { void setupAp(void); void setupStation(void); void sendNTPpacket(IPAddress& address); + #if defined(ESP8266) void onConnect(const WiFiEventStationModeGotIP& event); void onDisconnect(const WiFiEventStationModeDisconnected& event); + #else + void onWiFiEvent(WiFiEvent_t event); + #endif void welcome(String msg); settings_t *mConfig; DNSServer mDns; WiFiUDP mUdp; // for time server + #if defined(ESP8266) WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; + #endif bool mConnected, mInitNtp; uint8_t mCnt; From 3c6e3221e8d0989f7f28e0307049a7938e4f1da8 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 4 Dec 2022 20:19:02 +0100 Subject: [PATCH 130/431] added display-class: Nokia5110 and SDD1306 --- src/app.cpp | 15 +- src/app.h | 13 +- src/platformio.ini | 35 ++- .../MonochromeDisplay/MonochromeDisplay.h | 237 ++++++++++++++++++ 4 files changed, 294 insertions(+), 6 deletions(-) create mode 100644 src/plugins/MonochromeDisplay/MonochromeDisplay.h diff --git a/src/app.cpp b/src/app.cpp index 21bee17e..303ab562 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -38,15 +38,15 @@ void app::setup(uint32_t timeout) { mSys->setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); mSys->addInverters(&mConfig->inst); -#if !defined(AP_ONLY) + #if !defined(AP_ONLY) mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset); -#endif + #endif mWifi.setup(mConfig, &mUtcTimestamp); mPayload.setup(mSys); mPayload.enableSerialDebug(mConfig->serial.debug); -#if !defined(AP_ONLY) + #if !defined(AP_ONLY) if (mConfig->mqtt.broker[0] > 0) { mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1)); addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt)); @@ -54,7 +54,7 @@ void app::setup(uint32_t timeout) { addListener(EVERY_HR, std::bind(&PubMqttType::tickerHour, &mMqtt)); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); } -#endif + #endif setupLed(); mWeb = new web(this, mConfig, &mStat, mVersion); @@ -62,6 +62,13 @@ void app::setup(uint32_t timeout) { mWeb->setProtection(strlen(mConfig->sys.adminPwd) != 0); addListener(EVERY_SEC, std::bind(&web::tickSecond, mWeb)); + // Plugins + #if defined(ENA_NOKIA) || defined(ENA_SSD1306) + mMonoDisplay.setup(mSys, &mUtcTimestamp); + mPayload.addListener(std::bind(&MonoDisplayType::payloadEventListener, &mMonoDisplay, std::placeholders::_1)); + addListener(EVERY_SEC, std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay)); + #endif + //addListener(EVERY_MIN, std::bind(&PubSerialType::tickerMinute, &mPubSerial)); } diff --git a/src/app.h b/src/app.h index e2498815..82b0e646 100644 --- a/src/app.h +++ b/src/app.h @@ -27,6 +27,7 @@ #include "publisher/pubMqtt.h" #include "publisher/pubSerial.h" + // convert degrees and radians for sun calculation #define SIN(x) (sin(radians(x))) #define COS(x) (cos(radians(x))) @@ -38,7 +39,12 @@ typedef Payload PayloadType; typedef PubMqtt PubMqttType; typedef PubSerial PubSerialType; -class ahoywifi; +// PLUGINS +#if defined(ENA_NOKIA) || defined(ENA_SSD1306) + #include "plugins/MonochromeDisplay/MonochromeDisplay.h" + typedef MonochromeDisplay MonoDisplayType; +#endif + class web; class app : public ah::Scheduler { @@ -215,6 +221,11 @@ class app : public ah::Scheduler { int32_t mCalculatedTimezoneOffset; uint32_t mSunrise, mSunset; uint32_t mLatestSunTimestamp; + + // plugins + #if defined(ENA_NOKIA) || defined(ENA_SSD1306) + MonoDisplayType mMonoDisplay; + #endif }; #endif /*__APP_H__*/ diff --git a/src/platformio.ini b/src/platformio.ini index 0610c51d..3bf76cdc 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -37,7 +37,6 @@ lib_deps = nrf24/RF24 paulstoffregen/Time https://github.com/bertmelis/espMqttClient#v1.3.3 - ;knolleary/PubSubClient bblanchon/ArduinoJson ;esp8266/DNSServer ;esp8266/EEPROM @@ -90,6 +89,40 @@ monitor_filters = time ; Add timestamp with milliseconds for each new line log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory +[env:esp8266-nokia5110] +platform = espressif8266 +board = esp12e +board_build.f_cpu = 80000000L +build_flags = -D RELEASE -DU8X8_NO_HW_I2C -DENA_NOKIA +monitor_filters = + ;default ; Remove typical terminal control codes from input + time ; Add timestamp with milliseconds for each new line + ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory +lib_deps = + https://github.com/yubox-node-org/ESPAsyncWebServer + nrf24/RF24 + paulstoffregen/Time + https://github.com/bertmelis/espMqttClient#v1.3.3 + bblanchon/ArduinoJson + olikraus/U8g2 + +[env:esp8266-ssd1306] +platform = espressif8266 +board = esp12e +board_build.f_cpu = 80000000L +build_flags = -D RELEASE -DENA_SSD1306 +monitor_filters = + ;default ; Remove typical terminal control codes from input + time ; Add timestamp with milliseconds for each new line + ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory +lib_deps = + https://github.com/yubox-node-org/ESPAsyncWebServer + nrf24/RF24 + paulstoffregen/Time + https://github.com/bertmelis/espMqttClient#v1.3.3 + bblanchon/ArduinoJson + https://github.com/ThingPulse/esp8266-oled-ssd1306.git + [env:esp32-wroom32-release] platform = espressif32 board = lolin_d32 diff --git a/src/plugins/MonochromeDisplay/MonochromeDisplay.h b/src/plugins/MonochromeDisplay/MonochromeDisplay.h new file mode 100644 index 00000000..09ec45d4 --- /dev/null +++ b/src/plugins/MonochromeDisplay/MonochromeDisplay.h @@ -0,0 +1,237 @@ +#ifndef __MONOCHROME_DISPLAY__ +#define __MONOCHROME_DISPLAY__ + +#ifdef ENA_NOKIA + #include + #define DISP_PROGMEM U8X8_PROGMEM +#else // ENA_SSD1306 + /* esp8266 : SCL = 5, SDA = 4 */ + /* ewsp32 : SCL = 22, SDA = 21 */ + #include + #include + #define DISP_PROGMEM PROGMEM +#endif + + +#include "../../utils/helper.h" +#include "../../hm/hmSystem.h" + +static uint8_t bmp_arrow[] DISP_PROGMEM = { + B00000000, B00011100, B00011100, B00001110, B00001110, B11111110, B01111111, + B01110000, B01110000, B00110000, B00111000, B00011000, B01111111, B00111111, + B00011110, B00001110, B00000110, B00000000, B00000000, B00000000, B00000000} ; + +#if defined(ENA_NOKIA) || defined(ENA_SSD1306) +template +class MonochromeDisplay { + public: + #if defined(ENA_NOKIA) + MonochromeDisplay() : mDisplay(U8G2_R0,5,4,16) { + mNewPayload = false; + mExtra = 0; + } + #else // ENA_SSD1306 + MonochromeDisplay() : mDisplay(0x3c, SDA, SCL) { + mNewPayload = false; + mExtra = 0; + mRx = 50; + mUp = 1; + } + #endif + + void setup(HMSYSTEM *sys, uint32_t *utcTs) { + mSys = sys; + mUtcTs = utcTs; + #if defined(ENA_NOKIA) + mDisplay.begin(); + ShowInfoText("booting..."); + #else + mDisplay.init(); + mDisplay.flipScreenVertically(); + mDisplay.setContrast(63); + mDisplay.setBrightness(63); + + mDisplay.clear(); + mDisplay.setFont(ArialMT_Plain_24); + mDisplay.setTextAlignment(TEXT_ALIGN_CENTER_BOTH); + + mDisplay.drawString(64,22,"Starting..."); + mDisplay.display(); + mDisplay.setTextAlignment(TEXT_ALIGN_LEFT); + #endif + } + + void loop(void) { + + } + + void payloadEventListener(uint8_t cmd) { + mNewPayload = true; + } + + void tickerSecond() { + if(mNewPayload) { + mNewPayload = false; + DataScreen(); + } + } + + private: + #if defined(ENA_NOKIA) + void ShowInfoText(const char *txt) { + /* u8g2_font_open_iconic_embedded_2x_t 'D' + 'G' + 'J' */ + mDisplay.clear(); + mDisplay.firstPage(); + do { + const char *e; + const char *p = txt; + int y=10; + mDisplay.setFont(u8g2_font_5x8_tr); + while(1) { + for(e=p+1; (*e && (*e != '\n')); e++); + size_t len=e-p; + mDisplay.setCursor(2,y); + String res=((String)p).substring(0,len); + mDisplay.print(res); + if ( !*e ) + break; + p=e+1; + y+=12; + } + mDisplay.sendBuffer(); + } while( mDisplay.nextPage() ); + } + #endif + + void DataScreen(void) { + String timeStr = ah::getDateTimeStr(*mUtcTs).substring(2, 22); + IPAddress ip = WiFi.localIP(); + float totalYield = 0.000, totalYieldToday = 0.000, totalActual = 0.0; + char fmtText[32]; + int ucnt=0; + + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + uint8_t pos; + uint8_t list[] = {FLD_PAC, FLD_YT, FLD_YD}; + + if ( !iv->isProducing(*mUtcTs,rec) ) + continue; + + ucnt++; + + for (uint8_t fld = 0; fld < 3; fld++) { + pos = iv->getPosByChFld(CH0, list[fld],rec); + + if(fld == 1) + totalYield += iv->getValue(pos,rec); + if(fld == 2) + totalYieldToday += iv->getValue(pos,rec); + if(fld == 0) + totalActual += iv->getValue(pos,rec); + } + } + } + + /* u8g2_font_open_iconic_embedded_2x_t 'D' + 'G' + 'J' */ + mDisplay.clear(); + #if defined(ENA_NOKIA) + mDisplay.firstPage(); + do { + if(ucnt) { + mDisplay.drawXBMP(10,0,8,17,bmp_arrow); + mDisplay.setFont(u8g2_font_logisoso16_tr); + mDisplay.setCursor(25,16); + sprintf(fmtText,"%3.0f",totalActual); + mDisplay.print(String(fmtText)+F(" W")); + mDisplay.drawHLine(2,20,78); + mDisplay.setFont(u8g2_font_5x8_tr); + mDisplay.setCursor(5,29); + sprintf(fmtText,"%4.0f",totalYieldToday); + mDisplay.print(F("today ")+String(fmtText)+F(" Wh")); + mDisplay.setCursor(5,37); + sprintf(fmtText,"%.1f",totalYield); + mDisplay.print(F("total ")+String(fmtText)+F(" kWh")); + } + else { + mDisplay.setFont(u8g2_font_logisoso16_tr); + mDisplay.setCursor(30,30); + mDisplay.print(F("off")); + mDisplay.setFont(u8g2_font_5x8_tr); + } + if ( !(mExtra%20) ) { + mDisplay.setCursor(5,57); + mDisplay.print(ip); + } + else { + mDisplay.setCursor(0,47); + mDisplay.print(timeStr); + } + + mDisplay.sendBuffer(); + } while( mDisplay.nextPage() ); + mExtra++; + #else // ENA_SSD1306 + if(ucnt) { + mDisplay.setBrightness(63); + mDisplay.drawXbm(10,5,8,17,bmp_arrow); + mDisplay.setFont(ArialMT_Plain_24); + sprintf(fmtText,"%3.0f",totalActual); + mDisplay.drawString(25,0,String(fmtText)+F(" W")); + mDisplay.setFont(ArialMT_Plain_16); + sprintf(fmtText,"%4.0f",totalYieldToday); + mDisplay.drawString(5,22,F("today ")+String(fmtText)+F(" Wh")); + sprintf(fmtText,"%.1f",totalYield); + mDisplay.drawString(5,35,F("total ")+String(fmtText)+F(" kWh")); + mDisplay.drawLine(2,23,123,23); + } + else { + if(mUp) { + mRx += 2; + if(mRx >= 70) + mUp = 0; + } else { + mRx -= 2; + if(mRx <= 50) + mUp = 1; + } + mDisplay.setBrightness(1); + mDisplay.setFont(ArialMT_Plain_24); + mDisplay.drawString(mRx, 10, F("off")); + mDisplay.setFont(ArialMT_Plain_16); + } + if (!(mExtra % 20)) { + mDisplay.drawString(5, 49, ip.toString()); + } else { + int w = mDisplay.getStringWidth(timeStr.c_str(), timeStr.length(), 0); + if (w > 127) { + String tt=timeStr.substring(9, 17); + w=mDisplay.getStringWidth(tt.c_str(),tt.length(), 0); + mDisplay.drawString(127 - w, 49, tt); + } else + mDisplay.drawString(0, 49, timeStr); + } + + mDisplay.display(); + mExtra++; + #endif + } + + // private member variables + #if defined(ENA_NOKIA) + U8G2_PCD8544_84X48_1_4W_HW_SPI mDisplay; + #else // ENA_SSD1306 + SSD1306Wire mDisplay; + int mRx; + char mUp; + #endif + int mExtra; + bool mNewPayload; + uint32_t *mUtcTs; + HMSYSTEM *mSys; +}; +#endif + +#endif /*__MONOCHROME_DISPLAY__*/ From 9da0fc4058b1bb21d9dcd9829753d9f22c1f22c7 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 5 Dec 2022 23:16:54 +0100 Subject: [PATCH 131/431] fix #468 MQTT status at sunset --- src/app.cpp | 175 +++++++++--------- src/app.h | 38 +--- src/defines.h | 2 +- .../MonochromeDisplay/MonochromeDisplay.h | 2 +- src/publisher/pubMqtt.h | 29 ++- src/utils/scheduler.h | 89 ++++++++- src/web/html/index.html | 2 +- src/web/webApi.cpp | 1 - 8 files changed, 211 insertions(+), 127 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 303ab562..81a75980 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -24,25 +24,30 @@ void app::setup(uint32_t timeout) { while (!Serial) yield(); - addListener(EVERY_SEC, std::bind(&app::uptimeTick, this)); - addListener(EVERY_MIN, std::bind(&app::minuteTick, this)); - addListener(EVERY_12H, std::bind(&app::ntpUpdateTick, this)); - resetSystem(); mSettings.setup(); mSettings.getPtr(mConfig); DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false"))); + addListener(EVERY_SEC, std::bind(&app::tickSecond, this)); + addListener(EVERY_MIN, std::bind(&app::tickMinute, this)); + addListener(EVERY_12H, std::bind(&app::tickNtpUpdate, this)); + once(mConfig->nrf.sendInterval, std::bind(&app::tickSend, this), "tickSend"); + if((mConfig->sun.lat) && (mConfig->sun.lon)) { + once(5, std::bind(&app::tickCalcSunrise, this)); + mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; + } + mSys = new HmSystemType(); mSys->enableDebug(); mSys->setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); mSys->addInverters(&mConfig->inst); #if !defined(AP_ONLY) - mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset); + mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mTimestamp, &mSunrise, &mSunset); #endif - mWifi.setup(mConfig, &mUtcTimestamp); + mWifi.setup(mConfig, &mTimestamp); mPayload.setup(mSys); mPayload.enableSerialDebug(mConfig->serial.debug); @@ -51,8 +56,8 @@ void app::setup(uint32_t timeout) { mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1)); addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt)); addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt)); - addListener(EVERY_HR, std::bind(&PubMqttType::tickerHour, &mMqtt)); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); + } #endif setupLed(); @@ -64,7 +69,7 @@ void app::setup(uint32_t timeout) { // Plugins #if defined(ENA_NOKIA) || defined(ENA_SSD1306) - mMonoDisplay.setup(mSys, &mUtcTimestamp); + mMonoDisplay.setup(mSys, &mTimestamp); mPayload.addListener(std::bind(&MonoDisplayType::payloadEventListener, &mMonoDisplay, std::placeholders::_1)); addListener(EVERY_SEC, std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay)); #endif @@ -119,87 +124,95 @@ void app::loop(void) { } mMqtt.loop(); +} - if (ah::checkTicker(&mTicker, 1000)) { - if (mUtcTimestamp > 946684800 && mConfig->sun.lat && mConfig->sun.lon && (mUtcTimestamp + mCalculatedTimezoneOffset) / 86400 != (mLatestSunTimestamp + mCalculatedTimezoneOffset) / 86400) { // update on reboot or midnight - if (!mLatestSunTimestamp) { // first call: calculate time zone from longitude to refresh at local midnight - mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; - } - ah::calculateSunriseSunset(mUtcTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset); - mLatestSunTimestamp = mUtcTimestamp; +//----------------------------------------------------------------------------- +void app::tickCalcSunrise(void) { + if (0 == mTimestamp) { + once(5, std::bind(&app::tickCalcSunrise, this)); // check again in 5 secs + return; + } + ah::calculateSunriseSunset(mTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset); + + uint32_t nxtTrig = mTimestamp - (mTimestamp % 86400) + 86400; // next midnight + onceAt(nxtTrig, std::bind(&app::tickCalcSunrise, this), "calc sunrise"); + onceAt(mSunrise, std::bind(&app::tickSend, this), "tickSend"); // register next event + if (mConfig->mqtt.broker[0] > 0) { + once(1, std::bind(&PubMqttType::tickerSun, &mMqtt), "MQTT-tickerSun"); + onceAt(mSunset, std::bind(&PubMqttType::tickSunset, &mMqtt)); + } +} + +//----------------------------------------------------------------------------- +void app::tickSend(void) { + if ((mTimestamp > 0) && (!mConfig->sun.disNightCom || (mTimestamp >= mSunrise && mTimestamp <= mSunset))) { // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set) + once(mConfig->nrf.sendInterval, std::bind(&app::tickSend, this), "tickSend"); // register next event + if (mConfig->serial.debug) + DPRINTLN(DBG_DEBUG, F("Free heap: 0x") + String(ESP.getFreeHeap(), HEX)); + + if (!mSys->BufCtrl.empty()) { + if (mConfig->serial.debug) + DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->BufCtrl.getFill())); } + int8_t maxLoop = MAX_NUM_INVERTERS; + Inverter<> *iv = mSys->getInverterByPos(mSendLastIvId); + do { + mSendLastIvId = ((MAX_NUM_INVERTERS - 1) == mSendLastIvId) ? 0 : mSendLastIvId + 1; + iv = mSys->getInverterByPos(mSendLastIvId); + } while ((NULL == iv) && ((maxLoop--) > 0)); + if (NULL != iv) { + if (!mPayload.isComplete(iv)) + mPayload.process(false, mConfig->nrf.maxRetransPerPyld, &mStat); - if (++mSendTicker >= mConfig->nrf.sendInterval) { - mSendTicker = 0; + if (!mPayload.isComplete(iv)) { + if (0 == mPayload.getMaxPacketId(iv)) + mStat.rxFailNoAnser++; + else + mStat.rxFail++; - if (mUtcTimestamp > 946684800 && (!mConfig->sun.disNightCom || !mLatestSunTimestamp || (mUtcTimestamp >= mSunrise && mUtcTimestamp <= mSunset))) { // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set) + iv->setQueuedCmdFinished(); // command failed if (mConfig->serial.debug) - DPRINTLN(DBG_DEBUG, F("Free heap: 0x") + String(ESP.getFreeHeap(), HEX)); - - if (!mSys->BufCtrl.empty()) { - if (mConfig->serial.debug) - DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->BufCtrl.getFill())); + DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); + if (mConfig->serial.debug) { + DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") "); + DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload.getRetransmits(iv)) + ")"); } + } + + mPayload.reset(iv, mTimestamp); + mPayload.request(iv); - int8_t maxLoop = MAX_NUM_INVERTERS; - Inverter<> *iv = mSys->getInverterByPos(mSendLastIvId); - do { - mSendLastIvId = ((MAX_NUM_INVERTERS - 1) == mSendLastIvId) ? 0 : mSendLastIvId + 1; - iv = mSys->getInverterByPos(mSendLastIvId); - } while ((NULL == iv) && ((maxLoop--) > 0)); - - if (NULL != iv) { - if (!mPayload.isComplete(iv)) - mPayload.process(false, mConfig->nrf.maxRetransPerPyld, &mStat); - - if (!mPayload.isComplete(iv)) { - if (0 == mPayload.getMaxPacketId(iv)) - mStat.rxFailNoAnser++; - else - mStat.rxFail++; - - iv->setQueuedCmdFinished(); // command failed - if (mConfig->serial.debug) - DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); - if (mConfig->serial.debug) { - DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") "); - DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload.getRetransmits(iv)) + ")"); - } - } - - mPayload.reset(iv, mUtcTimestamp); - mPayload.request(iv); - - yield(); - if (mConfig->serial.debug) { - DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status())); - DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX)); - } - - if (iv->devControlRequest) { - if (mConfig->serial.debug) - DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0])); - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit); - mPayload.setTxCmd(iv, iv->devControlCmd); - iv->clearCmdQueue(); - iv->enqueCommand(SystemConfigPara); - } else { - uint8_t cmd = iv->getQueuedCmd(); - DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); - mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload.getTs(iv), iv->alarmMesIndex); - mPayload.setTxCmd(iv, cmd); - mRxTicker = 0; - } - } - } else if (mConfig->serial.debug) - DPRINTLN(DBG_WARN, F("Time not set or it is night time, therefore no communication to the inverter!")); yield(); + if (mConfig->serial.debug) { + DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status())); + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX)); + } - updateLed(); + if (iv->devControlRequest) { + if (mConfig->serial.debug) + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0])); + mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit); + mPayload.setTxCmd(iv, iv->devControlCmd); + iv->clearCmdQueue(); + iv->enqueCommand(SystemConfigPara); + } else { + uint8_t cmd = iv->getQueuedCmd(); + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); + mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload.getTs(iv), iv->alarmMesIndex); + mPayload.setTxCmd(iv, cmd); + mRxTicker = 0; + } } + } else { + once(3600, std::bind(&app::tickSend, this), "tickSend"); // register next event (one hour) + if (mConfig->serial.debug) + DPRINTLN(DBG_WARN, F("Time not set or it is night time, therefore no communication to the inverter!")); } + yield(); + + updateLed(); } //----------------------------------------------------------------------------- @@ -224,22 +237,18 @@ void app::resetSystem(void) { snprintf(mVersion, 12, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); mShouldReboot = false; - mUptimeSecs = 0; mUpdateNtp = false; mFlagSendDiscoveryConfig = false; #ifdef AP_ONLY - mUtcTimestamp = 1; + mTimestamp = 1; #else - mUtcTimestamp = 0; + mTimestamp = 0; #endif mSunrise = 0; mSunset = 0; - mSendTicker = 0xffff; - - mTicker = 0; mRxTicker = 0; mSendLastIvId = 0; @@ -278,7 +287,7 @@ void app::updateLed(void) { Inverter<> *iv = mSys->getInverterByPos(0); if (NULL != iv) { record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - if(iv->isProducing(mUtcTimestamp, rec)) + if(iv->isProducing(mTimestamp, rec)) digitalWrite(mConfig->led.led0, LOW); // LED on else digitalWrite(mConfig->led.led0, HIGH); // LED off diff --git a/src/app.h b/src/app.h index 82b0e646..08c2e3fe 100644 --- a/src/app.h +++ b/src/app.h @@ -92,27 +92,19 @@ class app : public ah::Scheduler { String getTimeStr(uint32_t offset = 0) { char str[10]; - if(0 == mUtcTimestamp) + if(0 == mTimestamp) sprintf(str, "n/a"); else - sprintf(str, "%02d:%02d:%02d ", hour(mUtcTimestamp + offset), minute(mUtcTimestamp + offset), second(mUtcTimestamp + offset)); + sprintf(str, "%02d:%02d:%02d ", hour(mTimestamp + offset), minute(mTimestamp + offset), second(mTimestamp + offset)); return String(str); } - inline uint32_t getUptime(void) { - return mUptimeSecs; - } - - inline uint32_t getTimestamp(void) { - return mUtcTimestamp; - } - void setTimestamp(uint32_t newTime) { DPRINTLN(DBG_DEBUG, F("setTimestamp: ") + String(newTime)); if(0 == newTime) mUpdateNtp = true; else - mUtcTimestamp = newTime; + Scheduler::setTimestamp(newTime); } inline uint32_t getSunrise(void) { @@ -121,9 +113,6 @@ class app : public ah::Scheduler { inline uint32_t getSunset(void) { return mSunset; } - inline uint32_t getLatestSunTimestamp(void) { - return mLatestSunTimestamp; - } inline bool mqttIsConnected(void) { return mMqtt.isConnected(); } inline bool getSettingsValid(void) { return mSettings.getValid(); } @@ -142,11 +131,7 @@ class app : public ah::Scheduler { void setupLed(void); void updateLed(void); - void uptimeTick(void) { - mUptimeSecs++; - if (0 != mUtcTimestamp) - mUtcTimestamp++; - + void tickSecond(void) { if (mShouldReboot) { DPRINTLN(DBG_INFO, F("Rebooting...")); ESP.restart(); @@ -158,16 +143,19 @@ class app : public ah::Scheduler { } } - void minuteTick(void) { - if(0 == mUtcTimestamp) { + void tickMinute(void) { + if(0 == mTimestamp) { mUpdateNtp = true; } } - void ntpUpdateTick(void) { + void tickNtpUpdate(void) { mUpdateNtp = true; } + void tickCalcSunrise(void); + void tickSend(void); + void stats(void) { DPRINTLN(DBG_VERBOSE, F("main.h:stats")); #ifdef ESP8266 @@ -188,9 +176,6 @@ class app : public ah::Scheduler { DPRINTLN(DBG_VERBOSE, F(" - frag: ") + String(frag)); } - uint32_t mUptimeSecs; - - uint32_t mUtcTimestamp; bool mUpdateNtp; bool mShowRebootRequest; @@ -204,13 +189,11 @@ class app : public ah::Scheduler { settings mSettings; settings_t *mConfig; - uint16_t mSendTicker; uint8_t mSendLastIvId; statistics_t mStat; // timer - uint32_t mTicker; uint32_t mRxTicker; // mqtt @@ -220,7 +203,6 @@ class app : public ah::Scheduler { // sun int32_t mCalculatedTimezoneOffset; uint32_t mSunrise, mSunset; - uint32_t mLatestSunTimestamp; // plugins #if defined(ENA_NOKIA) || defined(ENA_SSD1306) diff --git a/src/defines.h b/src/defines.h index 229d583b..d2f9b98f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 47 +#define VERSION_PATCH 48 //------------------------------------- typedef struct { diff --git a/src/plugins/MonochromeDisplay/MonochromeDisplay.h b/src/plugins/MonochromeDisplay/MonochromeDisplay.h index 09ec45d4..29f44be2 100644 --- a/src/plugins/MonochromeDisplay/MonochromeDisplay.h +++ b/src/plugins/MonochromeDisplay/MonochromeDisplay.h @@ -1,6 +1,7 @@ #ifndef __MONOCHROME_DISPLAY__ #define __MONOCHROME_DISPLAY__ +#if defined(ENA_NOKIA) || defined(ENA_SSD1306) #ifdef ENA_NOKIA #include #define DISP_PROGMEM U8X8_PROGMEM @@ -21,7 +22,6 @@ static uint8_t bmp_arrow[] DISP_PROGMEM = { B01110000, B01110000, B00110000, B00111000, B00011000, B01111111, B00111111, B00011110, B00001110, B00000110, B00000000, B00000000, B00000000, B00000000} ; -#if defined(ENA_NOKIA) || defined(ENA_SSD1306) template class MonochromeDisplay { public: diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 0e3e8417..e1dc1acd 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -89,11 +89,33 @@ class PubMqtt { } } - void tickerHour() { + void tickerSun() { publish("sunrise", String(*mSunrise).c_str(), true); publish("sunset", String(*mSunset).c_str(), true); } + void tickSunset() { + char topic[MAX_NAME_LENGTH + 15], val[32]; + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL == iv) + continue; // skip to next inverter + + snprintf(topic, MAX_NAME_LENGTH + 15, "%s/available_text", iv->config->name); + snprintf(val, 32, "not available and not producing"); + publish(topic, val, true); + + snprintf(topic, MAX_NAME_LENGTH + 15, "%s/available", iv->config->name); + snprintf(val, 32, "%d", MQTT_STATUS_NOT_AVAIL_NOT_PROD); + publish(topic, val, true); + } + } + + void payloadEventListener(uint8_t cmd) { + if(mClient.connected()) // prevent overflow if MQTT broker is not reachable but set + mSendList.push(cmd); + } + void publish(const char *subTopic, const char *payload, bool retained = false, bool addTopic = true) { char topic[MQTT_TOPIC_LEN + 2]; snprintf(topic, (MQTT_TOPIC_LEN + 2), "%s/%s", mCfgMqtt->topic, subTopic); @@ -110,11 +132,6 @@ class PubMqtt { mClient.subscribe(topic, QOS_0); } - void payloadEventListener(uint8_t cmd) { - if(mClient.connected()) // prevent overflow if MQTT broker is not reachable but set - mSendList.push(cmd); - } - void setSubscriptionCb(subscriptionCb cb) { mSubscriptionCb = cb; } diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h index ff732b58..25702ce3 100644 --- a/src/utils/scheduler.h +++ b/src/utils/scheduler.h @@ -14,6 +14,13 @@ enum {EVERY_SEC = 1, EVERY_MIN, EVERY_HR, EVERY_12H, EVERY_DAY}; typedef std::function SchedulerCb; +struct once_t { + uint32_t n; + SchedulerCb f; + once_t(uint32_t a, SchedulerCb b) : n(a), f(b) {} + once_t() : n(0), f(NULL) {} +}; + namespace ah { class Scheduler { public: @@ -21,18 +28,25 @@ class Scheduler { void setup() { mPrevMillis = 0; - mSeconds = 0; - mMinutes = 0; - mHours = 0; + mSeconds = 0; + mMinutes = 0; + mHours = 0; + mUptime = 0; + mTimestamp = 0; } void loop() { if (millis() - mPrevMillis >= 1000) { mPrevMillis += 1000; + mUptime++; + if(0 != mTimestamp) + mTimestamp++; notify(&mListSecond); + onceFuncTick(); if(++mSeconds >= 60) { mSeconds = 0; notify(&mListMinute); + onceAtFuncTick(); if(++mMinutes >= 60) { mMinutes = 0; notify(&mListHour); @@ -48,6 +62,30 @@ class Scheduler { } } + // checked every second + void once(uint32_t sec, SchedulerCb cb, const char *info = NULL) { + if(NULL != info) { + DPRINT(DBG_INFO, F("once in [s]: ") + String(sec)); + DBGPRINTLN(F(", ") + String(info)); + } + mOnce.push_back(once_t(sec, cb)); + } + + // checked every minute + void onceAt(uint32_t timestamp, SchedulerCb cb, const char *info = NULL) { + if(timestamp > mTimestamp) { + if(NULL != info) { + DPRINT(DBG_INFO, F("onceAt (UTC): ") + getDateTimeStr(timestamp)); + DBGPRINTLN(F(", ") + String(info)); + } + mOnceAt.push_back(once_t(timestamp, cb)); + } + } + + virtual void setTimestamp(uint32_t ts) { + mTimestamp = ts; + } + void addListener(uint8_t every, SchedulerCb cb) { switch(every) { case EVERY_SEC: mListSecond.push_back(cb); break; @@ -59,21 +97,60 @@ class Scheduler { } } + uint32_t getUptime(void) { + return mUptime; + } + + uint32_t getTimestamp(void) { + return mTimestamp; + } + + protected: virtual void notify(std::list *lType) { for(std::list::iterator it = lType->begin(); it != lType->end(); ++it) { (*it)(); } } - protected: + uint32_t mTimestamp; + + private: + void onceFuncTick(void) { + if(mOnce.empty()) + return; + for(std::list::iterator it = mOnce.begin(); it != mOnce.end();) { + if(((*it).n)-- == 0) { + ((*it).f)(); + it = mOnce.erase(it); + } + else + ++it; + } + } + + void onceAtFuncTick(void) { + if(mOnceAt.empty()) + return; + for(std::list::iterator it = mOnceAt.begin(); it != mOnceAt.end();) { + if(((*it).n) < mTimestamp) { + ((*it).f)(); + it = mOnceAt.erase(it); + } + else + ++it; + } + } + std::list mListSecond; std::list mListMinute; std::list mListHour; std::list mList12h; std::list mListDay; - private: - uint32_t mPrevMillis; + std::list mOnce; + std::list mOnceAt; + + uint32_t mPrevMillis, mUptime; uint8_t mSeconds, mMinutes, mHours; }; } diff --git a/src/web/html/index.html b/src/web/html/index.html index e0474c08..070aee31 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -134,7 +134,7 @@ e.addEventListener("click", setTime); } - if(!obj["ts_sun_upd"]) { + if(0 == obj["ts_sunrise"]) { var e = document.getElementById("sun"); if(null != e) e.parentNode.removeChild(e); diff --git a/src/web/webApi.cpp b/src/web/webApi.cpp index b11637fa..bed67fb7 100644 --- a/src/web/webApi.cpp +++ b/src/web/webApi.cpp @@ -163,7 +163,6 @@ void webApi::getSysInfo(JsonObject obj) { obj[F("ts_now")] = mApp->getTimestamp(); obj[F("ts_sunrise")] = mApp->getSunrise(); obj[F("ts_sunset")] = mApp->getSunset(); - obj[F("ts_sun_upd")] = mApp->getLatestSunTimestamp(); obj[F("wifi_rssi")] = WiFi.RSSI(); obj[F("mac")] = WiFi.macAddress(); obj[F("hostname")] = WiFi.getHostname(); From 30bdf06f0a76b4b4bd12bb85e461344257882647 Mon Sep 17 00:00:00 2001 From: burn79 Date: Tue, 6 Dec 2022 14:55:46 +0100 Subject: [PATCH 132/431] fix typo, fix broken link --- Getting_Started.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Getting_Started.md b/Getting_Started.md index 45e7f3c2..797d0093 100644 --- a/Getting_Started.md +++ b/Getting_Started.md @@ -51,11 +51,11 @@ Hoymiles Inverters - HM1200 - HM1500 -TSun Inverters: +TSUN Inverters: -- TSOL-350 -- TSOL-400 -- [TSOL-M800](http://de.tsun-ess.com/products/TSOL-M/User-Manual-TSOL-M350&M400&M800&M1600-EN-V1.0.pdf) +- [TSOL-M350](https://www.tsun-ess.com/Micro-Inverter/M350-M400) +- [TSOL-M400](https://www.tsun-ess.com/Micro-Inverter/M350-M400) +- [TSOL-M800/TSOL-M800(DE)](https://www.tsun-ess.com/Micro-Inverter/M800) - others may work as well (need to be verified). ## Things needed From d9290d9fdf1c666b92214aa97afbb3ee23286cc1 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 8 Dec 2022 17:44:34 +0100 Subject: [PATCH 133/431] fix #480 AP Mode on fresh ESP included #483 improvements fix #468 last_success MQTT fix #468 update available status at sunset fix #447 reorderd enqueue commands to not have same payload length in a row added ssd1306 and nokia display to build script --- .github/workflows/compile_development.yml | 2 +- .github/workflows/compile_esp8266.yml | 2 +- src/app.cpp | 53 ++--- src/app.h | 2 +- src/config/settings.h | 8 +- src/defines.h | 2 +- src/hm/hmInverter.h | 9 +- src/main.cpp | 2 +- src/publisher/pubMqtt.h | 3 +- src/publisher/pubSerial.h | 37 ++-- src/utils/llist.h | 108 ++++++++++ src/utils/scheduler.h | 238 ++++++++++------------ src/utils/sun.h | 2 +- src/web/html/index.html | 14 +- src/wifi/ahoywifi.cpp | 9 +- 15 files changed, 285 insertions(+), 206 deletions(-) create mode 100644 src/utils/llist.h diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index ec435880..8188e6d1 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -47,7 +47,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release + run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release - name: Rename Binary files id: rename-binary-files diff --git a/.github/workflows/compile_esp8266.yml b/.github/workflows/compile_esp8266.yml index cf61b1f9..ab902f74 100644 --- a/.github/workflows/compile_esp8266.yml +++ b/.github/workflows/compile_esp8266.yml @@ -49,7 +49,7 @@ jobs: working-directory: src/web/html run: python convert.py - name: Run PlatformIO - run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release + run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release - name: Rename Binary files id: rename-binary-files diff --git a/src/app.cpp b/src/app.cpp index 81a75980..7b7c6e0e 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -19,24 +19,29 @@ app::app() : ah::Scheduler() { //----------------------------------------------------------------------------- -void app::setup(uint32_t timeout) { +void app::setup() { Serial.begin(115200); while (!Serial) yield(); + ah::Scheduler::setup(); + resetSystem(); mSettings.setup(); mSettings.getPtr(mConfig); DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false"))); - addListener(EVERY_SEC, std::bind(&app::tickSecond, this)); - addListener(EVERY_MIN, std::bind(&app::tickMinute, this)); - addListener(EVERY_12H, std::bind(&app::tickNtpUpdate, this)); - once(mConfig->nrf.sendInterval, std::bind(&app::tickSend, this), "tickSend"); - if((mConfig->sun.lat) && (mConfig->sun.lon)) { - once(5, std::bind(&app::tickCalcSunrise, this)); - mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; - } + + everySec(std::bind(&app::tickSecond, this)); + everyMin(std::bind(&app::tickMinute, this)); + every12h(std::bind(&app::tickNtpUpdate, this)); + every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval); + #if !defined(AP_ONLY) + if((mConfig->sun.lat) && (mConfig->sun.lon)) { + mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; + once(std::bind(&app::tickCalcSunrise, this), 5); + } + #endif mSys = new HmSystemType(); mSys->enableDebug(); @@ -54,10 +59,9 @@ void app::setup(uint32_t timeout) { #if !defined(AP_ONLY) if (mConfig->mqtt.broker[0] > 0) { mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1)); - addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt)); - addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt)); + everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt)); + everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt)); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); - } #endif setupLed(); @@ -65,16 +69,17 @@ void app::setup(uint32_t timeout) { mWeb = new web(this, mConfig, &mStat, mVersion); mWeb->setup(); mWeb->setProtection(strlen(mConfig->sys.adminPwd) != 0); - addListener(EVERY_SEC, std::bind(&web::tickSecond, mWeb)); + everySec(std::bind(&web::tickSecond, mWeb)); // Plugins #if defined(ENA_NOKIA) || defined(ENA_SSD1306) mMonoDisplay.setup(mSys, &mTimestamp); mPayload.addListener(std::bind(&MonoDisplayType::payloadEventListener, &mMonoDisplay, std::placeholders::_1)); - addListener(EVERY_SEC, std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay)); + everySec(std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay)); #endif - //addListener(EVERY_MIN, std::bind(&PubSerialType::tickerMinute, &mPubSerial)); + mPubSerial.setup(mConfig, mSys, &mTimestamp); + every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval); } //----------------------------------------------------------------------------- @@ -129,27 +134,26 @@ void app::loop(void) { //----------------------------------------------------------------------------- void app::tickCalcSunrise(void) { if (0 == mTimestamp) { - once(5, std::bind(&app::tickCalcSunrise, this)); // check again in 5 secs + once(std::bind(&app::tickCalcSunrise, this), 5); // check again in 5 secs return; } ah::calculateSunriseSunset(mTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset); uint32_t nxtTrig = mTimestamp - (mTimestamp % 86400) + 86400; // next midnight - onceAt(nxtTrig, std::bind(&app::tickCalcSunrise, this), "calc sunrise"); - onceAt(mSunrise, std::bind(&app::tickSend, this), "tickSend"); // register next event + onceAt(std::bind(&app::tickCalcSunrise, this), nxtTrig); if (mConfig->mqtt.broker[0] > 0) { - once(1, std::bind(&PubMqttType::tickerSun, &mMqtt), "MQTT-tickerSun"); - onceAt(mSunset, std::bind(&PubMqttType::tickSunset, &mMqtt)); + once(std::bind(&PubMqttType::tickerSun, &mMqtt), 1); + onceAt(std::bind(&PubMqttType::tickSunset, &mMqtt), mSunset); } } //----------------------------------------------------------------------------- void app::tickSend(void) { + if(!mSys->Radio.isChipConnected()) { + DPRINTLN(DBG_WARN, "NRF24 not connected!"); + return; + } if ((mTimestamp > 0) && (!mConfig->sun.disNightCom || (mTimestamp >= mSunrise && mTimestamp <= mSunset))) { // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set) - once(mConfig->nrf.sendInterval, std::bind(&app::tickSend, this), "tickSend"); // register next event - if (mConfig->serial.debug) - DPRINTLN(DBG_DEBUG, F("Free heap: 0x") + String(ESP.getFreeHeap(), HEX)); - if (!mSys->BufCtrl.empty()) { if (mConfig->serial.debug) DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->BufCtrl.getFill())); @@ -206,7 +210,6 @@ void app::tickSend(void) { } } } else { - once(3600, std::bind(&app::tickSend, this), "tickSend"); // register next event (one hour) if (mConfig->serial.debug) DPRINTLN(DBG_WARN, F("Time not set or it is night time, therefore no communication to the inverter!")); } diff --git a/src/app.h b/src/app.h index 08c2e3fe..e494cf91 100644 --- a/src/app.h +++ b/src/app.h @@ -52,7 +52,7 @@ class app : public ah::Scheduler { app(); ~app() {} - void setup(uint32_t timeout); + void setup(void); void loop(void); void handleIntr(void); void cbMqtt(char* topic, byte* payload, unsigned int length); diff --git a/src/config/settings.h b/src/config/settings.h index 1895cd12..01d2b8c1 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -98,6 +98,7 @@ typedef struct { cfgMqtt_t mqtt; cfgLed_t led; cfgInst_t inst; + bool valid; } settings_t; class settings { @@ -107,7 +108,7 @@ class settings { void setup() { DPRINTLN(DBG_INFO, F("Initializing FS ..")); - mValid = false; + mCfg.valid = false; #if !defined(ESP32) LittleFSConfig cfg; cfg.setAutoFormat(false); @@ -145,7 +146,7 @@ class settings { } bool getValid(void) { - return mValid; + return mCfg.valid; } void getInfo(uint32_t *used, uint32_t *size) { @@ -173,7 +174,7 @@ class settings { DynamicJsonDocument root(4096); DeserializationError err = deserializeJson(root, fp); if(!err) { - mValid = true; + mCfg.valid = true; jsonWifi(root["wifi"]); jsonNrf(root["nrf"]); jsonNtp(root["ntp"]); @@ -409,7 +410,6 @@ class settings { } settings_t mCfg; - bool mValid; }; #endif /*__SETTINGS_H__*/ diff --git a/src/defines.h b/src/defines.h index d2f9b98f..d0c7a85f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 48 +#define VERSION_PATCH 49 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index f38a36cb..2494a979 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -160,17 +160,12 @@ class Inverter { } uint8_t getQueuedCmd() { - if (_commandQueue.empty()){ - // Fill with default commands - enqueCommand(RealTimeRunData_Debug); + if (_commandQueue.empty()) { if (fwVersion == 0) - { // info needed maybe after "one night" (=> DC>0 to DC=0 and to DC>0) or reboot enqueCommand(InverterDevInform_All); - } + enqueCommand(RealTimeRunData_Debug); if (actPowerLimit == 0xffff) - { // info needed maybe after "one nigth" (=> DC>0 to DC=0 and to DC>0) or reboot enqueCommand(SystemConfigPara); - } } return _commandQueue.front().get()->getCmd(); } diff --git a/src/main.cpp b/src/main.cpp index ea708282..c585d0f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,7 @@ IRAM_ATTR void handleIntr(void) { //----------------------------------------------------------------------------- void setup() { - myApp.setup(WIFI_TRY_CONNECT_TIME); + myApp.setup(); // TODO: move to HmRadio attachInterrupt(digitalPinToInterrupt(myApp.getIrqPin()), handleIntr, FALLING); diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index e1dc1acd..dbea4957 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -95,6 +95,7 @@ class PubMqtt { } void tickSunset() { + printf("tickSunset\n"); char topic[MAX_NAME_LENGTH + 15], val[32]; for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); @@ -387,7 +388,7 @@ class PubMqtt { publish(topic, val, true); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name); - snprintf(val, 40, "%i", iv->getLastTs(rec) * 1000); + snprintf(val, 40, "%d", iv->getLastTs(rec)); publish(topic, val, true); } diff --git a/src/publisher/pubSerial.h b/src/publisher/pubSerial.h index ef4fb88f..d1cc55aa 100644 --- a/src/publisher/pubSerial.h +++ b/src/publisher/pubSerial.h @@ -21,28 +21,24 @@ class PubSerial { mUtcTimestamp = utcTs; } - void tickerMinute() { - DPRINTLN(DBG_INFO, "tickerMinute"); - if(++mTick >= mCfg->serial.interval) { - mTick = 0; - if (mCfg->serial.showIv) { - char topic[30], val[10]; - for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL != iv) { - record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - if (iv->isAvailable(*mUtcTimestamp, rec)) { - DPRINTLN(DBG_INFO, F("Inverter: ") + String(id)); - for (uint8_t i = 0; i < rec->length; i++) { - if (0.0f != iv->getValue(i, rec)) { - snprintf(topic, 30, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec)); - snprintf(val, 10, "%.3f %s", iv->getValue(i, rec), iv->getUnit(i, rec)); - DPRINTLN(DBG_INFO, String(topic) + ": " + String(val)); - } - yield(); + void tick(void) { + if (mCfg->serial.showIv) { + char topic[32 + MAX_NAME_LENGTH], val[40]; + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + if (iv->isAvailable(*mUtcTimestamp, rec)) { + DPRINTLN(DBG_INFO, F("Inverter: ") + String(id)); + for (uint8_t i = 0; i < rec->length; i++) { + if (0.0f != iv->getValue(i, rec)) { + snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec)); + snprintf(val, 40, "%.3f %s", iv->getValue(i, rec), iv->getUnit(i, rec)); + DPRINTLN(DBG_INFO, String(topic) + ": " + String(val)); } - DPRINTLN(DBG_INFO, ""); + yield(); } + DPRINTLN(DBG_INFO, ""); } } } @@ -52,7 +48,6 @@ class PubSerial { private: settings_t *mCfg; HMSYSTEM *mSys; - uint8_t mTick; uint32_t *mUtcTimestamp; }; diff --git a/src/utils/llist.h b/src/utils/llist.h new file mode 100644 index 00000000..dd139c86 --- /dev/null +++ b/src/utils/llist.h @@ -0,0 +1,108 @@ +//----------------------------------------------------------------------------- +// 2022 Ahoy, https://ahoydtu.de +// Lukas Pusch, lukas@lpusch.de +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- +#ifndef __LIST_H__ +#define __LIST_H__ + +template +struct node_s { + typedef T dT; + node_s *pre; + node_s *nxt; + uint32_t id; + dT d; + node_s() : pre(NULL), nxt(NULL), d() {} + node_s(Args... args) : id(0), pre(NULL), nxt(NULL), d(args...) {} +}; + +template +class llist { + typedef node_s elmType; + typedef T dataType; + public: + llist() : root(mPool) { + root = NULL; + elmType *p = mPool; + for(uint32_t i = 0; i < MAX_NUM; i++) { + p->id = i; + p++; + } + mFill = mMax = 0; + } + + elmType *add(Args... args) { + elmType *p = root, *t; + if(NULL == (t = getFreeNode())) + return NULL; + if(++mFill > mMax) + mMax = mFill; + + if(NULL == root) { + p = root = t; + p->pre = p; + p->nxt = p; + } + else { + p = root->pre; + t->pre = p; + p->nxt->pre = t; + t->nxt = p->nxt; + p->nxt = t; + } + t->d = dataType(args...); + return p; + } + + elmType *getFront() { + return root; + } + + elmType *get(elmType *p) { + p = p->nxt; + return (p == root) ? NULL : p; + } + + elmType *rem(elmType *p) { + if(NULL == p) + return NULL; + elmType *t = p->nxt; + p->nxt->pre = p->pre; + p->pre->nxt = p->nxt; + if(root == p) + root = NULL; + p->nxt = NULL; + p->pre = NULL; + p = NULL; + mFill--; + return (NULL == root) ? NULL : ((t == root) ? NULL : t); + } + + uint16_t getFill(void) { + return mFill; + } + + uint16_t getMaxFill(void) { + return mMax; + } + + protected: + elmType *root; + + private: + elmType *getFreeNode(void) { + elmType *n = mPool; + for(uint32_t i = 0; i < MAX_NUM; i++) { + if(NULL == n->nxt) + return n; + n++; + } + return NULL; + } + + elmType mPool[MAX_NUM]; + uint16_t mFill, mMax; +}; + +#endif /*__LIST_H__*/ diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h index 25702ce3..5e7848b1 100644 --- a/src/utils/scheduler.h +++ b/src/utils/scheduler.h @@ -7,152 +7,132 @@ #ifndef __SCHEDULER_H__ #define __SCHEDULER_H__ -#include #include -#include - -enum {EVERY_SEC = 1, EVERY_MIN, EVERY_HR, EVERY_12H, EVERY_DAY}; -typedef std::function SchedulerCb; - -struct once_t { - uint32_t n; - SchedulerCb f; - once_t(uint32_t a, SchedulerCb b) : n(a), f(b) {} - once_t() : n(0), f(NULL) {} -}; +#include "llist.h" +#include "dbg.h" namespace ah { -class Scheduler { - public: - Scheduler() {} - - void setup() { - mPrevMillis = 0; - mSeconds = 0; - mMinutes = 0; - mHours = 0; - mUptime = 0; - mTimestamp = 0; - } - - void loop() { - if (millis() - mPrevMillis >= 1000) { - mPrevMillis += 1000; - mUptime++; - if(0 != mTimestamp) - mTimestamp++; - notify(&mListSecond); - onceFuncTick(); - if(++mSeconds >= 60) { - mSeconds = 0; - notify(&mListMinute); - onceAtFuncTick(); - if(++mMinutes >= 60) { - mMinutes = 0; - notify(&mListHour); - if(++mHours >= 24) { - mHours = 0; - notify(&mListDay); - notify(&mList12h); - } - else if(mHours == 12) - notify(&mList12h); - } - } + typedef std::function scdCb; + + enum {SCD_SEC = 1, SCD_MIN = 60, SCD_HOUR = 3600, SCD_12H = 43200, SCD_DAY = 86400}; + + struct scdEvry_s { + scdCb c; + uint32_t timeout; + uint32_t reload; + scdEvry_s() : c(NULL), timeout(0), reload(0) {} + scdEvry_s(scdCb a, uint32_t tmt, uint32_t rl) : c(a), timeout(tmt), reload(rl) {} + }; + + struct scdAt_s { + scdCb c; + uint32_t timestamp; + scdAt_s() : c(NULL), timestamp(0) {} + scdAt_s(scdCb a, uint32_t ts) : c(a), timestamp(ts) {} + }; + + + typedef node_s sP; + typedef node_s sPAt; + class Scheduler { + public: + Scheduler() {} + + void setup() { + mUptime = 0; + mTimestamp = 0; + mPrevMillis = millis(); } - } - // checked every second - void once(uint32_t sec, SchedulerCb cb, const char *info = NULL) { - if(NULL != info) { - DPRINT(DBG_INFO, F("once in [s]: ") + String(sec)); - DBGPRINTLN(F(", ") + String(info)); - } - mOnce.push_back(once_t(sec, cb)); - } - - // checked every minute - void onceAt(uint32_t timestamp, SchedulerCb cb, const char *info = NULL) { - if(timestamp > mTimestamp) { - if(NULL != info) { - DPRINT(DBG_INFO, F("onceAt (UTC): ") + getDateTimeStr(timestamp)); - DBGPRINTLN(F(", ") + String(info)); + void loop(void) { + mMillis = millis(); + mDiff = mMillis - mPrevMillis; + if(mDiff >= 1000) { + if(mMillis < mPrevMillis) { // overflow + mPrevMillis = mMillis; + return; + } + mDiffSeconds = mDiff / 1000; + mPrevMillis += (mPrevMillis * 1000); + checkEvery(); + checkAt(); + mUptime += mDiffSeconds; + if(0 != mTimestamp) + mTimestamp += mDiffSeconds; } - mOnceAt.push_back(once_t(timestamp, cb)); } - } - - virtual void setTimestamp(uint32_t ts) { - mTimestamp = ts; - } - - void addListener(uint8_t every, SchedulerCb cb) { - switch(every) { - case EVERY_SEC: mListSecond.push_back(cb); break; - case EVERY_MIN: mListMinute.push_back(cb); break; - case EVERY_HR: mListHour.push_back(cb); break; - case EVERY_12H: mList12h.push_back(cb); break; - case EVERY_DAY: mListDay.push_back(cb); break; - default: break; + + void once(scdCb c, uint32_t timeout) { mStack.add(c, timeout, 0); } + void every(scdCb c, uint32_t interval) { mStack.add(c, interval, interval); } + void onceAt(scdCb c, uint32_t timestamp) { mStackAt.add(c, timestamp); } + + void everySec(scdCb c) { mStack.add(c, SCD_SEC, SCD_SEC); } + void everyMin(scdCb c) { mStack.add(c, SCD_MIN, SCD_MIN); } + void everyHour(scdCb c) { mStack.add(c, SCD_HOUR, SCD_HOUR); } + void every12h(scdCb c) { mStack.add(c, SCD_12H, SCD_12H); } + void everyDay(scdCb c) { mStack.add(c, SCD_DAY, SCD_DAY); } + + virtual void setTimestamp(uint32_t ts) { + mTimestamp = ts; } - } - uint32_t getUptime(void) { - return mUptime; - } + uint32_t getUptime(void) { + return mUptime; + } - uint32_t getTimestamp(void) { - return mTimestamp; - } + uint32_t getTimestamp(void) { + return mTimestamp; + } - protected: - virtual void notify(std::list *lType) { - for(std::list::iterator it = lType->begin(); it != lType->end(); ++it) { - (*it)(); + void stat() { + DPRINTLN(DBG_INFO, "max fill every: " + String(mStack.getMaxFill())); + DPRINTLN(DBG_INFO, "max fill at: " + String(mStackAt.getMaxFill())); } - } - - uint32_t mTimestamp; - - private: - void onceFuncTick(void) { - if(mOnce.empty()) - return; - for(std::list::iterator it = mOnce.begin(); it != mOnce.end();) { - if(((*it).n)-- == 0) { - ((*it).f)(); - it = mOnce.erase(it); + + protected: + uint32_t mTimestamp; + + private: + inline void checkEvery(void) { + bool expired; + sP *p = mStack.getFront(); + while(NULL != p) { + if(mDiffSeconds >= p->d.timeout) expired = true; + else if((p->d.timeout--) == 0) expired = true; + else expired = false; + + if(expired) { + (p->d.c)(); + if(0 == p->d.reload) + p = mStack.rem(p); + else { + p->d.timeout = p->d.reload - 1; + p = mStack.get(p); + } + } + else + p = mStack.get(p); } - else - ++it; } - } - - void onceAtFuncTick(void) { - if(mOnceAt.empty()) - return; - for(std::list::iterator it = mOnceAt.begin(); it != mOnceAt.end();) { - if(((*it).n) < mTimestamp) { - ((*it).f)(); - it = mOnceAt.erase(it); + + inline void checkAt(void) { + sPAt *p = mStackAt.getFront(); + while(NULL != p) { + if((p->d.timestamp) <= mTimestamp) { + (p->d.c)(); + p = mStackAt.rem(p); + } + else + p = mStackAt.get(p); } - else - ++it; } - } - - std::list mListSecond; - std::list mListMinute; - std::list mListHour; - std::list mList12h; - std::list mListDay; - - std::list mOnce; - std::list mOnceAt; - uint32_t mPrevMillis, mUptime; - uint8_t mSeconds, mMinutes, mHours; -}; + llist<25, scdEvry_s, scdCb, uint32_t, uint32_t> mStack; + llist<10, scdAt_s, scdCb, uint32_t> mStackAt; + uint32_t mMillis, mPrevMillis, mDiff; + uint32_t mUptime; + uint8_t mDiffSeconds; + }; } #endif /*__SCHEDULER_H__*/ diff --git a/src/utils/sun.h b/src/utils/sun.h index c6d078d4..c66149c2 100644 --- a/src/utils/sun.h +++ b/src/utils/sun.h @@ -10,7 +10,7 @@ namespace ah { void calculateSunriseSunset(uint32_t utcTs, uint32_t offset, float lat, float lon, uint32_t *sunrise, uint32_t *sunset) { // Source: https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth - // Julian day since 1.1.2000 12:00 + correction 69.12s + // Julian day since 1.1.2000 12:00 double n_JulianDay = (utcTs + offset) / 86400 - 10957.0; // Mean solar time double J = n_JulianDay - lon / 360; diff --git a/src/web/html/index.html b/src/web/html/index.html index 070aee31..b5b55b9b 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -48,9 +48,6 @@
        Discuss with us on Discord
        -

        Documentation

        - ahoydtu.de -

        Support this project:

        • Report issues
        • @@ -118,10 +115,13 @@ var sec = up % 60; var sunrise = new Date(obj["ts_sunrise"] * 1000); var sunset = new Date(obj["ts_sunset"] * 1000); - document.getElementById("uptime").innerHTML = days + " Days, " - + ("0"+hrs).substr(-2) + ":" - + ("0"+min).substr(-2) + ":" - + ("0"+sec).substr(-2); + var e = document.getElementById("uptime"); + e.innerHTML = days + " Day"; + if(1 != days) + e.innerHTML += "s"; + e.innerHTML += ", " + ("0"+hrs).substr(-2) + ":" + + ("0"+min).substr(-2) + ":" + + ("0"+sec).substr(-2); var dSpan = document.getElementById("date"); if(0 != obj["ts_now"]) dSpan.innerHTML = date.toLocaleString('de-DE'); diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 82370031..c8a10412 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -8,8 +8,6 @@ #define F(sl) (sl) #endif #include "ahoywifi.h" -#include "../utils/ahoyTimer.h" - // NTP CONFIG #define NTP_PACKET_SIZE 48 @@ -25,17 +23,16 @@ ahoywifi::ahoywifi() { //----------------------------------------------------------------------------- void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp) { - char ipSta[16]; mConfig = config; mUtcTimestamp = utcTimestamp; #if !defined(FB_WIFI_OVERRIDDEN) - if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) != 0) + if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) == 0) setupAp(); #endif #if !defined(AP_ONLY) - setupStation(); - ah::ip2Char(mConfig->sys.ip.ip, ipSta); + if(mConfig->valid) + setupStation(); #endif #if defined(ESP8266) From 1fb45191a1ee62f964c7558ac794f62f771c3b74 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 8 Dec 2022 17:52:40 +0100 Subject: [PATCH 134/431] added builds for ESP32 and Nokia5110 and SSD1306 displays --- .github/workflows/compile_development.yml | 2 +- .github/workflows/compile_esp8266.yml | 2 +- src/platformio.ini | 34 +++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index 8188e6d1..8d8ab45e 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -47,7 +47,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release + run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 - name: Rename Binary files id: rename-binary-files diff --git a/.github/workflows/compile_esp8266.yml b/.github/workflows/compile_esp8266.yml index ab902f74..a3c450d2 100644 --- a/.github/workflows/compile_esp8266.yml +++ b/.github/workflows/compile_esp8266.yml @@ -49,7 +49,7 @@ jobs: working-directory: src/web/html run: python convert.py - name: Run PlatformIO - run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release + run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 - name: Rename Binary files id: rename-binary-files diff --git a/src/platformio.ini b/src/platformio.ini index 3bf76cdc..406bcdd1 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -143,3 +143,37 @@ monitor_filters = ;default ; Remove typical terminal control codes from input time ; Add timestamp with milliseconds for each new line log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory + +[env:esp32-wroom32-nokia5110] +platform = espressif32 +board = lolin_d32 +build_flags = -D RELEASE -std=gnu++14 -DU8X8_NO_HW_I2C -DENA_NOKIA +build_unflags = -std=gnu++11 +monitor_filters = + ;default ; Remove typical terminal control codes from input + time ; Add timestamp with milliseconds for each new line + ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory +lib_deps = + https://github.com/yubox-node-org/ESPAsyncWebServer + nrf24/RF24 + paulstoffregen/Time + https://github.com/bertmelis/espMqttClient#v1.3.3 + bblanchon/ArduinoJson + olikraus/U8g2 + +[env:esp32-wroom32-ssd1306] +platform = espressif32 +board = lolin_d32 +build_flags = -D RELEASE -std=gnu++14 -DENA_SSD1306 +build_unflags = -std=gnu++11 +monitor_filters = + ;default ; Remove typical terminal control codes from input + time ; Add timestamp with milliseconds for each new line + ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory +lib_deps = + https://github.com/yubox-node-org/ESPAsyncWebServer + nrf24/RF24 + paulstoffregen/Time + https://github.com/bertmelis/espMqttClient#v1.3.3 + bblanchon/ArduinoJson + https://github.com/ThingPulse/esp8266-oled-ssd1306.git From a9e4429f9f3b88d9ab25b498f52a5e1b5b0e53b1 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 8 Dec 2022 21:08:58 +0100 Subject: [PATCH 135/431] system clock was too fast included display builds into zip removed 10s info from index.html --- scripts/getVersion.py | 27 ++++++++++++++++++++++++++- src/defines.h | 2 +- src/publisher/pubMqtt.h | 2 +- src/utils/scheduler.h | 5 ++++- src/web/html/index.html | 21 +++++++++++++++++---- 5 files changed, 49 insertions(+), 8 deletions(-) diff --git a/scripts/getVersion.py b/scripts/getVersion.py index 21406418..ffcc2714 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -51,13 +51,26 @@ def readVersion(path, infile): os.mkdir(path + "firmware/") sha = os.getenv("SHA",default="sha") + versionout = version[:-1] + "_esp8266_" + sha + ".bin" src = path + ".pio/build/esp8266-release/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) gzip_bin(dst, dst + ".gz") + + versionout = version[:-1] + "_esp8266_nokia5110_" + sha + ".bin" + src = path + ".pio/build/esp8266-nokia5110/firmware.bin" + dst = path + "firmware/" + versionout + os.rename(src, dst) + gzip_bin(dst, dst + ".gz") + + versionout = version[:-1] + "_esp8266_ssd1306_" + sha + ".bin" + src = path + ".pio/build/esp8266-ssd1306/firmware.bin" + dst = path + "firmware/" + versionout + os.rename(src, dst) + gzip_bin(dst, dst + ".gz") - versionout = version[:-1] + "_esp8266_1m_" + sha + ".bin" + versionout = version[:-1] + "_esp8285_" + sha + ".bin" src = path + ".pio/build/esp8285-release/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) @@ -69,6 +82,18 @@ def readVersion(path, infile): os.rename(src, dst) gzip_bin(dst, dst + ".gz") + versionout = version[:-1] + "_esp32_nokia5110_" + sha + ".bin" + src = path + ".pio/build/esp32-wroom32-nokia5110/firmware.bin" + dst = path + "firmware/" + versionout + os.rename(src, dst) + gzip_bin(dst, dst + ".gz") + + versionout = version[:-1] + "_esp32_ssd1306_" + sha + ".bin" + src = path + ".pio/build/esp32-wroom32-ssd1306/firmware.bin" + dst = path + "firmware/" + versionout + os.rename(src, dst) + gzip_bin(dst, dst + ".gz") + # other ESP32 bin files src = path + ".pio/build/esp32-wroom32-release/" dst = path + "firmware/" diff --git a/src/defines.h b/src/defines.h index d0c7a85f..d223d764 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 49 +#define VERSION_PATCH 50 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index dbea4957..9a890f86 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -236,7 +236,7 @@ class PubMqtt { publish("version", mVersion, true); publish("device", mDevName, true); - publish("uptime", "0"); + tickerMinute(); publish(mLwtTopic, mLwtOnline, true, false); subscribe("ctrl/#"); diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h index 5e7848b1..d10b56fd 100644 --- a/src/utils/scheduler.h +++ b/src/utils/scheduler.h @@ -42,6 +42,7 @@ namespace ah { mUptime = 0; mTimestamp = 0; mPrevMillis = millis(); + mDiffFraq = 0; } void loop(void) { @@ -53,7 +54,8 @@ namespace ah { return; } mDiffSeconds = mDiff / 1000; - mPrevMillis += (mPrevMillis * 1000); + mDiffFraq = mDiff % 1000; + mPrevMillis += (mDiffSeconds * 1000) - mDiffFraq; checkEvery(); checkAt(); mUptime += mDiffSeconds; @@ -132,6 +134,7 @@ namespace ah { uint32_t mMillis, mPrevMillis, mDiff; uint32_t mUptime; uint8_t mDiffSeconds; + uint16_t mDiffFraq; }; } diff --git a/src/web/html/index.html b/src/web/html/index.html index b5b55b9b..6833e10d 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -39,12 +39,11 @@

        WiFi RSSI: dBm

        - Statistics: + System Infos:

        
                             
        
                             
        
                         

        -

        Every seconds the values are updated

        Discuss with us on Discord
        @@ -79,6 +78,8 @@
        -

        Uptime:

        -

        ESP-Time:

        +

        + Uptime:
        + ESP-Time: +

        - Sunrise:
        - Sunset: + Communication
        + start:
        + stop:

        WiFi RSSI: dBm

        diff --git a/src/web/html/system.html b/src/web/html/system.html index c95d581a..9835aca3 100644 --- a/src/web/html/system.html +++ b/src/web/html/system.html @@ -55,6 +55,7 @@ for (const [key, value] of Object.entries(obj)) { if(!data.includes(key) || (typeof value == 'undefined')) continue; var li = document.createElement("li"); + li.appendChild() li.appendChild(document.createTextNode(key + ": " + value)); ul.appendChild(li); } @@ -86,10 +87,6 @@ if(null != obj) { parseMenu(obj["menu"]); parseSys(obj["system"]); - parseSysInfo(obj["system"]); - parseRadio(obj["system"]["radio"]); - var e = document.getElementById("system"); - e.innerHTML = obj["html"]; if(null != obj["refresh"]) { var meta = document.createElement('meta'); @@ -97,6 +94,12 @@ meta.content = obj["refresh"] + "; URL=" + obj["refresh_url"]; document.getElementsByTagName('head')[0].appendChild(meta); } + else { + parseSysInfo(obj["system"]); + parseRadio(obj["system"]["radio"]); + } + var e = document.getElementById("system"); + e.innerHTML = obj["html"]; } } diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 203df285..294c4073 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -8,6 +8,7 @@ #define F(sl) (sl) #endif #include "ahoywifi.h" +#include // NTP CONFIG #define NTP_PACKET_SIZE 48 From 4df61833caad6632ad6ac482540ee9d3bb5180ff Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 18 Dec 2022 01:14:54 +0100 Subject: [PATCH 153/431] beautified system.html (converted to table) --- src/CHANGES.md | 1 + src/web/html/api.js | 3 +- src/web/html/style.css | 74 ++++++++++++++++++++++++++++++++++++++++ src/web/html/system.html | 47 ++++++++++++++----------- 4 files changed, 104 insertions(+), 21 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index e86a8b40..29c3d999 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -4,6 +4,7 @@ * factory reset formats entire little fs * renamed sunrise / sunset on indext.html to start / stop communication * show system information only if called directly from menu +* beautified system.html ## 0.5.55 * fixed static IP save diff --git a/src/web/html/api.js b/src/web/html/api.js index bdd0b6df..d74fb0b7 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -128,9 +128,10 @@ function opt(val, html) { return o; } -function div(cl) { +function div(cl, h=null) { e = document.createElement('div'); e.classList.add(...cl); + if(null != h) e.innerHTML = h; return e; } diff --git a/src/web/html/style.css b/src/web/html/style.css index 0af591ad..87b2c4a0 100644 --- a/src/web/html/style.css +++ b/src/web/html/style.css @@ -437,3 +437,77 @@ div.ModPwr, div.ModName { border: 0px; margin-bottom: 10px; } + + +.head { + background-color: #006ec0; + color: #fff; +} + +.row { display: flex; max-width: 100%; flex-wrap: wrap; } +.col { flex: 1 0 0%; } + +.col-1, .col-2, .col-3, .col-4, +.col-5, .col-6, .col-7, .col-8, +.col-9, .col-10, .col-11, .col-12 { flex: 0 0 auto; } + + +.col-1 { width: 8.333333333%; } +.col-2 { width: 16.66666667%; } +.col-3 { width: 25%; } +.col-4 { width: 33.33333333%; } +.col-5 { width: 41.66666667%; } +.col-6 { width: 50%; } +.col-7 { width: 58.33333333%; } +.col-8 { width: 66.66666667%; } +.col-9 { width: 75%; } +.col-10 { width: 83.33333333%; } +.col-11 { width: 91.66666667%; } +.col-12 { width: 100%; } + +.p-1 { padding: 0.25rem; } +.p-2 { padding: 0.5rem; } +.p-3 { padding: 1rem; } +.p-4 { padding: 1.5rem; } +.p-5 { padding: 3rem; } + +.mt-1 { margin-top: 0.25rem } +.mt-2 { margin-top: 0.5rem } +.mt-3 { margin-top: 1rem } +.mt-4 { margin-top: 1.5rem } +.mt-5 { margin-top: 3rem } + +.a-r { text-align: right; } +.a-c { text-align: center; } + +/* sm */ +@media(min-width: 768px) { + .col-sm-1 { width: 8.333333333%; } + .col-sm-2 { width: 16.66666667%; } + .col-sm-3 { width: 25%; } + .col-sm-4 { width: 33.33333333%; } + .col-sm-5 { width: 41.66666667%; } + .col-sm-6 { width: 50%; } + .col-sm-7 { width: 58.33333333%; } + .col-sm-8 { width: 66.66666667%; } + .col-sm-9 { width: 75%; } + .col-sm-10 { width: 83.33333333%; } + .col-sm-11 { width: 91.66666667%; } + .col-sm-12 { width: 100%; } +} + +/* md */ +@media(min-width: 992px) { + .col-md-1 { width: 8.333333333%; } + .col-md-2 { width: 16.66666667%; } + .col-md-3 { width: 25%; } + .col-md-4 { width: 33.33333333%; } + .col-md-5 { width: 41.66666667%; } + .col-md-6 { width: 50%; } + .col-md-7 { width: 58.33333333%; } + .col-md-8 { width: 66.66666667%; } + .col-md-9 { width: 75%; } + .col-md-10 { width: 83.33333333%; } + .col-md-11 { width: 91.66666667%; } + .col-md-12 { width: 100%; } +} diff --git a/src/web/html/system.html b/src/web/html/system.html index 9835aca3..7303bd0a 100644 --- a/src/web/html/system.html +++ b/src/web/html/system.html @@ -18,9 +18,9 @@

        -
          -
            -
            +
            +
            +
            @@ -35,23 +36,18 @@ Uptime:
            ESP-Time:

            -
            - Communication
            - start:
            - stop: -
            -

            WiFi RSSI: dBm

            - System Infos: -

            
            -                    
            
            -                    
            
            +                    System Infos:
            +                    
            +
            +

            +
            - Discuss with us on Discord

            Support this project:

              +
            • Discuss with us on Discord
            • Report issues
            • Contribute to documentation
            • Test development firmware
            • @@ -83,6 +79,7 @@ var exeOnce = true; var tickCnt = 0; var ts = 0; + var commInfo = ""; function apiCb(obj) { var e = document.getElementById("apiResult"); @@ -102,24 +99,28 @@ getAjax("/api/setup", apiCb, "POST", JSON.stringify(obj)); } - function parseSys(obj) { + function ts2Span(ts) { + return span(new Date(ts * 1000).toLocaleString('de-DE')); + } + + function parseGeneric(obj) { // Disclaimer //if(obj["disclaimer"] == false) sessionStorage.setItem("gDisclaimer", promptFunction()); if(exeOnce){ parseVersion(obj); parseESP(obj); } - document.getElementById("wifi_rssi").innerHTML = obj["wifi_rssi"]; + parseRssi(obj); + } + function parseSys(obj) { ts = obj["ts_now"]; var date = new Date(obj["ts_now"] * 1000); - var up = obj["ts_uptime"]; + var up = obj["generic"]["ts_uptime"]; var days = parseInt(up / 86400) % 365; var hrs = parseInt(up / 3600) % 24; var min = parseInt(up / 60) % 60; var sec = up % 60; - var sunrise = new Date(obj["ts_sunrise"] * 1000); - var sunset = new Date(obj["ts_sunset"] * 1000); var e = document.getElementById("uptime"); e.innerHTML = days + " Day"; if(1 != days) @@ -139,60 +140,73 @@ e.addEventListener("click", setTime); } - if(0 == obj["ts_sunrise"]) { - var e = document.getElementById("sun"); - if(null != e) - e.parentNode.removeChild(e); - } - else { - document.getElementById("sunrise").innerHTML = sunrise.toLocaleString('de-DE'); - document.getElementById("sunset").innerHTML = sunset.toLocaleString('de-DE'); + if(obj["ts_sunrise"] > 0) { + if(((obj["ts_sunrise"] - obj["ts_offset"]) < obj["ts_now"]) + && ((obj["ts_sunset"] + obj["ts_offset"]) > obj["ts_now"])) { + commInfo = "Polling inverter(s), will stop at " + (new Date((obj["ts_sunset"] + obj["ts_offset"]) * 1000).toLocaleString('de-DE')); + } + else { + commInfo = "Night time, no Communication to Inverter, "; + if(obj["ts_now"] > (obj["ts_sunrise"] - obj["ts_offset"])) { + commInfo += "stopped polling at " + (new Date((obj["ts_sunset"] + obj["ts_offset"]) * 1000).toLocaleString('de-DE')); + } + else { + commInfo += "will start polling at " + (new Date((obj["ts_sunrise"] - obj["ts_offset"]) * 1000).toLocaleString('de-DE')); + } + } } } - function parseStat(obj) { - document.getElementById("stat").innerHTML = "RX success: " + obj["rx_success"] - + "\nRX fail: " + obj["rx_fail"] - + "\nRX no answer: " + obj["rx_fail_answer"] - + "\nFrames received: " + obj["frame_cnt"] - + "\nTX cnt: " + obj["tx_cnt"]; - } - function parseIv(obj) { - var html = ""; + var p = div(["none"]); for(var i of obj) { - html += "Inverter #" + i["id"] + ": " + i["name"] + " (v" + i["version"] + ") is "; - if(false == i["is_avail"]) - html += "not yet available\n"; + var icon = iconWarn; + var color = "#F70"; + avail = ""; + if(false == i["enabled"]) { + avail = "disabled"; + } + else if(false == i["is_avail"]) { + icon = iconInfo; + color = "#00d"; + avail = "not yet available"; + } else { - html += "available and is "; + icon = iconSuccess; + avail = "available and is "; if(false == i["is_producing"]) - html += "not "; - html += "producing\n"; + avail += "not "; + avail += "producing"; } + p.append( + svg(icon, 20, 20, color, "icon"), + span("Inverter #" + i["id"] + ": " + i["name"] + " (v" + i["version"] + ") is " + avail), + br() + ); + if(false == i["is_avail"]) { if(i["ts_last_success"] > 0) { var date = new Date(i["ts_last_success"] * 1000); - html += "-> last successful transmission: " + date.toLocaleString('de-DE') + "\n"; + p.append(span("-> last successful transmission: " + date.toLocaleString('de-DE')), br()); } } - if(false == i["enabled"]) - html += "-> disabled\n"; - } - document.getElementById("iv").innerHTML = html; + document.getElementById("iv").replaceChildren(p); } - function parseWarnInfo(warn, info) { - var html = ""; + function parseWarnInfo(warn, success) { + var p = div(["none"]); for(var w of warn) { - html += "WARN: " + w + "\n"; + p.append(svg(iconWarn, 20, 20, "#F70", "icon"), span(w), br()); } - for(var i of info) { - html += "INFO: " + i + "\n"; + for(var i of success) { + p.append(svg(iconSuccess, 20, 20, "#090", "icon"), span(i), br()); } - document.getElementById("warn_info").innerHTML = html; + + if(commInfo.length > 0) + p.append(svg(iconInfo, 20, 20, "#00d", "icon"), span(commInfo), br()); + document.getElementById("warn_info").replaceChildren(p); } function tick() { @@ -208,8 +222,8 @@ if(null != obj) { if(exeOnce) parseMenu(obj["menu"]); - parseSys(obj["system"]); - parseStat(obj["statistics"]); + parseGeneric(obj["generic"]); + parseSys(obj); parseIv(obj["inverter"]); parseWarnInfo(obj["warnings"], obj["infos"]); if(exeOnce) { @@ -217,8 +231,6 @@ exeOnce = false; } } - else - document.getElementById("refresh").innerHTML = "n/a"; } getAjax("/api/index", parse); diff --git a/src/web/html/login.html b/src/web/html/login.html index 68f44084..6161461f 100644 --- a/src/web/html/login.html +++ b/src/web/html/login.html @@ -33,10 +33,10 @@
            diff --git a/src/web/html/serial.html b/src/web/html/serial.html index ea57f73f..a102b58c 100644 --- a/src/web/html/serial.html +++ b/src/web/html/serial.html @@ -15,6 +15,7 @@
            +
            @@ -83,7 +84,7 @@ var con = document.getElementById("serial"); var exeOnce = true; - function parseSys(obj) { + function parseGeneric(obj) { var up = obj["ts_uptime"]; var days = parseInt(up / 86400) % 365; var hrs = parseInt(up / 3600) % 24; @@ -94,10 +95,11 @@ + ("0"+min).substr(-2) + ":" + ("0"+sec).substr(-2); + parseRssi(obj); if(true == exeOnce) { parseVersion(obj); parseESP(obj); - window.setInterval("getAjax('/api/system', parseSys)", 10000); + window.setInterval("getAjax('/api/generic', parseGeneric)", 10000); exeOnce = false; getAjax("/api/setup", parse); } @@ -201,7 +203,7 @@ getAjax("/api/ctrl", ctrlCb, "POST", JSON.stringify(obj)); }); - getAjax("/api/system", parseSys); + getAjax("/api/generic", parseGeneric); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 3a83c5ee..0790c4bf 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -26,6 +26,7 @@
            +
            @@ -41,7 +42,7 @@
            - +
            WiFi @@ -116,6 +117,8 @@ + +

            @@ -337,8 +340,12 @@ var e = document.getElementsByName("adminpwd")[0]; if(!obj["pwd_set"]) e.value = ""; + } + + function parseGeneric(obj) { parseVersion(obj); parseESP(obj); + parseRssi(obj); } function parseStaticIp(obj) { @@ -368,6 +375,10 @@ document.getElementsByName("sunLat")[0].value = obj["lat"]; document.getElementsByName("sunLon")[0].value = obj["lon"]; document.getElementsByName("sunDisNightCom")[0].checked = obj["disnightcom"]; + const sel = document.getElementsByName("sunOffs")[0]; + for(var i = 0; i <= 60; i++) { + sel.appendChild(opt(i, i + " minutes", (i == (obj["offs"] / 60)))); + } } function parsePinout(obj, type) { @@ -452,6 +463,7 @@ if(null != root) { parseMenu(root["menu"]); parseSys(root["system"]); + parseGeneric(root["generic"]); parseStaticIp(root["static_ip"]); parseIv(root["inverter"]); parseMqtt(root["mqtt"]); diff --git a/src/web/html/style.css b/src/web/html/style.css index 87b2c4a0..8f4b473b 100644 --- a/src/web/html/style.css +++ b/src/web/html/style.css @@ -31,11 +31,11 @@ h2 { } .topnav a.icon { + top: 0; + left: 0; background: #333; display: block; position: absolute; - left: 0; - top: 0; } .topnav a:hover { @@ -43,6 +43,20 @@ h2 { color: #000; } +.topnav .info { + color: #fff; + position: absolute; + right: 24px; + top: 5px; +} + +svg.icon { + vertical-align: middle; + display: inline-block; + margin-top:-4x; + padding: 5px 7px 5px 0px; +} + .title { background-color: #006ec0; color: #fff !important; @@ -142,6 +156,13 @@ span.seperator { display: block; } + .topnav .info { + top: auto !important; + right: auto !important; + bottom: 14px; + left: 24px; + } + #content { padding: 15px 15px 120px 250px; } @@ -376,11 +397,16 @@ div.ModPwr, div.ModName { display: inline-block; } +div.hr { + height: 1px; + border-top: 1px solid #ccc; + margin: 10px 0px 10px; +} + #note { - margin: 50px 10px 10px 10px; + margin: 10px 10px 10px 10px; padding-top: 10px; width: 100%; - border-top: 1px solid #bbb; } @media(max-width: 500px) { @@ -477,6 +503,12 @@ div.ModPwr, div.ModName { .mt-4 { margin-top: 1.5rem } .mt-5 { margin-top: 3rem } +.mb-1 { margin-bottom: 0.25rem } +.mb-2 { margin-bottom: 0.5rem } +.mb-3 { margin-bottom: 1rem } +.mb-4 { margin-bottom: 1.5rem } +.mb-5 { margin-bottom: 3rem } + .a-r { text-align: right; } .a-c { text-align: center; } diff --git a/src/web/html/system.html b/src/web/html/system.html index 7303bd0a..12d48a8f 100644 --- a/src/web/html/system.html +++ b/src/web/html/system.html @@ -15,12 +15,15 @@
            +
            +
            
                             
            -
            +
            +
            From 4f962ff962ff66719cee77496a2b220f1f344ba5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 27 Dec 2022 23:27:53 +0100 Subject: [PATCH 171/431] potential fix of #526 duplicates in API `/api/record/live` --- src/CHANGES.md | 1 + src/web/RestApi.h | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index ef486e39..72abd30b 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -3,6 +3,7 @@ ## 0.5.63 * fix Update button protection (prevent double click #527) * optimized scheduler #515 (thx @beegee3) +* potential fix of #526 duplicates in API `/api/record/live` ## 0.5.62 * fix MQTT `status` update diff --git a/src/web/RestApi.h b/src/web/RestApi.h index b9483dc1..f1349057 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -69,10 +69,10 @@ class RestApi { else if(path == "setup") getSetup(root); else if(path == "setup/networks") getNetworks(root); else if(path == "live") getLive(root); - else if(path == "record/info") getRecord(root, iv->getRecordStruct(InverterDevInform_All)); - else if(path == "record/alarm") getRecord(root, iv->getRecordStruct(AlarmData)); - else if(path == "record/config") getRecord(root, iv->getRecordStruct(SystemConfigPara)); - else if(path == "record/live") getRecord(root, iv->getRecordStruct(RealTimeRunData_Debug)); + else if(path == "record/info") getRecord(root, InverterDevInform_All); + else if(path == "record/alarm") getRecord(root, AlarmData); + else if(path == "record/config") getRecord(root, SystemConfigPara); + else if(path == "record/live") getRecord(root, RealTimeRunData_Debug); else getNotFound(root, F("http://") + request->host() + F("/api/")); @@ -484,14 +484,16 @@ class RestApi { } } - void getRecord(JsonObject obj, record_t<> *rec) { + void getRecord(JsonObject obj, uint8_t recType) { JsonArray invArr = obj.createNestedArray(F("inverter")); Inverter<> *iv; + record_t<> *rec; uint8_t pos; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { iv = mSys->getInverterByPos(i); if(NULL != iv) { + rec = iv->getRecordStruct(recType); JsonArray obj2 = invArr.createNestedArray(); for(uint8_t j = 0; j < rec->length; j++) { byteAssign_t *assign = iv->getByteAssign(j, rec); From 75628ad230226c6ba9a104db9fa5ce726444dbdd Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 28 Dec 2022 00:08:18 +0100 Subject: [PATCH 172/431] added update information to `index.html` --- src/CHANGES.md | 1 + src/web/RestApi.h | 1 - src/web/html/index.html | 24 ++++++++++++++++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 72abd30b..1bd20103 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -4,6 +4,7 @@ * fix Update button protection (prevent double click #527) * optimized scheduler #515 (thx @beegee3) * potential fix of #526 duplicates in API `/api/record/live` +* added update information to `index.html` ## 0.5.62 * fix MQTT `status` update diff --git a/src/web/RestApi.h b/src/web/RestApi.h index f1349057..f1fca182 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -54,7 +54,6 @@ class RestApi { AsyncJsonResponse* response = new AsyncJsonResponse(false, 8192); JsonObject root = response->getRoot(); - Inverter<> *iv = mSys->getInverterByPos(0, false); String path = request->url().substring(5); if(path == "html/system") getHtmlSystem(root); else if(path == "html/logout") getHtmlLogout(root); diff --git a/src/web/html/index.html b/src/web/html/index.html index e702312b..0cd7f430 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -81,6 +81,7 @@ var tickCnt = 0; var ts = 0; var commInfo = ""; + var release = null; function apiCb(obj) { var e = document.getElementById("apiResult"); @@ -198,7 +199,7 @@ document.getElementById("iv").replaceChildren(p); } - function parseWarnInfo(warn, success) { + function parseWarnInfo(warn, success, version) { var p = div(["none"]); for(var w of warn) { p.append(svg(iconWarn, 20, 20, "#F70", "icon"), span(w), br()); @@ -209,6 +210,14 @@ if(commInfo.length > 0) p.append(svg(iconInfo, 20, 20, "#00d", "icon"), span(commInfo), br()); + + if(null != release) { + if(getVerInt(version) < getVerInt(release)) + p.append(svg(iconInfo, 20, 20, "#00d", "icon"), span("Update available, current released version: " + release), br()); + else if(getVerInt(version) > getVerInt(release)) + p.append(svg(iconInfo, 20, 20, "#00d", "icon"), span("You are using a development version, current released version: " + release), br()); + } + document.getElementById("warn_info").replaceChildren(p); } @@ -228,14 +237,25 @@ parseGeneric(obj["generic"]); parseSys(obj); parseIv(obj["inverter"]); - parseWarnInfo(obj["warnings"], obj["infos"]); + parseWarnInfo(obj["warnings"], obj["infos"], obj["generic"]["version"]); if(exeOnce) { window.setInterval("tick()", 1000); exeOnce = false; + getAjax("https://api.github.com/repos/lumapu/ahoy/releases/latest", parseRelease); } } } + + function getVerInt(ver) { + var a = ver.split('.'); + return (a[0] << 24) | (a[1] << 16) | a[2]; + } + + function parseRelease(obj) { + release = obj["name"].substring(6); + } + getAjax("/api/index", parse); From 73b6ff073cd8bb29509111d5c2a078d3d9ec0896 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 28 Dec 2022 23:38:33 +0100 Subject: [PATCH 173/431] channel name can use any character, not limited any more added `/` to MQTT topic and Inverter name trigger for `calcSunrise` is now using local time #515 fix reconnect timeout for WiFi #509 start AP only after boot, not on WiFi connection loss improved /system `free_heap` value (measured before JSON-tree is built) --- src/CHANGES.md | 8 ++++++++ src/app.cpp | 2 +- src/app.h | 2 +- src/defines.h | 2 +- src/web/RestApi.h | 6 +++++- src/web/html/setup.html | 6 +++--- src/wifi/ahoywifi.cpp | 21 ++++++++++----------- src/wifi/ahoywifi.h | 2 +- 8 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 1bd20103..f005f468 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,13 @@ # Changelog +## 0.5.64 +* channel name can use any character, not limited any more +* added `/` to MQTT topic and Inverter name +* trigger for `calcSunrise` is now using local time #515 +* fix reconnect timeout for WiFi #509 +* start AP only after boot, not on WiFi connection loss +* improved /system `free_heap` value (measured before JSON-tree is built) + ## 0.5.63 * fix Update button protection (prevent double click #527) * optimized scheduler #515 (thx @beegee3) diff --git a/src/app.cpp b/src/app.cpp index 2d3d1769..29df1e64 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -141,7 +141,7 @@ void app::tickCalcSunrise(void) { ah::calculateSunriseSunset(mTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset); tickIVCommunication(); - uint32_t nxtTrig = mTimestamp - ((mTimestamp - 10) % 86400) + 86400; // next midnight, -10 for safety that it is certain next day + uint32_t nxtTrig = mTimestamp - ((mTimestamp + mCalculatedTimezoneOffset - 10) % 86400) + 86400;; // next midnight, -10 for safety that it is certain next day, local timezone onceAt(std::bind(&app::tickCalcSunrise, this), nxtTrig); if (mConfig->mqtt.broker[0] > 0) { mMqtt.tickerSun(mSunrise, mSunset, mConfig->sun.offsetSec, mConfig->sun.disNightCom); diff --git a/src/app.h b/src/app.h index ca5b29e2..54dca314 100644 --- a/src/app.h +++ b/src/app.h @@ -156,7 +156,7 @@ class app : public IApp, public ah::Scheduler { } void getSchedulerInfo(uint8_t *max) { - return getStat(max); + getStat(max); } void setTimestamp(uint32_t newTime) { diff --git a/src/defines.h b/src/defines.h index 473d6724..fbc089b2 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 63 +#define VERSION_PATCH 64 //------------------------------------- typedef struct { diff --git a/src/web/RestApi.h b/src/web/RestApi.h index f1fca182..8ad55e26 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -19,6 +19,7 @@ class RestApi { public: RestApi() { mTimezoneOffset = 0; + mFreeHeap = 0; } void setup(IApp *app, HMSYSTEM *sys, AsyncWebServer *srv, settings_t *config) { @@ -51,6 +52,8 @@ class RestApi { private: void onApi(AsyncWebServerRequest *request) { + mFreeHeap = ESP.getFreeHeap(); + AsyncJsonResponse* response = new AsyncJsonResponse(false, 8192); JsonObject root = response->getRoot(); @@ -168,7 +171,7 @@ class RestApi { obj[F("sdk")] = ESP.getSdkVersion(); obj[F("cpu_freq")] = ESP.getCpuFreqMHz(); - obj[F("heap_free")] = ESP.getFreeHeap(); + obj[F("heap_free")] = mFreeHeap; obj[F("sketch_total")] = ESP.getFreeSketchSpace(); obj[F("sketch_used")] = ESP.getSketchSize() / 1024; // in kb getGeneric(obj); @@ -571,6 +574,7 @@ class RestApi { settings_t *mConfig; uint32_t mTimezoneOffset; + uint32_t mFreeHeap; }; #endif /*__WEB_API_H__*/ diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 3574a8f6..cf57f12b 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -147,7 +147,7 @@ - + @@ -320,10 +320,10 @@ iv.append( lbl(id + "Name", "Name*"), - inp(id + "Name", obj["name"], 32, ["text"], null, "text", "[A-Za-z0-9.\\-_\\+]+", "Invalid input") + inp(id + "Name", obj["name"], 32, ["text"], null, "text", "[A-Za-z0-9.\\-_\\+\\/]+", "Invalid input") ); - for(var j of [["ModPwr", "ch_max_power", "Max Module Power (Wp)", 4, "[0-9]+"], ["ModName", "ch_name", "Module Name", 16, "[A-Za-z0-9.\\-_\\+]+"]]) { + for(var j of [["ModPwr", "ch_max_power", "Max Module Power (Wp)", 4, "[0-9]+"], ["ModName", "ch_name", "Module Name", 16, null]]) { var cl = (re.test(obj["serial"])) ? null : ["hide"]; iv.appendChild(lbl(null, j[2], cl, "lbl" + id + j[0])); d = div([j[0]]); diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index f884b1a3..95eaf432 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -35,15 +35,17 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp) { WiFi.onEvent(std::bind(&ahoywifi::onWiFiEvent, this, std::placeholders::_1)); #endif - setupWifi(); + setupWifi(true); } //----------------------------------------------------------------------------- -void ahoywifi::setupWifi(void) { +void ahoywifi::setupWifi(bool startAP = false) { #if !defined(FB_WIFI_OVERRIDDEN) - setupAp(); - delay(1000); + if(startAP) { + setupAp(); + delay(1000); + } #endif #if !defined(AP_ONLY) if(mConfig->valid) { @@ -62,7 +64,6 @@ void ahoywifi::setupWifi(void) { void ahoywifi::tickWifiLoop() { #if !defined(AP_ONLY) if(mReconnect) { - delay(100); if (WiFi.softAPgetStationNum() > 0) { // do not reconnect if any AP connection exists mDns.processNextRequest(); if((WIFI_AP_STA == WiFi.getMode()) && !mScanActive) { @@ -78,12 +79,10 @@ void ahoywifi::tickWifiLoop() { } mCnt++; - if ((mCnt % 10) == 0) { - DBGPRINT(F("reconnect in ")); - DBGPRINT(String((100-mCnt)/10)); - DBGPRINTLN(F(" seconds")); - } - if((mCnt % 100) == 0) { // try to reconnect after 10 sec without connection + DBGPRINT(F("reconnect in ")); + DBGPRINT(String((100-mCnt)/10)); + DBGPRINTLN(F(" seconds")); + if((mCnt % 10) == 0) { // try to reconnect after 10 sec without connection WiFi.reconnect(); mCnt = 0; } diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index a84ba647..5b3b801c 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -27,7 +27,7 @@ class ahoywifi { void getAvailNetworks(JsonObject obj); private: - void setupWifi(void); + void setupWifi(bool startAP); void setupAp(void); void setupStation(void); void sendNTPpacket(IPAddress& address); From 52423e679fc4a367096171073fda55f150d7a3df Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 30 Dec 2022 22:26:37 +0100 Subject: [PATCH 174/431] wifi, code optimization #509 --- src/CHANGES.md | 3 ++ src/defines.h | 2 +- src/wifi/ahoywifi.cpp | 79 ++++++++++++++++++++++++++----------------- src/wifi/ahoywifi.h | 14 ++++++-- 4 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index f005f468..cce8144f 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Changelog +## 0.5.65 +* wifi, code optimization #509 + ## 0.5.64 * channel name can use any character, not limited any more * added `/` to MQTT topic and Inverter name diff --git a/src/defines.h b/src/defines.h index fbc089b2..2a04999f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 64 +#define VERSION_PATCH 65 //------------------------------------- typedef struct { diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 95eaf432..5214fe01 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -22,9 +22,8 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp) { mConfig = config; mUtcTimestamp = utcTimestamp; + mStaConn = DISCONNECTED; mCnt = 0; - mConnected = false; - mReconnect = false; mScanActive = false; #if defined(ESP8266) @@ -63,7 +62,7 @@ void ahoywifi::setupWifi(bool startAP = false) { //----------------------------------------------------------------------------- void ahoywifi::tickWifiLoop() { #if !defined(AP_ONLY) - if(mReconnect) { + if(mStaConn != GOT_IP) { if (WiFi.softAPgetStationNum() > 0) { // do not reconnect if any AP connection exists mDns.processNextRequest(); if((WIFI_AP_STA == WiFi.getMode()) && !mScanActive) { @@ -79,10 +78,17 @@ void ahoywifi::tickWifiLoop() { } mCnt++; + uint8_t timeout = 10; // seconds + + if (mStaConn == CONNECTED) // connected but no ip + timeout = 20; + DBGPRINT(F("reconnect in ")); - DBGPRINT(String((100-mCnt)/10)); + DBGPRINT(String(timeout-mCnt)); DBGPRINTLN(F(" seconds")); - if((mCnt % 10) == 0) { // try to reconnect after 10 sec without connection + if((mCnt % timeout) == 0) { // try to reconnect after x sec without connection + if(mStaConn != CONNECTED) + mStaConn = CONNECTING; WiFi.reconnect(); mCnt = 0; } @@ -128,11 +134,12 @@ void ahoywifi::setupStation(void) { if(!WiFi.config(ip, gateway, mask, dns1, dns2)) DPRINTLN(DBG_ERROR, F("failed to set static IP!")); } - mReconnect = (WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd) != WL_CONNECTED); + mStaConn = (WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd) != WL_CONNECTED) ? DISCONNECTED : CONNECTED; if(String(mConfig->sys.deviceName) != "") WiFi.hostname(mConfig->sys.deviceName); WiFi.mode(WIFI_AP_STA); + DBGPRINT(F("connect to network '")); DBGPRINT(mConfig->sys.stationSsid); DBGPRINTLN(F("' ...")); @@ -141,7 +148,7 @@ void ahoywifi::setupStation(void) { //----------------------------------------------------------------------------- bool ahoywifi::getNtpTime(void) { - if(!mConnected) + if(CONNECTED != mStaConn) return false; IPAddress timeServer; @@ -234,24 +241,34 @@ void ahoywifi::getAvailNetworks(JsonObject obj) { //----------------------------------------------------------------------------- -void ahoywifi::connectionEvent(bool connected) { - if (connected) { - if(!mConnected) { - mConnected = true; - mReconnect = false; - DBGPRINTLN(F("\n[WiFi] Connected")); - WiFi.mode(WIFI_STA); - DBGPRINTLN(F("[WiFi] AP disabled")); - mDns.stop(); - } - } else { - if(mConnected) { - mConnected = false; - mReconnect = true; - mCnt = 50; // try to reconnect in 5 sec - setupWifi(); // reconnect with AP / Station setup - DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); - } +void ahoywifi::connectionEvent(WiFiStatus_t status) { + switch(status) { + case CONNECTED: + if(mStaConn != CONNECTED) { + mStaConn = CONNECTED; + DBGPRINTLN(F("\n[WiFi] Connected")); + WiFi.mode(WIFI_STA); + DBGPRINTLN(F("[WiFi] AP disabled")); + mDns.stop(); + } + break; + + case GOT_IP: + mStaConn = GOT_IP; + welcome(WiFi.localIP().toString() + F(" (Station)")); + break; + + case DISCONNECTED: + if(mStaConn != CONNECTING) { + mStaConn = DISCONNECTED; + mCnt = 5; // try to reconnect in 5 sec + setupWifi(); // reconnect with AP / Station setup + DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); + } + break; + + default: + break; } } @@ -260,17 +277,17 @@ void ahoywifi::connectionEvent(bool connected) { #if defined(ESP8266) //------------------------------------------------------------------------- void ahoywifi::onConnect(const WiFiEventStationModeConnected& event) { - connectionEvent(true); + connectionEvent(CONNECTED); } //------------------------------------------------------------------------- void ahoywifi::onGotIP(const WiFiEventStationModeGotIP& event) { - welcome(WiFi.localIP().toString() + F(" (Station)")); + connectionEvent(GOT_IP); } //------------------------------------------------------------------------- void ahoywifi::onDisconnect(const WiFiEventStationModeDisconnected& event) { - connectionEvent(false); + connectionEvent(DISCONNECTED); } #else @@ -281,15 +298,15 @@ void ahoywifi::connectionEvent(bool connected) { switch(event) { case SYSTEM_EVENT_STA_CONNECTED: - connectionEvent(true); + connectionEvent(CONNECTED); break; case SYSTEM_EVENT_STA_GOT_IP: - welcome(WiFi.localIP().toString() + F(" (Station)")); + connectionEvent(GOT_IP); break; case SYSTEM_EVENT_STA_DISCONNECTED: - connectionEvent(false); + connectionEvent(DISCONNECTED); break; default: diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 5b3b801c..6eca48e2 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -27,11 +27,19 @@ class ahoywifi { void getAvailNetworks(JsonObject obj); private: + typedef enum WiFiStatus + { + DISCONNECTED = 0, + CONNECTING, + CONNECTED, + GOT_IP + } WiFiStatus_t; + void setupWifi(bool startAP); void setupAp(void); void setupStation(void); void sendNTPpacket(IPAddress& address); - void connectionEvent(bool connected); + void connectionEvent(WiFiStatus_t status); #if defined(ESP8266) void onConnect(const WiFiEventStationModeConnected& event); void onGotIP(const WiFiEventStationModeGotIP& event); @@ -51,8 +59,8 @@ class ahoywifi { WiFiEventHandler wifiConnectHandler, wifiDisconnectHandler, wifiGotIPHandler; #endif - bool mConnected, mReconnect, mDnsActive; - uint8_t mCnt, mClientCnt; + WiFiStatus_t mStaConn; + uint8_t mCnt; uint32_t *mUtcTimestamp; uint8_t mLoopCnt; From 8225a18292bb049e18f7bacb687b80a778be6955 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 30 Dec 2022 22:41:26 +0100 Subject: [PATCH 175/431] Release 0.5.65 --- src/CHANGES.md | 150 +++++++------------------------------------------ 1 file changed, 19 insertions(+), 131 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index cce8144f..ed53be33 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,148 +1,36 @@ -# Changelog +# Changelog v0.5.65 -## 0.5.65 -* wifi, code optimization #509 +**Note:** Version `0.5.42` to `0.5.64` were development versions. Last release version before this release was `0.5.41` +Detailed change log (development changes): https://github.com/lumapu/ahoy/blob/945a671d27d10d0f7c175ebbf2fbb2806f9cd79a/src/CHANGES.md -## 0.5.64 -* channel name can use any character, not limited any more -* added `/` to MQTT topic and Inverter name -* trigger for `calcSunrise` is now using local time #515 -* fix reconnect timeout for WiFi #509 -* start AP only after boot, not on WiFi connection loss -* improved /system `free_heap` value (measured before JSON-tree is built) -## 0.5.63 +* updated REST API and MQTT (both of them use the same functionality) +* improved stability +* Regular expressions for input fields which are used for MQTT to be compliant to MQTT +* WiFi optimization (AP Mode and STA in parallel, reconnect if local STA is unavailable) +* improved display of `/system` * fix Update button protection (prevent double click #527) -* optimized scheduler #515 (thx @beegee3) -* potential fix of #526 duplicates in API `/api/record/live` -* added update information to `index.html` - -## 0.5.62 -* fix MQTT `status` update +* optimized scheduler #515 +* fix of duplicates in API `/api/record/live` (#526) +* added update information to `index.html` (check for update with github.com) +* fix web logout (auto logout) +* switched MQTT library * removed MQTT `available_text` (can be deducted from `available`) * enhanced MQTT documentation in `User_Manual.md` -* remvoed `tickSunset` and `tickSunrise` from MQTT. It's not needed any more because of minute wise check of status (`processIvStatus`) * changed MQTT topic `status` to nummeric value, check documentation in `User_Manual.md` -* fix regular expression of `setup.html` for inverter name and channel name - -## 0.5.61 -* fix #521 no reconnect at beginning of day * added immediate (each minute) report of inverter status MQTT #522 -* added protection mask to select which pages should be protected -* update of monochrome display, show values also if nothing changed - -## 0.5.60 -* added regex to inverter name and MQTT topic (setup.html) -* beautified serial.html -* added ticker for wifi loop #515 - -## 0.5.59 -* fix night communication enable -* improved different WiFi connection scenarios (STA WiFi not found, reconnect #509, redirect for AP to configuration) * increased MQTT user, pwd and topic length to 64 characters + `\0`. (The string end `\0` reduces the available size by one) #516 - -## 0.5.58 -* improved stability -* improved WiFi initial connection - especially if station WiFi is not available -* removed new operators from web.h (reduce dynamic allocation) -* improved sun calculation #515, #505 -* fixed WiFi auto reconnect #509 * added disable night communication flag to MQTT #505 -* changed MQTT publish of `available` and `available_text` to sunset #468 - -## 0.5.57 -* improved stability +* added MQTT /status to show status over all inverters +* added MQTT RX counter to index.html +* added protection mask to select which pages should be protected +* added monochrome display that show values also if nothing changed and in offline mode #498 * added icons to index.html, added WiFi-strength symbol on each page -* moved packet stats and sun to system.html * refactored communication offset (adjustable in minutes now) - -## 0.5.56 * factory reset formats entire little fs * renamed sunrise / sunset on index.html to start / stop communication -* show system information only if called directly from menu -* beautified system.html - -## 0.5.55 * fixed static IP save - -## 0.5.54 -* changed sunrise / sunset calculation, angle is now `-3.5` instead of original `-0.83` -* improved scheduler (removed -1 from `reload`) #483 -* improved reboot flag in `app.h` -* fixed #493 no MQTT payload once display is defined - -## 0.5.53 -* Mono-Display: show values in offline mode #498 -* improved WiFi class #483 -* added communication enable / disable (to test mutliple DTUs with the same inverter) -* fix factory reset #495 - -## 0.5.52 -* improved ahoyWifi class -* added interface class for app -* refactored web and webApi -> RestApi -* fix calcSunrise was not called every day -* added MQTT RX counter to index.html +* fix NTP with static IP * all values are displayed on /live even if they are 0 -* added MQTT /status to show status over all inverters - -## 0.5.51 -* improved scheduler, @beegee3 #483 -* refactored get NTP time, @beegee3 #483 -* generate `bin.gz` only for 1M device ESP8285 -* fix calcSunrise was not called every day -* incresed number of allowed characters for MQTT user, broker and password, @DanielR92 -* added NRF24 info to Systeminfo, @DanielR92 -* added timezone for monochrome displays, @gh-fx2 -* added support for second inverter for monochrome displays, @gh-fx2 - -## 0.5.50 -* fixed scheduler, uptime and timestamp counted too fast -* added / renamed automatically build outputs -* fixed MQTT ESP uptime on reconnect (not zero any more) -* changed uptime on index.html to count each second, synced with ESP each 10 seconds - -## 0.5.49 -* fixed AP mode on brand new ESP modules -* fixed `last_success` MQTT message -* fixed MQTT inverter available status at sunset +* added NRF24 info to Systeminfo * reordered enqueue commands after boot up to prevent same payload length for successive commands -* added automatic build for Nokia5110 and SSD1306 displays (ESP8266) - -## 0.5.48 -* added MQTT message send at sunset -* added monochrome display support -* added `once` and `onceAt` to scheduler to make code cleaner -* improved sunrise / sunset calculation - -## 0.5.47 -* refactored ahoyWifi class: AP is opened on every boot, once station connection is successful the AP will be closed -* improved NTP sync after boot, faster sync -* fix NRF24 details only on valid SPI connection - -## 0.5.46 -* fix sunrise / sunset calculation -* improved setup.html: `reboot on save` is checked as default - -## 0.5.45 -* changed MQTT last will topic from `status` to `mqtt` -* fix sunrise / sunset calculation -* fix time of serial web console - -## 0.5.44 -* marked some MQTT messages as retained -* moved global functions to global location (no duplicates) -* changed index.html inverval to static 10 seconds -* fix static IP -* fix NTP with static IP -* print MQTT info only if MQTT was configured - -## 0.5.43 -* updated REST API and MQTT (both of them use the same functionality) -* added ESP-heap information as MQTT message -* changed output name of automatic development build to fixed name (to have a static link from https://ahoydtu.de) -* updated user manual to latest MQTT and API changes - -## 0.5.42 -* fix web logout (auto logout) -* switched MQTT library From ded5e70d790ba42dc2a1f7a69a321e8b606ce773 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 30 Dec 2022 22:44:38 +0100 Subject: [PATCH 176/431] Release 0.5.65 --- .github/workflows/compile_release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile_release.yml b/.github/workflows/compile_release.yml index 556f7b7d..20fcef87 100644 --- a/.github/workflows/compile_release.yml +++ b/.github/workflows/compile_release.yml @@ -51,7 +51,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 + run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 - name: Rename Binary files id: rename-binary-files From f8fe044e1be86e8f2730807fb0da79d97e880feb Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 30 Dec 2022 23:17:22 +0100 Subject: [PATCH 177/431] Release 0.5.66 (fix NTP sync) --- src/CHANGES.md | 4 ++-- src/defines.h | 2 +- src/wifi/ahoywifi.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index ed53be33..f8a2c5ca 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,6 +1,6 @@ -# Changelog v0.5.65 +# Changelog v0.5.66 -**Note:** Version `0.5.42` to `0.5.64` were development versions. Last release version before this release was `0.5.41` +**Note:** Version `0.5.42` to `0.5.65` were development versions. Last release version was `0.5.41` Detailed change log (development changes): https://github.com/lumapu/ahoy/blob/945a671d27d10d0f7c175ebbf2fbb2806f9cd79a/src/CHANGES.md diff --git a/src/defines.h b/src/defines.h index 2a04999f..ddfda35e 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 65 +#define VERSION_PATCH 66 //------------------------------------- typedef struct { diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 5214fe01..f9440183 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -148,7 +148,7 @@ void ahoywifi::setupStation(void) { //----------------------------------------------------------------------------- bool ahoywifi::getNtpTime(void) { - if(CONNECTED != mStaConn) + if(GOT_IP != mStaConn) return false; IPAddress timeServer; From 19e86ebdb28ac1756865223798021435e4541253 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 1 Jan 2023 23:37:13 +0100 Subject: [PATCH 178/431] changed calculation of start / stop communication to 1 min after last comm. stop #515 moved payload send to `payload.h`, function `ivSend` #515 --- src/CHANGES.md | 39 +++------------------ src/app.cpp | 63 ++++++++-------------------------- src/defines.h | 2 +- src/hm/payload.h | 89 ++++++++++++++++++++++++++++++------------------ 4 files changed, 76 insertions(+), 117 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index f8a2c5ca..e62f1333 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,36 +1,7 @@ -# Changelog v0.5.66 +# Changelog -**Note:** Version `0.5.42` to `0.5.65` were development versions. Last release version was `0.5.41` -Detailed change log (development changes): https://github.com/lumapu/ahoy/blob/945a671d27d10d0f7c175ebbf2fbb2806f9cd79a/src/CHANGES.md +(starting from release version `0.5.66`) - -* updated REST API and MQTT (both of them use the same functionality) -* improved stability -* Regular expressions for input fields which are used for MQTT to be compliant to MQTT -* WiFi optimization (AP Mode and STA in parallel, reconnect if local STA is unavailable) -* improved display of `/system` -* fix Update button protection (prevent double click #527) -* optimized scheduler #515 -* fix of duplicates in API `/api/record/live` (#526) -* added update information to `index.html` (check for update with github.com) -* fix web logout (auto logout) -* switched MQTT library -* removed MQTT `available_text` (can be deducted from `available`) -* enhanced MQTT documentation in `User_Manual.md` -* changed MQTT topic `status` to nummeric value, check documentation in `User_Manual.md` -* added immediate (each minute) report of inverter status MQTT #522 -* increased MQTT user, pwd and topic length to 64 characters + `\0`. (The string end `\0` reduces the available size by one) #516 -* added disable night communication flag to MQTT #505 -* added MQTT /status to show status over all inverters -* added MQTT RX counter to index.html -* added protection mask to select which pages should be protected -* added monochrome display that show values also if nothing changed and in offline mode #498 -* added icons to index.html, added WiFi-strength symbol on each page -* refactored communication offset (adjustable in minutes now) -* factory reset formats entire little fs -* renamed sunrise / sunset on index.html to start / stop communication -* fixed static IP save -* fix NTP with static IP -* all values are displayed on /live even if they are 0 -* added NRF24 info to Systeminfo -* reordered enqueue commands after boot up to prevent same payload length for successive commands +## 0.5.67 +* changed calculation of start / stop communication to 1 min after last comm. stop #515 +* moved payload send to `payload.h`, function `ivSend` #515 diff --git a/src/app.cpp b/src/app.cpp index 29df1e64..b0e310c4 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -51,7 +51,7 @@ void app::setup() { #endif mSys->addInverters(&mConfig->inst); - mPayload.setup(mSys); + mPayload.setup(mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); mPayload.enableSerialDebug(mConfig->serial.debug); if(!mSys->Radio.isChipConnected()) @@ -115,7 +115,9 @@ void app::loop(void) { yield(); if (rxRdy) - mPayload.process(true, mConfig->nrf.maxRetransPerPyld, &mStat); + mPayload.process(true); + + mRxTicker = 0; } #if !defined(AP_ONLY) @@ -138,14 +140,18 @@ void app::tickNtpUpdate(void) { //----------------------------------------------------------------------------- void app::tickCalcSunrise(void) { - ah::calculateSunriseSunset(mTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset); + if (mSunrise == 0) // on boot/reboot calc sun values for current time + ah::calculateSunriseSunset(mTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset); + + if (mTimestamp > (mSunset + mConfig->sun.offsetSec)) // current time is past communication stop, calc sun values for next day + ah::calculateSunriseSunset(mTimestamp + 86400, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset); + tickIVCommunication(); - uint32_t nxtTrig = mTimestamp - ((mTimestamp + mCalculatedTimezoneOffset - 10) % 86400) + 86400;; // next midnight, -10 for safety that it is certain next day, local timezone + uint32_t nxtTrig = mSunset + mConfig->sun.offsetSec + 60; // set next trigger to communication stop, +60 for safety that it is certain past communication stop onceAt(std::bind(&app::tickCalcSunrise, this), nxtTrig); - if (mConfig->mqtt.broker[0] > 0) { + if (mConfig->mqtt.broker[0] > 0) mMqtt.tickerSun(mSunrise, mSunset, mConfig->sun.offsetSec, mConfig->sun.disNightCom); - } } //----------------------------------------------------------------------------- @@ -187,49 +193,8 @@ void app::tickSend(void) { } while ((NULL == iv) && ((maxLoop--) > 0)); if (NULL != iv) { - if(iv->config->enabled) { - if (!mPayload.isComplete(iv)) - mPayload.process(false, mConfig->nrf.maxRetransPerPyld, &mStat); - - if (!mPayload.isComplete(iv)) { - if (0 == mPayload.getMaxPacketId(iv)) - mStat.rxFailNoAnser++; - else - mStat.rxFail++; - - iv->setQueuedCmdFinished(); // command failed - if (mConfig->serial.debug) - DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); - if (mConfig->serial.debug) { - DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") "); - DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload.getRetransmits(iv)) + ")"); - } - } - - mPayload.reset(iv, mTimestamp); - mPayload.request(iv); - - yield(); - if (mConfig->serial.debug) { - DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status())); - DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX)); - } - - if (iv->devControlRequest) { - if (mConfig->serial.debug) - DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0])); - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit); - mPayload.setTxCmd(iv, iv->devControlCmd); - iv->clearCmdQueue(); - iv->enqueCommand(SystemConfigPara); // read back power limit - } else { - uint8_t cmd = iv->getQueuedCmd(); - DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); - mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload.getTs(iv), iv->alarmMesIndex); - mPayload.setTxCmd(iv, cmd); - mRxTicker = 0; - } - } + if(iv->config->enabled) + mPayload.ivSend(iv); } } else { if (mConfig->serial.debug) diff --git a/src/defines.h b/src/defines.h index ddfda35e..301c9f17 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 66 +#define VERSION_PATCH 67 //------------------------------------- typedef struct { diff --git a/src/hm/payload.h b/src/hm/payload.h index ef69c4fe..9a23fbfe 100644 --- a/src/hm/payload.h +++ b/src/hm/payload.h @@ -34,45 +34,65 @@ class Payload : public Handler { public: Payload() : Handler() {} - void setup(HMSYSTEM *sys) { - mSys = sys; + void setup(HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { + mSys = sys; + mStat = stat; + mMaxRetrans = maxRetransmits; + mTimestamp = timestamp; memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t))); mLastPacketId = 0x00; - mSerialDebug = false; + mSerialDebug = false; } void enableSerialDebug(bool enable) { mSerialDebug = enable; } - bool isComplete(Inverter<> *iv) { - return mPayload[iv->id].complete; - } - - uint8_t getMaxPacketId(Inverter<> *iv) { - return mPayload[iv->id].maxPackId; - } - - uint8_t getRetransmits(Inverter<> *iv) { - return mPayload[iv->id].retransmits; + void notify(uint8_t val) { + for(typename std::list::iterator it = mList.begin(); it != mList.end(); ++it) { + (*it)(val); + } } - uint32_t getTs(Inverter<> *iv) { - return mPayload[iv->id].ts; - } + void ivSend(Inverter<> *iv) { + if (!mPayload[iv->id].complete) + process(false); - void request(Inverter<> *iv) { - mPayload[iv->id].requested = true; - } + if (!mPayload[iv->id].complete) { + if (0 == mPayload[iv->id].maxPackId) + mStat->rxFailNoAnser++; + else + mStat->rxFail++; + + iv->setQueuedCmdFinished(); // command failed + if (mSerialDebug) + DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); + if (mSerialDebug) { + DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") "); + DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload[iv->id].retransmits) + ")"); + } + } - void setTxCmd(Inverter<> *iv, uint8_t cmd) { - mPayload[iv->id].txCmd = cmd; - } + reset(iv); + mPayload[iv->id].requested = true; - void notify(uint8_t val) { - for(typename std::list::iterator it = mList.begin(); it != mList.end(); ++it) { - (*it)(val); - } + yield(); + if (mSerialDebug) + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX)); + + if (iv->devControlRequest) { + if (mSerialDebug) + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0])); + mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit); + mPayload[iv->id].txCmd = iv->devControlCmd; + iv->clearCmdQueue(); + iv->enqueCommand(SystemConfigPara); // read back power limit + } else { + uint8_t cmd = iv->getQueuedCmd(); + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); + mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex); + mPayload[iv->id].txCmd = cmd; + } } void add(packet_t *p, uint8_t len) { @@ -134,7 +154,7 @@ class Payload : public Handler { return (crc == crcRcv) ? true : false; } - void process(bool retransmit, uint8_t maxRetransmits, statistics_t *stat) { + void process(bool retransmit) { for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); if (NULL == iv) @@ -152,9 +172,9 @@ class Payload : public Handler { if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) { // This is required to prevent retransmissions without answer. DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm...")); - mPayload[iv->id].retransmits = maxRetransmits; + mPayload[iv->id].retransmits = mMaxRetrans; } else { - if (mPayload[iv->id].retransmits < maxRetransmits) { + if (mPayload[iv->id].retransmits < mMaxRetrans) { mPayload[iv->id].retransmits++; if (mPayload[iv->id].maxPackId != 0) { for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { @@ -207,7 +227,7 @@ class Payload : public Handler { DPRINTLN(DBG_ERROR, F("record is NULL!")); } else if ((rec->pyldLen == payloadLen) || (0 == rec->pyldLen)) { if (mPayload[iv->id].txId == (TX_REQ_INFO + 0x80)) - stat->rxSuccess++; + mStat->rxSuccess++; rec->ts = mPayload[iv->id].ts; for (uint8_t i = 0; i < rec->length; i++) { @@ -218,7 +238,7 @@ class Payload : public Handler { notify(mPayload[iv->id].txCmd); } else { DPRINTLN(DBG_ERROR, F("plausibility check failed, expected ") + String(rec->pyldLen) + F(" bytes")); - stat->rxFail++; + mStat->rxFail++; } iv->setQueuedCmdFinished(); @@ -230,7 +250,7 @@ class Payload : public Handler { } } - void reset(Inverter<> *iv, uint32_t utcTs) { + void reset(Inverter<> *iv) { DPRINTLN(DBG_INFO, "resetPayload: id: " + String(iv->id)); memset(mPayload[iv->id].len, 0, MAX_PAYLOAD_ENTRIES); mPayload[iv->id].txCmd = 0; @@ -238,11 +258,14 @@ class Payload : public Handler { mPayload[iv->id].maxPackId = 0; mPayload[iv->id].complete = false; mPayload[iv->id].requested = false; - mPayload[iv->id].ts = utcTs; + mPayload[iv->id].ts = *mTimestamp; } private: HMSYSTEM *mSys; + statistics_t *mStat; + uint8_t mMaxRetrans; + uint32_t *mTimestamp; invPayload_t mPayload[MAX_NUM_INVERTERS]; uint8_t mLastPacketId; bool mSerialDebug; From 2f19e70852463219635a8f92e6ee1f2e0217eed0 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 1 Jan 2023 23:49:31 +0100 Subject: [PATCH 179/431] payload: if last frame is missing, request all frames again --- src/CHANGES.md | 1 + src/hm/payload.h | 88 +++++++++++++++++++++++------------------------- 2 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index e62f1333..0ba677a3 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -5,3 +5,4 @@ ## 0.5.67 * changed calculation of start / stop communication to 1 min after last comm. stop #515 * moved payload send to `payload.h`, function `ivSend` #515 +* payload: if last frame is missing, request all frames again diff --git a/src/hm/payload.h b/src/hm/payload.h index 9a23fbfe..bc8b4949 100644 --- a/src/hm/payload.h +++ b/src/hm/payload.h @@ -21,6 +21,7 @@ typedef struct { uint8_t len[MAX_PAYLOAD_ENTRIES]; bool complete; uint8_t maxPackId; + bool lastFound; uint8_t retransmits; bool requested; } invPayload_t; @@ -56,43 +57,43 @@ class Payload : public Handler { void ivSend(Inverter<> *iv) { if (!mPayload[iv->id].complete) - process(false); + process(false); - if (!mPayload[iv->id].complete) { - if (0 == mPayload[iv->id].maxPackId) - mStat->rxFailNoAnser++; - else - mStat->rxFail++; - - iv->setQueuedCmdFinished(); // command failed - if (mSerialDebug) - DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); - if (mSerialDebug) { - DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") "); - DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload[iv->id].retransmits) + ")"); - } + if (!mPayload[iv->id].complete) { + if (0 == mPayload[iv->id].maxPackId) + mStat->rxFailNoAnser++; + else + mStat->rxFail++; + + iv->setQueuedCmdFinished(); // command failed + if (mSerialDebug) + DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); + if (mSerialDebug) { + DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") "); + DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload[iv->id].retransmits) + ")"); } + } - reset(iv); - mPayload[iv->id].requested = true; + reset(iv); + mPayload[iv->id].requested = true; - yield(); + yield(); + if (mSerialDebug) + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX)); + + if (iv->devControlRequest) { if (mSerialDebug) - DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX)); - - if (iv->devControlRequest) { - if (mSerialDebug) - DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0])); - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit); - mPayload[iv->id].txCmd = iv->devControlCmd; - iv->clearCmdQueue(); - iv->enqueCommand(SystemConfigPara); // read back power limit - } else { - uint8_t cmd = iv->getQueuedCmd(); - DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); - mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex); - mPayload[iv->id].txCmd = cmd; - } + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0])); + mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit); + mPayload[iv->id].txCmd = iv->devControlCmd; + iv->clearCmdQueue(); + iv->enqueCommand(SystemConfigPara); // read back power limit + } else { + uint8_t cmd = iv->getQueuedCmd(); + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); + mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex); + mPayload[iv->id].txCmd = cmd; + } } void add(packet_t *p, uint8_t len) { @@ -115,7 +116,7 @@ class Payload : public Handler { if ((*pid & 0x7f) > mPayload[iv->id].maxPackId) { mPayload[iv->id].maxPackId = (*pid & 0x7f); if (*pid > 0x81) - mLastPacketId = *pid; + mPayload[iv->id].lastFound = true; } } } @@ -162,7 +163,6 @@ class Payload : public Handler { if ((mPayload[iv->id].txId != (TX_REQ_INFO + ALL_FRAMES)) && (0 != mPayload[iv->id].txId)) { // no processing needed if txId is not 0x95 - // DPRINTLN(DBG_INFO, F("processPayload - set complete, txId: ") + String(mPayload[iv->id].txId, HEX)); mPayload[iv->id].complete = true; } @@ -176,24 +176,20 @@ class Payload : public Handler { } else { if (mPayload[iv->id].retransmits < mMaxRetrans) { mPayload[iv->id].retransmits++; - if (mPayload[iv->id].maxPackId != 0) { + if(false == mPayload[iv->id].lastFound) { + DPRINTLN(DBG_WARN, F("while retrieving data: last frame missing: Request Complete Retransmit")); + mPayload[iv->id].txCmd = iv->getQueuedCmd(); + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); + mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex); + } else if (mPayload[iv->id].maxPackId != 0) { for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { if (mPayload[iv->id].len[i] == 0) { DPRINTLN(DBG_WARN, F("while retrieving data: Frame ") + String(i + 1) + F(" missing: Request Retransmit")); mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); - break; // only retransmit one frame per loop + break; // only request retransmit one frame per loop } yield(); } - } else { - DPRINTLN(DBG_WARN, F("while retrieving data: last frame missing: Request Retransmit")); - if (0x00 != mLastPacketId) - mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, mLastPacketId, true); - else { - mPayload[iv->id].txCmd = iv->getQueuedCmd(); - DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); - mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex); - } } mSys->Radio.switchRxCh(100); } @@ -256,6 +252,7 @@ class Payload : public Handler { mPayload[iv->id].txCmd = 0; mPayload[iv->id].retransmits = 0; mPayload[iv->id].maxPackId = 0; + mPayload[iv->id].lastFound = false; mPayload[iv->id].complete = false; mPayload[iv->id].requested = false; mPayload[iv->id].ts = *mTimestamp; @@ -267,7 +264,6 @@ class Payload : public Handler { uint8_t mMaxRetrans; uint32_t *mTimestamp; invPayload_t mPayload[MAX_NUM_INVERTERS]; - uint8_t mLastPacketId; bool mSerialDebug; }; From 4a00f90e3481c0e6e607dde8030414b5def3f95d Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 1 Jan 2023 23:57:02 +0100 Subject: [PATCH 180/431] fix compile --- src/hm/payload.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hm/payload.h b/src/hm/payload.h index bc8b4949..2a37be32 100644 --- a/src/hm/payload.h +++ b/src/hm/payload.h @@ -41,7 +41,6 @@ class Payload : public Handler { mMaxRetrans = maxRetransmits; mTimestamp = timestamp; memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t))); - mLastPacketId = 0x00; mSerialDebug = false; } From 27b3a9cd87b195109c7b2b5f7e22103213e2c46e Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 2 Jan 2023 12:26:03 +0100 Subject: [PATCH 181/431] Powerlimit is transfered immediately to inverter --- src/CHANGES.md | 4 ++++ src/app.cpp | 3 +-- src/app.h | 4 ++++ src/appInterface.h | 3 +++ src/defines.h | 2 +- src/hm/payload.h | 45 ++++++++++++++++++++++++++++++--------------- src/web/RestApi.h | 1 + 7 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 0ba677a3..4a0a2f94 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,10 @@ (starting from release version `0.5.66`) +## 0.5.68 +* repaired receive payload +* Powerlimit is transfered immediately to inverter + ## 0.5.67 * changed calculation of start / stop communication to 1 min after last comm. stop #515 * moved payload send to `payload.h`, function `ivSend` #515 diff --git a/src/app.cpp b/src/app.cpp index b0e310c4..7ad48f26 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -90,6 +90,7 @@ void app::loop(void) { ah::Scheduler::loop(); mSys->Radio.loop(); + mPayload.loop(); yield(); @@ -116,8 +117,6 @@ void app::loop(void) { if (rxRdy) mPayload.process(true); - - mRxTicker = 0; } #if !defined(AP_ONLY) diff --git a/src/app.h b/src/app.h index 54dca314..8663c2a9 100644 --- a/src/app.h +++ b/src/app.h @@ -122,6 +122,10 @@ class app : public IApp, public ah::Scheduler { once(std::bind(&PubMqttType::sendDiscoveryConfig, &mMqtt), 1); } + void ivSendHighPrio(Inverter<> *iv) { + mPayload.ivSendHighPrio(iv); + } + bool getMqttIsConnected() { return mMqtt.isConnected(); } diff --git a/src/appInterface.h b/src/appInterface.h index 94f75399..64acab6b 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -7,6 +7,7 @@ #define __IAPP_H__ #include "defines.h" +#include "hm/hmSystem.h" // abstract interface to App. Make members of App accessible from child class // like web or API without forward declaration @@ -34,6 +35,8 @@ class IApp { virtual bool getSettingsValid() = 0; virtual void setMqttDiscoveryFlag() = 0; + virtual void ivSendHighPrio(Inverter<> *iv) = 0; + virtual bool getMqttIsConnected() = 0; virtual uint32_t getMqttRxCnt() = 0; virtual uint32_t getMqttTxCnt() = 0; diff --git a/src/defines.h b/src/defines.h index 301c9f17..616caa0d 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 67 +#define VERSION_PATCH 68 //------------------------------------- typedef struct { diff --git a/src/hm/payload.h b/src/hm/payload.h index 2a37be32..b0ea7464 100644 --- a/src/hm/payload.h +++ b/src/hm/payload.h @@ -42,6 +42,7 @@ class Payload : public Handler { mTimestamp = timestamp; memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t))); mSerialDebug = false; + mHighPrioIv = NULL; } void enableSerialDebug(bool enable) { @@ -54,22 +55,35 @@ class Payload : public Handler { } } - void ivSend(Inverter<> *iv) { - if (!mPayload[iv->id].complete) - process(false); + void loop() { + if(NULL != mHighPrioIv) { + ivSend(mHighPrioIv, true); + mHighPrioIv = NULL; + } + } - if (!mPayload[iv->id].complete) { - if (0 == mPayload[iv->id].maxPackId) - mStat->rxFailNoAnser++; - else - mStat->rxFail++; + void ivSendHighPrio(Inverter<> *iv) { + mHighPrioIv = iv; + } - iv->setQueuedCmdFinished(); // command failed - if (mSerialDebug) - DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); - if (mSerialDebug) { - DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") "); - DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload[iv->id].retransmits) + ")"); + void ivSend(Inverter<> *iv, bool highPrio = false) { + if(!highPrio) { + if (!mPayload[iv->id].complete) + process(false); + + if (!mPayload[iv->id].complete) { + if (0 == mPayload[iv->id].maxPackId) + mStat->rxFailNoAnser++; + else + mStat->rxFail++; + + iv->setQueuedCmdFinished(); // command failed + if (mSerialDebug) + DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); + if (mSerialDebug) { + DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") "); + DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload[iv->id].retransmits) + ")"); + } } } @@ -180,7 +194,7 @@ class Payload : public Handler { mPayload[iv->id].txCmd = iv->getQueuedCmd(); DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex); - } else if (mPayload[iv->id].maxPackId != 0) { + } else { for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { if (mPayload[iv->id].len[i] == 0) { DPRINTLN(DBG_WARN, F("while retrieving data: Frame ") + String(i + 1) + F(" missing: Request Retransmit")); @@ -264,6 +278,7 @@ class Payload : public Handler { uint32_t *mTimestamp; invPayload_t mPayload[MAX_NUM_INVERTERS]; bool mSerialDebug; + Inverter<> *mHighPrioIv; }; #endif /*__PAYLOAD_H_*/ diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 8ad55e26..4246a866 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -534,6 +534,7 @@ class RestApi { iv->powerLimit[1] = AbsolutNonPersistent; iv->devControlCmd = ActivePowerContr; iv->devControlRequest = true; + mApp->ivSendHighPrio(iv); } else if(F("dev") == jsonIn[F("cmd")]) { DPRINTLN(DBG_INFO, F("dev cmd")); From 93ae88fca20b4239625f3ca7f66926cfca2cd449 Mon Sep 17 00:00:00 2001 From: PaeserBastelstube <122045840+PaeserBastelstube@users.noreply.github.com> Date: Thu, 5 Jan 2023 18:50:44 +0100 Subject: [PATCH 182/431] change AC_CURRENT divider to 100 In line 514, ac_current dividor must be 100 not 10 There is a mismatch in AC output: power[Watt] = voltage[Volt] * current[Ampere] --- tools/rpi/hoymiles/decoders/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/rpi/hoymiles/decoders/__init__.py b/tools/rpi/hoymiles/decoders/__init__.py index 0935110e..379a472a 100644 --- a/tools/rpi/hoymiles/decoders/__init__.py +++ b/tools/rpi/hoymiles/decoders/__init__.py @@ -511,7 +511,7 @@ class Hm600Decode0B(StatusResponse): @property def ac_current_0(self): """ Phase 1 ampere """ - return self.unpack('>H', 34)[0]/10 + return self.unpack('>H', 34)[0]/100 @property def ac_power_0(self): """ Phase 1 watts """ From 94487641cc18f2a57b839c41d671fc869e72a55b Mon Sep 17 00:00:00 2001 From: dAjaY85 Date: Fri, 6 Jan 2023 12:08:05 +0100 Subject: [PATCH 183/431] =?UTF-8?q?Hinzuf=C3=BCgen=20vom=201,3"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.cpp | 2 +- src/app.h | 6 ++-- src/platformio.ini | 36 +++++++++++++++++++ .../MonochromeDisplay/MonochromeDisplay.h | 20 +++++++---- 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 7ad48f26..83be5a36 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -74,7 +74,7 @@ void app::setup() { mApi.setup(this, mSys, mWeb.getWebSrvPtr(), mConfig); // Plugins - #if defined(ENA_NOKIA) || defined(ENA_SSD1306) + #if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) mMonoDisplay.setup(mSys, &mTimestamp); everySec(std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay)); #endif diff --git a/src/app.h b/src/app.h index 8663c2a9..5a4bb494 100644 --- a/src/app.h +++ b/src/app.h @@ -46,7 +46,7 @@ typedef PubMqtt PubMqttType; typedef PubSerial PubSerialType; // PLUGINS -#if defined(ENA_NOKIA) || defined(ENA_SSD1306) +#if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) #include "plugins/MonochromeDisplay/MonochromeDisplay.h" typedef MonochromeDisplay MonoDisplayType; #endif @@ -180,7 +180,7 @@ class app : public IApp, public ah::Scheduler { #if !defined(AP_ONLY) mMqtt.payloadEventListener(cmd); #endif - #if defined(ENA_NOKIA) || defined(ENA_SSD1306) + #if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) mMonoDisplay.payloadEventListener(cmd); #endif } @@ -244,7 +244,7 @@ class app : public IApp, public ah::Scheduler { uint32_t mSunrise, mSunset; // plugins - #if defined(ENA_NOKIA) || defined(ENA_SSD1306) + #if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) MonoDisplayType mMonoDisplay; #endif }; diff --git a/src/platformio.ini b/src/platformio.ini index ba6c8be0..d64a8c93 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -125,6 +125,24 @@ lib_deps = https://github.com/ThingPulse/esp8266-oled-ssd1306.git https://github.com/JChristensen/Timezone +[env:esp8266-sh1106] +platform = espressif8266 +board = esp12e +board_build.f_cpu = 80000000L +build_flags = -D RELEASE -DENA_SH1106 +monitor_filters = + ;default ; Remove typical terminal control codes from input + time ; Add timestamp with milliseconds for each new line + ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory +lib_deps = + https://github.com/yubox-node-org/ESPAsyncWebServer + nrf24/RF24 + paulstoffregen/Time + https://github.com/bertmelis/espMqttClient#v1.3.3 + bblanchon/ArduinoJson + https://github.com/ThingPulse/esp8266-oled-ssd1306.git + https://github.com/JChristensen/Timezone + [env:esp32-wroom32-release] platform = espressif32 board = lolin_d32 @@ -181,3 +199,21 @@ lib_deps = bblanchon/ArduinoJson https://github.com/ThingPulse/esp8266-oled-ssd1306.git https://github.com/JChristensen/Timezone + +[env:esp32-wroom32-sh1106] +platform = espressif32 +board = lolin_d32 +build_flags = -D RELEASE -std=gnu++14 -DENA_SH1106 +build_unflags = -std=gnu++11 +monitor_filters = + ;default ; Remove typical terminal control codes from input + time ; Add timestamp with milliseconds for each new line + ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory +lib_deps = + https://github.com/yubox-node-org/ESPAsyncWebServer + nrf24/RF24 + paulstoffregen/Time + https://github.com/bertmelis/espMqttClient#v1.3.3 + bblanchon/ArduinoJson + https://github.com/ThingPulse/esp8266-oled-ssd1306.git + https://github.com/JChristensen/Timezone \ No newline at end of file diff --git a/src/plugins/MonochromeDisplay/MonochromeDisplay.h b/src/plugins/MonochromeDisplay/MonochromeDisplay.h index 83236992..3bfe9458 100644 --- a/src/plugins/MonochromeDisplay/MonochromeDisplay.h +++ b/src/plugins/MonochromeDisplay/MonochromeDisplay.h @@ -1,15 +1,19 @@ #ifndef __MONOCHROME_DISPLAY__ #define __MONOCHROME_DISPLAY__ -#if defined(ENA_NOKIA) || defined(ENA_SSD1306) +#if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) #ifdef ENA_NOKIA #include #define DISP_PROGMEM U8X8_PROGMEM -#else // ENA_SSD1306 +#else // ENA_SSD1306 || ENA_SH1106 /* esp8266 : SCL = 5, SDA = 4 */ /* ewsp32 : SCL = 22, SDA = 21 */ #include - #include + #ifdef ENA_SSD1306 + #include + # else //ENA_SH1106 + #include + #endif #define DISP_PROGMEM PROGMEM #endif @@ -34,7 +38,7 @@ class MonochromeDisplay { mNewPayload = false; mExtra = 0; } - #else // ENA_SSD1306 + #else // ENA_SSD1306 || ENA_SH1106 MonochromeDisplay() : mDisplay(0x3c, SDA, SCL), mCE(CEST, CET) { mNewPayload = false; mExtra = 0; @@ -215,7 +219,7 @@ class MonochromeDisplay { mDisplay.sendBuffer(); } while( mDisplay.nextPage() ); mExtra++; - #else // ENA_SSD1306 + #else // ENA_SSD1306 || ENA_SH1106 if(mUp) { mRx += 2; if(mRx >= 20) @@ -289,7 +293,11 @@ class MonochromeDisplay { #if defined(ENA_NOKIA) U8G2_PCD8544_84X48_1_4W_HW_SPI mDisplay; #else // ENA_SSD1306 - SSD1306Wire mDisplay; + #ifdef ENA_SSD1306 + SSD1306Wire mDisplay; + # else //ENA_SH1106 + SH1106Wire mDisplay; + #endif int mRx; char mUp; #endif From 712b5af9b9a32ace2dd8460a0a0e1a96a94040cc Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 7 Jan 2023 01:15:25 +0100 Subject: [PATCH 184/431] merged SH1106 1.3" Display, thx @dAjaY85 added SH1106 to automatic build added IP address to MQTT (version, device and IP are retained and only transmitted once after boot) #556 added `set_power_limit` acknowledge MQTT publish #553 changed: version, device name are only published via MQTT once after boot added `Login` to menu if admin password is set #554 added `development` to second changelog link in `index.html` #543 added interval for MQTT (as option). With this settings MQTT live data is published in a fixed timing (only if inverter is available) #542, #523 added MQTT `comm_disabled` #529 --- .github/workflows/compile_development.yml | 2 +- .github/workflows/compile_release.yml | 2 +- User_Manual.md | 2 + src/CHANGES.md | 11 +++++ src/app.cpp | 9 ++-- src/app.h | 4 ++ src/appInterface.h | 1 + src/config/settings.h | 6 ++- src/defines.h | 2 +- src/hm/payload.h | 10 ++++- src/publisher/pubMqtt.h | 53 ++++++++++++++++++----- src/web/RestApi.h | 24 ++++++---- src/web/html/index.html | 2 +- src/web/html/setup.html | 9 ++-- src/web/web.h | 1 + 15 files changed, 107 insertions(+), 31 deletions(-) diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index 8d8ab45e..203e23a7 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -47,7 +47,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 + run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp8266-sh1106 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 --environment esp32-wroom32-sh1106 - name: Rename Binary files id: rename-binary-files diff --git a/.github/workflows/compile_release.yml b/.github/workflows/compile_release.yml index 20fcef87..91c4c8e3 100644 --- a/.github/workflows/compile_release.yml +++ b/.github/workflows/compile_release.yml @@ -51,7 +51,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 + run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp8266-sh1106 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 --environment esp32-wroom32-sh1106 - name: Rename Binary files id: rename-binary-files diff --git a/User_Manual.md b/User_Manual.md index 529125a0..be7519ec 100644 --- a/User_Manual.md +++ b/User_Manual.md @@ -29,6 +29,7 @@ The AhoyDTU will publish on the following topics | `uptime` | 73630 | uptime in seconds | false | | `version` | 0.5.61 | current installed verison of AhoyDTU | true | | `wifi_rssi` | -75 | WiFi signal strength | false | +| `ip_addr` | 192.168.178.25 | WiFi Station IP Address | true | | status code | Remarks | |---|---| @@ -43,6 +44,7 @@ The AhoyDTU will publish on the following topics |---|---|---|---| | `available` | 2 | see table below | true | | `last_success` | 1672155690 | UTC Timestamp | true | +| `ack_pwr_limit` | true | fast information if inverter has accepted power limit | false | | status code | Remarks | |---|---| diff --git a/src/CHANGES.md b/src/CHANGES.md index 4a0a2f94..27fd1205 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,17 @@ (starting from release version `0.5.66`) +## 0.5.69 +* merged SH1106 1.3" Display, thx @dAjaY85 +* added SH1106 to automatic build +* added IP address to MQTT (version, device and IP are retained and only transmitted once after boot) #556 +* added `set_power_limit` acknowledge MQTT publish #553 +* changed: version, device name are only published via MQTT once after boot +* added `Login` to menu if admin password is set #554 +* added `development` to second changelog link in `index.html` #543 +* added interval for MQTT (as option). With this settings MQTT live data is published in a fixed timing (only if inverter is available) #542, #523 +* added MQTT `comm_disabled` #529 + ## 0.5.68 * repaired receive payload * Powerlimit is transfered immediately to inverter diff --git a/src/app.cpp b/src/app.cpp index 83be5a36..3e8da14f 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -51,7 +51,7 @@ void app::setup() { #endif mSys->addInverters(&mConfig->inst); - mPayload.setup(mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); + mPayload.setup(this, mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); mPayload.enableSerialDebug(mConfig->serial.debug); if(!mSys->Radio.isChipConnected()) @@ -162,14 +162,17 @@ void app::tickIVCommunication(void) { nxtTrig = mSunrise - mConfig->sun.offsetSec; } else { if (mTimestamp > (mSunset + mConfig->sun.offsetSec)) { // current time is past communication stop, nothing to do. Next update will be done at midnight by tickCalcSunrise - return; + nxtTrig = 0; } else { // current time lies within communication start/stop time, set next trigger to communication stop mIVCommunicationOn = true; nxtTrig = mSunset + mConfig->sun.offsetSec; } } - onceAt(std::bind(&app::tickIVCommunication, this), nxtTrig); + if (nxtTrig != 0) + onceAt(std::bind(&app::tickIVCommunication, this), nxtTrig); } + if (mConfig->mqtt.broker[0] > 0) + mMqtt.tickerComm(mIVCommunicationOn); } //----------------------------------------------------------------------------- diff --git a/src/app.h b/src/app.h index 5a4bb494..b08b7d05 100644 --- a/src/app.h +++ b/src/app.h @@ -122,6 +122,10 @@ class app : public IApp, public ah::Scheduler { once(std::bind(&PubMqttType::sendDiscoveryConfig, &mMqtt), 1); } + void setMqttPowerLimitAck(Inverter<> *iv) { + mMqtt.setPowerLimitAck(iv); + } + void ivSendHighPrio(Inverter<> *iv) { mPayload.ivSendHighPrio(iv); } diff --git a/src/appInterface.h b/src/appInterface.h index 64acab6b..4c25c3a2 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -34,6 +34,7 @@ class IApp { virtual bool getRebootRequestState() = 0; virtual bool getSettingsValid() = 0; virtual void setMqttDiscoveryFlag() = 0; + virtual void setMqttPowerLimitAck(Inverter<> *iv) = 0; virtual void ivSendHighPrio(Inverter<> *iv) = 0; diff --git a/src/config/settings.h b/src/config/settings.h index 47c59a8c..921ebc96 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -96,6 +96,7 @@ typedef struct { char user[MQTT_USER_LEN]; char pwd[MQTT_PWD_LEN]; char topic[MQTT_TOPIC_LEN]; + uint16_t interval; } cfgMqtt_t; typedef struct { @@ -297,6 +298,7 @@ class settings { snprintf(mCfg.mqtt.user, MQTT_USER_LEN, "%s", DEF_MQTT_USER); snprintf(mCfg.mqtt.pwd, MQTT_PWD_LEN, "%s", DEF_MQTT_PWD); snprintf(mCfg.mqtt.topic, MQTT_TOPIC_LEN, "%s", DEF_MQTT_TOPIC); + mCfg.mqtt.interval = 0; // off mCfg.led.led0 = DEF_LED0_PIN; mCfg.led.led1 = DEF_LED1_PIN; @@ -396,8 +398,10 @@ class settings { obj[F("user")] = mCfg.mqtt.user; obj[F("pwd")] = mCfg.mqtt.pwd; obj[F("topic")] = mCfg.mqtt.topic; + obj[F("intvl")] = mCfg.mqtt.interval; } else { - mCfg.mqtt.port = obj[F("port")]; + mCfg.mqtt.port = obj[F("port")]; + mCfg.mqtt.interval = obj[F("intvl")]; snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", obj[F("broker")].as()); snprintf(mCfg.mqtt.user, MQTT_USER_LEN, "%s", obj[F("user")].as()); snprintf(mCfg.mqtt.pwd, MQTT_PWD_LEN, "%s", obj[F("pwd")].as()); diff --git a/src/defines.h b/src/defines.h index 616caa0d..b37cb6c7 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 68 +#define VERSION_PATCH 69 //------------------------------------- typedef struct { diff --git a/src/hm/payload.h b/src/hm/payload.h index b0ea7464..1f112844 100644 --- a/src/hm/payload.h +++ b/src/hm/payload.h @@ -35,7 +35,8 @@ class Payload : public Handler { public: Payload() : Handler() {} - void setup(HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { + void setup(IApp *app, HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { + mApp = app; mSys = sys; mStat = stat; mMaxRetrans = maxRetransmits; @@ -141,7 +142,11 @@ class Payload : public Handler { iv->devControlRequest = false; if ((p->packet[12] == ActivePowerContr) && (p->packet[13] == 0x00)) { - String msg = (p->packet[10] == 0x00 && p->packet[11] == 0x00) ? "" : "NOT "; + String msg = ""; + if((p->packet[10] == 0x00) && (p->packet[11] == 0x00)) { + msg = "NOT "; + mApp->setMqttPowerLimitAck(iv); + } DPRINTLN(DBG_INFO, F("Inverter ") + String(iv->id) + F(" has ") + msg + F("accepted power limit set point ") + String(iv->powerLimit[0]) + F(" with PowerLimitControl ") + String(iv->powerLimit[1])); } iv->devControlCmd = Init; @@ -272,6 +277,7 @@ class Payload : public Handler { } private: + IApp *mApp; HMSYSTEM *mSys; statistics_t *mStat; uint8_t mMaxRetrans; diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index bd7a709f..382406f4 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -41,11 +41,13 @@ class PubMqtt { ~PubMqtt() { } void setup(cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs) { - mCfgMqtt = cfg_mqtt; - mDevName = devName; - mVersion = version; - mSys = sys; - mUtcTimestamp = utcTs; + mCfgMqtt = cfg_mqtt; + mDevName = devName; + mVersion = version; + mSys = sys; + mUtcTimestamp = utcTs; + mExeOnce = true; + mIntervalTimeout = 1; snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); @@ -73,7 +75,16 @@ class PubMqtt { } void tickerSecond() { - sendIvData(); + 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); + sendIvData(); + } + } + } void tickerMinute() { @@ -98,9 +109,16 @@ class PubMqtt { publish("dis_night_comm", ((disNightCom) ? "true" : "false"), true); } + void tickerComm(bool disabled) { + publish("comm_disabled", ((disabled) ? "true" : "false"), true); + publish("comm_dis_ts", String(*mUtcTimestamp).c_str(), true); + } + void payloadEventListener(uint8_t cmd) { - if(mClient.connected()) // prevent overflow if MQTT broker is not reachable but set - mSendList.push(cmd); + if(mClient.connected()) { // prevent overflow if MQTT broker is not reachable but set + if((0 == mCfgMqtt->interval) || (RealTimeRunData_Debug != cmd)) // no interval or no live data + mSendList.push(cmd); + } } void publish(const char *subTopic, const char *payload, bool retained = false, bool addTopic = true) { @@ -188,6 +206,15 @@ class PubMqtt { } } + void setPowerLimitAck(Inverter<> *iv) { + if (NULL != iv) { + char topic[7 + MQTT_TOPIC_LEN]; + + snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ack_pwr_limit", iv->config->name); + publish(topic, "true", true); + } + } + private: #if defined(ESP8266) void onWifiConnect(const WiFiEventStationModeGotIP& event) { @@ -223,8 +250,12 @@ class PubMqtt { DPRINTLN(DBG_INFO, F("MQTT connected")); mEnReconnect = true; - publish("version", mVersion, true); - publish("device", mDevName, true); + if(mExeOnce) { + publish("version", mVersion, true); + publish("device", mDevName, true); + publish("ip_addr", WiFi.localIP().toString().c_str(), true); + mExeOnce = false; + } tickerMinute(); publish(mLwtTopic, mLwtOnline, true, false); @@ -494,6 +525,8 @@ class PubMqtt { subscriptionCb mSubscriptionCb; bool mIvAvail; // shows if at least one inverter is available uint8_t mLastIvState[MAX_NUM_INVERTERS]; + bool mExeOnce; + uint16_t mIntervalTimeout; // last will topic and payload must be available trough lifetime of 'espMqttClient' char mLwtTopic[MQTT_TOPIC_LEN+5]; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 4246a866..8986e76d 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -276,11 +276,12 @@ class RestApi { } void getMqtt(JsonObject obj) { - obj[F("broker")] = String(mConfig->mqtt.broker); - obj[F("port")] = String(mConfig->mqtt.port); - obj[F("user")] = String(mConfig->mqtt.user); - obj[F("pwd")] = (strlen(mConfig->mqtt.pwd) > 0) ? F("{PWD}") : String(""); - obj[F("topic")] = String(mConfig->mqtt.topic); + obj[F("broker")] = String(mConfig->mqtt.broker); + obj[F("port")] = String(mConfig->mqtt.port); + obj[F("user")] = String(mConfig->mqtt.user); + obj[F("pwd")] = (strlen(mConfig->mqtt.pwd) > 0) ? F("{PWD}") : String(""); + obj[F("topic")] = String(mConfig->mqtt.topic); + obj[F("interval")] = String(mConfig->mqtt.interval); } void getNtp(JsonObject obj) { @@ -357,10 +358,15 @@ class RestApi { obj[F("name")][i] = "Documentation"; obj[F("link")][i] = "https://ahoydtu.de"; obj[F("trgt")][i++] = "_blank"; - if((strlen(mConfig->sys.adminPwd) > 0) && !mApp->getProtection()) { + if(strlen(mConfig->sys.adminPwd) > 0) { obj[F("name")][i++] = "-"; - obj[F("name")][i] = "Logout"; - obj[F("link")][i++] = "/logout"; + if(mApp->getProtection()) { + obj[F("name")][i] = "Login"; + obj[F("link")][i++] = "/login"; + } else { + obj[F("name")][i] = "Logout"; + obj[F("link")][i++] = "/logout"; + } } } @@ -411,6 +417,8 @@ class RestApi { JsonArray info = obj.createNestedArray(F("infos")); if(mApp->getMqttIsConnected()) info.add(F("MQTT is connected, ") + String(mApp->getMqttTxCnt()) + F(" packets sent, ") + String(mApp->getMqttRxCnt()) + F(" packets received")); + if(mConfig->mqtt.interval > 0) + info.add(F("MQTT publishes in a fixed interval of ") + String(mConfig->mqtt.interval) + F(" seconds")); } void getSetup(JsonObject obj) { diff --git a/src/web/html/index.html b/src/web/html/index.html index 0cd7f430..6634197e 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -51,7 +51,7 @@
          • Discuss with us on Discord
          • Report issues
          • Contribute to documentation
          • -
          • Download & Test development firmware, Changelog
          • +
          • Download & Test development firmware, Development Changelog
          • make a donation
          • diff --git a/src/web/html/setup.html b/src/web/html/setup.html index cf57f12b..8377cede 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -94,7 +94,7 @@

            General

            - + @@ -148,6 +148,9 @@ +

            Send Inverter data in a fixed interval, even if there is no change. A value of '0' disables the fixed interval. The data is published once it was successfully received from inverter. (default: 0)

            + + @@ -170,7 +173,7 @@
            - + @@ -389,7 +392,7 @@ } function parseMqtt(obj) { - for(var i of [["Addr", "broker"], ["Port", "port"], ["User", "user"], ["Pwd", "pwd"], ["Topic", "topic"]]) + for(var i of [["Addr", "broker"], ["Port", "port"], ["User", "user"], ["Pwd", "pwd"], ["Topic", "topic"], ["Interval", "interval"]]) document.getElementsByName("mqtt"+i[0])[0].value = obj[i[1]]; } diff --git a/src/web/web.h b/src/web/web.h index d8922747..b3667b64 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -494,6 +494,7 @@ class Web { request->arg("mqttPwd").toCharArray(mConfig->mqtt.pwd, MQTT_PWD_LEN); request->arg("mqttTopic").toCharArray(mConfig->mqtt.topic, MQTT_TOPIC_LEN); mConfig->mqtt.port = request->arg("mqttPort").toInt(); + mConfig->mqtt.interval = request->arg("mqttInterval").toInt(); // serial console if(request->arg("serIntvl") != "") { From cfb74c6a4c54f3963274da754cc2dad42bda6160 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 7 Jan 2023 01:32:53 +0100 Subject: [PATCH 185/431] changed name of binaries, moved GIT-Sha to the front #538 --- scripts/getVersion.py | 24 +++++++++++++++++------- src/CHANGES.md | 3 +++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/scripts/getVersion.py b/scripts/getVersion.py index f7c825ce..b53c82d4 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -52,42 +52,52 @@ def readVersion(path, infile): os.mkdir(path + "firmware/") sha = os.getenv("SHA",default="sha") - versionout = version[:-1] + "_esp8266_" + sha + ".bin" + versionout = version[:-1] + "_" + sha + "_esp8266.bin" src = path + ".pio/build/esp8266-release/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) - versionout = version[:-1] + "_esp8266_nokia5110_" + sha + ".bin" + versionout = version[:-1] + "_" + sha + "_esp8266_nokia5110.bin" src = path + ".pio/build/esp8266-nokia5110/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) - versionout = version[:-1] + "_esp8266_ssd1306_" + sha + ".bin" + versionout = version[:-1] + "_" + sha + "_esp8266_ssd1306.bin" src = path + ".pio/build/esp8266-ssd1306/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) + + versionout = version[:-1] + "_" + sha + "_esp8266_sh1106.bin" + src = path + ".pio/build/esp8266_sh1106/firmware.bin" + dst = path + "firmware/" + versionout + os.rename(src, dst) - versionout = version[:-1] + "_esp8285_" + sha + ".bin" + versionout = version[:-1] + "_" + sha + "_esp8285.bin" src = path + ".pio/build/esp8285-release/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) gzip_bin(dst, dst + ".gz") - versionout = version[:-1] + "_esp32_" + sha + ".bin" + versionout = version[:-1] + "_" + sha + "_esp32.bin" src = path + ".pio/build/esp32-wroom32-release/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) - versionout = version[:-1] + "_esp32_nokia5110_" + sha + ".bin" + versionout = version[:-1] + "_" + sha + "_esp32_nokia5110.bin" src = path + ".pio/build/esp32-wroom32-nokia5110/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) - versionout = version[:-1] + "_esp32_ssd1306_" + sha + ".bin" + versionout = version[:-1] + "_" + sha + "_esp32_ssd1306.bin" src = path + ".pio/build/esp32-wroom32-ssd1306/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) + versionout = version[:-1] + "_" + sha + "_esp32_sh1106.bin" + src = path + ".pio/build/esp32-wroom32-sh1106/firmware.bin" + dst = path + "firmware/" + versionout + os.rename(src, dst) + # other ESP32 bin files src = path + ".pio/build/esp32-wroom32-release/" dst = path + "firmware/" diff --git a/src/CHANGES.md b/src/CHANGES.md index 27fd1205..8fd8d8ad 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,8 @@ (starting from release version `0.5.66`) +## 0.5.70 + ## 0.5.69 * merged SH1106 1.3" Display, thx @dAjaY85 * added SH1106 to automatic build @@ -12,6 +14,7 @@ * added `development` to second changelog link in `index.html` #543 * added interval for MQTT (as option). With this settings MQTT live data is published in a fixed timing (only if inverter is available) #542, #523 * added MQTT `comm_disabled` #529 +* changed name of binaries, moved GIT-Sha to the front #538 ## 0.5.68 * repaired receive payload From 4265856814c59fccf4b6fe3e2bbf0a1647ad2779 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 7 Jan 2023 11:55:45 +0100 Subject: [PATCH 186/431] corrected github action corrected MQTT `comm_disabled` #529 --- scripts/getVersion.py | 2 +- src/CHANGES.md | 1 + src/app.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/getVersion.py b/scripts/getVersion.py index b53c82d4..5f96f37f 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -68,7 +68,7 @@ def readVersion(path, infile): os.rename(src, dst) versionout = version[:-1] + "_" + sha + "_esp8266_sh1106.bin" - src = path + ".pio/build/esp8266_sh1106/firmware.bin" + src = path + ".pio/build/esp8266-sh1106/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) diff --git a/src/CHANGES.md b/src/CHANGES.md index 8fd8d8ad..364b2b4d 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -3,6 +3,7 @@ (starting from release version `0.5.66`) ## 0.5.70 +* corrected MQTT `comm_disabled` #529 ## 0.5.69 * merged SH1106 1.3" Display, thx @dAjaY85 diff --git a/src/app.cpp b/src/app.cpp index 3e8da14f..6f53121b 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -172,7 +172,7 @@ void app::tickIVCommunication(void) { onceAt(std::bind(&app::tickIVCommunication, this), nxtTrig); } if (mConfig->mqtt.broker[0] > 0) - mMqtt.tickerComm(mIVCommunicationOn); + mMqtt.tickerComm(!mIVCommunicationOn); } //----------------------------------------------------------------------------- From 7dedcc2c8af677bcce997e0433d34ee35cf30fe7 Mon Sep 17 00:00:00 2001 From: PaeserBastelstube <122045840+PaeserBastelstube@users.noreply.github.com> Date: Sat, 7 Jan 2023 13:25:19 +0100 Subject: [PATCH 187/431] Add mqtt global head (print timestamp) and add DC-yield-daily MQTT record must have a timestamp for visualising last data received. DC-yield-daily is availible in "data" variable, but not printed in mqtt record. MQTT topics between ESP and RPI shoud be equel, so I sugest to change topic for YieldTotal --- tools/rpi/hoymiles/__main__.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index 8fc1b727..8a163aa5 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -209,6 +209,10 @@ def mqtt_send_status(broker, inverter_ser, data, topic=None): if not topic: topic = f'hoymiles/{inverter_ser}' + # Global Head + if data['time'] is not None: + broker.publish(f'{topic}/time', data['time'].strftime("%d.%m.%y - %H:%M:%S")) + # AC Data phase_id = 0 for phase in data['phases']: @@ -220,10 +224,11 @@ def mqtt_send_status(broker, inverter_ser, data, topic=None): # DC Data string_id = 0 for string in data['strings']: - broker.publish(f'{topic}/emeter-dc/{string_id}/total', string['energy_total']/1000) - broker.publish(f'{topic}/emeter-dc/{string_id}/power', string['power']) broker.publish(f'{topic}/emeter-dc/{string_id}/voltage', string['voltage']) broker.publish(f'{topic}/emeter-dc/{string_id}/current', string['current']) + broker.publish(f'{topic}/emeter-dc/{string_id}/power', string['power']) + broker.publish(f'{topic}/emeter-dc/{string_id}/YieldDay', string['energy_daily']) + broker.publish(f'{topic}/emeter-dc/{string_id}/YieldTotal', string['energy_total']/1000) string_id = string_id + 1 # Global if data['powerfactor'] is not None: From 1a435b4e7bab1e2777b6ae8fab3796d420723ab6 Mon Sep 17 00:00:00 2001 From: Sarge Date: Sat, 7 Jan 2023 21:34:53 +0100 Subject: [PATCH 188/431] MQTT topic input: allow more special chars (#$%&), removed needles escapes / minus at end as required by regex --- src/web/html/setup.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 8377cede..c60020e1 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -147,7 +147,7 @@ - +

            Send Inverter data in a fixed interval, even if there is no change. A value of '0' disables the fixed interval. The data is published once it was successfully received from inverter. (default: 0)

            From 2c7e60352d3ecf6d893e7fe6ede53cc5d7dd23c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knuti=5Fin=5FP=C3=A4se?= <122045840+PaeserBastelstube@users.noreply.github.com> Date: Sun, 8 Jan 2023 18:17:55 +0100 Subject: [PATCH 189/431] RPI: reactive power (Blindleistung) missing we are missing "weactive power" (Blindleistung) in our output on RPi. On ESP it is working allready. --- tools/rpi/hoymiles/decoders/__init__.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/rpi/hoymiles/decoders/__init__.py b/tools/rpi/hoymiles/decoders/__init__.py index 379a472a..f67cdfda 100644 --- a/tools/rpi/hoymiles/decoders/__init__.py +++ b/tools/rpi/hoymiles/decoders/__init__.py @@ -91,7 +91,7 @@ class Response: class StatusResponse(Response): """Inverter StatusResponse object""" - e_keys = ['voltage','current','power','energy_total','energy_daily','powerfactor'] + e_keys = ['voltage','current','power','energy_total','energy_daily','powerfactor', 'reactive_power'] temperature = None frequency = None powerfactor = None @@ -438,6 +438,10 @@ class Hm300Decode0B(StatusResponse): """ Grid frequency in Hertz """ return self.unpack('>H', 16)[0]/100 @property + def ac_reactive_power_0(self): + """ reactive power """ + return self.unpack('>H', 20)[0]/10 + @property def temperature(self): """ Inverter temperature in °C """ return self.unpack('>h', 26)[0]/10 @@ -521,6 +525,10 @@ class Hm600Decode0B(StatusResponse): """ Grid frequency in Hertz """ return self.unpack('>H', 28)[0]/100 @property + def ac_reactive_power_0(self): + """ reactive power """ + return self.unpack('>H', 32)[0]/10 + @property def powerfactor(self): """ Powerfactor """ return self.unpack('>H', 36)[0]/1000 @@ -654,6 +662,10 @@ class Hm1200Decode0B(StatusResponse): """ Grid frequency in Hertz """ return self.unpack('>H', 48)[0]/100 @property + def ac_reactive_power_0(self): + """ reactive power """ + return self.unpack('>H', 52)[0]/10 + @property def powerfactor(self): """ Powerfactor """ return self.unpack('>H', 56)[0]/1000 From 94cd4eb5bda7d9691552b85f2aebae8de8054193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knuti=5Fin=5FP=C3=A4se?= <122045840+PaeserBastelstube@users.noreply.github.com> Date: Sun, 8 Jan 2023 18:30:22 +0100 Subject: [PATCH 190/431] RPi: miss reactice power - add MQTT output [Q_VA] Add MQTT Output [Q_VA] for reactive Power --- tools/rpi/hoymiles/__main__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index 8a163aa5..2fd8f991 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -219,6 +219,7 @@ def mqtt_send_status(broker, inverter_ser, data, topic=None): broker.publish(f'{topic}/emeter/{phase_id}/power', phase['power']) broker.publish(f'{topic}/emeter/{phase_id}/voltage', phase['voltage']) broker.publish(f'{topic}/emeter/{phase_id}/current', phase['current']) + broker.publish(f'{topic}/emeter/{phase_id}/Q_AC', phase['reactive_power']) phase_id = phase_id + 1 # DC Data From d8e255ddc2c9c5b09ee14e739a744ed0597c980c Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 8 Jan 2023 22:16:14 +0100 Subject: [PATCH 191/431] corrected MQTT `comm_disabled` #529 fix Prometheus and JSON endpoints (`config_override.h`) #561 publish MQTT with fixed interval even if inverter is not available #542 added JSON settings upload. NOTE: settings JSON download changed, so only settings should be uploaded starting from version `0.5.70` #551 MQTT topic and inverter name have more allowed characters: `[A-Za-z0-9./#$%&=+_-]+`, thx: @Mo Demman improved potential issue with `checkTicker`, thx @cbscpe MQTT option for reset values on midnight / not avail / communication stop #539 small fix in `tickIVCommunication` #534 add `YieldTotal` correction, eg. to have the option to zero at year start #512 --- src/CHANGES.md | 8 +++ src/app.cpp | 14 +++- src/app.h | 7 +- src/appInterface.h | 1 + src/config/settings.h | 31 +++++++-- src/defines.h | 2 +- src/hm/hmInverter.h | 18 ++++- src/publisher/pubMqtt.h | 143 +++++++++++++++++++++++++++++---------- src/utils/ahoyTimer.h | 2 +- src/utils/llist.h | 110 ------------------------------ src/utils/scheduler.h | 1 + src/web/RestApi.h | 43 +++++++++--- src/web/html/setup.html | 47 ++++++++++--- src/web/html/update.html | 1 - src/web/web.h | 129 ++++++++++++++++++++++++++--------- src/wifi/ahoywifi.h | 3 +- 16 files changed, 344 insertions(+), 216 deletions(-) delete mode 100644 src/utils/llist.h diff --git a/src/CHANGES.md b/src/CHANGES.md index 364b2b4d..ce304e4b 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -4,6 +4,14 @@ ## 0.5.70 * corrected MQTT `comm_disabled` #529 +* fix Prometheus and JSON endpoints (`config_override.h`) #561 +* publish MQTT with fixed interval even if inverter is not available #542 +* added JSON settings upload. NOTE: settings JSON download changed, so only settings should be uploaded starting from version `0.5.70` #551 +* MQTT topic and inverter name have more allowed characters: `[A-Za-z0-9./#$%&=+_-]+`, thx: @Mo Demman +* improved potential issue with `checkTicker`, thx @cbscpe +* MQTT option for reset values on midnight / not avail / communication stop #539 +* small fix in `tickIVCommunication` #534 +* add `YieldTotal` correction, eg. to have the option to zero at year start #512 ## 0.5.69 * merged SH1106 1.3" Display, thx @dAjaY85 diff --git a/src/app.cpp b/src/app.cpp index 6f53121b..e42b8c2b 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -62,6 +62,9 @@ void app::setup() { if (mConfig->mqtt.broker[0] > 0) { everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt)); everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt)); + uint32_t nxtTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight + if(mConfig->mqtt.rstYieldMidNight) + onceAt(std::bind(&app::tickMidnight, this), nxtTrig); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); } #endif @@ -161,7 +164,7 @@ void app::tickIVCommunication(void) { if (mTimestamp < (mSunrise - mConfig->sun.offsetSec)) { // current time is before communication start, set next trigger to communication start nxtTrig = mSunrise - mConfig->sun.offsetSec; } else { - if (mTimestamp > (mSunset + mConfig->sun.offsetSec)) { // current time is past communication stop, nothing to do. Next update will be done at midnight by tickCalcSunrise + if (mTimestamp >= (mSunset + mConfig->sun.offsetSec)) { // current time is past communication stop, nothing to do. Next update will be done at midnight by tickCalcSunrise nxtTrig = 0; } else { // current time lies within communication start/stop time, set next trigger to communication stop mIVCommunicationOn = true; @@ -207,6 +210,15 @@ void app::tickSend(void) { updateLed(); } +//----------------------------------------------------------------------------- +void app::tickMidnight(void) { + // only used and enabled by MQTT (see setup()) + uint32_t nxtTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight + onceAt(std::bind(&app::tickMidnight, this), nxtTrig); + + mMqtt.tickerMidnight(); +} + //----------------------------------------------------------------------------- void app::handleIntr(void) { DPRINTLN(DBG_VERBOSE, F("app::handleIntr")); diff --git a/src/app.h b/src/app.h index b08b7d05..fdbf9616 100644 --- a/src/app.h +++ b/src/app.h @@ -78,6 +78,10 @@ class app : public IApp, public ah::Scheduler { return mSettings.saveSettings(); } + bool readSettings(const char *path) { + return mSettings.readSettings(path); + } + bool eraseSettings(bool eraseWifi = false) { return mSettings.eraseSettings(eraseWifi); } @@ -95,7 +99,7 @@ class app : public IApp, public ah::Scheduler { } void setRebootFlag() { - once(std::bind(&app::tickReboot, this), 1); + once(std::bind(&app::tickReboot, this), 3); } const char *getVersion() { @@ -203,6 +207,7 @@ class app : public IApp, public ah::Scheduler { void tickCalcSunrise(void); void tickIVCommunication(void); void tickSend(void); + void tickMidnight(void); /*void tickSerial(void) { if(Serial.available() == 0) return; diff --git a/src/appInterface.h b/src/appInterface.h index 4c25c3a2..c2d191b2 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -15,6 +15,7 @@ class IApp { public: virtual ~IApp() {} virtual bool saveSettings() = 0; + virtual bool readSettings(const char *path) = 0; virtual bool eraseSettings(bool eraseWifi) = 0; virtual void setRebootFlag() = 0; virtual const char *getVersion() = 0; diff --git a/src/config/settings.h b/src/config/settings.h index 921ebc96..50fbe01d 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -97,6 +97,9 @@ typedef struct { char pwd[MQTT_PWD_LEN]; char topic[MQTT_TOPIC_LEN]; uint16_t interval; + bool rstYieldMidNight; + bool rstValsNotAvail; + bool rstValsCommStop; } cfgMqtt_t; typedef struct { @@ -105,6 +108,7 @@ typedef struct { serial_u serial; uint16_t chMaxPwr[4]; char chName[4][MAX_NAME_LENGTH]; + uint32_t yieldCor; // YieldTotal correction value } cfgIv_t; typedef struct { @@ -155,7 +159,7 @@ class settings { else DPRINTLN(DBG_INFO, F(" .. done")); - readSettings(); + readSettings("/settings.json"); } // should be used before OTA @@ -186,9 +190,10 @@ class settings { #endif } - void readSettings(void) { + bool readSettings(const char* path) { + bool success = false; loadDefaults(); - File fp = LittleFS.open("/settings.json", "r"); + File fp = LittleFS.open(path, "r"); if(!fp) DPRINTLN(DBG_WARN, F("failed to load json, using default config")); else { @@ -206,6 +211,7 @@ class settings { jsonMqtt(root["mqtt"]); jsonLed(root["led"]); jsonInst(root["inst"]); + success = true; } else { Serial.println(F("failed to parse json, using default config")); @@ -213,6 +219,7 @@ class settings { fp.close(); } + return success; } bool saveSettings(void) { @@ -299,6 +306,9 @@ class settings { snprintf(mCfg.mqtt.pwd, MQTT_PWD_LEN, "%s", DEF_MQTT_PWD); snprintf(mCfg.mqtt.topic, MQTT_TOPIC_LEN, "%s", DEF_MQTT_TOPIC); mCfg.mqtt.interval = 0; // off + mCfg.mqtt.rstYieldMidNight = false; + mCfg.mqtt.rstValsNotAvail = false; + mCfg.mqtt.rstValsCommStop = false; mCfg.led.led0 = DEF_LED0_PIN; mCfg.led.led1 = DEF_LED1_PIN; @@ -399,9 +409,16 @@ class settings { obj[F("pwd")] = mCfg.mqtt.pwd; obj[F("topic")] = mCfg.mqtt.topic; obj[F("intvl")] = mCfg.mqtt.interval; + obj[F("rstMidNight")] = (bool)mCfg.mqtt.rstYieldMidNight; + obj[F("rstNotAvail")] = (bool)mCfg.mqtt.rstValsNotAvail; + obj[F("rstComStop")] = (bool)mCfg.mqtt.rstValsCommStop; + } else { mCfg.mqtt.port = obj[F("port")]; mCfg.mqtt.interval = obj[F("intvl")]; + mCfg.mqtt.rstYieldMidNight = (bool)obj["rstMidNight"]; + mCfg.mqtt.rstValsNotAvail = (bool)obj["rstNotAvail"]; + mCfg.mqtt.rstValsCommStop = (bool)obj["rstComStop"]; snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", obj[F("broker")].as()); snprintf(mCfg.mqtt.user, MQTT_USER_LEN, "%s", obj[F("user")].as()); snprintf(mCfg.mqtt.pwd, MQTT_PWD_LEN, "%s", obj[F("pwd")].as()); @@ -438,9 +455,10 @@ class settings { void jsonIv(JsonObject obj, cfgIv_t *cfg, bool set = false) { if(set) { - obj[F("en")] = (bool)cfg->enabled; - obj[F("name")] = cfg->name; - obj[F("sn")] = cfg->serial.u64; + obj[F("en")] = (bool)cfg->enabled; + obj[F("name")] = cfg->name; + obj[F("sn")] = cfg->serial.u64; + obj[F("yield")] = cfg->yieldCor; for(uint8_t i = 0; i < 4; i++) { obj[F("pwr")][i] = cfg->chMaxPwr[i]; obj[F("chName")][i] = cfg->chName[i]; @@ -449,6 +467,7 @@ class settings { cfg->enabled = (bool)obj[F("en")]; snprintf(cfg->name, MAX_NAME_LENGTH, "%s", obj[F("name")].as()); cfg->serial.u64 = obj[F("sn")]; + cfg->yieldCor = obj[F("yield")]; for(uint8_t i = 0; i < 4; i++) { cfg->chMaxPwr[i] = obj[F("pwr")][i]; snprintf(cfg->chName[i], MAX_NAME_LENGTH, "%s", obj[F("chName")][i].as()); diff --git a/src/defines.h b/src/defines.h index b37cb6c7..8ab9ccda 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 69 +#define VERSION_PATCH 70 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 8c1fccc8..f02c6b9b 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -233,11 +233,13 @@ class Inverter { val <<= 8; val |= buf[ptr]; } while(++ptr != end); - if(FLD_T == rec->assign[pos].fieldId) { + if (FLD_T == rec->assign[pos].fieldId) { // temperature is a signed value! rec->record[pos] = (REC_TYP)((int16_t)val) / (REC_TYP)(div); - } - else { + } else if ((FLD_YT == rec->assign[pos].fieldId) + && (config->yieldCor != 0)) { + rec->record[pos] = (REC_TYP)(val) / (REC_TYP)(div) - (REC_TYP)config->yieldCor; + } else { if ((REC_TYP)(div) > 1) rec->record[pos] = (REC_TYP)(val) / (REC_TYP)(div); else @@ -286,6 +288,16 @@ class Inverter { DPRINTLN(DBG_ERROR, F("addValue: assignment not found with cmd 0x")); } + bool setValue(uint8_t pos, record_t<> *rec, REC_TYP val) { + DPRINTLN(DBG_VERBOSE, F("hmInverter.h:setValue")); + if(NULL == rec) + return false; + if(pos > rec->length) + return false; + rec->record[pos] = val; + return true; + } + REC_TYP getValue(uint8_t pos, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getValue")); if(NULL == rec) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 382406f4..85742bd5 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -112,6 +112,27 @@ class PubMqtt { void tickerComm(bool disabled) { publish("comm_disabled", ((disabled) ? "true" : "false"), true); publish("comm_dis_ts", String(*mUtcTimestamp).c_str(), true); + + if(disabled && (mCfgMqtt->rstValsCommStop)) + zeroAllInverters(); + } + + void tickerMidnight() { + Inverter<> *iv; + record_t<> *rec; + + // set YieldDay to zero + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + iv = mSys->getInverterByPos(id); + if (NULL == iv) + continue; // skip to next inverter + rec = iv->getRecordStruct(RealTimeRunData_Debug); + uint8_t pos = iv->getPosByChFld(CH0, FLD_YD, rec); + iv->setValue(pos, rec, 0.0f); + } + + mSendList.push(RealTimeRunData_Debug); + sendIvData(); } void payloadEventListener(uint8_t cmd) { @@ -394,18 +415,21 @@ class PubMqtt { allAvail = false; } } - else if (!iv->isProducing(*mUtcTimestamp, rec)) { + else { mIvAvail = true; - if (MQTT_STATUS_AVAIL_PROD == status) - status = MQTT_STATUS_AVAIL_NOT_PROD; + if (!iv->isProducing(*mUtcTimestamp, rec)) { + if (MQTT_STATUS_AVAIL_PROD == status) + status = MQTT_STATUS_AVAIL_NOT_PROD; + } } - else - mIvAvail = true; if(mLastIvState[id] != status) { mLastIvState[id] = status; changed = true; + if(mCfgMqtt->rstValsNotAvail) + zeroValues(iv); + snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name); snprintf(val, 40, "%d", status); publish(topic, val, true); @@ -419,12 +443,13 @@ class PubMqtt { if(changed) { snprintf(val, 32, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((mIvAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE))); publish("status", val, true); + sendIvData(false); // false prevents loop of same function } return totalComplete; } - void sendIvData(void) { + void sendIvData(bool sendTotals = true) { if(mSendList.empty()) return; @@ -442,49 +467,52 @@ class PubMqtt { record_t<> *rec = iv->getRecordStruct(mSendList.front()); // data - if(iv->isAvailable(*mUtcTimestamp, rec)) { - for (uint8_t i = 0; i < rec->length; i++) { - bool retained = false; - if (mSendList.front() == RealTimeRunData_Debug) { + //if(iv->isAvailable(*mUtcTimestamp, rec) || (0 != mCfgMqtt->interval)) { // is avail or fixed pulish interval was set + for (uint8_t i = 0; i < rec->length; i++) { + bool retained = false; + if (mSendList.front() == RealTimeRunData_Debug) { + switch (rec->assign[i].fieldId) { + case FLD_YT: + case FLD_YD: + retained = true; + break; + } + } + + snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); + snprintf(val, 40, "%g", ah::round3(iv->getValue(i, rec))); + publish(topic, val, retained); + + // calculate total values for RealTimeRunData_Debug + if (mSendList.front() == RealTimeRunData_Debug) { + 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: - retained = true; + total[2] += iv->getValue(i, rec); + break; + case FLD_PDC: + total[3] += iv->getValue(i, rec); break; } } - - snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); - snprintf(val, 40, "%g", ah::round3(iv->getValue(i, rec))); - publish(topic, val, retained); - - // calculate total values for RealTimeRunData_Debug - if (mSendList.front() == RealTimeRunData_Debug) { - 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; - } - } - sendTotal = true; - } - yield(); + sendTotal = true; } + yield(); } + //} } mSendList.pop(); // remove from list once all inverters were processed + if(!sendTotals) // skip total value calculation + continue; + if ((true == sendTotal) && processIvStatus()) { uint8_t fieldId; for (uint8_t i = 0; i < 4; i++) { @@ -511,6 +539,47 @@ class PubMqtt { } } + void zeroAllInverters() { + Inverter<> *iv; + + // set values to zero, exept yields + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + iv = mSys->getInverterByPos(id); + if (NULL == iv) + continue; // skip to next inverter + + zeroValues(iv); + } + sendIvData(); + } + + void zeroValues(Inverter<> *iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + for(uint8_t ch = 0; ch <= iv->channels; ch++) { + uint8_t pos = 0; + uint8_t fld = 0; + while(0xff != pos) { + switch(fld) { + case FLD_YD: + case FLD_YT: + case FLD_FW_VERSION: + case FLD_FW_BUILD_YEAR: + case FLD_FW_BUILD_MONTH_DAY: + case FLD_FW_BUILD_HOUR_MINUTE: + case FLD_HW_ID: + case FLD_ACT_ACTIVE_PWR_LIMIT: + continue; + break; + } + pos = iv->getPosByChFld(ch, fld, rec); + iv->setValue(pos, rec, 0.0f); + fld++; + } + } + + mSendList.push(RealTimeRunData_Debug); + } + espMqttClient mClient; cfgMqtt_t *mCfgMqtt; #if defined(ESP8266) diff --git a/src/utils/ahoyTimer.h b/src/utils/ahoyTimer.h index 5c960a34..08c09016 100644 --- a/src/utils/ahoyTimer.h +++ b/src/utils/ahoyTimer.h @@ -15,7 +15,7 @@ namespace ah { *ticker = mil + interval; return true; } - else if(mil < (*ticker - interval)) { + else if((mil + interval) < (*ticker)) { *ticker = mil + interval; return true; } diff --git a/src/utils/llist.h b/src/utils/llist.h deleted file mode 100644 index 69750f19..00000000 --- a/src/utils/llist.h +++ /dev/null @@ -1,110 +0,0 @@ -//----------------------------------------------------------------------------- -// 2022 Ahoy, https://ahoydtu.de -// Lukas Pusch, lukas@lpusch.de -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ -//----------------------------------------------------------------------------- -#ifndef __LIST_H__ -#define __LIST_H__ - -template -struct node_s { - typedef T dT; - node_s *pre; - node_s *nxt; - uint8_t id; - dT d; - node_s() : pre(NULL), nxt(NULL), d() {} - node_s(Args... args) : id(0), pre(NULL), nxt(NULL), d(args...) {} -}; - -template -class llist { - typedef node_s elmType; - typedef T dataType; - public: - llist() : root(mPool) { - root = NULL; - elmType *p = mPool; - for(uint32_t i = 0; i < MAX_NUM; i++) { - p->id = i; - p++; - } - mFill = mMax = 0; - } - - elmType *add(Args... args) { - elmType *p = root, *t; - if(NULL == (t = getFreeNode())) - return NULL; - if(++mFill > mMax) - mMax = mFill; - - if(NULL == root) { - p = root = t; - p->pre = p; - p->nxt = p; - } - else { - p = root->pre; - t->pre = p; - p->nxt->pre = t; - t->nxt = p->nxt; - p->nxt = t; - } - t->d = dataType(args...); - return p; - } - - elmType *getFront() { - return root; - } - - elmType *get(elmType *p) { - p = p->nxt; - return (p == root) ? NULL : p; - } - - elmType *rem(elmType *p) { - if(NULL == p) - return NULL; - elmType *t = p->nxt; - p->nxt->pre = p->pre; - p->pre->nxt = p->nxt; - if((root == p) && (p->nxt == p)) - root = NULL; - else - root = p->nxt; - p->nxt = NULL; - p->pre = NULL; - p = NULL; - mFill--; - return (NULL == root) ? NULL : ((t == root) ? NULL : t); - } - - uint16_t getFill(void) { - return mFill; - } - - uint16_t getMaxFill(void) { - return mMax; - } - - protected: - elmType *root; - - private: - elmType *getFreeNode(void) { - elmType *n = mPool; - for(uint32_t i = 0; i < MAX_NUM; i++) { - if(NULL == n->nxt) - return n; - n++; - } - return NULL; - } - - elmType mPool[MAX_NUM]; - uint16_t mFill, mMax; -}; - -#endif /*__LIST_H__*/ diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h index 36dcdaae..330ab080 100644 --- a/src/utils/scheduler.h +++ b/src/utils/scheduler.h @@ -129,6 +129,7 @@ namespace ah { mTickerInUse[i] = false; else mTicker[i].timeout = mTicker[i].reload; + //DPRINTLN(DBG_INFO, "checkTick " + String(i) + " reload: " + String(mTicker[i].reload) + ", timeout: " + String(mTicker[i].timeout)); (mTicker[i].c)(); yield(); } diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 8986e76d..07c12994 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -134,17 +134,34 @@ class RestApi { ep[F("record/config")] = url + F("record/config"); ep[F("record/live")] = url + F("record/live"); } + void onDwnldSetup(AsyncWebServerRequest *request) { - AsyncJsonResponse* response = new AsyncJsonResponse(false, 8192); - JsonObject root = response->getRoot(); + AsyncWebServerResponse *response; - getSetup(root); + File fp = LittleFS.open("/settings.json", "r"); + if(!fp) { + DPRINTLN(DBG_ERROR, F("failed to load settings")); + response = request->beginResponse(200, F("application/json"), "{}"); + } + else { + String tmp = fp.readString(); + int i = 0; + // remove all passwords + while (i != -1) { + i = tmp.indexOf("\"pwd\":", i); + if(-1 != i) { + i+=7; + tmp.remove(i, tmp.indexOf("\"", i)-i); + } + } + response = request->beginResponse(200, F("application/json"), tmp); + } - response->setLength(); response->addHeader("Content-Type", "application/octet-stream"); response->addHeader("Content-Description", "File Transfer"); response->addHeader("Content-Disposition", "attachment; filename=ahoy_setup.json"); request->send(response); + fp.close(); } void getGeneric(JsonObject obj) { @@ -165,7 +182,7 @@ class RestApi { obj[F("device_name")] = mConfig->sys.deviceName; obj[F("mac")] = WiFi.macAddress(); - obj[F("hostname")] = WiFi.getHostname(); + obj[F("hostname")] = mConfig->sys.deviceName; obj[F("pwd_set")] = (strlen(mConfig->sys.adminPwd) > 0); obj[F("prot_mask")] = mConfig->sys.protectionMask; @@ -263,6 +280,7 @@ class RestApi { obj2[F("serial")] = String(iv->config->serial.u64, HEX); obj2[F("channels")] = iv->channels; obj2[F("version")] = String(iv->getFwVersion()); + obj2[F("yieldCor")] = iv->config->yieldCor; for(uint8_t j = 0; j < iv->channels; j ++) { obj2[F("ch_max_power")][j] = iv->config->chMaxPwr[j]; @@ -276,12 +294,15 @@ class RestApi { } void getMqtt(JsonObject obj) { - obj[F("broker")] = String(mConfig->mqtt.broker); - obj[F("port")] = String(mConfig->mqtt.port); - obj[F("user")] = String(mConfig->mqtt.user); - obj[F("pwd")] = (strlen(mConfig->mqtt.pwd) > 0) ? F("{PWD}") : String(""); - obj[F("topic")] = String(mConfig->mqtt.topic); - obj[F("interval")] = String(mConfig->mqtt.interval); + obj[F("broker")] = String(mConfig->mqtt.broker); + obj[F("port")] = String(mConfig->mqtt.port); + obj[F("user")] = String(mConfig->mqtt.user); + obj[F("pwd")] = (strlen(mConfig->mqtt.pwd) > 0) ? F("{PWD}") : String(""); + obj[F("topic")] = String(mConfig->mqtt.topic); + obj[F("interval")] = String(mConfig->mqtt.interval); + obj[F("rstMid")] = (bool)mConfig->mqtt.rstYieldMidNight; + obj[F("rstNAvail")] = (bool)mConfig->mqtt.rstValsNotAvail; + obj[F("rstComStop")] = (bool)mConfig->mqtt.rstValsCommStop; } void getNtp(JsonObject obj) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 8377cede..aad46232 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -31,7 +31,13 @@
            ERASE SETTINGS (not WiFi) - +
            + Upload JSON Settings +
            + + +
            +
            Device Host Name @@ -147,7 +153,13 @@ - + + +
            + +
            + +

            Send Inverter data in a fixed interval, even if there is no change. A value of '0' disables the fixed interval. The data is published once it was successfully received from inverter. (default: 0)

            @@ -184,7 +196,7 @@
            - Download your settings (JSON file) (only saved values) + Download your settings (JSON file) (only saved values, passwords will be removed!)
            @@ -212,8 +224,9 @@ const re = /11[2,4,6]1.*/; document.getElementById("btnAdd").addEventListener("click", function() { - if(highestId <= (maxInv-1)) - ivHtml(JSON.parse('{"enabled":true,"name":"","serial":"","channels":4,"ch_max_power":[0,0,0,0],"ch_name":["","","",""]}'), highestId + 1); + if(highestId <= (maxInv-1)) { + ivHtml(JSON.parse('{"enabled":true,"name":"","serial":"","channels":4,"ch_max_power":[0,0,0,0],"ch_name":["","","",""]}'), highestId); + } }); function apiCbWifi(obj) { @@ -268,6 +281,12 @@ getAjax("/api/setup", apiCbMqtt, "POST", JSON.stringify(obj)); } + function hide() { + document.getElementById("form").submit(); + var e = document.getElementById("content"); + e.replaceChildren(span("upload started")); + } + function delIv() { var id = this.id.substring(0,4); var e = document.getElementsByName(id + "Addr")[0]; @@ -278,8 +297,8 @@ } function ivHtml(obj, id) { - highestId = id; - if(highestId == (maxInv - 1)) + highestId = id + 1; + if(highestId == maxInv) setHide("btnAdd", true); iv = document.getElementById("inverter"); iv.appendChild(des("Inverter " + id)); @@ -292,7 +311,7 @@ iv.appendChild(br()); iv.appendChild(lbl(id + "Addr", "Serial Number (12 digits)*")); - var addr = inp(id + "Addr", obj["serial"], 12); + var addr = inp(id + "Addr", obj["serial"], 12, ["text"], null, "text", "[0-9]+", "Invalid input"); iv.appendChild(addr); ['keyup', 'change'].forEach(function(evt) { addr.addEventListener(evt, (e) => { @@ -323,7 +342,7 @@ iv.append( lbl(id + "Name", "Name*"), - inp(id + "Name", obj["name"], 32, ["text"], null, "text", "[A-Za-z0-9.\\-_\\+\\/]+", "Invalid input") + inp(id + "Name", obj["name"], 32, ["text"], null, "text", "[A-Za-z0-9./#$%&=+_-]+", "Invalid input") ); for(var j of [["ModPwr", "ch_max_power", "Max Module Power (Wp)", 4, "[0-9]+"], ["ModName", "ch_name", "Module Name", 16, null]]) { @@ -339,10 +358,15 @@ iv.appendChild(d); } + iv.append( + br(), + lbl(id + "YieldCor", "Yield Total Correction (will be subtracted) [kWh]"), + inp(id + "YieldCor", obj["yieldCor"], 32, ["text"], null, "text", "[0-9]+", "Invalid input") + ); + var del = inp(id+"del", "X", 0, ["btn", "btnDel"], id+"del", "button"); del.addEventListener("click", delIv); iv.append( - br(), lbl(id + "lbldel", "Delete"), del ); @@ -394,6 +418,9 @@ function parseMqtt(obj) { for(var i of [["Addr", "broker"], ["Port", "port"], ["User", "user"], ["Pwd", "pwd"], ["Topic", "topic"], ["Interval", "interval"]]) document.getElementsByName("mqtt"+i[0])[0].value = obj[i[1]]; + + for(var i of [["Mid", "rstMid"], ["ComStop", "rstNAvail"], ["NotAvail", "rstComStop"]]) + document.getElementsByName("mqttRst"+i[0])[0].checked = obj[i[1]]; } function parseNtp(obj) { diff --git a/src/web/html/update.html b/src/web/html/update.html index 215188db..e9bcde87 100644 --- a/src/web/html/update.html +++ b/src/web/html/update.html @@ -23,7 +23,6 @@ -
            - ERASE SETTINGS (not WiFi) -
            - Upload JSON Settings -
            - - -
            -
            Device Host Name @@ -196,7 +188,15 @@
            - Download your settings (JSON file) (only saved values, passwords will be removed!) + ERASE SETTINGS (not WiFi) +
            + Upload / Store JSON Settings + + + + +
            + Download settings (JSON file) (only saved values, passwords will be removed!)
            diff --git a/src/web/html/system.html b/src/web/html/system.html index 5419d7ba..75e05765 100644 --- a/src/web/html/system.html +++ b/src/web/html/system.html @@ -94,11 +94,12 @@ } main.append( + genTabRow("TX count", stat["tx_cnt"]), genTabRow("RX success", stat["rx_success"]), genTabRow("RX fail", stat["rx_fail"]), genTabRow("RX no answer", stat["rx_fail_answer"]), - genTabRow("RX frames received", stat["frame_cnt"]), - genTabRow("TX count", stat["tx_cnt"]) + genTabRow("RX fragments", stat["frame_cnt"]), + genTabRow("TX retransmits", stat["retransmits"]) ); } diff --git a/src/web/web.h b/src/web/web.h index 0756e009..e80ff76f 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -86,6 +86,7 @@ class Web { mWeb.on("/upload", HTTP_POST, std::bind(&Web::onUpload, this, std::placeholders::_1), std::bind(&Web::onUpload2, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)); mWeb.on("/serial", HTTP_GET, std::bind(&Web::onSerial, this, std::placeholders::_1)); + mWeb.on("/debug", HTTP_GET, std::bind(&Web::onDebug, this, std::placeholders::_1)); mEvts.onConnect(std::bind(&Web::onConnect, this, std::placeholders::_1)); @@ -189,12 +190,15 @@ class Web { msg.replace("\r\n", ""); if(mSerialAddTime) { if((9 + mSerialBufFill) <= WEB_SERIAL_BUF_SIZE) { - strncpy(&mSerialBuf[mSerialBufFill], mApp->getTimeStr(mApp->getTimezoneOffset()).c_str(), 9); - mSerialBufFill += 9; + if(mApp->getTimestamp() > 0) { + strncpy(&mSerialBuf[mSerialBufFill], mApp->getTimeStr(mApp->getTimezoneOffset()).c_str(), 9); + mSerialBufFill += 9; + } } else { mSerialBufFill = 0; - mEvts.send("webSerial, buffer overflow!", "serial", millis()); + mEvts.send("webSerial, buffer overflow!", "serial", millis()); + return; } mSerialAddTime = false; } @@ -209,7 +213,7 @@ class Web { } else { mSerialBufFill = 0; - mEvts.send("webSerial, buffer overflow!", "serial", millis()); + mEvts.send("webSerial, buffer overflow!", "serial", millis()); } } @@ -649,6 +653,12 @@ class Web { request->send(200, "text/json", "{success:true}"); }*/ + void onDebug(AsyncWebServerRequest *request) { + mApp->getSchedulerNames(); + AsyncWebServerResponse *response = request->beginResponse(200, F("text/html"), "ok"); + request->send(response); + } + void onSerial(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("onSerial")); diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index a743ddf5..c4fba044 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -11,7 +11,7 @@ // NTP CONFIG #define NTP_PACKET_SIZE 48 - +#define NTP_RETRIES 5 //----------------------------------------------------------------------------- ahoywifi::ahoywifi() : mApIp(192, 168, 4, 1) {} @@ -26,6 +26,7 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mStaConn = DISCONNECTED; mCnt = 0; mScanActive = false; + mRetries = NTP_RETRIES; #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); @@ -148,7 +149,17 @@ void ahoywifi::setupStation(void) { //----------------------------------------------------------------------------- -bool ahoywifi::getNtpTime(void) { +bool ahoywifi::getNtpTime(uint32_t *nxtTrig) { + if(0 != mRetries) { + DPRINTLN(DBG_INFO, "try to getNtpTime"); + *nxtTrig = 43200; // check again in 12h (if NTP was successful) + mRetries--; + } else if(0 != *mUtcTimestamp) { // time is availabe, but NTP not + *nxtTrig = 5; // check again 5s + mRetries = NTP_RETRIES; + return true; // true is necessary to enable all timers even if NTP was not reachable + } + if(GOT_IP != mStaConn) return false; @@ -267,6 +278,7 @@ void ahoywifi::connectionEvent(WiFiStatus_t status) { setupWifi(); // reconnect with AP / Station setup mAppWifiCb(false); DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); + mRetries = NTP_RETRIES; } break; diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index d8b503e4..72a80d7b 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -25,7 +25,7 @@ class ahoywifi { void setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb); void tickWifiLoop(void); - bool getNtpTime(void); + bool getNtpTime(uint32_t *nxtTrig); void scanAvailNetworks(void); void getAvailNetworks(JsonObject obj); @@ -68,6 +68,7 @@ class ahoywifi { uint8_t mLoopCnt; bool mScanActive; + uint8_t mRetries; }; #endif /*__AHOYWIFI_H__*/ From a0a40be9a6db3189820a8084b64b547b6c101a1e Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 19 Jan 2023 22:51:13 +0100 Subject: [PATCH 224/431] fix compile --- src/app.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.cpp b/src/app.cpp index d698bba8..643efb17 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -147,7 +147,7 @@ void app::regularTickers(void) { everySec(std::bind(&WebType::tickSecond, &mWeb), "webSc"); // Plugins #if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) - everySec(std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay)); + everySec(std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay), "disp"); #endif every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval, "uart"); } From 76b5818f487a58eb8526e5863bacb54bd75bd809 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 20 Jan 2023 07:21:28 +0100 Subject: [PATCH 225/431] fix compile --- src/plugins/MonochromeDisplay/MonochromeDisplay.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/MonochromeDisplay/MonochromeDisplay.h b/src/plugins/MonochromeDisplay/MonochromeDisplay.h index 7f050fe2..2e64844b 100644 --- a/src/plugins/MonochromeDisplay/MonochromeDisplay.h +++ b/src/plugins/MonochromeDisplay/MonochromeDisplay.h @@ -138,7 +138,7 @@ class MonochromeDisplay { for (uint8_t fld = 0; fld < 3; fld++) { pos = iv->getPosByChFld(CH0, list[fld],rec); - int isprod = iv->isProducing(*mUtcTs,rec); + int isprod = iv->isProducing(*mUtcTs); if(fld == 1) { From 2b3f252bbf1ed03b6896646bfe32bf6a9a4b1e58 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 21 Jan 2023 00:34:39 +0100 Subject: [PATCH 226/431] fix wakeup issue, once wifi was lost during night the communication didn't start in the morning reenabled FlashStringHelper because of lacking RAM complete rewrite of monochrome display class, thx to @dAjaY85 -> displays are now configurable in setup --- .github/workflows/compile_development.yml | 2 +- .github/workflows/compile_release.yml | 2 +- src/CHANGES.md | 5 + src/app.cpp | 22 +- src/app.h | 14 +- src/config/config.h | 2 - src/config/settings.h | 64 ++- src/defines.h | 2 +- src/hm/hmInverter.h | 16 + src/platformio.ini | 112 +---- .../MonochromeDisplay/MonochromeDisplay.h | 429 +++++++----------- src/utils/dbg.h | 2 +- src/web/RestApi.h | 13 +- src/web/html/setup.html | 151 +++--- src/web/web.h | 11 + src/wifi/ahoywifi.cpp | 25 +- src/wifi/ahoywifi.h | 4 +- 17 files changed, 389 insertions(+), 487 deletions(-) diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index 203e23a7..ec435880 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -47,7 +47,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp8266-sh1106 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 --environment esp32-wroom32-sh1106 + run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release - name: Rename Binary files id: rename-binary-files diff --git a/.github/workflows/compile_release.yml b/.github/workflows/compile_release.yml index 91c4c8e3..91ae35bf 100644 --- a/.github/workflows/compile_release.yml +++ b/.github/workflows/compile_release.yml @@ -51,7 +51,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp8266-sh1106 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 --environment esp32-wroom32-sh1106 + run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release - name: Rename Binary files id: rename-binary-files diff --git a/src/CHANGES.md b/src/CHANGES.md index 1e9b48e1..40cf5f8b 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,11 @@ (starting from release version `0.5.66`) +## 0.5.75 +* fix wakeup issue, once wifi was lost during night the communication didn't start in the morning +* reenabled FlashStringHelper because of lacking RAM +* complete rewrite of monochrome display class, thx to @dAjaY85 -> displays are now configurable in setup + ## 0.5.74 * improved payload handling (retransmit all fragments on CRC error) * improved `isAvailable`, checkes all record structs, inverter becomes available more early because version is check first diff --git a/src/app.cpp b/src/app.cpp index 643efb17..7f4071a2 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -64,9 +64,8 @@ void app::setup() { mApi.setup(this, mSys, mWeb.getWebSrvPtr(), mConfig); // Plugins - #if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) - mMonoDisplay.setup(&mConfig->plugin.display, mSys, &mTimestamp); - #endif + if(mConfig->plugin.display.type != 0) + mMonoDisplay.setup(&mConfig->plugin.display, mSys, &mTimestamp, 0xff, mVersion); mPubSerial.setup(mConfig, mSys, &mTimestamp); @@ -133,6 +132,7 @@ void app::onWifi(bool gotIp) { mInnerLoopCb = std::bind(&app::loopStandard, this); mSendTickerId = every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval, "tSend"); mMqttReconnect = true; + mSunrise = 0; // needs to be set to 0, to reinstall sunrise and ivComm tickers! once(std::bind(&app::tickNtpUpdate, this), 2, "ntp2"); } else { @@ -146,27 +146,27 @@ void app::regularTickers(void) { DPRINTLN(DBG_DEBUG, F("regularTickers")); everySec(std::bind(&WebType::tickSecond, &mWeb), "webSc"); // Plugins - #if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) - everySec(std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay), "disp"); - #endif + if(mConfig->plugin.display.type != 0) + everySec(std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay), "disp"); every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval, "uart"); } //----------------------------------------------------------------------------- void app::tickNtpUpdate(void) { uint32_t nxtTrig = 5; // default: check again in 5 sec - if (mWifi.getNtpTime(&nxtTrig)) { + if (mWifi.getNtpTime()) { if (mMqttReconnect && mMqttEnabled) { mMqtt.connect(); everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS"); everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt), "mqttM"); - uint32_t nxtTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight - if(mConfig->mqtt.rstYieldMidNight) - onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "midNi"); + if(mConfig->mqtt.rstYieldMidNight) { + uint32_t midTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight + onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi"); + } mMqttReconnect = false; } - nxtTrig = 43200; + nxtTrig = 43200; // check again in 12h if((mSunrise == 0) && (mConfig->sun.lat) && (mConfig->sun.lon)) { mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; diff --git a/src/app.h b/src/app.h index 7a0cd38e..0466daf8 100644 --- a/src/app.h +++ b/src/app.h @@ -46,10 +46,8 @@ typedef PubMqtt PubMqttType; typedef PubSerial PubSerialType; // PLUGINS -#if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) - #include "plugins/MonochromeDisplay/MonochromeDisplay.h" - typedef MonochromeDisplay MonoDisplayType; -#endif +#include "plugins/MonochromeDisplay/MonochromeDisplay.h" +typedef MonochromeDisplay MonoDisplayType; class app : public IApp, public ah::Scheduler { @@ -180,10 +178,8 @@ class app : public IApp, public ah::Scheduler { void setTimestamp(uint32_t newTime) { DPRINTLN(DBG_DEBUG, F("setTimestamp: ") + String(newTime)); - if(0 == newTime) { - uint32_t tmp; - mWifi.getNtpTime(&tmp); - } + if(0 == newTime) + mWifi.getNtpTime(); else Scheduler::setTimestamp(newTime); } @@ -269,9 +265,7 @@ class app : public IApp, public ah::Scheduler { uint32_t mSunrise, mSunset; // plugins - #if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) MonoDisplayType mMonoDisplay; - #endif }; #endif /*__APP_H__*/ diff --git a/src/config/config.h b/src/config/config.h index 2b5a0688..69e7193b 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -52,8 +52,6 @@ #define DEF_CE_PIN 2 #define DEF_IRQ_PIN 0 #endif -#define DEF_LED0_PIN 255 // off -#define DEF_LED1_PIN 255 // off // default NRF24 power, possible values (0 - 3) #define DEF_AMPLIFIERPOWER 1 diff --git a/src/config/settings.h b/src/config/settings.h index 5a83c699..dbf39d6c 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -17,6 +17,7 @@ * More info: * https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout * */ +#define DEF_PIN_OFF 255 #define PROT_MASK_INDEX 0x0001 @@ -117,10 +118,15 @@ typedef struct { } cfgInst_t; typedef struct { + uint8_t type; bool pwrSaveAtIvOffline; - uint32_t wakeUp; - uint32_t sleepAt; + bool logoEn; + bool pxShift; + uint16_t wakeUp; + uint16_t sleepAt; uint8_t contrast; + uint8_t pin0; + uint8_t pin1; } display_t; typedef struct { @@ -216,14 +222,15 @@ class settings { DeserializationError err = deserializeJson(root, fp); if(!err && (root.size() > 0)) { mCfg.valid = true; - jsonWifi(root["wifi"]); - jsonNrf(root["nrf"]); - jsonNtp(root["ntp"]); - jsonSun(root["sun"]); - jsonSerial(root["serial"]); - jsonMqtt(root["mqtt"]); - jsonLed(root["led"]); - jsonInst(root["inst"]); + jsonWifi(root[F("wifi")]); + jsonNrf(root[F("nrf")]); + jsonNtp(root[F("ntp")]); + jsonSun(root[F("sun")]); + jsonSerial(root[F("serial")]); + jsonMqtt(root[F("mqtt")]); + jsonLed(root[F("led")]); + jsonPlugin(root[F("plugin")]); + jsonInst(root[F("inst")]); success = true; } else { @@ -252,6 +259,7 @@ class settings { jsonSerial(root.createNestedObject(F("serial")), true); jsonMqtt(root.createNestedObject(F("mqtt")), true); jsonLed(root.createNestedObject(F("led")), true); + jsonPlugin(root.createNestedObject(F("plugin")), true); jsonInst(root.createNestedObject(F("inst")), true); if(0 == serializeJson(root, fp)) { @@ -323,13 +331,17 @@ class settings { mCfg.mqtt.rstValsNotAvail = false; mCfg.mqtt.rstValsCommStop = false; - mCfg.led.led0 = DEF_LED0_PIN; - mCfg.led.led1 = DEF_LED1_PIN; + mCfg.led.led0 = DEF_PIN_OFF; + mCfg.led.led1 = DEF_PIN_OFF; memset(&mCfg.inst, 0, sizeof(cfgInst_t)); mCfg.plugin.display.pwrSaveAtIvOffline = false; - mCfg.plugin.display.contrast = 60; + mCfg.plugin.display.contrast = 60; + mCfg.plugin.display.logoEn = true; + mCfg.plugin.display.pxShift = true; + mCfg.plugin.display.pin0 = DEF_PIN_OFF; // SCL + mCfg.plugin.display.pin1 = DEF_PIN_OFF; // SDA } void jsonWifi(JsonObject obj, bool set = false) { @@ -452,6 +464,32 @@ class settings { } } + void jsonPlugin(JsonObject obj, bool set = false) { + if(set) { + JsonObject disp = obj.createNestedObject("disp"); + disp[F("type")] = mCfg.plugin.display.type; + disp[F("pwrSafe")] = (bool)mCfg.plugin.display.pwrSaveAtIvOffline; + disp[F("logo")] = (bool)mCfg.plugin.display.logoEn; + disp[F("pxShift")] = (bool)mCfg.plugin.display.pxShift; + disp[F("wake")] = mCfg.plugin.display.wakeUp; + disp[F("sleep")] = mCfg.plugin.display.sleepAt; + disp[F("contrast")] = mCfg.plugin.display.contrast; + disp[F("pin0")] = mCfg.plugin.display.pin0; + disp[F("pin1")] = mCfg.plugin.display.pin1; + } else { + JsonObject disp = obj["disp"]; + mCfg.plugin.display.type = disp[F("type")]; + mCfg.plugin.display.pwrSaveAtIvOffline = (bool) disp[F("pwrSafe")]; + mCfg.plugin.display.logoEn = (bool) disp[F("logo")]; + mCfg.plugin.display.pxShift = (bool) disp[F("pxShift")]; + mCfg.plugin.display.wakeUp = disp[F("wake")]; + mCfg.plugin.display.sleepAt = disp[F("sleep")]; + mCfg.plugin.display.contrast = disp[F("contrast")]; + mCfg.plugin.display.pin0 = disp[F("pin0")]; + mCfg.plugin.display.pin1 = disp[F("pin1")]; + } + } + void jsonInst(JsonObject obj, bool set = false) { if(set) obj[F("en")] = (bool)mCfg.inst.enabled; diff --git a/src/defines.h b/src/defines.h index d0fe6bf1..544507ae 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 74 +#define VERSION_PATCH 75 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 18b0869c..ab86965d 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -315,6 +315,22 @@ class Inverter { return true; } + REC_TYP getChannelFieldValue(uint8_t channel, uint8_t fieldId, record_t<> *rec) { + uint8_t pos = 0; + if(NULL != rec) { + for(; pos < rec->length; pos++) { + if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId)) + break; + } + if(pos >= rec->length) + return 0; + + return rec->record[pos]; + } + else + return 0; + } + REC_TYP getValue(uint8_t pos, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getValue")); if(NULL == rec) diff --git a/src/platformio.ini b/src/platformio.ini index 897cd451..60245f69 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -38,6 +38,8 @@ lib_deps = paulstoffregen/Time https://github.com/bertmelis/espMqttClient#v1.3.3 bblanchon/ArduinoJson + https://github.com/JChristensen/Timezone + olikraus/U8g2 ;esp8266/DNSServer ;esp8266/EEPROM ;esp8266/ESP8266WiFi @@ -89,60 +91,6 @@ monitor_filters = time ; Add timestamp with milliseconds for each new line log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory -[env:esp8266-nokia5110] -platform = espressif8266 -board = esp12e -board_build.f_cpu = 80000000L -build_flags = -D RELEASE -DU8X8_NO_HW_I2C -DENA_NOKIA -monitor_filters = - ;default ; Remove typical terminal control codes from input - time ; Add timestamp with milliseconds for each new line - ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory -lib_deps = - https://github.com/yubox-node-org/ESPAsyncWebServer - nrf24/RF24 - paulstoffregen/Time - https://github.com/bertmelis/espMqttClient#v1.3.3 - bblanchon/ArduinoJson - https://github.com/JChristensen/Timezone - olikraus/U8g2 - -[env:esp8266-ssd1306] -platform = espressif8266 -board = esp12e -board_build.f_cpu = 80000000L -build_flags = -D RELEASE -DENA_SSD1306 -monitor_filters = - ;default ; Remove typical terminal control codes from input - time ; Add timestamp with milliseconds for each new line - ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory -lib_deps = - https://github.com/yubox-node-org/ESPAsyncWebServer - nrf24/RF24 - paulstoffregen/Time - https://github.com/bertmelis/espMqttClient#v1.3.3 - bblanchon/ArduinoJson - https://github.com/JChristensen/Timezone - olikraus/U8g2 - -[env:esp8266-sh1106] -platform = espressif8266 -board = esp12e -board_build.f_cpu = 80000000L -build_flags = -D RELEASE -DENA_SH1106 -monitor_filters = - ;default ; Remove typical terminal control codes from input - time ; Add timestamp with milliseconds for each new line - ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory -lib_deps = - https://github.com/yubox-node-org/ESPAsyncWebServer - nrf24/RF24 - paulstoffregen/Time - https://github.com/bertmelis/espMqttClient#v1.3.3 - bblanchon/ArduinoJson - https://github.com/JChristensen/Timezone - olikraus/U8g2 - [env:esp32-wroom32-release] platform = espressif32 board = lolin_d32 @@ -163,59 +111,3 @@ monitor_filters = ;default ; Remove typical terminal control codes from input time ; Add timestamp with milliseconds for each new line log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory - -[env:esp32-wroom32-nokia5110] -platform = espressif32 -board = lolin_d32 -build_flags = -D RELEASE -std=gnu++14 -DU8X8_NO_HW_I2C -DENA_NOKIA -build_unflags = -std=gnu++11 -monitor_filters = - ;default ; Remove typical terminal control codes from input - time ; Add timestamp with milliseconds for each new line - ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory -lib_deps = - https://github.com/yubox-node-org/ESPAsyncWebServer - nrf24/RF24 - paulstoffregen/Time - https://github.com/bertmelis/espMqttClient#v1.3.3 - bblanchon/ArduinoJson - https://github.com/JChristensen/Timezone - olikraus/U8g2 - -[env:esp32-wroom32-ssd1306] -platform = espressif32 -board = lolin_d32 -build_flags = -D RELEASE -std=gnu++14 -DENA_SSD1306 -build_unflags = -std=gnu++11 -monitor_filters = - ;default ; Remove typical terminal control codes from input - time ; Add timestamp with milliseconds for each new line - ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory -lib_deps = - https://github.com/yubox-node-org/ESPAsyncWebServer - nrf24/RF24 - paulstoffregen/Time - https://github.com/bertmelis/espMqttClient#v1.3.3 - bblanchon/ArduinoJson - https://github.com/ThingPulse/esp8266-oled-ssd1306.git - https://github.com/JChristensen/Timezone - olikraus/U8g2 - -[env:esp32-wroom32-sh1106] -platform = espressif32 -board = lolin_d32 -build_flags = -D RELEASE -std=gnu++14 -DENA_SH1106 -build_unflags = -std=gnu++11 -monitor_filters = - ;default ; Remove typical terminal control codes from input - time ; Add timestamp with milliseconds for each new line - ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory -lib_deps = - https://github.com/yubox-node-org/ESPAsyncWebServer - nrf24/RF24 - paulstoffregen/Time - https://github.com/bertmelis/espMqttClient#v1.3.3 - bblanchon/ArduinoJson - https://github.com/ThingPulse/esp8266-oled-ssd1306.git - https://github.com/JChristensen/Timezone - olikraus/U8g2 \ No newline at end of file diff --git a/src/plugins/MonochromeDisplay/MonochromeDisplay.h b/src/plugins/MonochromeDisplay/MonochromeDisplay.h index 2e64844b..7666abfb 100644 --- a/src/plugins/MonochromeDisplay/MonochromeDisplay.h +++ b/src/plugins/MonochromeDisplay/MonochromeDisplay.h @@ -1,46 +1,41 @@ #ifndef __MONOCHROME_DISPLAY__ #define __MONOCHROME_DISPLAY__ -/* esp8266 : SCL = 5, SDA = 4 */ -/* ewsp32 : SCL = 22, SDA = 21 */ -#if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) #include -#ifdef ENA_NOKIA - #define DISP_PROGMEM U8X8_PROGMEM -#else // ENA_SSD1306 || ENA_SH1106 - #define DISP_PROGMEM PROGMEM -#endif - #include #include "../../utils/helper.h" #include "../../hm/hmSystem.h" +#define DISP_DEFAULT_TIMEOUT 60 // in seconds + static uint8_t bmp_logo[] PROGMEM = { - B00000000,B00000000, // ................ - B11101100,B00110111, // ..##.######.##.. - B11101100,B00110111, // ..##.######.##.. - B11100000,B00000111, // .....######..... - B11010000,B00001011, // ....#.####.#.... - B10011000,B00011001, // ...##..##..##... - B10000000,B00000001, // .......##....... - B00000000,B00000000, // ................ - B01111000,B00011110, // ...####..####... - B11111100,B00111111, // ..############.. - B01111100,B00111110, // ..#####..#####.. - B00000000,B00000000, // ................ - B11111100,B00111111, // ..############.. - B11111110,B01111111, // .##############. - B01111110,B01111110, // .######..######. - B00000000,B00000000 // ................ + B00000000, B00000000, // ................ + B11101100, B00110111, // ..##.######.##.. + B11101100, B00110111, // ..##.######.##.. + B11100000, B00000111, // .....######..... + B11010000, B00001011, // ....#.####.#.... + B10011000, B00011001, // ...##..##..##... + B10000000, B00000001, // .......##....... + B00000000, B00000000, // ................ + B01111000, B00011110, // ...####..####... + B11111100, B00111111, // ..############.. + B01111100, B00111110, // ..#####..#####.. + B00000000, B00000000, // ................ + B11111100, B00111111, // ..############.. + B11111110, B01111111, // .##############. + B01111110, B01111110, // .######..######. + B00000000, B00000000 // ................ }; -static uint8_t bmp_arrow[] DISP_PROGMEM = { +static uint8_t bmp_arrow[] PROGMEM = { B00000000, B00011100, B00011100, B00001110, B00001110, B11111110, B01111111, B01110000, B01110000, B00110000, B00111000, B00011000, B01111111, B00111111, - B00011110, B00001110, B00000110, B00000000, B00000000, B00000000, B00000000}; + B00011110, B00001110, B00000110, B00000000, B00000000, B00000000, B00000000 +}; + static TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; // Central European Summer Time static TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central European Standard Tim @@ -48,31 +43,41 @@ static TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central Eu template class MonochromeDisplay { public: - #ifdef ENA_NOKIA - MonochromeDisplay() : mDisplay(U8G2_R0, 5, 4, 16), mCE(CEST, CET) { - mNewPayload = false; - mExtra = 0; - } - #else // ENA_SSD1306 || ENA_SH1106 - MonochromeDisplay() : mDisplay(U8G2_R0, SCL, SDA, U8X8_PIN_NONE), mCE(CEST, CET) { - mNewPayload = false; - mExtra = 0; - } - #endif + uint8_t dispContrast = 60; - void setup(display_t *cfg, HMSYSTEM *sys, uint32_t *utcTs) { + MonochromeDisplay() : mCE(CEST, CET) {} + + void setup(display_t *cfg, HMSYSTEM *sys, uint32_t *utcTs, uint8_t disp_reset, const char *version) { mCfg = cfg; mSys = sys; mUtcTs = utcTs; - memset( mToday, 0, sizeof(float)*MAX_NUM_INVERTERS ); - memset( mTotal, 0, sizeof(float)*MAX_NUM_INVERTERS ); - mLastHour = 25; - mDisplay.begin(); - ShowInfoText("booting..."); - } + mNewPayload = false; + mLoopCnt = 0; + + mTimeout = DISP_DEFAULT_TIMEOUT; // power off timeout (after inverters go offline) + if(mCfg->type) { + switch(mCfg->type) { + case 1: + mDisplay = new U8G2_PCD8544_84X48_F_4W_HW_SPI(U8G2_R0, mCfg->pin0, mCfg->pin1, disp_reset); + break; + case 2: + mDisplay = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R0, disp_reset, mCfg->pin0, mCfg->pin1); + break; + case 3: + mDisplay = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R0, disp_reset, mCfg->pin0, mCfg->pin1); + break; + } + mDisplay->begin(); - void loop(void) { + mIsLarge = ((mDisplay->getWidth() > 120) && (mDisplay->getHeight() > 60)); + calcLineHeights(); + mDisplay->clearBuffer(); + mDisplay->setContrast(mCfg->contrast); + printText("Ahoy!", 0, 35); + printText(version, 3, 46); + mDisplay->sendBuffer(); + } } void payloadEventListener(uint8_t cmd) { @@ -80,244 +85,136 @@ class MonochromeDisplay { } void tickerSecond() { - static int cnt=1; - if(mNewPayload || !(cnt % 10)) { - cnt=1; + if(mCfg->pwrSaveAtIvOffline) { + if(mTimeout != 0) + mTimeout--; + } + if(mNewPayload || ((++mLoopCnt % 10) == 0)) { mNewPayload = false; + mLoopCnt = 0; DataScreen(); } - else - cnt++; } private: - void ShowInfoText(const char *txt) { - /* u8g2_font_open_iconic_embedded_2x_t 'D' + 'G' + 'J' */ - mDisplay.clear(); - mDisplay.firstPage(); - do { - const char *e; - const char *p = txt; - int y=10; - mDisplay.setFont(u8g2_font_5x8_tr); - while(1) { - for(e=p+1; (*e && (*e != '\n')); e++); - size_t len=e-p; - mDisplay.setCursor(2,y); - String res=((String)p).substring(0,len); - mDisplay.print(res); - if ( !*e ) - break; - p=e+1; - y+=12; + void DataScreen() { + if (mCfg->type == 0) + return; + if(*mUtcTs == 0) + return; + + float totalPower = 0; + float totalYieldDay = 0; + float totalYieldTotal = 0; + + bool isprod = false; + + Inverter<> *iv; + record_t<> *rec; + for (uint8_t i = 0; i < mSys->getNumInverters(); i++) { + iv = mSys->getInverterByPos(i); + rec = iv->getRecordStruct(RealTimeRunData_Debug); + if (iv == NULL) + continue; + + if (iv->isProducing(*mUtcTs)) + isprod = true; + + totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec); + totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec); + totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec); + } + + mDisplay->clearBuffer(); + + // Logos + // pxMovement +x (0 - 6 px) + uint8_t ex = (_mExtra % 7); + if (isprod) { + mDisplay->drawXBMP(5 + ex, 1, 8, 17, bmp_arrow); + if (mCfg->logoEn) + mDisplay->drawXBMP(mDisplay->getWidth() - 24 + ex, 2, 16, 16, bmp_logo); + } + + if ((totalPower > 0) && isprod) { + mTimeout = DISP_DEFAULT_TIMEOUT; + mDisplay->setPowerSave(false); + mDisplay->setContrast(mCfg->contrast); + if (totalPower > 999) + snprintf(_fmtText, sizeof(_fmtText), "%2.1f kW", (totalPower / 1000)); + else + snprintf(_fmtText, sizeof(_fmtText), "%3.0f W", totalPower); + printText(_fmtText, 0, 20); + } else { + printText("offline", 0, 25); + if(mCfg->pwrSaveAtIvOffline) { + if(mTimeout == 0) + mDisplay->setPowerSave(true); } - mDisplay.sendBuffer(); - } while( mDisplay.nextPage() ); - } + } + + snprintf(_fmtText, sizeof(_fmtText), "today: %4.0f Wh", totalYieldDay); + printText(_fmtText, 1); + + snprintf(_fmtText, sizeof(_fmtText), "total: %.1f kWh", totalYieldTotal); + printText(_fmtText, 2); - void DataScreen(void) { - String timeStr = ah::getDateTimeStr(mCE.toLocal(*mUtcTs)).substring(2, 16); - int hr = timeStr.substring(9,2).toInt(); IPAddress ip = WiFi.localIP(); - float totalYield = 0.0, totalYieldToday = 0.0, totalActual = 0.0; - char fmtText[32]; - int ucnt=0, num_inv=0; - unsigned int pow_i[ MAX_NUM_INVERTERS ]; - - memset( pow_i, 0, sizeof(unsigned int)* MAX_NUM_INVERTERS ); - if ( hr < mLastHour ) // next day ? reset today-values - memset( mToday, 0, sizeof(float)*MAX_NUM_INVERTERS ); - mLastHour = hr; - - for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL != iv) { - record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - uint8_t pos; - uint8_t list[] = {FLD_PAC, FLD_YT, FLD_YD}; - - for (uint8_t fld = 0; fld < 3; fld++) { - pos = iv->getPosByChFld(CH0, list[fld],rec); - int isprod = iv->isProducing(*mUtcTs); - - if(fld == 1) - { - if ( isprod ) - mTotal[num_inv] = iv->getValue(pos,rec); - totalYield += mTotal[num_inv]; - } - if(fld == 2) - { - if ( isprod ) - mToday[num_inv] = iv->getValue(pos,rec); - totalYieldToday += mToday[num_inv]; - } - if((fld == 0) && isprod ) - { - pow_i[num_inv] = iv->getValue(pos,rec); - totalActual += iv->getValue(pos,rec); - ucnt++; - } - } - num_inv++; - } + if (!(_mExtra % 10) && (ip)) { + printText(ip.toString().c_str(), 3); + } else { + // Get current time + if(mIsLarge) + printText(ah::getDateTimeStr(mCE.toLocal(*mUtcTs)).c_str(), 3); + else + printText(ah::getTimeStr(mCE.toLocal(*mUtcTs)).c_str(), 3); + } + mDisplay->sendBuffer(); + + _mExtra++; + } + + void calcLineHeights() { + uint8_t yOff = 0; + for(uint8_t i = 0; i < 4; i++) { + setFont(i); + yOff += (mDisplay->getMaxCharHeight() + 1); + mLineOffsets[i] = yOff; + } + } + + inline void setFont(uint8_t line) { + switch (line) { + case 0: mDisplay->setFont((mIsLarge) ? u8g2_font_ncenB14_tr : u8g2_font_lubBI14_tr); break; + case 3: mDisplay->setFont(u8g2_font_5x8_tr); break; + default: mDisplay->setFont((mIsLarge) ? u8g2_font_ncenB10_tr : u8g2_font_5x8_tr); break; } - /* u8g2_font_open_iconic_embedded_2x_t 'D' + 'G' + 'J' */ - mDisplay.clear(); - mDisplay.firstPage(); - do { - #ifdef ENA_NOKIA - if(ucnt) { - //=====> Actual Production - mDisplay.drawXBMP(10,1,8,17,bmp_arrow); - mDisplay.setFont(u8g2_font_logisoso16_tr); - mDisplay.setCursor(25,17); - if (totalActual>999){ - sprintf(fmtText,"%2.1f",(totalActual/1000)); - mDisplay.print(String(fmtText)+F(" kW")); - } else { - sprintf(fmtText,"%3.0f",totalActual); - mDisplay.print(String(fmtText)+F(" W")); - } - //<======================= - } - else - { - //=====> Offline - mDisplay.setFont(u8g2_font_logisoso16_tr ); - mDisplay.setCursor(10,17); - mDisplay.print(String(F("offline"))); - //<======================= - - } - mDisplay.drawHLine(2,20,78); - mDisplay.setFont(u8g2_font_5x8_tr); - mDisplay.setCursor(5,29); - if (( num_inv < 2 ) || !(mExtra%2)) - { - sprintf(fmtText,"%4.0f",totalYieldToday); - mDisplay.print(F("today ")+String(fmtText)+F(" Wh")); - mDisplay.setCursor(5,37); - sprintf(fmtText,"%.1f",totalYield); - mDisplay.print(F("total ")+String(fmtText)+F(" kWh")); - } - else - { - int id1=(mExtra/2)%(num_inv-1); - if( pow_i[id1] ) - mDisplay.print(F("#")+String(id1+1)+F(" ")+String(pow_i[id1])+F(" W")); - else - mDisplay.print(F("#")+String(id1+1)+F(" -----")); - mDisplay.setCursor(5,37); - if( pow_i[id1+1] ) - mDisplay.print(F("#")+String(id1+2)+F(" ")+String(pow_i[id1+1])+F(" W")); - else - mDisplay.print(F("#")+String(id1+2)+F(" -----")); - } - if ( !(mExtra%10) && ip ) { - mDisplay.setCursor(5,47); - mDisplay.print(ip.toString()); - } - else { - mDisplay.setCursor(5,47); - mDisplay.print(timeStr); - } - #else // ENA_SSD1306 - mDisplay.setContrast(mCfg->contrast); - // pxZittern in +x (0 - 8 px) - int ex = 2*( mExtra % 5 ); - mDisplay.drawXBM(100+ex,2,16,16,bmp_logo); - mDisplay.setFont(u8g2_font_ncenB08_tr); - if(ucnt) { - //=====> Actual Production - mDisplay.setPowerSave(false); - displaySleep=false; - mDisplay.setFont(u8g2_font_logisoso18_tr); - mDisplay.drawXBM(10+ex,2,8,17,bmp_arrow); - mDisplay.setCursor(25+ex,20); - if (totalActual>999){ - sprintf(fmtText,"%2.1f",(totalActual/1000)); - mDisplay.print(String(fmtText)+F(" kW")); - } else { - sprintf(fmtText,"%3.0f",totalActual); - mDisplay.print(String(fmtText)+F(" W")); - } - //<======================= - } - else - { - //=====> Offline - if(!displaySleep) { - displaySleepTimer = millis(); - displaySleep=true; - } - mDisplay.setFont(u8g2_font_logisoso18_tr); - mDisplay.setCursor(10+ex,20); - mDisplay.print(String(F("offline"))); - if(mCfg->pwrSaveAtIvOffline) { - if ((millis() - displaySleepTimer) > displaySleepDelay) - mDisplay.setPowerSave(true); - } - //<======================= - } - mDisplay.drawLine(2+ex, 23, 123, 23); - mDisplay.setFont(u8g2_font_ncenB10_tr); - mDisplay.setCursor(2+ex,36); - if (( num_inv < 2 ) || !(mExtra%2)) - { - //=====> Today & Total Production - sprintf(fmtText,"%5.0f",totalYieldToday); - mDisplay.print(F("today: ")+String(fmtText)+F(" Wh")); - mDisplay.setCursor(2+ex,50); - sprintf(fmtText,"%.1f",totalYield); - mDisplay.print(F("total: ")+String(fmtText)+F(" kWh")); - //<======================= - } else { - int id1=(mExtra/2)%(num_inv-1); - if( pow_i[id1] ) - mDisplay.print(F("#")+String(id1+1)+F(" ")+String(pow_i[id1])+F(" W")); - else - mDisplay.print(F("#")+String(id1+1)+F(" -----")); - mDisplay.setCursor(5+ex,50); - if( pow_i[id1+1] ) - mDisplay.print(F("#")+String(id1+2)+F(" ")+String(pow_i[id1+1])+F(" W")); - else - mDisplay.print(F("#")+String(id1+2)+F(" -----")); - } - mDisplay.setFont(u8g2_font_5x8_tr); - mDisplay.setCursor(5+ex,63); - if ( !(mExtra%10) && ip ) - mDisplay.print(ip.toString()); - else - mDisplay.print(timeStr); - #endif - mDisplay.sendBuffer(); - } while( mDisplay.nextPage() ); - delay(200); - mExtra++; + } + + void printText(const char* text, uint8_t line, uint8_t dispX = 5) { + if(!mIsLarge) + dispX = 5; + setFont(line); + if(mCfg->pxShift) + dispX += (_mExtra % 7); // add pixel movement + mDisplay->drawStr(dispX, mLineOffsets[line], text); } // private member variables - #ifdef ENA_NOKIA - U8G2_PCD8544_84X48_1_4W_HW_SPI mDisplay; - #elif defined(ENA_SSD1306) - U8G2_SSD1306_128X64_NONAME_F_HW_I2C mDisplay; - #elif defined(ENA_SH1106) - U8G2_SH1106_128X64_NONAME_F_HW_I2C mDisplay; - #endif - int mExtra; + U8G2* mDisplay; + + uint8_t _mExtra; + uint16_t mTimeout; // interval at which to power save (milliseconds) + char _fmtText[32]; + bool mNewPayload; - float mTotal[ MAX_NUM_INVERTERS ]; - float mToday[ MAX_NUM_INVERTERS ]; + bool mIsLarge; + uint8_t mLoopCnt; uint32_t *mUtcTs; - int mLastHour; + uint8_t mLineOffsets[5]; display_t *mCfg; HMSYSTEM *mSys; Timezone mCE; - bool displaySleep; - uint32_t displaySleepTimer; - const uint32_t displaySleepDelay= 60000; }; -#endif #endif /*__MONOCHROME_DISPLAY__*/ diff --git a/src/utils/dbg.h b/src/utils/dbg.h index 7c956ef6..4f765ca6 100644 --- a/src/utils/dbg.h +++ b/src/utils/dbg.h @@ -5,7 +5,7 @@ #ifndef __DBG_H__ #define __DBG_H__ -#if defined(F) //defined(ESP32) && +#if defined(F) && defined(ESP32) #undef F #define F(sl) (sl) #endif diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 5461746d..c8025464 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -14,7 +14,7 @@ #include "../appInterface.h" -#if defined(F) //defined(ESP32) && +#if defined(F) && defined(ESP32) #undef F #define F(sl) (sl) #endif @@ -354,6 +354,16 @@ class RestApi { ah::ip2Char(mConfig->sys.ip.gateway, buf); obj[F("gateway")] = String(buf); } + void getDisplay(JsonObject obj) { + obj[F("disp_type")] = (uint8_t)mConfig->plugin.display.type; + obj[F("disp_pwr")] = (bool)mConfig->plugin.display.pwrSaveAtIvOffline; + obj[F("logo_en")] = (bool)mConfig->plugin.display.logoEn; + obj[F("px_shift")] = (bool)mConfig->plugin.display.pxShift; + obj[F("contrast")] = (uint8_t)mConfig->plugin.display.contrast; + obj[F("pinDisp0")] = mConfig->plugin.display.pin0; + obj[F("pinDisp1")] = mConfig->plugin.display.pin1; + } + void getMenu(JsonObject obj) { uint8_t i = 0; uint16_t mask = (mApp->getProtection()) ? mConfig->sys.protectionMask : 0; @@ -461,6 +471,7 @@ class RestApi { getRadio(obj.createNestedObject(F("radio"))); getSerial(obj.createNestedObject(F("serial"))); getStaticIp(obj.createNestedObject(F("static_ip"))); + getDisplay(obj.createNestedObject(F("display"))); } void getNetworks(JsonObject obj) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 1f9f81ea..025b3ce7 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -165,7 +165,7 @@
            System Config -

            Pinout (Wemos)

            +

            Pinout

            Radio (NRF24L01+)

            @@ -181,6 +181,25 @@
            + +
            +
            + Display Config +
            + +
            + +
            + +
            + + + +

            Pinout

            +
            +
            +
            +
            @@ -221,6 +240,56 @@ var highestId = 0; var maxInv = 0; + var esp8266pins = [ + [255, "off / default"], + [0, "D3 (GPIO0)"], + [1, "TX (GPIO1)"], + [2, "D4 (GPIO2)"], + [3, "RX (GPIO3)"], + [4, "D2 (GPIO4, SDA)"], + [5, "D1 (GPIO5, SCL)"], + [6, "GPIO6"], + [7, "GPIO7"], + [8, "GPIO8"], + [9, "GPIO9"], + [10, "GPIO10"], + [11, "GPIO11"], + [12, "D6 (GPIO12)"], + [13, "D7 (GPIO13)"], + [14, "D5 (GPIO14)"], + [15, "D8 (GPIO15)"], + [16, "D0 (GPIO16 - no IRQ!)"] + ]; + var esp32pins = [ + [255, "off / default"], + [0, "GPIO0"], + [1, "TX (GPIO1)"], + [2, "GPIO2 (LED)"], + [3, "RX (GPIO3)"], + [4, "GPIO4"], + [5, "GPIO5"], + [12, "GPIO12"], + [13, "GPIO13"], + [14, "GPIO14"], + [15, "GPIO15"], + [16, "GPIO16"], + [17, "GPIO17"], + [18, "GPIO18"], + [19, "GPIO19"], + [21, "GPIO21 (SDA)"], + [22, "GPIO22 (SCL)"], + [23, "GPIO23"], + [25, "GPIO25"], + [26, "GPIO26"], + [27, "GPIO27"], + [32, "GPIO32"], + [33, "GPIO33"], + [34, "GPIO34"], + [35, "GPIO35"], + [36, "VP (GPIO36)"], + [39, "VN (GPIO39)"] + ]; + const re = /11[2,4,6]1.*/; document.getElementById("btnAdd").addEventListener("click", function() { @@ -443,59 +512,7 @@ pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['led0', 'pinLed0'], ['led1', 'pinLed1']]; for(p of pins) { e.appendChild(lbl(p[1], p[0].toUpperCase())); - if("ESP8266" == type) { - e.appendChild(sel(p[1], [ - [255, "off / default"], - [0, "D3 (GPIO0)"], - [1, "TX (GPIO1)"], - [2, "D4 (GPIO2)"], - [3, "RX (GPIO3)"], - [4, "D2 (GPIO4)"], - [5, "D1 (GPIO5)"], - [6, "GPIO6"], - [7, "GPIO7"], - [8, "GPIO8"], - [9, "GPIO9"], - [10, "GPIO10"], - [11, "GPIO11"], - [12, "D6 (GPIO12)"], - [13, "D7 (GPIO13)"], - [14, "D5 (GPIO14)"], - [15, "D8 (GPIO15)"], - [16, "D0 (GPIO16 - no IRQ!)"] - ], obj[p[0]])); - } - else { - e.appendChild(sel(p[1], [ - [255, "off / default"], - [0, "GPIO0"], - [1, "TX (GPIO1)"], - [2, "GPIO2 (LED)"], - [3, "RX (GPIO3)"], - [4, "GPIO4"], - [5, "GPIO5"], - [12, "GPIO12"], - [13, "GPIO13"], - [14, "GPIO14"], - [15, "GPIO15"], - [16, "GPIO16"], - [17, "GPIO17"], - [18, "GPIO18"], - [19, "GPIO19"], - [21, "GPIO21"], - [22, "GPIO22"], - [23, "GPIO23"], - [25, "GPIO25"], - [26, "GPIO26"], - [27, "GPIO27"], - [32, "GPIO32"], - [33, "GPIO33"], - [34, "GPIO34"], - [35, "GPIO35"], - [36, "VP (GPIO36)"], - [39, "VN (GPIO39)"] - ], obj[p[0]])); - } + e.appendChild(sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]])); } } @@ -516,6 +533,29 @@ document.getElementsByName("serIntvl")[0].value = obj["interval"]; } + function parseDisplay(obj, type) { + for(var i of [["logoEn", "logo_en"], ["dispPwr", "disp_pwr"], ["dispPxSh", "px_shift"]]) + document.getElementsByName(i[0])[0].checked = obj[i[1]]; + + var e = document.getElementById("dispPins"); + pins = [['SCL / CS', 'pinDisp0'], ['SDA / DC', 'pinDisp1']]; + for(p of pins) { + e.appendChild(lbl(p[1], p[0].toUpperCase())); + e.appendChild(sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[1]])); + } + + var opts = [[0, "None"], [1, "Nokia5110"], [2, "SSD1306 0.96\""], [3, "SH1106 1.3\""]]; + document.getElementById("dispType").append( + lbl("dispType", "Type"), + sel("dispType", opts, obj["disp_type"]) + ); + + e = document.getElementById("contrast"); + for(var i = 30; i < 101; i += 2) { + e.appendChild(opt(i, i, (i == obj["contrast"]))); + } + } + function parse(root) { if(null != root) { parseMenu(root["menu"]); @@ -529,6 +569,7 @@ parsePinout(root["pinout"], root["system"]["esp_type"]); parseRadio(root["radio"]); parseSerial(root["serial"]); + parseDisplay(root["display"], root["system"]["esp_type"]); } } @@ -555,7 +596,7 @@ hiddenInput = document.getElementById("disclaimer") hiddenInput.value = sessionStorage.getItem("gDisclaimer"); - getAjax("/api/setup", parse); + getAjax("http://10.20.3.44/api/setup", parse); diff --git a/src/web/web.h b/src/web/web.h index e80ff76f..4c96f8b9 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -562,6 +562,17 @@ class Web { // Needed to log TX buffers to serial console mSys->Radio.mSerialDebug = mConfig->serial.debug; } + + // display + mConfig->plugin.display.pwrSaveAtIvOffline = (request->arg("dispPwr") == "on"); + mConfig->plugin.display.logoEn = (request->arg("logoEn") == "on"); + mConfig->plugin.display.pxShift = (request->arg("dispPxSh") == "on"); + mConfig->plugin.display.type = request->arg("dispType").toInt(); + mConfig->plugin.display.contrast = request->arg("dispCont").toInt(); + mConfig->plugin.display.pin0 = request->arg("pinDisp0").toInt(); + mConfig->plugin.display.pin1 = request->arg("pinDisp1").toInt(); + + mApp->saveSettings(); if(request->arg("reboot") == "on") diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index c4fba044..11bf5ae0 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -11,7 +11,6 @@ // NTP CONFIG #define NTP_PACKET_SIZE 48 -#define NTP_RETRIES 5 //----------------------------------------------------------------------------- ahoywifi::ahoywifi() : mApIp(192, 168, 4, 1) {} @@ -26,7 +25,7 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mStaConn = DISCONNECTED; mCnt = 0; mScanActive = false; - mRetries = NTP_RETRIES; + mLastNtpFailed = false; #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); @@ -149,26 +148,25 @@ void ahoywifi::setupStation(void) { //----------------------------------------------------------------------------- -bool ahoywifi::getNtpTime(uint32_t *nxtTrig) { - if(0 != mRetries) { - DPRINTLN(DBG_INFO, "try to getNtpTime"); - *nxtTrig = 43200; // check again in 12h (if NTP was successful) - mRetries--; - } else if(0 != *mUtcTimestamp) { // time is availabe, but NTP not - *nxtTrig = 5; // check again 5s - mRetries = NTP_RETRIES; +bool ahoywifi::getNtpTime() { + if(mLastNtpFailed && (0 != *mUtcTimestamp)) { // time is available, but NTP not maybe it was set by "sync with browser" + mLastNtpFailed = false; return true; // true is necessary to enable all timers even if NTP was not reachable } - if(GOT_IP != mStaConn) + if(GOT_IP != mStaConn) { + mLastNtpFailed = true; return false; + } IPAddress timeServer; uint8_t buf[NTP_PACKET_SIZE]; uint8_t retry = 0; - if (WiFi.hostByName(mConfig->ntp.addr, timeServer) != 1) + if (WiFi.hostByName(mConfig->ntp.addr, timeServer) != 1) { + mLastNtpFailed = true; return false; + } mUdp.begin(mConfig->ntp.port); sendNTPpacket(timeServer); @@ -193,6 +191,7 @@ bool ahoywifi::getNtpTime(uint32_t *nxtTrig) { } DPRINTLN(DBG_INFO, F("[NTP]: getNtpTime failed")); + mLastNtpFailed = true; return false; } @@ -275,10 +274,10 @@ void ahoywifi::connectionEvent(WiFiStatus_t status) { if(mStaConn != CONNECTING) { mStaConn = DISCONNECTED; mCnt = 5; // try to reconnect in 5 sec + mLastNtpFailed = false; setupWifi(); // reconnect with AP / Station setup mAppWifiCb(false); DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); - mRetries = NTP_RETRIES; } break; diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 72a80d7b..292c6074 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -25,7 +25,7 @@ class ahoywifi { void setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb); void tickWifiLoop(void); - bool getNtpTime(uint32_t *nxtTrig); + bool getNtpTime(); void scanAvailNetworks(void); void getAvailNetworks(JsonObject obj); @@ -68,7 +68,7 @@ class ahoywifi { uint8_t mLoopCnt; bool mScanActive; - uint8_t mRetries; + bool mLastNtpFailed; }; #endif /*__AHOYWIFI_H__*/ From f78e417a94299b5992b886f12d552380dac617b0 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 21 Jan 2023 00:35:53 +0100 Subject: [PATCH 227/431] fix ip --- src/web/html/setup.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 025b3ce7..3bd8ef6e 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -596,7 +596,7 @@ hiddenInput = document.getElementById("disclaimer") hiddenInput.value = sessionStorage.getItem("gDisclaimer"); - getAjax("http://10.20.3.44/api/setup", parse); + getAjax("/api/setup", parse); From 67043285bcfd53fca093e0065e7145b297cbfd5e Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 21 Jan 2023 00:42:45 +0100 Subject: [PATCH 228/431] fix script --- scripts/getVersion.py | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/scripts/getVersion.py b/scripts/getVersion.py index 5f96f37f..4ecb714e 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -56,21 +56,6 @@ def readVersion(path, infile): src = path + ".pio/build/esp8266-release/firmware.bin" dst = path + "firmware/" + versionout os.rename(src, dst) - - versionout = version[:-1] + "_" + sha + "_esp8266_nokia5110.bin" - src = path + ".pio/build/esp8266-nokia5110/firmware.bin" - dst = path + "firmware/" + versionout - os.rename(src, dst) - - versionout = version[:-1] + "_" + sha + "_esp8266_ssd1306.bin" - src = path + ".pio/build/esp8266-ssd1306/firmware.bin" - dst = path + "firmware/" + versionout - os.rename(src, dst) - - versionout = version[:-1] + "_" + sha + "_esp8266_sh1106.bin" - src = path + ".pio/build/esp8266-sh1106/firmware.bin" - dst = path + "firmware/" + versionout - os.rename(src, dst) versionout = version[:-1] + "_" + sha + "_esp8285.bin" src = path + ".pio/build/esp8285-release/firmware.bin" @@ -83,21 +68,6 @@ def readVersion(path, infile): dst = path + "firmware/" + versionout os.rename(src, dst) - versionout = version[:-1] + "_" + sha + "_esp32_nokia5110.bin" - src = path + ".pio/build/esp32-wroom32-nokia5110/firmware.bin" - dst = path + "firmware/" + versionout - os.rename(src, dst) - - versionout = version[:-1] + "_" + sha + "_esp32_ssd1306.bin" - src = path + ".pio/build/esp32-wroom32-ssd1306/firmware.bin" - dst = path + "firmware/" + versionout - os.rename(src, dst) - - versionout = version[:-1] + "_" + sha + "_esp32_sh1106.bin" - src = path + ".pio/build/esp32-wroom32-sh1106/firmware.bin" - dst = path + "firmware/" + versionout - os.rename(src, dst) - # other ESP32 bin files src = path + ".pio/build/esp32-wroom32-release/" dst = path + "firmware/" From 2dbf732ddcbcadf653e3e797a81537d2007be2b4 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 21 Jan 2023 00:52:16 +0100 Subject: [PATCH 229/431] fix power limit not possible #607 --- src/CHANGES.md | 1 + src/hm/hmInverter.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 40cf5f8b..89fd4632 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -6,6 +6,7 @@ * fix wakeup issue, once wifi was lost during night the communication didn't start in the morning * reenabled FlashStringHelper because of lacking RAM * complete rewrite of monochrome display class, thx to @dAjaY85 -> displays are now configurable in setup +* fix power limit not possible #607 ## 0.5.74 * improved payload handling (retransmit all fragments on CRC error) diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index ab86965d..3cdeb101 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -282,6 +282,7 @@ class Inverter { else if (rec->assign == InfoAssignment) { DPRINTLN(DBG_DEBUG, "add info"); // eg. fw version ... + isConnected = true; } else if (rec->assign == SystemConfigParaAssignment) { DPRINTLN(DBG_DEBUG, "add config"); @@ -289,7 +290,6 @@ class Inverter { if (getPosByChFld(0, FLD_ACT_ACTIVE_PWR_LIMIT, rec) == pos){ actPowerLimit = rec->record[pos]; DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit, 1)); - isConnected = true; } } else if (rec->assign == AlarmDataAssignment) { From 7ceaa7944f5c0841acdc6cd680e82019b4457544 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 21 Jan 2023 23:25:17 +0100 Subject: [PATCH 230/431] reduce MQTT retry interval from maximum speed to one second fixed homeassistant autodiscovery #565 --- src/CHANGES.md | 4 ++ src/defines.h | 2 +- .../MonochromeDisplay/MonochromeDisplay.h | 5 +-- src/publisher/pubMqtt.h | 41 ++++++++++++++----- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 89fd4632..f1b217dd 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,10 @@ (starting from release version `0.5.66`) +## 0.5.76 +* reduce MQTT retry interval from maximum speed to one second +* fixed homeassistant autodiscovery #565 + ## 0.5.75 * fix wakeup issue, once wifi was lost during night the communication didn't start in the morning * reenabled FlashStringHelper because of lacking RAM diff --git a/src/defines.h b/src/defines.h index 544507ae..a5f108de 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 75 +#define VERSION_PATCH 76 //------------------------------------- typedef struct { diff --git a/src/plugins/MonochromeDisplay/MonochromeDisplay.h b/src/plugins/MonochromeDisplay/MonochromeDisplay.h index 7666abfb..f4e1a69c 100644 --- a/src/plugins/MonochromeDisplay/MonochromeDisplay.h +++ b/src/plugins/MonochromeDisplay/MonochromeDisplay.h @@ -43,8 +43,6 @@ static TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central Eu template class MonochromeDisplay { public: - uint8_t dispContrast = 60; - MonochromeDisplay() : mCE(CEST, CET) {} void setup(display_t *cfg, HMSYSTEM *sys, uint32_t *utcTs, uint8_t disp_reset, const char *version) { @@ -75,6 +73,7 @@ class MonochromeDisplay { mDisplay->clearBuffer(); mDisplay->setContrast(mCfg->contrast); printText("Ahoy!", 0, 35); + printText("ahoydtu.de", 2, 20); printText(version, 3, 46); mDisplay->sendBuffer(); } @@ -193,7 +192,7 @@ class MonochromeDisplay { void printText(const char* text, uint8_t line, uint8_t dispX = 5) { if(!mIsLarge) - dispX = 5; + dispX = (line == 0) ? 10 : 5; setFont(line); if(mCfg->pxShift) dispX += (_mExtra % 7); // add pixel movement diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index bc3ecc7a..2cd175e4 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -46,6 +46,7 @@ class PubMqtt { mSys = sys; mUtcTimestamp = utcTs; mIntervalTimeout = 1; + mReconnectRequest = false; snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); @@ -66,6 +67,7 @@ class PubMqtt { } void connect() { + mReconnectRequest = false; if(!mClient.connected()) mClient.connect(); } @@ -80,7 +82,10 @@ class PubMqtt { sendIvData(); } } - + if(mReconnectRequest) { + connect(); + return; + } } void tickerMinute() { @@ -147,12 +152,21 @@ class PubMqtt { if(!mClient.connected()) return; - if(addTopic) { - String topic = String(mCfgMqtt->topic) + "/" + String(subTopic); - mClient.publish(topic.c_str(), QOS_0, retained, payload); - } - else - mClient.publish(subTopic, QOS_0, retained, payload); + String topic = ""; + if(addTopic) + topic = String(mCfgMqtt->topic) + "/"; + topic += String(subTopic); + + do { + if(0 != mClient.publish(topic.c_str(), QOS_0, retained, payload)) + break; + if(!mClient.connected()) + break; + + mClient.loop(); + yield(); + } while(1); + mTxCnt++; } @@ -181,7 +195,7 @@ class PubMqtt { void sendDiscoveryConfig(void) { DPRINTLN(DBG_VERBOSE, F("sendMqttDiscoveryConfig")); - char topic[64], buffer[512], name[32], uniq_id[32]; + char topic[64], name[32], uniq_id[32]; DynamicJsonDocument doc(512); for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); @@ -221,8 +235,12 @@ class PubMqtt { doc[F("stat_cla")] = String(stateCls); snprintf(topic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec)); - serializeJson(doc, buffer); - publish(topic, buffer, true, false); + size_t size = measureJson(doc) + 1; + char *buf = new char[size]; + memset(buf, 0, size); + serializeJson(doc, buf, size); + publish(topic, buf, true, false); + delete[] buf; } yield(); @@ -258,7 +276,7 @@ class PubMqtt { switch (reason) { case espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED: DBGPRINTLN(F("TCP disconnect")); - connect(); + mReconnectRequest = true; break; case espMqttClientTypes::DisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION: DBGPRINTLN(F("wrong protocol version")); @@ -561,6 +579,7 @@ class PubMqtt { std::queue mSendList; subscriptionCb mSubscriptionCb; bool mIvAvail; // shows if at least one inverter is available + bool mReconnectRequest; uint8_t mLastIvState[MAX_NUM_INVERTERS]; uint16_t mIntervalTimeout; From 9cedb41ff4ec19049dfde7f9e478a6a5c78d3854 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 22 Jan 2023 01:04:33 +0100 Subject: [PATCH 231/431] implemented `getNTPTime` improvements #609 partially #611 added alarm messages to MQTT #177, #600, #608 --- src/CHANGES.md | 2 ++ src/app.cpp | 10 +++++++--- src/app.h | 5 ++--- src/hm/hmInverter.h | 13 ++++++------- src/hm/payload.h | 33 +++++++++++++++++++++++++-------- src/publisher/pubMqtt.h | 27 +++++++++++++++++++++++++++ src/utils/handler.h | 33 --------------------------------- src/wifi/ahoywifi.cpp | 19 ++++--------------- src/wifi/ahoywifi.h | 7 +++++-- 9 files changed, 78 insertions(+), 71 deletions(-) delete mode 100644 src/utils/handler.h diff --git a/src/CHANGES.md b/src/CHANGES.md index f1b217dd..1d359129 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -5,6 +5,8 @@ ## 0.5.76 * reduce MQTT retry interval from maximum speed to one second * fixed homeassistant autodiscovery #565 +* implemented `getNTPTime` improvements #609 partially #611 +* added alarm messages to MQTT #177, #600, #608 ## 0.5.75 * fix wakeup issue, once wifi was lost during night the communication didn't start in the morning diff --git a/src/app.cpp b/src/app.cpp index 7f4071a2..0d88847e 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -28,7 +28,7 @@ void app::setup() { mSys = new HmSystemType(); mSys->enableDebug(); mSys->setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); - mPayload.addListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); + mPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); #if defined(AP_ONLY) mInnerLoopCb = std::bind(&app::loopStandard, this); @@ -54,6 +54,7 @@ void app::setup() { if (mMqttEnabled) { mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mTimestamp); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); + mPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } #endif setupLed(); @@ -134,6 +135,8 @@ void app::onWifi(bool gotIp) { mMqttReconnect = true; mSunrise = 0; // needs to be set to 0, to reinstall sunrise and ivComm tickers! once(std::bind(&app::tickNtpUpdate, this), 2, "ntp2"); + if(WIFI_AP == WiFi.getMode()) + everySec(std::bind(&ahoywifi::tickWifiLoop, &mWifi), "wifiL"); } else { mInnerLoopCb = std::bind(&app::loopWifi, this); @@ -154,7 +157,8 @@ void app::regularTickers(void) { //----------------------------------------------------------------------------- void app::tickNtpUpdate(void) { uint32_t nxtTrig = 5; // default: check again in 5 sec - if (mWifi.getNtpTime()) { + bool isOK = mWifi.getNtpTime(); + if (isOK || mTimestamp != 0) { if (mMqttReconnect && mMqttEnabled) { mMqtt.connect(); everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS"); @@ -166,7 +170,7 @@ void app::tickNtpUpdate(void) { mMqttReconnect = false; } - nxtTrig = 43200; // check again in 12h + nxtTrig = isOK ? 43200 : 60; // depending on NTP update success check again in 12 h or in 1 min if((mSunrise == 0) && (mConfig->sun.lat) && (mConfig->sun.lon)) { mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; diff --git a/src/app.h b/src/app.h index 0466daf8..d51c9209 100644 --- a/src/app.h +++ b/src/app.h @@ -195,9 +195,8 @@ class app : public IApp, public ah::Scheduler { #if !defined(AP_ONLY) mMqtt.payloadEventListener(cmd); #endif - #if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) - mMonoDisplay.payloadEventListener(cmd); - #endif + if(mConfig->plugin.display.type != 0) + mMonoDisplay.payloadEventListener(cmd); } void mqttSubRxCb(JsonObject obj); diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 3cdeb101..640aeae3 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -286,7 +286,6 @@ class Inverter { } else if (rec->assign == SystemConfigParaAssignment) { DPRINTLN(DBG_DEBUG, "add config"); - // get at least the firmware version and save it to the inverter object if (getPosByChFld(0, FLD_ACT_ACTIVE_PWR_LIMIT, rec) == pos){ actPowerLimit = rec->record[pos]; DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit, 1)); @@ -451,10 +450,10 @@ class Inverter { } } - bool parseAlarmLog(uint8_t id, uint8_t pyld[], uint8_t len) { + uint16_t parseAlarmLog(uint8_t id, uint8_t pyld[], uint8_t len, uint32_t *start, uint32_t *endTime) { uint8_t startOff = 2 + id * ALARM_LOG_ENTRY_SIZE; if((startOff + ALARM_LOG_ENTRY_SIZE) > len) - return false; + return 0; uint16_t wCode = ((uint16_t)pyld[startOff]) << 8 | pyld[startOff+1]; uint32_t startTimeOffset = 0, endTimeOffset = 0; @@ -464,11 +463,11 @@ class Inverter { if (((wCode >> 12) & 0x01) == 1) // check if is AM or PM endTimeOffset = 12 * 60 * 60; - uint32_t start = (((uint16_t)pyld[startOff + 4] << 8) | ((uint16_t)pyld[startOff + 5])) + startTimeOffset; - uint32_t end = (((uint16_t)pyld[startOff + 6] << 8) | ((uint16_t)pyld[startOff + 7])) + endTimeOffset; + *start = (((uint16_t)pyld[startOff + 4] << 8) | ((uint16_t)pyld[startOff + 5])) + startTimeOffset; + *endTime = (((uint16_t)pyld[startOff + 6] << 8) | ((uint16_t)pyld[startOff + 7])) + endTimeOffset; - DPRINTLN(DBG_INFO, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(start) + ", end: " + ah::getTimeStr(end)); - return true; + DPRINTLN(DBG_INFO, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(*start) + ", end: " + ah::getTimeStr(*endTime)); + return pyld[startOff+1]; } String getAlarmStr(uint16_t alarmCode) { diff --git a/src/hm/payload.h b/src/hm/payload.h index 093edbd3..7e66eb76 100644 --- a/src/hm/payload.h +++ b/src/hm/payload.h @@ -8,7 +8,6 @@ #include "../utils/dbg.h" #include "../utils/crc.h" -#include "../utils/handler.h" #include "../config/config.h" #include @@ -29,12 +28,13 @@ typedef struct { typedef std::function payloadListenerType; +typedef std::function alarmListenerType; template -class Payload : public Handler { +class Payload { public: - Payload() : Handler() {} + Payload() {} void setup(IApp *app, HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { mApp = app; @@ -53,10 +53,12 @@ class Payload : public Handler { mSerialDebug = enable; } - void notify(uint8_t val) { - for(typename std::list::iterator it = mList.begin(); it != mList.end(); ++it) { - (*it)(val); - } + void addPayloadListener(payloadListenerType cb) { + mCbPayload = cb; + } + + void addAlarmListener(alarmListenerType cb) { + mCbAlarm = cb; } void loop() { @@ -258,9 +260,13 @@ class Payload : public Handler { if(AlarmData == mPayload[iv->id].txCmd) { uint8_t i = 0; + uint16_t code; + uint32_t start, end; while(1) { - if(!iv->parseAlarmLog(i++, payload, payloadLen)) + code = iv->parseAlarmLog(i++, payload, payloadLen, &start, &end); + if(0 == code) break; + (mCbAlarm)(code, start, end); yield(); } } @@ -279,6 +285,14 @@ class Payload : public Handler { } private: + void notify(uint8_t val) { + (mCbPayload)(val); + } + + void notify(uint16_t code, uint32_t start, uint32_t endTime) { + (mCbAlarm)(code, start, endTime); + } + bool build(uint8_t id, bool *complete) { DPRINTLN(DBG_VERBOSE, F("build")); uint16_t crc = 0xffff, crcRcv = 0x0000; @@ -329,6 +343,9 @@ class Payload : public Handler { invPayload_t mPayload[MAX_NUM_INVERTERS]; bool mSerialDebug; Inverter<> *mHighPrioIv; + + alarmListenerType mCbAlarm; + payloadListenerType mCbPayload; }; #endif /*__PAYLOAD_H_*/ diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 2cd175e4..11744ab6 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -26,6 +26,13 @@ typedef std::function subscriptionCb; +struct alarm_t { + uint16_t code; + uint32_t start; + uint32_t end; + alarm_t(uint16_t c, uint32_t s, uint32_t e) : code(c), start(s), end(e) {} +}; + template class PubMqtt { public: @@ -148,6 +155,12 @@ class PubMqtt { } } + void alarmEventListener(uint16_t code, uint32_t start, uint32_t endTime) { + if(mClient.connected()) { + mAlarmList.push(alarm_t(code, start, endTime)); + } + } + void publish(const char *subTopic, const char *payload, bool retained = false, bool addTopic = true) { if(!mClient.connected()) return; @@ -436,6 +449,19 @@ class PubMqtt { return totalComplete; } + void sendAlarmData() { + if(mAlarmList.empty()) + return; + Inverter<> *iv = mSys->getInverterByPos(0, false); + while(!mAlarmList.empty()) { + alarm_t alarm = mAlarmList.front(); + publish("alarm", iv->getAlarmStr(alarm.code).c_str()); + publish("alarm_start", String(alarm.start).c_str()); + publish("alarm_end", String(alarm.end).c_str()); + mAlarmList.pop(); + } + } + void sendIvData(bool sendTotals = true) { if(mSendList.empty()) return; @@ -577,6 +603,7 @@ class PubMqtt { uint32_t *mUtcTimestamp; uint32_t mRxCnt, mTxCnt; std::queue mSendList; + std::queue mAlarmList; subscriptionCb mSubscriptionCb; bool mIvAvail; // shows if at least one inverter is available bool mReconnectRequest; diff --git a/src/utils/handler.h b/src/utils/handler.h deleted file mode 100644 index 51d64c0d..00000000 --- a/src/utils/handler.h +++ /dev/null @@ -1,33 +0,0 @@ -//----------------------------------------------------------------------------- -// 2022 Ahoy, https://ahoydtu.de -// Lukas Pusch, lukas@lpusch.de -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ -//----------------------------------------------------------------------------- - -#ifndef __HANDLER_H__ -#define __HANDLER_H__ - -#include -#include -#include - -template -class Handler { - public: - Handler() {} - - void addListener(TYPE f) { - mList.push_back(f); - } - - /*virtual void notify(void) { - for(typename std::list::iterator it = mList.begin(); it != mList.end(); ++it) { - (*it)(); - } - }*/ - - protected: - std::list mList; -}; - -#endif /*__HANDLER_H__*/ diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 11bf5ae0..6f7725eb 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -25,7 +25,6 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mStaConn = DISCONNECTED; mCnt = 0; mScanActive = false; - mLastNtpFailed = false; #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); @@ -70,6 +69,7 @@ void ahoywifi::tickWifiLoop() { DBGPRINTLN(F("AP client connected")); welcome(mApIp.toString()); WiFi.mode(WIFI_AP); + mAppWifiCb(true); } return; } @@ -148,25 +148,16 @@ void ahoywifi::setupStation(void) { //----------------------------------------------------------------------------- -bool ahoywifi::getNtpTime() { - if(mLastNtpFailed && (0 != *mUtcTimestamp)) { // time is available, but NTP not maybe it was set by "sync with browser" - mLastNtpFailed = false; - return true; // true is necessary to enable all timers even if NTP was not reachable - } - - if(GOT_IP != mStaConn) { - mLastNtpFailed = true; +bool ahoywifi::getNtpTime(void) { + if(GOT_IP != mStaConn) return false; - } IPAddress timeServer; uint8_t buf[NTP_PACKET_SIZE]; uint8_t retry = 0; - if (WiFi.hostByName(mConfig->ntp.addr, timeServer) != 1) { - mLastNtpFailed = true; + if (WiFi.hostByName(mConfig->ntp.addr, timeServer) != 1) return false; - } mUdp.begin(mConfig->ntp.port); sendNTPpacket(timeServer); @@ -191,7 +182,6 @@ bool ahoywifi::getNtpTime() { } DPRINTLN(DBG_INFO, F("[NTP]: getNtpTime failed")); - mLastNtpFailed = true; return false; } @@ -274,7 +264,6 @@ void ahoywifi::connectionEvent(WiFiStatus_t status) { if(mStaConn != CONNECTING) { mStaConn = DISCONNECTED; mCnt = 5; // try to reconnect in 5 sec - mLastNtpFailed = false; setupWifi(); // reconnect with AP / Station setup mAppWifiCb(false); DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 292c6074..7155a427 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -25,7 +25,7 @@ class ahoywifi { void setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb); void tickWifiLoop(void); - bool getNtpTime(); + bool getNtpTime(void); void scanAvailNetworks(void); void getAvailNetworks(JsonObject obj); @@ -68,7 +68,10 @@ class ahoywifi { uint8_t mLoopCnt; bool mScanActive; - bool mLastNtpFailed; + + void sortRSSI(int *sort, int n); + void getBSSIDs(void); + std::list mBSSIDList; }; #endif /*__AHOYWIFI_H__*/ From 2610f1adfba51f54225067de33854ab49d853ae1 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 22 Jan 2023 01:10:54 +0100 Subject: [PATCH 232/431] fix ESP32 compile --- src/publisher/pubMqtt.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 11744ab6..f066a38a 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -175,8 +175,9 @@ class PubMqtt { break; if(!mClient.connected()) break; - + #if defined(ESP8266) mClient.loop(); + #endif yield(); } while(1); From 96d64faf627582376fa3e144de79789095f8ec02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knuti=5Fin=5FP=C3=A4se?= Date: Wed, 25 Jan 2023 11:49:13 +0100 Subject: [PATCH 233/431] RPi: send value irradiation to VZ and MQTT to send all meassured and calculated values to Volkszaehler and to mqtt change some logging levels for better differentiation change frequency as part of AC phase --- tools/rpi/ahoy.yml.example | 28 +++++- tools/rpi/hoymiles/__init__.py | 2 +- tools/rpi/hoymiles/__main__.py | 6 +- tools/rpi/hoymiles/decoders/__init__.py | 36 ++++--- tools/rpi/hoymiles/outputs.py | 126 +++++++++++++++--------- 5 files changed, 132 insertions(+), 66 deletions(-) diff --git a/tools/rpi/ahoy.yml.example b/tools/rpi/ahoy.yml.example index 7cb0c3b7..c157e826 100644 --- a/tools/rpi/ahoy.yml.example +++ b/tools/rpi/ahoy.yml.example @@ -44,9 +44,7 @@ ahoy: - serial: 114172220003 url: 'http://localhost/middleware/' channels: - - type: 'temperature' - uid: 'ad578a40-1d97-11ed-8e8b-fda01a416575' - - type: 'frequency' + - type: 'ac_frequency0' uid: '' - type: 'ac_power0' uid: '7ca5ac50-1e41-11ed-927f-610c4cb2c69e' @@ -54,18 +52,42 @@ ahoy: uid: '9a38e2e0-1d94-11ed-b539-25f8607ac030' - type: 'ac_current0' uid: 'a9a4daf0-1e41-11ed-b68c-eb73eef3d21d' + - type: 'ac_reactive_power0' + uid: '' - type: 'dc_power0' uid: '38eb3ca0-1e53-11ed-b830-792e70a592fa' - type: 'dc_voltage0' uid: '' - type: 'dc_current0' uid: '' + - type: 'dc_energy_total0' + uid: '' + - type: 'dc_energy_daily0' + uid: 'c2a93ea0-9a4e-11ed-8000-7d82e3ac8959' + - type: 'dc_irradiation0' + uid: 'c2d887a0-9a4e-11ed-a7ac-0dab944fd82d' - type: 'dc_power1' uid: '51c0e9d0-1e53-11ed-b574-8bc81547eb8f' - type: 'dc_voltage1' uid: '' - type: 'dc_current1' uid: '' + - type: 'dc_energy_total1' + uid: '' + - type: 'dc_energy_daily1' + uid: 'c3c04df0-9a4e-11ed-82c6-a15a9aba54a3' + - type: 'dc_irradiation1' + uid: 'c3f3efd0-9a4e-11ed-9a77-3fd3187e6237' + - type: 'temperature' + uid: 'ad578a40-1d97-11ed-8e8b-fda01a416575' + - type: 'powerfactor' + uid: '' + - type: 'yield_total' + uid: '' + - type: 'yield_today' + uid: 'c4a76dd0-9a4e-11ed-b79f-2de013d39150' + - type: 'efficiency' + uid: 'c4d8e9c0-9a4e-11ed-9d9e-9737749e4b45' dtu: serial: 99978563001 diff --git a/tools/rpi/hoymiles/__init__.py b/tools/rpi/hoymiles/__init__.py index 4b46a95e..74ec9fd8 100644 --- a/tools/rpi/hoymiles/__init__.py +++ b/tools/rpi/hoymiles/__init__.py @@ -159,7 +159,7 @@ class ResponseDecoder(ResponseDecoderFactory): command = self.request_command c_datetime = self.time_rx.strftime("%Y-%m-%d %H:%M:%S.%f") - logging.debug(f'{c_datetime} model_decoder: {model}Decode{command.upper()}') + logging.info(f'{c_datetime} model_decoder: {model}Decode{command.upper()}') model_decoders = __import__('hoymiles.decoders') if hasattr(model_decoders, f'{model}Decode{command.upper()}'): diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index c5451fb0..1dfc8321 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -17,7 +17,7 @@ from suntimes import SunTimes import argparse import yaml from yaml.loader import SafeLoader -import paho.mqtt.client +# import paho.mqtt.client import hoymiles import logging @@ -174,7 +174,7 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): # get decoder object result = decoder.decode() if hoymiles.HOYMILES_DEBUG_LOGGING: - logging.debug(f'{c_datetime} Decoded: {result.__dict__()}') + logging.info(f'{c_datetime} Decoded: {result.__dict__()}') # check decoder object for output if isinstance(result, hoymiles.decoders.StatusResponse): @@ -284,7 +284,7 @@ if __name__ == '__main__': logging.error("Could not load config file. Try --help") sys.exit(2) except yaml.YAMLError as e_yaml: - logging.error('Failed to load config file {global_config.config_file}: {e_yaml}') + logging.error(f'Failed to load config file {global_config.config_file}: {e_yaml}') sys.exit(1) # read AHOY configuration file and prepare logging diff --git a/tools/rpi/hoymiles/decoders/__init__.py b/tools/rpi/hoymiles/decoders/__init__.py index 040f67ef..b46dbe48 100644 --- a/tools/rpi/hoymiles/decoders/__init__.py +++ b/tools/rpi/hoymiles/decoders/__init__.py @@ -93,7 +93,8 @@ class Response: class StatusResponse(Response): """Inverter StatusResponse object""" - e_keys = ['voltage','current','power','energy_total','energy_daily','powerfactor', 'reactive_power', 'irradiation'] + phase_keys = ['voltage','current','power','reactive_power','frequency'] + string_keys = ['voltage','current','power','energy_total','energy_daily', 'irradiation'] temperature = None frequency = None powerfactor = None @@ -125,7 +126,7 @@ class StatusResponse(Response): p_exists = False phase_id = len(phases) phase = {} - for key in self.e_keys: + for key in self.phase_keys: prop = f'ac_{key}_{phase_id}' if hasattr(self, prop): p_exists = True @@ -149,7 +150,7 @@ class StatusResponse(Response): s_exists = False string_id = len(strings) string = {} - for key in self.e_keys: + for key in self.string_keys: prop = f'dc_{key}_{string_id}' if hasattr(self, prop): s_exists = True @@ -170,14 +171,27 @@ class StatusResponse(Response): data['phases'] = self.phases data['strings'] = self.strings data['temperature'] = self.temperature - data['frequency'] = self.frequency data['powerfactor'] = self.powerfactor - data['event_count'] = self.event_count - data['time'] = self.time_rx - data['energy_total'] = 0.0 + data['yield_total'] = 0.0 + data['yield_today'] = 0.0 + for string in data['strings']: + data['yield_total'] += string['energy_total'] + data['yield_today'] += string['energy_daily'] + + ac_sum_power = 0.0 + for phase in data['phases']: + ac_sum_power += phase['power'] + dc_sum_power = 0.0 for string in data['strings']: - data['energy_total'] += string['energy_total'] + dc_sum_power += string['power'] + if dc_sum_power != 0: + data['efficiency'] = round(ac_sum_power * 100 / dc_sum_power, 2) + else: + data['efficiency'] = 0.0 + + data['event_count'] = self.event_count + data['time'] = self.time_rx return data @@ -469,7 +483,7 @@ class Hm300Decode0B(StatusResponse): """ Phase 1 watts """ return self.unpack('>H', 18)[0]/10 @property - def frequency(self): + def ac_frequency_0(self): """ Grid frequency in Hertz """ return self.unpack('>H', 16)[0]/100 @property @@ -568,7 +582,7 @@ class Hm600Decode0B(StatusResponse): """ Phase 1 watts """ return self.unpack('>H', 30)[0]/10 @property - def frequency(self): + def ac_frequency_0(self): """ Grid frequency in Hertz """ return self.unpack('>H', 28)[0]/100 @property @@ -729,7 +743,7 @@ class Hm1200Decode0B(StatusResponse): """ Phase 1 watts """ return self.unpack('>H', 50)[0]/10 @property - def frequency(self): + def ac_frequency_0(self): """ Grid frequency in Hertz """ return self.unpack('>H', 48)[0]/100 @property diff --git a/tools/rpi/hoymiles/outputs.py b/tools/rpi/hoymiles/outputs.py index 64763c37..18af494a 100644 --- a/tools/rpi/hoymiles/outputs.py +++ b/tools/rpi/hoymiles/outputs.py @@ -10,11 +10,6 @@ import logging from datetime import datetime, timezone from hoymiles.decoders import StatusResponse, HardwareInfoResponse -try: - from influxdb_client import InfluxDBClient -except ModuleNotFoundError: - pass - class OutputPluginFactory: def __init__(self, **params): """ @@ -59,10 +54,19 @@ class InfluxOutputPlugin(OutputPluginFactory): """ super().__init__(**params) + try: + from influxdb_client import InfluxDBClient + except ModuleNotFoundError: + ErrorText1 = f'Module "influxdb_client" for INFLUXDB necessary.' + ErrorText2 = f'Install module with command: python3 -m pip install influxdb_client' + print(ErrorText1, ErrorText2) + logging.error(ErrorText1) + logging.error(ErrorText2) + exit() + self._bucket = params.get('bucket', 'hoymiles/autogen') self._org = params.get('org', '') - self._measurement = params.get('measurement', - f'inverter,host={socket.gethostname()}') + self._measurement = params.get('measurement', f'inverter,host={socket.gethostname()}') client = InfluxDBClient(url, token, bucket=self._bucket) self.api = client.write_api() @@ -105,6 +109,7 @@ class InfluxOutputPlugin(OutputPluginFactory): data_stack.append(f'{measurement},phase={phase_id},type=current value={phase["current"]} {ctime}') data_stack.append(f'{measurement},phase={phase_id},type=power value={phase["power"]} {ctime}') data_stack.append(f'{measurement},phase={phase_id},type=Q_AC value={phase["reactive_power"]} {ctime}') + data_stack.append(f'{measurement},phase={phase_id},type=frequency value={phase["frequency"]:.3f} {ctime}') phase_id = phase_id + 1 # DC Data @@ -115,28 +120,23 @@ class InfluxOutputPlugin(OutputPluginFactory): data_stack.append(f'{measurement},string={string_id},type=power value={string["power"]:.2f} {ctime}') data_stack.append(f'{measurement},string={string_id},type=YieldDay value={string["energy_daily"]:.2f} {ctime}') data_stack.append(f'{measurement},string={string_id},type=YieldTotal value={string["energy_total"]/1000:.4f} {ctime}') - if 'irradiation' in string: - data_stack.append(f'{measurement},string={string_id},type=Irradiation value={string["irradiation"]:.2f} {ctime}') + data_stack.append(f'{measurement},string={string_id},type=Irradiation value={string["irradiation"]:.2f} {ctime}') string_id = string_id + 1 # Global if data['event_count'] is not None: data_stack.append(f'{measurement},type=total_events value={data["event_count"]} {ctime}') if data['powerfactor'] is not None: - data_stack.append(f'{measurement},type=pf value={data["powerfactor"]:f} {ctime}') - data_stack.append(f'{measurement},type=frequency value={data["frequency"]:.3f} {ctime}') - + data_stack.append(f'{measurement},type=PF_AC value={data["powerfactor"]:f} {ctime}') data_stack.append(f'{measurement},type=Temp value={data["temperature"]:.2f} {ctime}') - if data['energy_total'] is not None: - data_stack.append(f'{measurement},type=total value={data["energy_total"]/1000:.3f} {ctime}') + if data['yield_total'] is not None: + data_stack.append(f'{measurement},type=YieldTotal value={data["yield_total"]/1000:.3f} {ctime}') + if data['yield_today'] is not None: + data_stack.append(f'{measurement},type=YieldToday value={data["yield_today"]/1000:.3f} {ctime}') + data_stack.append(f'{measurement},type=Efficiency value={data["efficiency"]:.2f} {ctime}') self.api.write(self._bucket, self._org, data_stack) -try: - import paho.mqtt.client -except ModuleNotFoundError: - pass - class MqttOutputPlugin(OutputPluginFactory): """ Mqtt output plugin """ client = None @@ -164,6 +164,16 @@ class MqttOutputPlugin(OutputPluginFactory): """ super().__init__(**params) + try: + import paho.mqtt.client + except ModuleNotFoundError: + ErrorText1 = f'Module "paho.mqtt.client" for MQTT-output necessary.' + ErrorText2 = f'Install module with command: python3 -m pip install paho-mqtt' + print(ErrorText1, ErrorText2) + logging.error(ErrorText1) + logging.error(ErrorText2) + exit() + mqtt_client = paho.mqtt.client.Client() if config.get('useTLS',False): mqtt_client.tls_set() @@ -196,33 +206,41 @@ class MqttOutputPlugin(OutputPluginFactory): # AC Data phase_id = 0 + phase_sum_power = 0 for phase in data['phases']: - self.client.publish(f'{topic}/emeter/{phase_id}/power', phase['power']) self.client.publish(f'{topic}/emeter/{phase_id}/voltage', phase['voltage']) self.client.publish(f'{topic}/emeter/{phase_id}/current', phase['current']) + self.client.publish(f'{topic}/emeter/{phase_id}/power', phase['power']) self.client.publish(f'{topic}/emeter/{phase_id}/Q_AC', phase['reactive_power']) + self.client.publish(f'{topic}/emeter/{phase_id}/frequency', phase['frequency']) phase_id = phase_id + 1 + phase_sum_power += phase['power'] # DC Data string_id = 0 + string_sum_power = 0 for string in data['strings']: self.client.publish(f'{topic}/emeter-dc/{string_id}/voltage', string['voltage']) self.client.publish(f'{topic}/emeter-dc/{string_id}/current', string['current']) self.client.publish(f'{topic}/emeter-dc/{string_id}/power', string['power']) self.client.publish(f'{topic}/emeter-dc/{string_id}/YieldDay', string['energy_daily']) self.client.publish(f'{topic}/emeter-dc/{string_id}/YieldTotal', string['energy_total']/1000) - if 'irradiation' in string: - self.client.publish(f'{topic}/emeter-dc/{string_id}/Irradiation', string['irradiation']) + self.client.publish(f'{topic}/emeter-dc/{string_id}/Irradiation', string['irradiation']) string_id = string_id + 1 + string_sum_power += string['power'] # Global + if data['event_count'] is not None: + self.client.publish(f'{topic}/total_events', data['event_count']) if data['powerfactor'] is not None: - self.client.publish(f'{topic}/pf', data['powerfactor']) - self.client.publish(f'{topic}/frequency', data['frequency']) - + self.client.publish(f'{topic}/PF_AC', data['powerfactor']) self.client.publish(f'{topic}/Temp', data['temperature']) - if data['energy_total'] is not None: - self.client.publish(f'{topic}/total', data['energy_total']/1000) + if data['yield_total'] is not None: + self.client.publish(f'{topic}/YieldTotal', data['yield_total']/1000) + if data['yield_today'] is not None: + self.client.publish(f'{topic}/YieldToday', data['yield_today']/1000) + self.client.publish(f'{topic}/Efficiency', data['efficiency']) + elif isinstance(response, HardwareInfoResponse): self.client.publish(f'{topic}/Firmware/Version',\ @@ -236,12 +254,6 @@ class MqttOutputPlugin(OutputPluginFactory): else: raise ValueError('Data needs to be instance of StatusResponse or a instance of HardwareInfoResponse') -try: - import requests - import time -except ModuleNotFoundError: - pass - class VzInverterOutput: def __init__(self, config, session): self.session = session @@ -274,7 +286,8 @@ class VzInverterOutput: self.try_publish(ts, f'ac_voltage{phase_id}', phase['voltage']) self.try_publish(ts, f'ac_current{phase_id}', phase['current']) self.try_publish(ts, f'ac_power{phase_id}', phase['power']) - self.try_publish(ts, f'ac_Q{phase_id}', phase['reactive_power']) + self.try_publish(ts, f'ac_reactive_power{phase_id}', phase['reactive_power']) + self.try_publish(ts, f'ac_frequency{phase_id}', phase['frequency']) phase_id = phase_id + 1 # DC Data @@ -283,33 +296,39 @@ class VzInverterOutput: self.try_publish(ts, f'dc_voltage{string_id}', string['voltage']) self.try_publish(ts, f'dc_current{string_id}', string['current']) self.try_publish(ts, f'dc_power{string_id}', string['power']) - self.try_publish(ts, f'dc_YieldDay{string_id}', string['energy_daily']) - self.try_publish(ts, f'dc_YieldTotal{string_id}', string['energy_total']) - if 'irradiation' in string: - self.try_publish(ts, f'dc_Irradiation{string_id}', string['irradiation']) + self.try_publish(ts, f'dc_energy_daily{string_id}', string['energy_daily']) + self.try_publish(ts, f'dc_energy_total{string_id}', string['energy_total']) + self.try_publish(ts, f'dc_irradiation{string_id}', string['irradiation']) string_id = string_id + 1 # Global + if data['event_count'] is not None: + self.try_publish(ts, f'event_count', data['event_count']) if data['powerfactor'] is not None: self.try_publish(ts, f'powerfactor', data['powerfactor']) - self.try_publish(ts, f'frequency', data['frequency']) - - self.try_publish(ts, f'Temp', data['temperature']) - if data['energy_total'] is not None: - self.try_publish(ts, f'total', data['energy_total']) - + self.try_publish(ts, f'temperature', data['temperature']) + if data['yield_total'] is not None: + self.try_publish(ts, f'yield_total', data['yield_total']) + if data['yield_today'] is not None: + self.try_publish(ts, f'yield_today', data['yield_today']) + self.try_publish(ts, f'efficiency', data['efficiency']) def try_publish(self, ts, ctype, value): if not ctype in self.channels: + logging.warning(f'ctype \"{ctype}\" not found in ahoy.yml') return uid = self.channels[ctype] url = f'{self.baseurl}/data/{uid}.json?operation=add&ts={ts}&value={value}' try: r = self.session.get(url) - if r.status_code != 200: - raise ValueError('Could not send request (%s)' % url) - except requests.exceptions.ConnectionError as e: - raise ValueError('Could not send request (%s)' % e) + if r.status_code == 404: + logging.critical('VZ-DB not reachable, please check "middleware"') + if r.status_code == 400: + logging.critical('UUID not configured in VZ-DB') + elif r.status_code != 200: + raise ValueError(f'Transmit result {url}') + except ConnectionError as e: + raise ValueError(f'Could not connect VZ-DB {type(e)} {e.keys()}') class VolkszaehlerOutputPlugin(OutputPluginFactory): def __init__(self, config, **params): @@ -318,6 +337,17 @@ class VolkszaehlerOutputPlugin(OutputPluginFactory): """ super().__init__(**params) + try: + import requests + import time + except ModuleNotFoundError: + ErrorText1 = f'Module "requests" and "time" for VolkszaehlerOutputPlugin necessary.' + ErrorText2 = f'Install module with command: python3 -m pip install requests' + print(ErrorText1, ErrorText2) + logging.error(ErrorText1) + logging.error(ErrorText2) + exit(1) + self.session = requests.Session() self.inverters = dict() From 22ae6d2e22059ebf1d1eaf69c77433459040aaa5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 24 Jan 2023 22:12:23 +0100 Subject: [PATCH 234/431] fix wrong filename for automatically created manifest (online installer) #620 added rotate display feature #619 improved Prometheus endpoint #615, thx to fsck-block --- scripts/buildManifest.py | 4 +- src/CHANGES.md | 5 ++ src/config/settings.h | 4 ++ src/defines.h | 2 +- .../MonochromeDisplay/MonochromeDisplay.h | 10 +-- src/web/RestApi.h | 1 + src/web/html/setup.html | 4 +- src/web/web.h | 69 +++++++++++++++---- 8 files changed, 78 insertions(+), 21 deletions(-) diff --git a/scripts/buildManifest.py b/scripts/buildManifest.py index 9a5411d5..db29b352 100644 --- a/scripts/buildManifest.py +++ b/scripts/buildManifest.py @@ -36,13 +36,13 @@ def buildManifest(path, infile, outfile): esp32["parts"].append({"path": "bootloader.bin", "offset": 4096}) esp32["parts"].append({"path": "partitions.bin", "offset": 32768}) esp32["parts"].append({"path": "ota.bin", "offset": 57344}) - esp32["parts"].append({"path": version[1] + "_esp32_" + sha + ".bin", "offset": 65536}) + esp32["parts"].append({"path": version[1] + "_" + sha + "_esp32.bin", "offset": 65536}) data["builds"].append(esp32) esp8266 = {} esp8266["chipFamily"] = "ESP8266" esp8266["parts"] = [] - esp8266["parts"].append({"path": version[1] + "_esp8266_" + sha + ".bin", "offset": 0}) + esp8266["parts"].append({"path": version[1] + "_" + sha + "_esp8266.bin", "offset": 0}) data["builds"].append(esp8266) jsonString = json.dumps(data, indent=2) diff --git a/src/CHANGES.md b/src/CHANGES.md index 1d359129..9405fb15 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,11 @@ (starting from release version `0.5.66`) +## 0.5.77 +* fix wrong filename for automatically created manifest (online installer) #620 +* added rotate display feature #619 +* improved Prometheus endpoint #615, thx to fsck-block + ## 0.5.76 * reduce MQTT retry interval from maximum speed to one second * fixed homeassistant autodiscovery #565 diff --git a/src/config/settings.h b/src/config/settings.h index dbf39d6c..4a922962 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -122,6 +122,7 @@ typedef struct { bool pwrSaveAtIvOffline; bool logoEn; bool pxShift; + bool rot180; uint16_t wakeUp; uint16_t sleepAt; uint8_t contrast; @@ -340,6 +341,7 @@ class settings { mCfg.plugin.display.contrast = 60; mCfg.plugin.display.logoEn = true; mCfg.plugin.display.pxShift = true; + mCfg.plugin.display.rot180 = false; mCfg.plugin.display.pin0 = DEF_PIN_OFF; // SCL mCfg.plugin.display.pin1 = DEF_PIN_OFF; // SDA } @@ -471,6 +473,7 @@ class settings { disp[F("pwrSafe")] = (bool)mCfg.plugin.display.pwrSaveAtIvOffline; disp[F("logo")] = (bool)mCfg.plugin.display.logoEn; disp[F("pxShift")] = (bool)mCfg.plugin.display.pxShift; + disp[F("rot180")] = (bool)mCfg.plugin.display.rot180; disp[F("wake")] = mCfg.plugin.display.wakeUp; disp[F("sleep")] = mCfg.plugin.display.sleepAt; disp[F("contrast")] = mCfg.plugin.display.contrast; @@ -482,6 +485,7 @@ class settings { mCfg.plugin.display.pwrSaveAtIvOffline = (bool) disp[F("pwrSafe")]; mCfg.plugin.display.logoEn = (bool) disp[F("logo")]; mCfg.plugin.display.pxShift = (bool) disp[F("pxShift")]; + mCfg.plugin.display.rot180 = (bool) disp[F("rot180")]; mCfg.plugin.display.wakeUp = disp[F("wake")]; mCfg.plugin.display.sleepAt = disp[F("sleep")]; mCfg.plugin.display.contrast = disp[F("contrast")]; diff --git a/src/defines.h b/src/defines.h index a5f108de..ecb161bc 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 76 +#define VERSION_PATCH 77 //------------------------------------- typedef struct { diff --git a/src/plugins/MonochromeDisplay/MonochromeDisplay.h b/src/plugins/MonochromeDisplay/MonochromeDisplay.h index f4e1a69c..5cfd85f0 100644 --- a/src/plugins/MonochromeDisplay/MonochromeDisplay.h +++ b/src/plugins/MonochromeDisplay/MonochromeDisplay.h @@ -51,18 +51,20 @@ class MonochromeDisplay { mUtcTs = utcTs; mNewPayload = false; mLoopCnt = 0; - mTimeout = DISP_DEFAULT_TIMEOUT; // power off timeout (after inverters go offline) + + u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot180) ? U8G2_R2 : U8G2_R0); + if(mCfg->type) { switch(mCfg->type) { case 1: - mDisplay = new U8G2_PCD8544_84X48_F_4W_HW_SPI(U8G2_R0, mCfg->pin0, mCfg->pin1, disp_reset); + mDisplay = new U8G2_PCD8544_84X48_F_4W_HW_SPI(rot, mCfg->pin0, mCfg->pin1, disp_reset); break; case 2: - mDisplay = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R0, disp_reset, mCfg->pin0, mCfg->pin1); + mDisplay = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(rot, disp_reset, mCfg->pin0, mCfg->pin1); break; case 3: - mDisplay = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R0, disp_reset, mCfg->pin0, mCfg->pin1); + mDisplay = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(rot, disp_reset, mCfg->pin0, mCfg->pin1); break; } mDisplay->begin(); diff --git a/src/web/RestApi.h b/src/web/RestApi.h index c8025464..ec4fd61f 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -359,6 +359,7 @@ class RestApi { obj[F("disp_pwr")] = (bool)mConfig->plugin.display.pwrSaveAtIvOffline; obj[F("logo_en")] = (bool)mConfig->plugin.display.logoEn; obj[F("px_shift")] = (bool)mConfig->plugin.display.pxShift; + obj[F("rot180")] = (bool)mConfig->plugin.display.rot180; obj[F("contrast")] = (uint8_t)mConfig->plugin.display.contrast; obj[F("pinDisp0")] = mConfig->plugin.display.pin0; obj[F("pinDisp1")] = mConfig->plugin.display.pin1; diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 3bd8ef6e..fe514449 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -192,6 +192,8 @@

            + +
            @@ -534,7 +536,7 @@ } function parseDisplay(obj, type) { - for(var i of [["logoEn", "logo_en"], ["dispPwr", "disp_pwr"], ["dispPxSh", "px_shift"]]) + for(var i of [["logoEn", "logo_en"], ["dispPwr", "disp_pwr"], ["dispPxSh", "px_shift"], ["disp180", "rot180"]]) document.getElementsByName(i[0])[0].checked = obj[i[1]]; var e = document.getElementById("dispPins"); diff --git a/src/web/web.h b/src/web/web.h index 4c96f8b9..a661c987 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -565,12 +565,13 @@ class Web { // display mConfig->plugin.display.pwrSaveAtIvOffline = (request->arg("dispPwr") == "on"); - mConfig->plugin.display.logoEn = (request->arg("logoEn") == "on"); + mConfig->plugin.display.logoEn = (request->arg("logoEn") == "on"); mConfig->plugin.display.pxShift = (request->arg("dispPxSh") == "on"); - mConfig->plugin.display.type = request->arg("dispType").toInt(); - mConfig->plugin.display.contrast = request->arg("dispCont").toInt(); - mConfig->plugin.display.pin0 = request->arg("pinDisp0").toInt(); - mConfig->plugin.display.pin1 = request->arg("pinDisp1").toInt(); + mConfig->plugin.display.rot180 = (request->arg("disp180") == "on"); + mConfig->plugin.display.type = request->arg("dispType").toInt(); + mConfig->plugin.display.contrast = request->arg("dispCont").toInt(); + mConfig->plugin.display.pin0 = request->arg("pinDisp0").toInt(); + mConfig->plugin.display.pin1 = request->arg("pinDisp1").toInt(); mApp->saveSettings(); @@ -735,36 +736,78 @@ class Web { void showMetrics(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("web::showMetrics")); String metrics; - char headline[80]; + char infoline[90]; - snprintf(headline, 80, "ahoy_solar_info{version=\"%s\",image=\"\",devicename=\"%s\"} 1", mApp->getVersion(), mConfig->sys.deviceName); - metrics += "# TYPE ahoy_solar_info gauge\n" + String(headline) + "\n"; + // System info + snprintf(infoline, sizeof(infoline), "ahoy_solar_info{version=\"%s\",image=\"\",devicename=\"%s\"} 1", mApp->getVersion(), mConfig->sys.deviceName); + metrics += "# TYPE ahoy_solar_info gauge\n" + String(infoline) + "\n"; Inverter<> *iv; record_t<> *rec; - char type[60], topic[60], val[25]; + char type[60], topic[80], val[25]; for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { iv = mSys->getInverterByPos(id); if(NULL == iv) continue; + // Inverter info + snprintf(infoline, sizeof(infoline), "ahoy_solar_inverter_info{name=\"%s\",serial=\"%12llx\",enabled=\"%d\"} 1", + iv->config->name, iv->config->serial.u64,iv->config->enabled); + metrics += "# TYPE ahoy_solar_inverter_info gauge\n" + String(infoline) + "\n"; + // AC rec = iv->getRecordStruct(RealTimeRunData_Debug); for(uint8_t i = 0; i < rec->length; i++) { uint8_t channel = rec->assign[i].ch; if(channel == 0) { String promUnit, promType; std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(i, rec)); - snprintf(type, 60, "# TYPE ahoy_solar_%s_%s %s", iv->getFieldName(i, rec), promUnit.c_str(), promType.c_str()); - snprintf(topic, 60, "ahoy_solar_%s_%s{inverter=\"%s\"}", iv->getFieldName(i, rec), promUnit.c_str(), iv->config->name); - snprintf(val, 25, "%.3f", iv->getValue(i, rec)); + snprintf(type, sizeof(type), "# TYPE ahoy_solar_%s_%s %s", iv->getFieldName(i, rec), promUnit.c_str(), promType.c_str()); + snprintf(topic, sizeof(topic), "ahoy_solar_%s_%s{inverter=\"%s\"}", iv->getFieldName(i, rec), promUnit.c_str(), iv->config->name); + snprintf(val, sizeof(val), "%.3f", iv->getValue(i, rec)); + metrics += String(type) + "\n" + String(topic) + " " + String(val) + "\n"; + } + } + // channels DC + for(uint8_t j = 1; j <= iv->channels; j ++) { + uint8_t pos; + for (uint8_t k = 0; k < 6; k++) { + switch(k) { + default: pos = (iv->getPosByChFld(j, FLD_UDC, rec)); break; + case 1: pos = (iv->getPosByChFld(j, FLD_IDC, rec)); break; + case 2: pos = (iv->getPosByChFld(j, FLD_PDC, rec)); break; + case 3: pos = (iv->getPosByChFld(j, FLD_YD, rec)); break; + case 4: pos = (iv->getPosByChFld(j, FLD_YT, rec)); break; + case 5: pos = (iv->getPosByChFld(j, FLD_IRR, rec)); break; + } + String promUnit, promType; + std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(pos, rec)); + snprintf(type, sizeof(type), "# TYPE ahoy_solar_%s_%s %s", iv->getFieldName(pos, rec), promUnit.c_str(), promType.c_str()); + snprintf(topic, sizeof(topic), "ahoy_solar_%s_%s{inverter=\"%s\",channel=\"%s\"}", iv->getFieldName(pos, rec), promUnit.c_str(), iv->config->name, iv->config->chName[j-1]); + snprintf(val, sizeof(val), "%.3f", iv->getValue(pos, rec)); metrics += String(type) + "\n" + String(topic) + " " + String(val) + "\n"; } } } - AsyncWebServerResponse *response = request->beginResponse(200, F("text/html"), metrics); + // NRF Statistics + statistics_t *stat = mApp->getStatistics(); + metrics += radioStatistic(F("rx_success"), stat->rxSuccess); + metrics += radioStatistic(F("rx_fail"), stat->rxFail); + metrics += radioStatistic(F("rx_fail_answer"), stat->rxFailNoAnser); + metrics += radioStatistic(F("frame_cnt"), stat->frmCnt); + metrics += radioStatistic(F("tx_cnt"), mSys->Radio.mSendCnt); + + AsyncWebServerResponse *response = request->beginResponse(200, F("text/plain"), metrics); request->send(response); } + String radioStatistic(String statistic, uint32_t value) { + char type[60], topic[80], val[25]; + snprintf(type, sizeof(type), "# TYPE ahoy_solar_radio_%s gauge",statistic.c_str()); + snprintf(topic, sizeof(topic), "ahoy_solar_radio_%s",statistic.c_str()); + snprintf(val, sizeof(val), "%d", value); + return ( String(type) + "\n" + String(topic) + " " + String(val) + "\n"); + } + std::pair convertToPromUnits(String shortUnit) { if(shortUnit == "A") return {"ampere", "gauge"}; if(shortUnit == "V") return {"volt", "gauge"}; From 6721c8bbc11258abed2b066dd23f9ff6de496bff Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 25 Jan 2023 22:28:10 +0100 Subject: [PATCH 235/431] wifi debug --- src/CHANGES.md | 3 +- src/web/RestApi.h | 1 + src/wifi/ahoywifi.cpp | 121 ++++++++++++++++++++++++++++++++++-------- src/wifi/ahoywifi.h | 6 +-- 4 files changed, 105 insertions(+), 26 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 9405fb15..4d492205 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -5,7 +5,8 @@ ## 0.5.77 * fix wrong filename for automatically created manifest (online installer) #620 * added rotate display feature #619 -* improved Prometheus endpoint #615, thx to fsck-block +* improved Prometheus endpoint #615, thx to @fsck-block +* improved wifi to connect always to strongest RSSI, thx to @beegee3 #611 ## 0.5.76 * reduce MQTT retry interval from maximum speed to one second diff --git a/src/web/RestApi.h b/src/web/RestApi.h index ec4fd61f..3a5ba0b1 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -601,6 +601,7 @@ class RestApi { bool setSetup(JsonObject jsonIn, JsonObject jsonOut) { if(F("scan_wifi") == jsonIn[F("cmd")]) { + DPRINTLN(DBG_INFO, F("rqst scan")); mApp->scanAvailNetworks(); } else if(F("set_time") == jsonIn[F("cmd")]) diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 6f7725eb..6b5c13a5 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -25,6 +25,7 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mStaConn = DISCONNECTED; mCnt = 0; mScanActive = false; + mLastApClients = 0; #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); @@ -64,21 +65,44 @@ void ahoywifi::tickWifiLoop() { #if !defined(AP_ONLY) if(mStaConn != GOT_IP) { if (WiFi.softAPgetStationNum() > 0) { // do not reconnect if any AP connection exists - mDns.processNextRequest(); - if((WIFI_AP_STA == WiFi.getMode()) && !mScanActive) { - DBGPRINTLN(F("AP client connected")); - welcome(mApIp.toString()); - WiFi.mode(WIFI_AP); - mAppWifiCb(true); + if(WIFI_AP_STA == WiFi.getMode()) { + if(mScanActive && (mLastApClients != WiFi.softAPgetStationNum())) + mScanActive = false; + + if(mLastApClients != WiFi.softAPgetStationNum()) { + mLastApClients = WiFi.softAPgetStationNum(); + WiFi.scanDelete(); + WiFi.mode(WIFI_AP); + //mDns.start(53, "*", mApIp); + mAppWifiCb(true); + DBGPRINTLN(F("AP client connected")); + welcome(mApIp.toString()); + } } + mDns.processNextRequest(); return; } else if(WIFI_AP == WiFi.getMode()) { + mLastApClients = 0; mCnt = 0; + DPRINTLN(DBG_INFO, "DNS stop"); + mDns.stop(); WiFi.mode(WIFI_AP_STA); } mCnt++; + if(!mScanActive && mBSSIDList.empty()) { // start scanning APs with the given SSID + DBGPRINT(F("scanning APs with SSID ")); + DBGPRINTLN(String(mConfig->sys.stationSsid)); + mScanActive = true; + #if defined(ESP8266) + WiFi.scanNetworks(true, false, 0U, (uint8_t *)mConfig->sys.stationSsid); + #else + WiFi.scanNetworks(true, false, false, 300U, 0U, mConfig->sys.stationSsid); + #endif + return; + } + uint8_t timeout = 10; // seconds if (mStaConn == CONNECTED) // connected but no ip @@ -87,10 +111,27 @@ void ahoywifi::tickWifiLoop() { DBGPRINT(F("reconnect in ")); DBGPRINT(String(timeout-mCnt)); DBGPRINTLN(F(" seconds")); + if(mScanActive) { + getBSSIDs(); + if(!mScanActive) // scan completed + if ((mCnt % timeout) < 8) + mCnt = timeout - 2; + } if((mCnt % timeout) == 0) { // try to reconnect after x sec without connection if(mStaConn != CONNECTED) mStaConn = CONNECTING; - WiFi.reconnect(); + if(mBSSIDList.size() > 0) { // get first BSSID in list + DBGPRINT("try to connect to AP with BSSID:"); + uint8_t bssid[6]; + for (int j = 0; j < 6; j++) { + bssid[j] = mBSSIDList.front(); + mBSSIDList.pop_front(); + DBGPRINT(" " + String(bssid[j], HEX)); + } + DBGPRINTLN(""); + WiFi.disconnect(); + WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, 0, &bssid[0]); + } mCnt = 0; } } @@ -135,7 +176,7 @@ void ahoywifi::setupStation(void) { if(!WiFi.config(ip, gateway, mask, dns1, dns2)) DPRINTLN(DBG_ERROR, F("failed to set static IP!")); } - mStaConn = (WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd) != WL_CONNECTED) ? DISCONNECTED : CONNECTED; + mBSSIDList.clear(); if(String(mConfig->sys.deviceName) != "") WiFi.hostname(mConfig->sys.deviceName); WiFi.mode(WIFI_AP_STA); @@ -206,40 +247,72 @@ void ahoywifi::sendNTPpacket(IPAddress& address) { mUdp.endPacket(); } +//----------------------------------------------------------------------------- +void ahoywifi::sortRSSI(int *sort, int n) { + for (int i = 0; i < n; i++) + sort[i] = i; + for (int i = 0; i < n; i++) + for (int j = i + 1; j < n; j++) + if (WiFi.RSSI(sort[j]) > WiFi.RSSI(sort[i])) + std::swap(sort[i], sort[j]); +} //----------------------------------------------------------------------------- void ahoywifi::scanAvailNetworks(void) { + DPRINTLN(DBG_INFO, "start scan"); if(-2 == WiFi.scanComplete()) { mScanActive = true; if(WIFI_AP == WiFi.getMode()) WiFi.mode(WIFI_AP_STA); WiFi.scanNetworks(true); } + else + DPRINTLN(DBG_INFO, "complete!"); } - //----------------------------------------------------------------------------- void ahoywifi::getAvailNetworks(JsonObject obj) { JsonArray nets = obj.createNestedArray("networks"); + DPRINTLN(DBG_INFO, "getAvailNetworks"); int n = WiFi.scanComplete(); + if (n < 0) + return; if(n > 0) { int sort[n]; - for (int i = 0; i < n; i++) - sort[i] = i; - for (int i = 0; i < n; i++) - for (int j = i + 1; j < n; j++) - if (WiFi.RSSI(sort[j]) > WiFi.RSSI(sort[i])) - std::swap(sort[i], sort[j]); + sortRSSI(&sort[0], n); for (int i = 0; i < n; ++i) { - nets[i]["ssid"] = WiFi.SSID(sort[i]); - nets[i]["rssi"] = WiFi.RSSI(sort[i]); + DPRINTLN(DBG_INFO, "found network: " + WiFi.SSID(sort[i])); + nets[i]["ssid"] = WiFi.SSID(sort[i]); + nets[i]["rssi"] = WiFi.RSSI(sort[i]); } - mScanActive = false; - WiFi.scanDelete(); } + mScanActive = false; + WiFi.scanDelete(); } +//----------------------------------------------------------------------------- +void ahoywifi::getBSSIDs() { + int n = WiFi.scanComplete(); + if (n < 0) + return; + if(n > 0) { + mBSSIDList.clear(); + int sort[n]; + sortRSSI(&sort[0], n); + for (int i = 0; i < n; i++) { + DBGPRINT("BSSID " + String(i) + ":"); + uint8_t *bssid = WiFi.BSSID(sort[i]); + for (int j = 0; j < 6; j++){ + DBGPRINT(" " + String(bssid[j], HEX)); + mBSSIDList.push_back(bssid[j]); + } + DBGPRINTLN(""); + } + } + mScanActive = false; + WiFi.scanDelete(); +} //----------------------------------------------------------------------------- void ahoywifi::connectionEvent(WiFiStatus_t status) { @@ -248,15 +321,19 @@ void ahoywifi::connectionEvent(WiFiStatus_t status) { if(mStaConn != CONNECTED) { mStaConn = CONNECTED; DBGPRINTLN(F("\n[WiFi] Connected")); - WiFi.mode(WIFI_STA); - DBGPRINTLN(F("[WiFi] AP disabled")); - mDns.stop(); } break; case GOT_IP: mStaConn = GOT_IP; + if (mScanActive) { // maybe another scan has started + WiFi.scanDelete(); + mScanActive = false; + } welcome(WiFi.localIP().toString() + F(" (Station)")); + mDns.stop(); + WiFi.mode(WIFI_STA); + DBGPRINTLN(F("[WiFi] AP disabled")); mAppWifiCb(true); break; diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 7155a427..549bf716 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -50,7 +50,8 @@ class ahoywifi { void onWiFiEvent(WiFiEvent_t event); #endif void welcome(String msg); - + void sortRSSI(int *sort, int n); + void getBSSIDs(void); settings_t *mConfig; appWifiCb mAppWifiCb; @@ -68,9 +69,8 @@ class ahoywifi { uint8_t mLoopCnt; bool mScanActive; + uint8_t mLastApClients; - void sortRSSI(int *sort, int n); - void getBSSIDs(void); std::list mBSSIDList; }; From c8af9c2e9a51625d823c24c5f7f621f830ab1bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knuti=5Fin=5FP=C3=A4se?= Date: Fri, 27 Jan 2023 16:24:03 +0100 Subject: [PATCH 236/431] RPi:MQTT support QoS, Retain and Last-Will To support Quality of Service, Retain and Last-Will Switch in ahoy.yml.example --- tools/rpi/ahoy.yml.example | 5 ++++ tools/rpi/hoymiles/__main__.py | 23 ++++++++++++++- tools/rpi/hoymiles/outputs.py | 52 ++++++++++++++++++++-------------- 3 files changed, 58 insertions(+), 22 deletions(-) diff --git a/tools/rpi/ahoy.yml.example b/tools/rpi/ahoy.yml.example index c157e826..fb033f80 100644 --- a/tools/rpi/ahoy.yml.example +++ b/tools/rpi/ahoy.yml.example @@ -28,6 +28,11 @@ ahoy: password: 'password' useTLS: False insecureTLS: False #set True for e.g. self signed certificates. + QoS: 0 + Retain: True + last_will: + topic: Appelweg_PV/114181807700 # defaults to 'hoymiles/{serial}' + payload: "LAST-WILL-MESSAGE: Please check my HOST and Process!" # Influx2 output influxdb: diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index 1dfc8321..97773ed1 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -17,10 +17,31 @@ from suntimes import SunTimes import argparse import yaml from yaml.loader import SafeLoader -# import paho.mqtt.client import hoymiles import logging +################################################################################ +""" Signal Handler """ +################################################################################ +# from signal import signal, Signals, SIGINT, SIGTERM, SIGKILL, SIGHUP +from signal import * +def signal_handler(sig_num, frame): + signame = Signals(sig_num).name + logging.info(f'Stop by Signal {signame} ({sig_num})') + print (f'Stop by Signal <{signame}> ({sig_num}) at: {time.strftime("%d.%m.%Y %H:%M:%S")}') + + if mqtt_client: + mqtt_client.disco() + + sys.exit(0) + +signal(SIGINT, signal_handler) # Interrupt from keyboard (CTRL + C) +signal(SIGTERM, signal_handler) # Signal Handler from terminating processes +signal(SIGHUP, signal_handler) # Hangup detected on controlling terminal or death of controlling process +# signal(SIGKILL, signal_handler) # Signal Handler SIGKILL and SIGSTOP cannot be caught, blocked, or ignored!! +################################################################################ +################################################################################ + class InfoCommands(IntEnum): InverterDevInform_Simple = 0 # 0x00 InverterDevInform_All = 1 # 0x01 diff --git a/tools/rpi/hoymiles/outputs.py b/tools/rpi/hoymiles/outputs.py index 18af494a..723d82ca 100644 --- a/tools/rpi/hoymiles/outputs.py +++ b/tools/rpi/hoymiles/outputs.py @@ -179,10 +179,18 @@ class MqttOutputPlugin(OutputPluginFactory): mqtt_client.tls_set() mqtt_client.tls_insecure_set(config.get('insecureTLS',False)) mqtt_client.username_pw_set(config.get('user', None), config.get('password', None)) + mqtt_client.will_set(str(config.get('last_will', {}).get('topic', 'hoymiles')), str(config.get('last_will', None).get('payload', None))) + mqtt_client.connect(config.get('host', '127.0.0.1'), config.get('port', 1883)) mqtt_client.loop_start() self.client = mqtt_client + self.qos = config.get('QoS', 0) # Quality of Service + self.ret = config.get('Retain', True) # Retain Message + + def disco(self, **params): + self.client.loop_stop() # Stop loop + self.client.disconnect() # disconnect def store_status(self, response, **params): """ @@ -202,17 +210,17 @@ class MqttOutputPlugin(OutputPluginFactory): # Global Head if data['time'] is not None: - self.client.publish(f'{topic}/time', data['time'].strftime("%d.%m.%y - %H:%M:%S")) + self.client.publish(f'{topic}/time', data['time'].strftime("%d.%m.%y - %H:%M:%S"), self.qos, self.ret) # AC Data phase_id = 0 phase_sum_power = 0 for phase in data['phases']: - self.client.publish(f'{topic}/emeter/{phase_id}/voltage', phase['voltage']) - self.client.publish(f'{topic}/emeter/{phase_id}/current', phase['current']) - self.client.publish(f'{topic}/emeter/{phase_id}/power', phase['power']) - self.client.publish(f'{topic}/emeter/{phase_id}/Q_AC', phase['reactive_power']) - self.client.publish(f'{topic}/emeter/{phase_id}/frequency', phase['frequency']) + self.client.publish(f'{topic}/emeter/{phase_id}/voltage', phase['voltage'], self.qos, self.ret) + self.client.publish(f'{topic}/emeter/{phase_id}/current', phase['current'], self.qos, self.ret) + self.client.publish(f'{topic}/emeter/{phase_id}/power', phase['power'], self.qos, self.ret) + self.client.publish(f'{topic}/emeter/{phase_id}/Q_AC', phase['reactive_power'], self.qos, self.ret) + self.client.publish(f'{topic}/emeter/{phase_id}/frequency', phase['frequency'], self.qos, self.ret) phase_id = phase_id + 1 phase_sum_power += phase['power'] @@ -220,36 +228,38 @@ class MqttOutputPlugin(OutputPluginFactory): string_id = 0 string_sum_power = 0 for string in data['strings']: - self.client.publish(f'{topic}/emeter-dc/{string_id}/voltage', string['voltage']) - self.client.publish(f'{topic}/emeter-dc/{string_id}/current', string['current']) - self.client.publish(f'{topic}/emeter-dc/{string_id}/power', string['power']) - self.client.publish(f'{topic}/emeter-dc/{string_id}/YieldDay', string['energy_daily']) - self.client.publish(f'{topic}/emeter-dc/{string_id}/YieldTotal', string['energy_total']/1000) - self.client.publish(f'{topic}/emeter-dc/{string_id}/Irradiation', string['irradiation']) + self.client.publish(f'{topic}/emeter-dc/{string_id}/voltage', string['voltage'], self.qos, self.ret) + self.client.publish(f'{topic}/emeter-dc/{string_id}/current', string['current'], self.qos, self.ret) + self.client.publish(f'{topic}/emeter-dc/{string_id}/power', string['power'], self.qos, self.ret) + self.client.publish(f'{topic}/emeter-dc/{string_id}/YieldDay', string['energy_daily'], self.qos, self.ret) + self.client.publish(f'{topic}/emeter-dc/{string_id}/YieldTotal', string['energy_total']/1000, self.qos, self.ret) + self.client.publish(f'{topic}/emeter-dc/{string_id}/Irradiation', string['irradiation'], self.qos, self.ret) string_id = string_id + 1 string_sum_power += string['power'] # Global if data['event_count'] is not None: - self.client.publish(f'{topic}/total_events', data['event_count']) + self.client.publish(f'{topic}/total_events', data['event_count'], self.qos, self.ret) if data['powerfactor'] is not None: - self.client.publish(f'{topic}/PF_AC', data['powerfactor']) - self.client.publish(f'{topic}/Temp', data['temperature']) + self.client.publish(f'{topic}/PF_AC', data['powerfactor'], self.qos, self.ret) + self.client.publish(f'{topic}/Temp', data['temperature'], self.qos, self.ret) if data['yield_total'] is not None: - self.client.publish(f'{topic}/YieldTotal', data['yield_total']/1000) + self.client.publish(f'{topic}/YieldTotal', data['yield_total']/1000, self.qos, self.ret) if data['yield_today'] is not None: - self.client.publish(f'{topic}/YieldToday', data['yield_today']/1000) - self.client.publish(f'{topic}/Efficiency', data['efficiency']) + self.client.publish(f'{topic}/YieldToday', data['yield_today']/1000, self.qos, self.ret) + self.client.publish(f'{topic}/Efficiency', data['efficiency'], self.qos, self.ret) elif isinstance(response, HardwareInfoResponse): self.client.publish(f'{topic}/Firmware/Version',\ - f'{data["FW_ver_maj"]}.{data["FW_ver_min"]}.{data["FW_ver_pat"]}') + f'{data["FW_ver_maj"]}.{data["FW_ver_min"]}.{data["FW_ver_pat"]}', self.qos, self.ret) self.client.publish(f'{topic}/Firmware/Build_at',\ - f'{data["FW_build_dd"]}/{data["FW_build_mm"]}/{data["FW_build_yy"]}T{data["FW_build_HH"]}:{data["FW_build_MM"]}') + f'{data["FW_build_dd"]}/{data["FW_build_mm"]}/{data["FW_build_yy"]}T{data["FW_build_HH"]}:{data["FW_build_MM"]}',\ + self.qos, self.ret) - self.client.publish(f'{topic}/Firmware/HWPartId', f'{data["FW_HW_ID"]}') + self.client.publish(f'{topic}/Firmware/HWPartId',\ + f'{data["FW_HW_ID"]}', self.qos, self.ret) else: raise ValueError('Data needs to be instance of StatusResponse or a instance of HardwareInfoResponse') From 20abf8d3ba0932f6456f90a10af6d28f6d9ed7d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knuti=5Fin=5FP=C3=A4se?= Date: Fri, 27 Jan 2023 16:48:17 +0100 Subject: [PATCH 237/431] RPi:MQTT Last-Will - handling empty config To handle empty config for last-will --- tools/rpi/hoymiles/outputs.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/rpi/hoymiles/outputs.py b/tools/rpi/hoymiles/outputs.py index 723d82ca..8fb55f3e 100644 --- a/tools/rpi/hoymiles/outputs.py +++ b/tools/rpi/hoymiles/outputs.py @@ -179,7 +179,12 @@ class MqttOutputPlugin(OutputPluginFactory): mqtt_client.tls_set() mqtt_client.tls_insecure_set(config.get('insecureTLS',False)) mqtt_client.username_pw_set(config.get('user', None), config.get('password', None)) - mqtt_client.will_set(str(config.get('last_will', {}).get('topic', 'hoymiles')), str(config.get('last_will', None).get('payload', None))) + + last_will = config.get('last_will', None) + if last_will: + lw_topic = last_will.get('topic', 'last will hoymiles') + lw_payload = last_will.get('payload', 'last will') + mqtt_client.will_set(str(lw_topic), str(lw_payload)) mqtt_client.connect(config.get('host', '127.0.0.1'), config.get('port', 1883)) mqtt_client.loop_start() From 3bd8fe61b55acc800070b8ca5ddbdcbeded39e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20K?= Date: Sat, 28 Jan 2023 05:58:32 +0100 Subject: [PATCH 238/431] Fix attempt for HA autodiscovery --- src/publisher/pubMqtt.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index f066a38a..dc80d06d 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -236,23 +236,24 @@ class PubMqtt { const char *devCls = getFieldDeviceClass(rec->assign[i].fieldId); const char *stateCls = getFieldStateClass(rec->assign[i].fieldId); - doc.clear(); - doc[F("name")] = name; - doc[F("stat_t")] = String(mCfgMqtt->topic) + "/" + String(iv->config->name) + String(topic); - doc[F("unit_of_meas")] = iv->getUnit(i, rec); - doc[F("uniq_id")] = String(iv->config->serial.u64, HEX) + "_" + uniq_id; - doc[F("dev")] = deviceObj; - doc[F("exp_aft")] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!? + DynamicJsonDocument doc2(512); + doc2.clear(); + doc2[F("name")] = name; + doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + String(iv->config->name) + String(topic); + doc2[F("unit_of_meas")] = iv->getUnit(i, rec); + doc2[F("uniq_id")] = String(iv->config->serial.u64, HEX) + "_" + uniq_id; + doc2[F("dev")] = deviceObj; + 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) - doc[F("dev_cla")] = String(devCls); + doc2[F("dev_cla")] = String(devCls); if (stateCls != NULL) - doc[F("stat_cla")] = String(stateCls); + doc2[F("stat_cla")] = String(stateCls); snprintf(topic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec)); - size_t size = measureJson(doc) + 1; + size_t size = measureJson(doc2) + 1; char *buf = new char[size]; memset(buf, 0, size); - serializeJson(doc, buf, size); + serializeJson(doc2, buf, size); publish(topic, buf, true, false); delete[] buf; } From 9456937baf8bdef0f182f0814d00d3128e9dd5f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20K?= Date: Sat, 28 Jan 2023 10:39:09 +0100 Subject: [PATCH 239/431] Add Autodiscovery for total topic --- src/publisher/pubMqtt.h | 74 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index dc80d06d..e59eb9f4 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -258,8 +258,72 @@ class PubMqtt { delete[] buf; } - yield(); + yield(); + } +//Début modif + + String node_mac = WiFi.macAddress().substring(12,14)+ WiFi.macAddress().substring(15,17); + String node_id = "AHOY_DTU_" + node_mac; + doc.clear(); + doc[F("name")] = node_id; + doc[F("ids")] = node_id; + doc[F("cu")] = F("http://") + String(WiFi.localIP().toString()); + doc[F("mf")] = F("Hoymiles"); + doc[F("mdl")] = "AHOY_DTU"; + JsonObject deviceObj = doc.as(); + + uint8_t fieldId; + String fieldUnit; + for (uint8_t i = 0; i < 4; i++) { + switch (i) { + default: + case 0: + fieldId = FLD_PAC; + fieldUnit = "W"; + break; + case 1: + fieldId = FLD_YT; + fieldUnit = "kWh"; + break; + case 2: + fieldId = FLD_YD; + fieldUnit = "Wh"; + break; + case 3: + fieldId = FLD_PDC; + fieldUnit = "W"; + break; + } + + snprintf(name, 32, "Total %s", fields[fieldId]); + snprintf(topic, 64, "/%s", fields[fieldId]); + + + const char *devCls = getFieldDeviceClass(fieldId); + const char *stateCls = getFieldStateClass(fieldId); + + DynamicJsonDocument doc2(512); + doc2.clear(); + doc2[F("name")] = String(name); + doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/total" + String(topic); + doc2[F("unit_of_meas")] = fieldUnit; + doc2[F("uniq_id")] = String(node_id) + "_" + String(fields[fieldId]); + doc2[F("dev")] = deviceObj; + 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); + + snprintf(topic, 64, "%s/sensor/%s/Total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(),fields[fieldId]); + 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(); } void setPowerLimitAck(Inverter<> *iv) { @@ -388,6 +452,14 @@ class PubMqtt { return (pos >= DEVICE_CLS_ASSIGN_LIST_LEN) ? NULL : stateClasses[deviceFieldAssignment[pos].stateClsId]; } + const char *getFieldUnit(uint8_t fieldId) { + uint8_t pos = 0; + for (; pos < DEVICE_CLS_ASSIGN_LIST_LEN; pos++) { + if (deviceFieldAssignment[pos].fieldId == fieldId) + break; + } + return (pos >= DEVICE_CLS_ASSIGN_LIST_LEN) ? NULL : deviceClasses[deviceFieldAssignment[pos].deviceClsId]; + } bool processIvStatus() { // returns true if all inverters are available bool allAvail = true; From f8d4b4f5ae90d4fc4447eb05cfbe258bd696b398 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 28 Jan 2023 23:37:40 +0100 Subject: [PATCH 240/431] fixed Wifi scan during first configuration (client connected to AP of Ahoy) #611 --- src/web/RestApi.h | 4 +--- src/wifi/ahoywifi.cpp | 26 ++++++++++++++++---------- src/wifi/ahoywifi.h | 1 + 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 3a5ba0b1..43d53500 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -600,10 +600,8 @@ class RestApi { } bool setSetup(JsonObject jsonIn, JsonObject jsonOut) { - if(F("scan_wifi") == jsonIn[F("cmd")]) { - DPRINTLN(DBG_INFO, F("rqst scan")); + if(F("scan_wifi") == jsonIn[F("cmd")]) mApp->scanAvailNetworks(); - } else if(F("set_time") == jsonIn[F("cmd")]) mApp->setTimestamp(jsonIn[F("val")]); else if(F("sync_ntp") == jsonIn[F("cmd")]) diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 6b5c13a5..3fcbe22b 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -26,6 +26,7 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mCnt = 0; mScanActive = false; mLastApClients = 0; + mScanCnt = 0; #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); @@ -66,15 +67,21 @@ void ahoywifi::tickWifiLoop() { if(mStaConn != GOT_IP) { if (WiFi.softAPgetStationNum() > 0) { // do not reconnect if any AP connection exists if(WIFI_AP_STA == WiFi.getMode()) { + // first time switch to AP Mode if(mScanActive && (mLastApClients != WiFi.softAPgetStationNum())) mScanActive = false; + // scan is finished + if(!mScanActive) { + WiFi.mode(WIFI_AP); + mDns.start(53, "*", mApIp); + } + + // only once a client connects to AP if(mLastApClients != WiFi.softAPgetStationNum()) { mLastApClients = WiFi.softAPgetStationNum(); WiFi.scanDelete(); - WiFi.mode(WIFI_AP); - //mDns.start(53, "*", mApIp); - mAppWifiCb(true); + mAppWifiCb(false); DBGPRINTLN(F("AP client connected")); welcome(mApIp.toString()); } @@ -94,6 +101,7 @@ void ahoywifi::tickWifiLoop() { if(!mScanActive && mBSSIDList.empty()) { // start scanning APs with the given SSID DBGPRINT(F("scanning APs with SSID ")); DBGPRINTLN(String(mConfig->sys.stationSsid)); + mScanCnt = 0; mScanActive = true; #if defined(ESP8266) WiFi.scanNetworks(true, false, 0U, (uint8_t *)mConfig->sys.stationSsid); @@ -259,21 +267,17 @@ void ahoywifi::sortRSSI(int *sort, int n) { //----------------------------------------------------------------------------- void ahoywifi::scanAvailNetworks(void) { - DPRINTLN(DBG_INFO, "start scan"); if(-2 == WiFi.scanComplete()) { mScanActive = true; if(WIFI_AP == WiFi.getMode()) WiFi.mode(WIFI_AP_STA); WiFi.scanNetworks(true); } - else - DPRINTLN(DBG_INFO, "complete!"); } //----------------------------------------------------------------------------- void ahoywifi::getAvailNetworks(JsonObject obj) { JsonArray nets = obj.createNestedArray("networks"); - DPRINTLN(DBG_INFO, "getAvailNetworks"); int n = WiFi.scanComplete(); if (n < 0) @@ -282,7 +286,6 @@ void ahoywifi::getAvailNetworks(JsonObject obj) { int sort[n]; sortRSSI(&sort[0], n); for (int i = 0; i < n; ++i) { - DPRINTLN(DBG_INFO, "found network: " + WiFi.SSID(sort[i])); nets[i]["ssid"] = WiFi.SSID(sort[i]); nets[i]["rssi"] = WiFi.RSSI(sort[i]); } @@ -294,8 +297,11 @@ void ahoywifi::getAvailNetworks(JsonObject obj) { //----------------------------------------------------------------------------- void ahoywifi::getBSSIDs() { int n = WiFi.scanComplete(); - if (n < 0) - return; + if (n < 0){ + mScanCnt++; + if (mScanCnt < 20) + return; + } if(n > 0) { mBSSIDList.clear(); int sort[n]; diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 549bf716..321dbb86 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -70,6 +70,7 @@ class ahoywifi { uint8_t mLoopCnt; bool mScanActive; uint8_t mLastApClients; + uint8_t mScanCnt; std::list mBSSIDList; }; From 8457f46b0c6d24d41671ff52fb78a95cdc394a45 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 29 Jan 2023 00:55:10 +0100 Subject: [PATCH 241/431] further improvements regarding wifi #611, fix connection if only one AP with same SSID is there fix endless loop in `zerovalues` #564 fix auto discover again #565 added total values to autodiscover #630 improved zero at midnight #625 --- src/CHANGES.md | 7 ++++ src/defines.h | 2 +- src/publisher/pubMqtt.h | 78 ++++++++++++++++++++++++++--------------- src/wifi/ahoywifi.cpp | 19 +++++----- 4 files changed, 66 insertions(+), 40 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 4d492205..9e31ada2 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,13 @@ (starting from release version `0.5.66`) +## 0.5.78 +* further improvements regarding wifi #611, fix connection if only one AP with same SSID is there +* fix endless loop in `zerovalues` #564 +* fix auto discover again #565 +* added total values to autodiscover #630 +* improved zero at midnight #625 + ## 0.5.77 * fix wrong filename for automatically created manifest (online installer) #620 * added rotate display feature #619 diff --git a/src/defines.h b/src/defines.h index ecb161bc..5c626e02 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 77 +#define VERSION_PATCH 78 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index f066a38a..021a29eb 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -133,6 +133,7 @@ class PubMqtt { void tickerMidnight() { Inverter<> *iv; record_t<> *rec; + char topic[7 + MQTT_TOPIC_LEN], val[4]; // set YieldDay to zero for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { @@ -142,10 +143,11 @@ class PubMqtt { rec = iv->getRecordStruct(RealTimeRunData_Debug); uint8_t pos = iv->getPosByChFld(CH0, FLD_YD, rec); iv->setValue(pos, rec, 0.0f); - } - mSendList.push(RealTimeRunData_Debug); - sendIvData(); + snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch0/%s", iv->config->name, fields[FLD_YD]); + snprintf(val, 4, "0.0"); + publish(topic, val, true); + } } void payloadEventListener(uint8_t cmd) { @@ -210,7 +212,10 @@ class PubMqtt { DPRINTLN(DBG_VERBOSE, F("sendMqttDiscoveryConfig")); char topic[64], name[32], uniq_id[32]; - DynamicJsonDocument doc(512); + DynamicJsonDocument doc(128); + + uint8_t fldTotal[4] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC}; + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); if (NULL == iv) @@ -218,41 +223,55 @@ class PubMqtt { record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); doc.clear(); + doc[F("name")] = iv->config->name; doc[F("ids")] = String(iv->config->serial.u64, HEX); doc[F("cu")] = F("http://") + String(WiFi.localIP().toString()); doc[F("mf")] = F("Hoymiles"); doc[F("mdl")] = iv->config->name; - JsonObject deviceObj = doc.as(); - - for (uint8_t i = 0; i < rec->length; i++) { - 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)); - - const char *devCls = getFieldDeviceClass(rec->assign[i].fieldId); - const char *stateCls = getFieldStateClass(rec->assign[i].fieldId); - - doc.clear(); - doc[F("name")] = name; - doc[F("stat_t")] = String(mCfgMqtt->topic) + "/" + String(iv->config->name) + String(topic); - doc[F("unit_of_meas")] = iv->getUnit(i, rec); - doc[F("uniq_id")] = String(iv->config->serial.u64, HEX) + "_" + uniq_id; - doc[F("dev")] = deviceObj; - doc[F("exp_aft")] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!? + JsonObject deviceObj = doc.as(); // deviceObj is only pointer!? + + for (uint8_t i = 0; i < (rec->length + 4); i++) { + const char *devCls, *stateCls; + if(i < rec->length) { + 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-rec->length]]); + snprintf(topic, 64, "/%s", fields[fldTotal[i-rec->length]]); + snprintf(uniq_id, 32, "total_%s", fields[fldTotal[i-rec->length]]); + devCls = getFieldDeviceClass(fldTotal[i-rec->length]); + stateCls = getFieldStateClass(fldTotal[i-rec->length]); + } + + DynamicJsonDocument doc2(512); + doc2[F("name")] = name; + doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + String(iv->config->name) + String(topic); + doc2[F("unit_of_meas")] = iv->getUnit(((i < rec->length) ? i : (i - rec->length)), rec); + doc2[F("uniq_id")] = String(iv->config->serial.u64, HEX) + "_" + uniq_id; + doc2[F("dev")] = deviceObj; + 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) - doc[F("dev_cla")] = String(devCls); + doc2[F("dev_cla")] = String(devCls); if (stateCls != NULL) - doc[F("stat_cla")] = String(stateCls); + doc2[F("stat_cla")] = String(stateCls); - snprintf(topic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec)); - size_t size = measureJson(doc) + 1; + if(i < rec->length) + 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, iv->config->name, fields[fldTotal[i-rec->length]]); + size_t size = measureJson(doc2) + 1; char *buf = new char[size]; memset(buf, 0, size); - serializeJson(doc, buf, size); + serializeJson(doc2, buf, size); publish(topic, buf, true, false); delete[] buf; } @@ -582,6 +601,7 @@ class PubMqtt { case FLD_FW_BUILD_HOUR_MINUTE: case FLD_HW_ID: case FLD_ACT_ACTIVE_PWR_LIMIT: + fld++; continue; break; } diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 3fcbe22b..4ca7f290 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -98,7 +98,12 @@ void ahoywifi::tickWifiLoop() { } mCnt++; - if(!mScanActive && mBSSIDList.empty()) { // start scanning APs with the given SSID + uint8_t timeout = 10; // seconds + if (mStaConn == CONNECTED) // connected but no ip + timeout = 20; + + + if(!mScanActive && mBSSIDList.empty() && ((mCnt % timeout) == 0)) { // start scanning APs with the given SSID DBGPRINT(F("scanning APs with SSID ")); DBGPRINTLN(String(mConfig->sys.stationSsid)); mScanCnt = 0; @@ -110,20 +115,14 @@ void ahoywifi::tickWifiLoop() { #endif return; } - - uint8_t timeout = 10; // seconds - - if (mStaConn == CONNECTED) // connected but no ip - timeout = 20; - DBGPRINT(F("reconnect in ")); DBGPRINT(String(timeout-mCnt)); DBGPRINTLN(F(" seconds")); if(mScanActive) { getBSSIDs(); - if(!mScanActive) // scan completed - if ((mCnt % timeout) < 8) - mCnt = timeout - 2; + //if(!mScanActive) // scan completed + // if ((mCnt % timeout) < 8) + // mCnt = timeout - 2; } if((mCnt % timeout) == 0) { // try to reconnect after x sec without connection if(mStaConn != CONNECTED) From bd8de5f8f93267357c00d8b42b4829230e3f6d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20K?= Date: Sun, 29 Jan 2023 11:43:39 +0100 Subject: [PATCH 242/431] Send totals values once --- src/publisher/pubMqtt.h | 54 ++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 1b3effd3..c0bcff5e 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -217,24 +217,39 @@ class PubMqtt { uint8_t fldTotal[4] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC}; const char* unitTotal[4] = {"W", "kWh", "Wh", "W"}; - for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL == iv) + 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); - doc.clear(); - doc[F("name")] = iv->config->name; - doc[F("ids")] = String(iv->config->serial.u64, HEX); + 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"); - doc[F("mdl")] = iv->config->name; JsonObject deviceObj = doc.as(); // deviceObj is only pointer!? - for (uint8_t i = 0; i < (rec->length + 4); i++) { + for (uint8_t i = 0; i < ((!total) ? (rec->length) : (4) ) ; i++) { const char *devCls, *stateCls; - if(i < rec->length) { + if (!total) { if (rec->assign[i].ch == CH0) snprintf(name, 32, "%s %s", iv->config->name, iv->getFieldName(i, rec)); else @@ -245,19 +260,20 @@ class PubMqtt { devCls = getFieldDeviceClass(rec->assign[i].fieldId); stateCls = getFieldStateClass(rec->assign[i].fieldId); } + else { // total values - snprintf(name, 32, "Total %s", fields[fldTotal[i-rec->length]]); - snprintf(topic, 64, "/%s", fields[fldTotal[i-rec->length]]); - snprintf(uniq_id, 32, "total_%s", fields[fldTotal[i-rec->length]]); - devCls = getFieldDeviceClass(fldTotal[i-rec->length]); - stateCls = getFieldStateClass(fldTotal[i-rec->length]); + 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) + "/" + ((i < rec->length) ? String(iv->config->name) : "total" ) + String(topic); - doc2[F("unit_of_meas")] = ((i < rec->length) ? (iv->getUnit(i,rec)) : (unitTotal[i-rec->length])); - doc2[F("uniq_id")] = String(iv->config->serial.u64, HEX) + "_" + uniq_id; + 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; 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) @@ -265,10 +281,10 @@ class PubMqtt { if (stateCls != NULL) doc2[F("stat_cla")] = String(stateCls); - if(i < rec->length) + 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, iv->config->name, fields[fldTotal[i-rec->length]]); + 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); From a37a9d4cc0d6f9544a6471b95f6833e82a3da685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20K?= Date: Sun, 29 Jan 2023 19:08:18 +0100 Subject: [PATCH 243/431] Ignore "exp_aft" for yieldtotal and yieldday. --- src/publisher/pubMqtt.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index c0bcff5e..8788cb99 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -275,7 +275,8 @@ class PubMqtt { 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; - 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 (!(total && 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) From 9610e71a2c2cc77184146ec58669568f21b14621 Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 30 Jan 2023 18:59:34 +0100 Subject: [PATCH 244/431] chunked response for prometheus metrics --- doc/prometheus_ep_description.md | 47 +++++++++ src/web/web.h | 159 ++++++++++++++++++------------- 2 files changed, 138 insertions(+), 68 deletions(-) create mode 100644 doc/prometheus_ep_description.md diff --git a/doc/prometheus_ep_description.md b/doc/prometheus_ep_description.md new file mode 100644 index 00000000..bce0525f --- /dev/null +++ b/doc/prometheus_ep_description.md @@ -0,0 +1,47 @@ +# Prometheus Endpoint +Metrics available for AhoyDTU device, inverters and channels. + +Prometheus metrics provided at `/metrics`. + +## Labels +| Label name | Description | +|:-----------|:--------------------------------------| +| version | current installed version of AhoyDTU | +| image | currently not used | +| devicename | Device name from setup | +| name | Inverter name from setup | +| serial | Serial number of inverter | +| enabled | Communication enable for inverter | +| inverter | Inverter name from setup | +| channel | Channel name from setup | + + +## Exported Metrics +| Metric name | Type | Description | Labels | +|----------------------------------------|---------|--------------------------------------------------------|--------------| +| `ahoy_solar_info` | Gauge | Information about the AhoyDTU device | version, image, devicename | +| `ahoy_solar_inverter_info` | Gauge | Information about the configured inverter(s) | name, serial, enabled | +| `ahoy_solar_U_AC_volt` | Gauge | AC voltage of inverter [V] | inverter | +| `ahoy_solar_I_AC_ampere` | Gauge | AC current of inverter [A] | inverter | +| `ahoy_solar_P_AC_watt` | Gauge | AC power of inverter [W] | inverter | +| `ahoy_solar_Q_AC_var` | Gauge | AC reactive power[var] | inverter | +| `ahoy_solar_F_AC_hertz` | Gauge | AC frequency [Hz] | inverter | +| `ahoy_solar_PF_AC` | Gauge | AC Power factor | inverter | +| `ahoy_solar_Temp_celsius` | Gauge | Temperature of inverter | inverter | +| `ahoy_solar_ALARM_MES_ID` | Gauge | Last alarm message id of inverter | inverter | +| `ahoy_solar_YieldDay_wattHours` | Counter | Energy converted to AC per day [Wh] | inverter | +| `ahoy_solar_YieldTotal_kilowattHours` | Counter | Energy converted to AC since reset [kWh] | inverter | +| `ahoy_solar_P_DC_watt` | Gauge | DC power of inverter [W] | inverter | +| `ahoy_solar_Efficiency_ratio` | Gauge | ration AC Power over DC Power [%] | inverter | +| `ahoy_solar_U_DC_volt` | Gauge | DC voltage of channel [V] | inverter, channel | +| `ahoy_solar_I_DC_ampere` | Gauge | DC current of channel [A] | inverter, channel | +| `ahoy_solar_P_DC_watt` | Gauge | DC power of channel [P] | inverter, channel | +| `ahoy_solar_YieldDay_wattHours` | Counter | Energy converted to AC per day [Wh] | inverter, channel | +| `ahoy_solar_YieldTotal_kilowattHours` | Counter | Energy converted to AC since reset [kWh] | inverter, channel | +| `ahoy_solar_Irradiation_ratio` | Gauge | ratio DC Power over set maximum power per channel [%] | inverter, channel | +| `ahoy_solar_radio_rx_success` | Gauge | NRF24 statistic | | +| `ahoy_solar_radio_rx_fail` | Gauge | NRF24 statistic | | +| `ahoy_solar_radio_rx_fail_answer` | Gauge | NRF24 statistic | | +| `ahoy_solar_radio_frame_cnt` | Gauge | NRF24 statistic | | +| `ahoy_solar_radio_tx_cnt` | Gauge | NRF24 statistic | | + diff --git a/src/web/web.h b/src/web/web.h index a661c987..5641ef0d 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -733,70 +733,93 @@ class Web { #endif #ifdef ENABLE_PROMETHEUS_EP + enum { + metricsStateStart, metricsStateInverter, metricStateChannel,metricsStateEnd + } metricsStep; + int metricsInverterId,metricsChannelId; + void showMetrics(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("web::showMetrics")); - String metrics; - char infoline[90]; - // System info - snprintf(infoline, sizeof(infoline), "ahoy_solar_info{version=\"%s\",image=\"\",devicename=\"%s\"} 1", mApp->getVersion(), mConfig->sys.deviceName); - metrics += "# TYPE ahoy_solar_info gauge\n" + String(infoline) + "\n"; - Inverter<> *iv; - record_t<> *rec; - char type[60], topic[80], val[25]; - for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { - iv = mSys->getInverterByPos(id); - if(NULL == iv) - continue; - // Inverter info - snprintf(infoline, sizeof(infoline), "ahoy_solar_inverter_info{name=\"%s\",serial=\"%12llx\",enabled=\"%d\"} 1", - iv->config->name, iv->config->serial.u64,iv->config->enabled); - metrics += "# TYPE ahoy_solar_inverter_info gauge\n" + String(infoline) + "\n"; - - // AC - rec = iv->getRecordStruct(RealTimeRunData_Debug); - for(uint8_t i = 0; i < rec->length; i++) { - uint8_t channel = rec->assign[i].ch; - if(channel == 0) { - String promUnit, promType; - std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(i, rec)); - snprintf(type, sizeof(type), "# TYPE ahoy_solar_%s_%s %s", iv->getFieldName(i, rec), promUnit.c_str(), promType.c_str()); - snprintf(topic, sizeof(topic), "ahoy_solar_%s_%s{inverter=\"%s\"}", iv->getFieldName(i, rec), promUnit.c_str(), iv->config->name); - snprintf(val, sizeof(val), "%.3f", iv->getValue(i, rec)); - metrics += String(type) + "\n" + String(topic) + " " + String(val) + "\n"; - } - } - // channels DC - for(uint8_t j = 1; j <= iv->channels; j ++) { - uint8_t pos; - for (uint8_t k = 0; k < 6; k++) { - switch(k) { - default: pos = (iv->getPosByChFld(j, FLD_UDC, rec)); break; - case 1: pos = (iv->getPosByChFld(j, FLD_IDC, rec)); break; - case 2: pos = (iv->getPosByChFld(j, FLD_PDC, rec)); break; - case 3: pos = (iv->getPosByChFld(j, FLD_YD, rec)); break; - case 4: pos = (iv->getPosByChFld(j, FLD_YT, rec)); break; - case 5: pos = (iv->getPosByChFld(j, FLD_IRR, rec)); break; + metricsStep = metricsStateStart; + AsyncWebServerResponse *response = request->beginChunkedResponse(F("text/plain"), + [this](uint8_t *buffer, size_t maxLen, size_t filledLength) -> size_t + { + Inverter<> *iv; + record_t<> *rec; + statistics_t *stat; + String metrics; + char type[60], topic[100], val[25]; + size_t len = 0; + + switch (metricsStep) { + case metricsStateStart: // System Info & NRF Statistics : fit to one packet + snprintf(topic,sizeof(topic),"# TYPE ahoy_solar_info gauge\nahoy_solar_info{version=\"%s\",image=\"\",devicename=\"%s\"} 1\n", + mApp->getVersion(), mConfig->sys.deviceName); + metrics = topic; + // NRF Statistics + stat = mApp->getStatistics(); + metrics += radioStatistic(F("rx_success"), stat->rxSuccess); + metrics += radioStatistic(F("rx_fail"), stat->rxFail); + metrics += radioStatistic(F("rx_fail_answer"), stat->rxFailNoAnser); + metrics += radioStatistic(F("frame_cnt"), stat->frmCnt); + metrics += radioStatistic(F("tx_cnt"), mSys->Radio.mSendCnt); + + len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str()); + // Start Inverter loop + metricsInverterId = 0; + metricsStep = metricsStateInverter; + break; + + case metricsStateInverter: // Inverter loop + if (metricsInverterId < mSys->getNumInverters()) { + iv = mSys->getInverterByPos(metricsInverterId); + if(NULL != iv) { + // Inverter info + len = snprintf((char *)buffer, maxLen, "ahoy_solar_inverter_info{name=\"%s\",serial=\"%12llx\",enabled=\"%d\"} 1\n", + iv->config->name, iv->config->serial.u64,iv->config->enabled); + // Start Channel loop for this inverter + metricsChannelId = 0; + metricsStep = metricStateChannel; + } + } else { + metricsStep = metricsStateEnd; } - String promUnit, promType; - std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(pos, rec)); - snprintf(type, sizeof(type), "# TYPE ahoy_solar_%s_%s %s", iv->getFieldName(pos, rec), promUnit.c_str(), promType.c_str()); - snprintf(topic, sizeof(topic), "ahoy_solar_%s_%s{inverter=\"%s\",channel=\"%s\"}", iv->getFieldName(pos, rec), promUnit.c_str(), iv->config->name, iv->config->chName[j-1]); - snprintf(val, sizeof(val), "%.3f", iv->getValue(pos, rec)); - metrics += String(type) + "\n" + String(topic) + " " + String(val) + "\n"; - } - } - } - - // NRF Statistics - statistics_t *stat = mApp->getStatistics(); - metrics += radioStatistic(F("rx_success"), stat->rxSuccess); - metrics += radioStatistic(F("rx_fail"), stat->rxFail); - metrics += radioStatistic(F("rx_fail_answer"), stat->rxFailNoAnser); - metrics += radioStatistic(F("frame_cnt"), stat->frmCnt); - metrics += radioStatistic(F("tx_cnt"), mSys->Radio.mSendCnt); + break; + + case metricStateChannel: // Channel loop + iv = mSys->getInverterByPos(metricsInverterId); + rec = iv->getRecordStruct(RealTimeRunData_Debug); + if (metricsChannelId < rec->length) { + uint8_t channel = rec->assign[metricsChannelId].ch; + String promUnit, promType; + std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(metricsChannelId, rec)); + snprintf(type, sizeof(type), "# TYPE ahoy_solar_%s%s %s", iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), promType.c_str()); + if (0 == channel) { + snprintf(topic, sizeof(topic), "ahoy_solar_%s%s{inverter=\"%s\"}", iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name); + } else { + snprintf(topic, sizeof(topic), "ahoy_solar_%s%s{inverter=\"%s\",channel=\"%s\"}", iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name,iv->config->chName[channel-1]); + } + snprintf(val, sizeof(val), "%.3f", iv->getValue(metricsChannelId, rec)); + len = snprintf((char*)buffer,maxLen,"%s\n%s %s\n",type,topic,val); + + metricsChannelId++; + } else { + len = snprintf((char*)buffer,maxLen,"#\n"); // At least one char to send otherwise the transmission ends. + + // All channels processed --> try next inverter + metricsInverterId++; + metricsStep = metricsStateInverter; + } + break; - AsyncWebServerResponse *response = request->beginResponse(200, F("text/plain"), metrics); + case metricsStateEnd: + default: // end of transmission + len = 0; + break; + } + return len; + }); request->send(response); } @@ -809,18 +832,18 @@ class Web { } std::pair convertToPromUnits(String shortUnit) { - if(shortUnit == "A") return {"ampere", "gauge"}; - if(shortUnit == "V") return {"volt", "gauge"}; - if(shortUnit == "%") return {"ratio", "gauge"}; - if(shortUnit == "W") return {"watt", "gauge"}; - if(shortUnit == "Wh") return {"watt_daily", "counter"}; - if(shortUnit == "kWh") return {"watt_total", "counter"}; - if(shortUnit == "°C") return {"celsius", "gauge"}; - + if(shortUnit == "A") return {"_ampere", "gauge"}; + if(shortUnit == "V") return {"_volt", "gauge"}; + if(shortUnit == "%") return {"_ratio", "gauge"}; + if(shortUnit == "W") return {"_watt", "gauge"}; + if(shortUnit == "Wh") return {"_wattHours", "counter"}; + if(shortUnit == "kWh") return {"_kilowattHours", "counter"}; + if(shortUnit == "°C") return {"_celsius", "gauge"}; + if(shortUnit == "var") return {"_var", "gauge"}; + if(shortUnit == "Hz") return {"_hertz", "gauge"}; return {"", "gauge"}; } #endif - AsyncWebServer mWeb; AsyncEventSource mEvts; bool mProtected; From 146c7612f698de4d0322ba77eb497cf79cd0de20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20K?= Date: Tue, 31 Jan 2023 06:35:37 +0100 Subject: [PATCH 245/431] Remove exp_aft for all YD & YT. Add reset YD total at midnight. Publish YD & YT on CH0 only when iv is producing to avoids 0 at restart. --- src/config/config.h | 2 +- src/publisher/pubMqtt.h | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/config/config.h b/src/config/config.h index 69e7193b..722e5323 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -99,7 +99,7 @@ #define NTP_REFRESH_INTERVAL 12 * 3600 * 1000 // default mqtt interval -#define MQTT_INTERVAL 60 +#define MQTT_INTERVAL 90 // default MQTT broker uri #define DEF_MQTT_BROKER "\0" diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 8788cb99..ec3465d9 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -148,7 +148,10 @@ class PubMqtt { snprintf(val, 4, "0.0"); publish(topic, val, true); } - } + // set Total YieldDay to zero + snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[FLD_YD]); + snprintf(val, 4, "0.0"); + publish(topic, val, true); } void payloadEventListener(uint8_t cmd) { if(mClient.connected()) { // prevent overflow if MQTT broker is not reachable but set @@ -275,7 +278,7 @@ class PubMqtt { 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 (!(total && String(stateCls) == String("total_increasing"))) + 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); @@ -525,6 +528,8 @@ class PubMqtt { switch (rec->assign[i].fieldId) { case FLD_YT: case FLD_YD: + if ((rec->assign[i].ch == CH0) && (!iv->isProducing(*mUtcTimestamp))) // avoids returns to 0 on restart + continue; retained = true; break; } From a8b9ca0b4cfcde22e528f2897a730f45666efe53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20K?= Date: Tue, 31 Jan 2023 11:51:21 +0100 Subject: [PATCH 246/431] don't send "0" for CH0 YT YD at reboot --- src/publisher/pubMqtt.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index ec3465d9..8b5b7dce 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -145,12 +145,12 @@ class PubMqtt { iv->setValue(pos, rec, 0.0f); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch0/%s", iv->config->name, fields[FLD_YD]); - snprintf(val, 4, "0.0"); + snprintf(val, 2, "0"); publish(topic, val, true); } // set Total YieldDay to zero snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[FLD_YD]); - snprintf(val, 4, "0.0"); + snprintf(val, 2, "0"); publish(topic, val, true); } void payloadEventListener(uint8_t cmd) { @@ -484,7 +484,7 @@ class PubMqtt { if(changed) { snprintf(val, 32, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((mIvAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE))); publish("status", val, true); - sendIvData(false); // false prevents loop of same function + //sendIvData(false); // false prevents loop of same function } return totalComplete; From d996c2c10ba5b71eb4f7685ffe2509ff5759da17 Mon Sep 17 00:00:00 2001 From: Knuti_in_Paese Date: Wed, 1 Feb 2023 21:42:51 +0100 Subject: [PATCH 247/431] RPI:using pyRF24 on Debian 11 bullseye environment known RF24 lib can not installed on Debian 11 bullseye 64 bit operating system now, system try to import RF24 nor pyrf24 --- tools/rpi/README.md | 10 ++++++++++ tools/rpi/ahoy.yml.example | 2 +- tools/rpi/hoymiles/__init__.py | 14 +++++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/tools/rpi/README.md b/tools/rpi/README.md index bc8b23c0..75b5c1e2 100644 --- a/tools/rpi/README.md +++ b/tools/rpi/README.md @@ -78,6 +78,16 @@ cd examples_linux/ python3 getting_started.py # to test and see whether RF24 class can be loaded as module in python correctly ``` + +``` for bullseye - Debian 11 on 64 bit operating system +[ $(lscpu | grep Architecture | awk '{print $2}') != "aarch64" ]] && echo "Not a 64 bit architecture for this step!" + +git clone --recurse-submodules https://github.com/nRF24/pyRF24.git +cd pyRF24 +python -m pip install . -v # this step takes about 5 minutes! +``` + + If there are no error messages on the last step, then the NRF24 Wrapper has been installed successfully. Required python modules diff --git a/tools/rpi/ahoy.yml.example b/tools/rpi/ahoy.yml.example index fb033f80..928374de 100644 --- a/tools/rpi/ahoy.yml.example +++ b/tools/rpi/ahoy.yml.example @@ -31,7 +31,7 @@ ahoy: QoS: 0 Retain: True last_will: - topic: Appelweg_PV/114181807700 # defaults to 'hoymiles/{serial}' + topic: hoymiles/114172220003 # defaults to 'hoymiles/{serial}' payload: "LAST-WILL-MESSAGE: Please check my HOST and Process!" # Influx2 output diff --git a/tools/rpi/hoymiles/__init__.py b/tools/rpi/hoymiles/__init__.py index 74ec9fd8..eeb7e7de 100644 --- a/tools/rpi/hoymiles/__init__.py +++ b/tools/rpi/hoymiles/__init__.py @@ -11,9 +11,21 @@ import re from datetime import datetime import logging import crcmod -from RF24 import RF24, RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_250KBPS, RF24_CRC_DISABLED, RF24_CRC_8, RF24_CRC_16 from .decoders import * +try: + # OSI Layer 2 driver for nRF24L01 on Arduino & Raspberry Pi/Linux Devices + # https://github.com/nRF24/RF24.git + from RF24 import RF24, RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_250KBPS, RF24_CRC_DISABLED, RF24_CRC_8, RF24_CRC_16 +except ModuleNotFoundError: + try: + # Repo for pyRF24 package + # https://github.com/nRF24/pyRF24.git + from pyrf24 import RF24, RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_250KBPS, RF24_CRC_DISABLED, RF24_CRC_8, RF24_CRC_16 + except ModuleNotFoundError: + print("Module for RF24 not found - exit") + exit() + f_crc_m = crcmod.predefined.mkPredefinedCrcFun('modbus') f_crc8 = crcmod.mkCrcFun(0x101, initCrc=0, xorOut=0) From 0d552e3007976689463aa5cbed86822736c93cd3 Mon Sep 17 00:00:00 2001 From: Knuti_in_Paese Date: Thu, 2 Feb 2023 14:21:30 +0100 Subject: [PATCH 248/431] RPI:error handling while getting corruppted data extended error handling while getting corruppted data on 64 bit operating system (bullseye) lots of currupted data are reseived on Debian 11 OS. So we have to check the data length before using strict.unpack --- tools/rpi/README.md | 13 +++++++------ tools/rpi/hoymiles/__init__.py | 8 ++++---- tools/rpi/hoymiles/__main__.py | 3 ++- tools/rpi/hoymiles/decoders/__init__.py | 18 +++++++++++++----- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/tools/rpi/README.md b/tools/rpi/README.md index 75b5c1e2..36b08f79 100644 --- a/tools/rpi/README.md +++ b/tools/rpi/README.md @@ -78,8 +78,12 @@ cd examples_linux/ python3 getting_started.py # to test and see whether RF24 class can be loaded as module in python correctly ``` +If there are no error messages on the last step, then the NRF24 Wrapper has been installed successfully. + -``` for bullseye - Debian 11 on 64 bit operating system +for Debian 11 (bullseye) 64 bit operating system +------------------------------------------------- +```code [ $(lscpu | grep Architecture | awk '{print $2}') != "aarch64" ]] && echo "Not a 64 bit architecture for this step!" git clone --recurse-submodules https://github.com/nRF24/pyRF24.git @@ -87,15 +91,12 @@ cd pyRF24 python -m pip install . -v # this step takes about 5 minutes! ``` - -If there are no error messages on the last step, then the NRF24 Wrapper has been installed successfully. - Required python modules ----------------------- Some modules are not installed by default on a RaspberryPi, therefore add them manually: -``` +```code pip install crcmod pyyaml paho-mqtt SunTimes ``` @@ -122,7 +123,7 @@ Python parameters The application describes itself -``` +```code python3 -m hoymiles --help usage: hoymiles [-h] -c [CONFIG_FILE] [--log-transactions] [--verbose] diff --git a/tools/rpi/hoymiles/__init__.py b/tools/rpi/hoymiles/__init__.py index eeb7e7de..a754ff6d 100644 --- a/tools/rpi/hoymiles/__init__.py +++ b/tools/rpi/hoymiles/__init__.py @@ -170,15 +170,15 @@ class ResponseDecoder(ResponseDecoderFactory): model = self.inverter_model command = self.request_command - c_datetime = self.time_rx.strftime("%Y-%m-%d %H:%M:%S.%f") - logging.info(f'{c_datetime} model_decoder: {model}Decode{command.upper()}') + if HOYMILES_DEBUG_LOGGING: + c_datetime = self.time_rx.strftime("%Y-%m-%d %H:%M:%S.%f") + logging.info(f'{c_datetime} model_decoder: {model}Decode{command.upper()}') model_decoders = __import__('hoymiles.decoders') if hasattr(model_decoders, f'{model}Decode{command.upper()}'): device = getattr(model_decoders, f'{model}Decode{command.upper()}') else: - if HOYMILES_DEBUG_LOGGING: - device = getattr(model_decoders, 'DebugDecodeAny') + device = getattr(model_decoders, 'DebugDecodeAny') return device(self.response, time_rx=self.time_rx, diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index 97773ed1..35943eb4 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -179,8 +179,8 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): # Handle the response data if any if response: - c_datetime = datetime.now() if hoymiles.HOYMILES_DEBUG_LOGGING: + c_datetime = datetime.now() logging.debug(f'{c_datetime} Payload: ' + hoymiles.hexify_payload(response)) # prepare decoder object @@ -195,6 +195,7 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): # get decoder object result = decoder.decode() if hoymiles.HOYMILES_DEBUG_LOGGING: + c_datetime = datetime.now() logging.info(f'{c_datetime} Decoded: {result.__dict__()}') # check decoder object for output diff --git a/tools/rpi/hoymiles/decoders/__init__.py b/tools/rpi/hoymiles/decoders/__init__.py index b46dbe48..e27b502d 100644 --- a/tools/rpi/hoymiles/decoders/__init__.py +++ b/tools/rpi/hoymiles/decoders/__init__.py @@ -110,6 +110,9 @@ class StatusResponse(Response): :rtype: tuple """ size = struct.calcsize(fmt) + if (len(self.response) < base+size): + logging.error(f'base: {base} size: {size} len: {len(self.response)} fmt: {fmt} rep: {self.response}') + return [0] return struct.unpack(fmt, self.response[base:base+size]) @property @@ -331,10 +334,12 @@ class EventsResponse(UnknownResponse): logging.debug(' '.join([f'{byte:02x}' for byte in chunk]) + ': ') - opcode, a_code, a_count, uptime_sec = struct.unpack('>BBHH', chunk[0:6]) - a_text = self.alarm_codes.get(a_code, 'N/A') - - logging.debug(f' uptime={timedelta(seconds=uptime_sec)} a_count={a_count} opcode={opcode} a_code={a_code} a_text={a_text}') + if (len(chunk[0:6]) == 6): + opcode, a_code, a_count, uptime_sec = struct.unpack('>BBHH', chunk[0:6]) + a_text = self.alarm_codes.get(a_code, 'N/A') + logging.debug(f' uptime={timedelta(seconds=uptime_sec)} a_count={a_count} opcode={opcode} a_code={a_code} a_text={a_text}') + else: + logging.error(f'length of chunk must be greater or equal 6 bytes: {chunk}') dbg = '' for fmt in ['BBHHHHH']: @@ -362,7 +367,10 @@ class HardwareInfoResponse(UnknownResponse): """ Base values, availabe in each __dict__ call """ responce_info = self.response - logging.info(f'HardwareInfoResponse: {struct.unpack(">HHHHHHHH", responce_info)}') + if (len(responce_info) >= 16): + logging.info(f'HardwareInfoResponse: {struct.unpack(">HHHHHHHH", responce_info)}') + else: + logging.error(f'wrong length of HardwareInfoResponse: {responce_info}') fw_version, fw_build_yyyy, fw_build_mmdd, fw_build_hhmm, hw_id = struct.unpack('>HHHHH', self.response[0:10]) From 892f554ff54025af530219ec17e2260f19660af4 Mon Sep 17 00:00:00 2001 From: Knuti_in_Paese Date: Sat, 4 Feb 2023 11:41:29 +0100 Subject: [PATCH 249/431] RPI:finer tuned debug logging Description for prep RF24 and pyrf24 on debian 11 (bullseye) 64 bit OS --- tools/rpi/README.md | 52 +++++++++++++++++++++++-- tools/rpi/ahoy.service | 7 ++-- tools/rpi/hoymiles/__init__.py | 29 +++++++++++--- tools/rpi/hoymiles/__main__.py | 22 +++++++---- tools/rpi/hoymiles/decoders/__init__.py | 28 +++++++------ tools/rpi/hoymiles/outputs.py | 15 +++++-- 6 files changed, 118 insertions(+), 35 deletions(-) diff --git a/tools/rpi/README.md b/tools/rpi/README.md index 36b08f79..12b6f5ef 100644 --- a/tools/rpi/README.md +++ b/tools/rpi/README.md @@ -81,14 +81,58 @@ python3 getting_started.py # to test and see whether RF24 class can be loaded as If there are no error messages on the last step, then the NRF24 Wrapper has been installed successfully. -for Debian 11 (bullseye) 64 bit operating system -------------------------------------------------- +Building RF24 Wrapper for Debian 11 (bullseye) 64 bit operating system +---------------------------------------------------------------------- +The description above does not work on Debian 11 (bullseye) 64 bit operating system. +There are 2 possible sollutions to install the RF24 Wrapper. + + * `1. solution:` +```code +sudo apt install cmake git python3-dev libboost-python-dev python3-pip python3-rpi.gpio + +sudo ln -s $(ls /usr/lib/$(ls /usr/lib/gcc | \ + head -1)/libboost_python3*.so | \ + tail -1) /usr/lib/$(ls /usr/lib/gcc | \ + head -1)/libboost_python3.so + +git clone https://github.com/nRF24/RF24.git +cd RF24 + +rm -rf build Makefile.inc +./configure --driver=SPIDEV +``` + * edit `Makefile.inc` with your prefered editor e.g. nano or vi + old: +```code + CPUFLAGS=-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard + CFLAGS=-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -Ofast -Wall -pthread +``` + new: +```code + CPUFLAGS= + CFLAGS=-Ofast -Wall -pthread +``` + * continue with +```code +make +sudo make install + +cd pyRF24 +rm -r ./build/ ./dist/ ./RF24.egg-info/ ./__pycache__/ #just to make sure there is no old stuff +python3 -m pip install --upgrade pip +python3 -m pip install . +python3 -m pip list #watch for RF24 module - if its there its installed +``` + + + + * `2. solution:` ```code -[ $(lscpu | grep Architecture | awk '{print $2}') != "aarch64" ]] && echo "Not a 64 bit architecture for this step!" +sudo apt install git python3-dev libboost-python-dev python3-pip python3-rpi.gpio git clone --recurse-submodules https://github.com/nRF24/pyRF24.git cd pyRF24 -python -m pip install . -v # this step takes about 5 minutes! +python3 -m pip install . -v # this step takes about 5 minutes on my RPI-4 ! ``` Required python modules diff --git a/tools/rpi/ahoy.service b/tools/rpi/ahoy.service index 394bc09e..4af9ea89 100644 --- a/tools/rpi/ahoy.service +++ b/tools/rpi/ahoy.service @@ -6,11 +6,10 @@ # WorkingDirectory (absolute path to your private ahoy dir) # To change other config parameter, please consult systemd documentation # -# To activate this service, create a link, enable and start the ahoy.service -# $ mkdir -p $HOME/.config/systemd/user -# $ ln -sf $(pwd)/ahoy/tools/rpi/ahoy.service -t $HOME/.config/systemd/user +# To activate this service, create a link with enable and start the ahoy.service +# $ mkdir -p $HOME/.config/systemd/user +# $ systemctl --user enable $(pwd)/ahoy/tools/rpi/ahoy.service # $ systemctl --user status ahoy -# $ systemctl --user enable ahoy # $ systemctl --user start ahoy # $ systemctl --user status ahoy # diff --git a/tools/rpi/hoymiles/__init__.py b/tools/rpi/hoymiles/__init__.py index a754ff6d..210bed65 100644 --- a/tools/rpi/hoymiles/__init__.py +++ b/tools/rpi/hoymiles/__init__.py @@ -12,18 +12,26 @@ from datetime import datetime import logging import crcmod from .decoders import * +from os import environ try: # OSI Layer 2 driver for nRF24L01 on Arduino & Raspberry Pi/Linux Devices # https://github.com/nRF24/RF24.git from RF24 import RF24, RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_250KBPS, RF24_CRC_DISABLED, RF24_CRC_8, RF24_CRC_16 -except ModuleNotFoundError: + if environ.get('TERM') is not None: + print('Using python Module: RF24') +except ModuleNotFoundError as e: + if environ.get('TERM') is not None: + print(f'{e} - try to use module: RF24') try: # Repo for pyRF24 package # https://github.com/nRF24/pyRF24.git from pyrf24 import RF24, RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_250KBPS, RF24_CRC_DISABLED, RF24_CRC_8, RF24_CRC_16 - except ModuleNotFoundError: - print("Module for RF24 not found - exit") + if environ.get('TERM') is not None: + print(f'{e} - Using python Module: pyrf24') + except ModuleNotFoundError as e: + if environ.get('TERM') is not None: + print(f'{e} - exit') exit() f_crc_m = crcmod.predefined.mkPredefinedCrcFun('modbus') @@ -171,8 +179,19 @@ class ResponseDecoder(ResponseDecoderFactory): command = self.request_command if HOYMILES_DEBUG_LOGGING: - c_datetime = self.time_rx.strftime("%Y-%m-%d %H:%M:%S.%f") - logging.info(f'{c_datetime} model_decoder: {model}Decode{command.upper()}') + if command.upper() == '01': + model_desc = "Firmware version / date" + elif command.upper() == '02': + model_desc = "Inverter generic events log" + elif command.upper() == '0B': + model_desc = "mirco-inverters status data" + elif command.upper() == '0C': + model_desc = "mirco-inverters status data" + elif command.upper() == '11': + model_desc = "Inverter generic events log" + elif command.upper() == '12': + model_desc = "Inverter major events log" + logging.info(f'model_decoder: {model}Decode{command.upper()} - {model_desc}') model_decoders = __import__('hoymiles.decoders') if hasattr(model_decoders, f'{model}Decode{command.upper()}'): diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index 35943eb4..00608a44 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -174,12 +174,13 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): response = com.get_payload() payload_ttl = 0 except Exception as e_all: - logging.error(f'Error while retrieving data: {e_all}') + if hoymiles.HOYMILES_TRANSACTION_LOGGING: + logging.error(f'Error while retrieving data: {e_all}') pass # Handle the response data if any if response: - if hoymiles.HOYMILES_DEBUG_LOGGING: + if hoymiles.HOYMILES_TRANSACTION_LOGGING: c_datetime = datetime.now() logging.debug(f'{c_datetime} Payload: ' + hoymiles.hexify_payload(response)) @@ -195,8 +196,7 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): # get decoder object result = decoder.decode() if hoymiles.HOYMILES_DEBUG_LOGGING: - c_datetime = datetime.now() - logging.info(f'{c_datetime} Decoded: {result.__dict__()}') + logging.info(f'Decoded: {result.__dict__()}') # check decoder object for output if isinstance(result, hoymiles.decoders.StatusResponse): @@ -282,6 +282,12 @@ def init_logging(ahoy_config): lvl = logging.WARNING elif level == 'ERROR': lvl = logging.ERROR + elif level == 'FATAL': + lvl = logging.FATAL + if hoymiles.HOYMILES_TRANSACTION_LOGGING and hoymiles.HOYMILES_DEBUG_LOGGING: + lvl = logging.DEBUG + if not hoymiles.HOYMILES_TRANSACTION_LOGGING and not hoymiles.HOYMILES_DEBUG_LOGGING: + lvl = logging.INFO logging.basicConfig(filename=fn, format='%(asctime)s %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=lvl) if __name__ == '__main__': @@ -309,15 +315,15 @@ if __name__ == '__main__': logging.error(f'Failed to load config file {global_config.config_file}: {e_yaml}') sys.exit(1) - # read AHOY configuration file and prepare logging - ahoy_config = dict(cfg.get('ahoy', {})) - init_logging(ahoy_config) - if global_config.log_transactions: hoymiles.HOYMILES_TRANSACTION_LOGGING=True if global_config.verbose: hoymiles.HOYMILES_DEBUG_LOGGING=True + # read AHOY configuration file and prepare logging + ahoy_config = dict(cfg.get('ahoy', {})) + init_logging(ahoy_config) + # Prepare for multiple transceivers, makes them configurable for radio_config in ahoy_config.get('nrf', [{}]): hmradio = hoymiles.HoymilesNRF(**radio_config) diff --git a/tools/rpi/hoymiles/decoders/__init__.py b/tools/rpi/hoymiles/decoders/__init__.py index e27b502d..ff277dbd 100644 --- a/tools/rpi/hoymiles/decoders/__init__.py +++ b/tools/rpi/hoymiles/decoders/__init__.py @@ -99,6 +99,7 @@ class StatusResponse(Response): frequency = None powerfactor = None event_count = None + unpack_error = False def unpack(self, fmt, base): """ @@ -111,6 +112,7 @@ class StatusResponse(Response): """ size = struct.calcsize(fmt) if (len(self.response) < base+size): + self.unpack_error = True logging.error(f'base: {base} size: {size} len: {len(self.response)} fmt: {fmt} rep: {self.response}') return [0] return struct.unpack(fmt, self.response[base:base+size]) @@ -196,7 +198,8 @@ class StatusResponse(Response): data['event_count'] = self.event_count data['time'] = self.time_rx - return data + if not self.unpack_error: + return data class UnknownResponse(Response): """ @@ -334,12 +337,13 @@ class EventsResponse(UnknownResponse): logging.debug(' '.join([f'{byte:02x}' for byte in chunk]) + ': ') - if (len(chunk[0:6]) == 6): - opcode, a_code, a_count, uptime_sec = struct.unpack('>BBHH', chunk[0:6]) - a_text = self.alarm_codes.get(a_code, 'N/A') - logging.debug(f' uptime={timedelta(seconds=uptime_sec)} a_count={a_count} opcode={opcode} a_code={a_code} a_text={a_text}') - else: + if (len(chunk[0:6]) < 6): logging.error(f'length of chunk must be greater or equal 6 bytes: {chunk}') + return + + opcode, a_code, a_count, uptime_sec = struct.unpack('>BBHH', chunk[0:6]) + a_text = self.alarm_codes.get(a_code, 'N/A') + logging.debug(f' uptime={timedelta(seconds=uptime_sec)} a_count={a_count} opcode={opcode} a_code={a_code} a_text={a_text}') dbg = '' for fmt in ['BBHHHHH']: @@ -366,12 +370,15 @@ class HardwareInfoResponse(UnknownResponse): def __dict__(self): """ Base values, availabe in each __dict__ call """ + data = super().__dict__() responce_info = self.response - if (len(responce_info) >= 16): - logging.info(f'HardwareInfoResponse: {struct.unpack(">HHHHHHHH", responce_info)}') - else: - logging.error(f'wrong length of HardwareInfoResponse: {responce_info}') + if (len(self.response) != 16): + logging.error(f'HardwareInfoResponse: data length should be 16 bytes - measured {len(self.response)} bytes') + logging.error(f'HardwareInfoResponse: data: {self.response}') + return data + + logging.info(f'HardwareInfoResponse: {struct.unpack(">HHHHHHHH", self.response[0:16])}') fw_version, fw_build_yyyy, fw_build_mmdd, fw_build_hhmm, hw_id = struct.unpack('>HHHHH', self.response[0:10]) fw_version_maj = int((fw_version / 10000)) @@ -385,7 +392,6 @@ class HardwareInfoResponse(UnknownResponse): f'build at {fw_build_dd:>02}/{fw_build_mm:>02}/{fw_build_yyyy}T{fw_build_HH:>02}:{fw_build_MM:>02}, '\ f'HW revision {hw_id}') - data = super().__dict__() data['FW_ver_maj'] = fw_version_maj data['FW_ver_min'] = fw_version_min data['FW_ver_pat'] = fw_version_pat diff --git a/tools/rpi/hoymiles/outputs.py b/tools/rpi/hoymiles/outputs.py index 8fb55f3e..e4754fbc 100644 --- a/tools/rpi/hoymiles/outputs.py +++ b/tools/rpi/hoymiles/outputs.py @@ -9,6 +9,7 @@ import socket import logging from datetime import datetime, timezone from hoymiles.decoders import StatusResponse, HardwareInfoResponse +from hoymiles import HOYMILES_TRANSACTION_LOGGING, HOYMILES_DEBUG_LOGGING class OutputPluginFactory: def __init__(self, **params): @@ -277,9 +278,10 @@ class VzInverterOutput: self.channels = dict() for channel in config.get('channels', []): - uid = channel.get('uid') + uid = channel.get('uid', None) ctype = channel.get('type') - if uid and ctype: + # if uid and ctype: + if ctype: self.channels[ctype] = uid def store_status(self, data, session): @@ -330,10 +332,17 @@ class VzInverterOutput: def try_publish(self, ts, ctype, value): if not ctype in self.channels: - logging.warning(f'ctype \"{ctype}\" not found in ahoy.yml') + if HOYMILES_DEBUG_LOGGING: + logging.warning(f'ctype \"{ctype}\" not found in ahoy.yml') return + uid = self.channels[ctype] url = f'{self.baseurl}/data/{uid}.json?operation=add&ts={ts}&value={value}' + if uid == None: + if HOYMILES_DEBUG_LOGGING: + logging.warning(f'ctype \"{ctype}\" has no configured uid-value in ahoy.yml') + return + try: r = self.session.get(url) if r.status_code == 404: From 9a0bee831d33aaecd7c707fa1f8d08f672f76c14 Mon Sep 17 00:00:00 2001 From: Knuti_in_Paese Date: Sat, 4 Feb 2023 16:40:50 +0100 Subject: [PATCH 250/431] RPi:specify README.md and collect data from EventsResponse --- tools/rpi/README.md | 26 ++++++++++++++++++------- tools/rpi/hoymiles/decoders/__init__.py | 15 ++++++++++---- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/tools/rpi/README.md b/tools/rpi/README.md index 12b6f5ef..13758b08 100644 --- a/tools/rpi/README.md +++ b/tools/rpi/README.md @@ -84,9 +84,14 @@ If there are no error messages on the last step, then the NRF24 Wrapper has been Building RF24 Wrapper for Debian 11 (bullseye) 64 bit operating system ---------------------------------------------------------------------- The description above does not work on Debian 11 (bullseye) 64 bit operating system. -There are 2 possible sollutions to install the RF24 Wrapper. +Please check first, if you have Debian 11 (bullseye) 64 bit operating system installed: + - `uname -a` search for aarch64 + - `lsb_release -d` + - `cat /etc/debian_version` - * `1. solution:` +There are 2 possible solutions to install the RF24 wrapper: + + * `1. Solution:` ```code sudo apt install cmake git python3-dev libboost-python-dev python3-pip python3-rpi.gpio @@ -101,13 +106,13 @@ cd RF24 rm -rf build Makefile.inc ./configure --driver=SPIDEV ``` - * edit `Makefile.inc` with your prefered editor e.g. nano or vi - old: + # edit `Makefile.inc` with your prefered editor e.g. nano or vi + - old: ```code CPUFLAGS=-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard CFLAGS=-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -Ofast -Wall -pthread ``` - new: + - new: ```code CPUFLAGS= CFLAGS=-Ofast -Wall -pthread @@ -125,8 +130,7 @@ python3 -m pip list #watch for RF24 module - if its there its installed ``` - - * `2. solution:` + * `2. Solution:` ```code sudo apt install git python3-dev libboost-python-dev python3-pip python3-rpi.gpio @@ -135,6 +139,14 @@ cd pyRF24 python3 -m pip install . -v # this step takes about 5 minutes on my RPI-4 ! ``` +If you have problems with your radio module from ahoi, +e.g.: cannot interpret received data, +please try to reduce the speed of the radio module! +Add the following line to your ahoy.yml configuration file in "nrf" section: +* `spispeed: 600000` + + + Required python modules ----------------------- diff --git a/tools/rpi/hoymiles/decoders/__init__.py b/tools/rpi/hoymiles/decoders/__init__.py index ff277dbd..fa80a3b4 100644 --- a/tools/rpi/hoymiles/decoders/__init__.py +++ b/tools/rpi/hoymiles/decoders/__init__.py @@ -327,9 +327,9 @@ class EventsResponse(UnknownResponse): #logging.debug(' payload has valid modbus crc') self.response = self.response[:-2] - status = struct.unpack('>H', self.response[:2])[0] - a_text = self.alarm_codes.get(status, 'N/A') - logging.info (f' Inverter status: {a_text} ({status})') + self.status = struct.unpack('>H', self.response[:2])[0] + self.a_text = self.alarm_codes.get(self.status, 'N/A') + logging.info (f' Inverter status: {self.a_text} ({self.status})') chunk_size = 12 for i_chunk in range(2, len(self.response), chunk_size): @@ -350,6 +350,14 @@ class EventsResponse(UnknownResponse): dbg += f' {fmt:7}: ' + str(struct.unpack('>' + fmt, chunk)) logging.debug(dbg) + def __dict__(self): + """ Base values, availabe in each __dict__ call """ + + data = super().__dict__() + data['inv_stat_num'] = self.status + data['inv_stat_txt'] = self.a_text + return data + class HardwareInfoResponse(UnknownResponse): def __init__(self, *args, **params): super().__init__(*args, **params) @@ -371,7 +379,6 @@ class HardwareInfoResponse(UnknownResponse): """ Base values, availabe in each __dict__ call """ data = super().__dict__() - responce_info = self.response if (len(self.response) != 16): logging.error(f'HardwareInfoResponse: data length should be 16 bytes - measured {len(self.response)} bytes') From 57bc46191c4d93d02c9bec3d223d20f1a9acc2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knuti=5Fin=5FP=C3=A4se?= <122045840+PaeserBastelstube@users.noreply.github.com> Date: Sat, 4 Feb 2023 17:25:58 +0100 Subject: [PATCH 251/431] RPi: README.md format one new section --- tools/rpi/README.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tools/rpi/README.md b/tools/rpi/README.md index 13758b08..d1829706 100644 --- a/tools/rpi/README.md +++ b/tools/rpi/README.md @@ -91,7 +91,7 @@ Please check first, if you have Debian 11 (bullseye) 64 bit operating system ins There are 2 possible solutions to install the RF24 wrapper: - * `1. Solution:` +**__1. Solution:__** ```code sudo apt install cmake git python3-dev libboost-python-dev python3-pip python3-rpi.gpio @@ -106,18 +106,19 @@ cd RF24 rm -rf build Makefile.inc ./configure --driver=SPIDEV ``` - # edit `Makefile.inc` with your prefered editor e.g. nano or vi - - old: -```code - CPUFLAGS=-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard - CFLAGS=-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -Ofast -Wall -pthread -``` - - new: -```code - CPUFLAGS= - CFLAGS=-Ofast -Wall -pthread -``` - * continue with +> _edit `Makefile.inc` with your prefered editor e.g. nano or vi_ +> +> old: +>```code +> CPUFLAGS=-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard +> CFLAGS=-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -Ofast -Wall -pthread +>``` +> new: +>```code +> CPUFLAGS= +> CFLAGS=-Ofast -Wall -pthread +>``` +_continue now_ ```code make sudo make install @@ -130,7 +131,7 @@ python3 -m pip list #watch for RF24 module - if its there its installed ``` - * `2. Solution:` +**__2. Solution:__** ```code sudo apt install git python3-dev libboost-python-dev python3-pip python3-rpi.gpio @@ -139,11 +140,10 @@ cd pyRF24 python3 -m pip install . -v # this step takes about 5 minutes on my RPI-4 ! ``` -If you have problems with your radio module from ahoi, -e.g.: cannot interpret received data, -please try to reduce the speed of the radio module! -Add the following line to your ahoy.yml configuration file in "nrf" section: -* `spispeed: 600000` +If you have problems with your radio module from ahoi, e.g.: cannot interpret received data, +please try to reduce the speed of your radio module! +Add the following parameter to your ahoy.yml configuration file in "nrf" section: +`spispeed: 600000` (0.6 MHz) @@ -247,7 +247,7 @@ Todo - Ability to talk to multiple inverters - MQTT gateway - understand channel hopping -- configurable polling interval +- ~~configurable polling interval~~ done: interval ist configurable in ahoy.yml - commands - picture of setup! - python module From 802205ad911641bb14941eb0b9ac76ed2d5adce6 Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 14:46:31 +0100 Subject: [PATCH 252/431] Update appInterface.h --- src/appInterface.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/appInterface.h b/src/appInterface.h index a8e37a75..83a4f769 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -17,6 +17,7 @@ class IApp { virtual bool saveSettings() = 0; virtual bool readSettings(const char *path) = 0; virtual bool eraseSettings(bool eraseWifi) = 0; + virtual void setOnUpdate() = 0; virtual void setRebootFlag() = 0; virtual const char *getVersion() = 0; virtual statistics_t *getStatistics() = 0; From 139129ea8b0c3fbac9b4dd0ecc74227eb1dd1842 Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 14:49:49 +0100 Subject: [PATCH 253/431] Update app.h --- src/app.h | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/app.h b/src/app.h index d51c9209..d3709b89 100644 --- a/src/app.h +++ b/src/app.h @@ -18,10 +18,8 @@ #include "config/settings.h" #include "defines.h" #include "utils/crc.h" -#include "utils/ahoyTimer.h" #include "utils/scheduler.h" -#include "hm/CircularBuffer.h" #include "hm/hmSystem.h" #include "hm/payload.h" #include "wifi/ahoywifi.h" @@ -61,10 +59,6 @@ class app : public IApp, public ah::Scheduler { void loopWifi(void); void onWifi(bool gotIp); void regularTickers(void); - void handleIntr(void); - void cbMqtt(char* topic, byte* payload, unsigned int length); - void saveValues(void); - bool getWifiApActive(void); uint32_t getUptime() { return Scheduler::getUptime(); @@ -99,6 +93,10 @@ class app : public IApp, public ah::Scheduler { mWifi.getAvailNetworks(obj); } + void setOnUpdate() { + onWifi(false); + } + void setRebootFlag() { once(std::bind(&app::tickReboot, this), 3, "rboot"); } @@ -206,6 +204,9 @@ class app : public IApp, public ah::Scheduler { void tickReboot(void) { DPRINTLN(DBG_INFO, F("Rebooting...")); + onWifi(false); + ah::Scheduler::resetTicker(); + WiFi.disconnect(); ESP.restart(); } @@ -247,13 +248,9 @@ class app : public IApp, public ah::Scheduler { settings_t *mConfig; uint8_t mSendLastIvId; - uint8_t mSendTickerId; statistics_t mStat; - // timer - uint32_t mRxTicker; - // mqtt PubMqttType mMqtt; bool mMqttReconnect; From 5fb45f1b20b1e7de0f3f4edb98ffe6339bdeeccc Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 14:53:01 +0100 Subject: [PATCH 254/431] Update app.cpp --- src/app.cpp | 77 ++++++++++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 0d88847e..f5478f0f 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -82,40 +82,26 @@ void app::loop(void) { void app::loopStandard(void) { ah::Scheduler::loop(); - mSys->Radio.loop(); - mPayload.loop(); - - yield(); - - if (ah::checkTicker(&mRxTicker, 4)) { - bool rxRdy = mSys->Radio.switchRxCh(); - - if (!mSys->BufCtrl.empty()) { - uint8_t len; - packet_t *p = mSys->BufCtrl.getBack(); + if (mSys->Radio.loop()) { + while (!mSys->Radio.mBufCtrl.empty()) { + packet_t *p = &mSys->Radio.mBufCtrl.front(); - if (mSys->Radio.checkPaketCrc(p->packet, &len, p->rxCh)) { - if (mConfig->serial.debug) { - DPRINT(DBG_INFO, "RX " + String(len) + "B Ch" + String(p->rxCh) + " | "); - mSys->Radio.dumpBuf(NULL, p->packet, len); - } - mStat.frmCnt++; - - if (0 != len) - mPayload.add(p, len); + if (mConfig->serial.debug) { + DPRINT(DBG_INFO, "RX " + String(p->len) + "B Ch" + String(p->ch) + " | "); + mSys->Radio.dumpBuf(p->packet, p->len); } - mSys->BufCtrl.popBack(); - } - yield(); + mStat.frmCnt++; - if (rxRdy) - mPayload.process(true); + mPayload.add(p); + mSys->Radio.mBufCtrl.pop(); + yield(); + } + mPayload.process(true); } + mPayload.loop(); -#if !defined(AP_ONLY) if(mMqttEnabled) mMqtt.loop(); -#endif } //----------------------------------------------------------------------------- @@ -131,12 +117,14 @@ void app::onWifi(bool gotIp) { regularTickers(); // reinstall regular tickers if (gotIp) { mInnerLoopCb = std::bind(&app::loopStandard, this); - mSendTickerId = every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval, "tSend"); + every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval, "tSend"); mMqttReconnect = true; mSunrise = 0; // needs to be set to 0, to reinstall sunrise and ivComm tickers! once(std::bind(&app::tickNtpUpdate, this), 2, "ntp2"); - if(WIFI_AP == WiFi.getMode()) + if(WIFI_AP == WiFi.getMode()) { + mMqttEnabled = false; everySec(std::bind(&ahoywifi::tickWifiLoop, &mWifi), "wifiL"); + } } else { mInnerLoopCb = std::bind(&app::loopWifi, this); @@ -232,6 +220,15 @@ void app::tickComm(void) { once(std::bind(&app::tickComm, this), 1, "mqCom"); // MQTT not connected, retry } +//----------------------------------------------------------------------------- +void app::tickMidnight(void) { + // only used and enabled by MQTT (see setup()) + uint32_t nxtTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight + onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2"); + + mMqtt.tickerMidnight(); +} + //----------------------------------------------------------------------------- void app::tickSend(void) { if(!mSys->Radio.isChipConnected()) { @@ -239,9 +236,9 @@ void app::tickSend(void) { return; } if (mIVCommunicationOn) { - if (!mSys->BufCtrl.empty()) { + if (!mSys->Radio.mBufCtrl.empty()) { if (mConfig->serial.debug) - DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->BufCtrl.getFill())); + DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->Radio.mBufCtrl.size())); } int8_t maxLoop = MAX_NUM_INVERTERS; @@ -264,21 +261,6 @@ void app::tickSend(void) { updateLed(); } -//----------------------------------------------------------------------------- -void app::tickMidnight(void) { - // only used and enabled by MQTT (see setup()) - uint32_t nxtTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight - onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2"); - - mMqtt.tickerMidnight(); -} - -//----------------------------------------------------------------------------- -void app::handleIntr(void) { - DPRINTLN(DBG_VERBOSE, F("app::handleIntr")); - mSys->Radio.handleIntr(); -} - //----------------------------------------------------------------------------- void app::resetSystem(void) { snprintf(mVersion, 12, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); @@ -290,8 +272,7 @@ void app::resetSystem(void) { mSunrise = 0; mSunset = 0; - mRxTicker = 0; - mSendTickerId = 0xff; // invalid id + mMqttEnabled = false; mSendLastIvId = 0; mShowRebootRequest = false; From 447a43388eb20a7a9250af0d4c5e5c68ce49a62a Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:01:08 +0100 Subject: [PATCH 255/431] Update main.cpp --- src/main.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c585d0f2..42ed55f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,21 +7,11 @@ #include "app.h" #include "config/config.h" - app myApp; -//----------------------------------------------------------------------------- -IRAM_ATTR void handleIntr(void) { - myApp.handleIntr(); -} - - //----------------------------------------------------------------------------- void setup() { myApp.setup(); - - // TODO: move to HmRadio - attachInterrupt(digitalPinToInterrupt(myApp.getIrqPin()), handleIntr, FALLING); } From 975ee667f2dd29a269200ad82a42c179e6522689 Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:03:26 +0100 Subject: [PATCH 256/431] Update defines.h --- src/defines.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/defines.h b/src/defines.h index 5c626e02..d5f0fcb3 100644 --- a/src/defines.h +++ b/src/defines.h @@ -17,7 +17,8 @@ //------------------------------------- typedef struct { - uint8_t rxCh; + uint8_t ch; + uint8_t len; uint8_t packet[MAX_RF_PAYLOAD_SIZE]; } packet_t; From 7177d54d736e11fa5cc2e574ab6fe9232c39260a Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:10:15 +0100 Subject: [PATCH 257/431] Update pubMqtt.h --- src/publisher/pubMqtt.h | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 021a29eb..938499ea 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -15,7 +15,6 @@ #endif #include "../utils/dbg.h" -#include "../utils/ahoyTimer.h" #include "../config/config.h" #include #include @@ -40,8 +39,7 @@ class PubMqtt { mRxCnt = 0; mTxCnt = 0; mSubscriptionCb = NULL; - mIvAvail = true; - memset(mLastIvState, 0xff, MAX_NUM_INVERTERS); + memset(mLastIvState, MQTT_STATUS_NOT_AVAIL_NOT_PROD, MAX_NUM_INVERTERS); } ~PubMqtt() { } @@ -70,6 +68,7 @@ class PubMqtt { void loop() { #if defined(ESP8266) mClient.loop(); + yield(); #endif } @@ -408,13 +407,12 @@ class PubMqtt { bool processIvStatus() { // returns true if all inverters are available - bool allAvail = true; - bool first = true; + bool allAvail = true; // shows if all enabled inverters are available + bool anyAvail = false; // shows if at least one enabled inverter is available bool changed = false; char topic[7 + MQTT_TOPIC_LEN], val[40]; Inverter<> *iv; record_t<> *rec; - bool totalComplete = true; for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { iv = mSys->getInverterByPos(id); @@ -422,32 +420,21 @@ class PubMqtt { continue; // skip to next inverter rec = iv->getRecordStruct(RealTimeRunData_Debug); - if(first) - mIvAvail = false; - first = false; // inverter status - uint8_t status = MQTT_STATUS_AVAIL_PROD; - if ((!iv->isAvailable(*mUtcTimestamp)) || (!iv->config->enabled)) { - status = MQTT_STATUS_NOT_AVAIL_NOT_PROD; - if(iv->config->enabled) { // only change all-avail if inverter is enabled! - totalComplete = false; + uint8_t status = MQTT_STATUS_NOT_AVAIL_NOT_PROD; + if (iv->config->enabled) { + if (iv->isAvailable(*mUtcTimestamp)) + status = (iv->isProducing(*mUtcTimestamp)) ? MQTT_STATUS_AVAIL_PROD : MQTT_STATUS_AVAIL_NOT_PROD; + else // inverter is enabled but not available allAvail = false; - } - } - else { - mIvAvail = true; - if (!iv->isProducing(*mUtcTimestamp)) { - if (MQTT_STATUS_AVAIL_PROD == status) - status = MQTT_STATUS_AVAIL_NOT_PROD; - } } if(mLastIvState[id] != status) { mLastIvState[id] = status; changed = true; - if(mCfgMqtt->rstValsNotAvail) + if((MQTT_STATUS_NOT_AVAIL_NOT_PROD == status) && (mCfgMqtt->rstValsNotAvail)) zeroValues(iv); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name); @@ -461,12 +448,12 @@ class PubMqtt { } if(changed) { - snprintf(val, 32, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((mIvAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE))); + snprintf(val, 32, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE))); publish("status", val, true); sendIvData(false); // false prevents loop of same function } - return totalComplete; + return allAvail; } void sendAlarmData() { @@ -494,7 +481,7 @@ class PubMqtt { memset(total, 0, sizeof(float) * 4); for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL == iv) + if ((NULL == iv) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD == mLastIvState[id])) continue; // skip to next inverter record_t<> *rec = iv->getRecordStruct(mSendList.front()); @@ -626,7 +613,6 @@ class PubMqtt { std::queue mSendList; std::queue mAlarmList; subscriptionCb mSubscriptionCb; - bool mIvAvail; // shows if at least one inverter is available bool mReconnectRequest; uint8_t mLastIvState[MAX_NUM_INVERTERS]; uint16_t mIntervalTimeout; From 8f49aae4f35d5fd6629d57afc82105a25e47837e Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:15:53 +0100 Subject: [PATCH 258/431] Delete ahoyTimer.h --- src/utils/ahoyTimer.h | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 src/utils/ahoyTimer.h diff --git a/src/utils/ahoyTimer.h b/src/utils/ahoyTimer.h deleted file mode 100644 index 08c09016..00000000 --- a/src/utils/ahoyTimer.h +++ /dev/null @@ -1,27 +0,0 @@ -//----------------------------------------------------------------------------- -// 2022 Ahoy, https://ahoydtu.de -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ -//----------------------------------------------------------------------------- - -#ifndef __AHOY_TIMER_H__ -#define __AHOY_TIMER_H__ - -#include - -namespace ah { - inline bool checkTicker(uint32_t *ticker, uint32_t interval) { - uint32_t mil = millis(); - if(mil >= *ticker) { - *ticker = mil + interval; - return true; - } - else if((mil + interval) < (*ticker)) { - *ticker = mil + interval; - return true; - } - - return false; - } -} - -#endif /*__AHOY_TIMER_H__*/ From 48c4884e80c0e1ab8253da7d0db5d608c00dc793 Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:22:34 +0100 Subject: [PATCH 259/431] Update web.h --- src/web/web.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/web/web.h b/src/web/web.h index 5641ef0d..89d2dfb0 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -18,7 +18,6 @@ #include "../appInterface.h" #include "../hm/hmSystem.h" -#include "../utils/ahoyTimer.h" #include "../utils/helper.h" #include "html/h/index_html.h" @@ -132,6 +131,8 @@ class Web { } void showUpdate2(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { + mApp->setOnUpdate(); + if(!index) { Serial.printf("Update Start: %s\n", filename.c_str()); #ifndef ESP32 @@ -246,7 +247,7 @@ class Web { AsyncWebServerResponse *response = request->beginResponse(200, F("text/html"), html); response->addHeader("Connection", "close"); request->send(response); - if(reboot) + //if(reboot) mApp->setRebootFlag(); } @@ -263,7 +264,7 @@ class Web { AsyncWebServerResponse *response = request->beginResponse(200, F("text/html"), html); response->addHeader("Connection", "close"); request->send(response); - if(reboot) + //if(reboot) mApp->setRebootFlag(); } @@ -550,8 +551,8 @@ class Web { mConfig->mqtt.port = request->arg("mqttPort").toInt(); mConfig->mqtt.interval = request->arg("mqttInterval").toInt(); mConfig->mqtt.rstYieldMidNight = (request->arg("mqttRstMid") == "on"); - mConfig->mqtt.rstValsNotAvail = (request->arg("mqttRstComStop") == "on"); - mConfig->mqtt.rstValsCommStop = (request->arg("mqttRstNotAvail") == "on"); + mConfig->mqtt.rstValsNotAvail = (request->arg("mqttRstNotAvail") == "on"); + mConfig->mqtt.rstValsCommStop = (request->arg("mqttRstComStop") == "on"); // serial console if(request->arg("serIntvl") != "") { From 5056d7c729f2babd5df113188e864b01a23f30ee Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:25:54 +0100 Subject: [PATCH 260/431] Update ahoywifi.h --- src/wifi/ahoywifi.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 321dbb86..ac8c0dd0 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -34,6 +34,7 @@ class ahoywifi { DISCONNECTED = 0, CONNECTING, CONNECTED, + IN_AP_MODE, GOT_IP } WiFiStatus_t; @@ -41,6 +42,8 @@ class ahoywifi { void setupAp(void); void setupStation(void); void sendNTPpacket(IPAddress& address); + void sortRSSI(int *sort, int n); + void getBSSIDs(void); void connectionEvent(WiFiStatus_t status); #if defined(ESP8266) void onConnect(const WiFiEventStationModeConnected& event); @@ -50,8 +53,7 @@ class ahoywifi { void onWiFiEvent(WiFiEvent_t event); #endif void welcome(String msg); - void sortRSSI(int *sort, int n); - void getBSSIDs(void); + settings_t *mConfig; appWifiCb mAppWifiCb; @@ -67,11 +69,8 @@ class ahoywifi { uint8_t mCnt; uint32_t *mUtcTimestamp; - uint8_t mLoopCnt; - bool mScanActive; - uint8_t mLastApClients; uint8_t mScanCnt; - + bool mScanActive; std::list mBSSIDList; }; From bbee9abd28a35b4e40effe3ae3df8e9da7732707 Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:28:22 +0100 Subject: [PATCH 261/431] Update ahoywifi.cpp --- src/wifi/ahoywifi.cpp | 64 ++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 4ca7f290..8384c118 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -25,8 +25,6 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mStaConn = DISCONNECTED; mCnt = 0; mScanActive = false; - mLastApClients = 0; - mScanCnt = 0; #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); @@ -66,44 +64,31 @@ void ahoywifi::tickWifiLoop() { #if !defined(AP_ONLY) if(mStaConn != GOT_IP) { if (WiFi.softAPgetStationNum() > 0) { // do not reconnect if any AP connection exists - if(WIFI_AP_STA == WiFi.getMode()) { - // first time switch to AP Mode - if(mScanActive && (mLastApClients != WiFi.softAPgetStationNum())) - mScanActive = false; - - // scan is finished - if(!mScanActive) { - WiFi.mode(WIFI_AP); - mDns.start(53, "*", mApIp); - } - - // only once a client connects to AP - if(mLastApClients != WiFi.softAPgetStationNum()) { - mLastApClients = WiFi.softAPgetStationNum(); + if(mStaConn != IN_AP_MODE) { + mStaConn = IN_AP_MODE; + // first time switch to AP Mode + if (mScanActive) { WiFi.scanDelete(); - mAppWifiCb(false); - DBGPRINTLN(F("AP client connected")); - welcome(mApIp.toString()); + mScanActive = false; } + DBGPRINTLN(F("AP client connected")); + welcome(mApIp.toString()); + WiFi.mode(WIFI_AP); + mDns.start(53, "*", mApIp); + mAppWifiCb(true); } mDns.processNextRequest(); return; } - else if(WIFI_AP == WiFi.getMode()) { - mLastApClients = 0; + else if(mStaConn == IN_AP_MODE) { mCnt = 0; - DPRINTLN(DBG_INFO, "DNS stop"); mDns.stop(); WiFi.mode(WIFI_AP_STA); + mStaConn = DISCONNECTED; } mCnt++; - uint8_t timeout = 10; // seconds - if (mStaConn == CONNECTED) // connected but no ip - timeout = 20; - - - if(!mScanActive && mBSSIDList.empty() && ((mCnt % timeout) == 0)) { // start scanning APs with the given SSID + if(!mScanActive && mBSSIDList.empty()) { // start scanning APs with the given SSID DBGPRINT(F("scanning APs with SSID ")); DBGPRINTLN(String(mConfig->sys.stationSsid)); mScanCnt = 0; @@ -115,14 +100,20 @@ void ahoywifi::tickWifiLoop() { #endif return; } + + uint8_t timeout = 10; // seconds + + if (mStaConn == CONNECTED) // connected but no ip + timeout = 20; + DBGPRINT(F("reconnect in ")); DBGPRINT(String(timeout-mCnt)); DBGPRINTLN(F(" seconds")); if(mScanActive) { getBSSIDs(); - //if(!mScanActive) // scan completed - // if ((mCnt % timeout) < 8) - // mCnt = timeout - 2; + if(!mScanActive) // scan completed + if ((mCnt % timeout) < timeout - 2) + mCnt = timeout - 2; } if((mCnt % timeout) == 0) { // try to reconnect after x sec without connection if(mStaConn != CONNECTED) @@ -166,8 +157,6 @@ void ahoywifi::setupAp(void) { WiFi.mode(WIFI_AP_STA); WiFi.softAPConfig(mApIp, mApIp, IPAddress(255, 255, 255, 0)); WiFi.softAP(WIFI_AP_SSID, WIFI_AP_PWD); - - mDns.start(53, "*", mApIp); } @@ -266,10 +255,10 @@ void ahoywifi::sortRSSI(int *sort, int n) { //----------------------------------------------------------------------------- void ahoywifi::scanAvailNetworks(void) { - if(-2 == WiFi.scanComplete()) { + if(!mScanActive) { mScanActive = true; if(WIFI_AP == WiFi.getMode()) - WiFi.mode(WIFI_AP_STA); + WiFi.mode(WIFI_AP_STA); WiFi.scanNetworks(true); } } @@ -291,12 +280,14 @@ void ahoywifi::getAvailNetworks(JsonObject obj) { } mScanActive = false; WiFi.scanDelete(); + if(mStaConn == IN_AP_MODE) + WiFi.mode(WIFI_AP); } //----------------------------------------------------------------------------- void ahoywifi::getBSSIDs() { int n = WiFi.scanComplete(); - if (n < 0){ + if (n < 0) { mScanCnt++; if (mScanCnt < 20) return; @@ -336,7 +327,6 @@ void ahoywifi::connectionEvent(WiFiStatus_t status) { mScanActive = false; } welcome(WiFi.localIP().toString() + F(" (Station)")); - mDns.stop(); WiFi.mode(WIFI_STA); DBGPRINTLN(F("[WiFi] AP disabled")); mAppWifiCb(true); From 155d602e6e56e5d5dbf6bba2d6eeccc3aaa35f13 Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:29:24 +0100 Subject: [PATCH 262/431] Delete CircularBuffer.h --- src/hm/CircularBuffer.h | 161 ---------------------------------------- 1 file changed, 161 deletions(-) delete mode 100644 src/hm/CircularBuffer.h diff --git a/src/hm/CircularBuffer.h b/src/hm/CircularBuffer.h deleted file mode 100644 index 65c9e768..00000000 --- a/src/hm/CircularBuffer.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - CircularBuffer - An Arduino circular buffering library for arbitrary types. - - Created by Ivo Pullens, Emmission, 2014 -- www.emmission.nl - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef CircularBuffer_h -#define CircularBuffer_h - -#if defined(ESP8266) || defined(ESP32) -#define DISABLE_IRQ noInterrupts() -#define RESTORE_IRQ interrupts() -#else -#define DISABLE_IRQ \ - uint8_t sreg = SREG; \ - cli(); - -#define RESTORE_IRQ \ - SREG = sreg; -#endif - -template -class CircularBuffer { - - typedef BUFFERTYPE BufferType; - BufferType Buffer[BUFFERSIZE]; - - public: - CircularBuffer() : m_buff(Buffer) { - m_size = BUFFERSIZE; - clear(); - } - - /** Clear all entries in the circular buffer. */ - void clear(void) - { - m_front = 0; - m_fill = 0; - } - - /** Test if the circular buffer is empty */ - inline bool empty(void) const - { - return !m_fill; - } - - /** Return the number of records stored in the buffer */ - inline uint8_t available(void) const - { - return m_fill; - } - - /** Test if the circular buffer is full */ - inline bool full(void) const - { - return m_fill == m_size; - } - - inline uint8_t getFill(void) const { - return m_fill; - } - - /** Aquire record on front of the buffer, for writing. - * After filling the record, it has to be pushed to actually - * add it to the buffer. - * @return Pointer to record, or NULL when buffer is full. - */ - BUFFERTYPE* getFront(void) const - { - DISABLE_IRQ; - BUFFERTYPE* f = NULL; - if (!full()) - f = get(m_front); - RESTORE_IRQ; - return f; - } - - /** Push record to front of the buffer - * @param record Record to push. If record was aquired previously (using getFront) its - * data will not be copied as it is already present in the buffer. - * @return True, when record was pushed successfully. - */ - bool pushFront(BUFFERTYPE* record) - { - bool ok = false; - DISABLE_IRQ; - if (!full()) - { - BUFFERTYPE* f = get(m_front); - if (f != record) - *f = *record; - m_front = (m_front+1) % m_size; - m_fill++; - ok = true; - } - RESTORE_IRQ; - return ok; - } - - /** Aquire record on back of the buffer, for reading. - * After reading the record, it has to be pop'ed to actually - * remove it from the buffer. - * @return Pointer to record, or NULL when buffer is empty. - */ - BUFFERTYPE* getBack(void) const - { - BUFFERTYPE* b = NULL; - DISABLE_IRQ; - if (!empty()) - b = get(back()); - RESTORE_IRQ; - return b; - } - - /** Remove record from back of the buffer. - * @return True, when record was pop'ed successfully. - */ - bool popBack(void) - { - bool ok = false; - DISABLE_IRQ; - if (!empty()) - { - m_fill--; - ok = true; - } - RESTORE_IRQ; - return ok; - } - - protected: - inline BUFFERTYPE * get(const uint8_t idx) const - { - return &(m_buff[idx]); - } - inline uint8_t back(void) const - { - return (m_front - m_fill + m_size) % m_size; - } - - uint8_t m_size; // Total number of records that can be stored in the buffer. - BUFFERTYPE* const m_buff; - volatile uint8_t m_front; // Index of front element (not pushed yet). - volatile uint8_t m_fill; // Amount of records currently pushed. -}; - -#endif // CircularBuffer_h From 6159c0755973bf458fa4916cca684fab703ec32d Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:41:47 +0100 Subject: [PATCH 263/431] Update hmRadio.h --- src/hm/hmRadio.h | 331 +++++++++++++++++++---------------------------- 1 file changed, 132 insertions(+), 199 deletions(-) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index ee84263b..ea440b8c 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -9,28 +9,10 @@ #include "../utils/dbg.h" #include #include "../utils/crc.h" -#ifndef DISABLE_IRQ - #if defined(ESP8266) || defined(ESP32) - #define DISABLE_IRQ noInterrupts() - #define RESTORE_IRQ interrupts() - #else - #define DISABLE_IRQ \ - uint8_t sreg = SREG; \ - cli(); - #define RESTORE_IRQ \ - SREG = sreg; - #endif -#endif -//#define CHANNEL_HOP // switch between channels or use static channel to send +#define SPI_SPEED 1000000 -#define DEFAULT_RECV_CHANNEL 3 -#define SPI_SPEED 1000000 - -#define DUMMY_RADIO_ID ((uint64_t)0xDEADBEEF01ULL) - -#define RF_CHANNELS 5 -#define RF_LOOP_CNT 300 +#define RF_CHANNELS 5 #define TX_REQ_INFO 0x15 #define TX_REQ_DEVCONTROL 0x51 @@ -61,11 +43,12 @@ const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"}; #define BIT_CNT(x) ((x)<<3) +static volatile bool mIrqRcvd; //----------------------------------------------------------------------------- // HM Radio class //----------------------------------------------------------------------------- -template +template class HmRadio { public: HmRadio() : mNrf24(CE_PIN, CS_PIN, SPI_SPEED) { @@ -84,23 +67,22 @@ class HmRadio { mRfChLst[3] = 61; mRfChLst[4] = 75; + // default channels mTxChIdx = 2; // Start TX with 40 mRxChIdx = 0; // Start RX with 03 - mRxLoopCnt = RF_LOOP_CNT; - mSendCnt = 0; - mRetransmits = 0; + mSendCnt = 0; + mRetransmits = 0; - mSerialDebug = false; - mIrqRcvd = false; + mSerialDebug = false; + mIrqRcvd = false; } ~HmRadio() {} - void setup(BUFFER *ctrl, uint8_t ampPwr = RF24_PA_LOW, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN) { + void setup(uint8_t ampPwr = RF24_PA_LOW, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN) { DPRINTLN(DBG_VERBOSE, F("hmRadio.h:setup")); pinMode(irq, INPUT_PULLUP); - mBufCtrl = ctrl; - + attachInterrupt(digitalPinToInterrupt(irq), []()IRAM_ATTR{ mIrqRcvd = true; }, FALLING); uint32_t dtuSn = 0x87654321; uint32_t chipID = 0; // will be filled with last 3 bytes of MAC @@ -121,27 +103,22 @@ class HmRadio { DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; mNrf24.begin(ce, cs); - mNrf24.setRetries(0, 0); + mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms - mNrf24.setChannel(DEFAULT_RECV_CHANNEL); + mNrf24.setChannel(mRfChLst[mRxChIdx]); mNrf24.setDataRate(RF24_250KBPS); + mNrf24.setAutoAck(true); + mNrf24.enableDynamicPayloads(); mNrf24.setCRCLength(RF24_CRC_16); - mNrf24.setAutoAck(false); - mNrf24.setPayloadSize(MAX_RF_PAYLOAD_SIZE); mNrf24.setAddressWidth(5); mNrf24.openReadingPipe(1, DTU_RADIO_ID); - mNrf24.enableDynamicPayloads(); - // enable only receiving interrupts - mNrf24.maskIRQ(true, true, false); + // enable all receiving interrupts + mNrf24.maskIRQ(false, false, false); DPRINT(DBG_INFO, F("RF24 Amp Pwr: RF24_PA_")); DPRINTLN(DBG_INFO, String(rf24AmpPowerNames[ampPwr])); mNrf24.setPALevel(ampPwr & 0x03); - mNrf24.startListening(); - - - mTxCh = setDefaultChannels(); if(mNrf24.isChipConnected()) { DPRINTLN(DBG_INFO, F("Radio Config:")); @@ -151,77 +128,70 @@ class HmRadio { DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); } - void loop(void) { - if(mIrqRcvd) { - DISABLE_IRQ; - mIrqRcvd = false; - bool tx_ok, tx_fail, rx_ready; - mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH - RESTORE_IRQ; - uint8_t pipe, len; - packet_t *p; - while(mNrf24.available(&pipe)) { - if(!mBufCtrl->full()) { - p = mBufCtrl->getFront(); - p->rxCh = mRfChLst[mRxChIdx]; - len = mNrf24.getPayloadSize(); - if(len > MAX_RF_PAYLOAD_SIZE) - len = MAX_RF_PAYLOAD_SIZE; - - mNrf24.read(p->packet, len); - mBufCtrl->pushFront(p); - yield(); + bool loop(void) { + if (!mIrqRcvd) + return false; // nothing to do + mIrqRcvd = false; + bool tx_ok, tx_fail, rx_ready; + mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH + mNrf24.flush_tx(); // empty TX FIFO + //DBGPRINTLN("TX whatHappened Ch" + String(mRfChLst[mTxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); + + // start listening on the default RX channel + mRxChIdx = 0; + mNrf24.setChannel(mRfChLst[mRxChIdx]); + mNrf24.startListening(); + + //uint32_t debug_ms = millis(); + uint16_t cnt = 300; // that is 60 times 5 channels + while (0 < cnt--) { + uint32_t startMillis = millis(); + while (millis()-startMillis < 4) { // listen 4ms to each channel + if (mIrqRcvd) { + mIrqRcvd = false; + if (getReceived()) { // everything received + //DBGPRINTLN("RX finished Cnt: " + String(300-cnt) + " time used: " + String(millis()-debug_ms)+ " ms"); + mNrf24.stopListening(); + return true; + } } - else - break; + yield(); } - mNrf24.flush_rx(); // drop the packet - RESTORE_IRQ; + switchRxCh(); // switch to next RX channel + yield(); } + // not finished but time is over + //DBGPRINTLN("RX not finished: 300 time used: " + String(millis()-debug_ms)+ " ms"); + mNrf24.stopListening(); + return true; } + bool isChipConnected(void) { + //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:isChipConnected")); + return mNrf24.isChipConnected(); + } void enableDebug() { mSerialDebug = true; } - void handleIntr(void) { - mIrqRcvd = true; - } - - uint8_t setDefaultChannels(void) { - //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:setDefaultChannels")); - mTxChIdx = 2; // Start TX with 40 - mRxChIdx = 0; // Start RX with 03 - return mRfChLst[mTxChIdx]; - } - void sendControlPacket(uint64_t invId, uint8_t cmd, uint16_t *data, bool isRetransmit) { DPRINTLN(DBG_INFO, F("sendControlPacket cmd: 0x") + String(cmd, HEX)); - sendCmdPacket(invId, TX_REQ_DEVCONTROL, SINGLE_FRAME, false); - uint8_t cnt = 0; - mTxBuf[10 + cnt++] = cmd; // cmd -> 0 on, 1 off, 2 restart, 11 active power, 12 reactive power, 13 power factor - mTxBuf[10 + cnt++] = 0x00; + initPacket(invId, TX_REQ_DEVCONTROL, SINGLE_FRAME); + uint8_t cnt = 10; + mTxBuf[cnt++] = cmd; // cmd -> 0 on, 1 off, 2 restart, 11 active power, 12 reactive power, 13 power factor + mTxBuf[cnt++] = 0x00; if(cmd >= ActivePowerContr && cmd <= PFSet) { // ActivePowerContr, ReactivePowerContr, PFSet - mTxBuf[10 + cnt++] = ((data[0] * 10) >> 8) & 0xff; // power limit - mTxBuf[10 + cnt++] = ((data[0] * 10) ) & 0xff; // power limit - mTxBuf[10 + cnt++] = ((data[1] ) >> 8) & 0xff; // setting for persistens handlings - mTxBuf[10 + cnt++] = ((data[1] ) ) & 0xff; // setting for persistens handling + mTxBuf[cnt++] = ((data[0] * 10) >> 8) & 0xff; // power limit + mTxBuf[cnt++] = ((data[0] * 10) ) & 0xff; // power limit + mTxBuf[cnt++] = ((data[1] ) >> 8) & 0xff; // setting for persistens handlings + mTxBuf[cnt++] = ((data[1] ) ) & 0xff; // setting for persistens handling } - - // crc control data - uint16_t crc = ah::crc16(&mTxBuf[10], cnt); - mTxBuf[10 + cnt++] = (crc >> 8) & 0xff; - mTxBuf[10 + cnt++] = (crc ) & 0xff; - - // crc over all - mTxBuf[10 + cnt] = ah::crc8(mTxBuf, 10 + cnt); - - sendPacket(invId, mTxBuf, 10 + cnt + 1, isRetransmit, true); + sendPacket(invId, cnt, isRetransmit, true); } void sendTimePacket(uint64_t invId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit) { DPRINTLN(DBG_DEBUG, F("sendTimePacket 0x") + String(cmd, HEX)); - sendCmdPacket(invId, TX_REQ_INFO, ALL_FRAMES, isRetransmit, false); + initPacket(invId, TX_REQ_INFO, ALL_FRAMES); mTxBuf[10] = cmd; // cid mTxBuf[11] = 0x00; CP_U32_LittleEndian(&mTxBuf[12], ts); @@ -229,61 +199,16 @@ class HmRadio { mTxBuf[18] = (alarmMesId >> 8) & 0xff; mTxBuf[19] = (alarmMesId ) & 0xff; } - uint16_t crc = ah::crc16(&mTxBuf[10], 14); - mTxBuf[24] = (crc >> 8) & 0xff; - mTxBuf[25] = (crc ) & 0xff; - mTxBuf[26] = ah::crc8(mTxBuf, 26); - - sendPacket(invId, mTxBuf, 27, isRetransmit, true); + sendPacket(invId, 24, isRetransmit, true); } - void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool calcCrc = true) { - DPRINTLN(DBG_VERBOSE, F("sendCmdPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); - memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); - mTxBuf[0] = mid; // message id - CP_U32_BigEndian(&mTxBuf[1], (invId >> 8)); - CP_U32_BigEndian(&mTxBuf[5], (DTU_RADIO_ID >> 8)); - mTxBuf[9] = pid; - if(calcCrc) { - mTxBuf[10] = ah::crc8(mTxBuf, 10); - sendPacket(invId, mTxBuf, 11, isRetransmit, false); - } + void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit) { + initPacket(invId, mid, pid); + sendPacket(invId, 10, isRetransmit, false); } - bool checkPaketCrc(uint8_t buf[], uint8_t *len, uint8_t rxCh) { - //DPRINTLN(DBG_INFO, F("hmRadio.h:checkPaketCrc")); - *len = (buf[0] >> 2); - if(*len > (MAX_RF_PAYLOAD_SIZE - 2)) - *len = MAX_RF_PAYLOAD_SIZE - 2; - for(uint8_t i = 1; i < (*len + 1); i++) { - buf[i-1] = (buf[i] << 1) | (buf[i+1] >> 7); - } - - uint8_t crc = ah::crc8(buf, *len-1); - bool valid = (crc == buf[*len-1]); - - return valid; - } - - bool switchRxCh(uint16_t addLoop = 0) { - if(!mNrf24.isChipConnected()) - return true; - mRxLoopCnt += addLoop; - if(mRxLoopCnt != 0) { - mRxLoopCnt--; - DISABLE_IRQ; - mNrf24.stopListening(); - mNrf24.setChannel(getRxNxtChannel()); - mNrf24.startListening(); - RESTORE_IRQ; - } - return (0 == mRxLoopCnt); // receive finished - } - - void dumpBuf(const char *info, uint8_t buf[], uint8_t len) { + void dumpBuf(uint8_t buf[], uint8_t len) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:dumpBuf")); - if(NULL != info) - DBGPRINT(String(info)); for(uint8_t i = 0; i < len; i++) { DHEX(buf[i]); DBGPRINT(" "); @@ -291,11 +216,6 @@ class HmRadio { DBGPRINTLN(""); } - bool isChipConnected(void) { - //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:isChipConnected")); - return mNrf24.isChipConnected(); - } - uint8_t getDataRate(void) { if(!mNrf24.isChipConnected()) return 3; // unkown @@ -306,7 +226,7 @@ class HmRadio { return mNrf24.isPVariant(); } - + std::queue mBufCtrl; uint32_t mSendCnt; uint32_t mRetransmits; @@ -314,78 +234,91 @@ class HmRadio { bool mSerialDebug; private: - void sendPacket(uint64_t invId, uint8_t buf[], uint8_t len, bool isRetransmit, bool clear=false) { + bool getReceived(void) { + bool tx_ok, tx_fail, rx_ready; + mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH + DBGPRINTLN("RX whatHappened Ch" + String(mRfChLst[mRxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); + + bool isLastPackage = false; + while(mNrf24.available()) { + uint8_t len; + len = mNrf24.getDynamicPayloadSize(); // if payload size > 32, corrupt payload has been flushed + if (len > 0) { + packet_t p; + p.ch = mRfChLst[mRxChIdx]; + p.len = len; + mNrf24.read(p.packet, len); + mBufCtrl.push(p); + if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command + isLastPackage = (p.packet[9] > 0x81); // > 0x81 indicates last packet received + else if (p.packet[0] != 0x00) // ignore fragment number zero + isLastPackage = true; // response from dev control command + yield(); + } + } + return isLastPackage; + } + + void switchRxCh() { + mNrf24.stopListening(); + // get next channel index + if(++mRxChIdx >= RF_CHANNELS) + mRxChIdx = 0; + mNrf24.setChannel(mRfChLst[mRxChIdx]); + mNrf24.startListening(); + } + + void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { + DPRINTLN(DBG_VERBOSE, F("initPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); + memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); + mTxBuf[0] = mid; // message id + CP_U32_BigEndian(&mTxBuf[1], (invId >> 8)); + CP_U32_BigEndian(&mTxBuf[5], (DTU_RADIO_ID >> 8)); + mTxBuf[9] = pid; + } + + void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool clear=false) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); - //dumpBuf("SEN ", buf, len); + + // append crc's + if (len > 10) { + // crc control data + uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); + mTxBuf[len++] = (crc >> 8) & 0xff; + mTxBuf[len++] = (crc ) & 0xff; + } + // crc over all + mTxBuf[len++] = ah::crc8(mTxBuf, len); + if(mSerialDebug) { DPRINT(DBG_INFO, "TX " + String(len) + "B Ch" + String(mRfChLst[mTxChIdx]) + " | "); - dumpBuf(NULL, buf, len); + dumpBuf(mTxBuf, len); } - DISABLE_IRQ; - mNrf24.stopListening(); - - if(clear) - mRxLoopCnt = RF_LOOP_CNT; - mNrf24.setChannel(mRfChLst[mTxChIdx]); - mTxCh = getTxNxtChannel(); // switch channel for next packet - mNrf24.openWritingPipe(invId); // TODO: deprecated - mNrf24.setCRCLength(RF24_CRC_16); - mNrf24.enableDynamicPayloads(); - mNrf24.setAutoAck(true); - mNrf24.setRetries(3, 15); // 3*250us and 15 loops -> 11.25ms - mNrf24.write(buf, len); + mNrf24.openWritingPipe(reinterpret_cast(&invId)); + mNrf24.startWrite(mTxBuf, len, false); // false = request ACK response - // Try to avoid zero payload acks (has no effect) - mNrf24.openWritingPipe(DUMMY_RADIO_ID); // TODO: why dummy radio id?, deprecated - mRxChIdx = 0; - mNrf24.setChannel(mRfChLst[mRxChIdx]); - mNrf24.setAutoAck(false); - mNrf24.setRetries(0, 0); - mNrf24.disableDynamicPayloads(); - mNrf24.setCRCLength(RF24_CRC_DISABLED); - mNrf24.startListening(); + // switch TX channel for next packet + if(++mTxChIdx >= RF_CHANNELS) + mTxChIdx = 0; - RESTORE_IRQ; if(isRetransmit) mRetransmits++; else mSendCnt++; } - uint8_t getTxNxtChannel(void) { - - if(++mTxChIdx >= RF_CHANNELS) - mTxChIdx = 0; - return mRfChLst[mTxChIdx]; - } - - uint8_t getRxNxtChannel(void) { - - if(++mRxChIdx >= RF_CHANNELS) - mRxChIdx = 0; - return mRfChLst[mRxChIdx]; - } - uint64_t DTU_RADIO_ID; - uint8_t mTxCh; - uint8_t mTxChIdx; - uint8_t mRfChLst[RF_CHANNELS]; + uint8_t mTxChIdx; uint8_t mRxChIdx; - uint16_t mRxLoopCnt; RF24 mNrf24; - BUFFER *mBufCtrl; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; - - DevControlCmdType DevControlCmd; - - volatile bool mIrqRcvd; }; #endif /*__RADIO_H__*/ From 9638414ce29abcf80d51b6cb95c7cd1708ad8867 Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:44:19 +0100 Subject: [PATCH 264/431] Update hmSystem.h --- src/hm/hmSystem.h | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 85976cbd..58099d40 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -8,19 +8,11 @@ #include "hmInverter.h" #include "hmRadio.h" -#include "CircularBuffer.h" -typedef CircularBuffer BufferType; -typedef HmRadio RadioType; - -template > +template > class HmSystem { public: - typedef RADIO RadioType; - RadioType Radio; - typedef BUFFER BufferType; - BufferType BufCtrl; - //DevControlCmdType DevControlCmd; + HmRadio<> Radio; HmSystem() { mNumInv = 0; @@ -30,11 +22,11 @@ class HmSystem { } void setup() { - Radio.setup(&BufCtrl); + Radio.setup(); } void setup(uint8_t ampPwr, uint8_t irqPin, uint8_t cePin, uint8_t csPin) { - Radio.setup(&BufCtrl, ampPwr, irqPin, cePin, csPin); + Radio.setup(ampPwr, irqPin, cePin, csPin); } void addInverters(cfgInst_t *config) { From c241f356a0549cd2d9514ad07c2b843f02ff3c85 Mon Sep 17 00:00:00 2001 From: beegee3 <119520001+beegee3@users.noreply.github.com> Date: Sun, 5 Feb 2023 15:47:29 +0100 Subject: [PATCH 265/431] Update payload.h --- src/hm/payload.h | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/hm/payload.h b/src/hm/payload.h index 7e66eb76..72166390 100644 --- a/src/hm/payload.h +++ b/src/hm/payload.h @@ -46,7 +46,8 @@ class Payload { reset(i); } mSerialDebug = false; - mHighPrioIv = NULL; + mHighPrioIv = NULL; + mCbAlarm = NULL; } void enableSerialDebug(bool enable) { @@ -117,7 +118,7 @@ class Payload { } } - void add(packet_t *p, uint8_t len) { + void add(packet_t *p) { Inverter<> *iv = mSys->findInverter(&p->packet[1]); if(NULL == iv) @@ -132,8 +133,8 @@ class Payload { } else { DPRINTLN(DBG_DEBUG, "PID: 0x" + String(*pid, HEX)); if ((*pid & 0x7F) < MAX_PAYLOAD_ENTRIES) { - memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], len - 11); - mPayload[iv->id].len[(*pid & 0x7F) - 1] = len - 11; + memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], p->len - 11); + mPayload[iv->id].len[(*pid & 0x7F) - 1] = p->len - 11; mPayload[iv->id].gotFragment = true; } @@ -194,21 +195,24 @@ class Payload { if (mPayload[iv->id].retransmits < mMaxRetrans) { mPayload[iv->id].retransmits++; if(false == mPayload[iv->id].gotFragment) { + /* DPRINTLN(DBG_WARN, F("nothing received: Request Complete Retransmit")); mPayload[iv->id].txCmd = iv->getQueuedCmd(); DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket 0x") + String(mPayload[iv->id].txCmd, HEX)); mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + */ + DPRINTLN(DBG_WARN, F("(#") + String(iv->id) + F(") nothing received")); + mPayload[iv->id].retransmits = mMaxRetrans; } else { for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { if (mPayload[iv->id].len[i] == 0) { DPRINTLN(DBG_WARN, F("Frame ") + String(i + 1) + F(" missing: Request Retransmit")); - mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true, true); + mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); break; // only request retransmit one frame per loop } yield(); } } - mSys->Radio.switchRxCh(100); } } } @@ -241,13 +245,13 @@ class Payload { if (mSerialDebug) { DPRINT(DBG_INFO, F("Payload (") + String(payloadLen) + "): "); - mSys->Radio.dumpBuf(NULL, payload, payloadLen); + mSys->Radio.dumpBuf(payload, payloadLen); } if (NULL == rec) { DPRINTLN(DBG_ERROR, F("record is NULL!")); } else if ((rec->pyldLen == payloadLen) || (0 == rec->pyldLen)) { - if (mPayload[iv->id].txId == (TX_REQ_INFO + 0x80)) + if (mPayload[iv->id].txId == (TX_REQ_INFO + ALL_FRAMES)) mStat->rxSuccess++; rec->ts = mPayload[iv->id].ts; @@ -266,7 +270,8 @@ class Payload { code = iv->parseAlarmLog(i++, payload, payloadLen, &start, &end); if(0 == code) break; - (mCbAlarm)(code, start, end); + if (NULL != mCbAlarm) + (mCbAlarm)(code, start, end); yield(); } } @@ -278,9 +283,7 @@ class Payload { iv->setQueuedCmdFinished(); } } - yield(); - } } @@ -290,7 +293,8 @@ class Payload { } void notify(uint16_t code, uint32_t start, uint32_t endTime) { - (mCbAlarm)(code, start, endTime); + if (NULL != mCbAlarm) + (mCbAlarm)(code, start, endTime); } bool build(uint8_t id, bool *complete) { From a9179ec1eab666a9466c6366fa1bbc114d4bf1c5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 5 Feb 2023 22:14:59 +0100 Subject: [PATCH 266/431] fixed mixed reset flags #648 fixed `mCbAlarm` if MQTT is not used #653 --- src/CHANGES.md | 4 ++++ src/hm/payload.h | 7 +++++-- src/web/web.h | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 9e31ada2..7167da6b 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,10 @@ (starting from release version `0.5.66`) +## 0.5.79 +* fixed mixed reset flags #648 +* fixed `mCbAlarm` if MQTT is not used #653 + ## 0.5.78 * further improvements regarding wifi #611, fix connection if only one AP with same SSID is there * fix endless loop in `zerovalues` #564 diff --git a/src/hm/payload.h b/src/hm/payload.h index 7e66eb76..bc21a517 100644 --- a/src/hm/payload.h +++ b/src/hm/payload.h @@ -47,6 +47,7 @@ class Payload { } mSerialDebug = false; mHighPrioIv = NULL; + mCbAlarm = NULL; } void enableSerialDebug(bool enable) { @@ -266,7 +267,8 @@ class Payload { code = iv->parseAlarmLog(i++, payload, payloadLen, &start, &end); if(0 == code) break; - (mCbAlarm)(code, start, end); + if(NULL != mCbAlarm) + (mCbAlarm)(code, start, end); yield(); } } @@ -290,7 +292,8 @@ class Payload { } void notify(uint16_t code, uint32_t start, uint32_t endTime) { - (mCbAlarm)(code, start, endTime); + if(NULL != mCbAlarm) + (mCbAlarm)(code, start, endTime); } bool build(uint8_t id, bool *complete) { diff --git a/src/web/web.h b/src/web/web.h index 5641ef0d..1c8af295 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -550,8 +550,8 @@ class Web { mConfig->mqtt.port = request->arg("mqttPort").toInt(); mConfig->mqtt.interval = request->arg("mqttInterval").toInt(); mConfig->mqtt.rstYieldMidNight = (request->arg("mqttRstMid") == "on"); - mConfig->mqtt.rstValsNotAvail = (request->arg("mqttRstComStop") == "on"); - mConfig->mqtt.rstValsCommStop = (request->arg("mqttRstNotAvail") == "on"); + mConfig->mqtt.rstValsCommStop = (request->arg("mqttRstComStop") == "on"); + mConfig->mqtt.rstValsNotAvail = (request->arg("mqttRstNotAvail") == "on"); // serial console if(request->arg("serIntvl") != "") { From 3ed81513d5ed4b8ad2096aef49a012918d67b6c9 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 5 Feb 2023 22:44:10 +0100 Subject: [PATCH 267/431] next changes from @beegee many thanks for your contribution! replaced `CircularBuffer` by `std::queue` reworked `hmRadio.h` completely (interrupts, packaging) fix exception while `reboot` cleanup MQTT coding --- src/CHANGES.md | 5 +++++ src/defines.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 7167da6b..94d31e44 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -5,6 +5,11 @@ ## 0.5.79 * fixed mixed reset flags #648 * fixed `mCbAlarm` if MQTT is not used #653 +* next changes from @beegee many thanks for your contribution! +* replaced `CircularBuffer` by `std::queue` +* reworked `hmRadio.h` completely (interrupts, packaging) +* fix exception while `reboot` +* cleanup MQTT coding ## 0.5.78 * further improvements regarding wifi #611, fix connection if only one AP with same SSID is there diff --git a/src/defines.h b/src/defines.h index d5f0fcb3..2a12e0e6 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 78 +#define VERSION_PATCH 79 //------------------------------------- typedef struct { From a85ed6c0897ddc6883da28d8882820abb0333795 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 5 Feb 2023 23:14:33 +0100 Subject: [PATCH 268/431] fixed MQTT `autodiscover` #630 thanks to @antibill51 --- src/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CHANGES.md b/src/CHANGES.md index 94d31e44..09df4b0b 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -5,6 +5,7 @@ ## 0.5.79 * fixed mixed reset flags #648 * fixed `mCbAlarm` if MQTT is not used #653 +* fixed MQTT `autodiscover` #630 thanks to @antibill51 * next changes from @beegee many thanks for your contribution! * replaced `CircularBuffer` by `std::queue` * reworked `hmRadio.h` completely (interrupts, packaging) From edefcf1c830b5ea7cd202a9d27395811a6f5a03b Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 6 Feb 2023 00:07:58 +0100 Subject: [PATCH 269/431] fix Interrupt fix connect to WiFi with only one AP --- src/app.cpp | 1 + src/app.h | 5 +++++ src/hm/hmRadio.h | 5 ++++- src/main.cpp | 10 ++++++++++ src/wifi/ahoywifi.cpp | 13 ++++++------- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index f5478f0f..2f1bd58d 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -13,6 +13,7 @@ app::app() : ah::Scheduler() {} //----------------------------------------------------------------------------- void app::setup() { + mSys = NULL; Serial.begin(115200); while (!Serial) yield(); diff --git a/src/app.h b/src/app.h index d3709b89..36a77f9a 100644 --- a/src/app.h +++ b/src/app.h @@ -60,6 +60,11 @@ class app : public IApp, public ah::Scheduler { void onWifi(bool gotIp); void regularTickers(void); + void handleIntr(void) { + if(NULL != mSys) + mSys->Radio.handleIntr(); + } + uint32_t getUptime() { return Scheduler::getUptime(); } diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index ea440b8c..9f671c54 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -82,7 +82,6 @@ class HmRadio { void setup(uint8_t ampPwr = RF24_PA_LOW, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN) { DPRINTLN(DBG_VERBOSE, F("hmRadio.h:setup")); pinMode(irq, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(irq), []()IRAM_ATTR{ mIrqRcvd = true; }, FALLING); uint32_t dtuSn = 0x87654321; uint32_t chipID = 0; // will be filled with last 3 bytes of MAC @@ -166,6 +165,10 @@ class HmRadio { return true; } + void handleIntr(void) { + mIrqRcvd = true; + } + bool isChipConnected(void) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:isChipConnected")); return mNrf24.isChipConnected(); diff --git a/src/main.cpp b/src/main.cpp index 42ed55f4..c585d0f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,11 +7,21 @@ #include "app.h" #include "config/config.h" + app myApp; +//----------------------------------------------------------------------------- +IRAM_ATTR void handleIntr(void) { + myApp.handleIntr(); +} + + //----------------------------------------------------------------------------- void setup() { myApp.setup(); + + // TODO: move to HmRadio + attachInterrupt(digitalPinToInterrupt(myApp.getIrqPin()), handleIntr, FALLING); } diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 8384c118..dc8f03b5 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -88,7 +88,12 @@ void ahoywifi::tickWifiLoop() { } mCnt++; - if(!mScanActive && mBSSIDList.empty()) { // start scanning APs with the given SSID + uint8_t timeout = 10; // seconds + if (mStaConn == CONNECTED) // connected but no ip + timeout = 20; + + + if(!mScanActive && mBSSIDList.empty() && ((mCnt % timeout) == 0)) { // start scanning APs with the given SSID DBGPRINT(F("scanning APs with SSID ")); DBGPRINTLN(String(mConfig->sys.stationSsid)); mScanCnt = 0; @@ -100,12 +105,6 @@ void ahoywifi::tickWifiLoop() { #endif return; } - - uint8_t timeout = 10; // seconds - - if (mStaConn == CONNECTED) // connected but no ip - timeout = 20; - DBGPRINT(F("reconnect in ")); DBGPRINT(String(timeout-mCnt)); DBGPRINTLN(F(" seconds")); From e7fff27a4a6f4213fb0cf22ad80be109c6fc14f0 Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 6 Feb 2023 18:43:09 +0100 Subject: [PATCH 270/431] added further inverter and alarm info to prometheus endpoint --- doc/prometheus_ep_description.md | 28 ++++++------ src/web/web.h | 73 ++++++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/doc/prometheus_ep_description.md b/doc/prometheus_ep_description.md index bce0525f..9d274f1e 100644 --- a/doc/prometheus_ep_description.md +++ b/doc/prometheus_ep_description.md @@ -4,23 +4,24 @@ Metrics available for AhoyDTU device, inverters and channels. Prometheus metrics provided at `/metrics`. ## Labels -| Label name | Description | -|:-----------|:--------------------------------------| -| version | current installed version of AhoyDTU | -| image | currently not used | -| devicename | Device name from setup | -| name | Inverter name from setup | -| serial | Serial number of inverter | -| enabled | Communication enable for inverter | -| inverter | Inverter name from setup | -| channel | Channel name from setup | - +| Label name | Description | +|:-------------|:--------------------------------------| +| version | current installed version of AhoyDTU | +| image | currently not used | +| devicename | Device name from setup | +| name | Inverter name from setup | +| serial | Serial number of inverter | +| inverter | Inverter name from setup | +| channel | Channel name from setup | ## Exported Metrics | Metric name | Type | Description | Labels | |----------------------------------------|---------|--------------------------------------------------------|--------------| | `ahoy_solar_info` | Gauge | Information about the AhoyDTU device | version, image, devicename | -| `ahoy_solar_inverter_info` | Gauge | Information about the configured inverter(s) | name, serial, enabled | +| `ahoy_solar_inverter_info` | Gauge | Information about the configured inverter(s) | name, serial | +| `ahoy_solar_inverter_enabled` | Gauge | Is the inverter enabled? | inverter | +| `ahoy_solar_inverter_is_available` | Gauge | is the inverter available? | inverter | +| `ahoy_solar_inverter_is_producing` | Gauge | Is the inverter producing? | inverter | | `ahoy_solar_U_AC_volt` | Gauge | AC voltage of inverter [V] | inverter | | `ahoy_solar_I_AC_ampere` | Gauge | AC current of inverter [A] | inverter | | `ahoy_solar_P_AC_watt` | Gauge | AC power of inverter [W] | inverter | @@ -28,7 +29,8 @@ Prometheus metrics provided at `/metrics`. | `ahoy_solar_F_AC_hertz` | Gauge | AC frequency [Hz] | inverter | | `ahoy_solar_PF_AC` | Gauge | AC Power factor | inverter | | `ahoy_solar_Temp_celsius` | Gauge | Temperature of inverter | inverter | -| `ahoy_solar_ALARM_MES_ID` | Gauge | Last alarm message id of inverter | inverter | +| `ahoy_solar_ALARM_MES_ID` | Gauge | Alarm message index of inverter | inverter | +| `ahoy_solar_LastAlarmCode` | Gauge | Last alarm code from inverter | inverter | | `ahoy_solar_YieldDay_wattHours` | Counter | Energy converted to AC per day [Wh] | inverter | | `ahoy_solar_YieldTotal_kilowattHours` | Counter | Energy converted to AC since reset [kWh] | inverter | | `ahoy_solar_P_DC_watt` | Gauge | DC power of inverter [W] | inverter | diff --git a/src/web/web.h b/src/web/web.h index be4df73b..887f65aa 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -132,7 +132,7 @@ class Web { void showUpdate2(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { mApp->setOnUpdate(); - + if(!index) { Serial.printf("Update Start: %s\n", filename.c_str()); #ifndef ESP32 @@ -735,7 +735,7 @@ class Web { #ifdef ENABLE_PROMETHEUS_EP enum { - metricsStateStart, metricsStateInverter, metricStateChannel,metricsStateEnd + metricsStateStart, metricsStateInverter, metricStateRealtimeData,metricsStateAlarmData,metricsStateEnd } metricsStep; int metricsInverterId,metricsChannelId; @@ -749,15 +749,22 @@ class Web { Inverter<> *iv; record_t<> *rec; statistics_t *stat; + String promUnit, promType; String metrics; char type[60], topic[100], val[25]; size_t len = 0; + int alarmChannelId; switch (metricsStep) { case metricsStateStart: // System Info & NRF Statistics : fit to one packet - snprintf(topic,sizeof(topic),"# TYPE ahoy_solar_info gauge\nahoy_solar_info{version=\"%s\",image=\"\",devicename=\"%s\"} 1\n", + snprintf(type,sizeof(type),"# TYPE ahoy_solar_info gauge\n"); + snprintf(topic,sizeof(topic),"ahoy_solar_info{version=\"%s\",image=\"\",devicename=\"%s\"} 1\n", mApp->getVersion(), mConfig->sys.deviceName); - metrics = topic; + metrics = String(type) + String(topic); + + snprintf(topic,sizeof(topic),"# TYPE ahoy_solar_freeheap gauge\nahoy_solar_freeheap{devicename=\"%s\"} %u\n",mConfig->sys.deviceName,ESP.getFreeHeap()); + metrics += String(topic); + // NRF Statistics stat = mApp->getStatistics(); metrics += radioStatistic(F("rx_success"), stat->rxSuccess); @@ -776,24 +783,40 @@ class Web { if (metricsInverterId < mSys->getNumInverters()) { iv = mSys->getInverterByPos(metricsInverterId); if(NULL != iv) { - // Inverter info - len = snprintf((char *)buffer, maxLen, "ahoy_solar_inverter_info{name=\"%s\",serial=\"%12llx\",enabled=\"%d\"} 1\n", - iv->config->name, iv->config->serial.u64,iv->config->enabled); - // Start Channel loop for this inverter + // Inverter info : fit to one packet + snprintf(type,sizeof(type),"# TYPE ahoy_solar_inverter_info gauge\n"); + snprintf(topic,sizeof(topic),"ahoy_solar_inverter_info{name=\"%s\",serial=\"%12llx\"} 1\n", + iv->config->name, iv->config->serial.u64); + metrics = String(type) + String(topic); + + snprintf(type,sizeof(type),"# TYPE ahoy_solar_inverter_is_enabled gauge\n"); + snprintf(topic,sizeof(topic),"ahoy_solar_inverter_is_enabled {inverter=\"%s\"} %d\n",iv->config->name,iv->config->enabled); + metrics += String(type) + String(topic); + + snprintf(type,sizeof(type),"# TYPE ahoy_solar_inverter_is_available gauge\n"); + snprintf(topic,sizeof(topic),"ahoy_solar_inverter_is_available {inverter=\"%s\"} %d\n",iv->config->name,iv->isAvailable(mApp->getTimestamp())); + metrics += String(type) + String(topic); + + snprintf(type,sizeof(type),"# TYPE ahoy_solar_inverter_is_producing gauge\n"); + snprintf(topic,sizeof(topic),"ahoy_solar_inverter_is_producing {inverter=\"%s\"} %d\n",iv->config->name,iv->isProducing(mApp->getTimestamp())); + metrics += String(type) + String(topic); + + len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str()); + + // Start Realtime Data Channel loop for this inverter metricsChannelId = 0; - metricsStep = metricStateChannel; + metricsStep = metricStateRealtimeData; } } else { metricsStep = metricsStateEnd; } break; - case metricStateChannel: // Channel loop + case metricStateRealtimeData: // Realtime Data Channel loop iv = mSys->getInverterByPos(metricsInverterId); rec = iv->getRecordStruct(RealTimeRunData_Debug); if (metricsChannelId < rec->length) { uint8_t channel = rec->assign[metricsChannelId].ch; - String promUnit, promType; std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(metricsChannelId, rec)); snprintf(type, sizeof(type), "# TYPE ahoy_solar_%s%s %s", iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), promType.c_str()); if (0 == channel) { @@ -808,12 +831,34 @@ class Web { } else { len = snprintf((char*)buffer,maxLen,"#\n"); // At least one char to send otherwise the transmission ends. - // All channels processed --> try next inverter - metricsInverterId++; - metricsStep = metricsStateInverter; + // All realtime data channels processed --> try alarm data + metricsStep = metricsStateAlarmData; } break; + case metricsStateAlarmData: // Alarm Info loop + iv = mSys->getInverterByPos(metricsInverterId); + rec = iv->getRecordStruct(AlarmData); + // simple hack : there is only one channel with alarm data + // TODO: find the right one channel with the alarm id + alarmChannelId = 0; + // printf("AlarmData Length %d\n",rec->length); + if (alarmChannelId < rec->length) + { + //uint8_t channel = rec->assign[alarmChannelId].ch; + std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(alarmChannelId, rec)); + snprintf(type, sizeof(type), "# TYPE ahoy_solar_%s%s %s", iv->getFieldName(alarmChannelId, rec), promUnit.c_str(), promType.c_str()); + snprintf(topic, sizeof(topic), "ahoy_solar_%s%s{inverter=\"%s\"}", iv->getFieldName(alarmChannelId, rec), promUnit.c_str(), iv->config->name); + snprintf(val, sizeof(val), "%.3f", iv->getValue(alarmChannelId, rec)); + len = snprintf((char*)buffer,maxLen,"%s\n%s %s\n",type,topic,val); + } else { + len = snprintf((char*)buffer,maxLen,"#\n"); // At least one char to send otherwise the transmission ends. + } + // alarm channel processed --> try next inverter + metricsInverterId++; + metricsStep = metricsStateInverter; + break; + case metricsStateEnd: default: // end of transmission len = 0; From 0e6faa79e3e699066c0512a8e14ecf148745cda7 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 6 Feb 2023 21:47:12 +0100 Subject: [PATCH 271/431] fixed communication #656 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/hm/hmRadio.h | 4 ++-- src/hm/payload.h | 1 - 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 09df4b0b..ae341ba6 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,9 @@ (starting from release version `0.5.66`) +## 0.5.80 +* fixed communication #656 + ## 0.5.79 * fixed mixed reset flags #648 * fixed `mCbAlarm` if MQTT is not used #653 diff --git a/src/defines.h b/src/defines.h index 2a12e0e6..9dfb7884 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 79 +#define VERSION_PATCH 80 //------------------------------------- typedef struct { diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 9f671c54..b3466d00 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -9,6 +9,7 @@ #include "../utils/dbg.h" #include #include "../utils/crc.h" +#include "../config/config.h" #define SPI_SPEED 1000000 @@ -43,8 +44,6 @@ const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"}; #define BIT_CNT(x) ((x)<<3) -static volatile bool mIrqRcvd; - //----------------------------------------------------------------------------- // HM Radio class //----------------------------------------------------------------------------- @@ -313,6 +312,7 @@ class HmRadio { mSendCnt++; } + volatile bool mIrqRcvd; uint64_t DTU_RADIO_ID; uint8_t mRfChLst[RF_CHANNELS]; diff --git a/src/hm/payload.h b/src/hm/payload.h index 071dfe0c..72166390 100644 --- a/src/hm/payload.h +++ b/src/hm/payload.h @@ -48,7 +48,6 @@ class Payload { mSerialDebug = false; mHighPrioIv = NULL; mCbAlarm = NULL; - mCbAlarm = NULL; } void enableSerialDebug(bool enable) { From 67ff0209e86906e26a0c3f2edd41171979c5f34e Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 6 Feb 2023 22:12:12 +0100 Subject: [PATCH 272/431] renamed payload to hmPayload --- src/app.h | 4 ++-- src/hm/{payload.h => hmPayload.h} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/hm/{payload.h => hmPayload.h} (99%) diff --git a/src/app.h b/src/app.h index 36a77f9a..c60bb295 100644 --- a/src/app.h +++ b/src/app.h @@ -21,7 +21,7 @@ #include "utils/scheduler.h" #include "hm/hmSystem.h" -#include "hm/payload.h" +#include "hm/hmPayload.h" #include "wifi/ahoywifi.h" #include "web/web.h" #include "web/RestApi.h" @@ -37,7 +37,7 @@ #define ACOS(x) (degrees(acos(x))) typedef HmSystem HmSystemType; -typedef Payload PayloadType; +typedef HmPayload PayloadType; typedef Web WebType; typedef RestApi RestApiType; typedef PubMqtt PubMqttType; diff --git a/src/hm/payload.h b/src/hm/hmPayload.h similarity index 99% rename from src/hm/payload.h rename to src/hm/hmPayload.h index 72166390..2e599a6c 100644 --- a/src/hm/payload.h +++ b/src/hm/hmPayload.h @@ -32,9 +32,9 @@ typedef std::function al template -class Payload { +class HmPayload { public: - Payload() {} + HmPayload() {} void setup(IApp *app, HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { mApp = app; From 75539c5daf968598c7e336b78ae31e61bdf00fba Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 6 Feb 2023 23:37:05 +0100 Subject: [PATCH 273/431] started implementation of MI inverters (setup.html, own processing `MiPayload.h`) --- src/CHANGES.md | 3 + src/app.cpp | 65 ++++--- src/app.h | 8 +- src/defines.h | 2 +- src/hm/hmDefines.h | 3 + src/hm/hmInverter.h | 2 + src/hm/hmPayload.h | 17 +- src/hm/hmRadio.h | 8 +- src/hm/hmSystem.h | 39 +++-- src/hm/miPayload.h | 298 ++++++++++++++++++++++++++++++++ src/web/html/index.html | 2 +- src/web/html/login.html | 2 +- src/web/html/serial.html | 2 +- src/web/html/setup.html | 17 +- src/web/html/system.html | 2 +- src/web/html/update.html | 2 +- src/web/html/visualization.html | 2 +- 17 files changed, 408 insertions(+), 66 deletions(-) create mode 100644 src/hm/miPayload.h diff --git a/src/CHANGES.md b/src/CHANGES.md index ae341ba6..2e31c0e1 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,9 @@ (starting from release version `0.5.66`) +## 0.5.81 +* started implementation of MI inverters (setup.html, own processing `MiPayload.h`) + ## 0.5.80 * fixed communication #656 diff --git a/src/app.cpp b/src/app.cpp index 2f1bd58d..d64eefdb 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -13,7 +13,6 @@ app::app() : ah::Scheduler() {} //----------------------------------------------------------------------------- void app::setup() { - mSys = NULL; Serial.begin(115200); while (!Serial) yield(); @@ -26,9 +25,8 @@ void app::setup() { mSettings.getPtr(mConfig); DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false"))); - mSys = new HmSystemType(); - mSys->enableDebug(); - mSys->setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); + mSys.enableDebug(); + mSys.setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); mPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); #if defined(AP_ONLY) @@ -42,34 +40,37 @@ void app::setup() { everySec(std::bind(&ahoywifi::tickWifiLoop, &mWifi), "wifiL"); #endif - mSys->addInverters(&mConfig->inst); - mPayload.setup(this, mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); + mSys.addInverters(&mConfig->inst); + mPayload.setup(this, &mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); mPayload.enableSerialDebug(mConfig->serial.debug); - if(!mSys->Radio.isChipConnected()) + mMiPayload.setup(this, &mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); + mMiPayload.enableSerialDebug(mConfig->serial.debug); + + if(!mSys.Radio.isChipConnected()) DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); // when WiFi is in client mode, then enable mqtt broker #if !defined(AP_ONLY) mMqttEnabled = (mConfig->mqtt.broker[0] > 0); if (mMqttEnabled) { - mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mTimestamp); + mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, &mSys, &mTimestamp); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); mPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } #endif setupLed(); - mWeb.setup(this, mSys, mConfig); + mWeb.setup(this, &mSys, mConfig); mWeb.setProtection(strlen(mConfig->sys.adminPwd) != 0); - mApi.setup(this, mSys, mWeb.getWebSrvPtr(), mConfig); + mApi.setup(this, &mSys, mWeb.getWebSrvPtr(), mConfig); // Plugins if(mConfig->plugin.display.type != 0) - mMonoDisplay.setup(&mConfig->plugin.display, mSys, &mTimestamp, 0xff, mVersion); + mMonoDisplay.setup(&mConfig->plugin.display, &mSys, &mTimestamp, 0xff, mVersion); - mPubSerial.setup(mConfig, mSys, &mTimestamp); + mPubSerial.setup(mConfig, &mSys, &mTimestamp); regularTickers(); } @@ -83,23 +84,31 @@ void app::loop(void) { void app::loopStandard(void) { ah::Scheduler::loop(); - if (mSys->Radio.loop()) { - while (!mSys->Radio.mBufCtrl.empty()) { - packet_t *p = &mSys->Radio.mBufCtrl.front(); + if (mSys.Radio.loop()) { + while (!mSys.Radio.mBufCtrl.empty()) { + packet_t *p = &mSys.Radio.mBufCtrl.front(); if (mConfig->serial.debug) { DPRINT(DBG_INFO, "RX " + String(p->len) + "B Ch" + String(p->ch) + " | "); - mSys->Radio.dumpBuf(p->packet, p->len); + mSys.Radio.dumpBuf(p->packet, p->len); } mStat.frmCnt++; - mPayload.add(p); - mSys->Radio.mBufCtrl.pop(); + Inverter<> *iv = mSys.findInverter(&p->packet[1]); + if(NULL == iv) { + if(IV_HM == iv->ivGen) + mPayload.add(iv, p); + else + mMiPayload.add(iv, p); + } + mSys.Radio.mBufCtrl.pop(); yield(); } mPayload.process(true); + mMiPayload.process(true); } mPayload.loop(); + mMiPayload.loop(); if(mMqttEnabled) mMqtt.loop(); @@ -232,26 +241,30 @@ void app::tickMidnight(void) { //----------------------------------------------------------------------------- void app::tickSend(void) { - if(!mSys->Radio.isChipConnected()) { + if(!mSys.Radio.isChipConnected()) { DPRINTLN(DBG_WARN, "NRF24 not connected!"); return; } if (mIVCommunicationOn) { - if (!mSys->Radio.mBufCtrl.empty()) { + if (!mSys.Radio.mBufCtrl.empty()) { if (mConfig->serial.debug) - DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->Radio.mBufCtrl.size())); + DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys.Radio.mBufCtrl.size())); } int8_t maxLoop = MAX_NUM_INVERTERS; - Inverter<> *iv = mSys->getInverterByPos(mSendLastIvId); + Inverter<> *iv = mSys.getInverterByPos(mSendLastIvId); do { mSendLastIvId = ((MAX_NUM_INVERTERS - 1) == mSendLastIvId) ? 0 : mSendLastIvId + 1; - iv = mSys->getInverterByPos(mSendLastIvId); + iv = mSys.getInverterByPos(mSendLastIvId); } while ((NULL == iv) && ((maxLoop--) > 0)); if (NULL != iv) { - if(iv->config->enabled) - mPayload.ivSend(iv); + if(iv->config->enabled) { + if(iv->ivGen == IV_HM) + mPayload.ivSend(iv); + else + mMiPayload.ivSend(iv); + } } } else { if (mConfig->serial.debug) @@ -307,7 +320,7 @@ void app::setupLed(void) { //----------------------------------------------------------------------------- void app::updateLed(void) { if(mConfig->led.led0 != 0xff) { - Inverter<> *iv = mSys->getInverterByPos(0); + Inverter<> *iv = mSys.getInverterByPos(0); if (NULL != iv) { if(iv->isProducing(mTimestamp)) digitalWrite(mConfig->led.led0, LOW); // LED on diff --git a/src/app.h b/src/app.h index c60bb295..7e9499b7 100644 --- a/src/app.h +++ b/src/app.h @@ -22,6 +22,7 @@ #include "hm/hmSystem.h" #include "hm/hmPayload.h" +#include "hm/miPayload.h" #include "wifi/ahoywifi.h" #include "web/web.h" #include "web/RestApi.h" @@ -38,6 +39,7 @@ typedef HmSystem HmSystemType; typedef HmPayload PayloadType; +typedef MiPayload MiPayloadType; typedef Web WebType; typedef RestApi RestApiType; typedef PubMqtt PubMqttType; @@ -61,8 +63,7 @@ class app : public IApp, public ah::Scheduler { void regularTickers(void); void handleIntr(void) { - if(NULL != mSys) - mSys->Radio.handleIntr(); + mSys.Radio.handleIntr(); } uint32_t getUptime() { @@ -187,7 +188,7 @@ class app : public IApp, public ah::Scheduler { Scheduler::setTimestamp(newTime); } - HmSystemType *mSys; + HmSystemType mSys; private: typedef std::function innerLoopCb; @@ -246,6 +247,7 @@ class app : public IApp, public ah::Scheduler { WebType mWeb; RestApiType mApi; PayloadType mPayload; + MiPayloadType mMiPayload; PubSerialType mPubSerial; char mVersion[12]; diff --git a/src/defines.h b/src/defines.h index 9dfb7884..cf16e86b 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 80 +#define VERSION_PATCH 81 //------------------------------------- typedef struct { diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index fa7e08b2..aa9fe24f 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -9,6 +9,9 @@ #include "../utils/dbg.h" #include +// inverter generations +enum {IV_HM = 0, IV_MI}; + // units enum {UNIT_V = 0, UNIT_A, UNIT_W, UNIT_WH, UNIT_KWH, UNIT_HZ, UNIT_C, UNIT_PCT, UNIT_VAR, UNIT_NONE}; const char* const units[] = {"V", "A", "W", "Wh", "kWh", "Hz", "°C", "%", "var", ""}; diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 640aeae3..d50f341a 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -105,6 +105,7 @@ const calcFunc_t calcFunctions[] = { template class Inverter { public: + uint8_t ivGen; // generation of inverter (HM / MI) cfgIv_t *config; // stored settings uint8_t id; // unique id uint8_t type; // integer which refers to inverter type @@ -123,6 +124,7 @@ class Inverter { bool isConnected; // shows if inverter was successfully identified (fw version and hardware info) Inverter() { + ivGen = IV_HM; powerLimit[0] = 0xffff; // 65535 W Limit -> unlimited powerLimit[1] = AbsolutNonPersistent; // default power limit setting actPowerLimit = 0xffff; // init feedback from inverter to -1 diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 2e599a6c..a85f24e3 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -3,8 +3,8 @@ // Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ //----------------------------------------------------------------------------- -#ifndef __PAYLOAD_H__ -#define __PAYLOAD_H__ +#ifndef __HM_PAYLOAD_H__ +#define __HM_PAYLOAD_H__ #include "../utils/dbg.h" #include "../utils/crc.h" @@ -48,6 +48,7 @@ class HmPayload { mSerialDebug = false; mHighPrioIv = NULL; mCbAlarm = NULL; + mCbPayload = NULL; } void enableSerialDebug(bool enable) { @@ -118,12 +119,7 @@ class HmPayload { } } - void add(packet_t *p) { - Inverter<> *iv = mSys->findInverter(&p->packet[1]); - - if(NULL == iv) - return; - + void add(Inverter<> *iv, packet_t *p) { if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command mPayload[iv->id].txId = p->packet[0]; DPRINTLN(DBG_DEBUG, F("Response from info request received")); @@ -289,7 +285,8 @@ class HmPayload { private: void notify(uint8_t val) { - (mCbPayload)(val); + if(NULL != mCbPayload) + (mCbPayload)(val); } void notify(uint16_t code, uint32_t start, uint32_t endTime) { @@ -352,4 +349,4 @@ class HmPayload { payloadListenerType mCbPayload; }; -#endif /*__PAYLOAD_H_*/ +#endif /*__HM_PAYLOAD_H__*/ diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index b3466d00..5a6edb0e 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -291,16 +291,16 @@ class HmRadio { mTxBuf[len++] = (crc ) & 0xff; } // crc over all - mTxBuf[len++] = ah::crc8(mTxBuf, len); + mTxBuf[len+1] = ah::crc8(mTxBuf, len); if(mSerialDebug) { - DPRINT(DBG_INFO, "TX " + String(len) + "B Ch" + String(mRfChLst[mTxChIdx]) + " | "); - dumpBuf(mTxBuf, len); + DPRINT(DBG_INFO, "TX " + String(len+1) + "B Ch" + String(mRfChLst[mTxChIdx]) + " | "); + dumpBuf(mTxBuf, len+1); } mNrf24.setChannel(mRfChLst[mTxChIdx]); mNrf24.openWritingPipe(reinterpret_cast(&invId)); - mNrf24.startWrite(mTxBuf, len, false); // false = request ACK response + mNrf24.startWrite(mTxBuf, len+1, false); // false = request ACK response // switch TX channel for next packet if(++mTxChIdx >= RF_CHANNELS) diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 58099d40..3f3b29a7 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -14,18 +14,15 @@ class HmSystem { public: HmRadio<> Radio; - HmSystem() { - mNumInv = 0; - } - ~HmSystem() { - // TODO: cleanup - } + HmSystem() {} void setup() { + mNumInv = 0; Radio.setup(); } void setup(uint8_t ampPwr, uint8_t irqPin, uint8_t cePin, uint8_t csPin) { + mNumInv = 0; Radio.setup(ampPwr, irqPin, cePin, csPin); } @@ -34,8 +31,19 @@ class HmSystem { for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { iv = addInverter(&config->iv[i]); if (0ULL != config->iv[i].serial.u64) { - if (NULL != iv) - DPRINTLN(DBG_INFO, "added inverter " + String(iv->config->serial.u64, HEX)); + if (NULL != iv) { + DPRINT(DBG_INFO, "added inverter "); + if(iv->config->serial.b[5] == 0x11) + DBGPRINT("HM"); + else { + DBGPRINT(((iv->config->serial.b[4] & 0x03) == 0x01) ? " (2nd Gen) " : " (3rd Gen) "); + } + + DBGPRINTLN(String(iv->config->serial.u64, HEX)); + + if((iv->config->serial.b[5] == 0x10) && ((iv->config->serial.b[4] & 0x03) == 0x01)) + DPRINTLN(DBG_WARN, F("MI Inverter are not fully supported now!!!")); + } } } } @@ -51,16 +59,25 @@ class HmSystem { p->config = config; DPRINT(DBG_VERBOSE, "SERIAL: " + String(p->config->serial.b[5], HEX)); DPRINTLN(DBG_VERBOSE, " " + String(p->config->serial.b[4], HEX)); - if(p->config->serial.b[5] == 0x11) { + if((p->config->serial.b[5] == 0x11) || (p->config->serial.b[5] == 0x10)) { switch(p->config->serial.b[4]) { + case 0x22: case 0x21: p->type = INV_TYPE_1CH; break; + case 0x42: case 0x41: p->type = INV_TYPE_2CH; break; + case 0x62: case 0x61: p->type = INV_TYPE_4CH; break; default: - DPRINT(DBG_ERROR, F("unknown inverter type: 11")); - DPRINTLN(DBG_ERROR, String(p->config->serial.b[4], HEX)); + DPRINTLN(DBG_ERROR, F("unknown inverter type")); break; } + + if(p->config->serial.b[5] == 0x11) + p->ivGen = IV_HM; + else if((p->config->serial.b[4] & 0x03) == 0x02) // MI 3rd Gen -> same as HM + p->ivGen = IV_HM; + else // MI 2nd Gen + p->ivGen = IV_MI; } else if(p->config->serial.u64 != 0ULL) DPRINTLN(DBG_ERROR, F("inverter type can't be detected!")); diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h new file mode 100644 index 00000000..f578652c --- /dev/null +++ b/src/hm/miPayload.h @@ -0,0 +1,298 @@ +//----------------------------------------------------------------------------- +// 2023 Ahoy, https://ahoydtu.de +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#ifndef __MI_PAYLOAD_H__ +#define __MI_PAYLOAD_H__ + +#include "../utils/dbg.h" +#include "../utils/crc.h" +#include "../config/config.h" +#include + +typedef struct { + uint32_t ts; + bool requested; + uint8_t txCmd; + uint8_t len[MAX_PAYLOAD_ENTRIES]; + /* + uint8_t txId; + uint8_t invId; + uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; + bool complete; + uint8_t maxPackId; + bool lastFound; + uint8_t retransmits; + bool gotFragment;*/ +} miPayload_t; + + +typedef std::function miPayloadListenerType; + + +template +class MiPayload { + public: + MiPayload() {} + + void setup(IApp *app, HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { + mApp = app; + mSys = sys; + mStat = stat; + mMaxRetrans = maxRetransmits; + mTimestamp = timestamp; + for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { + reset(i); + } + mSerialDebug = false; + mCbMiPayload = NULL; + } + + void enableSerialDebug(bool enable) { + mSerialDebug = enable; + } + + void addPayloadListener(miPayloadListenerType cb) { + mCbMiPayload = cb; + } + + void loop() {} + + + void ivSend(Inverter<> *iv) { + reset(iv->id); + mPayload[iv->id].requested = true; + + yield(); + if (mSerialDebug) + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX)); + + uint8_t cmd = 0x09; //iv->getQueuedCmd(); + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); + mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); + mPayload[iv->id].txCmd = cmd; + } + + void add(Inverter<> *iv, packet_t *p) { + DPRINTLN(DBG_INFO, F("MI got data [0]=") + String(p->packet[0], HEX)); + + /*if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command + mPayload[iv->id].txId = p->packet[0]; + DPRINTLN(DBG_DEBUG, F("Response from info request received")); + uint8_t *pid = &p->packet[9]; + if (*pid == 0x00) { + DPRINT(DBG_DEBUG, F("fragment number zero received and ignored")); + } else { + DPRINTLN(DBG_DEBUG, "PID: 0x" + String(*pid, HEX)); + if ((*pid & 0x7F) < MAX_PAYLOAD_ENTRIES) { + memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], p->len - 11); + mPayload[iv->id].len[(*pid & 0x7F) - 1] = p->len - 11; + mPayload[iv->id].gotFragment = true; + } + + if ((*pid & ALL_FRAMES) == ALL_FRAMES) { + // Last packet + if (((*pid & 0x7f) > mPayload[iv->id].maxPackId) || (MAX_PAYLOAD_ENTRIES == mPayload[iv->id].maxPackId)) { + mPayload[iv->id].maxPackId = (*pid & 0x7f); + if (*pid > 0x81) + mPayload[iv->id].lastFound = true; + } + } + } + } else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command + DPRINTLN(DBG_DEBUG, F("Response from devcontrol request received")); + + mPayload[iv->id].txId = p->packet[0]; + iv->clearDevControlRequest(); + + if ((p->packet[12] == ActivePowerContr) && (p->packet[13] == 0x00)) { + String msg = ""; + if((p->packet[10] == 0x00) && (p->packet[11] == 0x00)) + mApp->setMqttPowerLimitAck(iv); + else + msg = "NOT "; + DPRINTLN(DBG_INFO, F("Inverter ") + String(iv->id) + F(" has ") + msg + F("accepted power limit set point ") + String(iv->powerLimit[0]) + F(" with PowerLimitControl ") + String(iv->powerLimit[1])); + iv->clearCmdQueue(); + iv->enqueCommand(SystemConfigPara); // read back power limit + } + iv->devControlCmd = Init; + }*/ + } + + void process(bool retransmit) { + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL == iv) + continue; // skip to next inverter + + /*if ((mPayload[iv->id].txId != (TX_REQ_INFO + ALL_FRAMES)) && (0 != mPayload[iv->id].txId)) { + // no processing needed if txId is not 0x95 + mPayload[iv->id].complete = true; + continue; // skip to next inverter + } + + if (!mPayload[iv->id].complete) { + bool crcPass, pyldComplete; + crcPass = build(iv->id, &pyldComplete); + if (!crcPass && !pyldComplete) { // payload not complete + if ((mPayload[iv->id].requested) && (retransmit)) { + if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) { + // This is required to prevent retransmissions without answer. + DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm...")); + mPayload[iv->id].retransmits = mMaxRetrans; + } else if(iv->devControlCmd == ActivePowerContr) { + DPRINTLN(DBG_INFO, F("retransmit power limit")); + mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true); + } else { + if (mPayload[iv->id].retransmits < mMaxRetrans) { + mPayload[iv->id].retransmits++; + if(false == mPayload[iv->id].gotFragment) { + DPRINTLN(DBG_WARN, F("(#") + String(iv->id) + F(") nothing received")); + mPayload[iv->id].retransmits = mMaxRetrans; + } else { + for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { + if (mPayload[iv->id].len[i] == 0) { + DPRINTLN(DBG_WARN, F("Frame ") + String(i + 1) + F(" missing: Request Retransmit")); + mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); + break; // only request retransmit one frame per loop + } + yield(); + } + } + } + } + } + } else if(!crcPass && pyldComplete) { // crc error on complete Payload + if (mPayload[iv->id].retransmits < mMaxRetrans) { + mPayload[iv->id].retransmits++; + DPRINTLN(DBG_WARN, F("CRC Error: Request Complete Retransmit")); + mPayload[iv->id].txCmd = iv->getQueuedCmd(); + DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket 0x") + String(mPayload[iv->id].txCmd, HEX)); + mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + } + } else { // payload complete + DPRINTLN(DBG_INFO, F("procPyld: cmd: 0x") + String(mPayload[iv->id].txCmd, HEX)); + DPRINTLN(DBG_INFO, F("procPyld: txid: 0x") + String(mPayload[iv->id].txId, HEX)); + DPRINTLN(DBG_DEBUG, F("procPyld: max: ") + String(mPayload[iv->id].maxPackId)); + record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser + mPayload[iv->id].complete = true; + + uint8_t payload[128]; + uint8_t payloadLen = 0; + + memset(payload, 0, 128); + + for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId); i++) { + memcpy(&payload[payloadLen], mPayload[iv->id].data[i], (mPayload[iv->id].len[i])); + payloadLen += (mPayload[iv->id].len[i]); + yield(); + } + payloadLen -= 2; + + if (mSerialDebug) { + DPRINT(DBG_INFO, F("Payload (") + String(payloadLen) + "): "); + mSys->Radio.dumpBuf(payload, payloadLen); + } + + if (NULL == rec) { + DPRINTLN(DBG_ERROR, F("record is NULL!")); + } else if ((rec->pyldLen == payloadLen) || (0 == rec->pyldLen)) { + if (mPayload[iv->id].txId == (TX_REQ_INFO + ALL_FRAMES)) + mStat->rxSuccess++; + + rec->ts = mPayload[iv->id].ts; + for (uint8_t i = 0; i < rec->length; i++) { + iv->addValue(i, payload, rec); + yield(); + } + iv->doCalculations(); + notify(mPayload[iv->id].txCmd); + + if(AlarmData == mPayload[iv->id].txCmd) { + uint8_t i = 0; + uint16_t code; + uint32_t start, end; + while(1) { + code = iv->parseAlarmLog(i++, payload, payloadLen, &start, &end); + if(0 == code) + break; + if (NULL != mCbAlarm) + (mCbAlarm)(code, start, end); + yield(); + } + } + } else { + DPRINTLN(DBG_ERROR, F("plausibility check failed, expected ") + String(rec->pyldLen) + F(" bytes")); + mStat->rxFail++; + } + + iv->setQueuedCmdFinished(); + } + }*/ + yield(); + } + } + + private: + void notify(uint8_t val) { + if(NULL != mCbMiPayload) + (mCbMiPayload)(val); + } + + bool build(uint8_t id, bool *complete) { + /*DPRINTLN(DBG_VERBOSE, F("build")); + uint16_t crc = 0xffff, crcRcv = 0x0000; + if (mPayload[id].maxPackId > MAX_PAYLOAD_ENTRIES) + mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; + + // check if all fragments are there + *complete = true; + for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) { + if(mPayload[id].len[i] == 0) + *complete = false; + } + if(!*complete) + return false; + + for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) { + if (mPayload[id].len[i] > 0) { + if (i == (mPayload[id].maxPackId - 1)) { + crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i] - 2, crc); + crcRcv = (mPayload[id].data[i][mPayload[id].len[i] - 2] << 8) | (mPayload[id].data[i][mPayload[id].len[i] - 1]); + } else + crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i], crc); + } + yield(); + } + + return (crc == crcRcv) ? true : false;*/ + return true; + } + + void reset(uint8_t id) { + DPRINTLN(DBG_INFO, "resetPayload: id: " + String(id)); + memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES); + /* + mPayload[id].gotFragment = false; + mPayload[id].retransmits = 0; + mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; + mPayload[id].lastFound = false; + mPayload[id].complete = false;*/ + mPayload[id].txCmd = 0; + mPayload[id].requested = false; + mPayload[id].ts = *mTimestamp; + } + + IApp *mApp; + HMSYSTEM *mSys; + statistics_t *mStat; + uint8_t mMaxRetrans; + uint32_t *mTimestamp; + miPayload_t mPayload[MAX_NUM_INVERTERS]; + bool mSerialDebug; + + payloadListenerType mCbMiPayload; +}; + +#endif /*__MI_PAYLOAD_H__*/ diff --git a/src/web/html/index.html b/src/web/html/index.html index 6634197e..0e71fcf7 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -62,7 +62,7 @@

            NiD9Bqb~mJph=jjg-Ijnmu? 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 literal 0 HcmV?d00001 diff --git a/tools/pcb-nokia5110/5_runTime.jpg b/tools/pcb-nokia5110/5_runTime.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8f02b13747c8bd72947b5bc3cbc47c77d6185f1b GIT binary patch literal 258781 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 r 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 uMWr?)yzF z%QRB2@s_aqZL&`8yMjSq{egZ`udCWQ4Gt}3J(}7eT9QNASV3Uu%V39(40J>_AC^t$ z_~CafC~I_Y?qjwEF%uPHcI(`mkf&p>(+39xdb7S+2pf0D9({NE4L0T>(Nj`{`}CW} zMSV=K&f}QKU>lnVYC(pT2%Ex)7PTa>#!o~$i?r3Vx@l*4i2smQdU#IDl-&Bsf4LSO zHV93&hDh5+$NWa|>iRuhKX$Km;Ju+LDI@t2Q@nu|^coXdO&zoGc&PLnb?kykQg~UA zep#3ak+I+T4w3nUh{ynZ4C_JXt(5WUsR(L)4E;8P{^b_Q6xi!u`n$o{HWHZ`bDUAY)MAe+6SW=vTQe67bJa4fd*gAyb0E zc+<-VGBp40FXc6C6$A?M_xW{(U^)i@ks~d;naWun6Qf-+?~esCc&>dZc$d3K_~3o> zNLMqX2r=rYRdaIyW{`(~Lq0ahK4!f1msVC&I4Qq}&*{11X2SB{t4%dd^}Tddag((Z zg0I@&G>EFmM!Bg6XS4VvZAOPk$h#D#*mk8_u^1e$xchQ7)t2wI;=Lc634s-1Je9u+ zehLe%AGAIl&EAtSk@}WvRTDcRkYaFG!vuZhklpFGoSEUp&~wwcpz`aevLjzZ@5m*2 z3K~QmHG3|+Mja6fKQ^`~G9>L;RaNC|WtVv-zjXSVPubei;-&6aQ;RaEix|(Gn%sTF zn#D(ObYJlOE&iLttDB$3Xh#~cp9l6=$LUq zzRC9f-ogKQuK%mScJ}oAgU66Pp86l8hJ1;S2V}C1eh9Ct`Gm)IK2H4?DG_!)hSs$1 zl?utovpRJ2H>$$-zV;7|_t*g)vouMW->96Hqq8D=3<}CzpK;c-VM0lHO|uzHISxI0 zi$ZN473>-4P&g=%e@0)7zq>3!qaar~rr2EKeynajfjFcwM`OS59r-+ZU%rf?7$09e zLF~bSqEN|0w|9S#OOpSkr1T6Sw-pH4^(_zJ8%mAdU&zC?FY>R{Q&~UbonQS%^^HeQ z^=nVN&KOSRj`U}y8&8aAIoHJ48=i4Jt)b9QF*KH25hG4mTAF-yQIe>o(p2 zWH+n=MRzdwx$>1*B}47>slB4gQ#RAamf;z>`FMaJ=L!|_YDq|lt^RG0=4ZP-pnti)pmlw9m>x(|HHzR0T<(A(Rt>dEydGe1|PHm@DJ^BZOK>*B+V zJJ|*4Y8tXf4ll5IndqR`~7O>jfDx_xCnaYhH2g zk}L+lmZJ7Xu!!;5cTKKu+6v7@J-x`*93k3g!yRpQ?aS9^0#Wm`^ObLkZyO9Q6q+s; zyZXvdxh9cozU?a+H!UfV$32X?aBF4uc)Dck^O_fVqhymG$2&%^>|95$c=ec+fKsk& zMw!NPTX$jpmgraGg7S^$GOCI{l~sH?l&q( z<<#=&N@TFN9yO_ps?-bDJfsbc(NbP*enhrpx;lQ2G=f{V{EZ4bV>qWuh!Vf(WG8ZD zQ^`YKH19>jGkd@MsHevJsM3DVMjewS+OBQgpVN3yI)T%^Yd+=|YLOBwyUuh$eSkLS{E1nW}Pjv@!)5rT55}1*T18t=0>g8 zf>)v(=tkQE_g=F*vZ>y`Tudhxz8}4R{|^WIAiq55SAO%*fz9c$(btoWlf8wx*A^z! z(%VA)nBx5({ou}H0r})vqgc589fK9F8xBFAeKVtu$E5B`wse*bTbhs*c<32vl4#qv z+gkCpv@8a2K8t|l)L9ndRia?-g{&Fuqwb+n9bJqnZxOAo6sitjS<=F^PNNx6Nx6`SW%L_<6BX}300N8#)Nqc<}+@p z>%P^Nhg)T5ks{thJn~{`Y3tk5f1Om+Nu`?!gvTtbb{>h-Sj+X07m+EYA8gLxE6k9v z$(jf~HzVBMAICW2HdVcJ^9?MT$P?Gx#60-hQzAXPJKfz%n<8c03THwj)awPkyQ2Qp zi)ei&bZF#EPPX36V>|^IU+jadWg+dFZ5ns}qfh4RyPR9e6OQWhqGH;`TwhhBlLfxJ zR%Lh2E;x=X!IKm?n^PsFMv8S+?s*vxe~_~6VaqsF6@KO3i@w^$*YGNWYH6u&Ov*>AovpLk{yLhK9{N!8x1f_`HC;Uv!2#P1b=nHKj^ zF%mP>w=|N2Ke5m>bTX>ttigqQ_m5i+x*rKi6?b~MR&~8U<)gh%$eW!X5W8$7G=8Im zz0fq;r?J6iK?CW@w~~iM%r2Iv3n;ETUgT)3uLzdia#|L}v0PnHoSJlt`YS^5;lhO5 z*m)nD&QLeFY(vX!Ejw?@;?U^jjrfE-*Yvp;uNEp_cAez75m7;!t?Wv>Y1MOsxHl{_ zBvsU@)K}6;G*6|Ouo03_kBRv9l&8l^$2a9kvcT+QNX~|Xb+Odhhl<&Q%IiW?r#Y0# zMp=pblcMW4jZZo*vgJ$ozFkUmZ5e8eW2#`m))qkef}^ z7Rn-}6RDyC$&~&X!({y&a*omZLH&$EvCeGs{uz_jk;Rb_M4r3`vR1xWWUyiPbk#Dh zc+bd-<_nYylP!SITTv+S$P+Y6#&Pg_Q z7ejHubp-`+dLt$nXM-wgFLpGsk&X_P)SgDVH zS)D7$K>wG~+8N&uP~aDpBy_s zrO7ipW+TFPsMZ>aR4llO{`B6jmTgK&V>Ca=S_eO`9 z1#^%6_@KS#$yd3YiFm!^CuIaTCv9m8O7hI@SN-6LxdBxU$2F_O`DFU_pc1ioBTR1 zJO?ZaDJY8D;`4CCZ`56(wvEF0WEyV6SUO~_N=7Qlqz4$oWa8K2ZYi94xNtCwz~+N! z!Q2x{50d%TUb&ML+BU>ft{bxZh|%QW-4!0DQ@q7umj}d5eSB}ijjd}u6D(EVll zq{V@1=-^9KsqKYH%0+<>6EuciY z=slxpW%C=gd-Sq9 z++39rtO=XG`F4afscF{J6ne|sSLw)aREI&bzC-9^1V>`Xd)KtHxDT z#Rb5es;52<4RUhRinRCa+ih1l{{mH>K1v`WLdUe>guql3w|Rf*^xC}mH15f7RH}f$ zH1)FWPcPZ*OYbCjB=3@aF)Sd$3DMr?gn%XiR868{PDab^p+OVcOzTp@fdjkk%JaV1 ze&|luHsK*Oj`$p1IAij#*Vsb%q5NREY;0yKUtolyz|HPPbsU@D`frp~=)Z9)FEVX= zx<)TFCuswU>J4V>cF4|#r-LxK-H5;%XXX98o^L^_s7SjnNWi38=f>+a5rmf zYXPa%{$v@v9A(U(%4T7jk#ncFkV`%IF+t2C(ymk_ye(OV;$_k*IH&VO=VfzLU5U7k zpuWLWDQH_W-UV%KMNFMO6cMN(l(sN;nf&S9>44r|pe1oqy*)xRfzri9FOlqdrtPjnjDMMvjx_7ggSD%?KQzql=g-wW!oIcZujg+Z|&&>ad!e2;SneuD~%tExn?G4ywCnT+G15BA3e92dhs6{2ICHwD_6ua7#6Ux&X@AE^@ z3)KpotF8QsEw-;OlN{GLY{YX7zE2h?>!H2AzGXpI<+jZQ#gB{-oX89atneK4yUx3 z_VniH@?VrLl|Ie0q|u)nr`Ljh@EMOg*TnLj+a0W=a7(-mgSl+b(HukwwOdFRmH2&{F2MnS6xh@OTM;h{s@EpYeJflyR}d*3310 zbZG6kK1Hq8iQxKyd&nwyM`?Tn=1p)lNPkKSquh|ryCl>zWiff*j7*NXsRUspN6N5kB_@IhiWabJ??1@%%>gc zd>}0{W1C2m8>T9(?JIvGs88W=4t*Lf6`3g9!6HC1TM+(6Q!3LBZug`qJty)xx5K7; zKOj+O_rQQ#^eB}BUil>aiCk{2h`XDj*1S@MJPE{Yv?pGO<0)kHS! zJuA*RM9$IHkV*$5s>9x&z7qn(M1g3bq(jfcJrV^w*|vC}V#!f|8EP6=<(Yq=hUBxg zd=*krLqEu7m(A#mjG^x0)w-S;)6V~97N4VVxf^*gav{$*Gs4BvakU7mOT7I@zAYDP ztbSBf7_!_a7$+R9zVFx40DIr2mrzVnKzW{FBf)~kJ+#~Imo7Q&{waLYf*x-nN1nr> zQ)OzE0@WcWC0oKRb#7l@yMF`s@X&i*xka;Bp+4(qO|!Q_p3B9H_v9g6N4jxac(}nl zY~srf>%6pZC$$6>BlLsv&jdNQe8tv1x#R8fZ$aJF3OX-wFJ48hr?jdb!;4vRi|I}7 z>3X9Vxh8vGyvFGZMCn8)#`G}r)wq$>7gBSI@2naQB6>|e@~c;`UWySDFJob5ZDJWy z=|$_44KI?M6fIkqbKe)p&)*c9gO@j#6TF!H7pVdzVvP_o3zkV;YKe5r6&7bqy*Nuv?l~+q7?5rxwt6Sr|wF? zf8tgikGVZokZ&B=7LwQXmoR#`U*0!igy^^s>EdwBAgjCidzoU(g<}#jqwTj0TxYFM z$gfn`=s#yTt*x;=!2XfUc8OyDCCvMg(;v!Qlvs}n8YwHf$-H1cmq+%Ed!}TdMu{R* zbmO|ozQ5W+&60VW4+ul=C!T#Ou(EggL$%Wt8D`pEL#>FNT{TqX=GqN#0H4Paf$j>fdh z4+v6rU%&Y_N-D&Jw1mCot+mwhQqw5=5}5-}kGnhSb3?^|H&R7t*OXMb7YVGgMG|%s zz*K&`;6c8by5HV4Gvb3+PFW@4Xt-2xhVh#aDX*cVrbsM_urF@&v|2Y|#3N~{_&~vz zw|R}%ZQHAOF#;*Z>2nK5x2^YzW?$gx* zu=S4q)W^VE$qfl!Qahh7JVQ#m?$UvxiC@bvVcH0l@<9m8rqEW1`U;*m9AKi0_@$ zu8kwB{Ym!GtmbSc`)ze{^BxRaQu@t|f{e5Ou6JGCxGEmxc2r5<<^KAKw^WOT^!Dmy z*YjRy6lG)ae<}ZC1E6c_IB4Gr-lgv8r!-iLK@q_#Czl7@Bsq^x(5_SD^=ii4@^=kR z@B`Q_7?0sG?rzRMXh>uxU}%Jy;ZMuSx^oNJ-|-p7(qluES+eg@`FMqUKWnQ>9|bgr zTz0DJjx~9F5jRNs)_j{P@|U2Z*M;W4cD3^_z9{f{vv1)SA$^VzrN1ocWjsCe@C1p? zE4`sVB^LusWxUk11~!KwW3{+EdE=&Ti1^UiCBaIO5w+x;R6LH|Wo=V{Ln`Eehzy;vd~Q(rzPxhRbZ^<1=Ub{^ia6W3s65sgCEOi%bV@FTb46XU zm6cxPf5G4S1*nOL^vqNjUg`ymA zU!M;|=`O78zj<%PKqord$aa7sV}K#^;gLgy7N4#jFrNObB;Lx_h;@At#RwRM|Lu5w z^LS&_yugc?3rBXn^LZ=?7|7l)YOT4DSVs0Lv2L0zJk>O-oLlSLi~p$TS#l9qJ}SR7 zGFbap^52t};y-T5-*>-*&-?10`Ob$bn61a*Iwxb`w%csEjK81k=YNYwc&>ZJwdwsE z=QCwN{8ZfS72n%mpM7($uWaioF>mRbIpbGg=0$sc#OIvR00PGQ9WKrLMK_%QrovMHN#2Uf8~S;i8kqW{{j< z$kA+bQ5E0jjG7}a4R%H7$a&fD+Ia9UOyDO%4S82?SjU%bYPprSTYdV{<+q{yrtF%_ z21bIm^;D%-@RI>=2wvsT!t*G?u?kTYhqSA8`j(BOqs{_SY_$*O^Q^Z15nSqg;8xz& zHR-TphcQGHF^CLnX-RFPQrp_#*IUFPp}KbhR@Q_`FJe3^&&{q|#@(~6+lnd|5n)iD zMq7On{dL{1Ku<*= zU;7@?c2_`n7ZX0=ZMoT+O6_sUkibtPOeNB(A#@lo^~YRSHy%X|2#DXmwlBMGNhant zLUF?_FPqEtoEDSful@ELWw3QgWS6|>y8b_=PD;;{f&P3l{MJW&y(GGln$Ez8J#6D~Ks(+ou7H1V}sog^>MUSB4#@g770zLX)-|eoOKL zivmtXZ%+E0Y;75nm&_R61YXUL+Xp%BE&%WI%F4K_|kl%b@_SUN8y4M>Yv9w?3 znnN;TEYPV>Mm;a$)&yR#Fi37-|Fur!(v}(-`JxmGbN}rlqBlYuAdD7kZ{c#Ep77Ic z3;p>|ywkzw=^boAe)rZECyk`+q(=<8rl0m*QQ&|_bxDspMlrf;EE{-b>1POZhZG5X z&A@+O_%zL7+djy}y`|~5{_v|tR8)DtVhiQo_>8rl&s}-j-o|t$+oj7hyf&SYH~0*k zmJ3;p#K7CZMptXn_@w31`bI{{H@Vz%>5Zo{W;CZPe`(A$2y_MDCu#`4QHks1N9%n`Rtq`1HePJT30@aE+?;pKDA*lf*({^hGV5#8{BU`J?L;4+Ys1>8 zfrP1oo5FIAft7kMuyDOeQRMgGTE*w+CAe|xMfiNNRsrpi34Fc*{oD}4FuUxLKE7)$ zf=U{5A$vW|XiBM@>GhorBF$0c@rLvU>nlnR`E7g0f=@_p@#4SNuNLxvKa2#LOaOzF zkx^&tzdvhbM^2~ygP+z2Q|=XfOL(UdVQeR|tFa(Q@AY!yhqBWFz{Wp#>T_uM_OriN z65aW>NcV3zsjJPTJdpZzMN#udPkkS;1*}57LmEp*x`I1beDHr&lw_OBb7OqP++=q-CGq@!bl4TvJAyZ%K-;;e4Q@lank`P6(s*K>$k0y`LoYmSI<~cP^ z&g^MyuZ~wTp?EYWgJ`+uZ)fO4k#ofGduHk5j2llY+<^7k0TYg6mSUA<*loF)DpS=DRN1)AQ~3 zIVfJ8?60-T7nWT`)s_C99J7`+=?+dk*Kn3+Q~mYwGg8YIw~C`)xU*6yh1bIcr#&08>rK@0 zdg}jS>@C2ee7^o+R8$0{L%Nobltv_^VaX*VB&0*y1!=w_u)xwSNbJ%f4HAL^(jeWU zbfdJC_@Bk^@ArS6_r2chdS~aFy=!OYo;Y*noX%nr2+6!cjL81w|^*NI+ zz<8~2yj&PpkpL~qJM6g?v~};JF~an`(wt!#DEH>Pb`eE7*xA`g zlkgBQJ#?=YO?6kuf7metU=vNszSfk^VS>#B?X5uGVo&H?7Hk3~S5hym9IC0PCCpvi zp_U2!O z?B7~l0TWd5KmfE9Ls0)`fchv`m%MtGeIP96D(Tnp^@CVJJJY8F0-FN@<-;zqtGYSi zxWXCq0M#keT65}9f+wJShe=T{Xe^u?89;4YZpqD6(-W}LF7A-?BnBjeJ<5Xr!9tP! z$ex4RT~-?y9%*WJrG5x=`ynOKFqHd-paikACAQ~95-;nZf&x4jxt8JrLo+ZwsOOlSMOMuE6?}khN*|E zoRlqo!|NMEd#tJFDac-W#Oo+c@ue?euCUk)f)E%O8(&?=uJCy^!(?*-B~hJ4HQk1k zFG&{c!a_BuR`0ZjWSLe|Foc_C>PeF9_!uY8L6eSzxvH9*4$H;sDIf=8*8TVByL#pp zhq4c6BACZZP@@67-x;F51!8y1QTi+KK70}3k#+bMbmZFEr6R#p{-GS_dRe+@S`ydV z6FsiR4@b+RBNCg7BY@%_wzJROx?RcOzQK9U9wCsy6POLw7<^u&qZ%n4gt>4}nHTGC`#zyJIqk_u~jY}N;{HDzu7D}C*#8oVzu0cnj0S5)cx$0^@ z(AveQi4D`I`ofhmy2g!+42(QecIq>9wnWZAQ||IZX`#H+?ylUJ71A^I_>7n3Q-34* zNS~p-9qM@dq`P{ZOe2$8kGkLu*2M2TT(a?2O@Wd4+(Nyi-zBzWa_6~svy-jY-!%8UW^26QCh@wgx7fkLD zjgWo+TrrSsXV`&BH)f4su&YG#uDt1(!z>)0mY*s)R?mINitO#iDP=6Q2Idj;AuEeg zZPc)%wEk}+U6qDjv!-*_?~V|SwR)Gr0XI^c%qc{eO>FWA*uMmSRvKGtL#hdQuev+{ z@fY#HaV&<(p=O!$*DKutyS5+P6p%UcrKJ9l3Ec+(++6O?&2Is_ddw3EWXqsw-Vc3< z`GW;%l$vf&%|AwURb76J(6qpp7D)QqqmHO{(HuFTbY$-QY(yIGtIJ}cw>zyQ&JWG7 z(*--iVNSc6JiO?|ab6y|OI8!0^V3??B==$Z^3^->;V}KJ`*KnQqRb{79pUoDMk^hW z(1hoCh?{8LVF&*8Of?xpZND!(g>KuZ?Z60M1{#JchpaMh$6$l0Q+{-wGXJ{_oD18e z3{CTS@J2v#{~6sG_NZ=A9c-^y)p>L)33GU4b%z1U%`C*5;Zn9gIi;3B(%*J(;ao_^ zxrLVMsP9-^x1u(piGNM^9(@7Fg>7QvMh%doo>b&fgeHK!5}L=<&*bYR|1$jSvs)+l zIfdl&L>4KDjvw~RrF-H&5kK6{X2`$*q0Vk4tB~Zslxf%g-q``P(5Z+?IWf7JV1uJF zRc=5x1x90@6ENiYaILtVDerOAw!Yf3@*4Tr$>8=I$11)oSfLiHa?3RA1!dY9I%ejv z^nTbLdxq9CU*b*E0>YzVE5!R?No8LxJo?ILyOpK>&&B%FttmgyTW9Ng9M#461iB+( zdzX(Wl=-2;6TGj-_Ns6B!*yQsNl)&pN;v78c#MvhkH{Cl3#((oylaZsUVgK5$Knsh zhf}^pxiY+-pQx%7st7OTx@Q z4xz4Bv1_`9MnL?CkM0FDsE5My`3UdQQg@ySfw5%L*JilEy^fGM3Ta~XdK2>ica^u> zBP|^PQkb?9^kE6?avHEll9=L-8c{OEu6eYSK#VN=QD1&t??imf13SJqa{0`WRu4zr z>AR>G5)BOj7tK72tbg6eyZsO~h^VRp1tcoJru~DZbdscA2$_r;aY)~~xQ@x+L>Xv4 zt@79n$BdpV^(Km2ynQ$a-rvZALksb!E((SRd`G~qUgHJ&j>6Y!H1Axda63m8(6+|& z)HlV%G)irbH@Mcg9zW49^Sakfpl^Bj+}tPC#8#6t?d<7_{t;|Vm&BLY)3KTFdfLc) z>Ma!>9^IN1o4enhDAyhkyv+GjnTMHY{iyzRIrgNqcZ3ue8a}Czm)E$^J&|%%OxUAL z#oQ)%bEbaf!b<^s>0Wl(t&~>@H2%_Um+G!6+X~aQ>V)<#?_9VZl|NWUnmt(a;l`u( zV%kM@*1t6GK0vKlA-7YTkn>8^gayo>Sl_YQGlWOl-FO%pB2Cwic{C^3IRN!mzu;?q~)wfQ#uDQ zxIQg0dP*h~aC+#N*2&gB16w`hnE4OZpnINL;;42WTvF9&V!v86`vBR>=cF{HApsyW?#d3YXCFWB)ZkQ zjsh!I61o~)nhjKsII)7EUhk^$no-Xn8_h14=D1RnmdZA!Q^wU2@8{=3y`Deq{jvoH z{S@L+tz4^iBdvn1XIOr9(OL!}&2!TJ%$wok>j-D=*u#J35n?W?zxX|Sz-k=gX}i*(d)p74SVPADS%Ste& zqOFjW;7NIBY4p{5k{C$ftna0$>usDVH)XebFx!ZjjvNyI9cnqHoY>6?Z z=G2Gw`}f@YR#XWWD0pfxZGJNLVK_xG`aH4s>l|tc{0dG=6|*@vR6&$ zQtlO>WH)JfVJ&I<2TSsKYtC=|Zb_}@t^G^7ftgFt;|fl;!Gva&4TLzohu6K3pgpK5sc9B6%Uaw`NE zKO6qC^F5p{`_&niU4HVxzcD-EbAxkZv9Q@Lub;9xIzk{%{GxeQ!`QJs#+)M5&wqIB z8~dnF&E96;oFos|`Mq-wnI=M+;s7VxuaGH}Ry1c1XV|GP>VCmlBH1^QXI&LOR5vbR z=i`_D^ultlVw~<8eXlK#T^SVcY48@C(i~e=seCMgqE+u{tjA?wcmHxzbSA&z7vnLX z9EIhfz5Z_tsX48A%Y>O9>af$dK8=SX2ZLc}OxA1A&C{8Jz1?CX4%|W|syEuI5dVwB z_=Jr-r`B!Lf(gpYBL?R}U#sN^vg!4%yDfp#DX|AF5lOkD=-pF{O+lVDpceovXLu38 zFT3TaP+F6xdi$Ea`4Mu7TdI0XX~F;r8>U2kUg=LGyVUq$rk6K>bS8A{_=A=H2g@hs zz4lH*rl-DMD4JGK#cS%TDLb{;aN-jWP76Ii89C*~_d(tod6g82)}?jK-AJmVWC{uf zqx*N{du6prVzWM9GS^(P%NFX2GdJtuUE$Cuf!vQv_l-L*?^fVbAjt0ng8b>y;urf? zRsx&CBlnAV>IJv84%lR7DFQnt*U>v;O;!hW8TdWo_Uf0^ZHJR<{=QnZKQtkhI~6XED4p|W7xH@()wBT9 zr_EB@2;ibRMT#CAy$@lSqF_L?s#Q~&%>SuRRTZB*QGF^x_URo*_C4vacbpNq7!yj2 zr4GEl9;glU-&sG=8v!fJUP>H(vi^&NnF5s&!xU;e9Te^sL@9&TzPrhCdm16t7cRKy zZmfJrV)^qjVoA;QJ_JSr}>X#ZX-&#SzPZ|&rt;*Xx8Fe2c7IqKzI-^Gyo7-Qvul& zFrfimC5r(Sh}S~}i^i1e%0e&~#WOsHFj9ZAExB6+d0-z`YSPmuP8(mO@g_;5CShIb z-C+tD50^Hpg7l`)Sdp^P21gPB1m(m!5rP*Obt~`Ab4r=S%ZKnJTnD5QMPi~rf%fYp zeB%2fK*X1@Wb{qj%B1PRFJB7o0onlEW>I}5a;}BRiOIvC)UjcC+NC8aI#)9W*i3R_ zv`S#NvTFQ!5onnrL=?#B0Fva&#`0KT|Jc+&$SGQ2Pf-^jyqXCF_E((NKQv?XQvkNh z3+#r@iPEgKIguznU2t_>6~(KtnZjI=q}xb(65eir4lWfcWp<5f`#ho-`tdV>=$c!@ z44&)4>GEJh>o8GWJ%Y$}k-~Mjt?UXru-4H9P-k&mgj{yvf9!X3Q{+%1{@CtoDnkWE zWF8!_x7xZ%R2`sE*F(2B$uKZ;5Xc~~LTEFY&*aNWuT{SS1G8#V_lx+8>dty9(yh8G z$?=jXj&fNvgGu0|8(d(xL!7X*(0I8QBO+D*+Yw;N(7ctiHUFQpn*SNDy6S%A(EqT$ zT|X!Gky1Wn=jGzGGc=u!wctKGF_9iI6>jUUHeB>zDERvuP7Km+BPV;tRy_?fh|x_o z*0`8jTj%|cfLXLm2oj1gP@*gCpMPxDUyE1RahCnRQE=Pxl(6z|&s>=(^I8wKH&Bvq z==Q1RIjBIQ+di^X&@7gwJ-uapzVPAk8f^#j5T*-Y#fQa&c z1u$yUt~7xdBsjn+U%@poNka<8N02^6%Y}bD%dO@a9PM^a99|I(- z$J*CMhSVycjP|VeRPQ4FR}$%-9mo{};R7uI+T#C$5C2Mfp;wnN7FqxT_pizm83*)^ z-dCE(20%%`{)Cboz{7z`bO>{r@;}}^$xwe0NSE;V=uwS4_QRE`SyqPv_)43*>u<+d zl{9H$4txMlod_BlQ+oV{)Ky7W>P|T8Pzw4)6&N#v(R*bAer2BwfY^T{m<1_7IhUsj z6tEFV|53-9nwtK#48KBIVY-s@c)}>Zm~0yJmgy9=4TiO>DKYA}n~~dXxxaHpswpIj zrK#D?_|I<@U0zRuLI5SNDx3wl*G98!LnJU~Pr6^6uFGSM`#iT;cU?#O zmewsssg&PBxI|Rb-;5IGlwW^AJ4Q}DQ=`1WjwmLRq`J?`dOdr(eHdD*K_(EDm`sNq z+L$NCbSXU}m7{Q5_mCCF$sL`i`kVvz2*IaK^||N*u9e^J!PL13K($hHVR~jgVci=3 zA0He`caK^h9X0$;h<~Jo()K#Nnd(M^GD4NBRnz0#9(xWYX=wQwuexM|i(I508fVA8 z8zru_IwM<=vcFQ)dUK#%!9~N&kcB7@zMvN_tAMki8WB#*N&GVW2`3r7J*m^o6Lg<+ z?(F)AJPgh}PQbK<7ZF0kyuoWOr}PL<3Oah*(Z7j^lh^~f+}kBJm&M>{IJdOda|YQs zFNi05C|j7fABJFHBh5|yMRfL&&UV=ZhiOAzA___lTOzWNPGTUFwC;^5P?YFd4tc`N z)S+B5-ZiW+tg_H9?`Klll;<<~&Ve(ru<^d1e|PvWT%4j#ZtoD8E7xZ6Ljxu^8HQTV zZHys38H~-2{gxMIfx^8s?szLK+bkX<T?q3A@~qUNpOYSG^T>U|hkeTrv}r z-iuRgxtIiOF@`*ZG`l?kU@Va(yzzwzZhol(VK`Pt^s@VX0rL<>-QbVQB{vDRhPBE@DeF~4k~ zd7xn%Z^d2+Nv;p-5=sy|k+0nNd6M*O{s4 z$)5e_QKgkv9ok07o7ljMu4C6#NX;B|N6Eau5mvzLL5D!gqUr}q>&|$ggP7K0@;S-jXb6myQoA6%v|@9GJ{Z&}-bF*r~@Ur(=(K_%f!nkfyHtBFV_j>CH)5ph1El*@V9 zIm(dmIJ2vgRTyi%k=6ZzKuQhoq&4_AH^d~D=rByJ2=>mGO56P>!7x1sSPJtJ z%g~vSsNs<~Q)7%#IC_8oSCL&q5`73tsC$t)B8RM+H;+ous8`6S&qAs`=3UlP3Wk@( z7>Zw(H@h>TZ#fu*3MucLyf9yu`wR`T;(uaxzhCT>T$iY_F~;rGr3MC9-r@xR4)A)5 zFQF0`6G3;_NAf&GA4SK9a*8!pRps!6Vc2A5?yxGBt+2C2P)HfergdZ>P5DG0VHxRG z@Yw=)a22u4#F$V7+m+`DG9{UstYdXS)R49H5HLv|N@2Rll-YUsVOnWn$a5_C1Fat#1L=tCGQ3X=3nQ z^ev3LkU}k%EvcL>?v10It>7w>Zq>gK4l>}2Aq+jPU094+YWS2ePBjQCS_&`*Wu_(u zZyg(ea}-OULnupfFIy4!9^>c*=B);R2L_5uyek~YmGy67&HJwh1eSyIB;_Gprx5Qn z_gXsQi#O&YqyjFZMHnzjEm=tNJKYSJ`@cRsz`6!3f`B>uzoCm%0prgCNr5)--&HoZQ6m%&csD8KUKfj( z`phv37r&be-bS+q6RGfFqB}q_ku$iaT^`eQLgqd6#)MoBIez8xgjN>LYYnX`Eiw__ zqpf<7W#ewmOBIpxvNgW$pzG0SIB0zP5Qb(!atE zPRurQ*A$-)w}I9LMhO7d18jbWaWC@a z#Xy}?1j@^0sOYN9k8L{`;p%ft)MubBPaN`&QWl#zTm^KAg z9H0sDK#%?#Kn)YGxE5S!JmC3&x&D73QXFx>lMErB5uZWBklSK>w1jY0pE7ip zq<~{bS#^f)OS$sX#;qHNyjfdgpeC9=z!GJFc`z&H#5?BVd#dum=7LH&Iqh~Wa0h+xe@$;>r(p<)_oNn&nxCDcY_lOG$>kipkj7FznxpeX;)D0Lp9iQ z$z`_xatA1pa5dslS2zJ&Oygg1uABdw0OW35oyqB+C+8raa7W=g3` z1bF=5aa~#K0=}jo#8}s_-2^Ta|LbZB>l*QOA`(W|XH1VD$Y}9rS6q3S0=K2F{lOY8 z!(ogb#U_#gkq(N(81&zWuZ9nT8VJf)SGhZX6jv{6VIIW){JA6b-*7K=c4^Zui@j$b zli-K?#dcd=Z=+O_eemc>fSVS zpzOOpSjO&gQJYyK7W5?wHiv4ylK1Hclf zPXG@j!J7t>!1BKXvwSx{KfuPJ-sQ%tfV<4{{gGE8ye3{n6kNKBmqET#BJXZVSv#D} zG#zm1caCp@bd%-G;mA9wWC{MQT%gv^IemQfNqN-h%hdv<&W)x6ho4cSHkz4!PKKwy zI>)oJ{G5!+rA}sQP5t+39X^~dISdZ8QvSUQiNhW6&MR3`&i^?mB^2R&aj;mf%k@#> zWL#YO-(-Y*^I#CkLsYJx>1U67uia{5}8wosM^EfehpmUUoi7^8ST6$?~%{iTP3@ zB~W&;U%kZfB*5EnFOf@ctq5~cGRP$*lu^u(@x;#|U2lyM*}_@-q-02nvo>!!X0U~$ z9iNNyCFqfNZO)SJw{nsCBhiw9GD*!-pAR!jV}Gzx%Kx5S%#81)@#&`< zwFoL~9z56Yv~MY0`d!)ITny)@oUfe-ioGwlES9V>$!=)WCNKR{8m znKd5hwhjC~T*NhfD-)E_nZ~;su$Qb=^n*Wj>lBP_f|@5sEH3PPB`KH8qVUbsQH2wU zdYyKhbN*~hJCx8JBb*xIQX(13*Q6wTTEMH)4azYGB^e|?Iln{wfQW-|p1+8;kcEZC z<8qu6NFr3~j{F-cDiW1A5Fk~C+^15S3CpKUvE4QhBJh-jLvBs5(_C#oCn zFCvGz&-T9pPd4!A8S4xbT5J<=RMtnZjcX5$v459Z1;N1 z?dBIw5ncsrw-=rSZ`E;mSM{F1*wJbA6A3w}ebRPLV;M*%V!z`VveyTx?AiOS!_!mQ zbh1&HOtnL3QY|I=ddbfvPE}MwR#4M}y`MO7T z86OT%jnNK0R-#u_IWip& z@~r&zzq5i0m!ss#3v5QAiR_%^wqqKD^uDTn9h3nzUiz~(X}5SGgQ+fxD0JQ$=RImSRE+X>^!f)^k<*8-XR6PA7T0H#B8ZWQ2b1o(Y& z{hK`wP6VctF>%QK!-kcR-~eC0;=#e{jatF&5u27h$73luNA>LYHVDw`PL-)wW;H=u^;_t)3A8eX=fy~u# zESb9bZGIDWv5ZnL_9ykZ$Mh*(lU?W64PX3qGb^X3>>D&*8AnmCYGXEb zgQ&8s9q*QU9{FxBO-HG2Yh>QNrCB9iG?Oy*9cNsccbcV z1N)37y|bR9L5e8`gEPegmG2Ce0iS3E45%6n>vBjdTAI(_oaJhZ+?t|KnKBzp7-{+B zX?ygK%-x+LC;4WJsnAbjb?si?dw(`%vY!)jJsqo5U93`}K4BCFu*%EyW$h zRl?ElJEA&IdEVQA!zw!ws+PZ3zobLw3TLRCDCfQxl(oF&iEDz@g}Wj){$S``qF}P(3CT>V&OPjFT8&TOzp`OO@ zIv7^)^?SHi!zA)C(|ggkKOcX2X5j{g-O`i1`rosuvyW%FoAQq&@6HIi5VqXff4vtU z9qW7-fPfBk`o|9Io)l%z>TUSYj1Gh;tUpY5_c42X8OM2;p#%Qq<2UCy(af|e^um4f z+r3A=)=nJ>8)gXFNo$+cpEGyyEFJ5nsZ+cp%xKsTV&#mbv5cV zKMeNq)QNPDy&vFQ9;~Q1UFV+FMlvi z-iOqS$r(+h@ze?Pn2cAvkE1e+Xz?798W|G_Z$$sj744j*zMJcuM@^Vn6W~7N!~)N| zz-4x?d*WZ2J)`(FuPb_8{94`PQ052;T$SRw?jh&AmQ|l?bs|%}97U)^SI^h>G!d%G zzV1FF5f95kPyMGGtnyk3ieL0OKRctCHbc}+%^BM_E9GR#e$7CSlX)HopG1Bz8ul?$ z=jfqUM4_k6o;y6PE*Ns320j>dvOdt){n$F*a$LiidOEf2YJ% zc5-_0QETI?+1JwlxTx<7Yi|_nx4)>Y`e^#S%Vi~WwsT_E|M2HZ=;D%{f5_<3^xo28 z#;o;6oA*%xesT}j=?fMJw{APT1&HZ3cI*=9{(j-WePjkTe^^rDIG>(T;40sMK3j7#A_I+kESvPw@=ZN_k8Cw%KYwhLP=#ZXkL7E#+!WBfz*=u4wU;G)5$x#cZW zEIP_kamMrAhh``F-MbQR@WJx;>hnN_=CFRDJYz7nqD3UZW3b`{D<1H`iv!3`Y!}=k z9)KVr8_-x6{WRfOW)F9NRw2*W68Hn7DjeAzy==}}%8+q1r=v?ov3;kP%biJyDEW$6 zE)nnL`1pX3WM2=|E6_#?WY1u^=%^>3IKbRZ55_D2|HxkZcOf8>!M#pIl$qG6tEvW5 ztcnn(3!O{#+28e$5LkA1#+t32e%cm)@d6LUFdEP@$sV%tK4A7A?E6BAE;rsBm*|Up z=Ue`SsdXR`2fAhD7heO}^Lt<3y??lmlyI4OKh=iA1XBng232^D!x*YlPD|qTF`z+k z-S_ie`ZmiAC&HMG?=)!kf!v|y+o}hxU@f>KYha6V`TpcIoyP0vy?1`GgIU@d)%~W) zJsLZjn~|(RLyqNOm32;|Aw48@`qeg+A=nOImvtD*pp07ZusY!ja(!!>+{N+jRjn%J z&eG~Pv%BATZs~NBwoL_ksi=%ssHht?D9n;C&Ki&J_U)f9y)e(udSEB0HQo}tWuz-y zoStTrv9JEfJpQyp95TgoBM1r|N|e&8E0SAm_!u+uex|g5ioHWjBdb8-8)flc!n1T+ zzq;2o3=Xwu@^MrkgRo0Yn(fm$qwsO|knu`tzJKh0qE2SYvU2l(+l*^EBx%2Pu$7ro zC(V5VdwqE4$13{VYLWjgd&i5UYuNnvsO2#$EDlT}d1e3SR*CFDV=z&ej7d^UB9SaQ z5|^V$g9+1f0{6&Zxr_*fkJsOu;n3B{KYk$_Wqt1^=XD%!+}ZGnx-a)15D{|>!E%|f z-aT$(#H`&MIUDBLI2OV-&7mXQpK@y(j%%9_+fJt-C#O@c>0;}9tAomPe$TTErEVq8&5iazz8cwh$OmW4_WWH#oy z>Z#af562;Hk7|0dl39>B1iAWi?4aiwsXO9LSVyIweLQL2#ni<^0H?S(o@G8Ds2U|C zhdLCk_)z>nVIPep$&W!Y_ThmAb25S>*=G zzc}#D-NS9GNt4?#myi7n{$N=-C@*nT%nm9cWYJA5koau{3o% z=(~oMew3ISBxnuXd%buthgXdBROY+ zc@?U8iyt>4rnD^ls}H-EvE_j?u*|Z&*L7~^)=JXj2ik@~Xn~zJRL}XkRXCB<&e3TT zc)&&~`=g=OsnkCn@TWwwjM1uiv3$!)>Rg^GpU%N}>D;ztPlb>?Zxe>SC9>yp=_% z4bwg04sT=hjWK6{NW?HfhY=OPlOEBnaqrw@GBO3z!U=)n_+ zK3^E37{Gat5N7)bm>%tyI(l4@;gA`dwLq~jNp3M8*8T<@g2cYeyg zYnvUf&yB;XOIVZD6>~{9nB73wx-O|ycu1cx;WMatn|(PYQL{U}`$Mb))4Y$wv)=ox zgep?pFX%SlUV;yD7Bw84jjS57_hOi{YV{s-*OU5lLTO25Nb==e)yF+v$IX#x=p&wdP=$9cWQea2oHks zP45QE%{MVsGu0V8W{d_|LY#xU)hsV@>-i%h!bgb_CxViCU%BwQ6&mz1)t^>bPy)L- zrq#r9$vdW+Zd^UvN~JzZxk5j~NPO!B#vM|?E9LvV*|e>Yi@okMyrtBZ(m=ncjvUbX zRsF4J-}abg>iN{U<+6J0rRKKEa!ODDq2B#7_Vp~(4{8KhL>Le?LEm0$9pmAcjVfev zcg@R1y2C0?m9~?t;IfNdD(nXk|5dL+8(>bk%jM1LEr}@fdA&>M zFIw{}Za?glNp7h7gqdYot~a=l{?!Hp%YxiD-x%*(gZ4YpmGqx|8Fbctseagwon`6# zR2_%fP9OVcT_sk2;G03HrTdg+6_IEE;#OiWFpa*k{lFi2n7E56&*jr;z#gLEmsp@w~VVDj`|& z60!SoJ%oTB>?`&Bki0SFi+m&5QM!A+?jM6XltK(4Lgm^Sf+ThQ*>h7h=ifd%qEGbG zj3Fa57t3N|^33R1Vp%sf>%sPA48hjMQ>b!Y_F`Io|0=J>N1t+Om=`;ksKS~xc^qQN zS6J0bK(Ann{Uje)J&Fs6JWntgaXaagNDXEpNH7PoDz7_`tS{Y@8eTvMD;Ece*Hj7c zxmay9sk&6Ss6J;-jotNQVBx283?ox=i$f*c(Ru%B+zc}#Ypf&PU8{WU3%dOUOjS>r zPOUFS07t;(H!?4SO{`4LMvJqY7#>r-?OdaDUqNliym&F%;6t#em9)0$-D`0oZhGns zY{t+qerna8f2u!a7Iwf?Wr4p)^6Pqac(7voftD#Z4WxF;(p)>^2i zUUs^fizryfEkCMKIA#w2e)pxL38Pm4k_5-9KXUGHy?dPRgx|wV1Lwkf+kzqC$q&l? z>*gOnU0R58LZ_^#b5z!!=Wr#+WOZ~89h}*giV%Kb+$O3jiEUHMam|Zt>#jd`Tv-3) zUAP&4r-8`ntIERNyS=Qhfm%o?@>~4dWla=8sFpRs$Oo7}J_Bnjs%)vAgfn&qZBiL0 zL+Iwse^P0JNP7g$jqF;$A*YH=U{<>|Pn8({h8rCRpH5MH<*83cogr@1@xXsUB%(^Q z-Xd`RfmEuMO@Byq51m4Eh{CV#i{P{J0_mEQ(iC34(@-*|>07S^r9W9Fc1va}JH1?2 zUWfzs#`S}$kGsM|?bIK9)nN+m-?$G6zRyW%ZDoE3Ctu%age~;8jqE}d->bKu<2y)W z_>k|)LX|G7O3^`fDq|J zx(df$PMZgNNOkJyRdWS~b7uRK^-5;hDyI~2f(l_eWQ8)CJ^GrPt0044Ob@pQ6*iFq zZf)pC#Nd7$M0l{ZD!yu+m7tN=p7W7o-fs8s<#1-Ws27X5jO?A(sL%S{=7oQ-j>A9H zCWz|j4RGZ4Qpv{8w44hN9i|iND!L`P56bP(%Nq*_)$&SnLMkn~YL4R!d1FIUa^(F+ zfR+xj#qle1Uy^Nor2nOy_Tqi{Z))i@XT(UW(BWH8gVl&8m5vp?8Lks&AOw9xMoAx( z6(zRz_|mF3ef*(_x`Fm5j7E4qMkASTdSpBuCaN?RvuRqoK#VIe7w0n$gT;e3{*tP`^*zGEzs7lHMRR1If&DJEU8Vko#>nBfIV-Oo1`SPAirZl*_f8!O3Lh)u35PI znWyNPUV9>|yQ9Nf6;HQBODlG9a>$3_DEx5zM0%>%JXOvS()d+57IVA0{Wc%(#B+EP zWp+yN3zG8V5PoX7u1qwXEXo%G+!`pUv&EoTj|8cs0&j8(2##e68a6D^GFNGC3~F$& zvRG_;Url90X89^zz`QUU7Z=5YZ*&%_4S+RIOMyr)W zw#-tT`5b-O<3qxosymWjL{D!w(t}U*%TTM{F;E`=FgBT}XO{J>U`8GB%ETynSLKF1 zYxI$8*1F~m-g?|K8m9n)@gP$wwq@7n7RG~dg+2ZeCUe{s)A-?(^g8#LZp1eUUXYW! z$}aXv!r>-x1i_(}7SEuHVbpHCx zBZbMC*vD7q=T=b8Q@r;Cg>BnTUr$Y*jY%@|m;M9-x+&#f2L8As`)n6?c`pK&Iv$7y zL|DcCK$5Ea=JloQnzaUEdkGE=!ZsvrOAm)nNDrV)?wr2zPN)%v_@&?<)URzm-W_dg zxC@`EQi+QsIb%UB+psX~I*Mz)55hq|8WPjOlG$Brubf{}vkMY;lhEipN%LSwy@QNi zAQGi~m%_SP97p~!2@VI0ceG*=xzIFGBWYcXg`|18hf)*FCzrnGgr@oKo8tK%FLCvB zsYAw>tQ%FAhUA(0$8yJf#G8^=^?Pu8ekwU$euK59fY@27 zA|?Kj6`|Hj8=^9E)pyWItRA*0dAsnCSwff9tCETEcI&#soc9VNgXgUxF1ts!Yt5lw(~fAzs=`T``f8FOp3u=i6s9I45g*TmA4G*8bT1F@+DIke?ZP8^ zbif_bcP4MH$*^puOyV*!Eg#djgRvhdV^VIoDaoFFm@~rCLAtIK!P3FNaVkYDg-#ajQ$)HN^+*+cw*CI(o;%?f3R+|-#`q+OPmn~6L%^LDGBxDCK#6fyEto7ElK2N zuKMVF<>fK=5%3gt2>y1<`SS@=$x5bhjLf8iItnfu|oo)Y2_YIRo!*B(C$*FA|Mu6 zZEX#+=to@8R`C|g$$K!Y2-7CHjb*wS{_nZs3s?or^pP~&l5mfA*o^m5kyQ7pV6|$d zWIdI<_s+TXWz#zE+_>I!Oip89k*8{9yjKfOW&)+97My)|Jl>VvoDvXeaGn(%H0swGLb)y-Wy6Lq)2E+rrX z`sd@F-4HbrM+@8bpYHWuru|tuFSc)nbtq=nd$OY~AFPnIpJ+eeT_if18ML@JZcN(H*ce+qViPj-{kF-dKc(Ks z(83d!ptZH!L-DQPZ@($Rb8HHmv=@r9?hMKW^oD)%qkIgnobLoX;ki$K6bb{C$PBz2 zatsSyc5ew5cXG6jywF?AE+U_<9^}!px&5XridcW(m=p%4?BFkV0y*;I==ZVZ#amS8SxafI~5e@!-Mcq&! zHUwM7IDB@SfoIEUrDs}f4mRMfi>gbraAQgD#`$pE-BM66@ zD2Vvx$8ZHEqA+UYQI_+QEhxIl|Lvn=b^m+JhPE>Gd=EeI$IM1r84tx$>>AF2gOCKk-HaZ@T#AR z!OPZ)4QUsw-&JB8s8VPyshRj2h>r6{Sl!HeAqBii9r~P2FB%fa;Da}V@M&`6d7bp$ zlyx#K+eEp-ZBBU~iCDZLr!Ohfw5eBkIXroD(9gu9*PB8q%@J-nlQo1&M;m7yn7{_( z4+eCMg%#}-3x@=hG?E3GT5@MA8Xj`tF|?9)(enngD-xY!2aM8@>)iV!vv1a`NYfO} zMR)g*Y43fI1YX%-qD|CY_W*VHd*uffvE0-`N_SI?$O{IDTk4|R{X}e#!p0_sIV>ujlo=EE>rI`}%Ij5l*wm}Emo?J!r=$X`CIFsYCE<_tD?i?R3BEGcOKMmGndtIU|um4uu|Vxs!^wSKsI}P8SLwEENkwZ>l|_ zvNB3}W%nvg$cc&$|D}b0`K75)}))luxljHY+CV%Ty zQ+lcKt6t)rN*bj!u1U)SMTKA??*u)soB`@|H$T05>wVQKxl#rjE+71g8x7Oc0;43C ze=&L(QixTC8S|yx?uf#H?mx+Ch#tRtXl1O99nT%*Hgv+b{PO)>ebHU@kcj_7)w@75 z{m1{~eR99$KKEf`Zgan;A-1t$G=t@aCZy|P9tjMc38uBcrfo4N?p&x1 znB`i>AMd9i{CTJyfxIj~c>$NmD9hq6xe1h)0!0EaCAY8$JV=#xh@ab5jcyN!)GCSM z?be^SeiH6FDg~A}C+h*K>aNu^1B9D^bnVh=q;E&IH4L^0aHqoC4eEuaRQbQ~*p1*K zll^(@Y?SP++J%D}YF~HmDOb1}>M|U~^S%w?b8~2o=RV|Px)8Fa9Jv*?_qN^&H=eQt zazJ^zIU);oL&1VVuNGkA1JCs$)Z0Phh=95Arl`y! z=`<1OfoR5whrywPt;UR9sNo>il=4cUfhN3}sPNwOO6>LAZQL-X@^rfsJGWw7Ri ztGYB5^IQhNz4S2DdlehFL_Y;{6|sU3=orEWpm$?mg*uvFWah(82*hDiJow_{;oQLE648D<;I=n5WkMQuxAC9$AB)hCQ3z^7xW!G3Z?H8w4KWJYM zO4rS^0DA&#Tcfgp;pxzmpa5@uJrmXEvN3Sm)pzRlv&Jke#6ypu8RQIMfhXIl7>fqR z;iiEHKvByU_3){1DPfKsF;mHNCL7`1V#s_)VaUf^kLXJW@(#O!#|N!`V6t*-3#ZQ* z&N?K2()TY0|MU5o_bLunaDzB+`{NvxZ?CM@V>sy1zVzwO;f>V}WkDPI8_KV%07 zFFoz=F-lM`E2{sA^Y<4REXlOrtlZp@e&feS#_D_wU+?^p{W--;eBCzz=;dKhvhdv< z+X|AYglvKuPo;|?Hp0q5Suid(xOY3N=?Hx%ecSP=nBMXzv+8D$h6!YCV<+@Xc57sH zRkN}0=j`n88sThr2QZk@biDvYbWq6+2B3E$hUw))ZYf4dK!2WKXkarX(pxM6E6mZ; zyM_2H@t$n5+V&)jHq$}d*3b_=Xc&AzasIK-E8CD;l5e8@7twVLu+QUR#aAu=Jk@1ExEd?xIbGD#n^YJ~%fsVUV!tr$Q7zUztJ@~X z`^;_~?~=A8qX~{}Skk=%K&7E2vT(98S0U$eY}7K1b*kP5m(cdZ?LIYLFT=Rp@ulrx zi}l00^YaXP?Ms_+IV0=K{V;)0W;fx5j1laG^uq>@iKOh-1_>&=%Lo>}s{+U3^9|80 zGtWXsjKtUxBHix>#tn32$w!`Tt|tVk994DkN*6;t*TA$9LSV0}Ns|Z)O$9fi) zVi5hHj{aZw@ZD3V_?3PSQnpEySkHA8fp8!=*%Bk z!1yFSHZ|N#wjBtCs<%Ts`i^fS(A>jGhOck-DC#Kg>KTa7lAJLuDkMXjaT zEz@`%BP`L04ZAg8oKF>jC9WnF1s1WHEdxs#VL_+c>W5d)JC^{0hcwHp5tEJf<`{-0| z>~`uNXkLz#PlFAo`=z7c;#Z<7`iVJIMliM4-#ApO)fR-bQFLrKZhR&H z#&W)72Po(ZQ2B^1K}QbN*>I!#Ip86&rJaIG$ckiL8_Oq4LnX}aahzsnFuF8mjt-9X z@uFh*NDYmx9|c`w7iDS-Wa?M4%7i6G$;u0M)zxhy3DgATlhOhbL9z3S3_?*2O0NK5 zudDuyf9<;xO{^p1aAVn?B5 zfc^W60$IUiQPC4QQ;D+~GcQ|aBCz@0FIVR+WeWQo&CK=r-#k%GuykkGJXaz`#=~6C zm-co1GY{gP%d~V(HysFSZ++dMO#%qHSjdKXwl$8o${<|DdEPr`gbUCKu5SSjEQ0EH z3!m$-0!Y0ue+_1|c1bJ*==|89m3TfQj2>?UtAe3B#$_uRGcq{Fd%!r5qpn&H55al>pW1s^1D6iWoGURyO^yS)Z>_{=;@7&f9pEA^#wp9(W!MS z>oy`kElUMBM&tzbtu%}|zSJuDsF+J(*wGxL1Nt-lEx3jF`mwo(n{R`Dc-OIXitn%P>eJ~{QDJRuMV@o_3Cn^%FzyNjk<~?e(Au*a^^x<=WzSB} zGvRJ$aKV$CK6;CS;>pt86x3~42|(r<-U#e!7h*I2@Oy3;D`I5_=DKKXN3?5dYfp%s zW9#JvG!yhO6zF_%yQ&bnmT{)6>Z0`7!Xf`r#OO2i9|OmJu;D;>U-fez=`YiVkXR$j z6Z!d_)5gP(71RmZV(J-W#mL6uZ!T-_=Th5|cRtFTXpol!t)TNbu8E#161=&IXCAFT zQ65X)g^`*}lA4X}29C!YI`lO~E&|kVx*H8;TC)z+BAQG&q9WOJUBh?*T#wMD@+}6a z0kKhPA9)uR>7Ab_a@4qE=wpEvE8(SwMUP)-+gJJNP_-Bx8(`X;zqu zT?E>d!SGfXZUY~2h9~X8E%CsG`C4k~01jC)Ak^Pg)*T$0$Fk!%%2OAO_-sgc8T zM{S)iWmtVGCU)rfczwwVWM6vMiy{7%DXO-SZ>6^H>A%hL6T$EtbB zvHil6pk`B3Fx_a5RfMhdh`J~Trv`c%a??!>kr^I9?7H*u@$tw>x}0bRDawY8o3k z%dN5`a3T`r<+3#(^Fl6n{a^j%5nJP7t0lo0dE1q_(-m+~g7F5vSK zB+HYrE z_8mJ+q2pVTjRqAj+5p#X-na=2zfoAjReFUjJ+C$i^O6^~#e=j@8Zd{@^3SHuOY61h z2)SOROFZcT&aR?7d*;DsV`{6PVnMu0VWBh;+AFr?gScubm~Q~N2j5%{V^6nLor4Ue zuI`WY?%_G#@fJ<3wy!a}o|BIR_8@z}XlDxJj@=HLW%3BcvY%HEXG<*-#I;xR(dwRz z+*^viJTt5d+0CnThBr(Avcd2&NdQQiK&OMRvMym1F*3GQrK4=mt>qS7H;#M(0vYteRZ$W=$amn!=@kleJVcQ~%+?Kszd;C-xTrsox5k{WVYp-Vn; z6mIg*{lGV;q3*4~sK|F^sWCzi#aPaLx}40@#o7PXvJ+o8#d&WM`Iq6$f`un4)Zfs| zUB&kXMXgAE1K7OcCNd|DazVNL^E>o?#u5fRTfEV95Fd!|w) zP|$ay!*xPm4>x=5;c%K#ARBKYdQmpVwr}B-b9Yu}Vr8vLSDOr^+p;|4FjCkb9)=4# zI*s-#t?WSKFQw<=q2Q3!Sq0ai#oW1csD)R$R9Zb_N1#v8z~*Q|qr?u5Xr~$9;*-+n z-$tw&n{Ze8)~W-(qqgm+hC z9OG%JXTQrs!|nm6u)gFsoMXq6xt_I(#OokZak8Ne>b@JTTt#G$`GQi2xm^8D)C$}{ zrHx>@ak|I7x(Bs7$U2{{> zH`WgU1+q8h9E32$>-`1XQ=o(#G*H-a4`Li4dDBS0zazB8k1N#PBR(i@Mx?CpW@lR1 z_Wi5Wc!1E^E)ThM+=19`$ZA0DrO~)Y{z4$BG+<7<5=&rYAdKh*`d-RJZl2bDUzKE+ z%vGRlGMAeGFg1`HN~`-E4-#U1(w=fF{ul9ECSCrxMA(G==ptHKC(^#SaO6+}=QKc8 z80izZ@%NagZ@7W!tFZ4ci!mxBNN$4iDxS!7OQ^P}mHV~=z-}**30=rF7>iEvjjmzu zA0E-r8st#HVo71ss8qwo*X%qWFywByih*xB>flsoFv4$GakAYyfntL2SV6e>rv-EK zb(?4}6Z2FfuOsZk@NPfxs2ww2WpD8_kmb$vN!Yfr({Z~;BQk0Chpx|tcCY14!LnS! z1Wl8Ib!$eP6Gdoj@dxfdSQV~B0P(T876J%o;Sqc!6(7vhW&ERH(#Z|cUAc4|E%`VI zt(L=e_ED|jys*w#&fjBh37?DS4_ZV~by7xJta*vFCZ%+Z|1emWk0|+zMGucpO4y?P zu$NSyRjYKQMFb=w7kD38+PW_$BCKhQHt6{V>)OOyio%`FL@erd|FVemGfA9htD=N;lwIq5`c*90*(AzoLt*vXij}*p zb4epzNj#5|Y<}S5%jf)Fqo3H75bb{@T2Z&!`I>c1p5=SUq^cz8u0EaTNs}cWh@F!a z%Q-3gtctTia|xAQcfxOEv$)VjK$y8dPE0d!;4F8CTu{xQ(m#=@{jmRhJ)!|&or(E5fHEHwXZY1?h7Tu9=BD9rLo^tR!(QjQeEz9UiAe01sqg=$&uGkf|) z2sT8s8joAUS`s6n;ZFJjszx<`B3No}s6MwFuj@=iu~v?ICx+fUVb3i53L8=3#_^70>z z{htHAV5d1*1Z(r;Qc0k-hMz9=f`v4^g*>;mv{helv*ITA=Z+v+UvX>Z zDEU6mq4rNt)}hS3?A9(r<;k9x2;IPEg=lN}&$S9(O6i>S3t1?oGzXpkw7oL@7sCFB zpZH%-xEO5jw?K8Q(P^ObXeHS*w_QYAs2NfyftBjnA_&!-HlGqB- zb(QU!zC^hS*jOlY8z?EMhy)Jp$u3TrTg}??f(WSpUF82gV*?KUzZYp*3;(y`|4!_G zexU!eMp5?r%;{0@>0UC=3%e0KF^(fdkH(Ot&I>FrMj0dhNmG6}-a?Xe>PSFAhFZn4 z`joS4z$?p$)n~=u=RZdkb+8eN(|@HBVWz3L{&FRur~FQ_R@$mV>%+gtI=nVl?Hq&~ z4&skwTMo<_Gwr9zwxWgLVo+(FU{y(D>lo5cxw%fcDM%KVKcAqV>J zqQcptPk>cPfVc2}qOP`GKIwd|T$;1Z;@rIwbAt2f{HcPJD{2e-I+NU~06>$isk$V6uz(A8qT>o6h)tyWf~wa+c_R!XjbO}0eK z{0PC|A-;+YLzk8T+jbXzJWakfv~zi*0*%m@!<|$76CL@(!4=MYf>#`H43??8Noqqlk8g8q)|Z1?=9ax!6U?6a!uu>PTUhuc!1`t+>?!3~w2 zWB!+JjeQ5Q$H@Nm$`digYS)m2pm z+KHf4ziqTTN%6^gxbq2FYQtb+D8*g=dohKvWA(RRJf(g2`X#F1kt)|u0z?_U0j*y^ap~=c*j^OYxo8OWe_(=NI@|K&lhZ}nh5~-&eM8>d zg*=|$ww$Sx^G1%dZsQLJ3xg^4rtl+)4gKxi+Ntog(aWTfl^34iT9}xqL_S;M&HiW; z^p@Y_XN9-gn}l^PMHT!>8nB(_CT(W zUu$_8RHu|44G-$r#7veR`IqLAgsuACdbJF$2^YPl1rF5Rm&lX-7gPdQigvTF7`9#Q z*RYVN+m`l`93F$P|8i*63b(WQkI8a&HQw$*-H-4i%jX}lgwy)|Q}$G(`<;BGQMV&z zk=0VOG)hRo$1_GZ<*O8)to^vvs(Wu2rhfZXe9(IQQR71Pg)*;8#9sq$eNDds8is^; zj{?)+Alf&z+-5`augTfZ%iK}f0pkLqM|IbPRq+|t;OpGk;9DXZbOU(0LO^jiY9A?^ zufZpoMmLiqg}DUh*Swy5`9cGo_AF!QWwBVG$f7~t9yj&`R}G*7rBd_)RdxQitgEuC zuSNkF>tRFbr%af0KJ)HNRK|m1-);23^bxZ1mv1tjWQWIndC2|GJ*rq>!Q6Kh(0LAn z75S@&r@t7Qhcab34!hZH!ej5C0Xev$t@_1bw1}hI%k;#Ppp$Zte9oISF3Rd(A@O%B z2r~a@k%F%rCXh@dUz683E5Ii;^`;8%AmEouX#)l5(evHZODYfldssB!3H1OVBGvY0 z?jt&Q)r)$>4HGjNbRc_us6mobs4pX(R*5Q6%Zqw(Uy2luqTR439Atg2dcGSId+x1?($7kU9|C1D#^Ss8}7#K3uqJL@PIWSgUpNEh1a2Ain)U zTCP%YMo5kD1Hqd}q(mJrQ>o3FwvFj}nu}j~V24;3sm4Q=>MPajE*l?k-0cqinpfBQ zl&9QUqIkRu_ohI$j#ot1K4VMdZuuEBxaWKT=8-ZZi?Ji}Oyn6zDt%71sCxqFvs!Ut z^(B~INLn+Y^aDI0Ns=Wjs997s_OkJS``o`64{b!E1)SDA@1eiQiQ2Z{!>)$Jm|F9crU+N$%>B%1=w>;kp)FQ*d?@cw$kRry+-l{a*xG2JNqDT2AjAiJ zW9W%Bskh`|#lYx|#-~qOX-e4+%_>teoWLODcaT<8ikZ=?j92}8sXoxp{c^pxv-iTM z(Vu&Sx`9!Q4;7bv%q_|)jjQRiFfF10l}*U;IK1dtt`w$3-0*H4kC*lCF%+K}3B zA+KL>6KKg?&{O0(v~%XdUW=WN`YZS!ugyv3u;A71MAV}lsSx>lnLY62*}fl+P?xVN zZ?Oj(cH0n@NC?ESDuqu>`i}gTsx>8Oe%tHcX!E5RVz~TcM;ZC{yy>IIqjt3+!Z|g9 zT@%WV1~TdRoCD6gImc}`0BZ_Jf<|Op=L__F-Z=hi`P^*VvlgH%QUItg008}M(ZOTuPlt%SqTC7^O}@v68b3is^b+ydtcaIF zz$~8Hkx@{ea$p}0*EY7VcX^EEWwhR5*A(2)4tq%+xOX5g4z#_a-mV`jrOqhIbI_Ac z5c26)V5A3(f4$=%`uAAck=&4=Hvkbdawv)~rJ#eC6k_YbQeNwe35=g0#fz1h>+2X8 zoHDEXKx%j@;?mS|;x(ors$g$}cu#j!j)w~E7EcBAYs2{Exu@e{Lv%GFlfU}v zmC0Fd@x?euty+@E;T51i=Pi)|=f}wU&#JYnogI>@jMH%x-@w4RJ8l@CRWsem$b#xxDDqcVZW#pPTjRQezr6H-l3 zqlL|XSIS3vnql0ZhKsGmJkjAEPIvtMoGnkfOG*Msm=KP0Y9P|tbe3+uV(qpMnR{3q9wDZ$P`OZ0HXMWCKDpJ+ZC`$bC=y#HxC^ zT_&0;yYuM4a;A7dneG~vTE4KWkEk!8T^dpJz-+1M7DgCttn&c z@N|3#(ElPWDs&z8$+9|jsDC8>x9UfJ5j&%7&hdwlzhEeBL++wpD(M%!A{s1v1_x{+_bs{N_~K2ht$3?kXDbLstqzL0zqu?O z_9?CA_l`F1T{xQTbU0(vcf*@}PEw{5xiv{0gUS7N!K!1$V?>wWY;O2>H|gsXy9EAw zOyYI0Xf6Hd!xitV+2dYeDUzWU?@RUTnhiazIhkxIftTH@oH4SNblUM|H)mG=P-v*i z{cm|DZ8uXSw*#zJGBgu-X)poF*K-MsLK$q)gyyMfpR2ad_?tFHRdZ!D8XAXcxN`hM z@2F>8me^C?yZ49HN&JWfDZCiI73Ss3ty32r>3zp`)w^MF;4T;>11HFPfNdg#-BlQJ`mqd%R z9C;4;IGD;oX)|?ZZ@q%V#O@6znhhAA`n3_@ZRgwAsSQv@csae|{T9i#z2zn-u?;$E zZESnbf3~wti`yV|wh4{^W^dpIh*2@cN~C&;{l3hZr0UDs91gOo*3eNIbBN-nlj70N z3?o&$d3hV!b~v5sE%Vq&f6EO4P|z1pPmsk`nyt1qL?>}&~j>n6mbrDwo%$Ei3 z`(FNJIxN;k_AQ79O>wF*_2p3A02tG0Pi^Y+xzeT9;_n6?efj)g$Ze6s9w@eQhpM>z zFNbuyGJ8cm-AC&$Ox8kAbl) zhdx~%N|pa_w(E)wA??=u_?R>ixT!|_&wr=lpu75#$hI=+_>W#*+W_t%1M>SM(oX@F zPW&XC8SRaUk8>z8A$QUShXe!H=vF_+D+Pq>ethsFaEKK5WvX}z_W`o)SrAn?Qxl~c zF9(qA`vMO!jBmv=U#Gd-!3!21#t%7tY|`9}GPtQAKV3 zfw-*JzQOt5L)$*rWBmd})sOB@4(Zs2%U&-64&BE)0IY_+29;O6Dc>9N!JpPtJ{G#0 z$x!RsRyyz_rN^*h)ljqG@A zKs+vi`&Iz{p9ZmO%0*^2PFN{ieY!T~kIu+d#Q7lcbk8(oW}?XAV#!faDYL`j_?x`z zqN%^Ww#GL#*%0PMGkSO5aWT$3HVB*=Iyy-U9kLm1#qPhF2xhis3t-c>66DP#o0zxe zQM*Aq_PU26k`V5;18v>MHE4XT!UtcTQMVay8zq+{`Fn!pDC=W$_eHva{)me)`7Hv4 zQ%Tnxu^d6R2rY+vLXf#xohmw9p1(Tmm%cjI4K27Mn$F!mcpzuOc+M7|F&qe;%KsWq zRzP0iE^g!h2@!^R$E~ns-#HXk!Mk%CF-@4`Oc=Hxy_?i~ zpUhQ*yovUJZ0sEbyMIhv#)3Z9UBEAag45VkP3SUY+aN~f;f+5Y_Z zm?&Qw>*Lkg?aybeabr>@7Pax>c^3Vu+!*}|2X*kInaTiVCX zo{JU~et8v`x1!i|H(}LDpxs#70O)D0HH|8bEfplG1tHX^R5WCe&LCoV&ylamN#f|> zASPN4viuWWmq!eJjTPF8Ti>tjQst9SI*lVBP%|WAaFdIJrxb@y{_?{``)$865xpk` z)y(y}w&g^Q#p(j5Ri#kO zd{6Jq=7+Jqg6`oKCqA#+U)G6zRmt1nF z=CdvX*H88qRZG<7*36dgxw~DMyx6z+tF)4j=E}9|&S{nsSMlsqpc%3dgn7k&xOu_Q;-$2E5-GWJX28#!5tGTExC?@NvB5!TShs^f7^IJv-TAL%j%#~fZip7odEpdZ`qtX-HnfB-(=r5nXA+KwJB76#7%pUJ& zz9=pmozyE(PYCr_;JIn_%XXuM>3Tb}o#q65Wv<~rVBk~DdfaYv|>8Bi0MY7?2c z#^>zwR!Yq?LvLQ5n}a!#KK^=j5y<-z{r6bs%BsFOJ0#8g;zCbj@d>+ZRn0^3)$5st zO1+zwJipNoid&mrNA;%&)}6^KbQjl`xh9o?n}S6H+-%f}kvLQ?KtZ}Wr%z})+5k-{ zipIXU9Gw1=TVMGy9E2rls%QYz#k<9T&eS9#EAMm2gc`v*|DM7Ch@=8fmnKWJ_a~Q7 zoZ?|)6z1^AuE7=9S81qPvd|}vF)yEwd}8S{s5W!P@CE$Rrb+17*8CBx?Z{O~v8ne! z;LahZ$;I6&f!KJP(HGnsO^Iu@a#BzhyBJGttGE;NYByfA6coI%W;=YT?(46uZ3RgI zNSDs@mk~(9TEvYZ+Yzs>ex`t2^>gy6B)iy2*gLouYm7`8kO`fDVxFC$9`DEs6vB(C z2I~kkmqrw*)B2iJF6HyGFwb-Qm|9a9cUCTWJBcyag&Vq0j)$^PJlKVEZyvQJF3n>7~dzn1J&$BE2MKv(+RC z^_OF~{p)X@)dk?GekEH|qUugi)xiIj8T)Hx4pz-ZMm1%ZUQfS=Y;p zvBR9S74BvZs&Ndu#X~EH6Dl2qD?)nA4HEg-|65hiALve-SD%MX`(&z9lREV_;RFsx zG&{;tMX%WT%$nhBQDZli7*~5d=mA)jan=m7C+D(hULC7=B&M2|01z2n%ULorxoG#K zYv$tion6z(c`AK-aRbk217bGPYZ=hm)iLs{@dUFfi~r7nfoPyXpuqgY$y>c%l-?io z{(u)pmK@Sl7sYR*aeA#bawk?m4>@GnM5EgmO6_U{CPp)I4{h;2chjXz^$Zb_d+(p7 z(oAR zV^Mn{|I}tBucD;}K?aaKu$*&QfgwNEA zu-N&Vo@NA>KQi)jk-u$Q9Q6anvmluaw5;+F-eyQn4)*1$6i;uv>Qr4hg_0aFB2m{% zHynzExeKyKduZMUV0J!+?Z3A4Lw-=T_$LeFDja_6RUudzyJSb-*#PYMs0{MGN{3(I zJ4uFb2)#i-n4h@MQC=iu{+sr6NzSWU#xIAULREgEn|fPv9Q(PHqDxSoZ`b;muLS4y z+*3Ik7edMu+--j;k(_I53yQNprB1X`HZw8GR4DV9flM24jDk``cA4k0d$%*otcE;g z^Nr=vA9LZ?R<4$c5j3Mt6_=-JHDFc=!jtV5B4{H7=6)915aYp&7_fQ8+wSChJW6aZq5Z0Wdw7iRT=%Nj&V8{shrhNFRvI7p6eOE zu$`^fo~pTAu;ZveKcfqy)K^{!<}#6fNgqhjXp(7a`XH0FGcNwB6w5A~JA7W&`mz#? zov->>7Jo$iJw}7FK~Pwu&mjM>Q?=1~`qsWqu*m(n*??Pd6`b@VgBJ)|c0n|#Fc=jJ zFU}ddAMn;Ik~uk)7HMvrlcs!xc>l1taMo5?D6eSQa%Z<)h z0@v1}3wmiwM5hIC9fMxX8`@=5RJrYgtjYf(td5KEKL6Y1yPwvWk@$1NAjP0ASdrrI z#_q(mzsJNbVR}lyQ8!iSVW9r}cYH%Q_gOpa&=y>jkUx~0HYw;Ll@3isJ_Bs@AhtdU zH!w#NY6JdAoi3x%)U+)f?zVy9y}nuz`Td8<*{2Hyi>{=m6BV7nJwz;dFup0irGW2A z2vQNy)uvp*zOf3ZzbZ=9y-qf#J<59oQf`kvl^ojmsvj2*P=CX7lliDPi{RxYsT3Cs z>UWQL^_bJemuD~z1U}}XhsJ&2-I?!r z$w&f4%2eeN?4sBxDI&9eF55?z@^A%$NTY_AAyaZa5V*8UInBiq*WTUqZT>5R{S){^0jkidL z&gy7e|FW-b?Ku^kHhRP155YqmgRao{W@B$(AAK!6021)SmtF|B35r*9N6naHO9dmI zd#KauqVuV4h>!Sk3GC;3_LniXo}siab$L(MX0&JJ>GPN#=W`Mx0`IiGbgjJ*?-RRF z-o$)x9lszN)x7lLtXTOone+v(>S@927zmPiO2b!Iabkp~enfS z)yZXB;F>k~{B=H9n&sG?RaG!WhP#4Zo+|^s8S~FvBAM1kyJ}cZhn|RjL-F=<3+|-lc9?|ug;se;PR|*~J2BHZZFzi}90C6`{>s6HD6fO0^ z{)swEg0XiG@v}wa+?3bLr4b}vzD{2~XdAUnQu=!=M7x8qJ(gN;iRuMv->!{5^J|C#46Ka1xJLn!E7g6L;9Sl)|h}K&4(+%H~xJpRiF? zik8Hnb8G@R%J2^!Jl>d~go=tc9$inZ-It-`e7Rtfm0u|2$JgZUybA_$yT|4GwCbjt zUS3iOYrAmWtRi-Dq;}oHZ8~tpjFRzGl7P1n+18$g)7rEin~5njPDYmVo*A)4W)TDO z9fg1BS595>H=@07Gaq+ds&SAgll1-tlvE53TwPAlv)R$dufqbIXTHe7N)* zli3Q;(m%SdOmrGk`{Mj4SvSG)BZAtlTwglzpEL_ZtT^JKvPy|}FCx3-y(=T_HKgxR z{m`Ov5bXV0_uL>Y>32Nos?}Y8Je6CtH7`eIaHw1WeU)QkMpqq1i%~oE8y!(78%ofZ zQzlRO6nD8kPGENpM}NAHU}7O!cY5tnEiS7Dyj1yXL{IkDBTun=6}fnA;!;B(?{5=7 zj``X@CB*mQ9zP&K=KhD*onFU!)rRJF!d2{8oGS%->alqcm@vfHjcWJ7)M8tsZN`il z5L~y8nfm8x-g{`Tw+!QTwaF<%1c__{n~Rg}VZnxg=*I@Hb0IrkkoAVbAf4tAk(!L> z!TEJR=I$F;7ZD;(Nzrnfo?f<*6aamJJ!O7a9khD?-9PBr&*iBI^?xVxmt1{7)F2H` zxurkl+w6Ku>y>IeFbkYs^v$r_g5rexUA|d$LGY)3Q+&w1pnn?O@=ljr0$oDwfZmBF z*}b7euqWb?+oam%Uwd5x4x5Gym~4+;cW%OchniaeR1L6rn2Du8#v|dQ`wv*ADmE;f zI8U0?+-rm>+W&y9F;E!}2#ECh{(Le-G{;^}k*_nDX#VA#Y<`ce!3?H27YQlU^#5WP zcJ0d4h0LltU$;`_QyrmfaL92+xOZIC$WwvLCS4=GbBE1fmvbHXIOU)*?$4uRW8oBV zO<2ijb0VZLWFWaD%ZB#U`!k7;^W{IBXG`n^60}!4iOB@5QDsZJw(Eh-2KW?(S<8_* z(r_+VTyU5B1?M>T(ib%|z7PGXOMpko+4pMm?k;;;WZW_O$YNMKW`vKazS^u+oB2a$2wx)21_^(}}ncjAgZffTBdAp6lOZv9u3sz~gcz4gPdOY-xdbh+Nn0+X~LS z%6kfnrDE5p!o3V9&RffAvQD0-BYa|0cVHOJC%YlSdZsrL0xNoN^+?$raa)bvzQm!Y zsKIe@YxX)bxW5{|<)Rtkydss)mJWE-;ygk}pBur?5Abd| z=AXG;STLU+9(|WK(0+Qr$^eHk9(`*@md7ZUIv@i`r!ywrploUd8n>BMLP;yNrx!Y; zT-k{T$%@A>`-z$jY49~_cPv=x2dj1CX%hh-Zsm1d(_Kxp$ewFs?m+1wb|Noi}RX?keA4GsIH{PIRsm~%hz+0((~MsHt&GxRqA^m*=pkEiY@F#nQ^g}tyff4@|^ z1?Zz-I3Qo^#g(8PTL&|=cw!6wF4*oUy9KIz{5Egqe750HkpCK+L`cJL`CdMew=lVp z^mW8o`^y z7DAp}lzA#)K+^ooa@ayXzC1xE23EyMmyUL`q0HGVfx9kK`!P%9_55kDXQE z&#%&i<3~_fpkg=e8D$`k1V)A!9FXwL|SI zTAz%%G_9QCFJyYk`^GpL>Sn+0G4tH)m^>%4v0#Jq6Lv+IIY!NFl43XgiC@~x{ZOgd z%x$UQE%6rhX4#B7(@YcZHkSUTBR1M!`j5~F*+;+8OA7LA^~;UehymNi?ZzUPVXtuk zuz<+n+qVz7b01YHWZ^@7tnJG)f zH*0t=lugGqb=YozDll^eta;4-rr+q6FK>Qia(UvFiQoy_$+^18tTY$kuI?_M?}jWY zXer}TeemJU=b)X{5cp;pX5{O$Cr>%=wGOAtJn7_M@jhNsEk9BHj4k(7hk{sKPQ|36b(Ha^^sWz-EOe*sA_kBm$jXNtP79L0 zyy!|HH%$obJf5MmK1tjot}zzH)>jVmQY+Iapi9C2jL6@57Qzw&9Ai5Kj|{cr3Cr}o zyszgnSx)AgNr<+aQ5V8+uj(F|3@@oGUg3oOLXViOmlqvTq6Q-!7jo73Xsv1#F3LAh zM~pxm)B#}IIKwZw2(zZX<3Waax6p^XkXvyJewL zI}N@J^w-riOyS7K?&-2Bggge{aX-*$&W4FH&-G3K3Og2H@3eCAnYr3-=n9Uzna1QS z+u@T*YoxQdOZ}Ttyi4EjP8XH$n_#l2x?my0xLm?Mxqo2nr`K!d2>j`x{E?%jphs{t z`k|Bprb%URL@^=#Lah*ENGhguCK42$sG+LLZe#}sb3~CO6vFAa&B{ou=pq)+x#vnyzoiJb{G5{if^OxDY zN}q-9Jh{6*J)p@Q-gv(2q{7_#(o?aBqR30uZeu03DFEBihGg$%z13YUcG;Qf>|{=l zSNu~PuvqfElKQ9Oy1A~pvdXXt_G*OK{R*ci5JwcVV(k2KwZQkn|UyC0i!*a-z)FpR;ici>yGR z8gd!}IYqx*MjicJ9-G3cqfKy8%=h}_<6L!BPYyl~V)wE}I$Cwx4G~e@d2-KzSO>1>(Sm2rq&qq19lxwg9%}?xA8QpTai7l&R5Q6tSm1CBHo^ zbc%YqnYjk!I7l9;{ufrIOzz*Q>7n~+2L2Ml29b~ezY#`AkpTEdZSy$D)}0VgJ-K1% zsNe0-+$W{Od##nGi1eyCVLb9#V*?%;ch&yp_Z0E%6vdG4P!qH<2@S$kS$fl1HGC&Q zzb-4KUqgP(wk2>&ACRI`E@FLnFSkThY&=;^ePK9$zf3R;cOd&^m7J=S#TMv1W>l=A z?A0;`8cuXGSrm!~^E2X7R&k|zTh@q$kd7(SK&|{<)-!27Z;`umyULFY1=H7DOD5R2 ze(HW%h6(&a)wL^*s+RguIdAH_OizA0D{Brea(FSl@6VEc-`BJc;6XpaP6szM;e*}Y zDiQGT=K&rR+*{#$tOW%OF*S{1$VX}rx60Y-YhZW{7KD7OpK)o}EzH&v);qNiO z#hsD^W81*0=LIoGzU8a_;T@vyg5lyMg2$fF=`FORuwr4qnbEIGW>sio2RC2av&aQm zNn;FBTyI!P2wMbi=t8a8f)+rff!JgiNX$K`1IaHFoHvg~{m_2Sr`>+#wJ2Q0 z1YpfJOi!k(rs;o&l$+fl;PXRO_Z3*1zX0mnNZFP6jSDv(cyj6eX|VZw>{aS}eCbGV zKH|z4#l<^W3^jdY2lk@MQV8=Bk^BYSHj6)T%Zk&A)8ORA)N)nkaA@IErtgtLJnE5< zZc{UW>Ff|HYBmO^Wu7ijkVq|1uX(#OI2XNWqRgP46c+C>MU1~gEvZbqM9wV`1NpX! zWc*6ekpIWjdqA_<$AAC#t*KEv_Lhj4MTosxV#KUf+R_rSRqfht#E6~Pv-uUF&$ikANGfa!nPPaOIw z(;tr8I75XBpq#4U^+YXH&k&)o5GgWYT5X7}B(J!YL*)%?EJHSYc&3Or(Upz_Q#;N*OYs&c`B4CnC5>A z$<=LF`n=PYbgx%N*fu(KP#;#vJ=ARxDp|EC==*@m^%bWOYG6RHysiPZiBLw=i}~Hq z9{jcXb`gR%1yX30h%5xFESHYUb}=#VbPX8JVC1%Rxpq6G4k&?18z~ zQ?69am5NvNeM4pXDhxA*+sg?)&b_MpS8BDDr!Ys)@l{Q>NLH1|8NJ*~C77WZHLq(pe$=6Gn0}vmcV&HP45n#6q^AVLe?!MDQ@&U zm)A-baF`YX-$qg08NNF+4dx+hQXMeqtKEPpGW=$Ow$TNWOgJV?z)IuKGz#7Yx?aL3 zxGDFP71AlQZXIf5pnu(y91@F1prT#?Ac6^E5e}r(WbMrM`bq!(a!xJHjh-n|uoCz&)fXQ>X-^4YQnEH7IuqL8#+c@c4ARy1WO@bERm-5C*sdDC zfZBL-d1W+kUSdOYUcJq(moIx$J=P6q!v28jnFUvoRr`heZqx3qj<5B7V!NcB42U;g zF`%bnbuSe^aTBMpcVL9$jm-ab47ULmfWTYA|0AVI)}tI1t0gTsshaX2k$LG6MjJ)h zP)?x0>qanWZZ|)@I}B&7jQB3%xd4oqO|Oiv#@sG5p5Ahvw^r;oWezmXR(mrIA29`_ zeeAWL3*$5`0C=UJc_a{{72|)j#{NJbMYP=g&m)g^S49YjjIH*9zRM)vQADM5(1^ zR6b+o5w+sE^{m)Lvbr>c>)?tmI4v!u0@F6Z_Fr-Y&;_JCfDxoDh)IEb#4DM#$v+S< zD{5t{Lx;z@QR+0+q!Wc52`LY#k!LV>dGSzRveFDFe|Kt?0oQ?+T^j`3h_3Y`54fsd z6c;dI!`rwF>1}GH7OFoz6}aGmV#|Xm&~P2f+eC?6C4(&0ZFQoV zWsLs;HY66)iKj55>d8M15D*DQ1au|;T=?0o2Kok^q&=RVDvB;dj2tQ)+gFa<5{w!D zE(`n4=ZlRBL8oPagHJ2}W|k(Uz;(yuZFq~*^5h0B-iY{Z%5Eh7>UY-Ehg*1~tRjN? z469j>5ISomI{I}t!U+$k-Dg4#$`iuw)e2S}$kgSe2FF$qpC{ee&Hv|UO@HB(wZ_V6 z&7IeKh%oz*Cq-y1g2!<#V5#C0#ynUqfzlq>%<$y zYil9tm@6Lo*66VudMJC$*1&KHV88Z8AODb~<7h_q`O#Zf5W!3}%sy)6+?I=TtdcXNl zLUX(;>Kdm(_QojZTsU2FUAxA>6&!B|1N)J#{-$p=AIlsClZy%@t6cy6%X3Yy$<~0E z?QP}^8*9irb@k_PCokzTKUB?9_0b=;xvoZEknLn(Q}M9@|9X138h3~iy47k`Q0}U zTmgBf$X{*;FD)!Y1oa_ffC(P)WD@RF#r$v0%{1Xc3NyK#5Jk*5!h=l)lIa-2zo1rZ zuSwPya+;s9-3z77*6*~PTQ#6cG%ggdX*K+n_Qk8Xu*M4$SR#s2tqppzAc@*Ol|JaW z8k~0!wc#p^?&*1S1ljftwPGf`BGC4XziEchOvqh5SR;48d2=>Bm2D2y5UtMqsSnDr z8G<@Wudt+8pqrlRdz#+3;Dh4LB`PRa#UsF>hvCf5k#UDh;;B2tB(-)*SO>(C`b@qo zt6jh%eLOI*$inx4BsDa5_s+IyVEE1be=Fzb;!=}~U)L(@~Ab>x$K zBD#_0AHV(!ZqEI4O!KkO5l4lBXEhynQ-F~iOrFt9adneF41gD(HvNm zk|H#b9;Dw#Ci5$>EsK4XYM0=!8 z&!*QUVU_g_BYj1j+P8ChbB|I&q4#$9@2}JLY~(cE`2{=>6F+@Y93pzg7cR5{&LE@- zitlBd``JyUKGR#$ps%Q9rxZpy&jgbob1q!+2^#d^K{4YVLu-h0dtPkMSi6Di>1)MP z2Snh`A$OzUopkj!6D<$Jsn>SD&yo(3Uq^IP(Xy5yw6>g+ETL5epoX!u=fZmBe`my5 zmtMvtaBw+NJT9}O>SisPVfaTC47$9pi0qYgEIn(6ePUp*ltE6n@=>8Z390?{=)xkQ zErr6$FgkGfbLN#0#=Fj0C}OYK!DbQ#C@JfCYr$Bxk}%IruV@UVXK1GvcPOwAjBHvP z*I7M6WvR#xx}GiZ`in72kL+v7r=AE7+lcm5-}a5dyo>}?Bqs1=n9dX90jqt5ge9jhxOwJMFgM7B?L4~-WxglFSXLgr}Gw^&|P z;F-wgZ#ATj@|J$dJVs{KluD3ducQ8J{Mi6s@(G0D@4 zbXT#*kd`9F|R@DJN9J(kz#9rdrag5ensK+rU6IRo8f0 zvr~=F*Yy_GQs@Q18%qg0uC;|G;Kz^ldyxrgyt@l+qC2@TeZ8vR`Md0)Y`eaU;hY?N z!jKDVVr;|Xat3tRvy zp;`=$59zyUv(o|o8GTW0#8|uFh?S$;gK`5t8U&C#Ux~%%^gkiB!GprO+`=% zAAhU#D+1WZ6D?rYXGwc1vi9(;M!Mi&8r2bFKloAMu$eS-Hpx~LcGu8!NMNc#fl_GA zfId{)Z>+7U7msoPtPALUSAvR4EXQgu%*2iSwAQ-r+6_O2CGR?kdpS^h9k6Y5Ur%-C zW~c>cwG|PY%aDwDj<9x<86@P5bG8L@>JpX};M=eoYk=G}+V8hYNRih~Ld@i$wP|J? zYPj}#0RbXvIaSu|92{*g-tkzHUZn;GWnp`-{^>yGqlC1bIO`_&b2e?1^*45^GgDa) z?B;L2x}6=To1K9R4P3D=Opq1d;h||zy7aa5t@+XScr=XDqDgFO9#ycb^fFe}GdT|= zIF(6gTG6}dg}9sr9gF^x5v#@cSGIh|3boGX>!P=-3oV1UC&hk^{jdW2&FX5eA+pD~ zNOUJD;2{G9Xl*Qc!_I*+92G~XugqDU+GpP!{_kH^sdr6jom=UDJ^)Od-9)sRJODjtMut8iZ;od`PJa=GpFCAVbtO=a6&J>KK zNW0;dUx<{CDw~SEz_WZLBmxm#EFU@OS+NTjRZx7`G2Cd}7+`gLn`&@j`?d8Kn>_4~ zj}&V!9b?&VOV!oGeozvp`*;11|D97gX3*`z0tL2R>v`=@1WHEVOxp2O`ykLm(#RVQ=HNZ4 zeqzrnds~cOyKrw0raLUY+pCFxZ~iuQ{>4kp78(ew)M>g{qUT3~;i(J;f9`$#W2TcEu3MtecrR zXDmYS8}s?)dr+SEV(Hz=AzYmBF_L!dC%bn`Czii2W~aeKU6c+f&ZryfAzfxykH`cP z%LspezJH|Zv!RElC31+|r81He-J@I^5xCA=av9DrqgUt8?}Ds)PUn|Fqjhq#dDp~G zAS1{7hv0X8R)d@m+MdZ3@O#wgpkb_Te4^`CFr_~2uMg~sxH$U%7VY@@(y?;Sc^%%6 z+Dw7l$L&(z_e?4IV_1qUGegKiQwMax*oV!yt06Y?^(WLa?WAAR8{v6zT)qA*kz6c2 zGmo)I@;kvqS5S~--{o*`KK=WIGa2R*(C?Jhpd{>1k9w24E<0KZTg;UvQJA!Y+y-Sh zkr^{{Jy6~Mj=U7-+I&r_uTAvGq*iHt2-ql;sS+Kl&rz0+l~@iuu%3bM#<6CmGj!QE z<4P#k>$h?mAC64}5Ngh`rj07EvLi4v&|0Irxuv)p%T@9|j%ItqBi@y1f)+RK)Q8iD z3gz4B*bD~U)BcWJ&23IyR(X}=W368u&&af`Yn>$keO+@ZlXsc0B_Rtm@}X33xC)h_ zEFCI?4#AUI`vP_o1%`ryQx9oOR#T78PQ&)$u!Cl%yq{lQ`rv&b3!W-ryqe*GblV9^7UA5~(-N&C)K9Zybg7?#s(i`|`U(kB zWm&|K#(3|XGnu(Ts*714w~K5i-+i$6rU)9QPXr93TQUkDB*lGG)qQlEt?Xv#gkseF zFPM9kK0XN)_pXSIw2X0ts0TxEF;TjZ$bQ%Jp5TBgxarn8Fv(KuUbO*kMYl8?~0Ftt1*=mlVNFJfJuw21zzndDQ5$^$&;NKaENR9M{fpqAtqEdHnrTA#jY zPPNnh!+JM!MbzZi7_zaPw5hY(oE@IwFXoVfq18;a`K!z(qcl||Z1Og_UP!h6k*@t4 z#gAMIod=Qn(c{iZ7z~{Q;d8<+(ZBxw@V1)#kc;7w;@1=bfiwfaT1gN3+m&vjncYX) zudtM!^QM_Qiu}Ag^(q|NHIQ7J$6dI-%`3GZk2a(uao&hG!mao@B5ID^I|+RRgF6rx zaMdXDeg^jj2c=K-7npzxRkLFOTiP?~EVFO$OE|OC}AJd`xiCpI7Rcd>i>$e@wHV zm#QtaQh!V_o%nqPm#{SGb-`qqE{!h$1G^XH(<$nf?E*i`jd(28^=lueD-QbE^#(cK5dstqavBtuS9-7v={pp6 z(4RWR?B|IV7EQMzfmyx~*ejh4{6$?_a3KeD?k!wPHBvLcX#Tl-RQuOj{L1@y(g|-} zycA0}euff?OI0Zwna`n^I>_J7`d_GU;i`3c%IxOPEj;$Uf#mMkIqdFc(vIeZ;7T&( zGqGyHqU>HNqbwU+_h#WW`{O1}_ph=WZa$(NsL`~ZY^-D3kCiRlobFu-#*?rzXjr%y zet69*){;U+6zZLN&8Cu4z@R%QC@~PaaoF!nLl#Fq0;>!cYNeiNBk-5lTt1o6V9%?> z-|w6;*;>0M>3GPAO(x1~K(otU3 zj85OINRf2S(R9u|X1Ws`BVNzPxXL!3VGc>Bex5BcOv^TRzLO7R=tU-Vq3va>dV#AP zmp3ydAI50+_Fd<_QRzCQ1U?pX8nxK8e3Zn>Z|j~`+~%CV_xk+9SDDytSGhi41>HKs zI!BG;I&Hx@(cEi+Ze!Xy4d_s79{FL7> zlLcaTV9-4v6?!U^ye)TmE|5_8(1Gr~I)Z#LBP=RXQql0^gXt__NOl`1cXts5%F_Q;QD(zE^Y?-*CwMs!o4IFrTj z!@GuA!7@Q(hj05lz7*X;qJzGn9%Ws( z1AU-15QD(|>~~T!?^Ws5a$eTFmIa#bruJ`}r(5xVz)U@Kvp6;9*;v$I7RiQ=56BO5 z45@mJC{TU6Sr-)yA8Dis)Uf&qe^Y+IZaVTXoX%I##YC(V?FPNJH-2n;-Ra2w4KhaJ z8&6GTXve#bE2%FQxiJjVj21$7P-s%>D%VsVu65H&^=nskR_=JER_qSG z!OHMK??3h|fhOhJ(^|m9UbL%8Hv{`fe}9B@9@h-ttVBkF+2aJ)e7tvrol8cOqfb1HW@?qYK38v$$&RfrG`)g$Rm-pKtz|5IXMqJ{IZnwZ$4p&v%*9AcRHd+)3gSJJ&3efYHQxkGRX@RE~f^L(Olf+ z%=1+1XW~0nfh_IJNNTt`lc1q>P5ty;mRjP!bEb}@}wXoG_*y7F8vMbF4T`(Zh95q^Ztz9+TW z{U#qddS$P90M)umP)0+73hIP1R~*zwdi}uc3#ss(2a#A0`{?XHo*kkyDnygm`{HN9 zaFenv4MR?&^^=i?T|V-o14`bOULr3LwstqrWxDV2+2VDZ?^Bn?pFVC_s20aQ64}uT zGaB~^7u6SINV%4SV)c{d2iLbmlo>N6)9n&ognV|;=GIeLIbg6?lYH4 z9~FScVMQA0p7ALx0z>3W`2{WO)@jz+6*yp=}LqnU~+x0j{^yTH3!Nj-#xZ={yoTbUY zQSYoB_qV^++?|ao-%Q^*?FEc>Yus=c7{UCou^wyt1H=sRy)&s-yb)+50Hk1s0MJb( zb!fKZiz|`oSa11$6wD~eKLnXh_l;}YV8dgo$w=)9KV_I|P(mcDAMX5~ay#uu)B96* z)4Q0?f?v?)SS)L7znobtGxfPPyvs3h&D}6B=Fv=^yphi`c>C@;Gqs8qGG}n>pt_sy zI=nK^Kv8=~=P~OFFQ=>psIvVhIV&S+nK=LH%zlMSjmUyX=9?Cwu^@)PkA{tD zS6-DyNoaI)Bt1Iq_-?tWi-98Feqrq6bh?Z~j%Ux25RX7HX@f?HIZ3P+^4^%!IrkoB zUbL!S$%Zn_<0Y>z5AADxL=%+cB_37v(om;?F`Vu>+)eZsMBStaktfgkGKk8RYLv4Y z>zz>XV%gLRMfF$iiJiF|+-&Sx>?+w12ht73bI`Y<* zfreX9KrSLce|Y>L*~3nHp3fDg{@)X+{8hEo%KE+(+}N-XeT{ZcR+0nz>xgbXPI{=O zu8_HWF0aaXHH5^&znIbe-O$h{}QfL-fCY-Fm2ZrT>jpn_9v}Ur0F2&chuU%4VJ5*1*~c zP?4hNJh)YOpP{())U0>Yu*i;2e$ZQu^QQ4`&nHN7zv1`WAyDnt`yRn}QqF{vDV-_< zZs9wqFK<_U<1cT2DN++{Yov>5J&~=G zG=<+5*}*W;|3a+W;cCc+E3T!hJWjpKB-21e6AfU9l`J3NL1lHTYAZvTpg#Q1%=gUc zV+uXT9i=#XGb)FT<;dOyf5){YBgnQw;GNAQ(a!_FYm~GdxLN4~ObX7K*nUKK#PA@#iM6c9H zUT%hy#0HM!o5D%}Nn>Of=5EW1xR4?-gE{>w)iu(RUk!}6gkKAq3I4qkcNg8oDQBEb zqDV*YTJ%0S5{2e(6vD*qgA7^fK7=vC46+mjSZuSDQ3~A9%`w^X$_|&Dvv2mG{8=J> z7(mE?>8}3WI?%wdEg7r+BC65q(oDrG_DZA>%BjZ5iab_GDz6>ut=fulQla=scG8_O z`Llz^*G;W#1}%~cRK1t|Q@ErSv3ix8z8^A3nlYB5o3;l50ivD428-^4_n#G05@oMi{a%F_DC4{yV8RsMFk(GEIyk8i!c!0V;PY6J!04^l&GvKHTTE<~3-{tUqinU;H< z-k6xCYxQqb?=WL|cXIQX>yV#Ie{2c^oH0%0u(hk+DpBLM_|hgB`(kF0Q!<@(k5BNr z5z1q8kXvsT11ii~cURi{?9rhD3Q+`veO*xr-Ss-Oe+ukZIboUk=dIBf40y_^5Jqmg zeopU4;G0=X4zGfj+*4|M$-jl&V)SZ^yuN>Ss%_4EUb1q8Y~mrq%T@xor4!j zX;x}VmNF*pcP90auUa}}c2;SGAbOsN7|MV>oq>PDpJ|EPEKB4X&$fyaIn7?Ca?Fxc z;u&pG$lg1kVz_U!EZFV==!Md*4E24ALDvuP3YP&jz?~k$9rwi!#vL9;XYk+m{B?JK z4&t4@RUwt8e-S*U$dOB2d&Q5%-*=x{ z4F+eN-Yns}$<4o?$W~MFGBJG9;QlA!XRsA9{uW&ZzZ7-K@&{erbYL3Xuq%Y-1)+GrexF;_IzT?L0nr^IP zLbJ?+=~}n&otn0wNvr-IV z^4QJiCJ;E1;MJjeDM0r(H&a4p-u_LVJ-5p2?DndKc?+7~gF_uRC~76+F)#~%-LKbc z#hnVErOzs6Z0`~_pUM=!&G#2+c{Fh7i&ZuekXAOpfs92nPw(LpJ~_aPhSy|L)?N+T z-+7?l!Mj%d^XRca=LvjW6IQX9Y>C2JY$f}fELV}-n=Psc(@Fg=GAQE!kCKLDI$k%L zsY8}19FKCGM90^$VP)gId!08PF$}idtNSgvn%ZGp-~G=*N70K$NLcwKvyODM8O_vU z_uNNELL^)JJNj25f=;YAH|OB;;?lq`DLq{o;6Yx&N3EqeLX!3w-BNkEr>?`-BIR_` zK&#-L>Yh(Dy`LJ>dzDxRC9E_@9}U$Ba34kM)=mf)!U;*y*VMlU%>>Thm8^=l?@;p@ z&=zp(3zx!i`wdoQL^L@Ir4-A3W}kkQGDJesD|T?#VO~OV(RzsJgGat{fevRoy60C zFs&!QCeJNMs4`4vE zS7BMDnpJ>vl!u&Ads^kbo$IX_vI?8kS{`M~6(ZyUo})!K%TQlgV9GMoW2j_ED!R$l zoD>(0J5_)uq7r{2?LhG2*=(<;`wb`g8Ebze(L3JgoeE##0nd9!|K4r$=*oW z;^&}0YS`=Dx3z>rTf~w!;N~XkOMQw(;v%Zx2e5>cb_H2dovmssE$7ftLdDuF1F>6IB!Yf#aZ5}2m zhVTY%1c_&C>EM|4uP%Zl((CQ|45y`XKAZ$}Q)PBiePi7im;maG(d5R`Y_sY6h@}>< z8{UdFAl4O2NKjk2B;YXFy;|ajfi7*oSx&iivP~?QKCxz??1>eGMbux}MV{G?_js=U z<{qM>^l3{;Ehjoer?rKZB<{s3Im0k^+uMf3t2s_bYqnpSg)k&fWwx1-(UtP@sEF;?am)=O%VqpG}QCP$R9d88cKm z)z(++6zeS8&N+*Fh~Qvk@>7#}KaALip$xDgyRLt3juAdUl{tC&{)Fz&c}H~|3bg`! zaWaex$&xakA|8E1lXr#s|@DFrA61m@L97^3Dob)Bk)_%Z9Y?0TL@8gw8u=_l)2 zxIsTxdLfTehFwdR5t2xiAbR^dVw?Kh?G4b|)TEp*Rl^_^)=FLG+n$7$+;7LfH^_`X zv8#gIW8jjk5EuIAm;IpKb3^l7y0tEJNJS6cQVHE+JR$lX8Cvfk?~F+i@!v_Sii6Ts zx+j$n+P#K)uHfVz#eX}KbiU~f^){Y4RP0xBk6{+ZAcGRwoRX&IbTXw`#XY2Whz*tp zrm_Gdyi7_#xE2qhq7G_=sNv}Vi=nnle)3c!#*G5P3dHNtLLFL z(Cu%gSxovnh2nMOm+9^2F)%gvWLZ~C_8+=>N8EGQ+y;C8JFmc$h)<>zg!xM1dU9Ux zhUAAk9QlPxAV~*SxoJLrL7f?h@XC0(2euj~-Z3(@+5}9*@={Y-%L9gV5mXSk+A6jE zYgeD5MDjWjT^qxIdBbHHEx=e6|EXQFmTkdH`&mayMfcw+jnSCKFO$%O>VLk6+oj*o zT`*6tkC*BSXsM>Qt+kG^+GS4$d+QG+V1efPY-^%2G;|Sy22P)8kA^}Rbw%Hci8P5~ zOrz3MSC2jM?v5{%D^msr;ZoBxPT6-EO+nK$Ws2sLfXY-7x%J_}{Z*jbUVADL3EXwU4CN9=| zW9GX1b~2R)^@#Q@@8|Vl^wt6&Sl3k0=Gg<6K=pI*uHkaqzzH9Ij%|r9jNR>Tg~!y@ zgEKMWp)NB=pyM$5+FLt46%wEaE7v97kh2(bAqc#C?hj7Et#=5~GK#(~;qxWk8KfMNNz1RAOyK%jl>RRBk8> zok;B)LFvB^(7E-Zl346<8q&jnBjqC<78SypF5A!YbM{)ovR*<$LK3hOg8AmooO)2u-s}qhoH<3=~kLiv>*IK*pb8Y&VraG+l}+u zCKS1QVdP1!%ZNMTf^WBJSu>TAH#g7B!^wglBD%p34T$N=C`Yla;%!maofa${PW%Ct zF=$#gY}fQ^2@^Ko56fK3$;KZf=IgLk3;j*!Xa-7?xK|zCk;bTl_1rSB zRvt|N^1{XCH7Ae4OEy!&sIi~1zIIGboL@}LJ&JoV?5FNtKI6&1E1F#6Zg79G6+%S= z8!CELm8vGhyN^-2T77CPD{D=`Qo~Ry|FMbTFV0wzF@FzLzBzlds06ph@1#hqMB4Za zFxYSms*X#YQmDvHDUvf?Gm)Oda;QL~5`KcrNnW~O9zIj_i54bVU?4OTx2?#4YXVbA zGnqUN7#W!VZjf2nl|_s1V+of1`-QQmein)AvtD8#V*f6Tc@(r^EriB=ddd!b(4pgz z%IfIx8f+Ca#_ps0rpmiToGyf~LC0q^xCMlV8k!gt%)+vsIssh6rI>rkpwq1+huZH# ztd451MIIIx+cV~rdgiye;P5Z9FO&v(GX~>1>9pbks>pgB9`lg^t&~3zUnZ1$Ifb*f zGvILu>^YeIgZ@1U(MBsqyc<6{u&~R7N6z%&jodg|JHDKlvdzt|d;*R~{OkR^(F!$9Xw`K{)d;<@NEUd)??2toMU25DI!Aia1ze+=` zJ1S@qU`CcCy+r>(tUaXXIpdqBePJwm|Doz-0i;vte>Ppx>`CP8ab$_X3hX8Myi5v( z{4WSk4rkrhB>xX9%slex=X=$(3Esv~DwNfop|4BpnBJ?D-q(b!>8Y=*GO(HWO~3lx zhy51Q#_Dm%&zNJCwbzynJK0E^oZuQx4+?_Pvl-(UOv zpI(@v6Q`_wtM=Hjjohnn|72FooHHDsQOr4J%M-}yFM{3KQ>aRK`A zuKYUxs-A35(J!to4cPXpN&0782YTN%91ZWuECN{UG0Msnj24vWDHUfDg4NLajWE$i z9tlYq!Ol=(e7TgQdtb<-UWU9_q1cCXK+&}V@I!G!oZ4#8Rqd@9DlJ;vf3ZI7v1Zjt z`R8!+$FxYp3z78_F%k@>ZSYHMOK{U%jz8Gs1bC!~5r%JyY!$D6cbmE>t~4-gj}3^M z!k+3rp{n#?E3-+*JIq+R(Aqr92*07dtn(E3!~|;obHy*LgS#~Ck-d=n^2yU%Q5U<- zK@I6!d7^6Ho?j?VLcnJeVl@9KEU$fJ<7Wk0|CB;iDp0|>sh zb}ad^>-T@qJ#&xmnsdcN#y|TcXnxt4Z5VJrL6FiENp_23SsO^2Kh$H{I2jt89q$^Z zBB{KwpgM6k|50Mi$fVKs<7Q5h4ALTvrvWP7dHAi%k`-QuY^JB9mmJH?nw5XA z-{oN*1ZQ3f#!Z1*>>Udjy$FSxmeE+5fRxM})&o_hgdGiml0!aOWu*tSy65nZz&XRI z1F1?91`6>S(wqls_!bYJ6z}E*Lpu;vO4_muEhe;f1Zm1o?@KN zaZ9Hi3Sgv%z!7#2bq26<1NMPF-6BI3?5hUODIl6)({U9OPFv1^1W=KyOtIJ;Te3m7UnNn8J0{bw&p) z0e8kb^zIAN=dTpkOpBOZJ`m&NlRoCjpWfku7vYtXcC|3RI_Ms?65)VamEL>MIHLchqFQ8$ZSp{mTVL7R9w z?XPA94PWa`U+U*H6c~Zr3m{C)5T5aTV=JAnEepZ9kkL97$W2r5(BCK!cBm*2I!Wfj zTEG^+P!D!2AG4wc(?7L85w7+Ngn#gOTD<7&=ACiVg4X1%ER}qka_lzT8>g%S_U0*l zBr9Tzxdj3T^TIW&@6$L%FJfk!`0+>fY<*KdB-(17`M?zp8K{UAio1S!UO@V!A`ma? zpm;n@^+X5fQiugVVgM-|e`3?!AR#mS(tXa@(gz9J5x&M-)A9R_TD-g3=YKSrv7(uU zj_I#TTKB}L{8nzuXB-e9Vw#(WkJ1y*1II(1eVj3y@~=#U@Lx~mZ}KZW$;r4rw)Q7T zq_i=9P$99(dWjZU464$u(9&dh!0%FCvOM6yyJJl{n#yL_<)N)PvyeO%WXJd__MfUfRex{m%h`t=#~)8WgW zmTcT*#-C{iez5~It{;|1ABuJz5>jpc5N_9M@b@#@H~~RGF*0Equ(X3!*r0ji?S5B( zMjp#SPoRfxkUE1++QksY9AbSEmUhsgTh9mt`SEn`w2|4T&Xpf|R5|r0q0r4Yh65w^ z;*bCRE7^C^fdH()uoqfL4m!Q&eUo-gIMFie;(8@?aLrqe8@*iQsKiQ)F68~^9H;@5 zy}i@s^SDvF#u!?|JAp_Oab*MolV>I!S$FjBOe>Z7I)v%1LtSNiCUvdD+3OAit{Ju$ zls_p~%y~PHRQ|MIfLW+MKykM-x>%jFHH(ll_D2ia@_s|nrCzrNF$TLX1O33ZR-uD4 zzQ=c0(ptJ5mzrcXl+-&P5VH;fQR$o975)xi{;a!Vn@dwj{W9RC>8gMK0v{m?zSJ|q z>@$n@V0MLQw46v5&vso(f_{96^bI`nFB~j~=ne7$Rp9M@A`+%<_rm(Dh;|gaSNZ5h zrFTD|91c}^_nl?dv47;`4?m??;WO}APWo=qRJ$_aMV74e7_>Qk+&w#ef2>~@k;Ewv zyumA+A@0%0XEZLwEU%gBc&}|AN0;EK!GT-r6B?4vBXr^E(l-Px!7^Wf>-bZiq~x0w z7Qz+&!M{f$Ar0&mQa+VfJ< zs~wFjL_aHNuq(QMnp!0XFESQ+=|UDhWI)9+W*c|tsxq#*p0v|s;$nIVZvzV^8ANVD zEBo~yce2oM$)pLtWtBT+FbCcW3kS7I7jx1|H4Vb(EyScoTHoUM_+nObPQ8hlCfspS zxEud;O3z9grPHZ?zdGJ&5*YV9%8S_qN75D1&*?-394Y}-WwO#kdA2ZlKk9H2nO58zBU5&ykv z08*}kr~*23TJzNSd1|uQbcd8V1H|>Y`+;bv15<*ww*>lHXfl!UfKjgL$8(g#U=MRg0i+{!U7 z`3gFaH3sY;m0g|R97)wmwehtF7E8M;&?cKZOS7_95_M(8&3ig;C43wyP#T|sSY{Wz z8yd;n#MQJ6b%dIdnzG37`?A5*ZOdsm89)KlNEBlN?$dF{bUesatkWcH#!)quRrZw- z8azl;4ZAlb#~x_LFFGTg)Njx#Gp1E>&Dj3F^$>aIO&PtF6O&ycw@6=1twCMNP2gvM zQlHTM#XL<-0qZAq1g-lubAnEG z@9-w|#^OYon|?jYWT{4PQ-((O5F^(OY#v{;Cqk6@JWqqzRi^5Qr#@2M98!T+yhmmW z7cRmOSUr*ipM>8w13&6)y|kw)K5$Vvv0EIcn()$JpETuqsb zJ2W?J)6{v)tRvFPLaTYFKqW+{6c;f|GaPdBGgy@eelIsU2J+$>pHTggQyCNVwll3`AH|q!^XPLRh221=o@}p zyyL(T{!7Wc(Qr~@@{A52ogPkyDhM+<7eZ;o<%#QC%ZfiQ!E8r z;A`RtY%z$eBglP*3*D-wsS6vf2s5bA!|3(`1TFRqs(nk)uOS-DetUv1xEd~44kmB^ z&4|%Yp`{2)te#>p2hul`y6Dvx5Bd1hr0nw0ce0j^k5u$F3ubveh42xxI?^ys?ktMM z@m%sd*Y#pLm%|w72%0jXOp8V;$4wZVXcN_d2c!^GNg)>wD9C(YQ~bF6L&kkg+9;7J zU4%X%$nSI{LM|IS=hcz4C%$Si5MCP&UUgaMMEdcPy$)7bejs2>DWw-r=j<1{#j{4$ z2{}bHn;2Q)Qlfl&teelEigP>Xu1KV`5fIMTi1QTw75@*8DHbWC%qbeG*?%P1tM1l7 zS)WmE3D>E#sEIMs4$Qqm5E9!FJf=(l`fTPzuz$gv_-r!{T|A81Ea1{x8s(U6kp@sRH*BjG=d& z{x&jHbPISSp2Tt#DKBW3eJog}MXOH_S7kevjXSr_Su_9VYJ@O2Q9NphJrul3{=jl@ z>jCobzdjk}VH8H|%y-_Y`i2U{PHu=79r@Kys|*Lfv__XZbUYRR`fmErp=tBHXqRZ? zmVL!LCmJe!J1za6$L}nBnosiC$|pG z#v_gLN$xAdjY5Y0M-i1NnImXyh^9g5v0&UhQfaag-Bmt5Eeq%EhG;aAv47=m8t=yl zX87(Oi+V6yYU+sSh7#ynSl<3aSSMXOf#$|i9|=~5@D@f{>2`cz99`NWFfQD=IdYuv zP15uN7(D6sLv!OkXJ@mq(m8)dB^?HYt<=5k>voa6xHwU3F+Cwf`)3)|eQPPUp%2BGU zOvw|Qt|>%W+JvOMgs}L6P2I&K(kbc}`Vt!=y5=27oR$^8&?51Gbr*%u8VYk^;=&?p z832RQEQ-hO7w_(cAx*OU<}U#)P|bACaQr zhW(;%8^vQDFck@p2mm^kbi!9@vw@F{&j$>PgqBMZphY!e z`*{fwz_N#Q8OaaId9|yx5r5c@qpis2|GjFIA5Gs%man$13`0O0tw-8~KXhT*FIaWs z^AJ^#26w@qd*Q?TnkK{q$KvUiE6f<Gbw?Zuan;mzN)8G9`>g6CW%pM)7Ooo z%0f-ckDksOJ|R#!j0KzqoTet|ijc1D<6z()+?^*wJ3`L|o<&JVW$nKic3!Mm`e9il zoz@NTe^l7b^Au*SR#R`W0Q%@qyJv8)v)r)q)!x>(Q{}tJsflk~1lULVFl&n!Bq_F%-$Yk_#lUjq2@1_|Hl>9m1HsgK)mRvb9Y zmUA7xnUADdl+*x+g^6KoKBzCO^E(p&ETR-mgA{<#kMg(bENRLA#BvXWviyIHeF zS+nm6G|*sx2I7bsH9*vi6E#58sEs5nA|eDt+!4@m9A{iuL`8{&#SIV;TxJ|a1owqi zkx^ue7$rc^sHms`;)o+EkO-(CylR~9-tXS;z2EO0L+tK!pZ=dZRdwoA)#*-j7#%g; zvP9$?hhG?OyD!^tAC=)keG0IJIO~N4^TnD1<^E;Z^-YH~ov$B>i~fjQc=S`)q#d)` z_$jd#{l+olGS&ogPH(+Hc;L3L!r@wY72uuQ4)`U^kA9f&Sa7x=@s{7pH^H&`{tcss z@0;SziV@6CwESzhdTaI4*L!7whnsh-PAZwv78mwdHh>?uV~?D#xw*M;PuGLYQ69tp zNSWr=lIoP=c8T5VMs}WTkUaQ$-uh8HlNH^3&>?c-!svm$@MO#c+>aql+ih%WOzg8g zFvi$|a$0@Qh?|taDhXD+^$_!S!Na3XGZGU1T6KHN(+roEBBw*!O2Y1M`#4Vf`PZ%q z1(kkDC5z&I{v!T(bTYib*x>f>vubM>+45sKc1i71E(LCXGbd9oAT)5%91E9gqYiSK z_ii#dzqix)9pT}2!B&zEk8@G&0_%NmH@7Es!%NHA8?K$|FlNsecF)_@&Au;zt z(jd}IKKQi2{AOaAz3Qg~5BE#m#FwPZzP*j=py(MNUyR)0GtKR&`o~YxM@{QD3FQS& zk6L%L(g}alkk*yBlYUG|e`~*W*u_rA8(UI}{2Nn-<$n3$RL+{e?IRni zpOBqfRAD_PFV=nf^v?3=bNkcEX$RYG#G5%{A4mLh^t&l3HydA0s~$w1g3~=+k5|61 zE|I%GI?LT<_~mKXWc!=bVw5W#p9mVg0(0iS_4*@r+vfBU!=IFO_x#XlUGCni)Kk97 z&G>uHp52vOfB0jB-#~HnSkqnmV>^G}J1z6b4M*p^++43V@0=;yun*$~pCP(F4e23$ zgb=YJ;8E}W5X0WaVb#dLLOzJ{l`)?PWNytugiI;veF`T*Vfl+mos!fY;Q7OMJ(=(N z?fAEE5&hf$75{$lKeh=GHbT;?hK~s2H71wV`I}%_aZ-esIwhk^gu+U>Vbx5%cx36* zxNTT?u#2EdN~HT(6A4&|k)Z1?Rbjl6EUH4N0>vxdG}QA&Szmh(yN`JLc4P;Nkg5k9 z2T|W3!jTD)g^<5eqOG7V0{Aq5pDM_av-FirZ9PjL|91S_w+I{hpQgw9_oM%Nn^?wQ z0@$N|c3_x`=q@>ChN<=dZYO4)G9Y!; ztTZ4w5bqxDf>@zR4_OPC564S-GCg1GzgTZ+WWWE%x;6uk2O0lZ_ zq%IND?niM+a?>a48ie}DVED5wZ2S4vXfLMm7K9FC=>r*W6R}=+hLR+b(Bi`ZA4f@& ze{a=EiB5Py6L$!I1EPs3AS!6AlG>n(8~m|cG2G=JtV0L?*O%~r?IRS6v#MD6a9Boa z5dx7k0@b1{J2jtl{;ovn-UcKub)jPrw;GDeyg`NJ)0N zle*pJK3|OKG*df?>zmK}-4^*oT9kz2#eEViBd^LVF} z%o#*7pni9>6orc^{J{Mbk_y=Tx1x{P%IFj%>cjol#y@DaGBQH^&-Q=+G(`AyFTy+y z0pW)}<6yS;V&WMw=_o@8C;XLUL3_FIF1Q(PpKG@RT_}F%P9I|nz@k}*arb= zhEy|-=A(3_K%0tWJ}kWJ(Vlj_lj~Jq^ZWk7ST4J9L=7-}M+Fg4%Maa+^f8c2lDx!;4vbrkgXm)g90mwkAXcUn;r{jEbjkl~`#(17;RvMzbxMjlGBIE0!>crd zG3GxDC@;(*F}kN=id!m343>p(5uFKYf&kGuz>^wc5jfi<`^AzNw!4-3gs#twhP${C z4G8h(GT;^wwRi>96gJ>A%@62)-nepI2~GJu4E*Xr#DdzH*S{MKw2+| zr}MxHl+oeFEGdp;7|+#|l!3tiM*%yN8tQ@4UW`!pIenl?)3AqAnNW!gVS46FT?N@y zh4k;DG;@xgDdxYYt2!U!C4(Bo2ssK_fY~GO5N3WGqF3{?OBEvcy* zb5b+4L85N(eyk4cJs#TXiWkaxIpmrN*MNtp9;2m_DsNKwtx740yaj|ydG+x$O)AeG zF?97@e+B$XxAFJ~OekVh?IDpA?-{XvYeD1aW~skIa@n~ZM|gvh;`?vl5hm#R#@zKh zRo%C1IThdTGQ?t_w!wb+AH|j0W1*o@+Ldnhv;FSO5dPw&Rzh;*w$IP1%StpUJKByt z-8aJh8DCe+qRtj`BXFwAY1CDG+Fb6e$;T#YKNcuiQhjUP9l*mzW;|aX3P4dZp^e3D zJ^3sldVVw{pt$3Q^Qg<<*JP)5V17sC5ZhEyk}yzbzRE!`YVe}xn;|MS-MC2>@y3R*iqKkQL3vi zyLoS0v=t*CVLTxURg$gJp?Ybg)CIFQ;a~c2R#NnCjhMqS!o$4i&GXs*O44Q?r6IaZ z5HcpSDw(Shx-%B|pEEFDN@`EEn^T(8iwSmY1Q0)&+x#!2Aa#V0hNXG)_Q2bwGyC&D zbRPGOZ{3?3@oZFU@u;_P9YwkiJo$=X^@rB$iWMsh-$%MR<<^e$yF<7;Lb4;JQJu1q ztlQl~&P~kya;dnlqp-;ZqkYE!7Sze86S6CYZf3xu&0}QWwRUvhGmw8CM&q1hu)qZA z`*D3GLsvyNZFZUhPAKB7T^`@x-WO zdUPHD?xb6550D}kj;jLKDS2sCm{38N8PTg_SO5MXQwpPzDwVod+R&|N z^U0zLR;3t8X3tr#WbVof+Y@5saccG;dRb(Zon)kR zP$#=S50)uoZZ;ZjX@BKHVs%$cX$;CXwXD4(H&|14Nq#zAbsk`a zQ{9wVF3;MO(w;y+c>EpA799b7Jrcs0O2aL{h^uF>Hs^Gv;5-kL`RlO@#+>kE zGOL1FAfxkSm@NpalrO^(AtrL%==hpFzqFO@n^MMkRrvem+?rn#=WFT(ZE^F@41eq^ z8gViVBi0*@3nF}cQ}IPhlyqH+eK$p{z|tSy&fah}cI(scXT_vz&j0#qv~nE#9BJC- zqcQXv`1$_G8T&_FZcUukF5e6!g)5kqI8SAa$D7eLb*!)hESZ8O9fsl;uzC8dLl2fc zJQP`1u7Zi-6@JKOmD>$X$h&3R?Xym9u|w|}>7 zV*Qx5KzRL{5m&xc``2ZD>(hbseH-FTPQ`Z&P^0NCS#DorEh(#=-ur%MTizDkoU59^ zfhKe3balsBqvpaUW#N8pJ#Je+h<=(^Kv9D%pc+5~yE1h!ovsq(@8;-Lkh(gSYZV6L zBPczJ=M9;wlR3VK(JaMydTbXkKNHydIA!N2XS?db84mX@l%3~hIb=1m;l#(3f96;C+(^Quao!LaUZ}R@sPPbPw3zZ8#%T_tOXge zEY|Y~ipRK)=DZ3aA@$*R?dIy>h|12$#UP>a*XM<@X+a?YR*{Fob(f12)1C!f_2ss? zOrGAj?7Q@kzj$uM0ybf`_O!p6S>Br$r2@>l{+T*w@M84;sf%$eqO*>4DcK<=DeJFX z{A{CFp1RUMiGrL3@C}h)HMvF%%tY#9ISqG6nbh#_w{(_1JpxRCdV$m&V|mg$U2$}e z<8X%^nv7iEAvsghdo@Bih$P)=iA>FEsA51>UhGbpK@&9?LtncMROnNj|Gj z#%MZ9*BO1j@vif6goe3YI_E-b9F1oCLVu;dQUG`<;+um`Cr>H4{*|OwNyOeIE$`{y znJoa@OIHD0Wu4{8)G1iuax!)SSEOWSOYz*r#8Pr;=w6P?0<%BGO~Zhbm;Y2df2hGw)Wq_$3wV{Vx>a@S~2zKa=awT#(PDeyhOt-4cK z!v-UsukmKZ?G?0|;Ndl7fRJ4<7aeqiL7o-ycy05cK*MDV4kmI4FKgAn60eT4-%aJn z#AH_4&BQ(BWM2Y|k$)|+#G9$J{np;bB^d+BiYJ zk@1-czl%3t{5XZB?@3KJeG?e2Q~$_LBsEeByRROms{z*qr>llQCK#=9)>5zZGohDH ziAi0jhrSY8N}WdYCcE}i6K{PPe!M%&aI^dqH$SH)^0KpHjFN1|Q79$)0+`bOQ}i%i zg>C1v-*^5cNHZr3jLqJzS2>f7Q+xc)%QcrH)W7S_n%KYnoOk2b#@ACe>}kr*efD?u zpTRs^Z;plBIzN$7IFH$7NQ-Hm@^t@2nBj>44-i>2_0KS;csXy##AJaPs{)G2nQ&7J zv7mDQciZz)mQ3vrug5odkA9xSrYr`q6+F1Q+w{T;#(fxYuNGk`jV0Xl*m*H4ceV$C zrw)i91SZ5#Ea)D3sEiw~gbp3`ApY{kaO+Sb#=@VJn;h3NPI}&cX|eUd$Vck6M<1-c zY}uC*bM}`!=^KwoHp4G9S}i8imrqvrJG#y?yBa(fo$@eFSwMf~^mZl8WX&n?x&!(( zeWpl?8ir`3U&o7pgWwUT`*x~ZG*_ie)^<)I0;A9_xhnYB+rhSnL4D`+IQc6gU+4#a@lg@5Nu zCG)u+7I5b6u6QuC_$nX`{)6Wyi%x{HhT!YbD93%wmi9mvdVJkKhnxr9vyGlxXH%33g!5s=-UQvA$tCD### zf~u+E!OS?_LXQkJLOP1gInp58hpP-ko{uN4#rSm%uLypq5BPSXRyyG-%g^v(s$ zO&`CyH#S%N>B;Do&<9bYc=qWzDbu&qzx^tr6BtWG=T+T7wqNZ(4KW1O0J?zc5+&&X zf_H%Hun!5&PFWdvQhQfJ%NUlKs&q$B{PCL%=!;Ya%fv%`132aE zz%kSI=>eNU!H^z|Nz_l;3e=fO+6WneXUx0=*HuE~)APL9nxxDD#DYIZm=VBCOM%jC zn)J&WKXqIL@6hDg3VJ?YW=>|oc~Us*zl+M;_kMWvU)LLB{KBsLiq0H%ouaL3s@prS zNb9pj{&%o!VC&hm4VSMrZfwh3JWP`rQ6-w7>-*UuY{aJ}9bw*EzO+?*5ct@CT{65q zX$T>J)ZHcCF%8B_zkw%^n3_6KpDO4D(q77Va&^M~?t}N`Xw7B+BRjZ5;6de3;*pO~ zXB=TS_uQiGjlVXR+K8Pl&uI7IAzyP+Dx>Gin7}$biu!b(oLQj!QM+SNcbWV=+4_ZF zJl{6)?tW&Gk(t+|+-0_L_~xVwh9N&Tw0h~Ac3HWbZ3#T{Fk)pfygjc(`+Qpbivd;2 ztwxpdX!NXtt&QzZa8SU63>0(C?6NDFrC3zw-FHwzA^AV z`F6>-e2wn!QV6Ps@v==AdM30*~&SO6#gX`DL;V+w*(wsBfG6qlk4%^MNCiUJEHTI8-QhhEFHBZV+mzAkzLk zwAyf&lbGZoLQ@k2=kO{hU!Mw2Gsb1!bTnUernBtRcvAnl`yk>e%lmoANMJuy%eT7V zJ50&#Qf}yd6rDC#;4*V#hd`d$)3|A->Uh6ge0HL+5+YFrcsKZVVAECLYv%E2#=6YnvXXUVIIWM~qfNG_ z>uNEbG5-O^&$`Xmmc|O?)>bnKX)L4Qfc{vWk@K4Lv^c(t*irmZHT72eX|QzG4cW8;O$tw_ zGu@WxQ9)4j29BXoW*UsR+Biy%{pKV8zXuXoRg6^XSA97PzI|O7S#l_0qp?Kc57QM=;SZAwINkWE=A+O)LjFZeL*d+t6Y!$>kwTMI2H{|2`CN3`PX6h7*g6hAB?m_gmM-?>7 z{h*KNh|)go;4&lJ($j|3Ga~TxGS9Xb;lDav{M4NL^Td=tre18{l&hFr*taop(uA@b zYeq~h?W>*kFrQoga6^0aXW4J-&i4J)sCKw>cG7>tcLlO4n7TL?9HNPt>9UtmZ(AJ4i={DM4akBzWqx9kkW%Pb|F9%gvmWD3L`u`# zM?$;nFu8&Sm+Wz2kB)lt7mJn*qDqhNezZ?z$&ZJOanj{pRTQf{u|NIfbn6GM7yE2d z@OOnzF6>EMvqvQ6kJ+NA?{2Ok;5UFm zo5u{l`}*k{0|2c;!k}|J+xDh*_VbCCp>8t|pE;8bP!_Qui z<5G!+oPpq~w&+PMtK2)%0=T|xntH*F7LvF<&D$eD>3^NvAU_96IW^ST~<4Z&_1L4^x-#($T}eaDINaYC9HJ z0o@G17{rl z5jad^?f0W)Shv6EXw&xaR4xpGyc!-+g%d)gH;*u86DZi?--raaf~f&;52@ROXs%4H0cllfwEc4Ghr-JZdMuifXQyEHs>xn4 znNx!*^a%gknCl(B@dv`e$R;RX{f^Jng1q=ZHO%`;Zegk*3*agLBTy3rWp@t1@&xKMDBGexQ??(G*)loLD5Y&i_&WymZ777bDt&*OG>3MEW z+5hY8j_cB%)8&?VWz6oz{WjU7uav=Cg`AI~A?E@GUnd5>Kvi@kGAC8;ym+svNwmCL zT|TXXi0~p+V8{6I2q7j#oQ7B~E174B5u@LyWtmuQfN%uep47OqXo<*H#DZS3Q;_xw zdN@qhTIlJu*Yi)*s>>SbHe+5}1m0!}7ZD%E& z8p_`+h)5#iP~4Nvx!-@!C_H+>byJf5YxHae@l@dRAVUhk{PQ`~SR^8AbWIdgCpM76s5K${lA|EK3ebJ3q z?AwBNrpZ#tN{oug>Rh=l-aMU|$tTgsRll6Q*q)vAvtY96J=Zno80Li>c442)u)z%; zk?t@r5UDDt*81XnDj=-n#(_C6=IY#er}mDkGZ<^!Tuf97T1?sCeb>Y>TPqo=ME=1_ zR=$Xg6>&aIBxx0t#o$ygcz{shZq7mAJ*pm<;X~R3UAy7kx-a~m!^d;;8@@0RAUd!^rc=O`3`htV>c1iR0rd3(U0y_= z>zJOy(oOj~??ZmQO``GEBFxgaAc)Mr!&K>qw1`$>mZtNj%95QPcaQb1X9TSM&QEUr zrES~W?5m38L8Q(rZ}*&HzPY%L)egB&Vy?&q+`imS1tTZU@YHYTL!=b(Au2kVZV%E{=@dAT z!03c2BwR}Y2mXN#ZdXiKK@6iuF10S{o3b#l_jw3r>4%NOT!!-qxnwwFe9OrI%aOw_ zY(5zz$Q+ox_lk8u+gQo8`#&v;7zo}an;bca%uCysuQiV;tk&P9ksc*O#JFs~HLV7) zk_}~VG%nxJQx=(nDNnr-H3zw+_Z9L!~#K<66f6^!;*QO zh&{4~9zI{Qs#KMD ze`WOdl>lLC_%vg#PRtZa@l(IPK_)}m*?{uLYAXoB;~Uuo6*%vF1pZ|KA3)f_RZ^Dk zGfuM!QzoLX7PEaJV2Rr4P9+N z;nY5-;Lh(qT>o)fpf0Aq^*4T)2S2NZpozz<^NnuiKKw>_gj0R4-3N&b{EVSnx6GqU zqft&GN%IgC>d|wg%+`&v@nCD4&}k5< zrW78lbuZcAW6gJp?l~%rp1AkY0}*y8l096~BQpq*E^Bb36EcxXS*ELJ>{)g(W=F9Z zZ&kF;b1q~3IrZXR=P6b*)C+DZ-yexdoe&=+nS3f{pu>tdRYU5;=+FsggB9~Kem)*2 z1^AeS5!orTmf{#V1XQ41cJtHqth2XQ5S6?%C1dq|zQ~1aFhNE79HIit(X);?fHG3a zWi)aTPxc}Iu{H_PXGkk(H7>BB;}6Usq=IMH;R}{CpXCoBmHTm?SCAU6T|B-i!WQIE;Lb@xT)x^86w%Oj=uCwVU(Nv8g`d!2=mH8@wxYlm_eu(>PZghH%SDD$Vaa5n58G~ypGa)*e%nSy;6}b`+12|S z*D=|ud+8w^rJwRrV2QB9g|>w$jZ?nx?xdEi;+VJXU;Q?inYEYY5kwxs{lFa6roMgm zcw~;=6l3L~fH6OD%f8e*fKCeA`tX<2Q5)jy6=w!f6LVD5tL5c~0$Dt#vQl5Jg$M-B zsqwz|^QiUB^Y*L(TXqP)!yUeq+F+c5K)S-Z%av(+su8U(PLJ z6>V!AQSOc{Uw_(dZ@_ngEly=OS5cGBe0R1-(6%{)$kXEX+4OI$1L`a z6R|Ka#{KFC731Igt>XGgg+?wq(<$gPbW1(ocr&g|qZjP|U>7&Be@pMJBGrk{jm}+i zXP$DPv+1&PZ=gW8`Rm(G%({in@!eNI8&h(n)~a4|<4;yvQN{O5USI{o*4WNxl(1xW zUQVsYm$Ach=Q5%eeHZ?**gIjQ=h2{D6DnDjj@8%8R~!loiF{DR?=ybrT=w~Q1RI8yPZmcX|0z$o}FNfhjB`7Rp&VpN`dMgI15?WhDe#E_XF= zHE{&=3WQ^V_+TtM{x)sch^f=%Ckr~B3l!o)`Q=X8@tF1lx(_BhRNgZh;tX!*ln$a) zY0HS=$pf2>N{esoXe)&^(%YUHpE|jrbAjHCtiA`S7t&se4sCjU*3WzTQg~{Nz270f z$d6AKJQ~go`})3DB0kI9*vRNR^9Kj;m)zoN_Xr*+*sRA(${bZTvQeQxa46)ddn(EkT`mdFvmDSnM}drL&_Mx%O# z7#dLLN)9fCc9LDVx!)(^dA|fx07Z~l z^_#`6f|f&br$eR`IJsR9@Vlz0KnWxQ>Qnq-t*gNGE6k_1=H`ilZQA5Jf2xI?M$o2H zfOkMsiIPyIKI8n)={}u}<~!smp|Y_O-Li@2Ot&b?!rE&42fj zwT=YYg-j%Sx%r&-qc2_Dy295LQjy`CkXkY35+ZJ_FZLdQ@3j*pE^uu=*-)iK74^h-0&vujVAHMOoPB{PK%h$ zJ^QzsUUjVgNnH|%aJqKiv@BV4!13t5oWdvUJv;N*vXMdbgMQdeUGYoFh?i@7G6UKg zLuN3edSCi6EJYtj1iV@jFV{}EzVYV3Rpg2|Qk-m2t?BsG6m*BUP=kW?F;yL3ClkPQ z9{NTFq?Z9uEZ>{xc^!Wu>ep6`tu^5nRRQhi=#(ZlK>VrZtYpkocbz*OGSt2*cabpT z-_r5bb`aIgZufCkC-2adWycu=<=wu;h}d!A@$RhnCA)IN1A$SsdSt{ti_^^L_Pjk$ z?BbqGR+a30oU%pCEKy$%l3ZmQB_8E+x#WlFz>T@G)%d6~zO znt;2Pu6d*of04iY{c>In(lcV}6l|Tsnl?1}T2aac(%U%}X7~w-)#S3tSWi=Ln} zKKU6p{qwJWBfb;KgFe=mG^;vpUdadM2O@KNKFUmQs;+!@d?zC8h8%)gZ*T}=h{gd& zLLr#CN!%_IUaH`xS;Tk{3ec!_24f>A@^!L$?+*=*vwD4&9!e=AN zUgxiE;+*u3IXNkXj|~rX=N;tV&r9g7yX*UGdQIVan#ce(h4mz?KYG9K_#pbwBO0rn ziz-dWPk6R*camxf@LZ|tL*$K_Hi?Ow)9?Mf=a(#z`>K%QXJ_5E)>?pL?nN*_ghbqk zLG-zuzO#4S%=2dEq@E$=assvi!GLj>5JSX*?gG0h$j7-X_j7GDTm$ArHA|ypLIaAF zsF_t#U_$7}S-y+WnB7uefkcDNx0;quP$?tY=j4Bw{ptFGFGpUVxRp8klXD`y|wfBjg`@nexo4Lo)opHX-F$?ae2L)~;W$lpZpu_0g!!`_C5t;>vg7g|Zb z-Xxjh_xNE{@nQEZzpeG~jT(PHAhId)weK9?Si@%2-@5*$I03?NP%svpStrol z)8jzWos_Ym`}w#CO|rIq&eh%xPKvIOk)&*S9evEk@@q0p}Al*Gy{P#R3Rk0 zzyks3?~uOb&)0vtJ68xYLzOI32J}(k?%YIE=7Sn++S7MaqUB?@^-cw|?UT-luPeXS ze)0PwQE&HnZA>XX_TkN4UW<6+Iri;c{xi_zxOuDuKX()=43iFjbob1SzIPWr$EQDW zBK9-aE_@jIz-p)FnCSF~KYwaDJUu$#DM?djA_)3^4zF`MCZLNmK`U zLpKhbS|vY4gpw^ZhQ^d!Q_pKo03js^jGJ?Zl7u3R%PX#0KBN17=Qr?3A6N=9(M-$Y z^tk?QxX$(Cm1y-X`^Gl(HJNbr z|5)5~Q7T)4`C_~^J6?X`uis^tSpd_zGm*SskF+L_MJ-VLER$SoICP#9T$a|LUp z>>@FlEoIof8u)UvJvjd#@M}_sI!XRr;oVZ*TLH`9qxIRdUs_ToO}_YceD;2Bp@JJX z&o0gcd=FxQORCw;4S(5KY+z3)c{%FW`GY9#ZAW&zVSuZvL5A#5_X0Pb#pBl1=|A(j zbw@||SOxnX4`7{;@iVS_w8zqajl@>Ddt|QNdd%Aghq;s`D(`<&?Qtk26k9BaN%T3cNx>&x z)O&*Ndz$W*-+GlQh*zxFgvnAqeOCRptYncN=J%q-y2Ub?0N*;K1Ct=wPX99Qx5@G7P*8AEq)`&tyCVR>06}hfrt$nTc zx}X)idP@!+U;9(qirNy{(I=6;P0I`zqF29(rk{}Xyjb6uCNenDU$0LexpwPzi@wq= z^4e+2af7IhJF7z}X)OJ_IeqA6>G}eZ6b3X#XeD*;h*U87k!oMta%afpFD@xerts^- zDm3bBzIGp5X2L@|+UZ?)At_l`MTYtYY#SZMz}fbu;G?5EKqCGfZp1E?gY0;3%Z57t z)&0&FcjlELoX@IZ#F=KYj4oFBJ4L>HvGS38+$mOq>FCVT;?o|3r>svWXO@=p4je+EG@fKTP=UTGpHd_h+;nkqx zA^70c-)$X!!1+9X;CRVnM?EAmX2hD)Blgp?_mXzdPIt1jt6kmO4+*9Vg@Q$6M21a) zU3zq>h@oomo~90wGrf(wQ0?^ok5Sv{>8<5XaecXIEO%Ch*XgRf$FY^Uzr@*i^m{0C z)&?9@Z7AxK@-*~YvDFU?uCLy|sL`)2NOJq(vPXow(dg9+=1ux?X_u!57_(Q^m%DpQ z`8w{6UZ*W`wf+KC4TvGxl?av)8_~$t1gbF^UJO{Zm~UuxarGhHhcf*nyrF{5i^q#( zkjM_$aXY1Tsbfd^*Y*lAaVk}Chwwb|d}R)#3wz^e9(}bhgiHflYPlM(g&(JXa%z0r z-&NIg>3A1&vOPU>-)7sL=k|AH^kUF{@KHMJk&x?LJ)M_qr_7Vthrh)L~T&^j0ou`7+O zDP{l;si6nc&EMugP6FqdlvxqSTPSB{$(RupOnCods~NiDth;nBBa4o?RP&(Qy6Ob} zDeN#$WDhxFGR#ha|8kgc*qNLEt~6%p+n6uyeW#Fqnnk`(>u7SzY}?@xn?Es{+Iupt z*uK=f3-?z&Yde&2>rr<63vOJEB&_>{ACduX=h^~^?moBSjyPf z>aIsvh8vdsZt+4azb0yRU6f@;@S~$(W3_nEO48bX3HBoM=bB38u#db1l6Yc;0%GB*tG^num5ObCSK zm@|3%ah4}0^kjz!>Gxye0e|xpAvi)HNckXGXT6MxWR{{*$zKh`hRC=SxF6Fq03hHffi}Unwdn_bm?!`4UPeVNGdoF8Rm&7r z5w6vO<_hv;sfzBX6k_Z(E-adeA5kxefT2jA<+q<>Wo``%atcCELWW2WJ!9XLjmK`y zxWDyx2{r=ll||l0PFtDQH=oa`J}%ysD5)YM%B`0eFAUtqymgqn_gyXoMmdu|zS#Ka z_prUsJon6eIqOG#!&`&s4rCGxq8l>$b;SpWwY-NE-jZIkF8g?;AiR!@SinfDAZQT( z#*n`$HC-=IB8^z^{uSwej~+G;-2N<$C&$5u6?%_J!?{{13Di|5\=ks{kfFP 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