From b611be804280621170a4c6ff477a1e262afca13c Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 31 Dec 2023 01:30:46 +0100 Subject: [PATCH 001/201] compile ok, function not ok --- src/appInterface.h | 4 --- src/eth/ahoyeth.cpp | 56 ++++++++++++++++++++++++----------------- src/eth/ahoyeth.h | 5 ++-- src/platformio.ini | 10 -------- src/publisher/pubMqtt.h | 4 +++ src/web/RestApi.h | 4 --- src/web/web.h | 4 --- 7 files changed, 40 insertions(+), 47 deletions(-) diff --git a/src/appInterface.h b/src/appInterface.h index 34dc5ddc..625f72db 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -8,11 +8,7 @@ #include "defines.h" #include "hm/hmSystem.h" -#if defined(ETHERNET) -#include "AsyncWebServer_ESP32_W5500.h" -#else #include "ESPAsyncWebServer.h" -#endif //#include "hms/hmsRadio.h" #if defined(ESP32) diff --git a/src/eth/ahoyeth.cpp b/src/eth/ahoyeth.cpp index 2226fce6..402abfc2 100644 --- a/src/eth/ahoyeth.cpp +++ b/src/eth/ahoyeth.cpp @@ -25,6 +25,7 @@ void ahoyeth::setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNe mUtcTimestamp = utcTimestamp; mOnNetworkCB = onNetworkCB; mOnTimeCB = onTimeCB; + mEthConnected = false; Serial.flush(); WiFi.onEvent([this](WiFiEvent_t event, arduino_event_info_t info) -> void { this->onEthernetEvent(event, info); }); @@ -33,7 +34,8 @@ void ahoyeth::setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNe #if defined(CONFIG_IDF_TARGET_ESP32S3) mEthSpi.begin(DEF_ETH_MISO_PIN, DEF_ETH_MOSI_PIN, DEF_ETH_SCK_PIN, DEF_ETH_CS_PIN, DEF_ETH_IRQ_PIN, DEF_ETH_RST_PIN); #else - ETH.begin(DEF_ETH_MISO_PIN, DEF_ETH_MOSI_PIN, DEF_ETH_SCK_PIN, DEF_ETH_CS_PIN, DEF_ETH_IRQ_PIN, ETH_SPI_CLOCK_MHZ, ETH_SPI_HOST); + //ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLK_MODE); + ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, DEF_ETH_MOSI_PIN, ETH_PHY_TYPE, ETH_CLK_MODE); #endif if(mConfig->sys.ip.ip[0] != 0) { @@ -130,7 +132,7 @@ void ahoyeth::welcome(String ip, String mode) { } void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) { - AWS_LOG(F("[ETH]: Got event...")); + DPRINTLN(DBG_VERBOSE, F("[ETH]: Got event...")); switch (event) { #if ( ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) && ( ARDUINO_ESP32_GIT_VER != 0x46d5afb1 ) ) // For breaking core v2.0.0 @@ -138,7 +140,7 @@ void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) { // compared to the old system_event_id_t, now in tools/sdk/esp32/include/esp_event/include/esp_event_legacy.h // You can preserve the old enum order and just adding new items to do no harm case ARDUINO_EVENT_ETH_START: - AWS_LOG(F("\nETH Started")); + DPRINTLN(DBG_INFO, F("\nETH Started")); //set eth hostname here if(String(mConfig->sys.deviceName) != "") ETH.setHostname(mConfig->sys.deviceName); @@ -147,26 +149,30 @@ void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) { break; case ARDUINO_EVENT_ETH_CONNECTED: - AWS_LOG(F("ETH Connected")); + DPRINTLN(DBG_INFO, F("ETH Connected")); break; case ARDUINO_EVENT_ETH_GOT_IP: - if (!ESP32_W5500_eth_connected) { + if (!mEthConnected) { + DPRINT(DBG_INFO, F("ETH MAC: ")); #if defined (CONFIG_IDF_TARGET_ESP32S3) - AWS_LOG3(F("ETH MAC: "), mEthSpi.macAddress(), F(", IPv4: "), ETH.localIP()); + DBGPRINT(mEthSpi.macAddress()); #else - AWS_LOG3(F("ETH MAC: "), ETH.macAddress(), F(", IPv4: "), ETH.localIP()); + DBGPRINT(ETH.macAddress()); #endif + DBGPRINT(F(", IPv4: ")); + DBGPRINTLN(String(ETH.localIP())); if (ETH.fullDuplex()) { - AWS_LOG0(F("FULL_DUPLEX, ")); + DPRINTLN(DBG_INFO, F("FULL_DUPLEX, ")); } else { - AWS_LOG0(F("HALF_DUPLEX, ")); + DPRINTLN(DBG_INFO, F("HALF_DUPLEX, ")); } - AWS_LOG1(ETH.linkSpeed(), F("Mbps")); + DPRINT(DBG_INFO, String(ETH.linkSpeed())); + DBGPRINTLN(F("Mbps")); - ESP32_W5500_eth_connected = true; + mEthConnected = true; mOnNetworkCB(true); } if (!MDNS.begin(mConfig->sys.deviceName)) { @@ -179,15 +185,15 @@ void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) { break; case ARDUINO_EVENT_ETH_DISCONNECTED: - AWS_LOG("ETH Disconnected"); - ESP32_W5500_eth_connected = false; + DPRINTLN(DBG_INFO, "ETH Disconnected"); + mEthConnected = false; mUdp.close(); mOnNetworkCB(false); break; case ARDUINO_EVENT_ETH_STOP: - AWS_LOG("\nETH Stopped"); - ESP32_W5500_eth_connected = false; + DPRINTLN(DBG_INFO, "\nETH Stopped"); + mEthConnected = false; mUdp.close(); mOnNetworkCB(false); break; @@ -200,7 +206,7 @@ void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) { // compared to the old system_event_id_t, now in tools/sdk/esp32/include/esp_event/include/esp_event_legacy.h // You can preserve the old enum order and just adding new items to do no harm case SYSTEM_EVENT_ETH_START: - AWS_LOG(F("\nETH Started")); + DPRINTLN(DBG_INFO, F("\nETH Started")); //set eth hostname here if(String(mConfig->sys.deviceName) != "") ETH.setHostname(mConfig->sys.deviceName); @@ -209,20 +215,24 @@ void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) { break; case SYSTEM_EVENT_ETH_CONNECTED: - AWS_LOG(F("ETH Connected")); + DPRINTLN(DBG_INFO, F("ETH Connected")); break; case SYSTEM_EVENT_ETH_GOT_IP: if (!ESP32_W5500_eth_connected) { - AWS_LOG3(F("ETH MAC: "), ETH.macAddress(), F(", IPv4: "), ETH.localIP()); + DPRINT(DBG_INFO, F("ETH MAC: ")); + DBGPRINT(ETH.macAddress()); + DBGPRINT(F(", IPv4: ")); + DBGPRINTLN(ETH.localIP()); if (ETH.fullDuplex()) { - AWS_LOG0(F("FULL_DUPLEX, ")); + DPRINTLN(DBG_INFO, F("FULL_DUPLEX, ")); } else { - AWS_LOG0(F("HALF_DUPLEX, ")); + DPRINTLN(DBG_INFO, F("HALF_DUPLEX, ")); } - AWS_LOG1(ETH.linkSpeed(), F("Mbps")); + DPRINT(DBG_INFO, ETH.linkSpeed()); + DBGPRINTLN(F("Mbps")); ESP32_W5500_eth_connected = true; mOnNetworkCB(true); @@ -237,14 +247,14 @@ void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) { break; case SYSTEM_EVENT_ETH_DISCONNECTED: - AWS_LOG("ETH Disconnected"); + DPRINT(DBG_INFO, F("ETH Disconnected")); ESP32_W5500_eth_connected = false; mUdp.close(); mOnNetworkCB(false); break; case SYSTEM_EVENT_ETH_STOP: - AWS_LOG("\nETH Stopped"); + DPRINT(DBG_INFO, F("ETH Stopped")); ESP32_W5500_eth_connected = false; mUdp.close(); mOnNetworkCB(false); diff --git a/src/eth/ahoyeth.h b/src/eth/ahoyeth.h index 157a9c76..2b0f8b62 100644 --- a/src/eth/ahoyeth.h +++ b/src/eth/ahoyeth.h @@ -9,17 +9,17 @@ #include +#include "../utils/dbg.h" #include #include #include #include "ethSpi.h" +#include #include "../utils/dbg.h" #include "../config/config.h" #include "../config/settings.h" -#include "AsyncWebServer_ESP32_W5500.h" - class app; @@ -57,6 +57,7 @@ class ahoyeth { OnNetworkCB mOnNetworkCB; OnTimeCB mOnTimeCB; + bool mEthConnected; }; diff --git a/src/platformio.ini b/src/platformio.ini index 2b4b25cf..e58c6804 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -90,16 +90,6 @@ monitor_filters = [env:esp32-wroom32-ethernet] platform = espressif32 board = esp32dev -lib_deps = - khoih-prog/AsyncWebServer_ESP32_W5500 - khoih-prog/AsyncUDP_ESP32_W5500 - nrf24/RF24 @ ^1.4.8 - paulstoffregen/Time @ ^1.6.1 - https://github.com/bertmelis/espMqttClient#v1.5.0 - bblanchon/ArduinoJson @ ^6.21.3 - https://github.com/JChristensen/Timezone @ ^1.2.4 - olikraus/U8g2 @ ^2.35.7 - zinggjm/GxEPD2 @ ^1.5.2 build_flags = ${env.build_flags} -D ETHERNET -DRELEASE diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index e062439c..b76b1677 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -14,6 +14,10 @@ #include #endif +#if defined(ETHERNET) +#include "../eth/ahoyeth.h" +#endif + #include "../utils/dbg.h" #include "../config/config.h" #include diff --git a/src/web/RestApi.h b/src/web/RestApi.h index a74f4f14..32975e39 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -16,11 +16,7 @@ #include "../hm/hmSystem.h" #include "../utils/helper.h" #include "AsyncJson.h" -#if defined(ETHERNET) -#include "AsyncWebServer_ESP32_W5500.h" -#else #include "ESPAsyncWebServer.h" -#endif #if defined(F) && defined(ESP32) #undef F diff --git a/src/web/web.h b/src/web/web.h index 1e87547b..e559264b 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -16,11 +16,7 @@ #include "../appInterface.h" #include "../hm/hmSystem.h" #include "../utils/helper.h" -#if defined(ETHERNET) -#include "AsyncWebServer_ESP32_W5500.h" -#else /* defined(ETHERNET) */ #include "ESPAsyncWebServer.h" -#endif /* defined(ETHERNET) */ #include "html/h/api_js.h" #include "html/h/colorBright_css.h" #include "html/h/colorDark_css.h" From 9d1147b3716f98856f4129f19bfeecb6bbd14c9a Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Tue, 13 Feb 2024 12:13:53 +0100 Subject: [PATCH 002/201] more gracefull handling of complete retransmits - Heuristics is less strict with complete retransmits - fix MI typo - new logic for MI alarms (not working correctly!) --- src/hm/Communication.h | 86 +++++++++++++++++++++++------------------- src/hm/Heuristic.h | 8 +++- src/hm/hmRadio.h | 4 +- 3 files changed, 56 insertions(+), 42 deletions(-) diff --git a/src/hm/Communication.h b/src/hm/Communication.h index a37bcdb2..8c7fbe6d 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -276,7 +276,7 @@ class Communication : public CommQueue<> { DBGPRINT(F(" frames missing ")); DBGPRINTLN(F("-> complete retransmit")); } - mHeu.evalTxChQuality(q->iv, false, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt); + mHeu.evalTxChQuality(q->iv, false, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt, true); q->iv->radioStatistics.txCnt--; q->iv->radioStatistics.retransmits++; mCompleteRetry = true; @@ -893,50 +893,60 @@ class Communication : public CommQueue<> { uint16_t prntsts = (statusMi == 3) ? 1 : statusMi; bool stsok = true; - if ( prntsts != rec->record[q->iv->getPosByChFld(0, FLD_EVT, rec)] ) { //sth.'s changed? - q->iv->alarmCnt = 1; // minimum... + bool changedStatus = false; //if true, raise alarms and send via mqtt (might affect single channel only) + uint8_t oldState = rec->record[q->iv->getPosByChFld(0, FLD_EVT, rec)]; + if ( prntsts != oldState ) { // sth.'s changed? stsok = false; - //sth is or was wrong? - if ((q->iv->type != INV_TYPE_1CH) - && ((statusMi != 3) - || ((q->iv->lastAlarm[stschan].code) && (q->iv->lastAlarm[stschan].code != 1))) - ) { - q->iv->lastAlarm[stschan+q->iv->type==INV_TYPE_2CH ? 2: 4] = alarm_t(q->iv->lastAlarm[stschan].code, q->iv->lastAlarm[stschan].start,q->ts); - q->iv->lastAlarm[stschan] = alarm_t(prntsts, q->ts,0); - q->iv->alarmCnt = q->iv->type == INV_TYPE_2CH ? 3 : 5; - } else if ((q->iv->type == INV_TYPE_1CH) - && ( (statusMi != 3) - || ((q->iv->lastAlarm[stschan].code) && (q->iv->lastAlarm[stschan].code != 1))) - ) { - q->iv->lastAlarm[stschan] = alarm_t(q->iv->lastAlarm[0].code, q->iv->lastAlarm[0].start,q->ts); - } else if (q->iv->type == INV_TYPE_1CH) - stsok = true; - - q->iv->alarmLastId = prntsts; //iv->alarmMesIndex; - - if (q->iv->alarmCnt > 1) { //more than one channel - for (uint8_t ch = 0; ch < (q->iv->alarmCnt); ++ch) { //start with 1 - if (q->iv->lastAlarm[ch].code == 1) { - stsok = true; - break; + if(!oldState) { // initial zero value? => just write this channel to main state and raise changed flags + changedStatus = true; + q->iv->alarmCnt = 1; // minimum... + } else { + //sth is or was wrong? + if (q->iv->type == INV_TYPE_1CH) { + changedStatus = true; + if(q->iv->alarmCnt == 2) // we had sth. other than "producing" in the past + q->iv->lastAlarm[1].end = q->ts; + else { // copy old state and mark as ended + q->iv->lastAlarm[1] = alarm_t(q->iv->lastAlarm[0].code, q->iv->lastAlarm[0].start,q->ts); + q->iv->alarmCnt = 2; + } + } else if((prntsts != 1) || (q->iv->alarmCnt > 1) ) { // we had sth. other than "producing" in the past in at least one channel (2 and 4 ch types) + if (q->iv->alarmCnt == 1) + q->iv->alarmCnt = (q->iv->type == INV_TYPE_2CH) ? 5 : 9; + if(q->iv->lastAlarm[stschan].code != prntsts) { // changed? + changedStatus = true; + if(q->iv->lastAlarm[stschan].code) // copy old data and mark as ended (if any) + q->iv->lastAlarm[(stschan + (q->iv->type==INV_TYPE_2CH ? 2 : 4))] = alarm_t(q->iv->lastAlarm[stschan].code, q->iv->lastAlarm[stschan].start,q->ts); + q->iv->lastAlarm[stschan] = alarm_t(prntsts, q->ts,0); + } + if(changedStatus) { + for (uint8_t i = 1; i <= q->iv->channels; i++) { //start with 1 + if (q->iv->lastAlarm[i].code == 1) { + stsok = true; + break; + } + } } } } - if(*mSerialDebug) { - DPRINT(DBG_WARN, F("New state on CH")); - DBGPRINT(String(stschan)); DBGPRINT(F(" (")); - DBGPRINT(String(prntsts)); DBGPRINT(F("): ")); - DBGPRINTLN(q->iv->getAlarmStr(prntsts)); - } - if(!q->iv->miMultiParts) - q->iv->miMultiParts = 1; // indicate we got status info (1+2 ch types) } if (!stsok) { q->iv->setValue(q->iv->getPosByChFld(0, FLD_EVT, rec), rec, prntsts); q->iv->lastAlarm[0] = alarm_t(prntsts, q->ts, 0); + } + if (changedStatus || !stsok) { rec->ts = q->ts; rec->mqttSentStatus = MqttSentStatus::NEW_DATA; + q->iv->alarmLastId = prntsts; //iv->alarmMesIndex; + if (NULL != mCbAlarm) + (mCbAlarm)(q->iv); + if(*mSerialDebug) { + DPRINT(DBG_WARN, F("New state on CH")); + DBGPRINT(String(stschan)); DBGPRINT(F(" (")); + DBGPRINT(String(prntsts)); DBGPRINT(F("): ")); + DBGPRINTLN(q->iv->getAlarmStr(prntsts)); + } } if (q->iv->alarmMesIndex < rec->record[q->iv->getPosByChFld(0, FLD_EVT, rec)]) { @@ -947,6 +957,8 @@ class Communication : public CommQueue<> { DBGPRINTLN(String(q->iv->alarmMesIndex)); } } + if(!q->iv->miMultiParts) + q->iv->miMultiParts = 1; // indicate we got status info (1+2 ch types) } @@ -986,10 +998,8 @@ class Communication : public CommQueue<> { ac_pow += iv->getValue(iv->getPosByChFld(1, FLD_PDC, rec), rec); } else { for(uint8_t i = 1; i <= iv->channels; i++) { - if ((!iv->lastAlarm[i].code) || (iv->lastAlarm[i].code == 1)) { - uint8_t pos = iv->getPosByChFld(i, FLD_PDC, rec); - ac_pow += iv->getValue(pos, rec); - } + if ((!iv->lastAlarm[i].code) || (iv->lastAlarm[i].code == 1)) + ac_pow += iv->getValue(iv->getPosByChFld(i, FLD_PDC, rec), rec); } } ac_pow = (int) (ac_pow*9.5); diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h index ecf82aa7..cc42df4f 100644 --- a/src/hm/Heuristic.h +++ b/src/hm/Heuristic.h @@ -38,6 +38,8 @@ class Heuristic { ih->txRfChId = curId; curId = (curId + 1) % RF_MAX_CHANNEL_ID; } + if(ih->txRfQuality[ih->txRfChId] == RF_MIN_QUALTIY) // all channels are bad, reset... + ih->clear(); if(ih->testPeriodSendCnt < 0xff) ih->testPeriodSendCnt++; @@ -71,7 +73,7 @@ class Heuristic { return id2Ch(ih->txRfChId); } - void evalTxChQuality(Inverter<> *iv, bool crcPass, uint8_t retransmits, uint8_t rxFragments) { + void evalTxChQuality(Inverter<> *iv, bool crcPass, uint8_t retransmits, uint8_t rxFragments, bool quotaMissed = false) { HeuristicInv *ih = &iv->heuristics; #if (DBG_DEBUG == DEBUG_LEVEL) @@ -84,8 +86,10 @@ class Heuristic { DBGPRINT(", "); DBGPRINTLN(String(ih->lastRxFragments)); #endif + if(quotaMissed) // we got not enough frames on this attempt, but iv was answering + updateQuality(ih, (rxFragments > 3 ? RF_TX_CHAN_QUALITY_GOOD : (rxFragments > 1 ? RF_TX_CHAN_QUALITY_OK : RF_TX_CHAN_QUALITY_LOW))); - if(ih->lastRxFragments == rxFragments) { + else if(ih->lastRxFragments == rxFragments) { if(crcPass) updateQuality(ih, RF_TX_CHAN_QUALITY_GOOD); else if(!retransmits || isNewTxCh(ih)) { // nothing received: send probably lost diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index d1d24364..eb44dd8c 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -77,7 +77,7 @@ class HmRadio : public Radio { #else mNrf24->begin(mSpi.get(), ce, cs); #endif - mNrf24->setRetries(3, 9); // wait 3*250 = 750us, 16 * 250us -> 4000us = 4ms + mNrf24->setRetries(3, 15); // wait 3*250 = 750us, 16 * 250us -> 4000us = 4ms mNrf24->setDataRate(RF24_250KBPS); //mNrf24->setAutoAck(true); // enabled by default @@ -159,7 +159,7 @@ class HmRadio : public Radio { mTimeslotStart = millis(); tempRxChIdx = mRxChIdx; // might be better to start off with one channel less? mRxPendular = false; - mNRFloopChannels = (mLastIv->mCmd == MI_REQ_CH1); + mNRFloopChannels = (mLastIv->mCmd == MI_REQ_CH1 || mLastIv->mCmd == MI_REQ_CH2); innerLoopTimeout = DURATION_LISTEN_MIN; } From 426d47786c1629d8ac60ab779822e7c1ef0e8e0a Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 17 Feb 2024 09:38:17 +0100 Subject: [PATCH 003/201] Remove hint to 'INV_RESET_MIDNIGHT' --- src/web/lang.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/web/lang.json b/src/web/lang.json index 066370c5..5b45a2b7 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -295,8 +295,8 @@ }, { "token": "INV_RESET_MIDNIGHT", - "en": "Reset values and YieldDay at midnight. ('Pause communication during night' need to be set)", - "de": "Werte und Gesamtertrag um Mitternacht zurücksetzen ('Kommunikation während der Nacht pausieren' muss gesetzt sein)" + "en": "Reset values and YieldDay at midnight", + "de": "Werte und Gesamtertrag um Mitternacht zurücksetzen" }, { "token": "INV_PAUSE_SUNSET", From c7f7d77fb2b2bd36ed3961471cb9c73bd16b9e99 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 19 Feb 2024 23:03:23 +0100 Subject: [PATCH 004/201] 0.8.84 * fix homeassistant autodiscovery #1432 --- src/CHANGES.md | 1300 +++++++++++++++++++++++++++++++++++++-- src/defines.h | 2 +- src/publisher/pubMqtt.h | 7 +- 3 files changed, 1268 insertions(+), 41 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 5fd4fc31..e55145c5 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,41 +1,1265 @@ -Changelog v0.8.83 +# Development Changes -* added German translations for all variants -* added reading grid profile -* added decimal place for active power control (APC aka power limit) -* added information about working IRQ for NRF24 and CMT2300A to `/system` -* added loss rate to `/visualization` in the statistics window and MqTT -* added optional output to display whether it's night time or not. Can be reused as output to control battery system or mapped to a LED -* added timestamp for `max ac power` as tooltip -* added wizard for initial WiFi connection -* added history graph (still under development) -* added simulator (must be activated before compile, standard: off) -* added minimal version (without: MqTT, Display, History), WebUI is not changed! (not compiled automatically) -* added info about installed binary to `/update` -* added protection to prevent update to wrong firmware (environment check) -* added optional custom link to the menu -* added support for other regions (USA, Indonesia) -* added warning for WiFi channel 12-14 (ESP8266 only) -* added `max_power` to MqTT total values -* added API-Token authentification for external scripts -* improved MqTT by marking sent data and improved `last_success` resends -* improved communication for HM and MI inverters -* improved reading live data from inverter -* improved sending active power control command faster -* improved `/settings`: pinout has an own subgroup -* improved export by saving settings before they are exported (to have everything in JSON) -* improved code quality (cppcheck) -* seperated sunrise and sunset offset to two fields -* fix MqTT night communication -* fix missing favicon to html header -* fix build on Windows of `opendtufusion` environments (git: trailing whitespaces) -* fix generation of DTU-ID -* fix: protect commands from popup in `/live` if password is set -* fix: prevent sending commands to inverter which isn't active -* combined firmware and hardware version to JSON topics (MqTT) -* updated Prometheus with latest changes -* upgraded most libraries to newer versions -* beautified typography, added spaces between value and unit for `/visualization` +## 0.8.84 - 2024-02-19 +* fix homeassistant autodiscovery #1432 + +# RELEASE 0.8.83 - 2024-02-16 + +## 0.8.82 - 2024-02-15 +* fixed crash once firmware version was read and sent via MqTT #1428 +* possible fix: reset yield offset on midnight #1429 + +## 0.8.81 - 2024-02-13 +* fixed authentication with empty token #1415 +* added new setting for future function to send log via MqTT +* combined firmware and hardware version to JSON topics (MqTT) #1212 + +## 0.8.80 - 2024-02-12 +* optimize API authentication, Error-Codes #1415 +* breaking change: authentication API command changed #1415 +* breaking change: limit has to be send als `float`, `0.0 .. 100.0` #1415 +* updated documentation #1415 +* fix don't send control command twice #1426 + +## 0.8.79 - 2024-02-11 +* fix `opendtufusion` build (started only once USB-console was connected) +* code quality improvments + +## 0.8.78 - 2024-02-10 +* finalized API token access #1415 +* possible fix of MqTT fix "total values are sent to often" #1421 +* removed `switchCycle` from `hmsRadio.h` #1412 +* merge PR: Add hint to INV_RESET_MIDNIGHT resp. INV_PAUSE_DURING_NIGHT #1418 +* merge PR: simplify rxOffset logic #1417 +* code quality improvments + +## 0.8.77 - 2024-02-08 +* merge PR: BugFix: ACK #1414 +* fix suspicious if condition #1416 +* prepared API token for access, not functional #1415 + +## 0.8.76 - 2024-02-07 +* revert changes from yesterday regarding snprintf and its size #1410, #1411 +* reduced cppcheck linter warnings significantly +* try to improve ePaper (ghosting) #1107 + +## 0.8.75 - 2024-02-06 +* fix active power control value #1406, #1409 +* update Mqtt lib to version `1.6.0` +* take care of null terminator of chars #1410, #1411 + +## 0.8.74 - 2024-02-05 +* reduced cppcheck linter warnings significantly + +## 0.8.73 - 2024-02-03 +* fix nullpointer during communication #1401 +* added `max_power` to MqTT total values #1375 + +## 0.8.72 - 2024-02-03 +* fixed translation #1403 +* fixed sending commands to inverters which are soft turned off #1397 +* reduce switchChannel command for HMS (only each 5th cycle it will be send now) + +## 0.8.71 - 2024-02-03 +* fix heuristics reset +* fix CMT missing frames problem +* removed inverter gap setting * removed add to total (MqTT) inverter setting +* fixed sending commands to inverters which are soft turned off +* save settings before they are exported #1395 +* fix autologin bug if no password is set +* translated `/serial` +* removed "yield day" history + +## 0.8.70 - 2024-02-01 +* prevent sending commands to inverter which isn't active #1387 +* protect commands from popup in `/live` if password is set #1199 + +## 0.8.69 - 2024-01-31 +* merge PR: Dynamic retries, pendular first rx chan #1394 + +## 0.8.68 - 2024-01-29 +* fix HMS / HMT startup +* added `flush_rx` to NRF on TX +* start with heuristics set to `0` +* added warning for WiFi channel 12-14 (ESP8266 only) #1381 + +## 0.8.67 - 2024-01-29 +* fix HMS frequency +* fix display of inverter id in serial log (was displayed twice) + +## 0.8.66 - 2024-01-28 +* added support for other regions - untested #1271 +* fix generation of DTU-ID; was computed twice without reset if two radios are enabled + +## 0.8.65 - 2024-01-24 +* removed patch for NRF `PLOS` +* fix lang issues #1388 +* fix build on Windows of `opendtufusion` environments (git: trailing whitespaces) + +## 0.8.64 - 2024-01-22 +* add `ARC` to log (NRF24 Debug) +* merge PR: ETH NTP update bugfix #1385 + +## 0.8.63 - 2024-01-22 +* made code review +* fixed endless loop #1387 + +## 0.8.62 - 2024-01-21 +* updated version in footer #1381 +* repaired radio statistics #1382 + +## 0.8.61 - 2024-01-21 +* add favicon to header +* improved NRF communication +* merge PR: provide localized times to display mono classes #1376 +* merge PR: Bypass OOM-Crash on minimal version & history access #1378 +* merge PR: Add some REST Api Endpoints to avail_endpoints #1380 + +## 0.8.60 - 2024-01-20 +* merge PR: non blocking nRF loop #1371 +* merge PR: fixed millis in serial log #1373 +* merge PR: fix powergraph scale #1374 +* changed inverter gap to `1` as default (old settings will be overridden) + +## 0.8.59 - 2024-01-18 +* merge PR: solve display settings dependencies #1369 +* fix language typos #1346 +* full update of ePaper after booting #1107 +* fix MqTT yield day reset even if `pause inverter during nighttime` isn't active #1368 + +## 0.8.58 - 2024-01-17 +* fix missing refresh URL #1366 +* fix view of grid profile #1365 +* fix webUI translation #1346 +* fix protection mask #1352 +* merge PR: Add Watchdog for ESP32 #1367 +* merge PR: ETH support for CMT2300A - HMS/HMT #1356 +* full refresh of ePaper after booting #1107 +* add optional custom link #1199 +* pinout has an own subgroup in `/settings` +* grid profile will be displayed as hex in every case #1199 + +## 0.8.57 - 2024-01-15 +* merge PR: fix immediate clearing of display after sunset #1364 +* merge PR: MI-MQTT and last retransmit #1363 +* fixed DTU-ID, now built from the unique part of the MAC +* fix lang in `/system` #1346 +* added protection to prevent update to wrong firmware (environment check) + +## 0.8.56 - 2024-01-15 +* potential fix of update problems and random reboots #1359 #1354 + +## 0.8.55 - 2024-01-14 +* merge PR: fix reboot problem with deactivated power graph #1360 +* changed scope of variables and member functions inside display classes +* removed automatically "minimal" builds +* fix include of "settings.h" (was already done in #1360) +* merge PR: Enhancement: Add info about compiled modules to version string #1357 +* add info about installed binary to `/update` #1353 +* fix lang in `/system` #1346 + +## 0.8.54 - 2024-01-13 +* added minimal version (without: MqTT, Display, History), WebUI is not changed! +* added simulator (must be activated before compile, standard: off) +* changed communication attempts back to 5 + +## 0.8.53 - 2024-01-12 +* fix history graph +* fix MqTT yield day #1331 + +## 0.8.52 - 2024-01-11 +* possible fix of 'division by zero' #1345 +* fix lang #1348 #1346 +* fix timestamp `max AC power` #1324 +* fix stylesheet overlay `max AC power` #1324 +* fix download link #1340 +* fix history graph +* try to fix #1331 + +## 0.8.51 - 2024-01-10 +* fix translation #1346 +* further improve sending active power control command faster #1332 +* added history protection mask +* merge PR: display graph improvements #1347 + +## 0.8.50 - 2024-01-09 +* merge PR: added history charts to web #1336 +* merge PR: small display changes #1339 +* merge PR: MI - add "get loss logic" #1341 +* translated `/history` +* fix translations in title of documents +* added translations for error messages #1343 + +## 0.8.49 - 2024-01-08 +* fix send total values if inverter state is different from `OFF` #1331 +* fix german language issues #1335 + +## 0.8.48 - 2024-01-07 +* merge PR: pin selection for ESP-32 S2 #1334 +* merge PR: enhancement: power graph display option #1330 + +## 0.8.47 - 2024-01-06 +* reduce GxEPD2 lib to compile faster +* upgraded GxEPD2 lib to `1.5.3` +* updated espressif32 platform to `6.5.0` +* updated U8g2 to `2.35.9` +* started to convert deprecated functions of new ArduinoJson `7.0.0` +* started to have german translations of all variants (environments) #925 #1199 +* merge PR: add defines for retry attempts #1329 + +## 0.8.46 - 2024-01-06 +* improved communication + +## 0.8.45 - 2024-01-05 +* fix MqTT total values #1326 +* start implementing a wizard for initial (WiFi) configuration #1199 + +## 0.8.44 - 2024-01-05 +* fix MqTT transmission of data #1326 +* live data is read much earlier / faster and more often #1272 + +## 0.8.43 - 2024-01-04 +* fix display of sunrise in `/system` #1308 +* fix overflow of `getLossRate` calculation #1318 +* improved MqTT by marking sent data and improved `last_success` resends #1319 +* added timestamp for `max ac power` as tooltip #1324 #1123 #1199 +* repaired Power-limit acknowledge #1322 +* fix `max_power` in `/visualization` was set to `0` after sunset + +## 0.8.42 - 2024-01-02 +* add LED to display whether it's night time or not. Can be reused as output to control battery system #1308 +* merge PR: beautifiying typography, added spaces between value and unit for `/visualization` #1314 +* merge PR: Prometheus add `getLossRate` and bugfixing #1315 +* add loss rate to `/visualization` in the statistics window +* corrected `getLossRate` infos for MqTT and prometheus +* added information about working IRQ for NRF24 and CMT2300A to `/system` + +## 0.8.41 - 2024-01-02 +* fix display timeout (OLED) to 60s +* change offs to signed value + +## 0.8.40 - 2024-01-02 +* fix display of sunrise and sunset in `/system` #1308 +* fix MqTT set power limit #1313 + +## 0.8.39 - 2024-01-01 +* fix MqTT dis_night_comm in the morning #1309 #1286 +* seperated offset for sunrise and sunset #1308 +* powerlimit (active power control) now has one decimal place (MqTT / API) #1199 +* merge Prometheus metrics fix #1310 +* merge MI grid profile request #1306 +* merge update documentation / readme #1305 +* add `getLossRate` to radio statistics and to MqTT #1199 + +## 0.8.38 - 2023-12-31 +* fix Grid-Profile JSON #1304 + +## 0.8.37 - 2023-12-30 +* added grid profiles +* format version of grid profile + +# RELEASE 0.8.36 - 2023-12-30 + +## 0.8.35 - 2023-12-30 +* added dim option for LEDS +* changed reload time for opendtufusion after update to 5s +* fix default interval and gap for communication +* fix serial number in exported json (was decimal, now correct as hexdecimal number) +* beautified factory reset +* added second stage for erase settings +* increased maximal number of inverters to 32 for opendtufusion board (ESP32-S3) +* fixed crash if CMT inverter is enabled, but CMT isn't configured + +# RELEASE 0.8.34 - 2023-12-29 + +## 0.8.33 - 2023-12-29 +* improved communication thx @rejoe2 + +## 0.8.32 - 2023-12-29 +* fix `start` / `stop` / `restart` commands #1287 +* added message, if profile was not read until now #1300 +* added developer option to use 'syslog-server' instead of 'web-serail' #1299 + +## 0.8.31 - 2023-12-29 +* added class to handle timeouts PR #1298 + +## 0.8.30 - 2023-12-28 +* added info if grid profile was not found +* merge PR #1293 +* merge PR #1295 fix ESP8266 pin settings +* merge PR #1297 fix layout for OLED displays + +## 0.8.29 - 2023-12-27 +* fix MqTT generic topic `comm_disabled` #1265 #1286 +* potential fix of #1285 (reset yield day) +* fix fraction of yield correction #1280 +* fix crash if `getLossRate` was read from inverter #1288 #1290 +* reduce reload time for opendtufusion ethernet variant to 5 seconds +* added basic grid parser +* added ESP32-C3 mini environment #1289 + +## 0.8.28 - 2023-12-23 +* fix bug heuristic +* add version information to clipboard once 'copy' was clicked +* add get loss rate @rejoe2 +* improve communication @rejoe2 + +## 0.8.27 - 2023-12-18 +* fix set power limit #1276 + +## 0.8.26 - 2023-12-17 +* read grid profile as HEX (`live` -> click inverter name -> `show grid profile`) + +## 0.8.25 - 2023-12-17 +* RX channel ID starts with fixed value #1277 +* fix static IP for Ethernet + +## 0.8.24 - 2023-12-16 +* fix NRF communication for opendtufusion ethernet variant + +## 0.8.23 - 2023-12-14 +* heuristics fix #1269 #1270 +* moved `sendInterval` in settings, **important:** *will be reseted to 15s after update to this version* +* try to prevent access to radio classes if they are not activated +* fixed millis in serial log +* changed 'print whole trace' = `false` as default +* added communication loop duration in [ms] to serial console +* don't print Hex-Payload if 'print whole trace' == `false` + +## 0.8.22 - 2023-12-13 +* fix communication state-machine regarding zero export #1267 + +## 0.8.21 - 2023-12-12 +* fix ethernet save inverter parameters #886 +* fix ethernet OTA update #886 +* improved radio statistics, fixed heuristic output for HMS and HMT inverters + +## 0.8.20 - 2023-12-12 +* improved HM communication #1259 #1249 +* fix `loadDefaults` for ethernet builds #1263 +* don't loop through radios which aren't in use #1264 + +## 0.8.19 - 2023-12-11 +* added ms to serial log +* added (debug) option to configure gap between inverter requests + +## 0.8.18 - 2023-12-10 +* copied even more from the original heuristic code #1259 +* added mDNS support #1262 + +## 0.8.17 - 2023-12-10 +* possible fix of NRF with opendtufusion (without ETH) +* small fix in heuristics (if conditions made assignment not comparisson) + +## 0.8.16 - 2023-12-09 +* fix crash if NRF is not enabled +* updated heuristic #1080 #1259 +* fix compile opendtufusion fusion ethernet + +## 0.8.15 - 2023-12-09 +* added support for opendtufusion fusion ethernet shield #886 +* fixed range of HMS / HMT frequencies to 863 to 870 MHz #1238 +* changed `yield effiency` per default to `1.0` #1243 +* small heuristics improvements #1258 +* added class to combine inverter heuristics fields #1258 + +## 0.8.14 - 2023-12-07 +* fixed decimal points for temperature (WebUI) PR #1254 #1251 +* fixed inverter statemachine available state PR #1252 #1253 +* fixed NTP update and sunrise calculation #1240 #886 +* display improvments #1248 #1247 +* fixed overflow in `hmRadio.h` #1244 + +## 0.8.13 - 2023-11-28 +* merge PR #1239 symbolic layout for OLED 128x64 + motion senser functionality +* fix MqTT IP addr for ETH connections PR #1240 +* added ethernet build for fusion board, not tested so far + +## 0.8.12 - 2023-11-20 +* added button `copy to clipboard` to `/serial` + +## 0.8.11 - 2023-11-20 +* improved communication, thx @rejoe2 +* improved heuristics, thx @rejoe2, @Oberfritze +* added option to strip payload of frames to significant area + +## 0.8.10 - 2023-11-19 +* fix Mi and HM inverter communication #1235 +* added privacy mode option #1211 +* changed serial debug option to work without reboot + +## 0.8.9 - 2023-11-19 +* merged PR #1234 +* added new alarm codes +* removed serial interval, was not in use anymore + +## 0.8.8 - 2023-11-16 +* fix ESP8266 save inverter #1232 + +## 0.8.7 - 2023-11-13 +* fix ESP8266 inverter settings #1226 +* send radio statistics via MqTT #1227 +* made night communication inverter depended +* added option to prevent adding values of inverter to total values (MqTT only) #1199 + +## 0.8.6 - 2023-11-12 +* merged PR #1225 +* improved heuristics (prevent update of statitistic during testing) + +## 0.8.5 - 2023-11-12 +* fixed endless loop while switching CMT frequency +* removed obsolete "retries" field from settings #1224 +* fixed crash while defining new invertes #1224 +* fixed default frequency settings +* added default input power to `400` while adding new inverters +* fixed color of wifi RSSI icon #1224 + +## 0.8.4 - 2023-11-10 +* changed MqTT alarm topic, removed retained flag #1212 +* reduce last_success MQTT messages (#1124) +* introduced tabs in WebGUI (inverter settings) +* added inverter-wise power level and frequency + +## 0.8.3 - 2023-11-09 +* fix yield day reset during day #848 +* add total AC Max Power to WebUI +* fix opendtufusion build (GxEPD patch) +* fix null ptr PR #1222 + +## 0.8.2 - 2023-11-08 +* beautified inverter settings in `setup` (preperation for future, settings become more inverter dependent) + +## 0.8.1 - 2023-11-05 +* added tx channel heuristics (per inverter) +* fix statistics counter + +## 0.8.0 - 2023-10-?? +* switched to new communication scheme + +## 0.7.66 - 2023-10-04 +* prepared PA-Level for CMT +* removed settings for number of retransmits, its fixed to `5` now +* added parentheses to have a excactly defined behaviour + +## 0.7.65 - 2023-10-02 +* MI control command review #1197 + +## 0.7.64 - 2023-10-02 +* moved active power control to modal in `live` view (per inverter) by click on current APC state + +## 0.7.63 - 2023-10-01 +* fix NRF24 communication #1200 + +## 0.7.62 - 2023-10-01 +* fix communication to inverters #1198 +* add timeout before payload is tried to process (necessary for HMS/HMT) + +## 0.7.61 - 2023-10-01 +* merged `hmPayload` and `hmsPayload` into single class +* merged generic radio functions into new parent class `radio.h` +* moved radio statistics into the inverter - each inverter has now seperate statistics which can be accessed by click on the footer in `/live` +* fix compiler warnings #1191 +* fix ePaper logo during night time #1151 + +## 0.7.60 - 2023-09-27 +* fixed typos in changelog #1172 +* fixed MqTT manual clientId storage #1174 +* fixed inverter name length in setup #1181 +* added inverter name to the header of alarm list #1181 +* improved code to avoid warning during compilation #1182 +* fix scheduler #1188, #1179 + +## 0.7.59 - 2023-09-20 +* re-add another HM-400 hardware serial number accidentally removed with `0.7.45` (#1169) +* merge PR #1170 +* reduce last_success MQTT messages (#1124) +* add re-request if inverter is known to be online and first try fails +* add alarm reporting to MI (might need review!) +* rebuild MI limiting code closer to DTUSimMI example +* round APC in `W` to an integer #1171 + +## 0.7.58 +* fix ESP8266 save settings issue #1166 + +## 0.7.57 - 2023-09-18 +* fix Alarms are always in queue (since 0.7.56) +* fix display active power control to long for small devices #1165 + +## 0.7.56 - 2023-09-17 +* only request alarms which were not received before #1113 +* added flag if alarm was requested but not received and re-request it #1105 +* merge PR #1163 + +## 0.7.55 - 2023-09-17 +* fix prometheus builds +* fix ESP32 default pinout #1159 +* added `opendtufusion-dev` because of annoying `-DARDUINO_USB_CDC_ON_BOOT=1` flag +* fix display of current power on `index` +* fix OTA, was damaged by version `0.7.51`, need to use webinstaller (from `0.7.51` to `0.7.54`) + +## 0.7.54 - 2023-09-16 +* added active power control in `W` to live view #201, #673 +* updated docu, active power control related #706 +* added current AC-Power to `index` page and removed version #763 +* improved statistic data, moved to entire struct +* removed `/api/statistics` endpoint from REST-API + +## 0.7.53 - 2023-09-16 +* fix ePaper / display night behaviour #1151 +* fix ESP8266 compile error + +## 0.7.52 - 2023-09-16 +* fix CMT configurable pins #1150, #1159 +* update MqTT lib to version `1.4.5` + +## 0.7.51 - 2023-09-16 +* fix CMT configurable pins #1150 +* fix default CMT pins for opendtufusion +* beautified `system` +* changed main loops, fix resets #1125, #1135 + +## 0.7.50 - 2023-09-12 +* moved MqTT info to `system` +* added CMT info for ESP32 devices +* improved CMT settings, now `SCLK` and `SDIO` are configurable #1046, #1150 +* changed `Power-Limit` in live-view to `Active Power Control` +* increase length of update file selector #1132 + +## 0.7.49 - 2023-09-11 +* merge PR: symbolic icons for mono displays, PR #1136 +* merge MI code restructuring PR #1145 +* merge Prometheus PR #1148 +* add option to strip webUI for ESP8266 (reduce code size, add ESP32 special features; `IF_ESP32` directives) +* started to get CMT info into `system` - not finished + +## 0.7.48 - 2023-09-10 +* fix SSD1309 2.42" display pinout +* improved setup page: save and delete of inverters + +## 0.7.47 - 2023-09-07 +* fix boot loop #1140 +* fix regex in `setup` page +* fix MI serial number display `max-module-power` in `setup` #1142 +* renamed `opendtufusionv1` to `opendtufusion` + +## 0.7.46 - 2023-09-04 +* removed `delay` from ePaper +* started improvements of `/system` +* fix LEDs to check all configured inverters +* send loop skip disabled inverters fix +* print generated DTU SN to console +* HW Versions for MI series PR #1133 +* 2.42" display (SSD1309) integration PR #1139 +* update user manual PR #1121 +* add / rename alarm codes PR #1118 +* revert default pin ESP32 for NRF23-CE #1132 +* luminance of display can be changed during runtime #1106 + +## 0.7.45 - 2023-08-29 +* change ePaper text to symbols PR #1131 +* added some invertes to dev info list #1111 + +## 0.7.44 - 2023-08-28 +* fix `last_success` transmitted to often #1124 + +## 0.7.43 - 2023-08-28 +* improved RSSI for NRF24, now it's read per package (and inverter) #1129 +* arranged `heap` related info together in `/system` +* fix display navi during save +* clean up binary output, separated to folders + +## 0.7.42 - 2023-08-27 +* fix ePaper for opendtufusion_v2.x boards (Software SPI) +* add signal strength for NRF24 - PR #1119 +* refactor wifi class to support ESP32 S2 PR #1127 +* update platform for ESP32 to 6.3.2 +* fix opendtufusion LED (were mixed) +* fix `last_success` transmitted to often #1124 +* added ESP32-S3-mini to github actions +* added old Changelog Entries, to have full log of changes + +## 0.7.41 - 2023-08-26 +* merge PR #1117 code spelling fixes #1112 +* alarms were not read after the first day + +## 0.7.40 - 2023-08-21 +* added default pins for opendtu-fusion-v1 board +* fixed hw version display in `live` +* removed development builds, renamed environments in `platform.ini` + +## 0.7.39 - 2023-08-21 +* fix background color of invalid inputs +* add hardware info (click in `live` on inverter name) + +## 0.7.38 - 2023-08-21 +* reset alarms at midnight (if inverter is not available) #1105, #1096 +* add option to reset 'max' values on midnight #1102 +* added default pins for CMT2300A (matching OpenDTU) + +## 0.7.37 - 2023-08-18 +* fix alarm time on WebGui #1099 +* added RSSI info for HMS and HMT inverters (MqTT + REST API) + +# RELEASE 0.7.36 - 2023-08-18 + +## 0.7.35 - 2023-08-17 +* fixed timestamp for alarms send over MqTT +* auto-patch of `AsyncWebServer` #834, #1036 +* Update documentation in Git regarding `ESP8266` default NRF24 pin assignments + +## 0.7.34 - 2023-08-16 +* fixed timezone offset of alarms +* added `AC` and `DC` to `/live` #1098 +* changed `ESP8266` default NRF24 pin assignments (`D3` = `CE` and `D4` = `IRQ`) +* fixed background of modal window for bright color +* fix MI crashes +* fix some lost debug messages +* merged PR #1095, MI fixes for 0.7.x versions +* fix scheduled reboot #1097 +* added vector graphic logo `/doc/logo.svg` +* merge PR #1093, improved Nokia5110 display layout + +## 0.7.33 - 2023-08-15 +* add alarms overview to WebGui #608 +* fix webGui total values #1084 + +## 0.7.32 - 2023-08-14 +* fix colors of live view #1091 + +## 0.7.31 - 2023-08-13 +* fixed docu #1085 +* changed active power limit MqTT messages to QOS2 #1072 +* improved alarm messages, added alarm-id to log #1089 +* trigger power limit read on next day (if inverter was offline meanwhile) +* disabled improv implementation to check if it is related to 'Schwuppdizitaet' +* changed live view to gray once inverter isn't available +* added inverter status to API +* changed sum of totals on WebGui depending on inverter status #1084 +* merge maximum power (AC and DC) from PR #1080 + +## 0.7.30 - 2023-08-10 +* attempt to improve speed / response times (Schwuppdizitaet) #1075 + +## 0.7.29 - 2023-08-09 +* MqTT alarm data was never sent, fixed +* REST API: added alarm data +* REST API: made get record obsolete +* REST API: added power limit acknowledge `/api/inverter/id/[0-x]` #1072 + +## 0.7.28 - 2023-08-08 +* fix MI inverter support #1078 + +## 0.7.27 - 2023-08-08 +* added compile option for ethernet #886 +* fix ePaper configuration, missing `Busy`-Pin #1075 + +# RELEASE 0.7.26 - 2023-08-06 + +* fix MqTT `last_success` + +# RELEASE 0.7.25 - 2023-08-06 + +## 0.7.24 - 2023-08-05 +* merge PR #1069 make MqTT client ID configurable +* fix #1016, general MqTT status depending on inverter state machine +* changed icon for fully available inverter to a filled check mark #1070 +* fixed `last_success` update with MqTT #1068 +* removed `improv` esp-web-installer script, because it is not fully functional at this time + +## 0.7.23 - 2023-08-04 +* merge PR #1056, visualization html +* update MqTT library to 1.4.4 +* update RF24 library to 1.4.7 +* update ArduinoJson library to 6.21.3 +* set minimum invervall for `/live` to 5 seconds + +## 0.7.22 - 2023-08-04 +* attempt to fix homeassistant auto discovery #1066 + +## 0.7.21 - 2023-07-30 +* fix MqTT YieldDay Total goes to 0 several times #1016 + +## 0.7.20 - 2023-07-28 +* merge PR #1048 version and hash in API, fixes #1045 +* fix: no yield day update if yield day reads `0` after inverter reboot (mostly on evening) #848 +* try to fix Wifi override #1047 +* added information after NTP sync to WebUI #1040 + +## 0.7.19 - 2023-07-27 +* next attempt to fix yield day for multiple inverters #1016 +* reduced threshold for inverter state machine from 60min to 15min to go from state `WAS_ON` to `OFF` + +## 0.7.18 - 2023-07-26 +* next attempt to fix yield day for multiple inverters #1016 + +## 0.7.17 - 2023-07-25 +* next attempt to fix yield day for multiple inverters #1016 +* added two more states for the inverter status (also docu) + +## 0.7.16 - 2023-07-24 +* next attempt to fix yield day for multiple inverters #1016 +* fix export settings date #1040 +* fix time on WebUI (timezone was not observed) #913 #1016 + +## 0.7.15 - 2023-07-23 +* add NTP sync interval #1019 +* adjusted range of contrast / luminance setting #1041 +* use only ISO time format in Web-UI #913 + +## 0.7.14 - 2023-07-23 +* fix Contrast for Nokia Display #1041 +* attempt to fix #1016 by improving inverter status +* added option to adjust efficiency for yield (day/total) #1028 + +## 0.7.13 - 2023-07-19 +* merged display PR #1027 +* add date, time and version to export json #1024 + +## 0.7.12 - 2023-07-09 +* added inverter status - state-machine #1016 + +## 0.7.11 - 2023-07-09 +* fix MqTT endless loop #1013 + +## 0.7.10 - 2023-07-08 +* fix MqTT endless loop #1013 + +## 0.7.9 - 2023-07-08 +* added 'improve' functions to set wifi password directly with ESP web tools #1014 +* fixed MqTT publish while applying power limit #1013 +* slightly improved HMT live view (Voltage & Current) + +## 0.7.8 - 2023-07-05 +* fix `YieldDay`, `YieldTotal` and `P_AC` in `TotalValues` #929 +* fix some serial debug prints +* merge PR #1005 which fixes issue #889 +* merge homeassistant PR #963 +* merge PR #890 which gives option for scheduled reboot at midnight (default off) + +## 0.7.7 - 2023-07-03 +* attempt to fix MqTT `YieldDay` in `TotalValues` #927 +* attempt to fix MqTT `YieldDay` and `YieldTotal` even if inverters are not completely available #929 +* fix wrong message 'NRF not connected' if it is disabled #1007 + +## 0.7.6 - 2023-06-17 +* fix display of hidden SSID checkbox +* changed yield correction data type to `double`, now decimal places are supported +* corrected name of 0.91" display in settings +* attempt to fix MqTT zero values only if setting is there #980, #957 +* made AP password configurable #951 +* added option to start without time-sync, eg. for AP-only-mode #951 + +## 0.7.5 - 2023-06-16 +* fix yield day reset on midnight #957 +* improved tickers in `app.cpp` + +## 0.7.4 - 2023-06-15 +* fix MqTT `P_AC` send if inverters are available #987 +* fix assignments for HMS 1CH and 2CH devices +* fixed uptime overflow #990 + +## 0.7.3 - 2023-06-09 +* fix hidden SSID scan #983 +* improved NRF24 missing message on home screen #981 +* fix MqTT publishing only updated values #982 + +## 0.7.2 - 2023-06-08 +* fix HMS-800 and HMS-1000 assignments #981 +* make nrf enabled all the time for ESP8266 +* fix menu item `active` highlight for 'API' and 'Doku' +* fix MqTT totals issue #927, #980 +* reduce maximum number of inverters to 4 for ESP8266, increase to 16 for ESP32 + +## 0.7.1 - 2023-06-05 +* enabled power limit control for HMS / HMT devices +* changed NRF24 lib version back to 1.4.5 because of compile problems for EPS8266 + +## 0.7.0 - 2023-06-04 +* HMS / HMT support for ESP32 devices + +## 0.6.15 - 2023-05-25 +* improved Prometheus Endpoint PR #958 +* fix turn off ePaper only if setting was set #956 +* improved reset values and update MqTT #957 + +## 0.6.14 - 2023-05-21 +* merge PR #902 Mono-Display + +## 0.6.13 - 2023-05-16 +* merge PR #934 (fix JSON API) and #944 (update manual) + +## 0.6.12 - 2023-04-28 +* improved MqTT +* fix menu active item + +## 0.6.11 - 2023-04-27 +* added MqTT class for publishing all values in Arduino `loop` + +## 0.6.10 - HMS +* Version available in `HMS` branch + +# RELEASE 0.6.9 - 2023-04-19 + +## 0.6.8 - 2023-04-19 +* fix #892 `zeroYieldDay` loop was not applied to all channels + +## 0.6.7 - 2023-04-13 +* merge PR #883, improved store of settings and javascript, thx @tastendruecker123 +* support `.` and `,` as floating point separator in setup #881 + +## 0.6.6 - 2023-04-12 +* increased distance for `import` button in mobile view #879 +* changed `led_high_active` to `bool` #879 + +## 0.6.5 - 2023-04-11 +* fix #845 MqTT subscription for `ctrl/power/[IV-ID]` was missing +* merge PR #876, check JSON settings during read for existence +* **NOTE:** incompatible change: renamed `led_high_active` to `act_high`, maybe setting must be changed after update +* merge PR #861 do not send channel metric if channel is disabled + +## 0.6.4 - 2023-04-06 +* merge PR #846, improved NRF24 communication and MI, thx @beegee3 & @rejoe2 +* merge PR #859, fix burger menu height, thx @ThomasPohl + +## 0.6.3 - 2023-04-04 +* fix login, password length was not checked #852 +* merge PR #854 optimize browser caching, thx @tastendruecker123 #828 +* fix WiFi reconnect not working #851 +* updated issue templates #822 + +## 0.6.2 - 2023-04-04 +* fix login from multiple clients #819 +* fix login screen on small displays + +## 0.6.1 - 2023-04-01 +* merge LED fix - LED1 shows MqTT state, LED configurable active high/low #839 +* only publish new inverter data #826 +* potential fix of WiFi hostname during boot up #752 + +# RELEASE 0.6.0 - 2023-03-27 + +## 0.5.110 +* MQTT fix reconnection by new lib version #780 +* add `about` page +* improved documentation regarding SPI pins #814 +* improved documentation (getting started) #815 #816 +* improved MI 4-ch inverter #820 + +## 0.5.109 +* reduced heap fragmentation by optimizing MqTT #768 +* ePaper: centered text thx @knickohr + +## 0.5.108 +* merge: PR SPI pins configurable (ESP32) #807, #806 (requires manual set of MISO=19, MOSI=23, SCLK=18 in GUI for existing installs) +* merge: PR MI serial outputs #809 +* fix: no MQTT `total` sensor for autodiscover if only one inverter was found #805 +* fix: MQTT `total` renamed to `device_name` + `_TOTOL` for better visibility #805 + +## 0.5.107 +* fix: show save message +* fix: removed serial newline for `enqueueCmd` +* Merged improved Prometheus #808 + +## 0.5.106 +* merged MI and debug message changes #804 +* fixed MQTT autodiscover #794, #632 + +## 0.5.105 +* merged MI, thx @rejoe2 #788 +* fixed reboot message #793 + +## 0.5.104 +* further improved save settings +* removed `#` character from ePaper +* fixed saving pinout for `Nokia-Display` +* removed `Reset` Pin for monochrome displays +* improved wifi connection #652 + +## 0.5.103 +* merged MI improvements, thx @rejoe2 #778 +* changed display inverter online message +* merged heap improvements #772 + +## 0.5.102 +* Warning: old exports are not compatible any more! +* fix JSON import #775 +* fix save settings, at least already stored settings are not lost #771 +* further save settings improvements (only store inverters which are existing) +* improved display of settings save return value +* made save settings asynchronous (more heap memory is free) + +## 0.5.101 +* fix SSD1306 +* update documentation +* Update miPayload.h +* Update README.md +* MI - remarks to user manual +* MI - fix AC calc +* MI - fix status msg. analysis + +## 0.5.100 +* fix add inverter `setup.html` #766 +* fix MQTT retained flag for total values #726 +* renamed buttons for import and export `setup.html` +* added serial message `settings saved` + +## 0.5.99 +* fix limit in [User_Manual.md](../User_Manual.md) +* changed `contrast` to `luminance` in `setup.html` +* try to fix SSD1306 display #759 +* only show necessary display pins depending on setting + +## 0.5.98 +* fix SH1106 rotation and turn off during night #756 +* removed MQTT subscription `sync_ntp`, `set_time` with a value of `0` does the same #696 +* simplified MQTT subscription for `limit`. Check [User_Manual.md](../User_Manual.md) for new syntax #696, #713 +* repaired inverter wise limit control +* fix upload settings #686 + +## 0.5.97 +* Attention: re-ordered display types, check your settings! #746 +* improved saving settings of display #747, #746 +* disabled contrast for Nokia display #746 +* added Prometheus as compile option #719, #615 +* update MQTT lib to v1.4.1 +* limit decimal places to 2 in `live` +* added `-DPIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48` to esp8266 debug build #657 +* a `max-module-power` of `0` disables channel in live view `setup` +* merge MI improvements, get firmware information #753 + +## 0.5.96 +* added Nokia display again for ESP8266 #764 +* changed `var` / `VAr` to SI unit `var` #732 +* fix MQTT retained flags for totals (P_AC, P_DC) #726, #721 + +## 0.5.95 +* merged #742 MI Improvements +* merged #736 remove obsolete JSON Endpoint + +## 0.5.94 +* added ePaper (for ESP32 only!), thx @dAjaY85 #735 +* improved `/live` margins #732 +* renamed `var` to `VAr` #732 + +## 0.5.93 +* improved web API for `live` +* added dark mode option +* converted all forms to reponsive design +* repaired menu with password protection #720, #716, #709 +* merged MI series fixes #729 + +## 0.5.92 +* fix mobile menu +* fix inverters in select `serial.html` #709 + +## 0.5.91 +* improved html and navi, navi is visible even when API dies #660 +* reduced maximum allowed JSON size for API to 6000Bytes #660 +* small fix: output command at `prepareDevInformCmd` #692 +* improved inverter handling #671 + +## 0.5.90 +* merged PR #684, #698, #705 +* webserial minor overflow fix #660 +* web `index.html` improve version information #701 +* fix MQTT sets power limit to zero (0) #692 +* changed `reset at midnight` with timezone #697 + +## 0.5.89 +* reduced heap fragmentation (removed `strtok` completely) #644, #645, #682 +* added part of mac address to MQTT client ID to separate multiple ESPs in same network +* added dictionary for MQTT to reduce heap-fragmentation +* removed `last Alarm` from Live view, because it showed always the same alarm - will change in future + +## 0.5.88 +* MQTT Yield Day zero, next try to fix #671, thx @beegee3 +* added Solenso inverter to supported devices +* improved reconnection of MQTT #650 + +## 0.5.87 +* fix yield total correction as module (inverter input) value #570 +* reneabled instant start communication (once NTP is synced) #674 + +## 0.5.86 +* prevent send devcontrol request during disabled night communication +* changed yield total correction as module (inverter input) value #570 +* MQTT Yield Day zero, next try to fix #671 + +## 0.5.85 +* fix power-limit was not checked for max retransmits #667 +* fix blue LED lights up all the time #672 +* fix installing schedulers if NTP server isn't available +* improved zero values on triggers #671 +* hardcoded MQTT subtopics, because wildcard `#` leads to errors +* rephrased some messages on webif, thx to @Argafal #638 +* fixed 'polling stop message' on `index.html` #639 + +## 0.5.84 +* fix blue LED lights up all the time #672 +* added an instant start communication (once NTP is synced) +* add MI 3rd generation inverters (10x2 serial numbers) +* first decodings of messages from MI 2nd generation inverters + +## 0.5.83 +* fix MQTT publishing, `callback` was set but reset by following `setup()` + +## 0.5.82 +* fixed communication error #652 +* reset values is no bound to MQTT any more, setting moved to `inverter` #649 +* fixed wording on `index.hmtl` #661 + +## 0.5.81 +* started implementation of MI inverters (setup.html, own processing `MiPayload.h`) + +## 0.5.80 +* fixed communication #656 + +## 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) +* 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 +* 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 +* 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 +* 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 +* re-enabled 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) +* improved `isAvailable`, checks all record structs, inverter becomes available more early because version is check first +* fix tickers were not set if NTP is not available +* disabled annoying `FlashStringHelper` it gives randomly Exceptions during development, feels more stable since then +* moved erase button to the bottom in settings, not nice but more functional +* split `tx_count` to `tx_cnt` and `retransmits` in `system.html` +* fix mqtt retransmit IP address #602 +* added debug infos for `scheduler` (web -> `/debug` as trigger prints list of tickers to serial console) + +## 0.5.73 +* improved payload handling (request / retransmit) #464 +* included alarm ID parse to serial console (in development) + +## 0.5.72 +* repaired system, scheduler was not called any more #596 + +## 0.5.71 +* improved wifi handling and tickers, many thanks to @beegee3 #571 +* fixed YieldTotal correction calculation #589 +* fixed serial output of power limit acknowledge #569 +* reviewed `sendDiscoveryConfig` #565 +* merged PR `Monodisplay`, many thanks to @dAjaY85 #566, Note: (settings are introduced but not able to be modified, will be included in next version) + +## 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 +* 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 +* changed name of binaries, moved GIT-Sha to the front #538 + +## 0.5.68 +* repaired receive payload +* Powerlimit is transferred 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 +* payload: if last frame is missing, request all frames again + +# RELEASE 0.5.66 - 2022-12-30 + +## 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 +* 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) +* potential fix of #526 duplicates in API `/api/record/live` +* added update information to `index.html` + +## 0.5.62 +* fix MQTT `status` update +* removed MQTT `available_text` (can be deducted from `available`) +* enhanced MQTT documentation in `User_Manual.md` +* removed `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 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 multiple 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 +* 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 +* increased 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 +* 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 interval 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 + +# RELEASE 0.5.41 - 2022-11-22 + +# RELEASE 0.5.28 - 2022-10-30 + +# RELEASE 0.5.17 - 2022-09-06 + +# RELEASE 0.5.16 - 2022-09-04 -full version log: [Development Log](https://github.com/lumapu/ahoy/blob/development03/src/CHANGES.md) diff --git a/src/defines.h b/src/defines.h index bf111d99..edcde7a0 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 83 +#define VERSION_PATCH 84 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 369d9ead..ea6f331e 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -397,6 +397,10 @@ class PubMqtt { std::array name; std::array uniq_id; std::array buf; + topic.fill(0); + name.fill(0); + uniq_id.fill(0); + buf.fill(0); const char *devCls, *stateCls; if (!total) { if (rec->assign[mDiscovery.sub].ch == CH0) @@ -420,7 +424,7 @@ class PubMqtt { DynamicJsonDocument doc2(512); constexpr static char* unitTotal[] = {"W", "kWh", "Wh", "W"}; - doc2[F("name")] = name; + doc2[F("name")] = String(name.data()); doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + ((!total) ? String(iv->config->name) : "total" ) + String(topic.data()); doc2[F("unit_of_meas")] = ((!total) ? (iv->getUnit(mDiscovery.sub, rec)) : (unitTotal[mDiscovery.sub])); doc2[F("uniq_id")] = ((!total) ? (String(iv->config->serial.u64, HEX)) : (node_id)) + "_" + uniq_id.data(); @@ -437,7 +441,6 @@ class PubMqtt { else // total values snprintf(topic.data(), topic.size(), "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(), fields[fldTotal[mDiscovery.sub]]); size_t size = measureJson(doc2) + 1; - buf.fill(0); serializeJson(doc2, buf.data(), size); publish(topic.data(), buf.data(), true, false); From f5009993463bda5280a4dcb075c76cfca74f5d2d Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 19 Feb 2024 23:09:32 +0100 Subject: [PATCH 005/201] 0.8.84 - 2024-02-19 * merge PR: more gracefull handling of complete retransmits #1433 --- src/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CHANGES.md b/src/CHANGES.md index e55145c5..98e1437c 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,7 @@ ## 0.8.84 - 2024-02-19 * fix homeassistant autodiscovery #1432 +* merge PR: more gracefull handling of complete retransmits #1433 # RELEASE 0.8.83 - 2024-02-16 From b6afec1c3ad2ee97fcaa4ca72616e5732e6538bd Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 22 Feb 2024 23:36:07 +0100 Subject: [PATCH 006/201] 0.8.85 - 2024-02-22 * possible fix of MqTT fix "total values are sent to often" #1421 * fix translation #1442 * availability check only related to live data #1035 #1437 --- src/CHANGES.md | 5 +++++ src/app.cpp | 3 +-- src/defines.h | 2 +- src/hm/hmInverter.h | 12 +++--------- src/publisher/pubMqttIvData.h | 7 +++++-- src/web/html/serial.html | 2 +- src/web/lang.json | 8 +++++++- 7 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 98e1437c..003c8cef 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.8.85 - 2024-02-22 +* possible fix of MqTT fix "total values are sent to often" #1421 +* fix translation #1442 +* availability check only related to live data #1035 #1437 + ## 0.8.84 - 2024-02-19 * fix homeassistant autodiscovery #1432 * merge PR: more gracefull handling of complete retransmits #1433 diff --git a/src/app.cpp b/src/app.cpp index 0bead49e..f53af865 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -472,6 +472,7 @@ void app:: zeroIvValues(bool checkAvail, bool skipYieldDay) { continue; } + changed = true; record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); for(uint8_t ch = 0; ch <= iv->channels; ch++) { uint8_t pos = 0; @@ -494,10 +495,8 @@ void app:: zeroIvValues(bool checkAvail, bool skipYieldDay) { iv->setValue(pos, rec, 0.0f); } iv->resetAlarms(); - iv->doCalculations(); } - changed = true; } if(changed) diff --git a/src/defines.h b/src/defines.h index edcde7a0..fc4988e6 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 84 +#define VERSION_PATCH 85 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 50b4267c..b7fb00a1 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -407,23 +407,17 @@ class Inverter { bool isAvailable() { bool avail = false; - if((recordMeas.ts == 0) && (recordInfo.ts == 0) && (recordConfig.ts == 0) && (recordAlarm.ts == 0)) + if(recordMeas.ts == 0) return false; - if((*timestamp - recordMeas.ts) < INVERTER_INACT_THRES_SEC) - avail = true; - if((*timestamp - recordInfo.ts) < INVERTER_INACT_THRES_SEC) - avail = true; - if((*timestamp - recordConfig.ts) < INVERTER_INACT_THRES_SEC) - avail = true; - if((*timestamp - recordAlarm.ts) < INVERTER_INACT_THRES_SEC) + if(((*timestamp) - recordMeas.ts) < INVERTER_INACT_THRES_SEC) avail = true; if(avail) { if(status < InverterStatus::PRODUCING) status = InverterStatus::STARTING; } else { - if((*timestamp - recordMeas.ts) > INVERTER_OFF_THRES_SEC) { + if(((*timestamp) - recordMeas.ts) > INVERTER_OFF_THRES_SEC) { if(status != InverterStatus::OFF) { status = InverterStatus::OFF; actPowerLimit = 0xffff; // power limit will be read once inverter becomes available diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index c3ae3814..c15c9799 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -75,6 +75,7 @@ class PubMqttIvData { mTotalFound = false; mSendTotalYd = true; mAllTotalFound = true; + mAtLeastOneWasntSent = false; if(!mSendList->empty()) { mCmd = mSendList->front().cmd; mIvSend = mSendList->front().iv; @@ -122,7 +123,7 @@ class PubMqttIvData { mIv->isProducing(); // recalculate status mState = SEND_DATA; - } else if(mSendTotals && mTotalFound) { + } else if(mSendTotals && mTotalFound && mAtLeastOneWasntSent) { if(mYldTotalStore > mTotal[2]) mSendTotalYd = false; // don't send yield total if last value was greater else @@ -177,6 +178,7 @@ class PubMqttIvData { } if (MqttSentStatus::LAST_SUCCESS_SENT == rec->mqttSentStatus) { + mAtLeastOneWasntSent = true; if(InverterDevInform_All == mCmd) { snprintf(mSubTopic.data(), mSubTopic.size(), "%s/firmware", mIv->config->name); snprintf(mVal.data(), mVal.size(), "{\"version\":%d,\"build_year\":\"%d\",\"build_month_day\":%d,\"build_hour_min\":%d,\"bootloader\":%d}", @@ -282,7 +284,8 @@ class PubMqttIvData { uint8_t mCmd = 0; uint8_t mLastIvId = 0; - bool mSendTotals = false, mTotalFound = false, mAllTotalFound = false, mSendTotalYd = false; + bool mSendTotals = false, mTotalFound = false, mAllTotalFound = false; + bool mSendTotalYd = false, mAtLeastOneWasntSent = false; float mTotal[5], mYldTotalStore = 0; Inverter<> *mIv = nullptr, *mIvSend = nullptr; diff --git a/src/web/html/serial.html b/src/web/html/serial.html index 83e614c8..ff63772c 100644 --- a/src/web/html/serial.html +++ b/src/web/html/serial.html @@ -35,7 +35,7 @@ var hrs = parseInt(up / 3600) % 24; var min = parseInt(up / 60) % 60; var sec = up % 60; - document.getElementById("uptime").innerHTML = days + " Days, " + document.getElementById("uptime").innerHTML = days + " {#DAYS}, " + ("0"+hrs).substr(-2) + ":" + ("0"+min).substr(-2) + ":" + ("0"+sec).substr(-2); diff --git a/src/web/lang.json b/src/web/lang.json index 066370c5..727eadcd 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -898,6 +898,12 @@ "en": "uptime", "de": "Laufzeit" } +, + { + "token": "DAYS", + "en": "days", + "de": "Tage" + } ] }, { @@ -986,7 +992,7 @@ { "token": "NIGHT_TIME", "en": "Night time, inverter polling disabled", - "de": "Wechselrichterabfrage deaktivert (Nacht)" + "de": "Wechselrichterabfrage deaktiviert (Nacht)" }, { "token": "PAUSED_AT", From 6d887e15402f88565aa2bd4f7f3c78b41a735332 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 24 Feb 2024 00:23:29 +0100 Subject: [PATCH 007/201] 0.8.86 * RestAPI check for parent element to be JsonObject #1449 * fix translation #1448 #1442 * fix reset values when inverter status is 'not available' #1035 #1437 --- src/CHANGES.md | 5 ++++ src/app.cpp | 2 +- src/defines.h | 2 +- src/web/RestApi.h | 52 +++++++++++++++++++++------------------- src/web/html/serial.html | 6 ++--- src/web/lang.json | 18 ++++++++++++-- 6 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 003c8cef..58c229c1 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.8.86 - 2024-02-23 +* RestAPI check for parent element to be JsonObject #1449 +* fix translation #1448 #1442 +* fix reset values when inverter status is 'not available' #1035 #1437 + ## 0.8.85 - 2024-02-22 * possible fix of MqTT fix "total values are sent to often" #1421 * fix translation #1442 diff --git a/src/app.cpp b/src/app.cpp index f53af865..bad880f5 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -468,7 +468,7 @@ void app:: zeroIvValues(bool checkAvail, bool skipYieldDay) { continue; // skip to next inverter if (checkAvail) { - if (!iv->isAvailable()) + if (iv->isAvailable()) continue; } diff --git a/src/defines.h b/src/defines.h index fc4988e6..5f4344b5 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 85 +#define VERSION_PATCH 86 //------------------------------------- typedef struct { diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 09bba06e..622ea2d8 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -141,7 +141,7 @@ class RestApi { DPRINTLN(DBG_VERBOSE, "onApiPostBody"); if(0 == index) { - if(NULL != mTmpBuf) + if(nullptr != mTmpBuf) delete[] mTmpBuf; mTmpBuf = new uint8_t[total+1]; mTmpSize = total; @@ -154,36 +154,40 @@ class RestApi { DynamicJsonDocument json(1000); - DeserializationError err = deserializeJson(json, reinterpret_cast(mTmpBuf), mTmpSize); - JsonObject obj = json.as(); - AsyncJsonResponse* response = new AsyncJsonResponse(false, 200); JsonObject root = response->getRoot(); - root[F("success")] = (err) ? false : true; - if(!err) { - String path = request->url().substring(5); - if(path == "ctrl") - root[F("success")] = setCtrl(obj, root, request->client()->remoteIP().toString().c_str()); - else if(path == "setup") - root[F("success")] = setSetup(obj, root, request->client()->remoteIP().toString().c_str()); - else { - root[F("success")] = false; - root[F("error")] = F(PATH_NOT_FOUND) + path; - } - } else { - switch (err.code()) { - case DeserializationError::Ok: break; - case DeserializationError::IncompleteInput: root[F("error")] = F(INCOMPLETE_INPUT); break; - case DeserializationError::InvalidInput: root[F("error")] = F(INVALID_INPUT); break; - case DeserializationError::NoMemory: root[F("error")] = F(NOT_ENOUGH_MEM); break; - default: root[F("error")] = F(DESER_FAILED); break; + DeserializationError err = deserializeJson(json, reinterpret_cast(mTmpBuf), mTmpSize); + if(!json.is()) + root[F("error")] = F(DESER_FAILED); + else { + 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(obj, root, request->client()->remoteIP().toString().c_str()); + else if(path == "setup") + root[F("success")] = setSetup(obj, root, request->client()->remoteIP().toString().c_str()); + else { + root[F("success")] = false; + root[F("error")] = F(PATH_NOT_FOUND) + path; + } + } else { + switch (err.code()) { + case DeserializationError::Ok: break; + case DeserializationError::IncompleteInput: root[F("error")] = F(INCOMPLETE_INPUT); break; + case DeserializationError::InvalidInput: root[F("error")] = F(INVALID_INPUT); break; + case DeserializationError::NoMemory: root[F("error")] = F(NOT_ENOUGH_MEM); break; + default: root[F("error")] = F(DESER_FAILED); break; + } } } response->setLength(); request->send(response); delete[] mTmpBuf; - mTmpBuf = NULL; + mTmpBuf = nullptr; } void getNotFound(JsonObject obj, String url) { @@ -974,7 +978,7 @@ class RestApi { uint32_t mTimezoneOffset = 0; uint32_t mHeapFree = 0, mHeapFreeBlk = 0; uint8_t mHeapFrag = 0; - uint8_t *mTmpBuf = NULL; + uint8_t *mTmpBuf = nullptr; uint32_t mTmpSize = 0; }; diff --git a/src/web/html/serial.html b/src/web/html/serial.html index ff63772c..a3e48a04 100644 --- a/src/web/html/serial.html +++ b/src/web/html/serial.html @@ -65,7 +65,7 @@ }); document.getElementById("scroll").addEventListener("click", function() { mAutoScroll = !mAutoScroll; - this.value = (mAutoScroll) ? "autoscroll" : "manual scroll"; + this.value = (mAutoScroll) ? "{#BTN_AUTOSCROLL}" : "{#BTN_MANUALSCROLL}"; }); document.getElementById("copy").addEventListener("click", function() { con.value = version + " - " + build + "\n---------------\n" + con.value; @@ -80,10 +80,10 @@ try { return document.execCommand("copy"); // Security exception may be thrown by some browsers. } catch (ex) { - alert("Copy to clipboard failed" + ex); + alert("CLIPBOARD_FAILED " + ex); } finally { document.body.removeChild(ta); - alert("Copied to clipboard"); + alert("{#COPIED_TO_CLIPBOARD}"); } } }); diff --git a/src/web/lang.json b/src/web/lang.json index 727eadcd..af888682 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -883,6 +883,11 @@ "en": "autoscroll", "de": "automatisch scrollen" }, + { + "token": "BTN_MANUALSCROLL", + "en": "manual scroll", + "de": "manuell scrollen" + }, { "token": "BTN_COPY", "en": "copy", @@ -897,12 +902,21 @@ "token": "UPTIME", "en": "uptime", "de": "Laufzeit" - } -, + }, { "token": "DAYS", "en": "days", "de": "Tage" + }, + { + "token": "COPIED_TO_CLIPBOARD", + "en": "Copied to clipboard", + "de": "in die Zwischenablage kopiert" + }, + { + "token": "CLIPBOARD_FAILED", + "en": "Copy failed", + "de": "kopieren fehlgeschlagen" } ] }, From e2ab5dacd4cfd1c4bd6ca7fc88276e178712edaa Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 24 Feb 2024 01:30:26 +0100 Subject: [PATCH 008/201] 0.8.86 * update workflow --- .github/workflows/compile_development.yml | 26 +++++++++++++++++++++++ scripts/buildManifest.py | 20 ++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index c15bd883..bd692598 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -164,9 +164,35 @@ jobs: env: VERSION: ${{ steps.version_name.outputs.name }} + + - name: Create ESP Web Tools Manifest + working-directory: src + run: python ../scripts/buildManifest.py + + - name: Copy install html + run: mv ../scripts/gh-action-dev-build-flash.html firmware/install.html + + - name: Copy Changes.md + run: mv CHANGES.md firmware/CHANGES.md + + - name: Rename firmware directory run: mv firmware ${{ steps.version_name.outputs.name }} + - name: delete environment Artifacts + uses: geekyeggo/delete-artifact@v4 + with: + name: dev-* + + - name: Create Artifact + uses: actions/upload-artifact@v4 + with: + name: dev-${{ steps.version_name.outputs.name }} + path: | + ${{ steps.version_name.outputs.name }}/* + manual/User_Manual.md + manual/Getting_Started.md + - name: Deploy uses: nogsantos/scp-deploy@master with: diff --git a/scripts/buildManifest.py b/scripts/buildManifest.py index 2664a39f..36e47ac0 100644 --- a/scripts/buildManifest.py +++ b/scripts/buildManifest.py @@ -36,9 +36,27 @@ def buildManifest(path, infile, outfile): esp32["parts"].append({"path": "ESP32/bootloader.bin", "offset": 4096}) esp32["parts"].append({"path": "ESP32/partitions.bin", "offset": 32768}) esp32["parts"].append({"path": "ESP32/ota.bin", "offset": 57344}) - esp32["parts"].append({"path": "ESP32/" + version[1] + "_" + sha + "_esp32.bin", "offset": 65536}) + esp32["parts"].append({"path": "ESP32/" + version[1] + "_" + sha + "_esp32-wroom32.bin", "offset": 65536}) data["builds"].append(esp32) + esp32s2 = {} + esp32s2["chipFamily"] = "ESP32-S2" + esp32s2["parts"] = [] + esp32s2["parts"].append({"path": "ESP32-S2/bootloader.bin", "offset": 4096}) + esp32s2["parts"].append({"path": "ESP32-S2/partitions.bin", "offset": 32768}) + esp32s2["parts"].append({"path": "ESP32-S2/ota.bin", "offset": 57344}) + esp32s2["parts"].append({"path": "ESP32-S2/" + version[1] + "_" + sha + "_esp32-s2-mini.bin", "offset": 65536}) + data["builds"].append(esp32s2) + + esp32s3 = {} + esp32s3["chipFamily"] = "ESP32-S3" + esp32s3["parts"] = [] + esp32s3["parts"].append({"path": "ESP32/bootloader.bin", "offset": 4096}) + esp32s3["parts"].append({"path": "ESP32/partitions.bin", "offset": 32768}) + esp32s3["parts"].append({"path": "ESP32/ota.bin", "offset": 57344}) + esp32s3["parts"].append({"path": "ESP32-S3/" + version[1] + "_" + sha + "_opendtufusion.bin", "offset": 65536}) + data["builds"].append(esp32s3) + esp8266 = {} esp8266["chipFamily"] = "ESP8266" esp8266["parts"] = [] From d4f49792454036aa0f9f4b0f953d9eb3d565d295 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 24 Feb 2024 01:42:33 +0100 Subject: [PATCH 009/201] 0.8.86 * fix workflow --- .github/workflows/compile_development.yml | 6 +++--- scripts/buildManifest.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index bd692598..3f89770c 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 build-en: - name: Build Environments (English) + name: Build (English) needs: check runs-on: ubuntu-latest continue-on-error: true @@ -77,7 +77,7 @@ jobs: path: firmware/* build-de: - name: Build Environments (German) + name: Build (German) needs: check runs-on: ubuntu-latest continue-on-error: true @@ -138,7 +138,7 @@ jobs: path: firmware/* deploy: - name: Deploy Environments + name: Update Artifacts / Deploy needs: [build-en, build-de] runs-on: ubuntu-latest continue-on-error: false diff --git a/scripts/buildManifest.py b/scripts/buildManifest.py index 36e47ac0..b91145cd 100644 --- a/scripts/buildManifest.py +++ b/scripts/buildManifest.py @@ -65,7 +65,7 @@ def buildManifest(path, infile, outfile): jsonString = json.dumps(data, indent=2) - fp = open(path + "firmware/" + outfile, "w") + fp = open(path + "../firmware/" + outfile, "w") fp.write(jsonString) fp.close() From e7d9a8ebcb2a1ca1bece6540a1598be2173f2bd7 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 24 Feb 2024 01:49:04 +0100 Subject: [PATCH 010/201] 0.8.86 * fix workflow --- .github/workflows/compile_development.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index 3f89770c..7f539871 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 build-en: - name: Build (English) + name: Build (EN) needs: check runs-on: ubuntu-latest continue-on-error: true @@ -77,7 +77,7 @@ jobs: path: firmware/* build-de: - name: Build (German) + name: Build (DE) needs: check runs-on: ubuntu-latest continue-on-error: true @@ -170,10 +170,10 @@ jobs: run: python ../scripts/buildManifest.py - name: Copy install html - run: mv ../scripts/gh-action-dev-build-flash.html firmware/install.html + run: mv scripts/gh-action-dev-build-flash.html firmware/install.html - name: Copy Changes.md - run: mv CHANGES.md firmware/CHANGES.md + run: mv src/CHANGES.md firmware/CHANGES.md - name: Rename firmware directory From 4f71ac014c3b866cd123e5783c35b8e85246ade4 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 25 Feb 2024 17:16:54 +0100 Subject: [PATCH 011/201] 0.8.87 * fix translations #1455 #1442 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/web/html/index.html | 4 ++-- src/web/html/serial.html | 2 +- src/web/lang.json | 10 ++++++++++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 58c229c1..4ca494f2 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.87 - 2024-02-25 +* fix translations #1455 #1442 + ## 0.8.86 - 2024-02-23 * RestAPI check for parent element to be JsonObject #1449 * fix translation #1448 #1442 diff --git a/src/defines.h b/src/defines.h index 5f4344b5..d3179469 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 86 +#define VERSION_PATCH 87 //------------------------------------- typedef struct { diff --git a/src/web/html/index.html b/src/web/html/index.html index 2611db5b..954ee012 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -70,9 +70,9 @@ var min = parseInt(up / 60) % 60; var sec = up % 60; var e = document.getElementById("uptime"); - e.innerHTML = days + " Day"; + e.innerHTML = days + " {#DAY}"; if(1 != days) - e.innerHTML += "s"; + e.innerHTML += "{#S}"; e.innerHTML += ", " + ("0"+hrs).substr(-2) + ":" + ("0"+min).substr(-2) + ":" + ("0"+sec).substr(-2); diff --git a/src/web/html/serial.html b/src/web/html/serial.html index a3e48a04..835f1766 100644 --- a/src/web/html/serial.html +++ b/src/web/html/serial.html @@ -80,7 +80,7 @@ try { return document.execCommand("copy"); // Security exception may be thrown by some browsers. } catch (ex) { - alert("CLIPBOARD_FAILED " + ex); + alert("{#CLIPBOARD_FAILED} " + ex); } finally { document.body.removeChild(ta); alert("{#COPIED_TO_CLIPBOARD}"); diff --git a/src/web/lang.json b/src/web/lang.json index af888682..7d9cdb43 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -993,6 +993,16 @@ "en": "Error", "de": "Fehler" }, + { + "token": "DAY", + "en": "day", + "de": "Tag" + }, + { + "token": "S", + "en": "s", + "de": "e" + }, { "token": "NTP_UNREACH", "en": "NTP timeserver unreachable", From 3b58522fd58df0ce14ba1ca615abd0ab18b758d2 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 29 Feb 2024 00:01:09 +0100 Subject: [PATCH 012/201] 0.8.88 * fix MqTT statistic data overflow #1458 * add HMS-400-1T support (serial number 1125...) #1460 * removed `yield efficiency` because the inverter already calculates correct #1243 --- src/CHANGES.md | 5 +++++ src/config/settings.h | 9 --------- src/defines.h | 2 +- src/hm/hmInverter.h | 4 ++-- src/hm/hmSystem.h | 8 ++++---- src/platformio.ini | 2 +- src/publisher/pubMqttIvData.h | 2 +- src/web/RestApi.h | 1 - src/web/html/setup.html | 9 +++------ src/web/lang.json | 5 ----- src/web/web.h | 1 - 11 files changed, 17 insertions(+), 31 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 4ca494f2..c5650f0d 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.8.88 - 2024-02-28 +* fix MqTT statistic data overflow #1458 +* add HMS-400-1T support (serial number 1125...) #1460 +* removed `yield efficiency` because the inverter already calculates correct #1243 + ## 0.8.87 - 2024-02-25 * fix translations #1455 #1442 diff --git a/src/config/settings.h b/src/config/settings.h index 18725b48..9c9b48c2 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -161,7 +161,6 @@ typedef struct { bool rstValsCommStop; bool rstMaxValsMidNight; bool startWithoutTime; - float yieldEffiency; bool readGrid; } cfgInst_t; @@ -452,7 +451,6 @@ class settings { mCfg.inst.rstValsCommStop = false; mCfg.inst.startWithoutTime = false; mCfg.inst.rstMaxValsMidNight = false; - mCfg.inst.yieldEffiency = 1.0f; mCfg.inst.readGrid = true; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { @@ -763,7 +761,6 @@ class settings { obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop; obj[F("strtWthtTime")] = (bool)mCfg.inst.startWithoutTime; obj[F("rstMaxMidNight")] = (bool)mCfg.inst.rstMaxValsMidNight; - obj[F("yldEff")] = mCfg.inst.yieldEffiency; obj[F("rdGrid")] = (bool)mCfg.inst.readGrid; } else { @@ -774,13 +771,7 @@ class settings { getVal(obj, F("rstComStop"), &mCfg.inst.rstValsCommStop); getVal(obj, F("strtWthtTime"), &mCfg.inst.startWithoutTime); getVal(obj, F("rstMaxMidNight"), &mCfg.inst.rstMaxValsMidNight); - getVal(obj, F("yldEff"), &mCfg.inst.yieldEffiency); getVal(obj, F("rdGrid"), &mCfg.inst.readGrid); - - if(mCfg.inst.yieldEffiency < 0.5) - mCfg.inst.yieldEffiency = 1.0f; - else if(mCfg.inst.yieldEffiency > 1.0f) - mCfg.inst.yieldEffiency = 1.0f; } JsonArray ivArr; diff --git a/src/defines.h b/src/defines.h index d3179469..8dcfe988 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 87 +#define VERSION_PATCH 88 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index b7fb00a1..1890d142 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -300,9 +300,9 @@ class Inverter { // temperature, Qvar, and power factor are a signed values rec->record[pos] = ((REC_TYP)((int16_t)val)) / (REC_TYP)(div); } else if (FLD_YT == rec->assign[pos].fieldId) { - rec->record[pos] = ((REC_TYP)(val) / (REC_TYP)(div) * generalConfig->yieldEffiency) + ((REC_TYP)config->yieldCor[rec->assign[pos].ch-1]); + rec->record[pos] = ((REC_TYP)(val) / (REC_TYP)(div)) + ((REC_TYP)config->yieldCor[rec->assign[pos].ch-1]); } else if (FLD_YD == rec->assign[pos].fieldId) { - float actYD = (REC_TYP)(val) / (REC_TYP)(div) * generalConfig->yieldEffiency; + float actYD = (REC_TYP)(val) / (REC_TYP)(div); uint8_t idx = rec->assign[pos].ch - 1; if (mLastYD[idx] > actYD) mOffYD[idx] += mLastYD[idx]; diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 7e79f30a..e9b839be 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -31,6 +31,7 @@ class HmSystem { if((iv->config->serial.b[5] == 0x11) || (iv->config->serial.b[5] == 0x10)) { switch(iv->config->serial.b[4]) { case 0x24: // HMS-500 + case 0x25: // HMS-400 case 0x22: case 0x21: iv->type = INV_TYPE_1CH; break; @@ -51,15 +52,14 @@ class HmSystem { } if(iv->config->serial.b[5] == 0x11) { - if((iv->config->serial.b[4] & 0x0f) == 0x04) { + if(((iv->config->serial.b[4] & 0x0f) == 0x04) || ((iv->config->serial.b[4] & 0x0f) == 0x05)) { iv->ivGen = IV_HMS; iv->ivRadioType = INV_RADIO_TYPE_CMT; } else { iv->ivGen = IV_HM; iv->ivRadioType = INV_RADIO_TYPE_NRF; } - } - else if((iv->config->serial.b[4] & 0x03) == 0x02) { // MI 3rd Gen -> same as HM + } else if((iv->config->serial.b[4] & 0x03) == 0x02) { // MI 3rd Gen -> same as HM iv->ivGen = IV_HM; iv->ivRadioType = INV_RADIO_TYPE_NRF; } else { // MI 2nd Gen @@ -82,7 +82,7 @@ class HmSystem { DPRINT(DBG_INFO, "added inverter "); if(iv->config->serial.b[5] == 0x11) { - if((iv->config->serial.b[4] & 0x0f) == 0x04) + if(((iv->config->serial.b[4] & 0x0f) == 0x04) || ((iv->config->serial.b[4] & 0x0f) == 0x05)) DBGPRINT("HMS"); else DBGPRINT("HM"); diff --git a/src/platformio.ini b/src/platformio.ini index f949aa37..7130bf4c 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -350,7 +350,7 @@ build_flags = ${env.build_flags} -DDEF_LED1=17 -DLED_ACTIVE_HIGH -DARDUINO_USB_MODE=1 - #-DARDUINO_USB_CDC_ON_BOOT=1 + -DARDUINO_USB_CDC_ON_BOOT=1 monitor_filters = esp32_exception_decoder, colorize diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index c15c9799..ac8b3bf0 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -293,7 +293,7 @@ class PubMqttIvData { bool mRTRDataHasBeenSent = false; std::array mSubTopic; - std::array mVal; + std::array mVal; std::queue *mSendList = nullptr; }; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 622ea2d8..0120375a 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -484,7 +484,6 @@ class RestApi { obj[F("strtWthtTm")] = (bool)mConfig->inst.startWithoutTime; obj[F("rdGrid")] = (bool)mConfig->inst.readGrid; obj[F("rstMaxMid")] = (bool)mConfig->inst.rstMaxValsMidNight; - obj[F("yldEff")] = mConfig->inst.yieldEffiency; } void getInverter(JsonObject obj, uint8_t id) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 47d935b9..57dc6a8c 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -157,10 +157,6 @@
{#INV_READ_GRID_PROFILE}
-
-
{#INV_YIELD_EFF}
-
-
@@ -605,7 +601,7 @@ } function ivGlob(obj) { - for(var i of [["invInterval", "interval"], ["yldEff", "yldEff"]]) + for(var i of [["invInterval", "interval"]]) document.getElementsByName(i[0])[0].value = obj[i[1]]; for(var i of ["Mid", "ComStop", "NotAvail", "MaxMid"]) document.getElementsByName("invRst"+i)[0].checked = obj["rst" + i]; @@ -786,7 +782,8 @@ case 0x1000: nrf = true; break; case 0x1100: switch(sn & 0x000f) { - case 0x0004: nrf = false; break; + case 0x0004: + case 0x0005: nrf = false; break; default: nrf = true; break; } break; diff --git a/src/web/lang.json b/src/web/lang.json index 7d9cdb43..eefd0516 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -323,11 +323,6 @@ "en": "Read Grid Profile", "de": "Grid-Profil auslesen" }, - { - "token": "INV_YIELD_EFF", - "en": "Yield Efficiency (default 1.0)", - "de": "Ertragseffizienz (Standard 1.0)" - }, { "token": "NTP_INTERVAL", "en": "NTP Interval (in minutes, min. 5 minutes)", diff --git a/src/web/web.h b/src/web/web.h index 8495ba23..de4938f1 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -483,7 +483,6 @@ class Web { mConfig->inst.startWithoutTime = (request->arg("strtWthtTm") == "on"); mConfig->inst.readGrid = (request->arg("rdGrid") == "on"); mConfig->inst.rstMaxValsMidNight = (request->arg("invRstMaxMid") == "on"); - mConfig->inst.yieldEffiency = (request->arg("yldEff")).toFloat(); // pinout From ec88dd19a56c061e51ea7da433f10cfeca19f1b2 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 29 Feb 2024 00:02:15 +0100 Subject: [PATCH 013/201] 0.8.88 platformio.ini fix --- src/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platformio.ini b/src/platformio.ini index 7130bf4c..f949aa37 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -350,7 +350,7 @@ build_flags = ${env.build_flags} -DDEF_LED1=17 -DLED_ACTIVE_HIGH -DARDUINO_USB_MODE=1 - -DARDUINO_USB_CDC_ON_BOOT=1 + #-DARDUINO_USB_CDC_ON_BOOT=1 monitor_filters = esp32_exception_decoder, colorize From 2bc6610a83f7f570c85be0472512ff86ab02c2d1 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 29 Feb 2024 00:04:45 +0100 Subject: [PATCH 014/201] 0.8.88 * merge PR: Remove hint to INV_RESET_MIDNIGHT resp. INV_PAUSE_DURING_NIGHT #1431 --- src/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CHANGES.md b/src/CHANGES.md index c5650f0d..2cd2300f 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -4,6 +4,7 @@ * fix MqTT statistic data overflow #1458 * add HMS-400-1T support (serial number 1125...) #1460 * removed `yield efficiency` because the inverter already calculates correct #1243 +* merge PR: Remove hint to INV_RESET_MIDNIGHT resp. INV_PAUSE_DURING_NIGHT #1431 ## 0.8.87 - 2024-02-25 * fix translations #1455 #1442 From f2f05a4de9ffc8823d3197d2a4216fe031e5f3ca Mon Sep 17 00:00:00 2001 From: VArt67 <132200455+VArt67@users.noreply.github.com> Date: Thu, 29 Feb 2024 22:07:25 +0100 Subject: [PATCH 015/201] 1st merge of reworked history.html implementation --- src/app.h | 23 +++ src/appInterface.h | 6 +- src/plugins/history.h | 214 ++++++++++++++++++-- src/web/RestApi.h | 137 ++++++++++++- src/web/html/colorBright.css | 4 + src/web/html/colorDark.css | 4 + src/web/html/history.html | 378 ++++++++++++++++++++++++++++++----- src/web/html/style.css | 24 ++- src/web/lang.json | 25 ++- 9 files changed, 731 insertions(+), 84 deletions(-) diff --git a/src/app.h b/src/app.h index b16d7aeb..a6960d89 100644 --- a/src/app.h +++ b/src/app.h @@ -314,6 +314,14 @@ class app : public IApp, public ah::Scheduler { #endif } + uint32_t getHistoryPeriode(uint8_t type) override { + #if defined(ENABLE_HISTORY) + return mHistory.getPeriode((HistoryStorageType)type); + #else + return 0; + #endif + } + uint16_t getHistoryMaxDay() override { #if defined(ENABLE_HISTORY) return mHistory.getMaximumDay(); @@ -322,6 +330,21 @@ class app : public IApp, public ah::Scheduler { #endif } + uint32_t getHistoryLastValueTs(uint8_t type) override { + #if defined(ENABLE_HISTORY) + return mHistory.getLastValueTs((HistoryStorageType)type); + #else + return 0; + #endif + } + #if defined(ENABLE_HISTORY_LOAD_DATA) + void addValueToHistory(uint8_t historyType, uint8_t valueType, uint32_t value) override { + #if defined(ENABLE_HISTORY) + return mHistory.addValue((HistoryStorageType)historyType, valueType, value); + #endif + } + #endif + private: #define CHECK_AVAIL true #define SKIP_YIELD_DAY true diff --git a/src/appInterface.h b/src/appInterface.h index 536455e0..8a18cf8d 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -67,8 +67,12 @@ class IApp { virtual bool isProtected(const char *clientIp, const char *token, bool askedFromWeb) const = 0; virtual uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0; + virtual uint32_t getHistoryPeriode(uint8_t type) = 0; virtual uint16_t getHistoryMaxDay() = 0; - + virtual uint32_t getHistoryLastValueTs(uint8_t type) = 0; + #if defined(ENABLE_HISTORY_LOAD_DATA) + virtual void addValueToHistory(uint8_t historyType, uint8_t valueType, uint32_t value) = 0; + #endif virtual void* getRadioObj(bool nrf) = 0; }; diff --git a/src/plugins/history.h b/src/plugins/history.h index 5076e295..c44eae5d 100644 --- a/src/plugins/history.h +++ b/src/plugins/history.h @@ -17,6 +17,7 @@ enum class HistoryStorageType : uint8_t { POWER, + POWER_DAY, YIELD }; @@ -25,14 +26,18 @@ class HistoryData { private: struct storage_t { uint16_t refreshCycle = 0; - uint16_t loopCnt = 0; - uint16_t listIdx = 0; // index for next Element to write into WattArr - uint16_t dispIdx = 0; // index for 1st Element to display from WattArr - bool wrapped = false; + uint16_t loopCnt; + uint16_t listIdx; // index for next Element to write into WattArr // ring buffer for watt history std::array data; - storage_t() { data.fill(0); } + void reset() { + loopCnt = 0; + listIdx = 0; + for(uint16_t i = 0; i < (HISTORY_DATA_ARR_LENGTH + 1); i++) { + data[i] = 0; + } + } }; public: @@ -42,8 +47,14 @@ class HistoryData { mConfig = config; mTs = ts; + mCurPwr.reset(); mCurPwr.refreshCycle = mConfig->inst.sendInterval; - //mYieldDay.refreshCycle = 60; + mCurPwrDay.reset(); + mCurPwrDay.refreshCycle = mConfig->inst.sendInterval; + mYieldDay.reset(); + mYieldDay.refreshCycle = 60; + mLastValueTs = 0; + mPgPeriod=0; } void tickerSecond() { @@ -51,6 +62,8 @@ class HistoryData { float curPwr = 0; float maxPwr = 0; float yldDay = -0.1; + uint32_t ts = 0; + for (uint8_t i = 0; i < mSys->getNumInverters(); i++) { Inverter<> *iv = mSys->getInverterByPos(i); record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); @@ -59,46 +72,198 @@ class HistoryData { curPwr += iv->getChannelFieldValue(CH0, FLD_PAC, rec); maxPwr += iv->getChannelFieldValue(CH0, FLD_MP, rec); yldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec); + if (rec->ts > ts) + ts = rec->ts; } if ((++mCurPwr.loopCnt % mCurPwr.refreshCycle) == 0) { mCurPwr.loopCnt = 0; - if (curPwr > 0) + if (curPwr > 0) { + mLastValueTs = ts; addValue(&mCurPwr, roundf(curPwr)); + } if (maxPwr > 0) mMaximumDay = roundf(maxPwr); } - /*if((++mYieldDay.loopCnt % mYieldDay.refreshCycle) == 0) { - if (*mTs > mApp->getSunset()) { + if ((++mCurPwrDay.loopCnt % mCurPwrDay.refreshCycle) == 0) { + mCurPwrDay.loopCnt = 0; + if (curPwr > 0) { + mLastValueTs = ts; + addValueDay(&mCurPwrDay, roundf(curPwr)); + } + } + + if((++mYieldDay.loopCnt % mYieldDay.refreshCycle) == 0) { + mYieldDay.loopCnt = 0; + if (*mTs > mApp->getSunset()) + { if ((!mDayStored) && (yldDay > 0)) { addValue(&mYieldDay, roundf(yldDay)); mDayStored = true; } - } else if (*mTs > mApp->getSunrise()) + } + else if (*mTs > mApp->getSunrise()) mDayStored = false; - }*/ + } } uint16_t valueAt(HistoryStorageType type, uint16_t i) { - //storage_t *s = (HistoryStorageType::POWER == type) ? &mCurPwr : &mYieldDay; - storage_t *s = &mCurPwr; - uint16_t idx = (s->dispIdx + i) % HISTORY_DATA_ARR_LENGTH; + storage_t *s=NULL; + uint16_t idx=i; + DPRINTLN(DBG_VERBOSE, F("valueAt ") + String((uint8_t)type) + " i=" + String(i)); + + switch (type) { + case HistoryStorageType::POWER: + s = &mCurPwr; + idx = (s->listIdx + i) % HISTORY_DATA_ARR_LENGTH; + break; + case HistoryStorageType::POWER_DAY: + s = &mCurPwrDay; + idx = i; + break; + case HistoryStorageType::YIELD: + s = &mYieldDay; + idx = (s->listIdx + i) % HISTORY_DATA_ARR_LENGTH; + break; + } + if (s) return s->data[idx]; + return 0; } uint16_t getMaximumDay() { return mMaximumDay; } + uint32_t getLastValueTs(HistoryStorageType type) { + DPRINTLN(DBG_VERBOSE, F("getLastValueTs ") + String((uint8_t)type)); + if (type == HistoryStorageType::POWER_DAY) + return mPgEndTime; + return mLastValueTs; + } + + uint32_t getPeriode(HistoryStorageType type) { + DPRINTLN(DBG_VERBOSE, F("getPeriode ") + String((uint8_t)type)); + switch (type) { + case HistoryStorageType::POWER: + return mCurPwr.refreshCycle; + break; + case HistoryStorageType::POWER_DAY: + return mPgPeriod / HISTORY_DATA_ARR_LENGTH; + break; + case HistoryStorageType::YIELD: + return (60 * 60 * 24); // 1 day + break; + } + return 0; + } + + #if defined(ENABLE_HISTORY_LOAD_DATA) + /* For filling data from outside */ + void addValue(HistoryStorageType historyType, uint8_t valueType, uint32_t value) { + if (valueType<2) { + storage_t *s=NULL; + switch (historyType) { + case HistoryStorageType::POWER: + s = &mCurPwr; + break; + case HistoryStorageType::POWER_DAY: + s = &mCurPwrDay; + break; + case HistoryStorageType::YIELD: + s = &mYieldDay; + break; + } + if (s) + { + if (valueType==0) + addValue(s, value); + if (valueType==1) + { + if (historyType == HistoryStorageType::POWER) + s->refreshCycle = value; + if (historyType == HistoryStorageType::POWER_DAY) + mPgPeriod = value * HISTORY_DATA_ARR_LENGTH; + } + } + return; + } + if (valueType == 2) + { + if (historyType == HistoryStorageType::POWER) + mLastValueTs = value; + if (historyType == HistoryStorageType::POWER_DAY) + mPgEndTime = value; + } + } + #endif + private: void addValue(storage_t *s, uint16_t value) { - if (s->wrapped) // after 1st time array wrap we have to increase the display index - s->dispIdx = (s->listIdx + 1) % (HISTORY_DATA_ARR_LENGTH); s->data[s->listIdx] = value; s->listIdx = (s->listIdx + 1) % (HISTORY_DATA_ARR_LENGTH); - if (s->listIdx == 0) - s->wrapped = true; + } + + void addValueDay(storage_t *s, uint16_t value) { + DPRINTLN(DBG_VERBOSE, F("addValueDay ") + String(value)); + bool storeStartEndTimes = false; + bool store_entry = false; + uint32_t pGraphStartTime = mApp->getSunrise(); + uint32_t pGraphEndTime = mApp->getSunset(); + uint32_t utcTs = mApp->getTimestamp(); + switch (mPgState) { + case PowerGraphState::NO_TIME_SYNC: + if ((pGraphStartTime > 0) + && (pGraphEndTime > 0) // wait until period data is available ... + && (utcTs >= pGraphStartTime) + && (utcTs < pGraphEndTime)) // and current time is in period + { + storeStartEndTimes = true; // period was received -> store + store_entry = true; + mPgState = PowerGraphState::IN_PERIOD; + } + break; + case PowerGraphState::IN_PERIOD: + if (utcTs > mPgEndTime) // check if end of day is reached ... + mPgState = PowerGraphState::WAIT_4_NEW_PERIOD; // then wait for new period setting + else + store_entry = true; + break; + case PowerGraphState::WAIT_4_NEW_PERIOD: + if ((mPgStartTime != pGraphStartTime) || (mPgEndTime != pGraphEndTime)) { // wait until new time period was received ... + storeStartEndTimes = true; // and store it for next period + mPgState = PowerGraphState::WAIT_4_RESTART; + } + break; + case PowerGraphState::WAIT_4_RESTART: + if ((utcTs >= mPgStartTime) && (utcTs < mPgEndTime)) { // wait until current time is in period again ... + mCurPwrDay.reset(); // then reset power graph data + store_entry = true; + mPgState = PowerGraphState::IN_PERIOD; + mCurPwr.reset(); // also reset "last values" graph + mMaximumDay = 0; // and the maximum of the (last) day + } + break; + } + + // store start and end times of current time period and calculate period length + if (storeStartEndTimes) { + mPgStartTime = pGraphStartTime; + mPgEndTime = pGraphEndTime; + mPgPeriod = pGraphEndTime - pGraphStartTime; // time period of power graph in sec for scaling of x-axis + } + + if (store_entry) { + DPRINTLN(DBG_VERBOSE, F("addValueDay store_entry") + String(value)); + if (mPgPeriod) { + uint16_t pgPos = (utcTs - mPgStartTime) * (HISTORY_DATA_ARR_LENGTH - 1) / mPgPeriod; + s->listIdx = std::min(pgPos, (uint16_t)(HISTORY_DATA_ARR_LENGTH - 1)); + } else + s->listIdx = 0; + DPRINTLN(DBG_VERBOSE, F("addValueDay store_entry idx=") + String(s->listIdx)); + s->data[s->listIdx] = std::max(s->data[s->listIdx], value); // update current datapoint to maximum of all seen values + } } private: @@ -109,8 +274,21 @@ class HistoryData { uint32_t *mTs = nullptr; storage_t mCurPwr; + storage_t mCurPwrDay; + storage_t mYieldDay; bool mDayStored = false; uint16_t mMaximumDay = 0; + uint32_t mLastValueTs = 0; + enum class PowerGraphState { + NO_TIME_SYNC, + IN_PERIOD, + WAIT_4_NEW_PERIOD, + WAIT_4_RESTART + }; + PowerGraphState mPgState = PowerGraphState::NO_TIME_SYNC; + uint32_t mPgStartTime = 0; + uint32_t mPgEndTime = 0; + uint32_t mPgPeriod = 0; // seconds }; #endif /*ENABLE_HISTORY*/ diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 0120375a..e541cdff 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -49,6 +49,12 @@ class RestApi { mRadioCmt = (CmtRadio<>*)mApp->getRadioObj(false); #endif mConfig = config; + #if defined(ENABLE_HISTORY_LOAD_DATA) + //Vart67: Debugging history graph (loading data into graph storage + mSrv->on("/api/addYDHist", + HTTP_POST, std::bind(&RestApi::onApiPost, this, std::placeholders::_1), + std::bind(&RestApi::onApiPostYDHist,this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)); + #endif mSrv->on("/api", HTTP_POST, std::bind(&RestApi::onApiPost, this, std::placeholders::_1)).onBody( std::bind(&RestApi::onApiPostBody, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); mSrv->on("/api", HTTP_GET, std::bind(&RestApi::onApi, this, std::placeholders::_1)); @@ -103,6 +109,8 @@ class RestApi { #endif /* !defined(ETHERNET) */ else if(path == "live") getLive(request,root); else if (path == "powerHistory") getPowerHistory(request, root); + else if (path == "powerHistoryDay") getPowerHistoryDay(request, root); + else if (path == "yieldDayHistory") getYieldDayHistory(request, root); else { if(path.substring(0, 12) == "inverter/id/") getInverter(root, request->url().substring(17).toInt()); @@ -137,7 +145,94 @@ class RestApi { #endif } - void onApiPostBody(AsyncWebServerRequest *request, const uint8_t *data, size_t len, size_t index, size_t total) { + #if defined(ENABLE_HISTORY_LOAD_DATA) + // VArt67: For debugging history graph. Loading data into graph + void onApiPostYDHist(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, size_t final) { + uint32_t total = request->contentLength(); + DPRINTLN(DBG_DEBUG, "[onApiPostYieldDHistory ] " + filename + " index:" + index + " len:" + len + " total:" + total + " final:" + final); + + if (0 == index) { + if (NULL != mTmpBuf) + delete[] mTmpBuf; + mTmpBuf = new uint8_t[total + 1]; + mTmpSize = total; + } + if (mTmpSize >= (len + index)) + memcpy(&mTmpBuf[index], data, len); + + if (!final) + return; // not last frame - nothing to do + + mTmpSize = len + index; // correct the total size + mTmpBuf[mTmpSize] = 0; + + #ifndef ESP32 + DynamicJsonDocument json(ESP.getMaxFreeBlockSize() - 512); // need some memory on heap + #else + DynamicJsonDocument json(12000)); // does this work? I have no ESP32 :-( + #endif + DeserializationError err = deserializeJson(json, (const char *)mTmpBuf, mTmpSize); + json.shrinkToFit(); + JsonObject obj = json.as(); + + // Debugging + // mTmpBuf[mTmpSize] = 0; + // DPRINTLN(DBG_DEBUG, (const char *)mTmpBuf); + + if (!err && obj) { + // insert data into yieldDayHistory object + HistoryStorageType dataType; + if (obj["maxDay"] > 0) // this is power history data + { + dataType = HistoryStorageType::POWER; + if (obj["refresh"] > 60) + dataType = HistoryStorageType::POWER_DAY; + + } + else + dataType = HistoryStorageType::YIELD; + + size_t cnt = obj[F("value")].size(); + DPRINTLN(DBG_DEBUG, "ArraySize: " + String(cnt)); + + for (uint16_t i = 0; i < cnt; i++) { + uint16_t val = obj[F("value")][i]; + mApp->addValueToHistory((uint8_t)dataType, 0, val); + // DPRINT(DBG_VERBOSE, "value " + String(i) + ": " + String(val) + ", "); + } + uint32_t refresh = obj[F("refresh")]; + mApp->addValueToHistory((uint8_t)dataType, 1, refresh); + if (dataType != HistoryStorageType::YIELD) { + uint32_t ts = obj[F("lastValueTs")]; + mApp->addValueToHistory((uint8_t)dataType, 2, ts); + } + + } else { + switch (err.code()) { + case DeserializationError::Ok: + break; + case DeserializationError::IncompleteInput: + DPRINTLN(DBG_DEBUG, F("Incomplete input")); + break; + case DeserializationError::InvalidInput: + DPRINTLN(DBG_DEBUG, F("Invalid input")); + break; + case DeserializationError::NoMemory: + DPRINTLN(DBG_DEBUG, F("Not enough memory ") + String(json.capacity()) + " bytes"); + break; + default: + DPRINTLN(DBG_DEBUG, F("Deserialization failed")); + break; + } + } + + request->send(204); // Success with no page load + delete[] mTmpBuf; + mTmpBuf = NULL; + } + #endif + + void onApiPostBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) { DPRINTLN(DBG_VERBOSE, "onApiPostBody"); if(0 == index) { @@ -207,6 +302,8 @@ class RestApi { ep[F("live")] = url + F("live"); #if defined(ENABLE_HISTORY) ep[F("powerHistory")] = url + F("powerHistory"); + ep[F("powerHistoryDay")] = url + F("powerHistoryDay"); + ep[F("yieldDayHistory")] = url + F("yieldDayHistory"); #endif } @@ -815,7 +912,7 @@ class RestApi { void getPowerHistory(AsyncWebServerRequest *request, JsonObject obj) { getGeneric(request, obj.createNestedObject(F("generic"))); #if defined(ENABLE_HISTORY) - obj[F("refresh")] = mConfig->inst.sendInterval; + obj[F("refresh")] = mApp->getHistoryPeriode((uint8_t)HistoryStorageType::POWER); uint16_t max = 0; for (uint16_t fld = 0; fld < HISTORY_DATA_ARR_LENGTH; fld++) { uint16_t value = mApp->getHistoryValue((uint8_t)HistoryStorageType::POWER, fld); @@ -825,8 +922,40 @@ class RestApi { } obj[F("max")] = max; obj[F("maxDay")] = mApp->getHistoryMaxDay(); - #else - obj[F("refresh")] = 86400; // 1 day; + obj[F("lastValueTs")] = mApp->getHistoryLastValueTs((uint8_t)HistoryStorageType::POWER); + #endif /*ENABLE_HISTORY*/ + } + + void getPowerHistoryDay(AsyncWebServerRequest *request, JsonObject obj){ + getGeneric(request, obj.createNestedObject(F("generic"))); + #if defined(ENABLE_HISTORY) + obj[F("refresh")] = mApp->getHistoryPeriode((uint8_t)HistoryStorageType::POWER_DAY); + uint16_t max = 0; + for (uint16_t fld = 0; fld < HISTORY_DATA_ARR_LENGTH; fld++) { + uint16_t value = mApp->getHistoryValue((uint8_t)HistoryStorageType::POWER_DAY, fld); + obj[F("value")][fld] = value; + if (value > max) + max = value; + } + obj[F("max")] = max; + obj[F("maxDay")] = mApp->getHistoryMaxDay(); + obj[F("lastValueTs")] = mApp->getHistoryLastValueTs((uint8_t)HistoryStorageType::POWER_DAY); + #endif /*ENABLE_HISTORY*/ + } + + + void getYieldDayHistory(AsyncWebServerRequest *request, JsonObject obj) { + getGeneric(request, obj.createNestedObject(F("generic"))); + #if defined(ENABLE_HISTORY) + obj[F("refresh")] = mApp->getHistoryPeriode((uint8_t)HistoryStorageType::YIELD); + uint16_t max = 0; + for (uint16_t fld = 0; fld < HISTORY_DATA_ARR_LENGTH; fld++) { + uint16_t value = mApp->getHistoryValue((uint8_t)HistoryStorageType::YIELD, fld); + obj[F("value")][fld] = value; + if (value > max) + max = value; + } + obj[F("max")] = max; #endif /*ENABLE_HISTORY*/ } diff --git a/src/web/html/colorBright.css b/src/web/html/colorBright.css index 2e676029..aedd05d4 100644 --- a/src/web/html/colorBright.css +++ b/src/web/html/colorBright.css @@ -30,4 +30,8 @@ --ch-head-bg: #006ec0; --ts-head: #333; --ts-bg: #555; + + --chart-cont: #fbfbfb; + --chart-bg: #f9f9f9; + --chart-text: #000000; } diff --git a/src/web/html/colorDark.css b/src/web/html/colorDark.css index 40bd4cf3..b5b1a72b 100644 --- a/src/web/html/colorDark.css +++ b/src/web/html/colorDark.css @@ -30,4 +30,8 @@ --ch-head-bg: #236; --ts-head: #333; --ts-bg: #555; + + --chart-cont: #0b0b0b; + --chart-bg: #090909; + --chart-text: #FFFFFF; } diff --git a/src/web/html/history.html b/src/web/html/history.html index 7e317b59..c1c0637b 100644 --- a/src/web/html/history.html +++ b/src/web/html/history.html @@ -13,80 +13,356 @@

{#TOTAL_POWER}

-
+ {#LAST} {#VALUES} +

- {#MAX_DAY}: W. {#LAST_VALUE}: W.
- {#MAXIMUM}: W. {#UPDATED} {#SECONDS} + {#LAST_VALUE}: W.
+ {#MAXIMUM}: W. + {#UPDATED} {#SECONDS}

+

{#TOTAL_POWER_DAY}

+
+
+

+ {#MAX_DAY}: W.
+ {#UPDATED} {#SECONDS} +

+
+

{#TOTAL_YIELD_PER_DAY}

+
+
+

+ {#MAXIMUM}: Wh
+

+
+ +

Insert data into Yield per day history

+
+ Insert data (*.json) i.e. from a saved "/api/yieldDayHistory" call + +
+ + +
+
+
{#HTML_FOOTER} diff --git a/src/web/html/style.css b/src/web/html/style.css index 556dfcdc..60805e19 100644 --- a/src/web/html/style.css +++ b/src/web/html/style.css @@ -34,15 +34,16 @@ textarea { } svg polyline { - fill-opacity: .5; - stroke-width: 1; + fill-opacity: .5; + stroke-width: 1; } svg text { - font-size: x-small; - fill: var(--chart-text); + font-size: x-small; + fill: var(--chart-text); } + div.chartDivContainer { padding: 1px; margin: 1px; From 0c39f1d2e0cb275aa0b66b2d89e6a5bc227baafc Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 14 Mar 2024 00:47:49 +0100 Subject: [PATCH 038/201] 0.8.93 improved history graph in WebUI #1491 merged PR: #1491 --- src/CHANGES.md | 4 ++++ src/defines.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 0ddc7101..412c57d8 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.8.93 - 2024-03-14 +* improved history graph in WebUI #1491 +* merge PR: 1491 + ## 0.8.92 - 2024-03-10 * fix read back of limit value, now with one decimal place * added grid profile for Mexico #1493 diff --git a/src/defines.h b/src/defines.h index bfe29c7a..8fcdc000 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 92 +#define VERSION_PATCH 93 //------------------------------------- typedef struct { From 0499d32c122d11eac52c712a6c877256109ce101 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 16 Mar 2024 01:04:47 +0100 Subject: [PATCH 039/201] 0.8.94 * switched AsyncWebServer library * Ethernet version now uses same AsyncWebServer library as Wifi version * fix languange of `/history` * fix RSSI on `/history` #1463 --- patches/AsyncWeb_Prometheus.patch | 22 ++-- scripts/applyPatches.py | 5 +- src/CHANGES.md | 6 + src/defines.h | 2 +- src/eth/ahoyeth.cpp | 182 ++++++++---------------------- src/platformio.ini | 46 ++++---- src/web/RestApi.h | 11 +- src/web/html/history.html | 14 ++- src/web/lang.json | 25 ---- src/wifi/ahoywifi.cpp | 2 +- src/wifi/ahoywifi.h | 1 + 11 files changed, 105 insertions(+), 211 deletions(-) diff --git a/patches/AsyncWeb_Prometheus.patch b/patches/AsyncWeb_Prometheus.patch index 21fe22cd..3c7deac4 100644 --- a/patches/AsyncWeb_Prometheus.patch +++ b/patches/AsyncWeb_Prometheus.patch @@ -1,26 +1,26 @@ diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp -index 12be5f8..cffeed7 100644 +index 6e88da9..09359c3 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp -@@ -737,7 +737,7 @@ void AsyncWebSocketClient::binary(const __FlashStringHelper *data, size_t len) - IPAddress AsyncWebSocketClient::remoteIP() const - { - if (!_client) -- return IPAddress(0U); -+ return IPAddress(); +@@ -827,7 +827,7 @@ void AsyncWebSocketClient::binary(AsyncWebSocketMessageBuffer * buffer) + IPAddress AsyncWebSocketClient::remoteIP() { + if(!_client) { +- return IPAddress((uint32_t)0); ++ return IPAddress(); + } return _client->remoteIP(); } diff --git a/src/WebResponses.cpp b/src/WebResponses.cpp -index 22a549f..e0b36b3 100644 +index a22e991..babef18 100644 --- a/src/WebResponses.cpp +++ b/src/WebResponses.cpp -@@ -318,7 +318,7 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest *request, size_t len, u +@@ -317,7 +317,7 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest *request, size_t len, u free(buf); return 0; } -- outLen = sprintf_P((char*)buf+headLen, PSTR("%x"), readLen) + headLen; -+ outLen = sprintf_P((char*)buf+headLen, PSTR("%04x"), readLen) + headLen; +- outLen = sprintf((char*)buf+headLen, "%x", readLen) + headLen; ++ outLen = sprintf((char*)buf+headLen, "%04x", readLen) + headLen; while(outLen < headLen + 4) buf[outLen++] = ' '; buf[outLen++] = '\r'; buf[outLen++] = '\n'; diff --git a/scripts/applyPatches.py b/scripts/applyPatches.py index 147fb0f3..57f1fa23 100644 --- a/scripts/applyPatches.py +++ b/scripts/applyPatches.py @@ -26,9 +26,10 @@ def applyPatch(libName, patchFile): # list of patches to apply (relative to /src) -if env['PIOENV'][:22] != "opendtufusion-ethernet": - applyPatch("ESP Async WebServer", "../patches/AsyncWeb_Prometheus.patch") +applyPatch("ESPAsyncWebServer-esphome", "../patches/AsyncWeb_Prometheus.patch") if env['PIOENV'][:13] == "opendtufusion": applyPatch("GxEPD2", "../patches/GxEPD2_SW_SPI.patch") + +if (env['PIOENV'][:13] == "opendtufusion"): # or (env['PIOENV'][:13] == "esp32-wroom32"): applyPatch("RF24", "../patches/RF24_Hal.patch") diff --git a/src/CHANGES.md b/src/CHANGES.md index 412c57d8..f9bedf29 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,11 @@ # Development Changes +## 0.8.94 - 2024-03-16 +* switched AsyncWebServer library +* Ethernet version now uses same AsyncWebServer library as Wifi version +* fix languange of `/history` +* fix RSSI on `/history` #1463 + ## 0.8.93 - 2024-03-14 * improved history graph in WebUI #1491 * merge PR: 1491 diff --git a/src/defines.h b/src/defines.h index 8fcdc000..b5e5dc6c 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 93 +#define VERSION_PATCH 94 //------------------------------------- typedef struct { diff --git a/src/eth/ahoyeth.cpp b/src/eth/ahoyeth.cpp index 9dc0fb36..83f0aef0 100644 --- a/src/eth/ahoyeth.cpp +++ b/src/eth/ahoyeth.cpp @@ -31,12 +31,7 @@ void ahoyeth::setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNe WiFi.onEvent([this](WiFiEvent_t event, arduino_event_info_t info) -> void { this->onEthernetEvent(event, info); }); Serial.flush(); - //#if defined(CONFIG_IDF_TARGET_ESP32S3) mEthSpi.begin(DEF_ETH_MISO_PIN, DEF_ETH_MOSI_PIN, DEF_ETH_SCK_PIN, DEF_ETH_CS_PIN, DEF_ETH_IRQ_PIN, DEF_ETH_RST_PIN); - //#else - //ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLK_MODE); - //ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, DEF_ETH_MOSI_PIN, ETH_PHY_TYPE, ETH_CLK_MODE); - //#endif if(mConfig->sys.ip.ip[0] != 0) { IPAddress ip(mConfig->sys.ip.ip); @@ -52,11 +47,6 @@ void ahoyeth::setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNe //----------------------------------------------------------------------------- bool ahoyeth::updateNtpTime(void) { - DPRINTLN(DBG_DEBUG, F(__FUNCTION__)); Serial.flush(); - Serial.printf("ETH.linkUp()=%s\n", ETH.linkUp() ? "up" : "down"); - Serial.print("ETH.localIP()="); - Serial.println(ETH.localIP()); - Serial.printf("Go on? %s\n", (!ETH.localIP()) ? "No..." : "Yes..."); if (!ETH.localIP()) return false; @@ -134,137 +124,55 @@ void ahoyeth::welcome(String ip, String mode) { void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) { DPRINTLN(DBG_VERBOSE, F("[ETH]: Got event...")); switch (event) { -#if ( ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) && ( ARDUINO_ESP32_GIT_VER != 0x46d5afb1 ) ) - // For breaking core v2.0.0 - // Why so strange to define a breaking enum arduino_event_id_t in WiFiGeneric.h - // compared to the old system_event_id_t, now in tools/sdk/esp32/include/esp_event/include/esp_event_legacy.h - // You can preserve the old enum order and just adding new items to do no harm - case ARDUINO_EVENT_ETH_START: - DPRINTLN(DBG_INFO, F("\nETH Started")); - //set eth hostname here - if(String(mConfig->sys.deviceName) != "") - ETH.setHostname(mConfig->sys.deviceName); - else - ETH.setHostname("ESP32_W5500"); - break; - - case ARDUINO_EVENT_ETH_CONNECTED: - DPRINTLN(DBG_INFO, F("ETH Connected")); - break; - - case ARDUINO_EVENT_ETH_GOT_IP: - if (!mEthConnected) { - DPRINT(DBG_INFO, F("ETH MAC: ")); - #if defined (CONFIG_IDF_TARGET_ESP32S3) - DBGPRINT(mEthSpi.macAddress()); - #else - DBGPRINT(ETH.macAddress()); - #endif - DBGPRINT(F(", IPv4: ")); - DBGPRINTLN(String(ETH.localIP())); - - if (ETH.fullDuplex()) { - DPRINTLN(DBG_INFO, F("FULL_DUPLEX, ")); - } else { - DPRINTLN(DBG_INFO, F("HALF_DUPLEX, ")); + case ARDUINO_EVENT_ETH_START: + DPRINTLN(DBG_VERBOSE, F("ETH Started")); + + if(String(mConfig->sys.deviceName) != "") + ETH.setHostname(mConfig->sys.deviceName); + else + ETH.setHostname(F("ESP32_W5500")); + break; + + case ARDUINO_EVENT_ETH_CONNECTED: + DPRINTLN(DBG_VERBOSE, F("ETH Connected")); + break; + + case ARDUINO_EVENT_ETH_GOT_IP: + if (!mEthConnected) { + /*DPRINT(DBG_INFO, F("ETH MAC: ")); + DBGPRINT(mEthSpi.macAddress());*/ + welcome(ETH.localIP().toString(), F(" (Station)")); + + mEthConnected = true; + mOnNetworkCB(true); } - DPRINT(DBG_INFO, String(ETH.linkSpeed())); - DBGPRINTLN(F("Mbps")); - - mEthConnected = true; - mOnNetworkCB(true); - } - if (!MDNS.begin(mConfig->sys.deviceName)) { - DPRINTLN(DBG_ERROR, F("Error setting up MDNS responder!")); - } else { - DBGPRINT(F("[WiFi] mDNS established: ")); - DBGPRINT(mConfig->sys.deviceName); - DBGPRINTLN(F(".local")); - } - break; - - case ARDUINO_EVENT_ETH_DISCONNECTED: - DPRINTLN(DBG_INFO, "ETH Disconnected"); - mEthConnected = false; - mUdp.close(); - mOnNetworkCB(false); - break; - - case ARDUINO_EVENT_ETH_STOP: - DPRINTLN(DBG_INFO, "\nETH Stopped"); - mEthConnected = false; - mUdp.close(); - mOnNetworkCB(false); - break; - -#else - - // For old core v1.0.6- - // Core v2.0.0 defines a stupid enum arduino_event_id_t, breaking any code for ESP32_W5500 written for previous core - // Why so strange to define a breaking enum arduino_event_id_t in WiFiGeneric.h - // compared to the old system_event_id_t, now in tools/sdk/esp32/include/esp_event/include/esp_event_legacy.h - // You can preserve the old enum order and just adding new items to do no harm - case SYSTEM_EVENT_ETH_START: - DPRINTLN(DBG_INFO, F("\nETH Started")); - //set eth hostname here - if(String(mConfig->sys.deviceName) != "") - ETH.setHostname(mConfig->sys.deviceName); - else - ETH.setHostname("ESP32_W5500"); - break; - - case SYSTEM_EVENT_ETH_CONNECTED: - DPRINTLN(DBG_INFO, F("ETH Connected")); - break; - - case SYSTEM_EVENT_ETH_GOT_IP: - if (!ESP32_W5500_eth_connected) { - DPRINT(DBG_INFO, F("ETH MAC: ")); - DBGPRINT(ETH.macAddress()); - DBGPRINT(F(", IPv4: ")); - DBGPRINTLN(ETH.localIP()); - - if (ETH.fullDuplex()) { - DPRINTLN(DBG_INFO, F("FULL_DUPLEX, ")); + if (!MDNS.begin(mConfig->sys.deviceName)) { + DPRINTLN(DBG_ERROR, F("Error setting up MDNS responder!")); } else { - DPRINTLN(DBG_INFO, F("HALF_DUPLEX, ")); + DBGPRINT(F("mDNS established: ")); + DBGPRINT(mConfig->sys.deviceName); + DBGPRINTLN(F(".local")); } - - DPRINT(DBG_INFO, ETH.linkSpeed()); - DBGPRINTLN(F("Mbps")); - - ESP32_W5500_eth_connected = true; - mOnNetworkCB(true); - } - if (!MDNS.begin(mConfig->sys.deviceName)) { - DPRINTLN(DBG_ERROR, F("Error setting up MDNS responder!")); - } else { - DBGPRINT(F("[WiFi] mDNS established: ")); - DBGPRINT(mConfig->sys.deviceName); - DBGPRINTLN(F(".local")); - } - break; - - case SYSTEM_EVENT_ETH_DISCONNECTED: - DPRINT(DBG_INFO, F("ETH Disconnected")); - ESP32_W5500_eth_connected = false; - mUdp.close(); - mOnNetworkCB(false); - break; - - case SYSTEM_EVENT_ETH_STOP: - DPRINT(DBG_INFO, F("ETH Stopped")); - ESP32_W5500_eth_connected = false; - mUdp.close(); - mOnNetworkCB(false); - break; -#endif - - default: - - break; - } + break; + + case ARDUINO_EVENT_ETH_DISCONNECTED: + DPRINTLN(DBG_INFO, F("ETH Disconnected")); + mEthConnected = false; + mUdp.close(); + mOnNetworkCB(false); + break; + + case ARDUINO_EVENT_ETH_STOP: + DPRINTLN(DBG_INFO, F("ETH Stopped")); + mEthConnected = false; + mUdp.close(); + mOnNetworkCB(false); + break; + + default: + break; + } } diff --git a/src/platformio.ini b/src/platformio.ini index 869f74c0..20f8005a 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -25,7 +25,7 @@ extra_scripts = pre:../scripts/reduceGxEPD2.py lib_deps = - https://github.com/yubox-node-org/ESPAsyncWebServer + https://github.com/esphome/ESPAsyncWebServer @ ^3.1.0 https://github.com/nRF24/RF24 @ 1.4.8 paulstoffregen/Time @ ^1.6.1 https://github.com/bertmelis/espMqttClient#v1.6.0 @@ -216,7 +216,7 @@ monitor_filters = platform = espressif32 board = lolin_d32 build_flags = ${env.build_flags} - -D ETHERNET + -DETHERNET -DRELEASE -DUSE_HSPI_FOR_EPD -DENABLE_MQTT @@ -241,7 +241,7 @@ monitor_filters = platform = espressif32 board = lolin_d32 build_flags = ${env.build_flags} - -D ETHERNET + -DETHERNET -DRELEASE -DUSE_HSPI_FOR_EPD -DLANG_DE @@ -436,16 +436,16 @@ monitor_filters = [env:opendtufusion-ethernet] platform = espressif32@6.5.0 board = esp32-s3-devkitc-1 -lib_deps = - khoih-prog/AsyncWebServer_ESP32_W5500 - khoih-prog/AsyncUDP_ESP32_W5500 - https://github.com/nrf24/RF24 @ ^1.4.8 - paulstoffregen/Time @ ^1.6.1 - https://github.com/bertmelis/espMqttClient#v1.6.0 - bblanchon/ArduinoJson @ ^6.21.3 - https://github.com/JChristensen/Timezone @ ^1.2.4 - olikraus/U8g2 @ ^2.35.9 - https://github.com/zinggjm/GxEPD2#1.5.3 +#lib_deps = +# khoih-prog/AsyncWebServer_ESP32_W5500 +# khoih-prog/AsyncUDP_ESP32_W5500 +# https://github.com/nrf24/RF24 @ ^1.4.8 +# paulstoffregen/Time @ ^1.6.1 +# https://github.com/bertmelis/espMqttClient#v1.6.0 +# bblanchon/ArduinoJson @ ^6.21.3 +# https://github.com/JChristensen/Timezone @ ^1.2.4 +# olikraus/U8g2 @ ^2.35.9 +# https://github.com/zinggjm/GxEPD2#1.5.3 upload_protocol = esp-builtin build_flags = ${env.build_flags} -DETHERNET @@ -481,16 +481,16 @@ monitor_filters = [env:opendtufusion-ethernet-de] platform = espressif32@6.5.0 board = esp32-s3-devkitc-1 -lib_deps = - khoih-prog/AsyncWebServer_ESP32_W5500 - khoih-prog/AsyncUDP_ESP32_W5500 - https://github.com/nrf24/RF24 @ ^1.4.8 - paulstoffregen/Time @ ^1.6.1 - https://github.com/bertmelis/espMqttClient#v1.6.0 - bblanchon/ArduinoJson @ ^6.21.3 - https://github.com/JChristensen/Timezone @ ^1.2.4 - olikraus/U8g2 @ ^2.35.9 - https://github.com/zinggjm/GxEPD2#1.5.3 +#lib_deps = +# khoih-prog/AsyncWebServer_ESP32_W5500 +# khoih-prog/AsyncUDP_ESP32_W5500 +# https://github.com/nrf24/RF24 @ ^1.4.8 +# paulstoffregen/Time @ ^1.6.1 +# https://github.com/bertmelis/espMqttClient#v1.6.0 +# bblanchon/ArduinoJson @ ^6.21.3 +# https://github.com/JChristensen/Timezone @ ^1.2.4 +# olikraus/U8g2 @ ^2.35.9 +# https://github.com/zinggjm/GxEPD2#1.5.3 upload_protocol = esp-builtin build_flags = ${env.build_flags} -DETHERNET diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 1ab12c30..399ea91f 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -350,8 +350,9 @@ class RestApi { void getGeneric(AsyncWebServerRequest *request, JsonObject obj) { mApp->resetLockTimeout(); - + #if !defined(ETHERNET) obj[F("wifi_rssi")] = (WiFi.status() != WL_CONNECTED) ? 0 : WiFi.RSSI(); + #endif obj[F("ts_uptime")] = mApp->getUptime(); obj[F("ts_now")] = mApp->getTimestamp(); obj[F("version")] = String(mApp->getVersion()); @@ -378,12 +379,13 @@ class RestApi { obj[F("ssid")] = mConfig->sys.stationSsid; obj[F("ap_pwd")] = mConfig->sys.apPwd; obj[F("hidd")] = mConfig->sys.isHidden; + obj[F("mac")] = WiFi.macAddress(); + obj[F("wifi_channel")] = WiFi.channel(); #endif /* !defined(ETHERNET) */ obj[F("device_name")] = mConfig->sys.deviceName; obj[F("dark_mode")] = (bool)mConfig->sys.darkMode; obj[F("sched_reboot")] = (bool)mConfig->sys.schedReboot; - obj[F("mac")] = WiFi.macAddress(); obj[F("hostname")] = mConfig->sys.deviceName; obj[F("pwd_set")] = (strlen(mConfig->sys.adminPwd) > 0); obj[F("prot_mask")] = mConfig->sys.protectionMask; @@ -393,7 +395,6 @@ class RestApi { obj[F("heap_free")] = mHeapFree; obj[F("sketch_total")] = ESP.getFreeSketchSpace(); obj[F("sketch_used")] = ESP.getSketchSize() / 1024; // in kb - obj[F("wifi_channel")] = WiFi.channel(); getGeneric(request, obj); getRadioNrf(obj.createNestedObject(F("radioNrf"))); @@ -426,9 +427,9 @@ class RestApi { //obj[F("littlefs_total")] = LittleFS.totalBytes(); //obj[F("littlefs_used")] = LittleFS.usedBytes(); - uint8_t max; + /*uint8_t max; mApp->getSchedulerInfo(&max); - obj[F("schMax")] = max; + obj[F("schMax")] = max;*/ } void getHtmlSystem(AsyncWebServerRequest *request, JsonObject obj) { diff --git a/src/web/html/history.html b/src/web/html/history.html index 2d1509d4..57bff2fc 100644 --- a/src/web/html/history.html +++ b/src/web/html/history.html @@ -12,12 +12,12 @@ {#HTML_NAV}
-

Total Power

+

{#TOTAL_POWER}

-

Total Power Today

+

{#TOTAL_POWER_DAY}

-

Total Yield per day

+

{#TOTAL_YIELD_PER_DAY}

@@ -136,8 +136,8 @@ return [ mlNs("polyline", {stroke: "url(#gLine)", fill: "none", points: pts}), mlNs("polyline", {stroke: "none", fill: "url(#gFill)", points: pts2}), - mlNs("text", {x: i*.8, y: 10}, "Maximum: " + String(obj.max) + "W"), - mlNs("text", {x: i*.8, y: 25}, "Last: " + String(lastVal) + "W") + mlNs("text", {x: i*.8, y: 10}, "{#MAX_DAY}: " + String(obj.max) + "W"), + mlNs("text", {x: i*.8, y: 25}, "{#LAST_VALUE}: " + String(lastVal) + "W") ] } @@ -145,7 +145,9 @@ function parsePowerHistory(obj){ if(once) { once = false - parseNav(obj.generic); + parseNav(obj.generic) + parseESP(obj.generic) + parseRssi(obj.generic) window.setInterval("getAjax('/api/powerHistory', parsePowerHistory)", obj.refresh * 1000) setTimeout(() => { window.setInterval("getAjax('/api/powerHistoryDay', parsePowerHistoryDay)", refresh * 1000) diff --git a/src/web/lang.json b/src/web/lang.json index 6416a61a..f1723688 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -1528,16 +1528,6 @@ "en": "Total Power", "de": "Gesamtleistung" }, - { - "token": "LAST", - "en": "Last", - "de": "Die letzten" - }, - { - "token": "VALUES", - "en": "values", - "de": "Werte" - }, { "token": "TOTAL_POWER_DAY", "en": "Total Power Today", @@ -1557,21 +1547,6 @@ "token": "LAST_VALUE", "en": "Last value", "de": "Letzter Wert" - }, - { - "token": "MAXIMUM", - "en": "Maximum value", - "de": "Maximalwert" - }, - { - "token": "UPDATED", - "en": "Updated every", - "de": "Aktualisiert alle" - }, - { - "token": "SECONDS", - "en": "seconds", - "de": "Sekunden" } ] } diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 9bcbdadc..69665b31 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -198,7 +198,7 @@ void ahoywifi::tickWifiLoop() { if (!MDNS.begin(mConfig->sys.deviceName)) { DPRINTLN(DBG_ERROR, F("Error setting up MDNS responder!")); } else { - DBGPRINT(F("[WiFi] mDNS established: ")); + DBGPRINT(F("mDNS established: ")); DBGPRINT(mConfig->sys.deviceName); DBGPRINTLN(F(".local")); } diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index d38701aa..e971c997 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -9,6 +9,7 @@ #include "../utils/dbg.h" #include +#include #include #include #include "ESPAsyncWebServer.h" From 6af07f5a33345f40ffbf1e82cd0c47508d46441f Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 16 Mar 2024 01:06:04 +0100 Subject: [PATCH 040/201] 0.8.94 --- src/CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index f9bedf29..b2b24f89 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -3,7 +3,7 @@ ## 0.8.94 - 2024-03-16 * switched AsyncWebServer library * Ethernet version now uses same AsyncWebServer library as Wifi version -* fix languange of `/history` +* fix translation of `/history` * fix RSSI on `/history` #1463 ## 0.8.93 - 2024-03-14 From 4fc61dc01f8839d27c00bae8280aaef9c8a2c3d3 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 17 Mar 2024 00:42:58 +0100 Subject: [PATCH 041/201] 0.8.95 * fix NTP issues #1440 #1497 #1499 --- src/CHANGES.md | 3 +++ src/app.cpp | 48 +++++++++++++++++++------------------------ src/app.h | 4 +--- src/defines.h | 2 +- src/wifi/ahoywifi.cpp | 6 ++++-- src/wifi/ahoywifi.h | 6 ++++-- 6 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index b2b24f89..99cf8ac8 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.95 - 2024-03-17 +* fix NTP issues #1440 #1497 #1499 + ## 0.8.94 - 2024-03-16 * switched AsyncWebServer library * Ethernet version now uses same AsyncWebServer library as Wifi version diff --git a/src/app.cpp b/src/app.cpp index bad880f5..37b0a37a 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -59,7 +59,7 @@ void app::setup() { #endif // ETHERNET #if !defined(ETHERNET) - mWifi.setup(mConfig, &mTimestamp, std::bind(&app::onNetwork, this, std::placeholders::_1)); + mWifi.setup(mConfig, &mTimestamp, [this](bool gotIp) { this->onNetwork(gotIp); }, [this](bool gotTime) { this->onNtpUpdate(gotTime); }); #if !defined(AP_ONLY) everySec(std::bind(&ahoywifi::tickWifiLoop, &mWifi), "wifiL"); #endif @@ -135,7 +135,6 @@ void app::setup() { }); #endif /*ENABLE_SIMULATOR*/ - esp_task_wdt_reset(); regularTickers(); } @@ -164,7 +163,7 @@ void app::loop(void) { //----------------------------------------------------------------------------- void app::onNetwork(bool gotIp) { - DPRINTLN(DBG_DEBUG, F("onNetwork")); + DPRINTLN(DBG_INFO, F("onNetwork")); mNetworkConnected = gotIp; ah::Scheduler::resetTicker(); regularTickers(); //reinstall regular tickers @@ -205,11 +204,9 @@ void app::regularTickers(void) { #endif /*ENABLE_SIMULATOR*/ } -#if defined(ETHERNET) void app::onNtpUpdate(bool gotTime) { mNtpReceived = true; } -#endif /* defined(ETHERNET) */ //----------------------------------------------------------------------------- void app::updateNtp(void) { @@ -250,30 +247,30 @@ void app::updateNtp(void) { //----------------------------------------------------------------------------- void app::tickNtpUpdate(void) { uint32_t nxtTrig = 5; // default: check again in 5 sec - bool isOK = false; #if defined(ETHERNET) - if (!mNtpReceived) - mEth.updateNtpTime(); - else { - mNtpReceived = false; - isOK = true; - } - #else - isOK = mWifi.getNtpTime(); + if (!mNtpReceived) + mEth.updateNtpTime(); + else + mNtpReceived = false; + #else + if (!mNtpReceived) + mWifi.updateNtpTime(); + else + mNtpReceived = false; #endif - if (isOK) { - this->updateNtp(); - nxtTrig = mConfig->ntp.interval * 60; // check again in 12h - - // immediately start communicating - if (mSendFirst) { - mSendFirst = false; - once(std::bind(&app::tickSend, this), 1, "senOn"); - } - mMqttReconnect = false; + updateNtp(); + nxtTrig = mConfig->ntp.interval * 60; // check again in 12h + + // immediately start communicating + if (mSendFirst) { + mSendFirst = false; + once(std::bind(&app::tickSend, this), 1, "senOn"); } + + mMqttReconnect = false; + once(std::bind(&app::tickNtpUpdate, this), nxtTrig, "ntp"); } @@ -561,10 +558,7 @@ void app::resetSystem(void) { mSaveReboot = false; mNetworkConnected = false; - -#if defined(ETHERNET) mNtpReceived = false; -#endif } //----------------------------------------------------------------------------- diff --git a/src/app.h b/src/app.h index 4069662f..a699bac0 100644 --- a/src/app.h +++ b/src/app.h @@ -299,7 +299,7 @@ class app : public IApp, public ah::Scheduler { #if defined(ETHERNET) mEth.updateNtpTime(); #else /* defined(ETHERNET) */ - mWifi.getNtpTime(); + mWifi.updateNtpTime(); #endif /* defined(ETHERNET) */ } else @@ -389,10 +389,8 @@ class app : public IApp, public ah::Scheduler { } void tickNtpUpdate(void); - #if defined(ETHERNET) void onNtpUpdate(bool gotTime); bool mNtpReceived = false; - #endif /* defined(ETHERNET) */ void updateNtp(void); void triggerTickSend() override { diff --git a/src/defines.h b/src/defines.h index b5e5dc6c..752b3437 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 94 +#define VERSION_PATCH 95 //------------------------------------- typedef struct { diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 69665b31..95bf0b8a 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -30,10 +30,11 @@ ahoywifi::ahoywifi() : mApIp(192, 168, 4, 1) {} */ //----------------------------------------------------------------------------- -void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { +void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb, OnTimeCB onTimeCb) { mConfig = config; mUtcTimestamp = utcTimestamp; mAppWifiCb = cb; + mOnTimeCb = onTimeCb; mGotDisconnect = false; mStaConn = DISCONNECTED; @@ -275,7 +276,7 @@ void ahoywifi::setupStation(void) { //----------------------------------------------------------------------------- -bool ahoywifi::getNtpTime(void) { +bool ahoywifi::updateNtpTime(void) { if(IN_STA_MODE != mStaConn) return false; @@ -302,6 +303,7 @@ bool ahoywifi::getNtpTime(void) { *mUtcTimestamp = secsSince1900 - 2208988800UL; // UTC time DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(*mUtcTimestamp) + " UTC"); + mOnTimeCb(true); return true; } else delay(10); diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index e971c997..78ec6ab1 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -21,13 +21,14 @@ class app; class ahoywifi { public: typedef std::function appWifiCb; + typedef std::function OnTimeCB; ahoywifi(); - void setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb); + void setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb, OnTimeCB onTimeCB); void tickWifiLoop(void); - bool getNtpTime(void); + bool updateNtpTime(void); void scanAvailNetworks(void); bool getAvailNetworks(JsonObject obj); void setStopApAllowedMode(bool allowed) { @@ -74,6 +75,7 @@ class ahoywifi { settings_t *mConfig = nullptr; appWifiCb mAppWifiCb; + OnTimeCB mOnTimeCb; DNSServer mDns; IPAddress mApIp; From a44a5833cae9f1c49134e72a315e892844693d43 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 19 Mar 2024 00:15:10 +0100 Subject: [PATCH 042/201] * made ethernet pinout configurable * combined common network functions into class * seperated wifi station from AP mode --- src/config/settings.h | 48 ++++- src/eth/ahoyeth.cpp | 2 +- src/network/AhoyEthernet.h | 82 ++++++++ .../ethSpi.h => network/AhoyEthernetSpi.h} | 8 +- src/network/AhoyNetwork.h | 194 ++++++++++++++++++ src/network/AhoyNetworkHelper.h | 29 +++ src/network/AhoyWifiAp.h | 70 +++++++ src/web/RestApi.h | 14 ++ src/web/html/setup.html | 64 +++++- src/web/lang.json | 5 + src/web/web.h | 47 ++++- src/wifi/ahoywifi.h | 2 +- 12 files changed, 540 insertions(+), 25 deletions(-) create mode 100644 src/network/AhoyEthernet.h rename src/{eth/ethSpi.h => network/AhoyEthernetSpi.h} (96%) create mode 100644 src/network/AhoyNetwork.h create mode 100644 src/network/AhoyNetworkHelper.h create mode 100644 src/network/AhoyWifiAp.h diff --git a/src/config/settings.h b/src/config/settings.h index fe0053a9..f130434c 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -63,6 +63,19 @@ typedef struct { uint8_t gateway[4]; // standard gateway } cfgIp_t; + +#if defined(ETHERNET) +typedef struct { + bool enabled; + uint8_t pinCs; + uint8_t pinSclk; + uint8_t pinMiso; + uint8_t pinMosi; + uint8_t pinIrq; + uint8_t pinRst; +} cfgEth_t; +#endif + typedef struct { char deviceName[DEVNAME_LEN]; char adminPwd[PWD_LEN]; @@ -72,15 +85,16 @@ typedef struct { uint8_t region; int8_t timezone; + char apPwd[PWD_LEN]; #if !defined(ETHERNET) // wifi char stationSsid[SSID_LEN]; char stationPwd[PWD_LEN]; - char apPwd[PWD_LEN]; bool isHidden; #endif /* !defined(ETHERNET) */ cfgIp_t ip; + cfgEth_t eth; } cfgSys_t; typedef struct { @@ -393,7 +407,17 @@ class settings { snprintf(mCfg.sys.apPwd, PWD_LEN, WIFI_AP_PWD); mCfg.sys.isHidden = false; } - #endif /* !defined(ETHERNET) */ + #endif + + #if defined(ETHERNET) + mCfg.sys.eth.enabled = false; + mCfg.sys.eth.pinCs = DEF_ETH_CS_PIN; + mCfg.sys.eth.pinSclk = DEF_ETH_SCK_PIN; + mCfg.sys.eth.pinMiso = DEF_ETH_MISO_PIN; + mCfg.sys.eth.pinMosi = DEF_ETH_MOSI_PIN; + mCfg.sys.eth.pinIrq = DEF_ETH_IRQ_PIN; + mCfg.sys.eth.pinRst = DEF_ETH_RST_PIN; + #endif snprintf(mCfg.sys.deviceName, DEVNAME_LEN, DEF_DEVICE_NAME); mCfg.sys.region = 0; // Europe @@ -544,6 +568,16 @@ class settings { 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); + + #if defined(ETHERNET) + obj[F("en")] = mCfg.sys.eth.enabled; + obj[F("cs")] = mCfg.sys.eth.pinCs; + obj[F("sclk")] = mCfg.sys.eth.pinSclk; + obj[F("miso")] = mCfg.sys.eth.pinMiso; + obj[F("mosi")] = mCfg.sys.eth.pinMosi; + obj[F("irq")] = mCfg.sys.eth.pinIrq; + obj[F("rst")] = mCfg.sys.eth.pinRst; + #endif } else { #if !defined(ETHERNET) getChar(obj, F("ssid"), mCfg.sys.stationSsid, SSID_LEN); @@ -567,6 +601,16 @@ class settings { if(mCfg.sys.protectionMask == 0) mCfg.sys.protectionMask = DEF_PROT_INDEX | DEF_PROT_LIVE | DEF_PROT_SERIAL | DEF_PROT_SETUP | DEF_PROT_UPDATE | DEF_PROT_SYSTEM | DEF_PROT_API | DEF_PROT_MQTT | DEF_PROT_HISTORY; + + #if defined(ETHERNET) + getVal(obj, F("en"), &mCfg.sys.eth.enabled); + getVal(obj, F("cs"), &mCfg.sys.eth.pinCs); + getVal(obj, F("sclk"), &mCfg.sys.eth.pinSclk); + getVal(obj, F("miso"), &mCfg.sys.eth.pinMiso); + getVal(obj, F("mosi"), &mCfg.sys.eth.pinMosi); + getVal(obj, F("irq"), &mCfg.sys.eth.pinIrq); + getVal(obj, F("rst"), &mCfg.sys.eth.pinRst); + #endif } } diff --git a/src/eth/ahoyeth.cpp b/src/eth/ahoyeth.cpp index 83f0aef0..497a542f 100644 --- a/src/eth/ahoyeth.cpp +++ b/src/eth/ahoyeth.cpp @@ -31,7 +31,7 @@ void ahoyeth::setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNe WiFi.onEvent([this](WiFiEvent_t event, arduino_event_info_t info) -> void { this->onEthernetEvent(event, info); }); Serial.flush(); - mEthSpi.begin(DEF_ETH_MISO_PIN, DEF_ETH_MOSI_PIN, DEF_ETH_SCK_PIN, DEF_ETH_CS_PIN, DEF_ETH_IRQ_PIN, DEF_ETH_RST_PIN); + mEthSpi.begin(config->sys.eth.pinMiso, config->sys.eth.pinMosi, config->sys.eth.pinSclk, config->sys.eth.pinCs, config->sys.eth.pinIrq, config->sys.eth.pinRst); if(mConfig->sys.ip.ip[0] != 0) { IPAddress ip(mConfig->sys.ip.ip); diff --git a/src/network/AhoyEthernet.h b/src/network/AhoyEthernet.h new file mode 100644 index 00000000..c56b4338 --- /dev/null +++ b/src/network/AhoyEthernet.h @@ -0,0 +1,82 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __AHOY_ETHERNET_H__ +#define __AHOY_ETHERNET_H__ + +#include +#include +#include +#include "AhoyEthernetSpi.h" +#include "AhoyEthernet.h" + +class AhoyEthernet : public AhoyNetwork { + public: + void begin() override { + setupIp([this](IPAddress ip, IPAddress gateway, IPAddress mask, IPAddress dns1, IPAddress dns2) -> bool { + return ETH.config(ip, gateway, mask, dns1, dns2); + }); + } + + void tickNetworkLoop() override { + switch(mState) { + case NetworkState::DISCONNECTED: + break; + } + } + + private: + + /*switch (event) { + case ARDUINO_EVENT_ETH_START: + DPRINTLN(DBG_VERBOSE, F("ETH Started")); + + if(String(mConfig->sys.deviceName) != "") + ETH.setHostname(mConfig->sys.deviceName); + else + ETH.setHostname(F("ESP32_W5500")); + break; + + case ARDUINO_EVENT_ETH_CONNECTED: + DPRINTLN(DBG_VERBOSE, F("ETH Connected")); + break; + + case ARDUINO_EVENT_ETH_GOT_IP: + if (!mEthConnected) { + welcome(ETH.localIP().toString(), F(" (Station)")); + + mEthConnected = true; + mOnNetworkCB(true); + } + + if (!MDNS.begin(mConfig->sys.deviceName)) { + DPRINTLN(DBG_ERROR, F("Error setting up MDNS responder!")); + } else { + DBGPRINT(F("mDNS established: ")); + DBGPRINT(mConfig->sys.deviceName); + DBGPRINTLN(F(".local")); + } + break; + + case ARDUINO_EVENT_ETH_DISCONNECTED: + DPRINTLN(DBG_INFO, F("ETH Disconnected")); + mEthConnected = false; + mUdp.close(); + mOnNetworkCB(false); + break; + + case ARDUINO_EVENT_ETH_STOP: + DPRINTLN(DBG_INFO, F("ETH Stopped")); + mEthConnected = false; + mUdp.close(); + mOnNetworkCB(false); + break; + + default: + break; + }*/ +}; + +#endif /*__AHOY_ETHERNET_H__*/ diff --git a/src/eth/ethSpi.h b/src/network/AhoyEthernetSpi.h similarity index 96% rename from src/eth/ethSpi.h rename to src/network/AhoyEthernetSpi.h index 1339c8ec..12e58e4d 100644 --- a/src/eth/ethSpi.h +++ b/src/network/AhoyEthernetSpi.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- -// 2024 Ahoy, https://www.mikrocontroller.net/topic/525778 -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #if defined(ETHERNET) @@ -18,10 +18,10 @@ void tcpipInit(); void add_esp_interface_netif(esp_interface_t interface, esp_netif_t* esp_netif); -class EthSpi { +class AhoyEthernetSpi { public: - EthSpi() : + AhoyEthernetSpi() : eth_handle(nullptr), eth_netif(nullptr) {} diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h new file mode 100644 index 00000000..01d7cd8c --- /dev/null +++ b/src/network/AhoyNetwork.h @@ -0,0 +1,194 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __AHOY_NETWORK_H__ +#define __AHOY_NETWORK_H__ + +#include "AhoyNetworkHelper.h" +#include +#include "../config/settings.h" +#include "../utils/helper.h" + +#if defined(ESP32) +#include +#else +#include +#endif + +#define NTP_PACKET_SIZE 48 + +class AhoyNetwork { + public: + typedef std::function OnNetworkCB; + typedef std::function OnTimeCB; + + public: + void setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNetworkCB, OnTimeCB onTimeCB) { + mConfig = config; + mUtcTimestamp = utcTimestamp; + mOnNetworkCB = onNetworkCB; + mOnTimeCB = onTimeCB; + + #if defined(ESP32) + WiFi.onEvent([this](WiFiEvent_t event) -> void { + this->OnEvent(event); + }); + #else + wifiConnectHandler = WiFi.onStationModeConnected( + [this](const WiFiEventStationModeConnected& event) -> void { + OnEvent(SYSTEM_EVENT_STA_CONNECTED); + }); + wifiGotIPHandler = WiFi.onStationModeGotIP( + [this](const WiFiEventStationModeGotIP& event) -> void { + OnEvent(SYSTEM_EVENT_STA_GOT_IP); + }); + wifiDisconnectHandler = WiFi.onStationModeDisconnected( + [this](const WiFiEventStationModeDisconnected& event) -> void { + OnEvent(SYSTEM_EVENT_STA_DISCONNECTED); + }); + #endif + } + + bool isConnected() const { + return (mStatus == NetworkState.CONNECTED); + } + + bool updateNtpTime(void) { + if(CONNECTED != mStatus) + return; + + if (!mUdp.connected()) { + IPAddress timeServer; + if (!WiFi.hostByName(mConfig->ntp.addr, timeServer)) + return false; + if (!mUdp.connect(timeServer, mConfig->ntp.port)) + return false; + } + + mUdp.onPacket([this](AsyncUDPPacket packet) { + this->handleNTPPacket(packet); + }); + sendNTPpacket(timeServer); + + return true; + } + + public: + virtual void begin() = 0; + virtual void tickNetworkLoop() = 0; + virtual void connectionEvent(WiFiStatus_t status) = 0; + + protected: + void setupIp(void) { + if(mConfig->sys.ip.ip[0] != 0) { + IPAddress ip(mConfig->sys.ip.ip); + IPAddress mask(mConfig->sys.ip.mask); + IPAddress dns1(mConfig->sys.ip.dns1); + IPAddress dns2(mConfig->sys.ip.dns2); + IPAddress gateway(mConfig->sys.ip.gateway); + if(!ETH.config(ip, gateway, mask, dns1, dns2)) + DPRINTLN(DBG_ERROR, F("failed to set static IP!")); + } + } + + void OnEvent(WiFiEvent_t event) { + switch(event) { + case SYSTEM_EVENT_STA_CONNECTED: + [[fallthrough]]; + case ARDUINO_EVENT_ETH_CONNECTED: + if(NetworkState::CONNECTED != mStatus) { + mStatus = NetworkState::CONNECTED; + DPRINTLN(DBG_INFO, F("Network connected")); + } + break; + + case SYSTEM_EVENT_STA_GOT_IP: + [[fallthrough]]; + case ARDUINO_EVENT_ETH_GOT_IP: + mStatus = NetworkState::GOT_IP; + break; + + case ARDUINO_EVENT_WIFI_STA_LOST_IP: + [[fallthrough]]; + case ARDUINO_EVENT_WIFI_STA_STOP: + [[fallthrough]]; + case SYSTEM_EVENT_STA_DISCONNECTED: + [[fallthrough]]; + case ARDUINO_EVENT_ETH_STOP: + [[fallthrough]]; + case ARDUINO_EVENT_ETH_DISCONNECTED: + mStatus = NetworkState::DISCONNECTED; + break; + + default: + break; + } + } + + private: + void sendNTPpacket(IPAddress& address) { + //DPRINTLN(DBG_VERBOSE, F("wifi::sendNTPpacket")); + uint8_t buf[NTP_PACKET_SIZE]; + memset(buf, 0, NTP_PACKET_SIZE); + + buf[0] = 0b11100011; // LI, Version, Mode + buf[1] = 0; // Stratum + buf[2] = 6; // Max Interval between messages in seconds + buf[3] = 0xEC; // Clock Precision + // bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset + buf[12] = 49; // four-byte reference ID identifying + buf[13] = 0x4E; + buf[14] = 49; + buf[15] = 52; + + //mUdp.beginPacket(address, 123); // NTP request, port 123 + mUdp.write(buf, NTP_PACKET_SIZE); + //mUdp.endPacket(); + } + + void handleNTPPacket(AsyncUDPPacket packet) { + char buf[80]; + + memcpy(buf, packet.data(), sizeof(buf)); + + unsigned long highWord = word(buf[40], buf[41]); + unsigned long lowWord = word(buf[42], buf[43]); + + // combine the four bytes (two words) into a long integer + // this is NTP time (seconds since Jan 1 1900): + unsigned long secsSince1900 = highWord << 16 | lowWord; + + *mUtcTimestamp = secsSince1900 - 2208988800UL; // UTC time + DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(*mUtcTimestamp) + " UTC"); + mOnTimeCB(true); + mUdp.close(); + } + + protected: + enum class NetworkState : uint8_t { + DISCONNECTED, + CONNECTING, + CONNECTED, + IN_AP_MODE, + GOT_IP, + IN_STA_MODE, + RESET, + SCAN_READY + }; + + protected: + settings_t *mConfig = nullptr; + uint32_t *mUtcTimestamp = nullptr; + + OnNetworkCB mOnNetworkCB; + OnTimeCB mOnTimeCB; + + NetworkState mStatus = NetworkState.DISCONNECTED; + + WiFiUDP mUdp; // for time server + DNSServer mDns; +}; + +#endif /*__AHOY_NETWORK_H__*/ diff --git a/src/network/AhoyNetworkHelper.h b/src/network/AhoyNetworkHelper.h new file mode 100644 index 00000000..ab23f5bc --- /dev/null +++ b/src/network/AhoyNetworkHelper.h @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __AHOY_NETWORK_HELPER_H__ +#define __AHOY_NETWORK_HELPER_H__ + +#include "../utils/dbg.h" +#include +#include +#include +#include + +namespace ah { + void welcome(String ip, String info) { + DBGPRINTLN(F("\n\n-------------------")); + DBGPRINTLN(F("Welcome to AHOY!")); + DBGPRINT(F("\npoint your browser to http://")); + DBGPRINT(ip); + DBGPRINT(" ("); + DBGPRINT(info); + DBGPRINTLN(")"); + DBGPRINTLN(F("to configure your device")); + DBGPRINTLN(F("-------------------\n")); + } +} + +#endif /*__AHOY_NETWORK_HELPER_H__*/ diff --git a/src/network/AhoyWifiAp.h b/src/network/AhoyWifiAp.h new file mode 100644 index 00000000..f919e030 --- /dev/null +++ b/src/network/AhoyWifiAp.h @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __AHOY_WIFI_AP_H__ +#define __AHOY_WIFI_AP_H__ + +#include "../utils/dbg.h" +#include +#include "../config/settings.h" +#include "AhoyNetworkHelper.h" + +class AhoyWifiAp { + public: + AhoyWifiAp() : mIp(192, 168, 4, 1) {} + + void setup(cfgSys_t *cfg) { + mCfg = cfg; + } + + void tickLoop() { + if(mEnabled) + mDns.processNextRequest(); + } + + void enable() { + ah::welcome(mIp.toString(), String(F("Password: ") + String(mCfg->apPwd))); + if('\0' == mCfg->deviceName[0]) + snprintf(mCfg->deviceName, DEVNAME_LEN, "%s", DEF_DEVICE_NAME); + WiFi.hostname(mCfg->deviceName); + + #if defined(ETHERNET) + WiFi.mode(WIFI_AP); + #else + WiFi.mode(WIFI_AP_STA); + #endif + WiFi.softAPConfig(mIp, mIp, IPAddress(255, 255, 255, 0)); + WiFi.softAP(WIFI_AP_SSID, mCfg->apPwd); + + mDns.start(53, "*", mIp); + + mEnabled = true; + tickLoop(); + } + + void disable() { + mDns.stop(); + WiFi.softAPdisconnect(); + #if defined(ETHERNET) + WiFi.mode(WIFI_OFF); + #else + WiFi.mode(WIFI_STA); + #endif + + mEnabled = false; + } + + bool getEnable() const { + return mEnabled; + } + + private: + cfgSys_t *mCfg = nullptr; + DNSServer mDns; + IPAddress mIp; + bool mEnabled = false; +}; + +#endif /*__AHOY_WIFI_AP_H__*/ diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 399ea91f..197c6982 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -381,6 +381,8 @@ class RestApi { obj[F("hidd")] = mConfig->sys.isHidden; obj[F("mac")] = WiFi.macAddress(); obj[F("wifi_channel")] = WiFi.channel(); + #else + getEthernet(obj.createNestedObject(F("eth"))); #endif /* !defined(ETHERNET) */ obj[F("device_name")] = mConfig->sys.deviceName; obj[F("dark_mode")] = (bool)mConfig->sys.darkMode; @@ -762,6 +764,18 @@ class RestApi { } #endif + #if defined(ETHERNET) + void getEthernet(JsonObject obj) { + obj[F("en")] = mConfig->sys.eth.enabled; + obj[F("cs")] = mConfig->sys.eth.pinCs; + obj[F("sclk")] = mConfig->sys.eth.pinSclk; + obj[F("miso")] = mConfig->sys.eth.pinMiso; + obj[F("mosi")] = mConfig->sys.eth.pinMosi; + obj[F("irq")] = mConfig->sys.eth.pinIrq; + obj[F("reset")] = mConfig->sys.eth.pinRst; + } + #endif + void getRadioNrf(JsonObject obj) { obj[F("en")] = (bool) mConfig->nrf.enabled; if(mConfig->nrf.enabled) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index b6b8929e..8f3fe07c 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -245,7 +245,7 @@

{#MQTT_NOTE}

{#INTERVAL}
-
+
Discovery Config (homeassistant)
@@ -270,6 +270,10 @@

{#RADIO} (CMT2300A)

+ +

Ethernet

+
+
@@ -986,7 +990,7 @@ ) } - function parseNrfRadio(obj, objPin, type, system) { + function parseNrfRadio(obj, objPin) { var e = document.getElementById("rf24"); var en = inp("nrfEnable", null, null, ["cb"], "nrfEnable", "checkbox"); en.checked = obj["en"]; @@ -1013,11 +1017,11 @@ ]) ); - if ("ESP8266" == type) { - pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq']]; - } else { - pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['sclk', 'pinSclk'], ['mosi', 'pinMosi'], ['miso', 'pinMiso']]; - } + /*IF_ESP32*/ + var pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['sclk', 'pinSclk'], ['mosi', 'pinMosi'], ['miso', 'pinMiso']]; + /*ELSE*/ + var pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq']]; + /*ENDIF_ESP32*/ for(p of pins) { e.append( ml("div", {class: "row mb-3"}, [ @@ -1031,7 +1035,7 @@ } /*IF_ESP32*/ - function parseCmtRadio(obj, type, system) { + function parseCmtRadio(obj) { var e = document.getElementById("cmt"); var en = inp("cmtEnable", null, null, ["cb"], "cmtEnable", "checkbox"); var pinList = esp32pins; @@ -1046,7 +1050,6 @@ /*ENDIF_ESP32-C3*/ en.checked = obj["en"]; - e.replaceChildren ( ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-8 col-sm-3 my-2"}, "{#CMT_ENABLE}"), @@ -1073,6 +1076,42 @@ } /*ENDIF_ESP32*/ + /*IF_ETHERNET*/ + function parseEth(obj) { + var e = document.getElementById("eth"); + var en = inp("ethEn", null, null, ["cb"], "ethEn", "checkbox"); + var pinList = esp32pins; + /*IF_ESP32-S2*/ + pinList = esp32sXpins; + /*ENDIF_ESP32-S2*/ + /*IF_ESP32-S3*/ + pinList = esp32sXpins; + /*ENDIF_ESP32-S3*/ + /*IF_ESP32-C3*/ + pinList = esp32c3pins; + /*ENDIF_ESP32-C3*/ + + en.checked = obj["en"]; + e.replaceChildren ( + ml("div", {class: "row mb-3"}, [ + ml("div", {class: "col-8 col-sm-3 my-2"}, "{#ETH_ENABLE}"), + ml("div", {class: "col-4 col-sm-9"}, en) + ]) + ); + pins = [['cs', 'ethCs'], ['sclk', 'ethSclk'], ['miso', 'ethMiso'], ['mosi', 'ethMosi'], ['irq', 'ethIrq'], ['reset', 'ethRst']]; + for(p of pins) { + e.append( + ml("div", {class: "row mb-3"}, [ + ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), + ml("div", {class: "col-12 col-sm-9"}, + sel(p[1], pinList, obj[p[0]]) + ) + ]) + ); + } + } + /*ENDIF_ETHERNET*/ + function parseSerial(obj) { var e = document.getElementById("serialCb") var l = [["serEn", "show_live_data", "{#LOG_PRINT_INVERTER_DATA}"], ["serDbg", "debug", "{#LOG_SERIAL_DEBUG}"], ["priv", "priv", "{#LOG_PRIVACY_MODE}"], ["wholeTrace", "wholeTrace", "{#LOG_PRINT_TRACES}"], ["log2mqtt", "log2mqtt", "{#LOG_TO_MQTT}"]] @@ -1253,10 +1292,13 @@ parseNtp(root["ntp"]); parseSun(root["sun"]); parsePinout(root["pinout"], root["system"]["esp_type"], root["system"]); - parseNrfRadio(root["radioNrf"], root["pinout"], root["system"]["esp_type"], root["system"]); + parseNrfRadio(root["radioNrf"], root["pinout"]); /*IF_ESP32*/ - parseCmtRadio(root["radioCmt"], root["system"]["esp_type"], root["system"]); + parseCmtRadio(root["radioCmt"]); /*ENDIF_ESP32*/ + /*IF_ETHERNET*/ + parseEth(root.system.eth) + /*ENDIF_ETHERNET*/ parseSerial(root["serial"]); /*IF_PLUGIN_DISPLAY*/ parseDisplay(root["display"], root["system"]["esp_type"], root["system"]); diff --git a/src/web/lang.json b/src/web/lang.json index f1723688..419dd4f4 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -723,6 +723,11 @@ "en": "CMT2300A radio enable", "de": "CMT2300A Funkmodul aktivieren" }, + { + "token": "ETH_ENABLE", + "en": "Ethernet enable", + "de": "Ethernet aktivieren" + }, { "token": "DISP_NONE", "en": "None", diff --git a/src/web/web.h b/src/web/web.h index 3e7d00a8..f4389163 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -37,14 +37,19 @@ #define WEB_SERIAL_BUF_SIZE 2048 -const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinSclk", "pinMosi", "pinMiso", "pinLed0", "pinLed1", "pinLed2", "pinLedHighActive", "pinLedLum", "pinCmtSclk", "pinSdio", "pinCsb", "pinFcsb", "pinGpio3"}; +const char* const pinArgNames[] = { + "pinCs", "pinCe", "pinIrq", "pinSclk", "pinMosi", "pinMiso", "pinLed0", + "pinLed1", "pinLed2", "pinLedHighActive", "pinLedLum", "pinCmtSclk", + "pinSdio", "pinCsb", "pinFcsb", "pinGpio3" + #if defined (ETHERNET) + , "ethCs", "ethSclk", "ethMiso", "ethMosi", "ethIrq", "ethRst" + #endif +}; template class Web { public: - Web(void) : mWeb(80), mEvts("/events") { - memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE); - } + Web(void) : mWeb(80), mEvts("/events") {} void setup(IApp *app, HMSYSTEM *sys, settings_t *config) { mApp = app; @@ -101,11 +106,17 @@ class Web { void tickSecond() { if (mSerialClientConnnected) { + if(nullptr == mSerialBuf) + return; + if (mSerialBufFill > 0) { mEvts.send(mSerialBuf, "serial", millis()); memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE); mSerialBufFill = 0; } + } else if(nullptr != mSerialBuf) { + delete[] mSerialBuf; + mSerialBuf = nullptr; } } @@ -177,6 +188,9 @@ class Web { if (!mSerialClientConnnected) return; + if(nullptr == mSerialBuf) + return; + msg.replace("\r\n", ""); if (mSerialAddTime) { if ((13 + mSerialBufFill) < WEB_SERIAL_BUF_SIZE) { @@ -293,6 +307,10 @@ class Web { void onConnect(AsyncEventSourceClient *client) { DPRINTLN(DBG_VERBOSE, "onConnect"); + if(nullptr == mSerialBuf) { + mSerialBuf = new char[WEB_SERIAL_BUF_SIZE]; + memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE); + } mSerialClientConnnected = true; if (client->lastId()) @@ -482,7 +500,12 @@ class Web { // pinout - for (uint8_t i = 0; i < 16; i++) { + #if defined(ETHERNET) + for (uint8_t i = 0; i < 22; i++) + #else + for (uint8_t i = 0; i < 16; i++) + #endif + { uint8_t pin = request->arg(String(pinArgNames[i])).toInt(); switch(i) { case 0: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_NRF_CS_PIN); break; @@ -501,11 +524,23 @@ class Web { case 13: mConfig->cmt.pinCsb = pin; break; case 14: mConfig->cmt.pinFcsb = pin; break; case 15: mConfig->cmt.pinIrq = pin; break; + + #if defined(ETHERNET) + case 16: mConfig->sys.eth.pinCs = pin; break; + case 17: mConfig->sys.eth.pinSclk = pin; break; + case 18: mConfig->sys.eth.pinMiso = pin; break; + case 19: mConfig->sys.eth.pinMosi = pin; break; + case 20: mConfig->sys.eth.pinIrq = pin; break; + case 21: mConfig->sys.eth.pinRst = pin; break; + #endif } } mConfig->nrf.enabled = (request->arg("nrfEnable") == "on"); mConfig->cmt.enabled = (request->arg("cmtEnable") == "on"); + #if defined(ETHERNET) + mConfig->sys.eth.enabled = (request->arg("ethEn") == "on"); + #endif // ntp if (request->arg("ntpAddr") != "") { @@ -906,7 +941,7 @@ class Web { settings_t *mConfig = nullptr; bool mSerialAddTime = true; - char mSerialBuf[WEB_SERIAL_BUF_SIZE]; + char *mSerialBuf = nullptr; uint16_t mSerialBufFill = 0; bool mSerialClientConnnected = false; diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 78ec6ab1..acf6d7d4 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -63,7 +63,7 @@ class ahoywifi { void connectionEvent(WiFiStatus_t status); bool isTimeout(uint8_t timeout) { return (mCnt % timeout) == 0; } -#if defined(ESP8266) + #if defined(ESP8266) void onConnect(const WiFiEventStationModeConnected& event); void onGotIP(const WiFiEventStationModeGotIP& event); void onDisconnect(const WiFiEventStationModeDisconnected& event); From 89f7b4f1c6ff22238fa1749be7b487fb185d3b5c Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 21 Mar 2024 21:06:02 +0100 Subject: [PATCH 043/201] ethernet and wifi are working for ESP32 --- src/app.cpp | 38 +-- src/app.h | 39 +-- src/appInterface.h | 4 +- src/config/settings.h | 3 +- src/eth/ahoyeth.cpp | 179 ----------- src/eth/ahoyeth.h | 65 ---- src/network/AhoyEthernet.h | 87 +++--- src/network/AhoyNetwork.h | 43 +-- src/network/AhoyNetworkHelper.cpp | 20 ++ src/network/AhoyNetworkHelper.h | 12 +- src/network/AhoyWifiAp.h | 11 +- src/network/AhoyWifiEsp32.h | 112 +++++++ src/publisher/pubMqtt.h | 14 +- src/web/RestApi.h | 4 +- src/wifi/ahoywifi.cpp | 490 ------------------------------ src/wifi/ahoywifi.h | 100 ------ 16 files changed, 238 insertions(+), 983 deletions(-) delete mode 100644 src/eth/ahoyeth.cpp delete mode 100644 src/eth/ahoyeth.h create mode 100644 src/network/AhoyNetworkHelper.cpp create mode 100644 src/network/AhoyWifiEsp32.h delete mode 100644 src/wifi/ahoywifi.cpp delete mode 100644 src/wifi/ahoywifi.h diff --git a/src/app.cpp b/src/app.cpp index 37b0a37a..0d0d2698 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -53,17 +53,16 @@ void app::setup() { mCmtRadio.setup(&mConfig->serial.debug, &mConfig->serial.privacyLog, &mConfig->serial.printWholeTrace, mConfig->cmt.pinSclk, mConfig->cmt.pinSdio, mConfig->cmt.pinCsb, mConfig->cmt.pinFcsb, mConfig->sys.region); } #endif + #ifdef ETHERNET delay(1000); - mEth.setup(mConfig, &mTimestamp, [this](bool gotIp) { this->onNetwork(gotIp); }, [this](bool gotTime) { this->onNtpUpdate(gotTime); }); + mNetwork = (AhoyNetwork*) new AhoyEthernet(); + #else + mNetwork = (AhoyNetwork*) new AhoyWifi(); #endif // ETHERNET - - #if !defined(ETHERNET) - mWifi.setup(mConfig, &mTimestamp, [this](bool gotIp) { this->onNetwork(gotIp); }, [this](bool gotTime) { this->onNtpUpdate(gotTime); }); - #if !defined(AP_ONLY) - everySec(std::bind(&ahoywifi::tickWifiLoop, &mWifi), "wifiL"); - #endif - #endif /* defined(ETHERNET) */ + mNetwork->setup(mConfig, &mTimestamp, [this](bool gotIp) { this->onNetwork(gotIp); }, [this](bool gotTime) { this->onNtpUpdate(gotTime); }); + mNetwork->begin(); + everySec(std::bind(&AhoyNetwork::tickNetworkLoop, mNetwork), "net"); esp_task_wdt_reset(); @@ -89,7 +88,7 @@ void app::setup() { #if defined(ENABLE_MQTT) mMqttEnabled = (mConfig->mqtt.broker[0] > 0); if (mMqttEnabled) { - mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, &mSys, &mTimestamp, &mUptime); + mMqtt.setup(this, &mConfig->mqtt, mConfig->sys.deviceName, mVersion, &mSys, &mTimestamp, &mUptime); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); mCommunication.addAlarmListener([this](Inverter<> *iv) { mMqtt.alarmEvent(iv); }); } @@ -171,12 +170,6 @@ void app::onNetwork(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 !defined(ETHERNET) - if (WIFI_AP == WiFi.getMode()) { - mMqttEnabled = false; - } - everySec(std::bind(&ahoywifi::tickWifiLoop, &mWifi), "wifiL"); - #endif /* !defined(ETHERNET) */ } //----------------------------------------------------------------------------- @@ -248,17 +241,10 @@ void app::updateNtp(void) { void app::tickNtpUpdate(void) { uint32_t nxtTrig = 5; // default: check again in 5 sec - #if defined(ETHERNET) - if (!mNtpReceived) - mEth.updateNtpTime(); - else - mNtpReceived = false; - #else - if (!mNtpReceived) - mWifi.updateNtpTime(); - else - mNtpReceived = false; - #endif + if (!mNtpReceived) + mNetwork->updateNtpTime(); + else + mNtpReceived = false; updateNtp(); nxtTrig = mConfig->ntp.interval * 60; // check again in 12h diff --git a/src/app.h b/src/app.h index a699bac0..b3e5cffa 100644 --- a/src/app.h +++ b/src/app.h @@ -37,9 +37,9 @@ #include "web/web.h" #include "hm/Communication.h" #if defined(ETHERNET) - #include "eth/ahoyeth.h" + #include "network/AhoyEthernet.h" #else /* defined(ETHERNET) */ - #include "wifi/ahoywifi.h" + #include "network/AhoyWifiEsp32.h" #include "utils/improv.h" #endif /* defined(ETHERNET) */ @@ -164,31 +164,30 @@ class app : public IApp, public ah::Scheduler { #if !defined(ETHERNET) void scanAvailNetworks() override { - mWifi.scanAvailNetworks(); + mNetwork->scanAvailNetworks(); } bool getAvailNetworks(JsonObject obj) override { - return mWifi.getAvailNetworks(obj); + return mNetwork->getAvailNetworks(obj); } void setupStation(void) override { - mWifi.setupStation(); + mNetwork->begin(); } - void setStopApAllowedMode(bool allowed) override { + /*void setStopApAllowedMode(bool allowed) override { mWifi.setStopApAllowedMode(allowed); - } - - String getStationIp(void) override { - return mWifi.getStationIp(); - } + }*/ bool getWasInCh12to14(void) const override { - return mWifi.getWasInCh12to14(); + return false; // @todo mWifi.getWasInCh12to14(); } - #endif /* !defined(ETHERNET) */ + String getIp(void) override { + return mNetwork->getIp(); + } + void setRebootFlag() override { once(std::bind(&app::tickReboot, this), 3, "rboot"); } @@ -295,13 +294,7 @@ class app : public IApp, public ah::Scheduler { DPRINT(DBG_DEBUG, F("setTimestamp: ")); DBGPRINTLN(String(newTime)); if(0 == newTime) - { - #if defined(ETHERNET) - mEth.updateNtpTime(); - #else /* defined(ETHERNET) */ - mWifi.updateNtpTime(); - #endif /* defined(ETHERNET) */ - } + mNetwork->updateNtpTime(); else Scheduler::setTimestamp(newTime); } @@ -414,11 +407,7 @@ class app : public IApp, public ah::Scheduler { bool mShowRebootRequest = false; - #if defined(ETHERNET) - ahoyeth mEth; - #else /* defined(ETHERNET) */ - ahoywifi mWifi; - #endif /* defined(ETHERNET) */ + AhoyNetwork *mNetwork; WebType mWeb; RestApiType mApi; Protection *mProtection = nullptr; diff --git a/src/appInterface.h b/src/appInterface.h index b465edf9..b7ee2aaf 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -29,10 +29,10 @@ class IApp { virtual void scanAvailNetworks() = 0; virtual bool getAvailNetworks(JsonObject obj) = 0; virtual void setupStation(void) = 0; - virtual void setStopApAllowedMode(bool allowed) = 0; - virtual String getStationIp(void) = 0; + //virtual void setStopApAllowedMode(bool allowed) = 0; virtual bool getWasInCh12to14(void) const = 0; #endif /* defined(ETHERNET) */ + virtual String getIp(void) = 0; virtual uint32_t getUptime() = 0; virtual uint32_t getTimestamp() = 0; diff --git a/src/config/settings.h b/src/config/settings.h index f130434c..ace968fb 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -91,10 +91,11 @@ typedef struct { char stationSsid[SSID_LEN]; char stationPwd[PWD_LEN]; bool isHidden; +#else + cfgEth_t eth; #endif /* !defined(ETHERNET) */ cfgIp_t ip; - cfgEth_t eth; } cfgSys_t; typedef struct { diff --git a/src/eth/ahoyeth.cpp b/src/eth/ahoyeth.cpp deleted file mode 100644 index 497a542f..00000000 --- a/src/eth/ahoyeth.cpp +++ /dev/null @@ -1,179 +0,0 @@ -//----------------------------------------------------------------------------- -// 2023 Ahoy, https://www.mikrocontroller.net/topic/525778 -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ -//----------------------------------------------------------------------------- - -#if defined(ETHERNET) - -#if defined(ESP32) && defined(F) - #undef F - #define F(sl) (sl) -#endif -#include "ahoyeth.h" -#include - -//----------------------------------------------------------------------------- -ahoyeth::ahoyeth() -{ - // WiFi.onEvent(ESP32_W5500_event); -} - - -//----------------------------------------------------------------------------- -void ahoyeth::setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNetworkCB, OnTimeCB onTimeCB) { - mConfig = config; - mUtcTimestamp = utcTimestamp; - mOnNetworkCB = onNetworkCB; - mOnTimeCB = onTimeCB; - mEthConnected = false; - - Serial.flush(); - WiFi.onEvent([this](WiFiEvent_t event, arduino_event_info_t info) -> void { this->onEthernetEvent(event, info); }); - - Serial.flush(); - mEthSpi.begin(config->sys.eth.pinMiso, config->sys.eth.pinMosi, config->sys.eth.pinSclk, config->sys.eth.pinCs, config->sys.eth.pinIrq, config->sys.eth.pinRst); - - if(mConfig->sys.ip.ip[0] != 0) { - IPAddress ip(mConfig->sys.ip.ip); - IPAddress mask(mConfig->sys.ip.mask); - IPAddress dns1(mConfig->sys.ip.dns1); - IPAddress dns2(mConfig->sys.ip.dns2); - IPAddress gateway(mConfig->sys.ip.gateway); - if(!ETH.config(ip, gateway, mask, dns1, dns2)) - DPRINTLN(DBG_ERROR, F("failed to set static IP!")); - } -} - - -//----------------------------------------------------------------------------- -bool ahoyeth::updateNtpTime(void) { - if (!ETH.localIP()) - return false; - - DPRINTLN(DBG_DEBUG, F("updateNtpTime: checking udp \"connection\"...")); Serial.flush(); - if (!mUdp.connected()) { - DPRINTLN(DBG_DEBUG, F("updateNtpTime: About to (re)connect...")); Serial.flush(); - IPAddress timeServer; - if (!WiFi.hostByName(mConfig->ntp.addr, timeServer)) - return false; - - if (!mUdp.connect(timeServer, mConfig->ntp.port)) - return false; - - DPRINTLN(DBG_DEBUG, F("updateNtpTime: Connected...")); Serial.flush(); - mUdp.onPacket([this](AsyncUDPPacket packet) { - DPRINTLN(DBG_DEBUG, F("updateNtpTime: about to handle ntp packet...")); Serial.flush(); - this->handleNTPPacket(packet); - }); - } - - DPRINTLN(DBG_DEBUG, F("updateNtpTime: prepare packet...")); Serial.flush(); - - // set all bytes in the buffer to 0 - memset(mUdpPacketBuffer, 0, NTP_PACKET_SIZE); - // Initialize values needed to form NTP request - // (see URL above for details on the packets) - - mUdpPacketBuffer[0] = 0b11100011; // LI, Version, Mode - mUdpPacketBuffer[1] = 0; // Stratum, or type of clock - mUdpPacketBuffer[2] = 6; // Polling Interval - mUdpPacketBuffer[3] = 0xEC; // Peer Clock Precision - - // 8 bytes of zero for Root Delay & Root Dispersion - mUdpPacketBuffer[12] = 49; - mUdpPacketBuffer[13] = 0x4E; - mUdpPacketBuffer[14] = 49; - mUdpPacketBuffer[15] = 52; - - //Send unicast - DPRINTLN(DBG_DEBUG, F("updateNtpTime: send packet...")); Serial.flush(); - mUdp.write(mUdpPacketBuffer, sizeof(mUdpPacketBuffer)); - - return true; -} - -//----------------------------------------------------------------------------- -void ahoyeth::handleNTPPacket(AsyncUDPPacket packet) { - char buf[80]; - - memcpy(buf, packet.data(), sizeof(buf)); - - unsigned long highWord = word(buf[40], buf[41]); - unsigned long lowWord = word(buf[42], buf[43]); - - // combine the four bytes (two words) into a long integer - // this is NTP time (seconds since Jan 1 1900): - unsigned long secsSince1900 = highWord << 16 | lowWord; - - *mUtcTimestamp = secsSince1900 - 2208988800UL; // UTC time - DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(*mUtcTimestamp) + " UTC"); - mOnTimeCB(true); -} - -//----------------------------------------------------------------------------- -void ahoyeth::welcome(String ip, String mode) { - DBGPRINTLN(F("\n\n--------------------------------")); - DBGPRINTLN(F("Welcome to AHOY!")); - DBGPRINT(F("\npoint your browser to http://")); - DBGPRINT(ip); - DBGPRINTLN(mode); - DBGPRINTLN(F("to configure your device")); - DBGPRINTLN(F("--------------------------------\n")); -} - -void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) { - DPRINTLN(DBG_VERBOSE, F("[ETH]: Got event...")); - switch (event) { - case ARDUINO_EVENT_ETH_START: - DPRINTLN(DBG_VERBOSE, F("ETH Started")); - - if(String(mConfig->sys.deviceName) != "") - ETH.setHostname(mConfig->sys.deviceName); - else - ETH.setHostname(F("ESP32_W5500")); - break; - - case ARDUINO_EVENT_ETH_CONNECTED: - DPRINTLN(DBG_VERBOSE, F("ETH Connected")); - break; - - case ARDUINO_EVENT_ETH_GOT_IP: - if (!mEthConnected) { - /*DPRINT(DBG_INFO, F("ETH MAC: ")); - DBGPRINT(mEthSpi.macAddress());*/ - welcome(ETH.localIP().toString(), F(" (Station)")); - - mEthConnected = true; - mOnNetworkCB(true); - } - - if (!MDNS.begin(mConfig->sys.deviceName)) { - DPRINTLN(DBG_ERROR, F("Error setting up MDNS responder!")); - } else { - DBGPRINT(F("mDNS established: ")); - DBGPRINT(mConfig->sys.deviceName); - DBGPRINTLN(F(".local")); - } - break; - - case ARDUINO_EVENT_ETH_DISCONNECTED: - DPRINTLN(DBG_INFO, F("ETH Disconnected")); - mEthConnected = false; - mUdp.close(); - mOnNetworkCB(false); - break; - - case ARDUINO_EVENT_ETH_STOP: - DPRINTLN(DBG_INFO, F("ETH Stopped")); - mEthConnected = false; - mUdp.close(); - mOnNetworkCB(false); - break; - - default: - break; - } - -} - -#endif /* defined(ETHERNET) */ diff --git a/src/eth/ahoyeth.h b/src/eth/ahoyeth.h deleted file mode 100644 index 557db5ec..00000000 --- a/src/eth/ahoyeth.h +++ /dev/null @@ -1,65 +0,0 @@ -//----------------------------------------------------------------------------- -// 2024 Ahoy, https://github.com/lumpapu/ahoy -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed -//----------------------------------------------------------------------------- - -#if defined(ETHERNET) -#ifndef __AHOYETH_H__ -#define __AHOYETH_H__ - -#include - -#include "../utils/dbg.h" -#include -#include -#include - -#include "ethSpi.h" -#include -#include "../utils/dbg.h" -#include "../config/config.h" -#include "../config/settings.h" - - -class app; - -#define NTP_PACKET_SIZE 48 - -class ahoyeth { - public: /* types */ - typedef std::function OnNetworkCB; - typedef std::function OnTimeCB; - - public: - ahoyeth(); - - void setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNetworkCB, OnTimeCB onTimeCB); - bool updateNtpTime(void); - - private: - void setupEthernet(); - - void handleNTPPacket(AsyncUDPPacket packet); - - void welcome(String ip, String mode); - - void onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info); - - private: - //#if defined(CONFIG_IDF_TARGET_ESP32S3) - EthSpi mEthSpi; - //#endif - settings_t *mConfig = nullptr; - - uint32_t *mUtcTimestamp; - AsyncUDP mUdp; // for time server - byte mUdpPacketBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets - - OnNetworkCB mOnNetworkCB; - OnTimeCB mOnTimeCB; - bool mEthConnected; - -}; - -#endif /*__AHOYETH_H__*/ -#endif /* defined(ETHERNET) */ diff --git a/src/network/AhoyEthernet.h b/src/network/AhoyEthernet.h index c56b4338..ce176ec3 100644 --- a/src/network/AhoyEthernet.h +++ b/src/network/AhoyEthernet.h @@ -6,77 +6,64 @@ #ifndef __AHOY_ETHERNET_H__ #define __AHOY_ETHERNET_H__ +#if defined(ETHERNET) #include #include #include #include "AhoyEthernetSpi.h" -#include "AhoyEthernet.h" +#include "AhoyNetwork.h" class AhoyEthernet : public AhoyNetwork { public: void begin() override { + mAp.enable(); + + // static IP setupIp([this](IPAddress ip, IPAddress gateway, IPAddress mask, IPAddress dns1, IPAddress dns2) -> bool { return ETH.config(ip, gateway, mask, dns1, dns2); }); + + ETH.setHostname(mConfig->sys.deviceName); } void tickNetworkLoop() override { - switch(mState) { + if(mAp.isEnabled()) + mAp.tickLoop(); + + switch(mStatus) { case NetworkState::DISCONNECTED: + if(mConnected) { + mConnected = false; + mOnNetworkCB(false); + mAp.enable(); + } break; - } - } - - private: - - /*switch (event) { - case ARDUINO_EVENT_ETH_START: - DPRINTLN(DBG_VERBOSE, F("ETH Started")); - - if(String(mConfig->sys.deviceName) != "") - ETH.setHostname(mConfig->sys.deviceName); - else - ETH.setHostname(F("ESP32_W5500")); - break; - case ARDUINO_EVENT_ETH_CONNECTED: - DPRINTLN(DBG_VERBOSE, F("ETH Connected")); - break; - - case ARDUINO_EVENT_ETH_GOT_IP: - if (!mEthConnected) { - welcome(ETH.localIP().toString(), F(" (Station)")); - - mEthConnected = true; - mOnNetworkCB(true); - } + case NetworkState::CONNECTED: + break; - if (!MDNS.begin(mConfig->sys.deviceName)) { - DPRINTLN(DBG_ERROR, F("Error setting up MDNS responder!")); - } else { - DBGPRINT(F("mDNS established: ")); - DBGPRINT(mConfig->sys.deviceName); - DBGPRINTLN(F(".local")); - } - break; + case NetworkState::GOT_IP: + mAp.disable(); - case ARDUINO_EVENT_ETH_DISCONNECTED: - DPRINTLN(DBG_INFO, F("ETH Disconnected")); - mEthConnected = false; - mUdp.close(); - mOnNetworkCB(false); - break; + if(!mConnected) { + mConnected = true; + ah::welcome(ETH.localIP().toString(), F("Station")); + MDNS.begin(mConfig->sys.deviceName); + mOnNetworkCB(true); + } + break; + } + } - case ARDUINO_EVENT_ETH_STOP: - DPRINTLN(DBG_INFO, F("ETH Stopped")); - mEthConnected = false; - mUdp.close(); - mOnNetworkCB(false); - break; + String getIp(void) override { + return ETH.localIP().toString(); + } - default: - break; - }*/ + void scanAvailNetworks(void) override {}; + bool getAvailNetworks(JsonObject obj) override { + return false; + } }; +#endif /*ETHERNET*/ #endif /*__AHOY_ETHERNET_H__*/ diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index 01d7cd8c..952206f0 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -7,9 +7,11 @@ #define __AHOY_NETWORK_H__ #include "AhoyNetworkHelper.h" -#include +#include #include "../config/settings.h" #include "../utils/helper.h" +#include "AhoyWifiAp.h" +#include "AsyncJson.h" #if defined(ESP32) #include @@ -31,9 +33,15 @@ class AhoyNetwork { mOnNetworkCB = onNetworkCB; mOnTimeCB = onTimeCB; + if('\0' == mConfig->sys.deviceName[0]) + snprintf(mConfig->sys.deviceName, DEVNAME_LEN, "%s", DEF_DEVICE_NAME); + WiFi.hostname(mConfig->sys.deviceName); + + mAp.setup(&mConfig->sys); + #if defined(ESP32) - WiFi.onEvent([this](WiFiEvent_t event) -> void { - this->OnEvent(event); + WiFi.onEvent([this](WiFiEvent_t event, arduino_event_info_t info) -> void { + OnEvent(event); }); #else wifiConnectHandler = WiFi.onStationModeConnected( @@ -52,15 +60,15 @@ class AhoyNetwork { } bool isConnected() const { - return (mStatus == NetworkState.CONNECTED); + return (mStatus == NetworkState::CONNECTED); } bool updateNtpTime(void) { - if(CONNECTED != mStatus) - return; + if(NetworkState::CONNECTED != mStatus) + return false; + IPAddress timeServer; if (!mUdp.connected()) { - IPAddress timeServer; if (!WiFi.hostByName(mConfig->ntp.addr, timeServer)) return false; if (!mUdp.connect(timeServer, mConfig->ntp.port)) @@ -78,17 +86,19 @@ class AhoyNetwork { public: virtual void begin() = 0; virtual void tickNetworkLoop() = 0; - virtual void connectionEvent(WiFiStatus_t status) = 0; + virtual String getIp(void) = 0; + virtual void scanAvailNetworks(void) = 0; + virtual bool getAvailNetworks(JsonObject obj) = 0; protected: - void setupIp(void) { + void setupIp(std::function cb) { if(mConfig->sys.ip.ip[0] != 0) { IPAddress ip(mConfig->sys.ip.ip); IPAddress mask(mConfig->sys.ip.mask); IPAddress dns1(mConfig->sys.ip.dns1); IPAddress dns2(mConfig->sys.ip.dns2); IPAddress gateway(mConfig->sys.ip.gateway); - if(!ETH.config(ip, gateway, mask, dns1, dns2)) + if(cb(ip, gateway, mask, dns1, dns2)) DPRINTLN(DBG_ERROR, F("failed to set static IP!")); } } @@ -169,25 +179,22 @@ class AhoyNetwork { protected: enum class NetworkState : uint8_t { DISCONNECTED, - CONNECTING, CONNECTED, - IN_AP_MODE, - GOT_IP, - IN_STA_MODE, - RESET, - SCAN_READY + GOT_IP }; protected: settings_t *mConfig = nullptr; uint32_t *mUtcTimestamp = nullptr; + bool mConnected = false; OnNetworkCB mOnNetworkCB; OnTimeCB mOnTimeCB; - NetworkState mStatus = NetworkState.DISCONNECTED; + NetworkState mStatus = NetworkState::DISCONNECTED; - WiFiUDP mUdp; // for time server + AhoyWifiAp mAp; + AsyncUDP mUdp; // for time server DNSServer mDns; }; diff --git a/src/network/AhoyNetworkHelper.cpp b/src/network/AhoyNetworkHelper.cpp new file mode 100644 index 00000000..09678023 --- /dev/null +++ b/src/network/AhoyNetworkHelper.cpp @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#include "AhoyNetworkHelper.h" + +namespace ah { + void welcome(String ip, String info) { + DBGPRINTLN(F("\n\n-------------------")); + DBGPRINTLN(F("Welcome to AHOY!")); + DBGPRINT(F("\npoint your browser to http://")); + DBGPRINT(ip); + DBGPRINT(" ("); + DBGPRINT(info); + DBGPRINTLN(")"); + DBGPRINTLN(F("to configure your device")); + DBGPRINTLN(F("-------------------\n")); + } +} diff --git a/src/network/AhoyNetworkHelper.h b/src/network/AhoyNetworkHelper.h index ab23f5bc..f814f1db 100644 --- a/src/network/AhoyNetworkHelper.h +++ b/src/network/AhoyNetworkHelper.h @@ -13,17 +13,7 @@ #include namespace ah { - void welcome(String ip, String info) { - DBGPRINTLN(F("\n\n-------------------")); - DBGPRINTLN(F("Welcome to AHOY!")); - DBGPRINT(F("\npoint your browser to http://")); - DBGPRINT(ip); - DBGPRINT(" ("); - DBGPRINT(info); - DBGPRINTLN(")"); - DBGPRINTLN(F("to configure your device")); - DBGPRINTLN(F("-------------------\n")); - } + void welcome(String ip, String info); } #endif /*__AHOY_NETWORK_HELPER_H__*/ diff --git a/src/network/AhoyWifiAp.h b/src/network/AhoyWifiAp.h index f919e030..3c75dc12 100644 --- a/src/network/AhoyWifiAp.h +++ b/src/network/AhoyWifiAp.h @@ -25,10 +25,10 @@ class AhoyWifiAp { } void enable() { + if(mEnabled) + return; + ah::welcome(mIp.toString(), String(F("Password: ") + String(mCfg->apPwd))); - if('\0' == mCfg->deviceName[0]) - snprintf(mCfg->deviceName, DEVNAME_LEN, "%s", DEF_DEVICE_NAME); - WiFi.hostname(mCfg->deviceName); #if defined(ETHERNET) WiFi.mode(WIFI_AP); @@ -45,6 +45,9 @@ class AhoyWifiAp { } void disable() { + if(!mEnabled) + return; + mDns.stop(); WiFi.softAPdisconnect(); #if defined(ETHERNET) @@ -56,7 +59,7 @@ class AhoyWifiAp { mEnabled = false; } - bool getEnable() const { + bool isEnabled() const { return mEnabled; } diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h new file mode 100644 index 00000000..53d39af3 --- /dev/null +++ b/src/network/AhoyWifiEsp32.h @@ -0,0 +1,112 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __AHOY_Wifi_ESP32_H__ +#define __AHOY_Wifi_ESP32_H__ + +#if defined(ESP32) && !defined(ETHERNET) +#include +#include +#include +#include "AhoyNetwork.h" + +class AhoyWifi : public AhoyNetwork { + public: + void begin() override { + mAp.enable(); + + // static IP + setupIp([this](IPAddress ip, IPAddress gateway, IPAddress mask, IPAddress dns1, IPAddress dns2) -> bool { + return WiFi.config(ip, gateway, mask, dns1, dns2); + }); + + WiFi.setHostname(mConfig->sys.deviceName); + WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); + WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL); + WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, WIFI_ALL_CHANNEL_SCAN); + + DBGPRINT(F("connect to network '")); Serial.flush(); + DBGPRINT(mConfig->sys.stationSsid); + } + + void tickNetworkLoop() override { + if(mAp.isEnabled()) + mAp.tickLoop(); + + switch(mStatus) { + case NetworkState::DISCONNECTED: + if(mConnected) { + mConnected = false; + mOnNetworkCB(false); + mAp.enable(); + } + + if (WiFi.softAPgetStationNum() > 0) { + DBGPRINTLN(F("AP client connected")); + } + break; + + case NetworkState::CONNECTED: + break; + + case NetworkState::GOT_IP: + if(!mConnected) { + mAp.disable(); + mConnected = true; + ah::welcome(WiFi.localIP().toString(), F("Station")); + MDNS.begin(mConfig->sys.deviceName); + mOnNetworkCB(true); + } + break; + } + } + + String getIp(void) override { + return WiFi.localIP().toString(); + } + + void scanAvailNetworks(void) override { + if(!mScanActive) { + mScanActive = true; + WiFi.scanNetworks(true); + } + } + + bool getAvailNetworks(JsonObject obj) override { + JsonArray nets = obj.createNestedArray(F("networks")); + + int n = WiFi.scanComplete(); + if (n < 0) + return false; + if(n > 0) { + int sort[n]; + sortRSSI(&sort[0], n); + for (int i = 0; i < n; ++i) { + nets[i][F("ssid")] = WiFi.SSID(sort[i]); + nets[i][F("rssi")] = WiFi.RSSI(sort[i]); + } + } + mScanActive = false; + WiFi.scanDelete(); + + return true; + } + + private: + void 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]); + } + + private: + bool mScanActive = false; +}; + +#endif /*ESP32 & !ETHERNET*/ +#endif /*__AHOY_Wifi_ESP32_H__*/ diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 2dbf67ec..2d393b8b 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -16,10 +16,6 @@ #endif #include -#if defined(ETHERNET) -#include "../eth/ahoyeth.h" -#endif - #include "../utils/dbg.h" #include "../config/config.h" #include @@ -56,7 +52,8 @@ class PubMqtt { ~PubMqtt() { } - void setup(cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs, uint32_t *uptime) { + void setup(IApp *app, cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs, uint32_t *uptime) { + mApp = app; mCfgMqtt = cfg_mqtt; mDevName = devName; mVersion = version; @@ -256,11 +253,7 @@ class PubMqtt { publish(subtopics[MQTT_VERSION], mVersion, true); publish(subtopics[MQTT_DEVICE], mDevName, true); - #if defined(ETHERNET) - publish(subtopics[MQTT_IP_ADDR], ETH.localIP().toString().c_str(), true); - #else - publish(subtopics[MQTT_IP_ADDR], WiFi.localIP().toString().c_str(), true); - #endif + publish(subtopics[MQTT_IP_ADDR], mApp->getIp().c_str(), true); tickerMinute(); publish(mLwtTopic.data(), mqttStr[MQTT_STR_LWT_CONN], true, false); @@ -611,6 +604,7 @@ class PubMqtt { espMqttClient mClient; cfgMqtt_t *mCfgMqtt = nullptr; + IApp *mApp; #if defined(ESP8266) WiFiEventHandler mHWifiCon, mHWifiDiscon; #endif diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 197c6982..4dcd7c9b 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -893,7 +893,7 @@ class RestApi { mApp->getAvailNetworks(obj); } void getWifiIp(JsonObject obj) { - obj[F("ip")] = mApp->getStationIp(); + obj[F("ip")] = mApp->getIp(); } #endif /* !defined(ETHERNET) */ @@ -1048,7 +1048,7 @@ class RestApi { snprintf(mConfig->sys.stationSsid, SSID_LEN, "%s", jsonIn[F("ssid")].as()); snprintf(mConfig->sys.stationPwd, PWD_LEN, "%s", jsonIn[F("pwd")].as()); mApp->saveSettings(false); // without reboot - mApp->setStopApAllowedMode(false); + //mApp->setStopApAllowedMode(false); mApp->setupStation(); } #endif /* !defined(ETHERNET */ diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp deleted file mode 100644 index 95bf0b8a..00000000 --- a/src/wifi/ahoywifi.cpp +++ /dev/null @@ -1,490 +0,0 @@ -//----------------------------------------------------------------------------- -// 2024 Ahoy, https://ahoydtu.de -// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed -//----------------------------------------------------------------------------- - -#if !defined(ETHERNET) -#if defined(ESP32) && defined(F) - #undef F - #define F(sl) (sl) -#endif -#include "ahoywifi.h" - -#if defined(ESP32) -#include -#else -#include -#endif - -// NTP CONFIG -#define NTP_PACKET_SIZE 48 - -//----------------------------------------------------------------------------- -ahoywifi::ahoywifi() : mApIp(192, 168, 4, 1) {} - - -/** - * TODO: ESP32 has native strongest AP support! - * WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); - WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL); -*/ - -//----------------------------------------------------------------------------- -void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb, OnTimeCB onTimeCb) { - mConfig = config; - mUtcTimestamp = utcTimestamp; - mAppWifiCb = cb; - mOnTimeCb = onTimeCb; - - mGotDisconnect = false; - mStaConn = DISCONNECTED; - mCnt = 0; - mScanActive = false; - mScanCnt = 0; - mStopApAllowed = true; - - #if defined(ESP8266) - wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); - wifiGotIPHandler = WiFi.onStationModeGotIP(std::bind(&ahoywifi::onGotIP, 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 - - setupWifi(true); -} - - -//----------------------------------------------------------------------------- -void ahoywifi::setupWifi(bool startAP = false) { - #if !defined(FB_WIFI_OVERRIDDEN) - if(startAP) { - setupAp(); - delay(1000); - } - #endif - #if !defined(AP_ONLY) - #if defined(FB_WIFI_OVERRIDDEN) - snprintf(mConfig->sys.stationSsid, SSID_LEN, "%s", FB_WIFI_SSID); - snprintf(mConfig->sys.stationPwd, PWD_LEN, "%s", FB_WIFI_PWD); - setupStation(); - #else - if(mConfig->valid) { - if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) != 0) - setupStation(); - } - #endif - #endif -} - - -void ahoywifi::tickWifiLoop() { - static const uint8_t TIMEOUT = 20; - static const uint8_t SCAN_TIMEOUT = 10; - #if !defined(AP_ONLY) - - mCnt++; - - switch (mStaConn) { - case IN_STA_MODE: - // Nothing to do - if (mGotDisconnect) { - mStaConn = RESET; - } - #if !defined(ESP32) - MDNS.update(); - if(WiFi.channel() > 11) - mWasInCh12to14 = true; - #endif - return; - case IN_AP_MODE: - if ((WiFi.softAPgetStationNum() == 0) || (!mStopApAllowed)) { - mCnt = 0; - mDns.stop(); - WiFi.mode(WIFI_AP_STA); - mStaConn = DISCONNECTED; - } else { - mDns.processNextRequest(); - return; - } - break; - case DISCONNECTED: - if ((WiFi.softAPgetStationNum() > 0) && (mStopApAllowed)) { - mStaConn = IN_AP_MODE; - // first time switch to AP Mode - if (mScanActive) { - WiFi.scanDelete(); - 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 (!mScanActive) { - DBGPRINT(F("scanning APs with SSID ")); - DBGPRINTLN(String(mConfig->sys.stationSsid)); - mScanCnt = 0; - mCnt = 0; - mScanActive = true; -#if defined(ESP8266) - WiFi.scanNetworks(true, true, 0U, ([this]() { - if (mConfig->sys.isHidden) - return (uint8_t*)NULL; - return (uint8_t*)(mConfig->sys.stationSsid); - })()); -#else - WiFi.scanNetworks(true, true, false, 300U, 0U, ([this]() { - if (mConfig->sys.isHidden) - return (char*)NULL; - return (mConfig->sys.stationSsid); - })()); -#endif - return; - } else if(getBSSIDs()) { - // Scan ready - mStaConn = SCAN_READY; - } else { - // In case of a timeout, what do we do? - // For now we start scanning again as the original code did. - // Would be better to into PA mode - - if (isTimeout(SCAN_TIMEOUT)) { - WiFi.scanDelete(); - mScanActive = false; - } - } - break; - case SCAN_READY: - mStaConn = CONNECTING; - mCnt = 0; - DBGPRINT(F("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(""); - mGotDisconnect = false; - WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, 0, &bssid[0]); - - break; - case CONNECTING: - if (isTimeout(TIMEOUT)) { - WiFi.disconnect(); - mStaConn = mBSSIDList.empty() ? DISCONNECTED : SCAN_READY; - } - break; - case CONNECTED: - // Connection but no IP yet - if (isTimeout(TIMEOUT) || mGotDisconnect) { - mStaConn = RESET; - } - break; - case GOT_IP: - welcome(WiFi.localIP().toString(), F(" (Station)")); - if(mStopApAllowed) { - WiFi.softAPdisconnect(); - WiFi.mode(WIFI_STA); - DBGPRINTLN(F("[WiFi] AP disabled")); - delay(100); - } - mAppWifiCb(true); - mGotDisconnect = false; - mStaConn = IN_STA_MODE; - - if (!MDNS.begin(mConfig->sys.deviceName)) { - DPRINTLN(DBG_ERROR, F("Error setting up MDNS responder!")); - } else { - DBGPRINT(F("mDNS established: ")); - DBGPRINT(mConfig->sys.deviceName); - DBGPRINTLN(F(".local")); - } - - break; - case RESET: - mGotDisconnect = false; - mStaConn = DISCONNECTED; - mCnt = 5; // try to reconnect in 5 sec - setupWifi(); // reconnect with AP / Station setup - mAppWifiCb(false); - DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); - break; - default: - DBGPRINTLN(F("Unhandled status")); - break; - } - -#endif -} - -//----------------------------------------------------------------------------- -void ahoywifi::setupAp(void) { - DPRINTLN(DBG_VERBOSE, F("wifi::setupAp")); - - DBGPRINTLN(F("\n---------\nAhoyDTU Info:")); - DBGPRINT(F("Version: ")); - DBGPRINT(String(VERSION_MAJOR)); - DBGPRINT(F(".")); - DBGPRINT(String(VERSION_MINOR)); - DBGPRINT(F(".")); - DBGPRINTLN(String(VERSION_PATCH)); - DBGPRINT(F("Github Hash: ")); - DBGPRINTLN(String(AUTO_GIT_HASH)); - - DBGPRINT(F("\n---------\nAP MODE\nSSID: ")); - DBGPRINTLN(WIFI_AP_SSID); - DBGPRINT(F("PWD: ")); - DBGPRINTLN(mConfig->sys.apPwd); - DBGPRINT(F("IP Address: http://")); - DBGPRINTLN(mApIp.toString()); - DBGPRINTLN(F("---------\n")); - - if(String(mConfig->sys.deviceName) != "") - WiFi.hostname(mConfig->sys.deviceName); - - WiFi.mode(WIFI_AP_STA); - WiFi.softAPConfig(mApIp, mApIp, IPAddress(255, 255, 255, 0)); - WiFi.softAP(WIFI_AP_SSID, mConfig->sys.apPwd); -} - - -//----------------------------------------------------------------------------- -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); - IPAddress dns1(mConfig->sys.ip.dns1); - IPAddress dns2(mConfig->sys.ip.dns2); - IPAddress gateway(mConfig->sys.ip.gateway); - if(!WiFi.config(ip, gateway, mask, dns1, dns2)) - DPRINTLN(DBG_ERROR, F("failed to set static IP!")); - } - mBSSIDList.clear(); - 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("' ...")); -} - - -//----------------------------------------------------------------------------- -bool ahoywifi::updateNtpTime(void) { - if(IN_STA_MODE != mStaConn) - return false; - - IPAddress timeServer; - uint8_t buf[NTP_PACKET_SIZE]; - uint8_t retry = 0; - - if (WiFi.hostByName(mConfig->ntp.addr, timeServer) != 1) - return false; - - mUdp.begin(mConfig->ntp.port); - sendNTPpacket(timeServer); - - while(retry++ < 5) { - int wait = 150; - while(--wait) { - if(NTP_PACKET_SIZE <= mUdp.parsePacket()) { - uint64_t secsSince1900; - mUdp.read(buf, NTP_PACKET_SIZE); - secsSince1900 = ((uint64_t)buf[40] << 24); - secsSince1900 |= (buf[41] << 16); - secsSince1900 |= (buf[42] << 8); - secsSince1900 |= (buf[43] ); - - *mUtcTimestamp = secsSince1900 - 2208988800UL; // UTC time - DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(*mUtcTimestamp) + " UTC"); - mOnTimeCb(true); - return true; - } else - delay(10); - } - } - - DPRINTLN(DBG_INFO, F("[NTP]: getNtpTime failed")); - return false; -} - - -//----------------------------------------------------------------------------- -void ahoywifi::sendNTPpacket(IPAddress& address) { - //DPRINTLN(DBG_VERBOSE, F("wifi::sendNTPpacket")); - uint8_t buf[NTP_PACKET_SIZE] = {0}; - - buf[0] = B11100011; // LI, Version, Mode - buf[1] = 0; // Stratum - buf[2] = 6; // Max Interval between messages in seconds - buf[3] = 0xEC; // Clock Precision - // bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset - buf[12] = 49; // four-byte reference ID identifying - buf[13] = 0x4E; - buf[14] = 49; - buf[15] = 52; - - mUdp.beginPacket(address, 123); // NTP request, port 123 - mUdp.write(buf, NTP_PACKET_SIZE); - 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) { - if(!mScanActive) { - mScanActive = true; - if(WIFI_AP == WiFi.getMode()) - WiFi.mode(WIFI_AP_STA); - WiFi.scanNetworks(true); - } -} - -//----------------------------------------------------------------------------- -bool ahoywifi::getAvailNetworks(JsonObject obj) { - JsonArray nets = obj.createNestedArray("networks"); - - int n = WiFi.scanComplete(); - if (n < 0) - return false; - if(n > 0) { - int sort[n]; - 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]); - } - } - mScanActive = false; - WiFi.scanDelete(); - if(mStaConn == IN_AP_MODE) - WiFi.mode(WIFI_AP); - - return true; -} - -//----------------------------------------------------------------------------- -bool ahoywifi::getBSSIDs() { - bool result = false; - int n = WiFi.scanComplete(); - if (n < 0) { - if (++mScanCnt < 20) - return false; - } - 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(""); - } - result = true; - } - mScanActive = false; - WiFi.scanDelete(); - return result; -} - -//----------------------------------------------------------------------------- -void ahoywifi::connectionEvent(WiFiStatus_t status) { - DPRINTLN(DBG_INFO, "connectionEvent"); - - switch(status) { - case CONNECTED: - if(mStaConn != CONNECTED) { - mStaConn = CONNECTED; - mGotDisconnect = false; - DBGPRINTLN(F("\n[WiFi] Connected")); - } - break; - - case GOT_IP: - mStaConn = GOT_IP; - break; - - case DISCONNECTED: - mGotDisconnect = true; - break; - - default: - break; - } -} - - -//----------------------------------------------------------------------------- -#if defined(ESP8266) - //------------------------------------------------------------------------- - void ahoywifi::onConnect(const WiFiEventStationModeConnected& event) { - connectionEvent(CONNECTED); - } - - //------------------------------------------------------------------------- - void ahoywifi::onGotIP(const WiFiEventStationModeGotIP& event) { - connectionEvent(GOT_IP); - } - - //------------------------------------------------------------------------- - void ahoywifi::onDisconnect(const WiFiEventStationModeDisconnected& event) { - connectionEvent(DISCONNECTED); - } - -#else - //------------------------------------------------------------------------- - void ahoywifi::onWiFiEvent(WiFiEvent_t event) { - DBGPRINT(F("Wifi event: ")); - DBGPRINTLN(String(event)); - - switch(event) { - case SYSTEM_EVENT_STA_CONNECTED: - connectionEvent(CONNECTED); - break; - - case SYSTEM_EVENT_STA_GOT_IP: - connectionEvent(GOT_IP); - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: - connectionEvent(DISCONNECTED); - break; - - default: - break; - } - } -#endif - - -//----------------------------------------------------------------------------- -void ahoywifi::welcome(String ip, String mode) { - DBGPRINTLN(F("\n\n--------------------------------")); - DBGPRINTLN(F("Welcome to AHOY!")); - DBGPRINT(F("\npoint your browser to http://")); - DBGPRINT(ip); - DBGPRINTLN(mode); - DBGPRINTLN(F("to configure your device")); - DBGPRINTLN(F("--------------------------------\n")); -} - -#endif /* !defined(ETHERNET) */ diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h deleted file mode 100644 index acf6d7d4..00000000 --- a/src/wifi/ahoywifi.h +++ /dev/null @@ -1,100 +0,0 @@ -//------------------------------------//----------------------------------------------------------------------------- -// 2024 Ahoy, https://github.com/lumpapu/ahoy -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed -//----------------------------------------------------------------------------- - -#if !defined(ETHERNET) -#ifndef __AHOYWIFI_H__ -#define __AHOYWIFI_H__ - -#include "../utils/dbg.h" -#include -#include -#include -#include -#include "ESPAsyncWebServer.h" - -#include "../config/settings.h" - -class app; - -class ahoywifi { - public: - typedef std::function appWifiCb; - typedef std::function OnTimeCB; - - ahoywifi(); - - - void setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb, OnTimeCB onTimeCB); - void tickWifiLoop(void); - bool updateNtpTime(void); - void scanAvailNetworks(void); - bool getAvailNetworks(JsonObject obj); - void setStopApAllowedMode(bool allowed) { - mStopApAllowed = allowed; - } - String getStationIp(void) { - return WiFi.localIP().toString(); - } - void setupStation(void); - - bool getWasInCh12to14() const { - return mWasInCh12to14; - } - - private: - typedef enum WiFiStatus { - DISCONNECTED = 0, - SCAN_READY, - CONNECTING, - CONNECTED, - IN_AP_MODE, - GOT_IP, - IN_STA_MODE, - RESET - } WiFiStatus_t; - - void setupWifi(bool startAP); - void setupAp(void); - void sendNTPpacket(IPAddress& address); - void sortRSSI(int *sort, int n); - bool getBSSIDs(void); - void connectionEvent(WiFiStatus_t status); - bool isTimeout(uint8_t timeout) { return (mCnt % timeout) == 0; } - - #if defined(ESP8266) - void onConnect(const WiFiEventStationModeConnected& event); - void onGotIP(const WiFiEventStationModeGotIP& event); - void onDisconnect(const WiFiEventStationModeDisconnected& event); - #else - void onWiFiEvent(WiFiEvent_t event); - #endif - void welcome(String ip, String mode); - - - settings_t *mConfig = nullptr; - appWifiCb mAppWifiCb; - OnTimeCB mOnTimeCb; - - DNSServer mDns; - IPAddress mApIp; - WiFiUDP mUdp; // for time server - #if defined(ESP8266) - WiFiEventHandler wifiConnectHandler, wifiDisconnectHandler, wifiGotIPHandler; - #endif - - WiFiStatus_t mStaConn = DISCONNECTED; - uint8_t mCnt = 0; - uint32_t *mUtcTimestamp = nullptr; - - uint8_t mScanCnt = 0; - bool mScanActive = false; - bool mGotDisconnect = false; - std::list mBSSIDList; - bool mStopApAllowed = false; - bool mWasInCh12to14 = false; -}; - -#endif /*__AHOYWIFI_H__*/ -#endif /* !defined(ETHERNET) */ From bb3f466c925f002c138bf6727a3622efffb60692 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 21 Mar 2024 22:41:02 +0100 Subject: [PATCH 044/201] started ESP8266 wifi refactored platformio.ini --- src/app.h | 6 +- src/network/AhoyNetwork.h | 21 ++-- src/network/AhoyNetworkHelper.h | 24 +++- src/network/AhoyWifiEsp32.h | 6 +- src/network/AhoyWifiEsp8266.h | 110 +++++++++++++++++ src/platformio.ini | 212 ++++---------------------------- 6 files changed, 175 insertions(+), 204 deletions(-) create mode 100644 src/network/AhoyWifiEsp8266.h diff --git a/src/app.h b/src/app.h index b3e5cffa..05b11469 100644 --- a/src/app.h +++ b/src/app.h @@ -39,7 +39,11 @@ #if defined(ETHERNET) #include "network/AhoyEthernet.h" #else /* defined(ETHERNET) */ - #include "network/AhoyWifiEsp32.h" + #if defined(ESP32) + #include "network/AhoyWifiEsp32.h" + #else + #include "network/AhoyWifiEsp8266.h" + #endif #include "utils/improv.h" #endif /* defined(ETHERNET) */ diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index 952206f0..7c51c38d 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -7,18 +7,11 @@ #define __AHOY_NETWORK_H__ #include "AhoyNetworkHelper.h" -#include #include "../config/settings.h" #include "../utils/helper.h" #include "AhoyWifiAp.h" #include "AsyncJson.h" -#if defined(ESP32) -#include -#else -#include -#endif - #define NTP_PACKET_SIZE 48 class AhoyNetwork { @@ -46,15 +39,15 @@ class AhoyNetwork { #else wifiConnectHandler = WiFi.onStationModeConnected( [this](const WiFiEventStationModeConnected& event) -> void { - OnEvent(SYSTEM_EVENT_STA_CONNECTED); + OnEvent((WiFiEvent_t)SYSTEM_EVENT_STA_CONNECTED); }); wifiGotIPHandler = WiFi.onStationModeGotIP( [this](const WiFiEventStationModeGotIP& event) -> void { - OnEvent(SYSTEM_EVENT_STA_GOT_IP); + OnEvent((WiFiEvent_t)SYSTEM_EVENT_STA_GOT_IP); }); wifiDisconnectHandler = WiFi.onStationModeDisconnected( [this](const WiFiEventStationModeDisconnected& event) -> void { - OnEvent(SYSTEM_EVENT_STA_DISCONNECTED); + OnEvent((WiFiEvent_t)SYSTEM_EVENT_STA_DISCONNECTED); }); #endif } @@ -194,8 +187,14 @@ class AhoyNetwork { NetworkState mStatus = NetworkState::DISCONNECTED; AhoyWifiAp mAp; - AsyncUDP mUdp; // for time server DNSServer mDns; + + #if defined(ESP32) + AsyncUDP mUdp; // for time server + #else + WiFiUDP mUdp; // for time server + WiFiEventHandler wifiConnectHandler, wifiDisconnectHandler, wifiGotIPHandler; + #endif }; #endif /*__AHOY_NETWORK_H__*/ diff --git a/src/network/AhoyNetworkHelper.h b/src/network/AhoyNetworkHelper.h index f814f1db..33f71029 100644 --- a/src/network/AhoyNetworkHelper.h +++ b/src/network/AhoyNetworkHelper.h @@ -8,8 +8,28 @@ #include "../utils/dbg.h" #include -#include -#include +#if defined(ESP32) + #include + #include + #include +#else + #include + #include + //#include + #include "ESPAsyncUDP.h" + + enum { + SYSTEM_EVENT_STA_CONNECTED = 1, + ARDUINO_EVENT_ETH_CONNECTED, + SYSTEM_EVENT_STA_GOT_IP, + ARDUINO_EVENT_ETH_GOT_IP, + ARDUINO_EVENT_WIFI_STA_LOST_IP, + ARDUINO_EVENT_WIFI_STA_STOP, + SYSTEM_EVENT_STA_DISCONNECTED, + ARDUINO_EVENT_ETH_STOP, + ARDUINO_EVENT_ETH_DISCONNECTED + }; +#endif #include namespace ah { diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index 53d39af3..f9fc064a 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -3,8 +3,8 @@ // Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- -#ifndef __AHOY_Wifi_ESP32_H__ -#define __AHOY_Wifi_ESP32_H__ +#ifndef __AHOY_WIFI_ESP32_H__ +#define __AHOY_WIFI_ESP32_H__ #if defined(ESP32) && !defined(ETHERNET) #include @@ -109,4 +109,4 @@ class AhoyWifi : public AhoyNetwork { }; #endif /*ESP32 & !ETHERNET*/ -#endif /*__AHOY_Wifi_ESP32_H__*/ +#endif /*__AHOY_WIFI_ESP32_H__*/ diff --git a/src/network/AhoyWifiEsp8266.h b/src/network/AhoyWifiEsp8266.h new file mode 100644 index 00000000..1a068797 --- /dev/null +++ b/src/network/AhoyWifiEsp8266.h @@ -0,0 +1,110 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __AHOY_WIFI_ESP8266_H__ +#define __AHOY_WIFI_ESP8266_H__ + +#if defined(ESP8266) +#include +#include +#include "AhoyNetwork.h" +#include "ESPAsyncWebServer.h" + +class AhoyWifi : public AhoyNetwork { + public: + void begin() override { + mAp.enable(); + + // static IP + setupIp([this](IPAddress ip, IPAddress gateway, IPAddress mask, IPAddress dns1, IPAddress dns2) -> bool { + return WiFi.config(ip, gateway, mask, dns1, dns2); + }); + + WiFi.setHostname(mConfig->sys.deviceName); + WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd); + + DBGPRINT(F("connect to network '")); Serial.flush(); + DBGPRINT(mConfig->sys.stationSsid); + } + + void tickNetworkLoop() override { + if(mAp.isEnabled()) + mAp.tickLoop(); + + switch(mStatus) { + case NetworkState::DISCONNECTED: + if(mConnected) { + mConnected = false; + mOnNetworkCB(false); + mAp.enable(); + } + + if (WiFi.softAPgetStationNum() > 0) { + DBGPRINTLN(F("AP client connected")); + } + break; + + case NetworkState::CONNECTED: + break; + + case NetworkState::GOT_IP: + if(!mConnected) { + mAp.disable(); + mConnected = true; + ah::welcome(WiFi.localIP().toString(), F("Station")); + MDNS.begin(mConfig->sys.deviceName); + mOnNetworkCB(true); + } + break; + } + } + + String getIp(void) override { + return WiFi.localIP().toString(); + } + + void scanAvailNetworks(void) override { + if(!mScanActive) { + mScanActive = true; + WiFi.scanNetworks(true); + } + } + + bool getAvailNetworks(JsonObject obj) override { + JsonArray nets = obj.createNestedArray(F("networks")); + + int n = WiFi.scanComplete(); + if (n < 0) + return false; + if(n > 0) { + int sort[n]; + sortRSSI(&sort[0], n); + for (int i = 0; i < n; ++i) { + nets[i][F("ssid")] = WiFi.SSID(sort[i]); + nets[i][F("rssi")] = WiFi.RSSI(sort[i]); + } + } + mScanActive = false; + WiFi.scanDelete(); + + return true; + } + + private: + void 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]); + } + + private: + bool mScanActive = false; +}; + +#endif /*ESP8266*/ +#endif /*__AHOY_WIFI_ESP8266_H__*/ diff --git a/src/platformio.ini b/src/platformio.ini index 20f8005a..de9028d0 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -33,6 +33,7 @@ lib_deps = https://github.com/JChristensen/Timezone @ ^1.2.4 olikraus/U8g2 @ ^2.35.9 https://github.com/zinggjm/GxEPD2#1.5.3 + build_flags = -std=c++17 -std=gnu++17 @@ -44,6 +45,9 @@ build_unflags = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L +lib_deps = + ${env.lib_deps} + https://github.com/me-no-dev/ESPAsyncUDP build_flags = ${env.build_flags} -DEMC_MIN_FREE_MEMORY=4096 -DENABLE_MQTT @@ -156,33 +160,28 @@ build_flags = ${env.build_flags} monitor_filters = esp8266_exception_decoder -[env:esp32-wroom32] +[env:esp32-wroom32-minimal] platform = espressif32@6.5.0 board = lolin_d32 build_flags = ${env.build_flags} -DUSE_HSPI_FOR_EPD - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY monitor_filters = esp32_exception_decoder -[env:esp32-wroom32-minimal] +[env:esp32-wroom32] platform = espressif32@6.5.0 board = lolin_d32 -build_flags = ${env.build_flags} - -DUSE_HSPI_FOR_EPD +build_flags = ${env:esp32-wroom32-minimal.build_flags} + -DENABLE_MQTT + -DPLUGIN_DISPLAY + -DENABLE_HISTORY monitor_filters = esp32_exception_decoder [env:esp32-wroom32-de] platform = espressif32@6.5.0 board = lolin_d32 -build_flags = ${env.build_flags} - -DUSE_HSPI_FOR_EPD - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY +build_flags = ${env:esp32-wroom32.build_flags} -DLANG_DE monitor_filters = esp32_exception_decoder @@ -190,38 +189,24 @@ monitor_filters = [env:esp32-wroom32-prometheus] platform = espressif32@6.5.0 board = lolin_d32 -build_flags = ${env.build_flags} - -DUSE_HSPI_FOR_EPD +build_flags = ${env:esp32-wroom32.build_flags} -DENABLE_PROMETHEUS_EP - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY monitor_filters = esp32_exception_decoder [env:esp32-wroom32-prometheus-de] platform = espressif32@6.5.0 board = lolin_d32 -build_flags = ${env.build_flags} - -DUSE_HSPI_FOR_EPD +build_flags = ${env:esp32-wroom32-prometheus.build_flags} -DLANG_DE - -DENABLE_PROMETHEUS_EP - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY monitor_filters = esp32_exception_decoder [env:esp32-wroom32-ethernet] platform = espressif32 board = lolin_d32 -build_flags = ${env.build_flags} +build_flags = ${env:esp32-wroom32.build_flags} -DETHERNET - -DRELEASE - -DUSE_HSPI_FOR_EPD - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY -DDEF_ETH_CS_PIN=15 -DDEF_ETH_SCK_PIN=14 -DDEF_ETH_MISO_PIN=12 @@ -240,26 +225,8 @@ monitor_filters = [env:esp32-wroom32-ethernet-de] platform = espressif32 board = lolin_d32 -build_flags = ${env.build_flags} - -DETHERNET - -DRELEASE - -DUSE_HSPI_FOR_EPD +build_flags = ${env:esp32-wroom32-ethernet.build_flags} -DLANG_DE - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY - -DDEF_ETH_CS_PIN=15 - -DDEF_ETH_SCK_PIN=14 - -DDEF_ETH_MISO_PIN=12 - -DDEF_ETH_MOSI_PIN=13 - -DDEF_ETH_IRQ_PIN=4 - -DDEF_ETH_RST_PIN=2 - -DDEF_NRF_CS_PIN=5 - -DDEF_NRF_CE_PIN=17 - -DDEF_NRF_IRQ_PIN=16 - -DDEF_NRF_MISO_PIN=19 - -DDEF_NRF_MOSI_PIN=23 - -DDEF_NRF_SCLK_PIN=18 monitor_filters = esp32_exception_decoder @@ -288,22 +255,7 @@ monitor_filters = [env:esp32-s2-mini-de] platform = espressif32@6.5.0 board = lolin_s2_mini -build_flags = ${env.build_flags} - -DUSE_HSPI_FOR_EPD - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY - -DDEF_NRF_CS_PIN=12 - -DDEF_NRF_CE_PIN=3 - -DDEF_NRF_IRQ_PIN=5 - -DDEF_NRF_MISO_PIN=9 - -DDEF_NRF_MOSI_PIN=11 - -DDEF_NRF_SCLK_PIN=7 - -DDEF_CMT_CSB=16 - -DDEF_CMT_FCSB=18 - -DDEF_CMT_IRQ=33 - -DDEF_CMT_SDIO=35 - -DDEF_CMT_SCLK=37 +build_flags = ${env:esp32-s2-mini.build_flags} -DLANG_DE monitor_filters = esp32_exception_decoder @@ -333,34 +285,16 @@ monitor_filters = [env:esp32-c3-mini-de] platform = espressif32@6.5.0 board = lolin_c3_mini -build_flags = ${env.build_flags} - -DUSE_HSPI_FOR_EPD - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY - -DDEF_NRF_CS_PIN=5 - -DDEF_NRF_CE_PIN=0 - -DDEF_NRF_IRQ_PIN=1 - -DDEF_NRF_MISO_PIN=3 - -DDEF_NRF_MOSI_PIN=4 - -DDEF_NRF_SCLK_PIN=2 - -DDEF_CMT_CSB=255 - -DDEF_CMT_FCSB=255 - -DDEF_CMT_IRQ=255 - -DDEF_CMT_SDIO=255 - -DDEF_CMT_SCLK=255 +build_flags = ${env:esp32-c3-mini.build_flags} -DLANG_DE monitor_filters = esp32_exception_decoder -[env:opendtufusion] +[env:opendtufusion-minimal] platform = espressif32@6.5.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env.build_flags} - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY -DSPI_HAL -DDEF_NRF_CS_PIN=37 -DDEF_NRF_CE_PIN=38 @@ -381,75 +315,32 @@ build_flags = ${env.build_flags} monitor_filters = esp32_exception_decoder, colorize -[env:opendtufusion-de] +[env:opendtufusion] platform = espressif32@6.5.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin -build_flags = ${env.build_flags} - -DLANG_DE +build_flags = ${env:opendtufusion-minimal.build_flags} -DENABLE_MQTT -DPLUGIN_DISPLAY -DENABLE_HISTORY - -DSPI_HAL - -DDEF_NRF_CS_PIN=37 - -DDEF_NRF_CE_PIN=38 - -DDEF_NRF_IRQ_PIN=47 - -DDEF_NRF_MISO_PIN=48 - -DDEF_NRF_MOSI_PIN=35 - -DDEF_NRF_SCLK_PIN=36 - -DDEF_CMT_CSB=4 - -DDEF_CMT_FCSB=21 - -DDEF_CMT_IRQ=8 - -DDEF_CMT_SDIO=5 - -DDEF_CMT_SCLK=6 - -DDEF_LED0=18 - -DDEF_LED1=17 - -DLED_ACTIVE_HIGH - -DARDUINO_USB_MODE=1 monitor_filters = esp32_exception_decoder, colorize -[env:opendtufusion-minimal] +[env:opendtufusion-de] platform = espressif32@6.5.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin -build_flags = ${env.build_flags} - -DSPI_HAL - -DDEF_NRF_CS_PIN=37 - -DDEF_NRF_CE_PIN=38 - -DDEF_NRF_IRQ_PIN=47 - -DDEF_NRF_MISO_PIN=48 - -DDEF_NRF_MOSI_PIN=35 - -DDEF_NRF_SCLK_PIN=36 - -DDEF_CMT_CSB=4 - -DDEF_CMT_FCSB=21 - -DDEF_CMT_IRQ=8 - -DDEF_CMT_SDIO=5 - -DDEF_CMT_SCLK=6 - -DDEF_LED0=18 - -DDEF_LED1=17 - -DLED_ACTIVE_HIGH - -DARDUINO_USB_MODE=1 +build_flags = ${env:opendtufusion.build_flags} + -DLANG_DE monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-ethernet] platform = espressif32@6.5.0 board = esp32-s3-devkitc-1 -#lib_deps = -# khoih-prog/AsyncWebServer_ESP32_W5500 -# khoih-prog/AsyncUDP_ESP32_W5500 -# https://github.com/nrf24/RF24 @ ^1.4.8 -# paulstoffregen/Time @ ^1.6.1 -# https://github.com/bertmelis/espMqttClient#v1.6.0 -# bblanchon/ArduinoJson @ ^6.21.3 -# https://github.com/JChristensen/Timezone @ ^1.2.4 -# olikraus/U8g2 @ ^2.35.9 -# https://github.com/zinggjm/GxEPD2#1.5.3 upload_protocol = esp-builtin -build_flags = ${env.build_flags} +build_flags = ${env:opendtufusion-minimal.build_flags} -DETHERNET - -DSPI_HAL -DENABLE_MQTT -DPLUGIN_DISPLAY -DENABLE_HISTORY @@ -459,67 +350,14 @@ build_flags = ${env.build_flags} -DDEF_ETH_MOSI_PIN=40 -DDEF_ETH_IRQ_PIN=44 -DDEF_ETH_RST_PIN=43 - -DDEF_NRF_CS_PIN=37 - -DDEF_NRF_CE_PIN=38 - -DDEF_NRF_IRQ_PIN=47 - -DDEF_NRF_MISO_PIN=48 - -DDEF_NRF_MOSI_PIN=35 - -DDEF_NRF_SCLK_PIN=36 - -DDEF_CMT_CSB=4 - -DDEF_CMT_FCSB=21 - -DDEF_CMT_IRQ=8 - -DDEF_CMT_SDIO=5 - -DDEF_CMT_SCLK=6 - -DDEF_LED0=18 - -DDEF_LED1=17 - -DLED_ACTIVE_HIGH - -DARDUINO_USB_MODE=1 - #-DARDUINO_USB_CDC_ON_BOOT=1 monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-ethernet-de] platform = espressif32@6.5.0 board = esp32-s3-devkitc-1 -#lib_deps = -# khoih-prog/AsyncWebServer_ESP32_W5500 -# khoih-prog/AsyncUDP_ESP32_W5500 -# https://github.com/nrf24/RF24 @ ^1.4.8 -# paulstoffregen/Time @ ^1.6.1 -# https://github.com/bertmelis/espMqttClient#v1.6.0 -# bblanchon/ArduinoJson @ ^6.21.3 -# https://github.com/JChristensen/Timezone @ ^1.2.4 -# olikraus/U8g2 @ ^2.35.9 -# https://github.com/zinggjm/GxEPD2#1.5.3 upload_protocol = esp-builtin -build_flags = ${env.build_flags} - -DETHERNET - -DSPI_HAL +build_flags = ${env:opendtufusion-ethernet.build_flags} -DLANG_DE - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY - -DDEF_ETH_CS_PIN=42 - -DDEF_ETH_SCK_PIN=39 - -DDEF_ETH_MISO_PIN=41 - -DDEF_ETH_MOSI_PIN=40 - -DDEF_ETH_IRQ_PIN=44 - -DDEF_ETH_RST_PIN=43 - -DDEF_NRF_CS_PIN=37 - -DDEF_NRF_CE_PIN=38 - -DDEF_NRF_IRQ_PIN=47 - -DDEF_NRF_MISO_PIN=48 - -DDEF_NRF_MOSI_PIN=35 - -DDEF_NRF_SCLK_PIN=36 - -DDEF_CMT_CSB=4 - -DDEF_CMT_FCSB=21 - -DDEF_CMT_IRQ=8 - -DDEF_CMT_SDIO=5 - -DDEF_CMT_SCLK=6 - -DDEF_LED0=18 - -DDEF_LED1=17 - -DLED_ACTIVE_HIGH - -DARDUINO_USB_MODE=1 - #-DARDUINO_USB_CDC_ON_BOOT=1 monitor_filters = esp32_exception_decoder, colorize From 825c90c59cd3305ad409a3cfc2cc1263f834fc17 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 21 Mar 2024 22:43:27 +0100 Subject: [PATCH 045/201] fix compile --- src/network/AhoyNetwork.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index 7c51c38d..3c3489bd 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -189,10 +189,8 @@ class AhoyNetwork { AhoyWifiAp mAp; DNSServer mDns; - #if defined(ESP32) - AsyncUDP mUdp; // for time server - #else - WiFiUDP mUdp; // for time server + AsyncUDP mUdp; // for time server + #if defined(ESP8266) WiFiEventHandler wifiConnectHandler, wifiDisconnectHandler, wifiGotIPHandler; #endif }; From a0e32bb06c84a3c7264c360366dfec21edf67b5b Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 21 Mar 2024 23:09:19 +0100 Subject: [PATCH 046/201] 0.8.96 * fix precision of power limit in `/live` #1517 * fix translation of `Werte ausgeben` in `settings` #1507 * add grid profile #1518 --- src/CHANGES.md | 5 ++ src/defines.h | 2 +- src/web/html/grid_info.json | 102 ++++++++++++++++++++++++++++++++ src/web/html/visualization.html | 2 +- src/web/lang.json | 2 +- 5 files changed, 110 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 99cf8ac8..1b1bccab 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.8.96 - 2024-03-21 +* fix precision of power limit in `/live` #1517 +* fix translation of `Werte ausgeben` in `settings` #1507 +* add grid profile #1518 + ## 0.8.95 - 2024-03-17 * fix NTP issues #1440 #1497 #1499 diff --git a/src/defines.h b/src/defines.h index 752b3437..9078730f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 95 +#define VERSION_PATCH 96 //------------------------------------- typedef struct { diff --git a/src/web/html/grid_info.json b/src/web/html/grid_info.json index bff1ae80..efb5651d 100644 --- a/src/web/html/grid_info.json +++ b/src/web/html/grid_info.json @@ -10,6 +10,7 @@ {"0x0908": "France_VFR2014"}, {"0x0a00": "DE NF_EN_50549-1:2019"}, {"0x0c00": "AT_TOR_Erzeuger_default"}, + {"0x0c04": "AT_TOR_Erzeuger_default"}, {"0x0d00": "FR_VFR2019"}, {"0x0d04": "NF_EN_50549-1:2019"}, {"0x1000": "ES_RD1699"}, @@ -252,6 +253,78 @@ } ] }, + { + "0x000b": [ + { + "name": "Nominal Voltage", + "div": 10, + "def": 230, + "unit": "V" + }, + { + "name": "Low Voltage 1", + "div": 10, + "min": 170, + "max": 184, + "def": 184, + "unit": "V" + }, + { + "name": "LV1 Maximum Trip Time", + "div": 10, + "def": 1.5, + "unit": "s" + }, + { + "name": "High Voltage 1", + "div": 10, + "min": 253, + "max": 270, + "def": 255.3, + "unit": "V" + }, + { + "name": "HV1 Maximum Trip Time", + "div": 10, + "def": 0.1, + "unit": "s" + }, + { + "name": "Low Voltage 2", + "div": 10, + "def": 57.5, + "unit": "V" + }, + { + "name": "LV2 Maximum Trip Time", + "div": 100, + "def": 0.5, + "unit": "s" + }, + { + "name": "High Voltage 2", + "div": 10, + "min": 264.5, + "max": 275, + "def": 264.5, + "unit": "V" + }, + { + "name": "HV2 Maximum Trip Time", + "div": 100, + "def": 0.08, + "unit": "s" + }, + { + "name": "10mins Average High Voltage", + "div": 10, + "min": 245, + "max": 255.3, + "def": 255.3, + "unit": "V" + } + ] + }, { "0x000c": [ { @@ -805,6 +878,35 @@ } ] }, + { + "0x6004": [ + { + "name": "VW Function Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 1 + }, + { + "name": "Start of Voltage Watt Droop", + "div": 10, + "def": 253, + "unit": "V" + }, + { + "name": "End of Voltage Watt Droop", + "div": 10, + "def": 257.6, + "unit": "V" + }, + { + "name": "VW Droop Slope", + "div": 100, + "def": 21.74, + "unit": "Pn%/V" + } + ] + }, { "0x7000": [ { diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html index aec6b0d8..cfc84e72 100644 --- a/src/web/html/visualization.html +++ b/src/web/html/visualization.html @@ -116,7 +116,7 @@ if(65535 != obj.power_limit_read) { pwrLimit = obj.power_limit_read + " %"; if(0 != obj.max_pwr) - pwrLimit += ", " + (obj.max_pwr * obj.power_limit_read / 100) + " W"; + pwrLimit += ", " + (obj.max_pwr * obj.power_limit_read / 100).toFixed(1) + " W"; } var maxAcPwr = toIsoDateStr(new Date(obj.ts_max_ac_pwr * 1000)); diff --git a/src/web/lang.json b/src/web/lang.json index f1723688..beab0e12 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -186,7 +186,7 @@ { "token": "LOG_PRINT_INVERTER_DATA", "en": "print inverter data", - "de": "Livedaten ausgeben" + "de": "Inverterwerte ausgeben" }, { "token": "LOG_SERIAL_DEBUG", From 99cfdb5324e961bddec4d8a7dee44fb17ae160a4 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 22 Mar 2024 22:38:08 +0100 Subject: [PATCH 047/201] 0.8.97 * add support for newest generation of inverters with A-F in their serial number --- src/web/RestApi.h | 2 +- src/web/html/setup.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 399ea91f..6a528a8c 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -332,7 +332,7 @@ class RestApi { if(-1 != i) { i+=5; String sn = tmp.substring(i, tmp.indexOf("\"", i)-1); - tmp.replace(sn, String(atoll(sn.c_str()), HEX)); + tmp.replace(sn, String(sn) + ",\"note\":\"" + String(atoll(sn.c_str()), HEX) + "\""); } } response = request->beginResponse(200, F("application/json; charset=utf-8"), tmp); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index b6b8929e..ed6c4410 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -783,7 +783,7 @@ cbEn.checked = (obj.enabled); cbDisNightCom.checked = (obj.disnightcom); - var ser = ml("input", {name: "ser", class: "text", type: "number", max: 138999999999, value: obj.serial}, null); + var ser = ml("input", {name: "ser", class: "text", type: "text", pattern: "[0-9a-fA-F]{12}", value: obj.serial}, null); var html = ml("div", {}, [ tabs(["{#TAB_GENERAL}", "{#TAB_INPUTS}", "{#TAB_RADIO}", "{#TAB_ADVANCED}"]), ml("div", {id: "div{#TAB_GENERAL}", class: "tab-content"}, [ From 9971ed7f8aa5d497ba9ccf119f38456be8598b67 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 22 Mar 2024 22:40:35 +0100 Subject: [PATCH 048/201] 0.8.97 * add support for newest generation of inverters with A-F in their serial number * fix NTP and sunrise / sunset * set default coordinates to the mid of Germany #1516 --- src/CHANGES.md | 5 +++++ src/app.cpp | 11 +++++++---- src/config/settings.h | 4 ++-- src/defines.h | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 1b1bccab..af1ecd86 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.8.97 - 2024-03-22 +* add support for newest generation of inverters with A-F in their serial number +* fix NTP and sunrise / sunset +* set default coordinates to the mid of Germany #1516 + ## 0.8.96 - 2024-03-21 * fix precision of power limit in `/live` #1517 * fix translation of `Werte ausgeben` in `settings` #1507 diff --git a/src/app.cpp b/src/app.cpp index 37b0a37a..119894f1 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -204,8 +204,13 @@ void app::regularTickers(void) { #endif /*ENABLE_SIMULATOR*/ } +//----------------------------------------------------------------------------- void app::onNtpUpdate(bool gotTime) { mNtpReceived = true; + if ((0 == mSunrise) && (0.0 != mConfig->sun.lat) && (0.0 != mConfig->sun.lon)) { + mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; + tickCalcSunrise(); + } } //----------------------------------------------------------------------------- @@ -236,10 +241,8 @@ void app::updateNtp(void) { } } - if ((0 == mSunrise) && (0.0 != mConfig->sun.lat) && (0.0 != mConfig->sun.lon)) { - mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; - tickCalcSunrise(); - } + if(mNtpReceived) + onNtpUpdate(true); mMqttReconnect = false; } diff --git a/src/config/settings.h b/src/config/settings.h index fe0053a9..e115160b 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -427,8 +427,8 @@ class settings { mCfg.ntp.port = DEF_NTP_PORT; mCfg.ntp.interval = 720; - mCfg.sun.lat = 0.0; - mCfg.sun.lon = 0.0; + mCfg.sun.lat = 51.1; // mid of Germany + mCfg.sun.lon = 10.5; // mid of Germany mCfg.sun.offsetSecMorning = 0; mCfg.sun.offsetSecEvening = 0; diff --git a/src/defines.h b/src/defines.h index 9078730f..16a1adf9 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 96 +#define VERSION_PATCH 97 //------------------------------------- typedef struct { From 73c48fab9c1dd887bafe2a9be060d9e5bed54ffd Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 24 Mar 2024 16:27:24 +0100 Subject: [PATCH 049/201] esp8266 works --- src/CHANGES.md | 2 ++ src/network/AhoyWifiEsp32.h | 14 ++++++++------ src/network/AhoyWifiEsp8266.h | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index af1ecd86..8d89f003 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,7 @@ # Development Changes +## 0.8.98 - 2024-03-23 + ## 0.8.97 - 2024-03-22 * add support for newest generation of inverters with A-F in their serial number * fix NTP and sunrise / sunset diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index f9fc064a..99733ad2 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -23,12 +23,14 @@ class AhoyWifi : public AhoyNetwork { }); WiFi.setHostname(mConfig->sys.deviceName); - WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); - WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL); - WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, WIFI_ALL_CHANNEL_SCAN); - - DBGPRINT(F("connect to network '")); Serial.flush(); - DBGPRINT(mConfig->sys.stationSsid); + #if !defined(AP_ONLY) + WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); + WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL); + WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, WIFI_ALL_CHANNEL_SCAN); + + DBGPRINT(F("connect to network '")); Serial.flush(); + DBGPRINT(mConfig->sys.stationSsid); + #endif } void tickNetworkLoop() override { diff --git a/src/network/AhoyWifiEsp8266.h b/src/network/AhoyWifiEsp8266.h index 1a068797..16a62b4b 100644 --- a/src/network/AhoyWifiEsp8266.h +++ b/src/network/AhoyWifiEsp8266.h @@ -23,10 +23,12 @@ class AhoyWifi : public AhoyNetwork { }); WiFi.setHostname(mConfig->sys.deviceName); - WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd); + #if !defined(AP_ONLY) + WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd); - DBGPRINT(F("connect to network '")); Serial.flush(); - DBGPRINT(mConfig->sys.stationSsid); + DBGPRINT(F("connect to network '")); Serial.flush(); + DBGPRINT(mConfig->sys.stationSsid); + #endif } void tickNetworkLoop() override { From 444c97e933d6cc51b9085f87e5fb85b44a92e678 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 24 Mar 2024 16:58:13 +0100 Subject: [PATCH 050/201] 0.8.98 * new network routines --- src/CHANGES.md | 3 +- src/app.cpp | 1 - src/network/AhoyNetwork.h | 4 +- src/network/AhoyWifiEsp8266.h | 86 ++++++++++++++++++++++++++++++++--- 4 files changed, 85 insertions(+), 9 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 8d89f003..f2cc8785 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,6 +1,7 @@ # Development Changes -## 0.8.98 - 2024-03-23 +## 0.8.98 - 2024-03-24 +* new network routines ## 0.8.97 - 2024-03-22 * add support for newest generation of inverters with A-F in their serial number diff --git a/src/app.cpp b/src/app.cpp index f06e4a53..2dd8c49c 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -162,7 +162,6 @@ void app::loop(void) { //----------------------------------------------------------------------------- void app::onNetwork(bool gotIp) { - DPRINTLN(DBG_INFO, F("onNetwork")); mNetworkConnected = gotIp; ah::Scheduler::resetTicker(); regularTickers(); //reinstall regular tickers diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index 3c3489bd..59e000bd 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -173,7 +173,9 @@ class AhoyNetwork { enum class NetworkState : uint8_t { DISCONNECTED, CONNECTED, - GOT_IP + GOT_IP, + SCAN_READY, // ESP8266 + CONNECTING // ESP8266 }; protected: diff --git a/src/network/AhoyWifiEsp8266.h b/src/network/AhoyWifiEsp8266.h index 16a62b4b..2db24c21 100644 --- a/src/network/AhoyWifiEsp8266.h +++ b/src/network/AhoyWifiEsp8266.h @@ -8,6 +8,7 @@ #if defined(ESP8266) #include +#include #include #include "AhoyNetwork.h" #include "ESPAsyncWebServer.h" @@ -23,18 +24,15 @@ class AhoyWifi : public AhoyNetwork { }); WiFi.setHostname(mConfig->sys.deviceName); - #if !defined(AP_ONLY) - WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd); - - DBGPRINT(F("connect to network '")); Serial.flush(); - DBGPRINT(mConfig->sys.stationSsid); - #endif + mBSSIDList.clear(); } void tickNetworkLoop() override { if(mAp.isEnabled()) mAp.tickLoop(); + mCnt++; + switch(mStatus) { case NetworkState::DISCONNECTED: if(mConnected) { @@ -46,6 +44,45 @@ class AhoyWifi : public AhoyNetwork { if (WiFi.softAPgetStationNum() > 0) { DBGPRINTLN(F("AP client connected")); } + #if !defined(AP_ONLY) + else if (!mScanActive) { + DBGPRINT(F("scanning APs with SSID ")); + DBGPRINTLN(String(mConfig->sys.stationSsid)); + mScanCnt = 0; + mCnt = 0; + mScanActive = true; + WiFi.scanNetworks(true, true, 0U, ([this]() { + if (mConfig->sys.isHidden) + return (uint8_t*)NULL; + return (uint8_t*)(mConfig->sys.stationSsid); + })()); + } else if(getBSSIDs()) { + mStatus = NetworkState::SCAN_READY; + DBGPRINT(F("connect to network '")); Serial.flush(); + DBGPRINTLN(mConfig->sys.stationSsid); + } + #endif + break; + + case NetworkState::SCAN_READY: + mStatus = NetworkState::CONNECTING; + DBGPRINT(F("try to connect to 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(""); + mGotDisconnect = false; + WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, 0, &bssid[0]); + break; + + case NetworkState::CONNECTING: + if (isTimeout(TIMEOUT)) { + WiFi.disconnect(); + mStatus = mBSSIDList.empty() ? NetworkState::DISCONNECTED : NetworkState::SCAN_READY; + } break; case NetworkState::CONNECTED: @@ -104,8 +141,45 @@ class AhoyWifi : public AhoyNetwork { std::swap(sort[i], sort[j]); } + bool getBSSIDs() { + bool result = false; + int n = WiFi.scanComplete(); + if (n < 0) { + if (++mScanCnt < 20) + return false; + } + 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(""); + } + result = true; + } + mScanActive = false; + WiFi.scanDelete(); + return result; + } + + bool isTimeout(uint8_t timeout) { + return ((mCnt % timeout) == 0); + } + private: + uint8_t mCnt = 0; + uint8_t mScanCnt = 0; bool mScanActive = false; + bool mGotDisconnect = false; + std::list mBSSIDList; + static constexpr uint8_t TIMEOUT = 20; + static constexpr uint8_t SCAN_TIMEOUT = 10; }; #endif /*ESP8266*/ From 104033073ec36b0a8688d76985c1d241f8a6f1b5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 24 Mar 2024 16:59:08 +0100 Subject: [PATCH 051/201] 0.8.98 * new network routines --- src/defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/defines.h b/src/defines.h index 16a1adf9..2058ce3a 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 97 +#define VERSION_PATCH 98 //------------------------------------- typedef struct { From 92231672e87e514c4f3c6343a0c023ad55b63c8d Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 25 Mar 2024 22:25:50 +0100 Subject: [PATCH 052/201] 0.8.98 * fix Ethernet * modified wizard * fix github compile? --- src/app.h | 6 +- src/config/config.h | 2 +- src/config/settings.h | 12 +- src/network/AhoyEthernet.h | 17 +-- src/network/AhoyEthernetSpi.h | 17 ++- src/network/AhoyNetwork.h | 47 ++++++- src/network/AhoyNetworkHelper.h | 2 +- src/network/AhoyWifiEsp32.h | 32 +---- src/network/AhoyWifiEsp8266.h | 43 +------ src/platformio.ini | 55 +++------ src/web/RestApi.h | 18 ++- src/web/html/setup.html | 8 +- src/web/html/wizard.html | 212 +++++++++++++++++++++++++++++++- src/web/lang.json | 35 ++++++ src/web/web.h | 4 +- 15 files changed, 371 insertions(+), 139 deletions(-) diff --git a/src/app.h b/src/app.h index 05b11469..cb546267 100644 --- a/src/app.h +++ b/src/app.h @@ -184,7 +184,11 @@ class app : public IApp, public ah::Scheduler { }*/ bool getWasInCh12to14(void) const override { - return false; // @todo mWifi.getWasInCh12to14(); + #if defined(ESP8266) + return mNetwork->getWasInCh12to14(); + #else + return false; + #endif } #endif /* !defined(ETHERNET) */ diff --git a/src/config/config.h b/src/config/config.h index 23e27a8c..a4b84934 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -78,7 +78,7 @@ #define DEF_ETH_CS_PIN 15 #endif #ifndef DEF_ETH_RST_PIN - #define DEF_ETH_RST_PIN 2 + #define DEF_ETH_RST_PIN DEF_PIN_OFF #endif #else /* defined(ETHERNET) */ // time in seconds how long the station info (ssid + pwd) will be tried diff --git a/src/config/settings.h b/src/config/settings.h index fb8689b9..8f20ba8f 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -405,13 +405,17 @@ class settings { else { snprintf(mCfg.sys.stationSsid, SSID_LEN, FB_WIFI_SSID); snprintf(mCfg.sys.stationPwd, PWD_LEN, FB_WIFI_PWD); - snprintf(mCfg.sys.apPwd, PWD_LEN, WIFI_AP_PWD); mCfg.sys.isHidden = false; } #endif + snprintf(mCfg.sys.apPwd, PWD_LEN, WIFI_AP_PWD); #if defined(ETHERNET) - mCfg.sys.eth.enabled = false; + #if defined(DEF_ETH_ENABLED) + mCfg.sys.eth.enabled = true; + #else + mCfg.sys.eth.enabled = false; + #endif mCfg.sys.eth.pinCs = DEF_ETH_CS_PIN; mCfg.sys.eth.pinSclk = DEF_ETH_SCK_PIN; mCfg.sys.eth.pinMiso = DEF_ETH_MISO_PIN; @@ -431,7 +435,11 @@ class settings { mCfg.nrf.pinMosi = DEF_NRF_MOSI_PIN; mCfg.nrf.pinSclk = DEF_NRF_SCLK_PIN; + #if defined(ETHERNET) + mCfg.nrf.enabled = false; + #else mCfg.nrf.enabled = true; + #endif #if defined(ESP32) mCfg.cmt.pinSclk = DEF_CMT_SCLK; diff --git a/src/network/AhoyEthernet.h b/src/network/AhoyEthernet.h index ce176ec3..db624a41 100644 --- a/src/network/AhoyEthernet.h +++ b/src/network/AhoyEthernet.h @@ -18,12 +18,16 @@ class AhoyEthernet : public AhoyNetwork { void begin() override { mAp.enable(); + if(!mConfig->sys.eth.enabled) + return; + + mEthSpi.begin(mConfig->sys.eth.pinMiso, mConfig->sys.eth.pinMosi, mConfig->sys.eth.pinSclk, mConfig->sys.eth.pinCs, mConfig->sys.eth.pinIrq, mConfig->sys.eth.pinRst); + ETH.setHostname(mConfig->sys.deviceName); + // static IP setupIp([this](IPAddress ip, IPAddress gateway, IPAddress mask, IPAddress dns1, IPAddress dns2) -> bool { return ETH.config(ip, gateway, mask, dns1, dns2); }); - - ETH.setHostname(mConfig->sys.deviceName); } void tickNetworkLoop() override { @@ -43,9 +47,8 @@ class AhoyEthernet : public AhoyNetwork { break; case NetworkState::GOT_IP: - mAp.disable(); - if(!mConnected) { + mAp.disable(); mConnected = true; ah::welcome(ETH.localIP().toString(), F("Station")); MDNS.begin(mConfig->sys.deviceName); @@ -59,10 +62,8 @@ class AhoyEthernet : public AhoyNetwork { return ETH.localIP().toString(); } - void scanAvailNetworks(void) override {}; - bool getAvailNetworks(JsonObject obj) override { - return false; - } + private: + AhoyEthernetSpi mEthSpi; }; #endif /*ETHERNET*/ diff --git a/src/network/AhoyEthernetSpi.h b/src/network/AhoyEthernetSpi.h index 12e58e4d..b41431b4 100644 --- a/src/network/AhoyEthernetSpi.h +++ b/src/network/AhoyEthernetSpi.h @@ -26,9 +26,11 @@ class AhoyEthernetSpi { eth_netif(nullptr) {} void begin(int8_t pin_miso, int8_t pin_mosi, int8_t pin_sclk, int8_t pin_cs, int8_t pin_int, int8_t pin_rst) { - gpio_reset_pin(static_cast(pin_rst)); - gpio_set_direction(static_cast(pin_rst), GPIO_MODE_OUTPUT); - gpio_set_level(static_cast(pin_rst), 0); + if(-1 != pin_rst) { + gpio_reset_pin(static_cast(pin_rst)); + gpio_set_direction(static_cast(pin_rst), GPIO_MODE_OUTPUT); + gpio_set_level(static_cast(pin_rst), 0); + } gpio_reset_pin(static_cast(pin_sclk)); gpio_reset_pin(static_cast(pin_mosi)); @@ -42,6 +44,7 @@ class AhoyEthernetSpi { gpio_reset_pin(static_cast(pin_int)); gpio_set_pull_mode(static_cast(pin_int), GPIO_PULLUP_ONLY); + spi_bus_config_t buscfg = { .mosi_io_num = pin_mosi, .miso_io_num = pin_miso, @@ -80,9 +83,11 @@ class AhoyEthernetSpi { ESP_ERROR_CHECK(spi_bus_add_device(SPI3_HOST, &devcfg, &spi)); // Reset sequence - delayMicroseconds(500); - gpio_set_level(static_cast(pin_rst), 1); - delayMicroseconds(1000); + if(-1 != pin_rst) { + delayMicroseconds(500); + gpio_set_level(static_cast(pin_rst), 1); + delayMicroseconds(1000); + } // Arduino function to start networking stack if not already started tcpipInit(); diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index 59e000bd..5ce668df 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -80,8 +80,39 @@ class AhoyNetwork { virtual void begin() = 0; virtual void tickNetworkLoop() = 0; virtual String getIp(void) = 0; - virtual void scanAvailNetworks(void) = 0; - virtual bool getAvailNetworks(JsonObject obj) = 0; + + virtual bool getWasInCh12to14() { + return false; + } + + #if !defined(ETHERNET) + void scanAvailNetworks(void) { + if(!mScanActive) { + mScanActive = true; + WiFi.scanNetworks(true); + } + } + + bool getAvailNetworks(JsonObject obj) { + JsonArray nets = obj.createNestedArray(F("networks")); + + int n = WiFi.scanComplete(); + if (n < 0) + return false; + if(n > 0) { + int sort[n]; + sortRSSI(&sort[0], n); + for (int i = 0; i < n; ++i) { + nets[i][F("ssid")] = WiFi.SSID(sort[i]); + nets[i][F("rssi")] = WiFi.RSSI(sort[i]); + } + } + mScanActive = false; + WiFi.scanDelete(); + + return true; + } + #endif protected: void setupIp(std::function cb) { @@ -169,6 +200,17 @@ class AhoyNetwork { mUdp.close(); } + #if !defined(ETHERNET) + void 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]); + } + #endif + protected: enum class NetworkState : uint8_t { DISCONNECTED, @@ -182,6 +224,7 @@ class AhoyNetwork { settings_t *mConfig = nullptr; uint32_t *mUtcTimestamp = nullptr; bool mConnected = false; + bool mScanActive = false; OnNetworkCB mOnNetworkCB; OnTimeCB mOnTimeCB; diff --git a/src/network/AhoyNetworkHelper.h b/src/network/AhoyNetworkHelper.h index 33f71029..378ba033 100644 --- a/src/network/AhoyNetworkHelper.h +++ b/src/network/AhoyNetworkHelper.h @@ -9,7 +9,7 @@ #include "../utils/dbg.h" #include #if defined(ESP32) - #include + #include "ESPAsyncWebServer.h" #include #include #else diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index 99733ad2..255f2b03 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -9,8 +9,8 @@ #if defined(ESP32) && !defined(ETHERNET) #include #include -#include #include "AhoyNetwork.h" +#include "ESPAsyncWebServer.h" class AhoyWifi : public AhoyNetwork { public: @@ -69,33 +69,6 @@ class AhoyWifi : public AhoyNetwork { return WiFi.localIP().toString(); } - void scanAvailNetworks(void) override { - if(!mScanActive) { - mScanActive = true; - WiFi.scanNetworks(true); - } - } - - bool getAvailNetworks(JsonObject obj) override { - JsonArray nets = obj.createNestedArray(F("networks")); - - int n = WiFi.scanComplete(); - if (n < 0) - return false; - if(n > 0) { - int sort[n]; - sortRSSI(&sort[0], n); - for (int i = 0; i < n; ++i) { - nets[i][F("ssid")] = WiFi.SSID(sort[i]); - nets[i][F("rssi")] = WiFi.RSSI(sort[i]); - } - } - mScanActive = false; - WiFi.scanDelete(); - - return true; - } - private: void sortRSSI(int *sort, int n) { for (int i = 0; i < n; i++) @@ -105,9 +78,6 @@ class AhoyWifi : public AhoyNetwork { if (WiFi.RSSI(sort[j]) > WiFi.RSSI(sort[i])) std::swap(sort[i], sort[j]); } - - private: - bool mScanActive = false; }; #endif /*ESP32 & !ETHERNET*/ diff --git a/src/network/AhoyWifiEsp8266.h b/src/network/AhoyWifiEsp8266.h index 2db24c21..b9417556 100644 --- a/src/network/AhoyWifiEsp8266.h +++ b/src/network/AhoyWifiEsp8266.h @@ -74,7 +74,6 @@ class AhoyWifi : public AhoyNetwork { DBGPRINT(" " + String(bssid[j], HEX)); } DBGPRINTLN(""); - mGotDisconnect = false; WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, 0, &bssid[0]); break; @@ -96,6 +95,9 @@ class AhoyWifi : public AhoyNetwork { MDNS.begin(mConfig->sys.deviceName); mOnNetworkCB(true); } + + if(WiFi.channel() > 11) + mWasInCh12to14 = true; break; } } @@ -104,43 +106,11 @@ class AhoyWifi : public AhoyNetwork { return WiFi.localIP().toString(); } - void scanAvailNetworks(void) override { - if(!mScanActive) { - mScanActive = true; - WiFi.scanNetworks(true); - } - } - - bool getAvailNetworks(JsonObject obj) override { - JsonArray nets = obj.createNestedArray(F("networks")); - - int n = WiFi.scanComplete(); - if (n < 0) - return false; - if(n > 0) { - int sort[n]; - sortRSSI(&sort[0], n); - for (int i = 0; i < n; ++i) { - nets[i][F("ssid")] = WiFi.SSID(sort[i]); - nets[i][F("rssi")] = WiFi.RSSI(sort[i]); - } - } - mScanActive = false; - WiFi.scanDelete(); - - return true; + bool getWasInCh12to14() override { + return mWasInCh12to14; } private: - void 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]); - } - bool getBSSIDs() { bool result = false; int n = WiFi.scanComplete(); @@ -175,9 +145,8 @@ class AhoyWifi : public AhoyNetwork { private: uint8_t mCnt = 0; uint8_t mScanCnt = 0; - bool mScanActive = false; - bool mGotDisconnect = false; std::list mBSSIDList; + bool mWasInCh12to14 = false; static constexpr uint8_t TIMEOUT = 20; static constexpr uint8_t SCAN_TIMEOUT = 10; }; diff --git a/src/platformio.ini b/src/platformio.ini index de9028d0..4d0d528d 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -41,6 +41,16 @@ build_unflags = -std=gnu++11 +[env:esp8266-minimal] +platform = espressif8266 +board = esp12e +board_build.f_cpu = 80000000L +build_flags = ${env.build_flags} + -DEMC_MIN_FREE_MEMORY=4096 + ;-Wl,-Map,output.map +monitor_filters = + esp8266_exception_decoder + [env:esp8266] platform = espressif8266 board = esp12e @@ -48,10 +58,8 @@ board_build.f_cpu = 80000000L lib_deps = ${env.lib_deps} https://github.com/me-no-dev/ESPAsyncUDP -build_flags = ${env.build_flags} - -DEMC_MIN_FREE_MEMORY=4096 +build_flags = ${env:esp8266-minimal.build_flags} -DENABLE_MQTT - ;-Wl,-Map,output.map monitor_filters = esp8266_exception_decoder @@ -59,11 +67,8 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = ${env.build_flags} - -DEMC_MIN_FREE_MEMORY=4096 +build_flags = ${env:esp8266.build_flags} -DLANG_DE - -DENABLE_MQTT - ;-Wl,-Map,output.map monitor_filters = esp8266_exception_decoder @@ -71,12 +76,9 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = ${env.build_flags} - -DEMC_MIN_FREE_MEMORY=4096 - -DENABLE_MQTT +build_flags = ${env:esp8266.build_flags} -DPLUGIN_DISPLAY -DENABLE_HISTORY - ;-Wl,-Map,output.map monitor_filters = esp8266_exception_decoder @@ -84,13 +86,8 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = ${env.build_flags} - -DEMC_MIN_FREE_MEMORY=4096 +build_flags = ${env:esp8266-all.build_flags} -DLANG_DE - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY - ;-Wl,-Map,output.map monitor_filters = esp8266_exception_decoder @@ -98,12 +95,8 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = ${env.build_flags} - -DEMC_MIN_FREE_MEMORY=4096 +build_flags = ${env:esp8266-all.build_flags} -DENABLE_PROMETHEUS_EP - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY monitor_filters = esp8266_exception_decoder @@ -111,23 +104,8 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = ${env.build_flags} - -DEMC_MIN_FREE_MEMORY=4096 - -DENABLE_PROMETHEUS_EP +build_flags = ${env:esp8266-prometheus.build_flags} -DLANG_DE - -DENABLE_MQTT - -DPLUGIN_DISPLAY - -DENABLE_HISTORY -monitor_filters = - esp8266_exception_decoder - -[env:esp8266-minimal] -platform = espressif8266 -board = esp12e -board_build.f_cpu = 80000000L -build_flags = ${env.build_flags} - -DEMC_MIN_FREE_MEMORY=4096 - ;-Wl,-Map,output.map monitor_filters = esp8266_exception_decoder @@ -350,6 +328,7 @@ build_flags = ${env:opendtufusion-minimal.build_flags} -DDEF_ETH_MOSI_PIN=40 -DDEF_ETH_IRQ_PIN=44 -DDEF_ETH_RST_PIN=43 + -DDEF_ETH_ENABLED monitor_filters = esp32_exception_decoder, colorize diff --git a/src/web/RestApi.h b/src/web/RestApi.h index f4c655b5..8087883e 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -375,14 +375,12 @@ class RestApi { } void getSysInfo(AsyncWebServerRequest *request, JsonObject obj) { + obj[F("ap_pwd")] = mConfig->sys.apPwd; #if !defined(ETHERNET) obj[F("ssid")] = mConfig->sys.stationSsid; - obj[F("ap_pwd")] = mConfig->sys.apPwd; obj[F("hidd")] = mConfig->sys.isHidden; obj[F("mac")] = WiFi.macAddress(); obj[F("wifi_channel")] = WiFi.channel(); - #else - getEthernet(obj.createNestedObject(F("eth"))); #endif /* !defined(ETHERNET) */ obj[F("device_name")] = mConfig->sys.deviceName; obj[F("dark_mode")] = (bool)mConfig->sys.darkMode; @@ -882,6 +880,9 @@ class RestApi { #if defined(ESP32) getRadioCmt(obj.createNestedObject(F("radioCmt"))); #endif + #if defined(ETHERNET) + getEthernet(obj.createNestedObject(F("eth"))); + #endif getRadioNrf(obj.createNestedObject(F("radioNrf"))); getSerial(obj.createNestedObject(F("serial"))); getStaticIp(obj.createNestedObject(F("static_ip"))); @@ -1051,6 +1052,17 @@ class RestApi { //mApp->setStopApAllowedMode(false); mApp->setupStation(); } + #else + else if(F("save_eth") == jsonIn[F("cmd")]) { + mConfig->sys.eth.enabled = jsonIn[F("en")].as(); + mConfig->sys.eth.pinCs = jsonIn[F("cs")].as(); + mConfig->sys.eth.pinSclk = jsonIn[F("sclk")].as(); + mConfig->sys.eth.pinMiso = jsonIn[F("miso")].as(); + mConfig->sys.eth.pinMosi = jsonIn[F("mosi")].as(); + mConfig->sys.eth.pinIrq = jsonIn[F("irq")].as(); + mConfig->sys.eth.pinRst = jsonIn[F("reset")].as(); + mApp->saveSettings(true); + } #endif /* !defined(ETHERNET */ else if(F("save_iv") == jsonIn[F("cmd")]) { Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")], false); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 9af66314..fb1eff97 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -949,7 +949,7 @@ } } - function parsePinout(obj, type, system) { + function parsePinout(obj) { var e = document.getElementById("pinout"); /*IF_ESP32*/ var pinList = esp32pins; @@ -1291,13 +1291,13 @@ parseMqtt(root["mqtt"]); parseNtp(root["ntp"]); parseSun(root["sun"]); - parsePinout(root["pinout"], root["system"]["esp_type"], root["system"]); + parsePinout(root.pinout); parseNrfRadio(root["radioNrf"], root["pinout"]); /*IF_ESP32*/ - parseCmtRadio(root["radioCmt"]); + parseCmtRadio(root.radioCmt); /*ENDIF_ESP32*/ /*IF_ETHERNET*/ - parseEth(root.system.eth) + parseEth(root.eth) /*ENDIF_ETHERNET*/ parseSerial(root["serial"]); /*IF_PLUGIN_DISPLAY*/ diff --git a/src/web/html/wizard.html b/src/web/html/wizard.html index 3df44dc4..179adb5a 100644 --- a/src/web/html/wizard.html +++ b/src/web/html/wizard.html @@ -15,6 +15,165 @@ var found = false; var c = document.getElementById("con"); + /*IF_ESP32*/ + var pinList = [ + [255, "{#PIN_OFF}"], + [0, "GPIO0"], + [1, "TX (GPIO1)"], + [2, "GPIO2 (LED)"], + [3, "RX (GPIO3)"], + [4, "GPIO4"], + [5, "GPIO5"], + [12, "GPIO12 (HSPI MISO)"], + [13, "GPIO13 (HSPI MOSI)"], + [14, "GPIO14 (HSPI SCLK)"], + [15, "GPIO15"], + [16, "GPIO16"], + [17, "GPIO17"], + [18, "GPIO18 (VSPI SCLK)"], + [19, "GPIO19 (VSPI MISO)"], + [21, "GPIO21 (SDA)"], + [22, "GPIO22 (SCL)"], + [23, "GPIO23 (VSPI MOSI)"], + [25, "GPIO25"], + [26, "GPIO26"], + [27, "GPIO27"], + [32, "GPIO32"], + [33, "GPIO33"], + [34, "GPIO34 ({#PIN_INPUT_ONLY})"], + [35, "GPIO35 ({#PIN_INPUT_ONLY})"], + [36, "VP (GPIO36, {#PIN_INPUT_ONLY})"], + [39, "VN (GPIO39, {#PIN_INPUT_ONLY})"] + ]; + /*IF_ESP32-S2*/ + pinList = [ + [255, "off / default"], + [0, "GPIO0 ({#PIN_DONT_USE} - BOOT)"], + [1, "GPIO1"], + [2, "GPIO2"], + [3, "GPIO3"], + [4, "GPIO4"], + [5, "GPIO5"], + [6, "GPIO6"], + [7, "GPIO7"], + [8, "GPIO8"], + [9, "GPIO9"], + [10, "GPIO10"], + [11, "GPIO11"], + [12, "GPIO12"], + [13, "GPIO13"], + [14, "GPIO14"], + [15, "GPIO15"], + [16, "GPIO16"], + [17, "GPIO17"], + [18, "GPIO18"], + [19, "GPIO19 ({#PIN_DONT_USE} - USB-)"], + [20, "GPIO20 ({#PIN_DONT_USE} - USB+)"], + [21, "GPIO21"], + [26, "GPIO26 (PSRAM - {#PIN_NOT_AVAIL})"], + [27, "GPIO27 (FLASH - {#PIN_NOT_AVAIL})"], + [28, "GPIO28 (FLASH - {#PIN_NOT_AVAIL})"], + [29, "GPIO29 (FLASH - {#PIN_NOT_AVAIL})"], + [30, "GPIO30 (FLASH - {#PIN_NOT_AVAIL})"], + [31, "GPIO31 (FLASH - {#PIN_NOT_AVAIL})"], + [32, "GPIO32 (FLASH - {#PIN_NOT_AVAIL})"], + [33, "GPIO33 (not exposed on S3-WROOM modules)"], + [34, "GPIO34 (not exposed on S3-WROOM modules)"], + [35, "GPIO35"], + [36, "GPIO36"], + [37, "GPIO37"], + [38, "GPIO38"], + [39, "GPIO39"], + [40, "GPIO40"], + [41, "GPIO41"], + [42, "GPIO42"], + [43, "GPIO43"], + [44, "GPIO44"], + [45, "GPIO45 ({#PIN_DONT_USE} - STRAPPING PIN)"], + [46, "GPIO46 ({#PIN_DONT_USE} - STRAPPING PIN)"], + [47, "GPIO47"], + [48, "GPIO48"], + ]; + /*ENDIF_ESP32-S2*/ + /*IF_ESP32-S3*/ + pinList = [ + [255, "off / default"], + [0, "GPIO0 ({#PIN_DONT_USE} - BOOT)"], + [1, "GPIO1"], + [2, "GPIO2"], + [3, "GPIO3"], + [4, "GPIO4"], + [5, "GPIO5"], + [6, "GPIO6"], + [7, "GPIO7"], + [8, "GPIO8"], + [9, "GPIO9"], + [10, "GPIO10"], + [11, "GPIO11"], + [12, "GPIO12"], + [13, "GPIO13"], + [14, "GPIO14"], + [15, "GPIO15"], + [16, "GPIO16"], + [17, "GPIO17"], + [18, "GPIO18"], + [19, "GPIO19 ({#PIN_DONT_USE} - USB-)"], + [20, "GPIO20 ({#PIN_DONT_USE} - USB+)"], + [21, "GPIO21"], + [26, "GPIO26 (PSRAM - {#PIN_NOT_AVAIL})"], + [27, "GPIO27 (FLASH - {#PIN_NOT_AVAIL})"], + [28, "GPIO28 (FLASH - {#PIN_NOT_AVAIL})"], + [29, "GPIO29 (FLASH - {#PIN_NOT_AVAIL})"], + [30, "GPIO30 (FLASH - {#PIN_NOT_AVAIL})"], + [31, "GPIO31 (FLASH - {#PIN_NOT_AVAIL})"], + [32, "GPIO32 (FLASH - {#PIN_NOT_AVAIL})"], + [33, "GPIO33 (not exposed on S3-WROOM modules)"], + [34, "GPIO34 (not exposed on S3-WROOM modules)"], + [35, "GPIO35"], + [36, "GPIO36"], + [37, "GPIO37"], + [38, "GPIO38"], + [39, "GPIO39"], + [40, "GPIO40"], + [41, "GPIO41"], + [42, "GPIO42"], + [43, "GPIO43"], + [44, "GPIO44"], + [45, "GPIO45 ({#PIN_DONT_USE} - STRAPPING PIN)"], + [46, "GPIO46 ({#PIN_DONT_USE} - STRAPPING PIN)"], + [47, "GPIO47"], + [48, "GPIO48"], + ]; + /*ENDIF_ESP32-S3*/ + /*IF_ESP32-C3*/ + pinList = [ + [255, "off / default"], + [0, "GPIO0"], + [1, "GPIO1"], + [2, "GPIO2"], + [3, "GPIO3"], + [4, "GPIO4"], + [5, "GPIO5"], + [6, "GPIO6"], + [7, "GPIO7"], + [8, "GPIO8"], + [9, "GPIO9"], + [10, "GPIO10"], + [11, "GPIO11"], + [12, "GPIO12 (PSRAM/FLASH)"], + [13, "GPIO13 (PSRAM/FLASH)"], + [14, "GPIO14 (PSRAM/FLASH)"], + [15, "GPIO15 (PSRAM/FLASH)"], + [16, "GPIO16 (PSRAM/FLASH)"], + [17, "GPIO17 (PSRAM/FLASH)"], + [18, "GPIO18 ({#PIN_DONT_USE} - USB-)"], + [19, "GPIO19 ({#PIN_DONT_USE} - USB+)"], + [20, "GPIO20 (RX)"], + [21, "GPIO21 (TX)"], + ]; + /*ENDIF_ESP32-C3*/ + /*ENDIF_ESP32*/ + function sect(e1, e2) { return ml("div", {class: "row"}, [ ml("div", {class: "col-12"}, ml("p", {}, e1)), @@ -22,7 +181,36 @@ ]) } - function wifi() { + /*IF_ETHERNET*/ + var pins = ['cs', 'sclk', 'miso', 'mosi', 'irq', 'reset'] + function step1(obj) { + console.log(obj) + lst = [] + for(p of pins) { + lst.push( + ml("div", {class: "row mb-3"}, [ + ml("div", {class: "col-12 col-sm-3 my-2"}, p.toUpperCase()), + ml("div", {class: "col-12 col-sm-9"}, + sel(p, pinList, obj[p]) + ) + ]) + ) + } + let en = inp("en", null, null, ["cb"], "en", "checkbox"); + en.checked = obj["en"]; + + return sect("{#NETWORK_SETUP}", [ + ml("div", {class: "row mb-3"}, [ + ml("div", {class: "col-8"}, "{#ETH_ENABLE}"), + ml("div", {class: "col-4"}, en) + ]), + ...lst, + ml("div", {class: "row my-4"}, ml("div", {class: "col a-r"}, ml("input", {type: "button", class:"btn", value: "{#BTN_REBOOT}", onclick: () => {saveEth()}}, null))), + ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {href: "http://192.168.4.1/"}, "{#STOP_WIZARD}"))) + ]) + } + /*ELSE*/ + function step1() { return ml("div", {}, [ ml("div", {class: "row my-5"}, ml("div", {class: "col"}, ml("span", {class: "fs-1"}, "{#WELCOME}"))), ml("div", {class: "row"}, ml("div", {class: "col"}, ml("span", {class: "fs-5"}, "{#NETWORK_SETUP}"))), @@ -33,6 +221,7 @@ ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {href: "http://192.168.4.1/"}, "{#STOP_WIZARD}"))) ]) } + /*ENDIF_ETHERNET*/ function checkWifi() { c.replaceChildren( @@ -57,13 +246,29 @@ } } + /*IF_ETHERNET*/ + function saveEth() { + let o = { + cmd: "save_eth", + en: document.getElementsByName("en")[0].checked + } + for(p of pins) { + o[p] = document.getElementsByName(p)[0].value + } + getAjax("/api/setup", ((o) => {}), "POST", JSON.stringify(o)); + } + /*ELSE*/ function saveWifi() { var ssid = document.getElementById("net").value; if(-1 == ssid) ssid = document.getElementById("man").value; getAjax("/api/setup", ((o) => {if(!o.error) checkWifi()}), "POST", JSON.stringify({cmd: "save_wifi", ssid: ssid, pwd: document.getElementById("pwd").value})); } + /*ENDIF_ETHERNET*/ + /*IF_ETHERNET*/ + getAjax("/api/setup", ((o) => c.append(step1(o.eth)))); + /*ELSE*/ function nets(obj) { var e = document.getElementById("net"); if(obj.networks.length > 0) { @@ -79,9 +284,10 @@ } getAjax("/api/setup", ((o) => {}), "POST", JSON.stringify({cmd: "scan_wifi"})); - c.append(wifi()) - + c.append(step1()) v = setInterval(() => {getAjax('/api/setup/networks', nets)}, 2500); + /*ENDIF_ETHERNET*/ + diff --git a/src/web/lang.json b/src/web/lang.json index 22449f30..f2274b69 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -83,6 +83,11 @@ "en": "next >>", "de": "prüfen >>" }, + { + "token": "BTN_REBOOT", + "en": "reboot >>", + "de": "Ahoy neustarten >>" + }, { "token": "TEST_CONNECTION", "en": "Test Connection", @@ -112,6 +117,36 @@ "token": "NUM_NETWORKS_FOUND", "en": "Network(s) found", "de": "Netzwerk(e) gefunden" + }, + { + "token": "PIN_OFF", + "en": "off / default", + "de": "aus / Standard" + }, + { + "token": "PIN_NO_IRQ", + "en": "no IRQ!", + "de": "kein Interrupt!" + }, + { + "token": "PIN_INPUT_ONLY", + "en": "in only", + "de": "nur Eingang" + }, + { + "token": "PIN_DONT_USE", + "en": "DONT USE", + "de": "nicht benutzen" + }, + { + "token": "PIN_NOT_AVAIL", + "en": "not available", + "de": "nicht verfügbar" + }, + { + "token": "ETH_ENABLE", + "en": "Ethernet enable", + "de": "Ethernet aktivieren" } ] }, diff --git a/src/web/web.h b/src/web/web.h index f4389163..419d6826 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -447,10 +447,10 @@ class Web { request->arg("ssid").toCharArray(mConfig->sys.stationSsid, SSID_LEN); if (request->arg("pwd") != "{PWD}") request->arg("pwd").toCharArray(mConfig->sys.stationPwd, PWD_LEN); - if (request->arg("ap_pwd") != "") - request->arg("ap_pwd").toCharArray(mConfig->sys.apPwd, PWD_LEN); mConfig->sys.isHidden = (request->arg("hidd") == "on"); #endif /* !defined(ETHERNET) */ + if (request->arg("ap_pwd") != "") + request->arg("ap_pwd").toCharArray(mConfig->sys.apPwd, PWD_LEN); if (request->arg("device") != "") request->arg("device").toCharArray(mConfig->sys.deviceName, DEVNAME_LEN); mConfig->sys.darkMode = (request->arg("darkMode") == "on"); From 4291b4c83f31930564401838655ed2116a35264e Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 26 Mar 2024 00:03:27 +0100 Subject: [PATCH 053/201] 0.8.98 fix RF24_Hal.patch --- patches/RF24_Hal.patch | 116 ++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 78 deletions(-) diff --git a/patches/RF24_Hal.patch b/patches/RF24_Hal.patch index 88a53bf9..e0f44819 100644 --- a/patches/RF24_Hal.patch +++ b/patches/RF24_Hal.patch @@ -1,5 +1,5 @@ diff --git a/RF24.cpp b/RF24.cpp -index 9e5b4a8..af00758 100644 +index 2e500b6..af00758 100644 --- a/RF24.cpp +++ b/RF24.cpp @@ -12,228 +12,24 @@ @@ -605,8 +605,7 @@ index 9e5b4a8..af00758 100644 /****************************************************************************/ -bool RF24::begin(_SPI* spiBus, rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin) -+bool RF24::begin(RF24_hal* _hal) - { +-{ - ce_pin = _cepin; - csn_pin = _cspin; - return begin(spiBus); @@ -617,7 +616,8 @@ index 9e5b4a8..af00758 100644 -/****************************************************************************/ - -bool RF24::begin(rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin) --{ ++bool RF24::begin(RF24_hal* _hal) + { - ce_pin = _cepin; - csn_pin = _cspin; + hal = _hal; @@ -670,17 +670,12 @@ index 9e5b4a8..af00758 100644 bool RF24::_init_pins() { if (!isValid()) { -@@ -1028,46 +527,7 @@ bool RF24::_init_pins() +@@ -1028,41 +527,7 @@ bool RF24::_init_pins() return false; } -#if defined(RF24_LINUX) - -- #if defined(MRAA) -- GPIO(); -- gpio.begin(ce_pin, csn_pin); -- #endif -- - pinMode(ce_pin, OUTPUT); - ce(LOW); - delay(100); @@ -718,7 +713,7 @@ index 9e5b4a8..af00758 100644 } /****************************************************************************/ -@@ -1151,7 +611,7 @@ bool RF24::isChipConnected() +@@ -1146,7 +611,7 @@ bool RF24::isChipConnected() bool RF24::isValid() { @@ -727,7 +722,7 @@ index 9e5b4a8..af00758 100644 } /****************************************************************************/ -@@ -1675,15 +1135,8 @@ void RF24::closeReadingPipe(uint8_t pipe) +@@ -1670,15 +1135,8 @@ void RF24::closeReadingPipe(uint8_t pipe) void RF24::toggle_features(void) { @@ -745,7 +740,7 @@ index 9e5b4a8..af00758 100644 } /****************************************************************************/ -@@ -1871,6 +1324,11 @@ uint8_t RF24::getARC(void) +@@ -1866,6 +1324,11 @@ uint8_t RF24::getARC(void) return read_register(OBSERVE_TX) & 0x0F; } @@ -758,7 +753,7 @@ index 9e5b4a8..af00758 100644 bool RF24::setDataRate(rf24_datarate_e speed) diff --git a/RF24.h b/RF24.h -index dbd32ae..74ae35d 100644 +index c029c8e..c9d612a 100644 --- a/RF24.h +++ b/RF24.h @@ -16,12 +16,7 @@ @@ -775,7 +770,7 @@ index dbd32ae..74ae35d 100644 /** * @defgroup PALevel Power Amplifier level -@@ -115,29 +110,8 @@ typedef enum +@@ -115,26 +110,8 @@ typedef enum class RF24 { private: @@ -784,18 +779,15 @@ index dbd32ae..74ae35d 100644 -#elif defined(SPI_UART) - SPIUARTClass uspi; -#endif -- ++ RF24_hal *hal; + -#if defined(RF24_LINUX) || defined(XMEGA_D3) /* XMEGA can use SPI class */ - SPI spi; -#endif // defined (RF24_LINUX) || defined (XMEGA_D3) -#if defined(RF24_SPI_PTR) - _SPI* _spi; -#endif // defined (RF24_SPI_PTR) --#if defined(MRAA) -- GPIO gpio; --#endif -+ RF24_hal *hal; - +- - rf24_gpio_pin_t ce_pin; /* "Chip Enable" pin, activates the RX or TX role */ - rf24_gpio_pin_t csn_pin; /* SPI Chip select */ - uint32_t spi_speed; /* SPI Bus Speed */ @@ -806,7 +798,7 @@ index dbd32ae..74ae35d 100644 uint8_t status; /* The status byte returned from every SPI transaction */ uint8_t payload_size; /* Fixed size of payloads */ uint8_t pipe0_reading_address[5]; /* Last address set on pipe 0 for reading. */ -@@ -146,16 +120,6 @@ private: +@@ -143,16 +120,6 @@ private: bool _is_p0_rx; /* For keeping track of pipe 0's usage in user-triggered RX mode. */ protected: @@ -823,7 +815,7 @@ index dbd32ae..74ae35d 100644 /** Whether ack payloads are enabled. */ bool ack_payloads_enabled; /** The address width to use (3, 4 or 5 bytes). */ -@@ -198,30 +162,15 @@ public: +@@ -195,30 +162,15 @@ public: * * See [Related Pages](pages.html) for device specific information * @@ -858,7 +850,7 @@ index dbd32ae..74ae35d 100644 #if defined(RF24_LINUX) virtual ~RF24() {}; -@@ -243,58 +192,16 @@ public: +@@ -240,58 +192,16 @@ public: */ bool begin(void); @@ -869,15 +861,16 @@ index dbd32ae..74ae35d 100644 - * @note This function assumes the `SPI::begin()` method was called before to - * calling this function. - * -- * @warning This function is for the Arduino platforms only -- * + * @warning This function is for the Arduino platforms only + * - * @param spiBus A pointer or reference to an instantiated SPI bus object. - * The `_SPI` datatype is a "wrapped" definition that will represent - * various SPI implementations based on the specified platform. - * @see Review the [Arduino support page](md_docs_arduino.html). -- * -- * @return same result as begin() -- */ ++ * @param _hal A pointer to the device specific hardware abstraction layer + * + * @return same result as begin() + */ - bool begin(_SPI* spiBus); - - /** @@ -887,8 +880,8 @@ index dbd32ae..74ae35d 100644 - * @note This function assumes the `SPI::begin()` method was called before to - * calling this function. - * - * @warning This function is for the Arduino platforms only - * +- * @warning This function is for the Arduino platforms only +- * - * @param spiBus A pointer or reference to an instantiated SPI bus object. - * The `_SPI` datatype is a "wrapped" definition that will represent - * various SPI implementations based on the specified platform. @@ -896,8 +889,7 @@ index dbd32ae..74ae35d 100644 - * @param _cspin The pin attached to Chip Select (often labeled CSN) on the radio module. - * - For the Arduino Due board, the [Arduino Due extended SPI feature](https://www.arduino.cc/en/Reference/DueExtendedSPI) - * is not supported. This means that the Due's pins 4, 10, or 52 are not mandated options (can use any digital output pin) for the radio's CSN pin. -+ * @param _hal A pointer to the device specific hardware abstraction layer - * +- * - * @see Review the [Arduino support page](md_docs_arduino.html). - * - * @return same result as begin() @@ -912,14 +904,14 @@ index dbd32ae..74ae35d 100644 - * @param _cspin The pin attached to Chip Select (often labeled CSN) on the radio module. - * - For the Arduino Due board, the [Arduino Due extended SPI feature](https://www.arduino.cc/en/Reference/DueExtendedSPI) - * is not supported. This means that the Due's pins 4, 10, or 52 are not mandated options (can use any digital output pin) for the radio's CSN pin. - * @return same result as begin() - */ +- * @return same result as begin() +- */ - bool begin(rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin); + bool begin(RF24_hal* _hal); /** * Checks if the chip is connected to the SPI bus -@@ -667,12 +574,12 @@ public: +@@ -664,12 +574,12 @@ public: * This function uses much less ram than other `*print*Details()` methods. * * @code @@ -934,17 +926,7 @@ index dbd32ae..74ae35d 100644 * cause undefined behavior. * * Registers names and/or data corresponding to the index of the `encoded_details` array: -@@ -704,9 +611,6 @@ public: - * | 35 | FIFO_STATUS | - * | 36 | DYNPD | - * | 37 | FEATURE | -- * | 38-39 | ce_pin | -- * | 40-41 | csn_pin | -- * | 42 | SPI speed (in MHz) or'd with (isPlusVariant << 4) | - */ - void encodeRadioDetails(uint8_t* encoded_status); - -@@ -1644,6 +1548,7 @@ public: +@@ -1641,6 +1551,7 @@ public: * @return Returns values from 0 to 15. */ uint8_t getARC(void); @@ -952,7 +934,7 @@ index dbd32ae..74ae35d 100644 /** * Set the transmission @ref Datarate -@@ -1896,18 +1801,6 @@ private: +@@ -1893,17 +1804,6 @@ private: */ bool _init_pins(); @@ -967,35 +949,13 @@ index dbd32ae..74ae35d 100644 - * @param mode HIGH to take this unit off the SPI bus, LOW to put it on - */ - void csn(bool mode); -- + /** * Set chip enable - * -diff --git a/RF24_hal.cpp b/RF24_hal.cpp -new file mode 100644 -index 0000000..3cc78e4 ---- /dev/null -+++ b/RF24_hal.cpp -@@ -0,0 +1 @@ -+#include "RF24_hal.h" -diff --git a/RF24_hal.h b/RF24_hal.h -new file mode 100644 -index 0000000..baceab3 ---- /dev/null -+++ b/RF24_hal.h -@@ -0,0 +1,15 @@ -+#pragma once -+ -+#include "RF24_config.h" -+ -+class RF24_hal -+{ -+public: -+ virtual void ce(bool level) = 0; -+ virtual uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t len) = 0; -+ virtual uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t data_len, uint8_t blank_len) = 0; -+ virtual uint8_t write(uint8_t cmd, const uint8_t* buf, uint8_t len) = 0; -+ virtual uint8_t write(uint8_t cmd, const uint8_t* buf, uint8_t len, uint8_t blank_len) = 0; -+ virtual bool begin() = 0; -+ virtual void end() = 0; -+}; +@@ -2412,4 +2312,4 @@ private: + * Use `ctrl+c` to quit at any time. + */ + +-#endif // __RF24_H__ +\ No newline at end of file ++#endif // __RF24_H__ From 8a0b9e90299d385dd7d1de972f0a98da06add4c3 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 26 Mar 2024 00:18:24 +0100 Subject: [PATCH 054/201] 0.8.98 fix compile --- src/network/AhoyNetwork.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index 5ce668df..f90096db 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -161,6 +161,17 @@ class AhoyNetwork { } } + #if !defined(ETHERNET) + void 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]); + } + #endif + private: void sendNTPpacket(IPAddress& address) { //DPRINTLN(DBG_VERBOSE, F("wifi::sendNTPpacket")); @@ -200,17 +211,6 @@ class AhoyNetwork { mUdp.close(); } - #if !defined(ETHERNET) - void 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]); - } - #endif - protected: enum class NetworkState : uint8_t { DISCONNECTED, From f47cb107f32a248b4c5abf05d154b9d18f7c1004 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 26 Mar 2024 00:31:09 +0100 Subject: [PATCH 055/201] 0.8.98 fix compile --- src/hm/nrfHal.h | 2 +- src/platformio.ini | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/hm/nrfHal.h b/src/hm/nrfHal.h index b9265626..89fe0885 100644 --- a/src/hm/nrfHal.h +++ b/src/hm/nrfHal.h @@ -11,7 +11,7 @@ #include "../utils/spiPatcher.h" #include -#include +#include #define NRF_MAX_TRANSFER_SZ 64 #define NRF_DEFAULT_SPI_SPEED 10000000 // 10 MHz diff --git a/src/platformio.ini b/src/platformio.ini index 4d0d528d..7edf99ba 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -67,6 +67,7 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L +lib_deps = ${env:esp8266.lib_deps} build_flags = ${env:esp8266.build_flags} -DLANG_DE monitor_filters = @@ -76,6 +77,7 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L +lib_deps = ${env:esp8266.lib_deps} build_flags = ${env:esp8266.build_flags} -DPLUGIN_DISPLAY -DENABLE_HISTORY @@ -86,6 +88,7 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L +lib_deps = ${env:esp8266.lib_deps} build_flags = ${env:esp8266-all.build_flags} -DLANG_DE monitor_filters = @@ -95,6 +98,7 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L +lib_deps = ${env:esp8266.lib_deps} build_flags = ${env:esp8266-all.build_flags} -DENABLE_PROMETHEUS_EP monitor_filters = @@ -104,6 +108,7 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L +lib_deps = ${env:esp8266.lib_deps} build_flags = ${env:esp8266-prometheus.build_flags} -DLANG_DE monitor_filters = @@ -116,6 +121,7 @@ platform = espressif8266 board = esp8285 board_build.ldscript = eagle.flash.1m64.ld board_build.f_cpu = 80000000L +lib_deps = ${env:esp8266.lib_deps} build_flags = ${env.build_flags} -DEMC_MIN_FREE_MEMORY=4096 -DENABLE_MQTT @@ -129,6 +135,7 @@ platform = espressif8266 board = esp8285 board_build.ldscript = eagle.flash.1m64.ld board_build.f_cpu = 80000000L +lib_deps = ${env:esp8266.lib_deps} build_flags = ${env.build_flags} -DEMC_MIN_FREE_MEMORY=4096 -DLANG_DE From d5ed0272e9f3211a04d0e60a12f1ded02f8a599f Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 26 Mar 2024 22:30:11 +0100 Subject: [PATCH 056/201] 0.8.99 * fix compilation of all environments --- patches/RF24_Hal.patch | 21 +++++++++++++++++++++ src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/platformio.ini | 6 ++++-- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/patches/RF24_Hal.patch b/patches/RF24_Hal.patch index e0f44819..ed2c5bec 100644 --- a/patches/RF24_Hal.patch +++ b/patches/RF24_Hal.patch @@ -959,3 +959,24 @@ index c029c8e..c9d612a 100644 -#endif // __RF24_H__ \ No newline at end of file +#endif // __RF24_H__ +diff --git a/RF24_hal.h b/RF24_hal.h +new file mode 100644 +index 0000000..baceab3 +--- /dev/null ++++ b/RF24_hal.h +@@ -0,0 +1,15 @@ ++#pragma once ++ ++#include "RF24_config.h" ++ ++class RF24_hal ++{ ++public: ++ virtual void ce(bool level) = 0; ++ virtual uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t len) = 0; ++ virtual uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t data_len, uint8_t blank_len) = 0; ++ virtual uint8_t write(uint8_t cmd, const uint8_t* buf, uint8_t len) = 0; ++ virtual uint8_t write(uint8_t cmd, const uint8_t* buf, uint8_t len, uint8_t blank_len) = 0; ++ virtual bool begin() = 0; ++ virtual void end() = 0; ++}; diff --git a/src/CHANGES.md b/src/CHANGES.md index f2cc8785..3193ac15 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.99 - 2024-03-27 +* fix compilation of all environments + ## 0.8.98 - 2024-03-24 * new network routines diff --git a/src/defines.h b/src/defines.h index 2058ce3a..5c09041d 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 98 +#define VERSION_PATCH 99 //------------------------------------- typedef struct { diff --git a/src/platformio.ini b/src/platformio.ini index 7edf99ba..cde08cb1 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -45,6 +45,9 @@ build_unflags = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L +lib_deps = + ${env.lib_deps} + https://github.com/me-no-dev/ESPAsyncUDP build_flags = ${env.build_flags} -DEMC_MIN_FREE_MEMORY=4096 ;-Wl,-Map,output.map @@ -55,8 +58,7 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -lib_deps = - ${env.lib_deps} +lib_deps = ${env:esp8266-minimal.lib_deps} https://github.com/me-no-dev/ESPAsyncUDP build_flags = ${env:esp8266-minimal.build_flags} -DENABLE_MQTT From 4b75e72bf3efde5aad73510169fd1fd43751b18d Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 26 Mar 2024 23:39:09 +0100 Subject: [PATCH 057/201] 0.8.100 * fix captions in `/history #1532 * fix get NTP time #1529 #1530 * fix translation #1516 --- src/CHANGES.md | 5 +++++ src/app.cpp | 12 +++--------- src/app.h | 1 - src/defines.h | 3 +-- src/network/AhoyNetwork.h | 10 ++++------ src/web/html/history.html | 2 +- src/web/lang.json | 10 +++++----- 7 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 3193ac15..15b9a380 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.8.100 - 2024-03-27 +* fix captions in `/history #1532 +* fix get NTP time #1529 #1530 +* fix translation #1516 + ## 0.8.99 - 2024-03-27 * fix compilation of all environments diff --git a/src/app.cpp b/src/app.cpp index 2dd8c49c..506074c5 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -245,17 +245,12 @@ void app::tickNtpUpdate(void) { if (!mNtpReceived) mNetwork->updateNtpTime(); - else + else { + nxtTrig = mConfig->ntp.interval * 60; // check again in configured interval mNtpReceived = false; + } updateNtp(); - nxtTrig = mConfig->ntp.interval * 60; // check again in 12h - - // immediately start communicating - if (mSendFirst) { - mSendFirst = false; - once(std::bind(&app::tickSend, this), 1, "senOn"); - } mMqttReconnect = false; @@ -532,7 +527,6 @@ void app::resetSystem(void) { mTimestamp = 1; #endif - mSendFirst = true; mAllIvNotAvail = true; mSunrise = 0; diff --git a/src/app.h b/src/app.h index cb546267..66234a31 100644 --- a/src/app.h +++ b/src/app.h @@ -440,7 +440,6 @@ class app : public IApp, public ah::Scheduler { bool mSaveReboot = false; uint8_t mSendLastIvId = 0; - bool mSendFirst = false; bool mAllIvNotAvail = false; bool mNetworkConnected = false; diff --git a/src/defines.h b/src/defines.h index 5c09041d..86c8a888 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,8 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 99 - +#define VERSION_PATCH 100 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index f90096db..9573f48f 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -57,11 +57,11 @@ class AhoyNetwork { } bool updateNtpTime(void) { - if(NetworkState::CONNECTED != mStatus) + if(NetworkState::GOT_IP != mStatus) return false; - IPAddress timeServer; if (!mUdp.connected()) { + IPAddress timeServer; if (!WiFi.hostByName(mConfig->ntp.addr, timeServer)) return false; if (!mUdp.connect(timeServer, mConfig->ntp.port)) @@ -71,7 +71,7 @@ class AhoyNetwork { mUdp.onPacket([this](AsyncUDPPacket packet) { this->handleNTPPacket(packet); }); - sendNTPpacket(timeServer); + sendNTPpacket(); return true; } @@ -173,7 +173,7 @@ class AhoyNetwork { #endif private: - void sendNTPpacket(IPAddress& address) { + void sendNTPpacket(void) { //DPRINTLN(DBG_VERBOSE, F("wifi::sendNTPpacket")); uint8_t buf[NTP_PACKET_SIZE]; memset(buf, 0, NTP_PACKET_SIZE); @@ -188,9 +188,7 @@ class AhoyNetwork { buf[14] = 49; buf[15] = 52; - //mUdp.beginPacket(address, 123); // NTP request, port 123 mUdp.write(buf, NTP_PACKET_SIZE); - //mUdp.endPacket(); } void handleNTPPacket(AsyncUDPPacket packet) { diff --git a/src/web/html/history.html b/src/web/html/history.html index 57bff2fc..7ec9be7e 100644 --- a/src/web/html/history.html +++ b/src/web/html/history.html @@ -136,7 +136,7 @@ return [ mlNs("polyline", {stroke: "url(#gLine)", fill: "none", points: pts}), mlNs("polyline", {stroke: "none", fill: "url(#gFill)", points: pts2}), - mlNs("text", {x: i*.8, y: 10}, "{#MAX_DAY}: " + String(obj.max) + "W"), + mlNs("text", {x: i*.8, y: 10}, "{#MAXIMUM}: " + String(obj.max) + "W"), mlNs("text", {x: i*.8, y: 25}, "{#LAST_VALUE}: " + String(lastVal) + "W") ] } diff --git a/src/web/lang.json b/src/web/lang.json index f2274b69..ee942608 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -631,7 +631,7 @@ { "token": "BTN_INV_ADD", "en": "add Inverter", - "de": "Wechselrichter hinzufuegen" + "de": "Wechselrichter hinzuf\u00FCgen" }, { "token": "INV_INPUT", @@ -656,7 +656,7 @@ { "token": "TAB_INPUTS", "en": "Inputs", - "de": "Eingaenge" + "de": "Eingänge" }, { "token": "TAB_RADIO", @@ -1579,9 +1579,9 @@ "de": "Gesamtertrag pro Tag" }, { - "token": "MAX_DAY", - "en": "Maximum day", - "de": "Tagesmaximum" + "token": "MAXIMUM", + "en": "Maximum", + "de": "Maximum" }, { "token": "LAST_VALUE", From 2a4c83647af2c832de06ecf9a10b552d22e377b0 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 27 Mar 2024 22:49:18 +0100 Subject: [PATCH 058/201] 0.8.101 * updated converter scripts to include all enabled features again (redundant scan of build flags) #1534 --- scripts/convertHtml.py | 20 +++++++++++++++----- scripts/htmlPreprocessorDefines.py | 2 +- src/CHANGES.md | 3 +++ src/defines.h | 2 +- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/scripts/convertHtml.py b/scripts/convertHtml.py index ec16b5f3..026c28da 100644 --- a/scripts/convertHtml.py +++ b/scripts/convertHtml.py @@ -9,19 +9,29 @@ from pathlib import Path import subprocess import configparser Import("env") +build_flags = [] import htmlPreprocessorDefines as prepro +def getFlagsOfEnv(env): + config = configparser.ConfigParser() + config.read('platformio.ini') + global build_flags + flags = config[env]['build_flags'].split('\n') + + for i in range(len(flags)): + if flags[i][:2] == "-D" or flags[i][:2] == "${": + flags[i] = flags[i][2:] + if flags[i][-13:-1] == ".build_flags": + getFlagsOfEnv(flags[i].split(".build_flags")[0]) + elif len(flags[i]) > 0: + build_flags = build_flags + [flags[i]] def get_build_flags(): + getFlagsOfEnv("env:" + env['PIOENV']) config = configparser.ConfigParser() config.read('platformio.ini') - global build_flags - build_flags = config["env:" + env['PIOENV']]['build_flags'].split('\n') - - for i in range(len(build_flags)): - build_flags[i] = build_flags[i][2:] # translate board board = config["env:" + env['PIOENV']]['board'] diff --git a/scripts/htmlPreprocessorDefines.py b/scripts/htmlPreprocessorDefines.py index f5d7cc31..f8230a90 100644 --- a/scripts/htmlPreprocessorDefines.py +++ b/scripts/htmlPreprocessorDefines.py @@ -35,6 +35,6 @@ def check(inp, lst, pattern): return out def conv(inp, lst): - #print(lst) + print(lst) out = check(inp, lst, r'\/\*(?:IF_|ELS|ENDIF_)([A-Z0-9\-_]+)?\*\/') return check(out, lst, r'\<\!\-\-(?:IF_|ELS|ENDIF_)([A-Z0-9\-_]+)?\-\-\>') diff --git a/src/CHANGES.md b/src/CHANGES.md index 15b9a380..f8b8ba84 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.101 - 2024-03-28 +* updated converter scripts to include all enabled features again (redundant scan of build flags) #1534 + ## 0.8.100 - 2024-03-27 * fix captions in `/history #1532 * fix get NTP time #1529 #1530 diff --git a/src/defines.h b/src/defines.h index 86c8a888..3edc6f09 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 100 +#define VERSION_PATCH 101 //------------------------------------- typedef struct { uint8_t ch; From 5294ae3009d858a5459b486d4ca1094b136433ca Mon Sep 17 00:00:00 2001 From: geronet1 Date: Fri, 29 Mar 2024 22:20:47 +0100 Subject: [PATCH 059/201] =?UTF-8?q?MQTT=20JSON=20Payload=20pro=20Kanal=20u?= =?UTF-8?q?nd=20total,=20ausw=C3=A4hlbar=20NodeRED=20Beispiel=20Bug=20#152?= =?UTF-8?q?2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/settings.h | 4 + src/publisher/pubMqtt.h | 2 +- src/publisher/pubMqttIvData.h | 63 ++- src/web/RestApi.h | 3 +- src/web/html/setup.html | 5 + src/web/lang.json | 5 + src/web/web.h | 1 + tools/NodeRED/flows-mqtt-json-example.json | 466 +++++++++++++++++++++ 8 files changed, 537 insertions(+), 12 deletions(-) create mode 100644 tools/NodeRED/flows-mqtt-json-example.json diff --git a/src/config/settings.h b/src/config/settings.h index 8f20ba8f..016af2e3 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -151,6 +151,7 @@ typedef struct { char user[MQTT_USER_LEN]; char pwd[MQTT_PWD_LEN]; char topic[MQTT_TOPIC_LEN]; + bool json; uint16_t interval; } cfgMqtt_t; @@ -477,6 +478,7 @@ 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.json = 0; // off mCfg.inst.sendInterval = SEND_INTERVAL; mCfg.inst.rstYieldMidNight = false; @@ -732,11 +734,13 @@ class settings { obj[F("user")] = mCfg.mqtt.user; obj[F("pwd")] = mCfg.mqtt.pwd; obj[F("topic")] = mCfg.mqtt.topic; + obj[F("json")] = mCfg.mqtt.json; obj[F("intvl")] = mCfg.mqtt.interval; } else { getVal(obj, F("port"), &mCfg.mqtt.port); getVal(obj, F("intvl"), &mCfg.mqtt.interval); + getVal(obj, F("json"), &mCfg.mqtt.json); getChar(obj, F("broker"), mCfg.mqtt.broker, MQTT_ADDR_LEN); getChar(obj, F("user"), mCfg.mqtt.user, MQTT_USER_LEN); getChar(obj, F("clientId"), mCfg.mqtt.clientId, MQTT_CLIENTID_LEN); diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 2d393b8b..14445a2b 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -62,7 +62,7 @@ class PubMqtt { mUptime = uptime; mIntervalTimeout = 1; - SendIvData.setup(sys, utcTs, &mSendList); + SendIvData.setup(sys, cfg_mqtt->json, utcTs, &mSendList); SendIvData.setPublishFunc([this](const char *subTopic, const char *payload, bool retained, uint8_t qos) { publish(subTopic, payload, retained, true, qos); }); diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 6ddd63a9..6ac59cca 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -24,8 +24,9 @@ class PubMqttIvData { public: PubMqttIvData() : mTotal{}, mSubTopic{}, mVal{} {} - void setup(HMSYSTEM *sys, uint32_t *utcTs, std::queue *sendList) { + void setup(HMSYSTEM *sys, bool json, uint32_t *utcTs, std::queue *sendList) { mSys = sys; + mJson = json; mUtcTimestamp = utcTs; mSendList = sendList; mState = IDLE; @@ -197,18 +198,43 @@ class PubMqttIvData { static_cast(mIv->getChannelFieldValue(CH0, FLD_GRID_PROFILE_VERSION, rec))); retained = true; } else { - snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); - snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mIv->getValue(mPos, rec))); + if (!mJson) { + snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); + snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mIv->getValue(mPos, rec))); + } } - uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0; - if((FLD_EVT != rec->assign[mPos].fieldId) - && (FLD_LAST_ALARM_CODE != rec->assign[mPos].fieldId)) - mPublish(mSubTopic.data(), mVal.data(), retained, qos); + if (InverterDevInform_All == mCmd || InverterDevInform_Simple == mCmd || !mJson) { + uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0; + if((FLD_EVT != rec->assign[mPos].fieldId) + && (FLD_LAST_ALARM_CODE != rec->assign[mPos].fieldId)) + mPublish(mSubTopic.data(), mVal.data(), retained, qos); + } } mPos++; } else { if (MqttSentStatus::LAST_SUCCESS_SENT == rec->mqttSentStatus) { + if (mJson) { + DynamicJsonDocument doc(300); + std::array buf; + int ch = rec->assign[0].ch; + + for (mPos = 0; mPos <= rec->length; mPos++) { + if (rec->assign[mPos].ch != ch) { + // if next channel.. publish + serializeJson(doc, buf.data(), buf.size()); + doc.clear(); + snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d", mIv->config->name, ch); + mPublish(mSubTopic.data(), buf.data(), false, QOS_0); + ch = rec->assign[mPos].ch; + } + if (mPos == rec->length) + break; + + doc[fields[rec->assign[mPos].fieldId]] = ah::round3(mIv->getValue(mPos, rec)); + } + } + sendRadioStat(rec->length); rec->mqttSentStatus = MqttSentStatus::DATA_SENT; } @@ -265,11 +291,27 @@ class PubMqttIvData { retained = false; break; } - snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[fieldId]); - snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mTotal[mPos])); - mPublish(mSubTopic.data(), mVal.data(), retained, QOS_0); + if (!mJson) { + snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[fieldId]); + snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mTotal[mPos])); + mPublish(mSubTopic.data(), mVal.data(), retained, QOS_0); + } mPos++; } else { + if (mJson) { + int type[5] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC, FLD_MP}; + snprintf(mVal.data(), mVal.size(), "{"); + + for (mPos = 0; mPos < 5; mPos++) { + snprintf(mSubTopic.data(), mSubTopic.size(), "\"%s\":%g", fields[type[mPos]], ah::round3(mTotal[mPos])); + strcat(mVal.data(), mSubTopic.data()); + if (mPos < 4) + strcat(mVal.data(), ","); + else + strcat(mVal.data(), "}"); + } + mPublish(F("total"), mVal.data(), true, QOS_0); + } mSendList->pop(); mSendTotals = false; mState = IDLE; @@ -294,6 +336,7 @@ class PubMqttIvData { std::array mSubTopic; std::array mVal; + bool mJson; std::queue *mSendList = nullptr; }; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 8087883e..31104af0 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -80,7 +80,7 @@ class RestApi { mHeapFrag = ESP.getHeapFragmentation(); #endif - AsyncJsonResponse* response = new AsyncJsonResponse(false, 6000); + AsyncJsonResponse* response = new AsyncJsonResponse(false, 8000); JsonObject root = response->getRoot(); String path = request->url().substring(5); @@ -709,6 +709,7 @@ class RestApi { 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("json")] = (bool) mConfig->mqtt.json; obj[F("interval")] = String(mConfig->mqtt.interval); } diff --git a/src/web/html/setup.html b/src/web/html/setup.html index fb1eff97..0e248c08 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -242,6 +242,10 @@
Topic
+
+
{#MQTT_JSON}
+
+

{#MQTT_NOTE}

{#INTERVAL}
@@ -931,6 +935,7 @@ function parseMqtt(obj) { for(var i of [["Addr", "broker"], ["Port", "port"], ["ClientId", "clientId"], ["User", "user"], ["Pwd", "pwd"], ["Topic", "topic"], ["Interval", "interval"]]) document.getElementsByName("mqtt"+i[0])[0].value = obj[i[1]]; + document.getElementsByName("mqttJson")[0].checked = obj["json"]; } function parseNtp(obj) { diff --git a/src/web/lang.json b/src/web/lang.json index ee942608..70ca2015 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -418,6 +418,11 @@ "en": "Password (optional)", "de": "Passwort (optional)" }, + { + "token": "MQTT_JSON", + "en": "Payload as JSON", + "de": "Ausgabe als JSON" + }, { "token": "MQTT_NOTE", "en": "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)", diff --git a/src/web/web.h b/src/web/web.h index 419d6826..bd806b84 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -574,6 +574,7 @@ class Web { 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.json = (request->arg("mqttJson") == "on"); mConfig->mqtt.port = request->arg("mqttPort").toInt(); mConfig->mqtt.interval = request->arg("mqttInterval").toInt(); diff --git a/tools/NodeRED/flows-mqtt-json-example.json b/tools/NodeRED/flows-mqtt-json-example.json new file mode 100644 index 00000000..5e2e09a1 --- /dev/null +++ b/tools/NodeRED/flows-mqtt-json-example.json @@ -0,0 +1,466 @@ +[ + { + "id": "67bced2c4e728783", + "type": "mqtt in", + "z": "5de5756d190f9086", + "name": "", + "topic": "hoymiles/+", + "qos": "0", + "datatype": "auto-detect", + "broker": "319864a4e0fd913f", + "nl": false, + "rap": true, + "rh": 0, + "inputs": 0, + "x": 80, + "y": 2100, + "wires": [ + [ + "a55632ad0dff0b69" + ] + ] + }, + { + "id": "a7f0d307d7cf77e2", + "type": "mqtt in", + "z": "5de5756d190f9086", + "name": "", + "topic": "hoymiles/X/#", + "qos": "0", + "datatype": "auto-detect", + "broker": "319864a4e0fd913f", + "nl": false, + "rap": true, + "rh": 0, + "inputs": 0, + "x": 90, + "y": 2260, + "wires": [ + [ + "7e17e5a3f4df3011", + "1a8cca488d53394a" + ] + ] + }, + { + "id": "7e17e5a3f4df3011", + "type": "debug", + "z": "5de5756d190f9086", + "name": "Inverter X", + "active": false, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 340, + "y": 2260, + "wires": [] + }, + { + "id": "fb7357db50501627", + "type": "change", + "z": "5de5756d190f9086", + "name": "Tags setzen", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "(\t $a := $split(topic, '/');\t [\t payload,\t {\t \"device\":$a[0],\t \"name\":$a[1],\t \"channel\":$a[2]\t }\t ]\t)\t", + "tot": "jsonata" + }, + { + "t": "delete", + "p": "topic", + "pt": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 610, + "y": 2360, + "wires": [ + [ + "91a4607dfda84b67" + ] + ] + }, + { + "id": "670eb9fbb5c31b2c", + "type": "debug", + "z": "5de5756d190f9086", + "name": "InfluxDB", + "active": false, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 940, + "y": 2360, + "wires": [] + }, + { + "id": "1a8cca488d53394a", + "type": "switch", + "z": "5de5756d190f9086", + "name": "", + "property": "$split(topic, '/')[2]", + "propertyType": "jsonata", + "rules": [ + { + "t": "eq", + "v": "available", + "vt": "str" + }, + { + "t": "eq", + "v": "last_success", + "vt": "str" + }, + { + "t": "regex", + "v": "(ch[0-6])\\b", + "vt": "str", + "case": false + }, + { + "t": "eq", + "v": "radio_stat", + "vt": "str" + }, + { + "t": "eq", + "v": "firmware", + "vt": "str" + }, + { + "t": "eq", + "v": "hardware", + "vt": "str" + }, + { + "t": "eq", + "v": "alarm", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 7, + "x": 330, + "y": 2380, + "wires": [ + [ + "845aeb93e39092c5" + ], + [ + "241a8e70e9fde93c" + ], + [ + "fb7357db50501627" + ], + [ + "9d38f021308664c1" + ], + [ + "a508355f0cc87966" + ], + [ + "d2c9aa1a8978aca6" + ], + [ + "b27032beb597d5a7" + ] + ] + }, + { + "id": "845aeb93e39092c5", + "type": "debug", + "z": "5de5756d190f9086", + "name": "available", + "active": true, + "tosidebar": false, + "console": false, + "tostatus": true, + "complete": "payload", + "targetType": "msg", + "statusVal": "payload", + "statusType": "auto", + "x": 600, + "y": 2240, + "wires": [] + }, + { + "id": "241a8e70e9fde93c", + "type": "debug", + "z": "5de5756d190f9086", + "name": "last_success", + "active": true, + "tosidebar": false, + "console": false, + "tostatus": true, + "complete": "payload", + "targetType": "msg", + "statusVal": "payload", + "statusType": "auto", + "x": 610, + "y": 2300, + "wires": [] + }, + { + "id": "9d38f021308664c1", + "type": "debug", + "z": "5de5756d190f9086", + "name": "radio_stat", + "active": false, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 600, + "y": 2400, + "wires": [] + }, + { + "id": "a508355f0cc87966", + "type": "debug", + "z": "5de5756d190f9086", + "name": "firmware", + "active": false, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 600, + "y": 2440, + "wires": [] + }, + { + "id": "d2c9aa1a8978aca6", + "type": "debug", + "z": "5de5756d190f9086", + "name": "hardware", + "active": false, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 600, + "y": 2480, + "wires": [] + }, + { + "id": "b27032beb597d5a7", + "type": "debug", + "z": "5de5756d190f9086", + "name": "alarm", + "active": false, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 590, + "y": 2520, + "wires": [] + }, + { + "id": "d814738cf55ad663", + "type": "debug", + "z": "5de5756d190f9086", + "name": "total", + "active": false, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 590, + "y": 2160, + "wires": [] + }, + { + "id": "a55632ad0dff0b69", + "type": "switch", + "z": "5de5756d190f9086", + "name": "", + "property": "$split(topic, '/')[1]", + "propertyType": "jsonata", + "rules": [ + { + "t": "eq", + "v": "uptime", + "vt": "str" + }, + { + "t": "eq", + "v": "wifi_rssi", + "vt": "str" + }, + { + "t": "eq", + "v": "status", + "vt": "str" + }, + { + "t": "eq", + "v": "total", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 4, + "x": 330, + "y": 2100, + "wires": [ + [ + "1fbb0674d2576ee7" + ], + [ + "e6be1c98ac55f511" + ], + [ + "f9c2d3b30e34fdda" + ], + [ + "d814738cf55ad663" + ] + ] + }, + { + "id": "f9c2d3b30e34fdda", + "type": "debug", + "z": "5de5756d190f9086", + "name": "status", + "active": false, + "tosidebar": false, + "console": false, + "tostatus": true, + "complete": "payload", + "targetType": "msg", + "statusVal": "payload", + "statusType": "auto", + "x": 590, + "y": 2100, + "wires": [] + }, + { + "id": "e6be1c98ac55f511", + "type": "debug", + "z": "5de5756d190f9086", + "name": "wifi_rssi", + "active": false, + "tosidebar": false, + "console": false, + "tostatus": true, + "complete": "payload", + "targetType": "msg", + "statusVal": "payload", + "statusType": "auto", + "x": 600, + "y": 2040, + "wires": [] + }, + { + "id": "1fbb0674d2576ee7", + "type": "debug", + "z": "5de5756d190f9086", + "name": "uptime", + "active": false, + "tosidebar": false, + "console": false, + "tostatus": true, + "complete": "payload", + "targetType": "msg", + "statusVal": "payload", + "statusType": "auto", + "x": 590, + "y": 1980, + "wires": [] + }, + { + "id": "91a4607dfda84b67", + "type": "change", + "z": "5de5756d190f9086", + "name": "Lösche", + "rules": [ + { + "t": "delete", + "p": "payload[0].YieldDay", + "pt": "msg" + }, + { + "t": "delete", + "p": "payload[0].MaxPower", + "pt": "msg" + }, + { + "t": "delete", + "p": "payload[0].ALARM_MES_ID", + "pt": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 780, + "y": 2360, + "wires": [ + [ + "670eb9fbb5c31b2c" + ] + ] + }, + { + "id": "319864a4e0fd913f", + "type": "mqtt-broker", + "name": "broker", + "broker": "localhost", + "port": "1883", + "clientid": "", + "autoConnect": true, + "usetls": false, + "protocolVersion": "4", + "keepalive": "60", + "cleansession": true, + "birthTopic": "", + "birthQos": "0", + "birthPayload": "", + "birthMsg": {}, + "closeTopic": "", + "closeQos": "0", + "closePayload": "", + "closeMsg": {}, + "willTopic": "", + "willQos": "0", + "willPayload": "", + "willMsg": {}, + "userProps": "", + "sessionExpiry": "" + } +] \ No newline at end of file From 59b1fe866f9851e5f865b2ba25516409fba26985 Mon Sep 17 00:00:00 2001 From: geronet1 Date: Sun, 31 Mar 2024 21:20:35 +0200 Subject: [PATCH 060/201] mqtt->rssi nicht in /ch0/, mqtt->json kein YieldDay/YieldTotal einzeln --- .../htmlPreprocessorDefines.cpython-311.pyc | Bin 0 -> 2235 bytes src/publisher/pubMqtt.h | 3 +++ src/publisher/pubMqttIvData.h | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 scripts/__pycache__/htmlPreprocessorDefines.cpython-311.pyc diff --git a/scripts/__pycache__/htmlPreprocessorDefines.cpython-311.pyc b/scripts/__pycache__/htmlPreprocessorDefines.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8b8e34409896b76a6d2fa979407131efe3b7e1f0 GIT binary patch literal 2235 zcma)7-EY%Y6u;LWiIWtPEUh46Dk)t>%~pz_v`7PGL53D}{+ zTlUb>(ygV*AWs==io_C%!AOr|3XctXLtc|jZNYc*vy;NtvP5KIS&>#F31K!VN(muy zKbaX5m9)hOa+JhUiY(k$HsW6qDMgY|NtTmjPFjs6B>8+QW3Un-NkTYK%EBuT0m-2T zr`0h&9rkFk)j0bJ~Dy7XGcb) z56Lj=mOV17(iK|=*Wr4-m(K&v-r4PNy|^r=aw6q#Z>#q1*}8QiVq(}1Cd+Q;kM!Gi zgx{ZmKjtmIH+n6q>?+l(0V5SsJdKF+5E4H`;K^@CdU81Gtq6YeVG$&5#n*9G2=6J_hnw959uDK)%3a}b3Am8n=wq~qH@2RR6t++EBdC8!J(ts{Jgm^W$I zLgBeD=I_1!2gYkN?+qHJ1`cfvj)rb7hxp(|OqOGbwO}$OC4#aNQKStip$zdZgWXI^ zX~}ThjIAbbTP#H+!w!`yM&faUj!OxHF=tS-8!07Y&}))n(5bXyRj*--q(G<0I}AFO zNC93}40|e~C=y8+c+;ShY3L;Dl9V!-IF!GE9~)Sb%{mIU1~D_*V59e?=sFn&-rSWX zI0^Iw?%1}w#`)`RQYomKs-F&;Y?=96_YRc&1%LVTns=z~9jYw7@}8}F z&*~m;i7l|&rX_bri`P8Eb&hkXf6RdlJRZsA(?mC`ZBxbmy?Jfrs zvv*m2RRpHDud4WPK6d|HRHR}N?}F@})z?5AWvLzn1qiAa0l7?vw|HS(I5&D@5>i)% ztX21unjigkW^Coc*fnA7-rZ068^SqZd}~~o7KVf|VeJ3m01~eA6fs+~m0LVb0w#aT zB!fU?(^E*r{VZgn$;3l40!!vAUj(xMV;X+4_;fM1*l@ZvT3fCL=4;M{x^p2n+i-a_ zpBAm2`m*K<*InT%6SgAC+sH>CZBR*>c!06$#d5(?|0}XkmeqIM^hQ!l$EE9J6p&^K s%L0%ljWO1dBWFEbOkd7=nhb?qP1Gh_0K1#0O|H`T7KX(BPik5J7Z*a)+W-In literal 0 HcmV?d00001 diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 14445a2b..a9a91974 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -559,6 +559,9 @@ class PubMqtt { } void sendData(Inverter<> *iv, uint8_t curInfoCmd) { + if (cfg_mqtt->json) + return; + record_t<> *rec = iv->getRecordStruct(curInfoCmd); uint32_t lastTs = iv->getLastTs(rec); diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 6ac59cca..6c1e433d 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -115,7 +115,7 @@ class PubMqttIvData { mPublish(mSubTopic.data(), mVal.data(), true, QOS_0); if((mIv->ivGen == IV_HMS) || (mIv->ivGen == IV_HMT)) { - snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch0/rssi", mIv->config->name); + snprintf(mSubTopic.data(), mSubTopic.size(), "%s/rssi", mIv->config->name); snprintf(mVal.data(), mVal.size(), "%d", mIv->rssi); mPublish(mSubTopic.data(), mVal.data(), false, QOS_0); } From d664221e5400be354df1eca5b81ef7db3eebfe38 Mon Sep 17 00:00:00 2001 From: geronet1 Date: Sun, 31 Mar 2024 21:32:57 +0200 Subject: [PATCH 061/201] mCfgMqtt statt cfg_mqtt --- src/publisher/pubMqtt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index a9a91974..159c7939 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -559,7 +559,7 @@ class PubMqtt { } void sendData(Inverter<> *iv, uint8_t curInfoCmd) { - if (cfg_mqtt->json) + if (mCfgMqtt->json) return; record_t<> *rec = iv->getRecordStruct(curInfoCmd); From d0741a91e8d0e9edcff94c16d3e0a86c5b83e0fc Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Mon, 1 Apr 2024 13:42:48 +0200 Subject: [PATCH 062/201] shorten last cmt waiting time after last frame is received. Works, see around this discord post: https://discord.com/channels/984173303147155506/1029761098381017098/1220679912587792404 --- src/hms/hmsRadio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index d074442b..54975197 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -183,7 +183,7 @@ class CmtRadio : public Radio { if(p.packet[9] > ALL_FRAMES) { // indicates last frame setExpectedFrames(p.packet[9] - ALL_FRAMES); - mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first get back to rx mode? + mRadioWaitTime.startTimeMonitor(2); // let the inverter first get back to rx mode? } } From bcc52c793c6c9e582dbadd725cfbda36bbcc8130 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 1 Apr 2024 14:54:08 +0200 Subject: [PATCH 063/201] 0.8.102 - 2024-04-01 * fix NTP for `opendtufusion` #1542 * fix scan WiFi in AP mode --- scripts/htmlPreprocessorDefines.py | 2 +- src/CHANGES.md | 4 ++++ src/app.cpp | 2 +- src/app.h | 8 -------- src/appInterface.h | 2 -- src/defines.h | 2 +- src/network/AhoyNetwork.h | 16 ++++++++-------- src/network/AhoyWifiAp.h | 7 +++++++ src/network/AhoyWifiEsp32.h | 6 +----- src/network/AhoyWifiEsp8266.h | 2 ++ src/utils/improv.h | 8 +++++--- src/web/RestApi.h | 15 +++++---------- src/web/html/wizard.html | 9 +++++---- src/web/web.h | 1 + 14 files changed, 41 insertions(+), 43 deletions(-) diff --git a/scripts/htmlPreprocessorDefines.py b/scripts/htmlPreprocessorDefines.py index f8230a90..f5d7cc31 100644 --- a/scripts/htmlPreprocessorDefines.py +++ b/scripts/htmlPreprocessorDefines.py @@ -35,6 +35,6 @@ def check(inp, lst, pattern): return out def conv(inp, lst): - print(lst) + #print(lst) out = check(inp, lst, r'\/\*(?:IF_|ELS|ENDIF_)([A-Z0-9\-_]+)?\*\/') return check(out, lst, r'\<\!\-\-(?:IF_|ELS|ENDIF_)([A-Z0-9\-_]+)?\-\-\>') diff --git a/src/CHANGES.md b/src/CHANGES.md index f8b8ba84..5cc43614 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.8.102 - 2024-04-01 +* fix NTP for `opendtufusion` #1542 +* fix scan WiFi in AP mode + ## 0.8.101 - 2024-03-28 * updated converter scripts to include all enabled features again (redundant scan of build flags) #1534 diff --git a/src/app.cpp b/src/app.cpp index 506074c5..ae50ba49 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -62,7 +62,6 @@ void app::setup() { #endif // ETHERNET mNetwork->setup(mConfig, &mTimestamp, [this](bool gotIp) { this->onNetwork(gotIp); }, [this](bool gotTime) { this->onNtpUpdate(gotTime); }); mNetwork->begin(); - everySec(std::bind(&AhoyNetwork::tickNetworkLoop, mNetwork), "net"); esp_task_wdt_reset(); @@ -176,6 +175,7 @@ void app::regularTickers(void) { DPRINTLN(DBG_DEBUG, F("regularTickers")); everySec(std::bind(&WebType::tickSecond, &mWeb), "webSc"); everySec([this]() { mProtection->tickSecond(); }, "prot"); + everySec([this]() {mNetwork->tickNetworkLoop(); }, "net"); // Plugins #if defined(PLUGIN_DISPLAY) diff --git a/src/app.h b/src/app.h index 66234a31..300c1c25 100644 --- a/src/app.h +++ b/src/app.h @@ -167,10 +167,6 @@ class app : public IApp, public ah::Scheduler { } #if !defined(ETHERNET) - void scanAvailNetworks() override { - mNetwork->scanAvailNetworks(); - } - bool getAvailNetworks(JsonObject obj) override { return mNetwork->getAvailNetworks(obj); } @@ -179,10 +175,6 @@ class app : public IApp, public ah::Scheduler { mNetwork->begin(); } - /*void setStopApAllowedMode(bool allowed) override { - mWifi.setStopApAllowedMode(allowed); - }*/ - bool getWasInCh12to14(void) const override { #if defined(ESP8266) return mNetwork->getWasInCh12to14(); diff --git a/src/appInterface.h b/src/appInterface.h index b7ee2aaf..49470e02 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -26,10 +26,8 @@ class IApp { virtual const char *getVersionModules() = 0; #if !defined(ETHERNET) - virtual void scanAvailNetworks() = 0; virtual bool getAvailNetworks(JsonObject obj) = 0; virtual void setupStation(void) = 0; - //virtual void setStopApAllowedMode(bool allowed) = 0; virtual bool getWasInCh12to14(void) const = 0; #endif /* defined(ETHERNET) */ virtual String getIp(void) = 0; diff --git a/src/defines.h b/src/defines.h index 3edc6f09..ab7c860b 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 101 +#define VERSION_PATCH 102 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index 9573f48f..c98d9866 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -86,19 +86,20 @@ class AhoyNetwork { } #if !defined(ETHERNET) - void scanAvailNetworks(void) { + bool getAvailNetworks(JsonObject obj) { + JsonArray nets = obj.createNestedArray(F("networks")); + if(!mScanActive) { mScanActive = true; - WiFi.scanNetworks(true); + WiFi.disconnect(); + WiFi.scanNetworks(true, true); + return false; } - } - - bool getAvailNetworks(JsonObject obj) { - JsonArray nets = obj.createNestedArray(F("networks")); int n = WiFi.scanComplete(); - if (n < 0) + if (WIFI_SCAN_RUNNING == n) return false; + if(n > 0) { int sort[n]; sortRSSI(&sort[0], n); @@ -174,7 +175,6 @@ class AhoyNetwork { private: void sendNTPpacket(void) { - //DPRINTLN(DBG_VERBOSE, F("wifi::sendNTPpacket")); uint8_t buf[NTP_PACKET_SIZE]; memset(buf, 0, NTP_PACKET_SIZE); diff --git a/src/network/AhoyWifiAp.h b/src/network/AhoyWifiAp.h index 3c75dc12..56ff63d7 100644 --- a/src/network/AhoyWifiAp.h +++ b/src/network/AhoyWifiAp.h @@ -22,6 +22,12 @@ class AhoyWifiAp { void tickLoop() { if(mEnabled) mDns.processNextRequest(); + + if (WiFi.softAPgetStationNum() != mLast) { + mLast = WiFi.softAPgetStationNum(); + if(mLast > 0) + DBGPRINTLN(F("AP client connected")); + } } void enable() { @@ -68,6 +74,7 @@ class AhoyWifiAp { DNSServer mDns; IPAddress mIp; bool mEnabled = false; + uint8_t mLast = 0; }; #endif /*__AHOY_WIFI_AP_H__*/ diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index 255f2b03..58f5dc5d 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -28,7 +28,7 @@ class AhoyWifi : public AhoyNetwork { WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL); WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, WIFI_ALL_CHANNEL_SCAN); - DBGPRINT(F("connect to network '")); Serial.flush(); + DBGPRINT(F("connect to network '")); DBGPRINT(mConfig->sys.stationSsid); #endif } @@ -44,10 +44,6 @@ class AhoyWifi : public AhoyNetwork { mOnNetworkCB(false); mAp.enable(); } - - if (WiFi.softAPgetStationNum() > 0) { - DBGPRINTLN(F("AP client connected")); - } break; case NetworkState::CONNECTED: diff --git a/src/network/AhoyWifiEsp8266.h b/src/network/AhoyWifiEsp8266.h index b9417556..93597f72 100644 --- a/src/network/AhoyWifiEsp8266.h +++ b/src/network/AhoyWifiEsp8266.h @@ -96,6 +96,8 @@ class AhoyWifi : public AhoyNetwork { mOnNetworkCB(true); } + MDNS.update(); + if(WiFi.channel() > 11) mWasInCh12to14 = true; break; diff --git a/src/utils/improv.h b/src/utils/improv.h index 20b2bcad..d2ccc0c3 100644 --- a/src/utils/improv.h +++ b/src/utils/improv.h @@ -147,10 +147,12 @@ class Improv { } void getNetworks(void) { - if(!mScanRunning) - mApp->scanAvailNetworks(); - JsonObject obj; + if(!mScanRunning) { + mApp->getAvailNetworks(obj); + return; + } + if(!mApp->getAvailNetworks(obj)) return; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 8087883e..0f256f25 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -100,7 +100,7 @@ class RestApi { else if(path == "setup") getSetup(request, root); #if !defined(ETHERNET) else if(path == "setup/networks") getNetworks(root); - else if(path == "setup/getip") getWifiIp(root); + else if(path == "setup/getip") getIp(root); #endif /* !defined(ETHERNET) */ else if(path == "live") getLive(request,root); else if (path == "powerHistory") getPowerHistory(request, root); @@ -891,12 +891,13 @@ class RestApi { #if !defined(ETHERNET) void getNetworks(JsonObject obj) { - mApp->getAvailNetworks(obj); + obj[F("success")] = mApp->getAvailNetworks(obj); } - void getWifiIp(JsonObject obj) { + #endif /* !defined(ETHERNET) */ + + void getIp(JsonObject obj) { obj[F("ip")] = mApp->getIp(); } - #endif /* !defined(ETHERNET) */ void getLive(AsyncWebServerRequest *request, JsonObject obj) { getGeneric(request, obj.createNestedObject(F("generic"))); @@ -1031,11 +1032,6 @@ class RestApi { if(isProtected(jsonIn, jsonOut, clientIP)) return false; - #if !defined(ETHERNET) - if(F("scan_wifi") == jsonIn[F("cmd")]) - mApp->scanAvailNetworks(); - else - #endif /* !defined(ETHERNET) */ if(F("set_time") == jsonIn[F("cmd")]) mApp->setTimestamp(jsonIn[F("val")]); else if(F("sync_ntp") == jsonIn[F("cmd")]) @@ -1049,7 +1045,6 @@ class RestApi { snprintf(mConfig->sys.stationSsid, SSID_LEN, "%s", jsonIn[F("ssid")].as()); snprintf(mConfig->sys.stationPwd, PWD_LEN, "%s", jsonIn[F("pwd")].as()); mApp->saveSettings(false); // without reboot - //mApp->setStopApAllowedMode(false); mApp->setupStation(); } #else diff --git a/src/web/html/wizard.html b/src/web/html/wizard.html index 179adb5a..d57562d1 100644 --- a/src/web/html/wizard.html +++ b/src/web/html/wizard.html @@ -231,7 +231,7 @@ ml("div", {class: "row my-4"}, ml("div", {class: "col a-r"}, ml("input", {type: "button", class:"btn hide", id: "btn", value: "{#BTN_FINISH}", onclick: () => {redirect()}}, null))), ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {href: "http://192.168.4.1/"}, "{#STOP_WIZARD}"))) ) - v = setInterval(() => {getAjax('/api/setup/getip', printIp)}, 2500); + v = setInterval(() => {getAjax('/api/setup/getip', printIp)}, 1000); } function redirect() { @@ -270,6 +270,9 @@ getAjax("/api/setup", ((o) => c.append(step1(o.eth)))); /*ELSE*/ function nets(obj) { + if(!obj.success) + return; + var e = document.getElementById("net"); if(obj.networks.length > 0) { var a = [] @@ -280,12 +283,10 @@ } e.replaceChildren(...a) } - getAjax("/api/setup", ((o) => {}), "POST", JSON.stringify({cmd: "scan_wifi"})); } - getAjax("/api/setup", ((o) => {}), "POST", JSON.stringify({cmd: "scan_wifi"})); c.append(step1()) - v = setInterval(() => {getAjax('/api/setup/networks', nets)}, 2500); + v = setInterval(() => {getAjax('/api/setup/networks', nets)}, 1000); /*ENDIF_ETHERNET*/ diff --git a/src/web/web.h b/src/web/web.h index 419d6826..56ff577e 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -402,6 +402,7 @@ class Web { void showNotFound(AsyncWebServerRequest *request) { checkProtection(request); + //DBGPRINTLN(request->url()); request->redirect("/wizard"); } From 42ee440e114fa54e6679e6edbe42213ccccce6fa Mon Sep 17 00:00:00 2001 From: geronet1 Date: Mon, 1 Apr 2024 15:55:09 +0200 Subject: [PATCH 064/201] MaxTemp Berechnung und Anzeige --- src/hm/hmDefines.h | 17 ++++++++++------- src/hm/hmInverter.h | 29 ++++++++++++++++++++++++++++- src/hms/hmsDefines.h | 12 ++++++++---- src/web/RestApi.h | 5 +++-- src/web/html/visualization.html | 4 +++- 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index 6ba92774..c6ca7066 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -24,20 +24,20 @@ enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT, FLD_IRR, FLD_Q, FLD_EVT, FLD_FW_VERSION, FLD_FW_BUILD_YEAR, FLD_FW_BUILD_MONTH_DAY, FLD_FW_BUILD_HOUR_MINUTE, FLD_BOOTLOADER_VER, FLD_ACT_ACTIVE_PWR_LIMIT, FLD_PART_NUM, FLD_HW_VERSION, FLD_GRID_PROFILE_CODE, - FLD_GRID_PROFILE_VERSION, /*FLD_ACT_REACTIVE_PWR_LIMIT, FLD_ACT_PF,*/ FLD_LAST_ALARM_CODE, FLD_MP}; + FLD_GRID_PROFILE_VERSION, /*FLD_ACT_REACTIVE_PWR_LIMIT, FLD_ACT_PF,*/ FLD_LAST_ALARM_CODE, FLD_MP, FLD_MT}; const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal", "U_AC", "U_AC_1N", "U_AC_2N", "U_AC_3N", "UAC_12", "UAC_23", "UAC_31", "I_AC", "IAC_1", "I_AC_2", "I_AC_3", "P_AC", "F_AC", "Temp", "PF_AC", "Efficiency", "Irradiation","Q_AC", "ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","FWBuildHourMinute","BootloaderVersion", "active_PowerLimit", "HWPartNumber", "HWVersion", "GridProfileCode", - "GridProfileVersion", /*"reactivePowerLimit","Powerfactor",*/ "LastAlarmCode", "MaxPower"}; + "GridProfileVersion", /*"reactivePowerLimit","Powerfactor",*/ "LastAlarmCode", "MaxPower", "MaxTemp"}; const char* const notAvail = "n/a"; const uint8_t fieldUnits[] = {UNIT_V, UNIT_A, UNIT_W, UNIT_WH, UNIT_KWH, UNIT_KWH, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_A, UNIT_A, UNIT_A, UNIT_A, UNIT_W, UNIT_HZ, UNIT_C, UNIT_NONE, UNIT_PCT, UNIT_PCT, UNIT_VAR, - UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_PCT, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_W}; + UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_PCT, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_W, UNIT_C}; // mqtt discovery device classes enum {DEVICE_CLS_NONE = 0, DEVICE_CLS_CURRENT, DEVICE_CLS_ENERGY, DEVICE_CLS_PWR, DEVICE_CLS_VOLTAGE, DEVICE_CLS_FREQ, DEVICE_CLS_TEMP}; @@ -68,7 +68,7 @@ const byteAssign_fieldDeviceClass deviceFieldAssignment[] = { #define DEVICE_CLS_ASSIGN_LIST_LEN (sizeof(deviceFieldAssignment) / sizeof(byteAssign_fieldDeviceClass)) // indices to calculation functions, defined in hmInverter.h -enum {CALC_YT_CH0 = 0, CALC_YD_CH0, CALC_UDC_CH, CALC_PDC_CH0, CALC_EFF_CH0, CALC_IRR_CH, CALC_MPAC_CH0, CALC_MPDC_CH}; +enum {CALC_YT_CH0 = 0, CALC_YD_CH0, CALC_UDC_CH, CALC_PDC_CH0, CALC_EFF_CH0, CALC_IRR_CH, CALC_MPAC_CH0, CALC_MPDC_CH, CALC_MT_CH0}; enum {CMD_CALC = 0xffff}; @@ -173,7 +173,8 @@ const byteAssign_t hm1chAssignment[] = { { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }, - { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC } + { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }, + { FLD_MT, UNIT_C, CH0, CALC_MT_CH0, 0, CMD_CALC } }; #define HM1CH_LIST_LEN (sizeof(hm1chAssignment) / sizeof(byteAssign_t)) #define HM1CH_PAYLOAD_LEN 30 @@ -211,7 +212,8 @@ const byteAssign_t hm2chAssignment[] = { { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }, - { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC } + { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }, + { FLD_MT, UNIT_C, CH0, CALC_MT_CH0, 0, CMD_CALC } }; #define HM2CH_LIST_LEN (sizeof(hm2chAssignment) / sizeof(byteAssign_t)) @@ -266,7 +268,8 @@ const byteAssign_t hm4chAssignment[] = { { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }, - { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC } + { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }, + { FLD_MT, UNIT_C, CH0, CALC_MT_CH0, 0, CMD_CALC } }; #define HM4CH_LIST_LEN (sizeof(hm4chAssignment) / sizeof(byteAssign_t)) #define HM4CH_PAYLOAD_LEN 62 diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 1d7e6620..6754fd45 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -53,6 +53,9 @@ static T calcIrradiation(Inverter<> *iv, uint8_t arg0); template static T calcMaxPowerAcCh0(Inverter<> *iv, uint8_t arg0); +template +static T calcMaxTempCh0(Inverter<> *iv, uint8_t arg0); + template static T calcMaxPowerDc(Inverter<> *iv, uint8_t arg0); @@ -107,7 +110,8 @@ const calcFunc_t calcFunctions[] = { { CALC_EFF_CH0, &calcEffiencyCh0 }, { CALC_IRR_CH, &calcIrradiation }, { CALC_MPAC_CH0, &calcMaxPowerAcCh0 }, - { CALC_MPDC_CH, &calcMaxPowerDc } + { CALC_MPDC_CH, &calcMaxPowerDc }, + { CALC_MT_CH0, &calcMaxTempCh0 } }; template @@ -147,6 +151,7 @@ class Inverter { HeuristicInv heuristics; // heuristic information / logic uint8_t curCmtFreq = 0; // current used CMT frequency, used to check if freq. was changed during runtime uint32_t tsMaxAcPower = 0; // holds the timestamp when the MaxAC power was seen + uint32_t tsMaxTemp = 0; // holds the timestamp when the max temp was seen bool commEnabled = true; // 'pause night communication' sets this field to false public: @@ -951,6 +956,28 @@ static T calcMaxPowerAcCh0(Inverter<> *iv, uint8_t arg0) { return acMaxPower; } +template +static T calcMaxTempCh0(Inverter<> *iv, uint8_t arg0) { + DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcMaxTempCh0")); + T maxTemp = 0.0; + if(NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + T Temp = iv->getChannelFieldValue(arg0, FLD_T, rec); + + for(uint8_t i = 0; i < rec->length; i++) { + if((FLD_MT == rec->assign[i].fieldId) && (0 == rec->assign[i].ch)) { + maxTemp = iv->getValue(i, rec); + } + } + if(Temp > maxTemp) { + iv->tsMaxTemp = *iv->timestamp; + return Temp; + } + } + return maxTemp; +} + + template static T calcMaxPowerDc(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcMaxPowerDc")); diff --git a/src/hms/hmsDefines.h b/src/hms/hmsDefines.h index 61275dc1..c71aa796 100644 --- a/src/hms/hmsDefines.h +++ b/src/hms/hmsDefines.h @@ -33,7 +33,8 @@ const byteAssign_t hms1chAssignment[] = { { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }, - { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC } + { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }, + { FLD_MT, UNIT_C, CH0, CALC_MT_CH0, 0, CMD_CALC } }; #define HMS1CH_LIST_LEN (sizeof(hms1chAssignment) / sizeof(byteAssign_t)) #define HMS1CH_PAYLOAD_LEN 30 @@ -70,7 +71,8 @@ const byteAssign_t hms2chAssignment[] = { { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }, - { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC } + { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }, + { FLD_MT, UNIT_C, CH0, CALC_MT_CH0, 0, CMD_CALC } }; #define HMS2CH_LIST_LEN (sizeof(hms2chAssignment) / sizeof(byteAssign_t)) #define HMS2CH_PAYLOAD_LEN 42 @@ -123,7 +125,8 @@ const byteAssign_t hms4chAssignment[] = { { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }, - { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC } + { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }, + { FLD_MT, UNIT_C, CH0, CALC_MT_CH0, 0, CMD_CALC } }; #define HMS4CH_LIST_LEN (sizeof(hms4chAssignment) / sizeof(byteAssign_t)) #define HMS4CH_PAYLOAD_LEN 66 @@ -199,7 +202,8 @@ const byteAssign_t hmt6chAssignment[] = { { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }, - { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC } + { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }, + { FLD_MT, UNIT_C, CH0, CALC_MT_CH0, 0, CMD_CALC } }; #define HMT6CH_LIST_LEN (sizeof(hmt6chAssignment) / sizeof(byteAssign_t)) #define HMT6CH_PAYLOAD_LEN 98 diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 31104af0..3a578add 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -602,6 +602,7 @@ class RestApi { obj[F("alarm_cnt")] = iv->alarmCnt; obj[F("rssi")] = iv->rssi; obj[F("ts_max_ac_pwr")] = iv->tsMaxAcPower; + obj[F("ts_max_temp")] = iv->tsMaxTemp; JsonArray ch = obj.createNestedArray("ch"); @@ -1110,9 +1111,9 @@ class RestApi { private: constexpr static uint8_t acList[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PF, FLD_T, FLD_YT, - FLD_YD, FLD_PDC, FLD_EFF, FLD_Q, FLD_MP}; + FLD_YD, FLD_PDC, FLD_EFF, FLD_Q, FLD_MP, FLD_MT}; constexpr static uint8_t acListHmt[] = {FLD_UAC_1N, FLD_IAC_1, FLD_PAC, FLD_F, FLD_PF, FLD_T, - FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_Q, FLD_MP}; + FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_Q, FLD_MP, FLD_MT}; constexpr static uint8_t dcList[] = {FLD_UDC, FLD_IDC, FLD_PDC, FLD_YD, FLD_YT, FLD_IRR, FLD_MP}; private: diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html index cfc84e72..6c3bb67f 100644 --- a/src/web/html/visualization.html +++ b/src/web/html/visualization.html @@ -120,6 +120,7 @@ } var maxAcPwr = toIsoDateStr(new Date(obj.ts_max_ac_pwr * 1000)); + var maxTemp = toIsoDateStr(new Date(obj.ts_max_temp * 1000)); return ml("div", {class: "row mt-2"}, ml("div", {class: "col"}, [ ml("div", {class: "p-2 " + clh}, @@ -134,7 +135,8 @@ ml("div", {class: "col a-c"}, ml("span", { class: "pointer", onclick: function() { getAjax("/api/inverter/alarm/" + obj.id, parseIvAlarm); }}, ("{#ALARMS}: " + obj.alarm_cnt))), - ml("div", {class: "col a-r mx-2 mx-md-1"}, String(obj.ch[0][5].toFixed(1)) + t.innerText) + ml("div", {class: "col a-r mx-2 mx-md-1 tooltip", data: maxTemp}, String(obj.ch[0][5].toFixed(1)) + t.innerText + "
" + + "Max:" + String(obj.ch[0][12].toFixed(1)) + t.innerText) ]) ), ml("div", {class: "p-2 " + clbg}, [ From 1033ddc11aa06a288f87095ed9166c6bebb15ccf Mon Sep 17 00:00:00 2001 From: Sebastian Rothe Date: Mon, 1 Apr 2024 16:48:38 +0200 Subject: [PATCH 065/201] Fix typos and spelling --- .github/ISSUE_TEMPLATE/report.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/report.yaml b/.github/ISSUE_TEMPLATE/report.yaml index 9a2824c4..19b71de2 100644 --- a/.github/ISSUE_TEMPLATE/report.yaml +++ b/.github/ISSUE_TEMPLATE/report.yaml @@ -12,7 +12,7 @@ body: Wir lesen auch gerne Deutsch, bitte fülle die u.a. Fragen aus damit wir Dir bestmöglich helfen können Danke! Bitte unser FAQ als Hilfestellung prüfen: https://ahoydtu.de/faq - Please read, copy & fill in the template from our Posting Guide lines into your Support Forum post. + Please read, then copy & fill in the template from our Posting Guide lines into your Support Forum post. We do enjoy the english language, but we need a couple of things to best support you in your goal, please fill in all / most of the details given below. Thanks! Check our FAQ: https://ahoydtu.de/faq - type: markdown @@ -35,7 +35,7 @@ body: label: Assembly description: options: - - I did the assebly by myself + - I did the assembly by myself - the DTU was already assembled validations: required: true @@ -84,7 +84,7 @@ body: label: Connection picture description: options: - - label: I will attach/upload an Image of my wiring + - label: I will attach/upload an image of my wiring validations: required: true - type: markdown From 4d5ae72cb6d1050ac81ed4f21e9b62328561527d Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 1 Apr 2024 17:02:43 +0200 Subject: [PATCH 066/201] 0.8.102 * fix MDNS #1538 * improved Wizard * improved MqTT on devcontrol e.g. set power limit --- .gitignore | 1 + src/.gitignore | 2 ++ src/CHANGES.md | 3 ++ src/app.cpp | 55 ++++++++++++++++++++--------------- src/app.h | 11 +++++-- src/appInterface.h | 3 +- src/network/AhoyNetwork.h | 7 ++++- src/network/AhoyWifiAp.h | 3 ++ src/network/AhoyWifiEsp32.h | 6 +++- src/network/AhoyWifiEsp8266.h | 4 +++ src/web/RestApi.h | 2 +- src/web/html/setup.html | 28 +----------------- src/web/html/wizard.html | 9 +++--- src/web/lang.json | 20 ++++--------- src/web/web.h | 9 ++++-- 15 files changed, 86 insertions(+), 77 deletions(-) diff --git a/.gitignore b/.gitignore index 21ae2a57..b5c699cc 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ src/web/html/tmp/* src/output.map /.venv +/scripts/__pycache__/htmlPreprocessorDefines.cpython-311.pyc diff --git a/src/.gitignore b/src/.gitignore index 89cc49cb..30f1d1ca 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -3,3 +3,5 @@ .vscode/c_cpp_properties.json .vscode/launch.json .vscode/ipch +scripts/__pycache__/* +*.pyc diff --git a/src/CHANGES.md b/src/CHANGES.md index 5cc43614..1ba9edd1 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -3,6 +3,9 @@ ## 0.8.102 - 2024-04-01 * fix NTP for `opendtufusion` #1542 * fix scan WiFi in AP mode +* fix MDNS #1538 +* improved Wizard +* improved MqTT on devcontrol e.g. set power limit ## 0.8.101 - 2024-03-28 * updated converter scripts to include all enabled features again (redundant scan of build flags) #1534 diff --git a/src/app.cpp b/src/app.cpp index ae50ba49..5166c035 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -403,29 +403,7 @@ void app::tickSend(void) { for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { Inverter<> *iv = mSys.getInverterByPos(i); - if(NULL == iv) - continue; - - if(iv->config->enabled) { - if(!iv->commEnabled) { - DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINTLN(F("no communication to the inverter (night time)")); - continue; - } - - if(!iv->radio->isChipConnected()) - continue; - - if(InverterStatus::OFF != iv->status) - notAvail = false; - - iv->tickSend([this, iv](uint8_t cmd, bool isDevControl) { - if(isDevControl) - mCommunication.addImportant(iv, cmd); - else - mCommunication.add(iv, cmd); - }); - } + sendIv(iv); } if(mAllIvNotAvail != notAvail) @@ -435,6 +413,37 @@ void app::tickSend(void) { updateLed(); } +//----------------------------------------------------------------------------- +bool app::sendIv(Inverter<> *iv) { + bool notAvail = true; + if(NULL == iv) + return notAvail; + + if(!iv->config->enabled) + return notAvail; + + if(!iv->commEnabled) { + DPRINT_IVID(DBG_INFO, iv->id); + DBGPRINTLN(F("no communication to the inverter (night time)")); + return notAvail; + } + + if(!iv->radio->isChipConnected()) + return notAvail; + + if(InverterStatus::OFF != iv->status) + notAvail = false; + + iv->tickSend([this, iv](uint8_t cmd, bool isDevControl) { + if(isDevControl) + mCommunication.addImportant(iv, cmd); + else + mCommunication.add(iv, cmd); + }); + + return notAvail; +} + //----------------------------------------------------------------------------- void app:: zeroIvValues(bool checkAvail, bool skipYieldDay) { Inverter<> *iv; diff --git a/src/app.h b/src/app.h index 300c1c25..8fe9420d 100644 --- a/src/app.h +++ b/src/app.h @@ -188,6 +188,10 @@ class app : public IApp, public ah::Scheduler { return mNetwork->getIp(); } + bool isApActive(void) override { + return mNetwork->isApActive(); + } + void setRebootFlag() override { once(std::bind(&app::tickReboot, this), 3, "rboot"); } @@ -386,8 +390,10 @@ class app : public IApp, public ah::Scheduler { bool mNtpReceived = false; void updateNtp(void); - void triggerTickSend() override { - once(std::bind(&app::tickSend, this), 0, "tSend"); + void triggerTickSend(uint8_t id) override { + once([this, id]() { + sendIv(mSys.getInverterByPos(id)); + }, 0, "devct"); } void tickCalcSunrise(void); @@ -396,6 +402,7 @@ class app : public IApp, public ah::Scheduler { void tickSunrise(void); void tickComm(void); void tickSend(void); + bool sendIv(Inverter<> *iv); void tickMinute(void); void tickZeroValues(void); void tickMidnight(void); diff --git a/src/appInterface.h b/src/appInterface.h index 49470e02..a1f5cd0e 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -31,6 +31,7 @@ class IApp { virtual bool getWasInCh12to14(void) const = 0; #endif /* defined(ETHERNET) */ virtual String getIp(void) = 0; + virtual bool isApActive(void) = 0; virtual uint32_t getUptime() = 0; virtual uint32_t getTimestamp() = 0; @@ -42,7 +43,7 @@ class IApp { virtual void getSchedulerInfo(uint8_t *max) = 0; virtual void getSchedulerNames() = 0; - virtual void triggerTickSend() = 0; + virtual void triggerTickSend(uint8_t id) = 0; virtual bool getRebootRequestState() = 0; virtual bool getSettingsValid() = 0; diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index c98d9866..55c5d193 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -85,13 +85,18 @@ class AhoyNetwork { return false; } + bool isApActive() { + return mAp.isEnabled(); + } + #if !defined(ETHERNET) bool getAvailNetworks(JsonObject obj) { JsonArray nets = obj.createNestedArray(F("networks")); if(!mScanActive) { mScanActive = true; - WiFi.disconnect(); + if(NetworkState::GOT_IP != mStatus) + WiFi.disconnect(); WiFi.scanNetworks(true, true); return false; } diff --git a/src/network/AhoyWifiAp.h b/src/network/AhoyWifiAp.h index 56ff63d7..ce2bbd1b 100644 --- a/src/network/AhoyWifiAp.h +++ b/src/network/AhoyWifiAp.h @@ -54,6 +54,9 @@ class AhoyWifiAp { if(!mEnabled) return; + if(WiFi.softAPgetStationNum() > 0) + return; + mDns.stop(); WiFi.softAPdisconnect(); #if defined(ETHERNET) diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index 58f5dc5d..41956dfc 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -43,6 +43,7 @@ class AhoyWifi : public AhoyNetwork { mConnected = false; mOnNetworkCB(false); mAp.enable(); + MDNS.end(); } break; @@ -50,11 +51,14 @@ class AhoyWifi : public AhoyNetwork { break; case NetworkState::GOT_IP: - if(!mConnected) { + if(mAp.isEnabled()) mAp.disable(); + + if(!mConnected) { mConnected = true; ah::welcome(WiFi.localIP().toString(), F("Station")); MDNS.begin(mConfig->sys.deviceName); + MDNS.addServiceTxt("http", "tcp", "path", "/"); mOnNetworkCB(true); } break; diff --git a/src/network/AhoyWifiEsp8266.h b/src/network/AhoyWifiEsp8266.h index 93597f72..2497448b 100644 --- a/src/network/AhoyWifiEsp8266.h +++ b/src/network/AhoyWifiEsp8266.h @@ -39,6 +39,7 @@ class AhoyWifi : public AhoyNetwork { mConnected = false; mOnNetworkCB(false); mAp.enable(); + MDNS.end(); } if (WiFi.softAPgetStationNum() > 0) { @@ -93,6 +94,9 @@ class AhoyWifi : public AhoyNetwork { mConnected = true; ah::welcome(WiFi.localIP().toString(), F("Station")); MDNS.begin(mConfig->sys.deviceName); + MDNSResponder::hMDNSService hRes = MDNS.addService(NULL, "http", "tcp", 80); + MDNS.addServiceTxt(hRes, "path", "/"); + MDNS.announce(); mOnNetworkCB(true); } diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 0f256f25..a9756944 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -1011,7 +1011,7 @@ class RestApi { accepted = iv->setDevControlRequest(ActivePowerContr); if(accepted) - mApp->triggerTickSend(); + mApp->triggerTickSend(iv->id); } else if(F("dev") == jsonIn[F("cmd")]) { DPRINTLN(DBG_INFO, F("dev cmd")); iv->setDevCommand(jsonIn[F("val")].as()); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index fb1eff97..51d48f7c 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -57,22 +57,9 @@
{#AP_PWD}
-
-
{#SEARCH_NETWORKS}
-
-
- -
-
{#AVAIL_NETWORKS}
-
- -
-
SSID
-
+
{#SSID_HIDDEN}
@@ -606,12 +593,6 @@ setTimeout(function() {getAjax('/api/index', apiCbNtp2)}, 2000) } - function scan() { - var obj = {cmd: "scan_wifi", token: "*"} - getAjax("/api/setup", apiCbWifi, "POST", JSON.stringify(obj)); - setTimeout(function() {getAjax('/api/setup/networks', listNetworks)}, 5000); - } - function syncTime() { var obj = {cmd: "sync_ntp", token: "*"} getAjax("/api/setup", apiCbNtp, "POST", JSON.stringify(obj)) @@ -1319,13 +1300,6 @@ s.appendChild(opt("-1", "{#NO_NETWORK_FOUND}")); } - function selNet() { - var s = document.getElementById("networks"); - var e = document.getElementsByName("ssid")[0]; - if(-1 != s.value) - e.value = s.value; - } - getAjax("/api/setup", parse); diff --git a/src/web/html/wizard.html b/src/web/html/wizard.html index d57562d1..1fc8503c 100644 --- a/src/web/html/wizard.html +++ b/src/web/html/wizard.html @@ -218,7 +218,7 @@ sect("{#WIFI_MANUAL}", ml("input", {id: "man", type: "text"})), sect("{#WIFI_PASSWORD}", ml("input", {id: "pwd", type: "password"})), ml("div", {class: "row my-4"}, ml("div", {class: "col a-r"}, ml("input", {type: "button", class:"btn", value: "{#BTN_NEXT}", onclick: () => {saveWifi()}}, null))), - ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {href: "http://192.168.4.1/"}, "{#STOP_WIZARD}"))) + ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {href: "http://192.168.4.1/index"}, "{#STOP_WIZARD}"))) ]) } /*ENDIF_ETHERNET*/ @@ -229,9 +229,9 @@ ml("div", {class: "row"}, ml("div", {class: "col"}, ml("span", {class: "fs-5"}, "{#TEST_CONNECTION}"))), sect("{#TRY_TO_CONNECT}", ml("span", {id: "state"}, "{#CONNECTING}")), ml("div", {class: "row my-4"}, ml("div", {class: "col a-r"}, ml("input", {type: "button", class:"btn hide", id: "btn", value: "{#BTN_FINISH}", onclick: () => {redirect()}}, null))), - ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {href: "http://192.168.4.1/"}, "{#STOP_WIZARD}"))) + ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {href: "http://192.168.4.1/index"}, "{#STOP_WIZARD}"))) ) - v = setInterval(() => {getAjax('/api/setup/getip', printIp)}, 1000); + v = setInterval(() => {getAjax('/api/setup/getip', printIp)}, 300); } function redirect() { @@ -286,7 +286,8 @@ } c.append(step1()) - v = setInterval(() => {getAjax('/api/setup/networks', nets)}, 1000); + getAjax('/api/setup/networks', nets) + v = setInterval(() => {getAjax('/api/setup/networks', nets)}, 1000) /*ENDIF_ETHERNET*/ diff --git a/src/web/lang.json b/src/web/lang.json index ee942608..57ded1dd 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -81,7 +81,7 @@ { "token": "BTN_NEXT", "en": "next >>", - "de": "prüfen >>" + "de": "prüfen >>" }, { "token": "BTN_REBOOT", @@ -91,7 +91,7 @@ { "token": "TEST_CONNECTION", "en": "Test Connection", - "de": "Verbindung wird überprüft" + "de": "Verbindung wird überprüft" }, { "token": "TRY_TO_CONNECT", @@ -259,19 +259,9 @@ "de": "Netzwerke suchen" }, { - "token": "BTN_SCAN", - "en": "scan", - "de": "Suche starten" - }, - { - "token": "AVAIL_NETWORKS", - "en": "Avail Networks", - "de": "Verfügbare Netzwerke" - }, - { - "token": "NETWORK_NOT_SCANNED", - "en": "not scanned", - "de": "nicht gesucht" + "token": "SCAN_WIFI", + "en": "scan for WiFi networks", + "de": "nach WiFi Netzwerken suchen" }, { "token": "SSID_HIDDEN", diff --git a/src/web/web.h b/src/web/web.h index 56ff577e..4f93b905 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -57,7 +57,8 @@ class Web { mConfig = config; DPRINTLN(DBG_VERBOSE, F("app::setup-on")); - mWeb.on("/", HTTP_GET, std::bind(&Web::onIndex, this, std::placeholders::_1)); + mWeb.on("/", HTTP_GET, std::bind(&Web::onIndex, this, std::placeholders::_1, true)); + mWeb.on("/index", HTTP_GET, std::bind(&Web::onIndex, this, std::placeholders::_1, false)); mWeb.on("/login", HTTP_ANY, std::bind(&Web::onLogin, this, std::placeholders::_1)); mWeb.on("/logout", HTTP_GET, std::bind(&Web::onLogout, this, std::placeholders::_1)); mWeb.on("/colors.css", HTTP_GET, std::bind(&Web::onColor, this, std::placeholders::_1)); @@ -319,7 +320,11 @@ class Web { client->send("hello!", NULL, millis(), 1000); } - void onIndex(AsyncWebServerRequest *request) { + void onIndex(AsyncWebServerRequest *request, bool checkAp = true) { + if(mApp->isApActive() && checkAp) { + onWizard(request); + return; + } getPage(request, PROT_MASK_INDEX, index_html, index_html_len); } From 1e6f7c1247ddfbb51a78df92c07ad5d30e41c7b4 Mon Sep 17 00:00:00 2001 From: Sebastian Rothe Date: Mon, 1 Apr 2024 18:45:16 +0200 Subject: [PATCH 067/201] fix: get refresh property from object --- src/web/html/history.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/web/html/history.html b/src/web/html/history.html index 7ec9be7e..d21e6b96 100644 --- a/src/web/html/history.html +++ b/src/web/html/history.html @@ -150,11 +150,11 @@ parseRssi(obj.generic) window.setInterval("getAjax('/api/powerHistory', parsePowerHistory)", obj.refresh * 1000) setTimeout(() => { - window.setInterval("getAjax('/api/powerHistoryDay', parsePowerHistoryDay)", refresh * 1000) + window.setInterval("getAjax('/api/powerHistoryDay', parsePowerHistoryDay)", obj.refresh * 1000) }, 200) /*IF_ENABLE_HISTORY_YIELD_PER_DAY*/ setTimeout(() => { - window.setInterval("getAjax('/api/yieldDayHistory', parseYieldDayHistory)", refresh * 1000) + window.setInterval("getAjax('/api/yieldDayHistory', parseYieldDayHistory)", obj.refresh * 1000) }, 400) /*ENDIF_ENABLE_HISTORY_YIELD_PER_DAY*/ } From 1887d6cea5cc79b0d51ef767e880d6261e6aa700 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 2 Apr 2024 11:55:57 +0200 Subject: [PATCH 068/201] 0.8.103 * merge PR: fix: get refresh property from object #1552 * merge PR: fix typos and spelling in Github Issue template #1550 * merge PR: shorten last cmt waiting time #1549 --- src/CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CHANGES.md b/src/CHANGES.md index 1ba9edd1..3705c785 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.8.103 - 2024-04-02 +* merge PR: fix: get refresh property from object #1552 +* merge PR: fix typos and spelling in Github Issue template #1550 +* merge PR: shorten last cmt waiting time #1549 + ## 0.8.102 - 2024-04-01 * fix NTP for `opendtufusion` #1542 * fix scan WiFi in AP mode From 7ee1f992cb4d3c59a9b7f1fdb5f4d797f4a24085 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 2 Apr 2024 13:09:19 +0200 Subject: [PATCH 069/201] 0.8.103 * fix cppcheck warnings * changed MqTT retained flags of some topics --- src/CHANGES.md | 2 ++ src/app.cpp | 17 +++++++++-------- src/app.h | 2 +- src/defines.h | 2 +- src/network/AhoyWifiEsp32.h | 10 ---------- src/publisher/pubMqtt.h | 4 ++-- src/publisher/pubMqttIvData.h | 2 -- src/web/RestApi.h | 2 +- 8 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 3705c785..73c5c5d4 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -4,6 +4,8 @@ * merge PR: fix: get refresh property from object #1552 * merge PR: fix typos and spelling in Github Issue template #1550 * merge PR: shorten last cmt waiting time #1549 +* fix cppcheck warnings +* changed MqTT retained flags of some topics ## 0.8.102 - 2024-04-01 * fix NTP for `opendtufusion` #1542 diff --git a/src/app.cpp b/src/app.cpp index 5166c035..f22e6906 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -56,9 +56,9 @@ void app::setup() { #ifdef ETHERNET delay(1000); - mNetwork = (AhoyNetwork*) new AhoyEthernet(); + mNetwork = static_cast(new AhoyEthernet()); #else - mNetwork = (AhoyNetwork*) new AhoyWifi(); + mNetwork = static_cast(new AhoyWifi()); #endif // ETHERNET mNetwork->setup(mConfig, &mTimestamp, [this](bool gotIp) { this->onNetwork(gotIp); }, [this](bool gotTime) { this->onNtpUpdate(gotTime); }); mNetwork->begin(); @@ -403,7 +403,8 @@ void app::tickSend(void) { for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { Inverter<> *iv = mSys.getInverterByPos(i); - sendIv(iv); + if(!sendIv(iv)) + notAvail = false; } if(mAllIvNotAvail != notAvail) @@ -415,22 +416,22 @@ void app::tickSend(void) { //----------------------------------------------------------------------------- bool app::sendIv(Inverter<> *iv) { - bool notAvail = true; if(NULL == iv) - return notAvail; + return true; if(!iv->config->enabled) - return notAvail; + return true; if(!iv->commEnabled) { DPRINT_IVID(DBG_INFO, iv->id); DBGPRINTLN(F("no communication to the inverter (night time)")); - return notAvail; + return true; } if(!iv->radio->isChipConnected()) - return notAvail; + return true; + bool notAvail = true; if(InverterStatus::OFF != iv->status) notAvail = false; diff --git a/src/app.h b/src/app.h index 8fe9420d..2fc37ea8 100644 --- a/src/app.h +++ b/src/app.h @@ -414,7 +414,7 @@ class app : public IApp, public ah::Scheduler { bool mShowRebootRequest = false; - AhoyNetwork *mNetwork; + AhoyNetwork *mNetwork = nullptr; WebType mWeb; RestApiType mApi; Protection *mProtection = nullptr; diff --git a/src/defines.h b/src/defines.h index ab7c860b..502568a8 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 102 +#define VERSION_PATCH 103 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index 41956dfc..a3bbb9cf 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -68,16 +68,6 @@ class AhoyWifi : public AhoyNetwork { String getIp(void) override { return WiFi.localIP().toString(); } - - private: - void 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]); - } }; #endif /*ESP32 & !ETHERNET*/ diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 2d393b8b..35dc2b71 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -251,8 +251,8 @@ class PubMqtt { void onConnect(bool sessionPreset) { DPRINTLN(DBG_INFO, F("MQTT connected")); - publish(subtopics[MQTT_VERSION], mVersion, true); - publish(subtopics[MQTT_DEVICE], mDevName, true); + publish(subtopics[MQTT_VERSION], mVersion, false); + publish(subtopics[MQTT_DEVICE], mDevName, false); publish(subtopics[MQTT_IP_ADDR], mApp->getIp().c_str(), true); tickerMinute(); publish(mLwtTopic.data(), mqttStr[MQTT_STR_LWT_CONN], true, false); diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 6ddd63a9..cd212aa4 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -187,7 +187,6 @@ class PubMqttIvData { static_cast(mIv->getChannelFieldValue(CH0, FLD_FW_BUILD_MONTH_DAY, rec)), static_cast(mIv->getChannelFieldValue(CH0, FLD_FW_BUILD_HOUR_MINUTE, rec)), static_cast(mIv->getChannelFieldValue(CH0, FLD_BOOTLOADER_VER, rec))); - retained = true; } else if(InverterDevInform_Simple == mCmd) { snprintf(mSubTopic.data(), mSubTopic.size(), "%s/hardware", mIv->config->name); snprintf(mVal.data(), mVal.size(), "{\"part\":%d,\"version\":\"%d\",\"grid_profile_code\":%d,\"grid_profile_version\":%d}", @@ -195,7 +194,6 @@ class PubMqttIvData { static_cast(mIv->getChannelFieldValue(CH0, FLD_HW_VERSION, rec)), static_cast(mIv->getChannelFieldValue(CH0, FLD_GRID_PROFILE_CODE, rec)), static_cast(mIv->getChannelFieldValue(CH0, FLD_GRID_PROFILE_VERSION, rec))); - retained = true; } else { snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mIv->getValue(mPos, rec))); diff --git a/src/web/RestApi.h b/src/web/RestApi.h index a9756944..665a3333 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -166,7 +166,7 @@ class RestApi { #else DynamicJsonDocument json(12000); // does this work? I have no ESP32 :-( #endif - DeserializationError err = deserializeJson(json, (const char *)mTmpBuf, mTmpSize); + DeserializationError err = deserializeJson(json, static_cast(mTmpBuf, mTmpSize)); json.shrinkToFit(); JsonObject obj = json.as(); From f105e25d3c040922956921c2750292cac8ce43b4 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 4 Apr 2024 01:47:24 +0200 Subject: [PATCH 070/201] 0.8.104 * fix reboot on inverter save (ESP32) #1559 * fix NRF and Ethernet #1506 --- scripts/applyPatches.py | 2 +- src/CHANGES.md | 4 ++++ src/hm/hmRadio.h | 10 +++++----- src/network/AhoyWifiEsp32.h | 2 +- src/platformio.ini | 35 +++++++++++++++++++---------------- src/web/html/setup.html | 26 ++++++++++++-------------- 6 files changed, 42 insertions(+), 37 deletions(-) diff --git a/scripts/applyPatches.py b/scripts/applyPatches.py index 57f1fa23..91b3498c 100644 --- a/scripts/applyPatches.py +++ b/scripts/applyPatches.py @@ -31,5 +31,5 @@ applyPatch("ESPAsyncWebServer-esphome", "../patches/AsyncWeb_Prometheus.patch") if env['PIOENV'][:13] == "opendtufusion": applyPatch("GxEPD2", "../patches/GxEPD2_SW_SPI.patch") -if (env['PIOENV'][:13] == "opendtufusion"): # or (env['PIOENV'][:13] == "esp32-wroom32"): +if (env['PIOENV'][:13] == "opendtufusion") or (env['PIOENV'][:5] == "esp32"): applyPatch("RF24", "../patches/RF24_Hal.patch") diff --git a/src/CHANGES.md b/src/CHANGES.md index 73c5c5d4..bb9bc7d5 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.8.104 - 2024-04-04 +* fix reboot on inverter save (ESP32) #1559 +* fix NRF and Ethernet #1506 + ## 0.8.103 - 2024-04-02 * merge PR: fix: get refresh property from object #1552 * merge PR: fix typos and spelling in Github Issue template #1550 diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index eb44dd8c..f187d4fa 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -10,7 +10,7 @@ #include "SPI.h" #include "radio.h" #include "../config/config.h" -#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL) +#if defined(SPI_HAL) #include "nrfHal.h" #endif @@ -34,7 +34,7 @@ class HmRadio : public Radio { HmRadio() { mDtuSn = DTU_SN; mIrqRcvd = false; - #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL) + #if defined(SPI_HAL) //mNrf24.reset(new RF24()); #else mNrf24.reset(new RF24(CE_PIN, CS_PIN, SPI_SPEED)); @@ -55,7 +55,7 @@ class HmRadio : public Radio { mDtuRadioId = ((uint64_t)(((mDtuSn >> 24) & 0xFF) | ((mDtuSn >> 8) & 0xFF00) | ((mDtuSn << 8) & 0xFF0000) | ((mDtuSn << 24) & 0xFF000000)) << 8) | 0x01; #ifdef ESP32 - #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL) + #if defined(SPI_HAL) mNrfHal.init(mosi, miso, sclk, cs, ce, SPI_SPEED); mNrf24.reset(new RF24(&mNrfHal)); #else @@ -72,7 +72,7 @@ class HmRadio : public Radio { mSpi->begin(); #endif - #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL) + #if defined(SPI_HAL) mNrf24->begin(); #else mNrf24->begin(mSpi.get(), ce, cs); @@ -432,7 +432,7 @@ class HmRadio : public Radio { std::unique_ptr mSpi; std::unique_ptr mNrf24; - #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL) + #if defined(SPI_HAL) nrfHal mNrfHal; #endif Inverter<> *mLastIv = NULL; diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index a3bbb9cf..6ccb077a 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -58,7 +58,7 @@ class AhoyWifi : public AhoyNetwork { mConnected = true; ah::welcome(WiFi.localIP().toString(), F("Station")); MDNS.begin(mConfig->sys.deviceName); - MDNS.addServiceTxt("http", "tcp", "path", "/"); + //MDNS.addServiceTxt("http", "tcp", "path", "/"); mOnNetworkCB(true); } break; diff --git a/src/platformio.ini b/src/platformio.ini index cde08cb1..a831f7c2 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -148,17 +148,18 @@ monitor_filters = esp8266_exception_decoder [env:esp32-wroom32-minimal] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env.build_flags} - -DUSE_HSPI_FOR_EPD + -DSPI_HAL monitor_filters = esp32_exception_decoder [env:esp32-wroom32] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env:esp32-wroom32-minimal.build_flags} + -DUSE_HSPI_FOR_EPD -DENABLE_MQTT -DPLUGIN_DISPLAY -DENABLE_HISTORY @@ -166,7 +167,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env:esp32-wroom32.build_flags} -DLANG_DE @@ -174,7 +175,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-prometheus] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env:esp32-wroom32.build_flags} -DENABLE_PROMETHEUS_EP @@ -182,7 +183,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-prometheus-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env:esp32-wroom32-prometheus.build_flags} -DLANG_DE @@ -199,7 +200,7 @@ build_flags = ${env:esp32-wroom32.build_flags} -DDEF_ETH_MISO_PIN=12 -DDEF_ETH_MOSI_PIN=13 -DDEF_ETH_IRQ_PIN=4 - -DDEF_ETH_RST_PIN=2 + -DDEF_ETH_RST_PIN=255 -DDEF_NRF_CS_PIN=5 -DDEF_NRF_CE_PIN=17 -DDEF_NRF_IRQ_PIN=16 @@ -218,10 +219,11 @@ monitor_filters = esp32_exception_decoder [env:esp32-s2-mini] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_s2_mini build_flags = ${env.build_flags} -DUSE_HSPI_FOR_EPD + -DSPI_HAL -DENABLE_MQTT -DPLUGIN_DISPLAY -DENABLE_HISTORY @@ -240,7 +242,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-s2-mini-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_s2_mini build_flags = ${env:esp32-s2-mini.build_flags} -DLANG_DE @@ -248,10 +250,11 @@ monitor_filters = esp32_exception_decoder [env:esp32-c3-mini] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_c3_mini build_flags = ${env.build_flags} -DUSE_HSPI_FOR_EPD + -DSPI_HAL -DENABLE_MQTT -DPLUGIN_DISPLAY -DENABLE_HISTORY @@ -270,7 +273,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-c3-mini-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_c3_mini build_flags = ${env:esp32-c3-mini.build_flags} -DLANG_DE @@ -278,7 +281,7 @@ monitor_filters = esp32_exception_decoder [env:opendtufusion-minimal] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env.build_flags} @@ -303,7 +306,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-minimal.build_flags} @@ -314,7 +317,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion.build_flags} @@ -323,7 +326,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-ethernet] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-minimal.build_flags} @@ -342,7 +345,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-ethernet-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-ethernet.build_flags} diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 51d48f7c..122f5427 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -52,14 +52,18 @@
WiFi -
{#AP_PWD}
+ +
SSID
- +
+
+ {#SCAN_WIFI} +
{#SSID_HIDDEN}
@@ -69,6 +73,7 @@
{#PASSWORD}
+
{#STATIC_IP} @@ -652,9 +657,14 @@ } function parseSys(obj) { + /*IF_ETHERNET*/ + for(var i of [["device", "device_name"], ["ap_pwd", "ap_pwd"]]) + document.getElementsByName(i[0])[0].value = obj[i[1]]; + /*ELSE*/ for(var i of [["device", "device_name"], ["ssid", "ssid"], ["ap_pwd", "ap_pwd"]]) document.getElementsByName(i[0])[0].value = obj[i[1]]; document.getElementsByName("hidd")[0].checked = obj["hidd"]; + /*ENDIF_ETHERNET*/ document.getElementsByName("darkMode")[0].checked = obj["dark_mode"]; document.getElementsByName("schedReboot")[0].checked = obj["sched_reboot"]; e = document.getElementsByName("adminpwd")[0]; @@ -1288,18 +1298,6 @@ } } - function listNetworks(root) { - var s = document.getElementById("networks"); - selDelAllOpt(s); - if(root["networks"].length > 0) { - s.appendChild(opt("-1", "{#NETWORK_PLEASE_SELECT}")); - for(i = 0; i < root["networks"].length; i++) { - s.appendChild(opt(root["networks"][i]["ssid"], root["networks"][i]["ssid"] + " (" + root["networks"][i]["rssi"] + " dBm)")); - } - } else - s.appendChild(opt("-1", "{#NO_NETWORK_FOUND}")); - } - getAjax("/api/setup", parse); From 5a3228853664a3697135054a5ac685b246938fef Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 4 Apr 2024 01:49:56 +0200 Subject: [PATCH 071/201] 0.8.104 --- src/defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/defines.h b/src/defines.h index 502568a8..d551ee8a 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 103 +#define VERSION_PATCH 104 //------------------------------------- typedef struct { uint8_t ch; From 29adc76936b12a2250ef3c0443a444a85f8c1195 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 5 Apr 2024 00:34:52 +0200 Subject: [PATCH 072/201] 0.8.105 * cleanup of `defines.h` --- scripts/convertHtml.py | 11 ++++++++ src/CHANGES.md | 3 ++ src/config/settings.h | 15 +++++++++- src/defines.h | 62 +---------------------------------------- src/hm/hmDefines.h | 35 +++++++++++++++++++++++ src/publisher/pubMqtt.h | 4 +++ 6 files changed, 68 insertions(+), 62 deletions(-) diff --git a/scripts/convertHtml.py b/scripts/convertHtml.py index 026c28da..9a83d081 100644 --- a/scripts/convertHtml.py +++ b/scripts/convertHtml.py @@ -27,11 +27,22 @@ def getFlagsOfEnv(env): elif len(flags[i]) > 0: build_flags = build_flags + [flags[i]] +def parseDefinesH(): + global build_flags + pattern = r'^\s*#\s*define\s+(\w+)' + + with open("defines.h", "r") as f: + for line in f: + match = re.match(pattern, line) + if match: + build_flags += [match.group(1)] + def get_build_flags(): getFlagsOfEnv("env:" + env['PIOENV']) config = configparser.ConfigParser() config.read('platformio.ini') + parseDefinesH() # translate board board = config["env:" + env['PIOENV']]['board'] diff --git a/src/CHANGES.md b/src/CHANGES.md index bb9bc7d5..a6f16b50 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.105 - 2024-04-05 +* cleanup of `defines.h` + ## 0.8.104 - 2024-04-04 * fix reboot on inverter save (ESP32) #1559 * fix NRF and Ethernet #1506 diff --git a/src/config/settings.h b/src/config/settings.h index 8f20ba8f..2d1d2229 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -33,7 +33,6 @@ #define CONFIG_VERSION 11 - #define PROT_MASK_INDEX 0x0001 #define PROT_MASK_LIVE 0x0002 #define PROT_MASK_SERIAL 0x0004 @@ -55,6 +54,20 @@ #define DEF_PROT_MQTT 0x0000 +#define SSID_LEN 32 +#define PWD_LEN 64 +#define DEVNAME_LEN 16 +#define NTP_ADDR_LEN 32 // DNS Name + +#define MQTT_ADDR_LEN 64 // DNS Name +#define MQTT_CLIENTID_LEN 22 // number of chars is limited to 23 up to v3.1 of MQTT +#define MQTT_USER_LEN 65 // there is another byte necessary for \0 +#define MQTT_PWD_LEN 65 +#define MQTT_TOPIC_LEN 65 + +#define MQTT_MAX_PACKET_SIZE 384 + + typedef struct { uint8_t ip[4]; // ip address uint8_t mask[4]; // sub mask diff --git a/src/defines.h b/src/defines.h index d551ee8a..f3079aff 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 104 +#define VERSION_PATCH 105 //------------------------------------- typedef struct { uint8_t ch; @@ -23,41 +23,6 @@ typedef struct { uint16_t millis; } packet_t; -typedef enum { - InverterDevInform_Simple = 0, // 0x00 - InverterDevInform_All = 1, // 0x01 - GridOnProFilePara = 2, // 0x02 - HardWareConfig = 3, // 0x03 - SimpleCalibrationPara = 4, // 0x04 - SystemConfigPara = 5, // 0x05 - RealTimeRunData_Debug = 11, // 0x0b - RealTimeRunData_Reality = 12, // 0x0c - RealTimeRunData_A_Phase = 13, // 0x0d - RealTimeRunData_B_Phase = 14, // 0x0e - RealTimeRunData_C_Phase = 15, // 0x0f - AlarmData = 17, // 0x11, Alarm data - all unsent alarms - AlarmUpdate = 18, // 0x12, Alarm data - all pending alarms - RecordData = 19, // 0x13 - InternalData = 20, // 0x14 - GetLossRate = 21, // 0x15 - GetSelfCheckState = 30, // 0x1e - InitDataState = 0xff -} InfoCmdType; - -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; - typedef enum { AbsolutNonPersistent = 0UL, // 0x0000 RelativNonPersistent = 1UL, // 0x0001 @@ -70,13 +35,6 @@ union serial_u { uint8_t b[8]; }; -#define MIN_SERIAL_INTERVAL 2 // 5 -#define MIN_SEND_INTERVAL 15 -#define MIN_MQTT_INTERVAL 60 - - -enum {MQTT_STATUS_OFFLINE = 0, MQTT_STATUS_PARTIAL, MQTT_STATUS_ONLINE}; - enum { DISP_TYPE_T0_NONE = 0, DISP_TYPE_T1_SSD1306_128X64 = 1, @@ -88,24 +46,6 @@ enum { DISP_TYPE_T10_EPAPER = 10 }; - -//------------------------------------- -// EEPROM -//------------------------------------- -#define SSID_LEN 32 -#define PWD_LEN 64 -#define DEVNAME_LEN 16 -#define NTP_ADDR_LEN 32 // DNS Name - -#define MQTT_ADDR_LEN 64 // DNS Name -#define MQTT_CLIENTID_LEN 22 // number of chars is limited to 23 up to v3.1 of MQTT -#define MQTT_USER_LEN 65 // there is another byte necessary for \0 -#define MQTT_PWD_LEN 65 -#define MQTT_TOPIC_LEN 65 - -#define MQTT_MAX_PACKET_SIZE 384 - - typedef struct { uint32_t rxFail; uint32_t rxFailNoAnswer; diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index 6ba92774..1dc3148d 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -9,6 +9,41 @@ #include "../utils/dbg.h" #include +typedef enum { + InverterDevInform_Simple = 0, // 0x00 + InverterDevInform_All = 1, // 0x01 + GridOnProFilePara = 2, // 0x02 + HardWareConfig = 3, // 0x03 + SimpleCalibrationPara = 4, // 0x04 + SystemConfigPara = 5, // 0x05 + RealTimeRunData_Debug = 11, // 0x0b + RealTimeRunData_Reality = 12, // 0x0c + RealTimeRunData_A_Phase = 13, // 0x0d + RealTimeRunData_B_Phase = 14, // 0x0e + RealTimeRunData_C_Phase = 15, // 0x0f + AlarmData = 17, // 0x11, Alarm data - all unsent alarms + AlarmUpdate = 18, // 0x12, Alarm data - all pending alarms + RecordData = 19, // 0x13 + InternalData = 20, // 0x14 + GetLossRate = 21, // 0x15 + GetSelfCheckState = 30, // 0x1e + InitDataState = 0xff +} InfoCmdType; + +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 generations enum {IV_MI = 0, IV_HM, IV_HMS, IV_HMT, IV_UNKNOWN}; const char* const generationNames[] = {"MI", "HM", "HMS", "HMT", "UNKNOWN"}; diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 35dc2b71..2ba8ac1a 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -602,6 +602,10 @@ class PubMqtt { mLastAnyAvail = anyAvail; } + private: + enum {MQTT_STATUS_OFFLINE = 0, MQTT_STATUS_PARTIAL, MQTT_STATUS_ONLINE}; + + private: espMqttClient mClient; cfgMqtt_t *mCfgMqtt = nullptr; IApp *mApp; From da34e737c6453581d714f54afcc04e81ed72617e Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 5 Apr 2024 00:49:27 +0200 Subject: [PATCH 073/201] 0.8.105 * fix compile of esp32-minimal --- src/CHANGES.md | 1 + src/plugins/Display/Display_ePaper.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index a6f16b50..48534a7f 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,7 @@ ## 0.8.105 - 2024-04-05 * cleanup of `defines.h` +* fix compile of esp32-minimal ## 0.8.104 - 2024-04-04 * fix reboot on inverter save (ESP32) #1559 diff --git a/src/plugins/Display/Display_ePaper.cpp b/src/plugins/Display/Display_ePaper.cpp index 6d9d929e..1b52703e 100644 --- a/src/plugins/Display/Display_ePaper.cpp +++ b/src/plugins/Display/Display_ePaper.cpp @@ -39,7 +39,7 @@ void DisplayEPaper::init(uint8_t type, uint8_t _CS, uint8_t _DC, uint8_t _RST, u #if defined(ESP32) && defined(USE_HSPI_FOR_EPD) hspi.begin(_SCK, _BUSY, _MOSI, _CS); _display->epd2.selectSPI(hspi, SPISettings(spiClk, MSBFIRST, SPI_MODE0)); -#elif defined(ESP32) +#elif defined(ESP32) && defined(PLUGIN_DISPLAY) _display->epd2.init(_SCK, _MOSI, 115200, true, 20, false); #endif _display->init(115200, true, 20, false); From 2d19138463b3b6b81fb4b21bb0c01d97c221f13c Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 5 Apr 2024 23:38:28 +0200 Subject: [PATCH 074/201] 0.8.106 * fix bootloop with CMT and NRF on ESP32 #1566 #1562 --- src/CHANGES.md | 3 ++ src/app.cpp | 7 ++-- src/app.h | 4 +-- src/hm/{hmRadio.h => NrfRadio.h} | 61 ++++++++++++++++++++------------ src/hm/hmInverter.h | 2 +- src/hm/radio.h | 2 +- src/hms/cmt2300a.h | 4 +-- src/hms/hmsRadio.h | 8 ++--- src/plugins/Display/Display.h | 10 +++--- src/web/RestApi.h | 4 +-- 10 files changed, 61 insertions(+), 44 deletions(-) rename src/hm/{hmRadio.h => NrfRadio.h} (92%) diff --git a/src/CHANGES.md b/src/CHANGES.md index 48534a7f..bc4eb51f 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.106 - 2024-04-05 +* fix bootloop with CMT and NRF on ESP32 #1566 #1562 + ## 0.8.105 - 2024-04-05 * cleanup of `defines.h` * fix compile of esp32-minimal diff --git a/src/app.cpp b/src/app.cpp index f22e6906..0577aa8f 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -45,9 +45,7 @@ void app::setup() { esp_task_wdt_reset(); - if(mConfig->nrf.enabled) { - mNrfRadio.setup(&mConfig->serial.debug, &mConfig->serial.privacyLog, &mConfig->serial.printWholeTrace, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs, mConfig->nrf.pinSclk, mConfig->nrf.pinMosi, mConfig->nrf.pinMiso); - } + mNrfRadio.setup(&mConfig->serial.debug, &mConfig->serial.privacyLog, &mConfig->serial.printWholeTrace, &mConfig->nrf); #if defined(ESP32) if(mConfig->cmt.enabled) { mCmtRadio.setup(&mConfig->serial.debug, &mConfig->serial.privacyLog, &mConfig->serial.printWholeTrace, mConfig->cmt.pinSclk, mConfig->cmt.pinSdio, mConfig->cmt.pinCsb, mConfig->cmt.pinFcsb, mConfig->sys.region); @@ -141,8 +139,7 @@ void app::setup() { void app::loop(void) { esp_task_wdt_reset(); - if(mConfig->nrf.enabled) - mNrfRadio.loop(); + mNrfRadio.loop(); #if defined(ESP32) if(mConfig->cmt.enabled) diff --git a/src/app.h b/src/app.h index 2fc37ea8..49d78f56 100644 --- a/src/app.h +++ b/src/app.h @@ -17,7 +17,7 @@ #include "defines.h" #include "appInterface.h" #include "hm/hmSystem.h" -#include "hm/hmRadio.h" +#include "hm/NrfRadio.h" #if defined(ESP32) #include "hms/hmsRadio.h" #endif @@ -409,7 +409,7 @@ class app : public IApp, public ah::Scheduler { void notAvailChanged(void); HmSystemType mSys; - HmRadio<> mNrfRadio; + NrfRadio<> mNrfRadio; Communication mCommunication; bool mShowRebootRequest = false; diff --git a/src/hm/hmRadio.h b/src/hm/NrfRadio.h similarity index 92% rename from src/hm/hmRadio.h rename to src/hm/NrfRadio.h index f187d4fa..2b228fb6 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/NrfRadio.h @@ -8,8 +8,9 @@ #include #include "SPI.h" -#include "radio.h" +#include "Radio.h" #include "../config/config.h" +#include "../config/settings.h" #if defined(SPI_HAL) #include "nrfHal.h" #endif @@ -28,10 +29,10 @@ const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"}; //----------------------------------------------------------------------------- // HM Radio class //----------------------------------------------------------------------------- -template -class HmRadio : public Radio { +template +class NrfRadio : public Radio { public: - HmRadio() { + NrfRadio() { mDtuSn = DTU_SN; mIrqRcvd = false; #if defined(SPI_HAL) @@ -40,12 +41,18 @@ class HmRadio : public Radio { mNrf24.reset(new RF24(CE_PIN, CS_PIN, SPI_SPEED)); #endif } - ~HmRadio() {} + ~NrfRadio() {} - void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN, uint8_t sclk = SCLK_PIN, uint8_t mosi = MOSI_PIN, uint8_t miso = MISO_PIN) { - DPRINTLN(DBG_VERBOSE, F("hmRadio.h:setup")); + void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, cfgNrf24_t *cfg) { + DPRINTLN(DBG_VERBOSE, F("NrfRadio::setup")); - pinMode(irq, INPUT_PULLUP); + mCfg = cfg; + //uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN, uint8_t sclk = SCLK_PIN, uint8_t mosi = MOSI_PIN, uint8_t miso = MISO_PIN + + if(!mCfg->enabled) + return; + + pinMode(mCfg->pinIrq, INPUT_PULLUP); mSerialDebug = serialDebug; mPrivacyMode = privacyMode; @@ -56,7 +63,7 @@ class HmRadio : public Radio { #ifdef ESP32 #if defined(SPI_HAL) - mNrfHal.init(mosi, miso, sclk, cs, ce, SPI_SPEED); + mNrfHal.init(mCfg->pinMosi, mCfg->pinMiso, mCfg->pinSclk, mCfg->pinCs, mCfg->pinCe, SPI_SPEED); mNrf24.reset(new RF24(&mNrfHal)); #else #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 @@ -64,7 +71,7 @@ class HmRadio : public Radio { #else mSpi.reset(new SPIClass(VSPI)); #endif - mSpi->begin(sclk, miso, mosi, cs); + mSpi->begin(mCfg->pinSclk, mCfg->pinMiso, mCfg->pinMosi, mCfg->pinCs); #endif #else //the old ESP82xx cannot freely place their SPI pins @@ -75,7 +82,7 @@ class HmRadio : public Radio { #if defined(SPI_HAL) mNrf24->begin(); #else - mNrf24->begin(mSpi.get(), ce, cs); + mNrf24->begin(mSpi.get(), mCfg->pinCe, mCfg->pinCs); #endif mNrf24->setRetries(3, 15); // wait 3*250 = 750us, 16 * 250us -> 4000us = 4ms @@ -99,21 +106,24 @@ class HmRadio : public Radio { } // returns true if communication is active - bool loop(void) override { + void loop(void) { + if(!mCfg->enabled) + return; + if (!mIrqRcvd && !mNRFisInRX) - return false; // first quick check => nothing to do at all here + return; // first quick check => nothing to do at all here if(NULL == mLastIv) // prevent reading on NULL object! - return false; + return; if(!mIrqRcvd) { // no news from nRF, check timers if ((millis() - mTimeslotStart) < innerLoopTimeout) - return true; // nothing to do, still waiting + return; // nothing to do, still waiting if (mRadioWaitTime.isTimeout()) { // timeout reached! mNRFisInRX = false; rx_ready = false; - return false; + return; } // otherwise switch to next RX channel @@ -132,7 +142,7 @@ class HmRadio : public Radio { mNrf24->setChannel(mRfChLst[tempRxChIdx]); isRxInit = false; - return true; // communicating, but changed RX channel + return; // communicating, but changed RX channel } else { // here we got news from the nRF mIrqRcvd = false; @@ -145,7 +155,7 @@ class HmRadio : public Radio { if(mNRFisInRX) { DPRINTLN(DBG_WARN, F("unexpected tx irq!")); - return false; + return; } mNRFisInRX = true; @@ -181,18 +191,23 @@ class HmRadio : public Radio { } } rx_ready = false; // reset - return mNRFisInRX; + return; } } - return false; + return; } bool isChipConnected(void) const override { + if(!mCfg->enabled) + return false; return mNrf24->isChipConnected(); } void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) override { + if(!mCfg->enabled) + return; + DPRINT_IVID(DBG_INFO, iv->id); DBGPRINT(F("sendControlPacket cmd: ")); DBGHEXLN(cmd); @@ -279,13 +294,14 @@ class HmRadio : public Radio { } uint8_t getDataRate(void) const { - if(!mNrf24->isChipConnected()) + if(!isChipConnected()) return 3; // unknown return mNrf24->getDataRate(); } bool isPVariant(void) const { - return mNrf24->isPVariant(); + if(!isChipConnected()) + return mNrf24->isPVariant(); } private: @@ -413,6 +429,7 @@ class HmRadio : public Radio { } uint64_t mDtuRadioId = 0ULL; + cfgNrf24_t *mCfg = nullptr; const uint8_t mRfChLst[RF_CHANNELS] = {03, 23, 40, 61, 75}; // channel List:2403, 2423, 2440, 2461, 2475MHz uint8_t mTxChIdx = 0; uint8_t mRxChIdx = 0; diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 1d7e6620..9053c19f 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -22,7 +22,7 @@ #include #include "../config/settings.h" -#include "radio.h" +#include "Radio.h" /** * For values which are of interest and not transmitted by the inverter can be * calculated automatically. diff --git a/src/hm/radio.h b/src/hm/radio.h index 31643980..12e80850 100644 --- a/src/hm/radio.h +++ b/src/hm/radio.h @@ -33,7 +33,7 @@ class Radio { virtual uint16_t getBaseFreqMhz() { return 0; } virtual uint16_t getBootFreqMhz() { return 0; } virtual std::pair getFreqRangeMhz(void) { return std::make_pair(0, 0); } - virtual bool loop(void) = 0; + virtual void loop(void) = 0; Radio() : mTxBuf{} {} diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index 23911b15..ed3aab54 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -6,7 +6,7 @@ #ifndef __CMT2300A_H__ #define __CMT2300A_H__ -#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL) +#if defined(SPI_HAL) #include "cmtHal.h" #else #include "esp32_3wSpi.h" @@ -545,7 +545,7 @@ class Cmt2300a { } private: - #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL) + #if defined(SPI_HAL) cmtHal mSpi; #else esp32_3wSpi mSpi; diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 54975197..4b043ae2 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -7,7 +7,7 @@ #define __HMS_RADIO_H__ #include "cmt2300a.h" -#include "../hm/radio.h" +#include "../hm/Radio.h" //#define CMT_SWITCH_CHANNEL_CYCLE 5 @@ -24,16 +24,16 @@ class CmtRadio : public Radio { mTxBuf.fill(0); } - bool loop() override { + void loop() override { mCmt.loop(); if((!mIrqRcvd) && (!mRqstGetRx)) - return false; + return; getRx(); if(CmtStatus::SUCCESS == mCmt.goRx()) { mIrqRcvd = false; mRqstGetRx = false; } - return false; + return; } bool isChipConnected(void) const override { diff --git a/src/plugins/Display/Display.h b/src/plugins/Display/Display.h index e263d667..0ce1522c 100644 --- a/src/plugins/Display/Display.h +++ b/src/plugins/Display/Display.h @@ -7,7 +7,7 @@ #include #include "../../hm/hmSystem.h" -#include "../../hm/hmRadio.h" +#include "../../hm/NrfRadio.h" #include "../../utils/helper.h" #include "../plugin_lang.h" #include "Display_Mono.h" @@ -25,9 +25,9 @@ class Display { mMono = NULL; } - void setup(IApp *app, display_t *cfg, HMSYSTEM *sys, RADIO *hmradio, RADIO *hmsradio, uint32_t *utcTs) { + void setup(IApp *app, display_t *cfg, HMSYSTEM *sys, RADIO *nrfRadio, RADIO *hmsradio, uint32_t *utcTs) { mApp = app; - mHmRadio = hmradio; + mNrfRadio = nrfRadio; mHmsRadio = hmsradio; mCfg = cfg; mSys = sys; @@ -149,7 +149,7 @@ class Display { mDisplayData.totalYieldDay = totalYieldDay; mDisplayData.totalYieldTotal = totalYieldTotal; bool nrf_en = mApp->getNrfEnabled(); - bool nrf_ok = nrf_en && mHmRadio->isChipConnected(); + bool nrf_ok = nrf_en && mNrfRadio->isChipConnected(); #if defined(ESP32) bool cmt_en = mApp->getCmtEnabled(); bool cmt_ok = cmt_en && mHmsRadio->isChipConnected(); @@ -231,7 +231,7 @@ class Display { uint32_t *mUtcTs = nullptr; display_t *mCfg = nullptr; HMSYSTEM *mSys = nullptr; - RADIO *mHmRadio = nullptr; + RADIO *mNrfRadio = nullptr; RADIO *mHmsRadio = nullptr; uint16_t mRefreshCycle = 0; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 665a3333..fdc54fa4 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -40,7 +40,7 @@ class RestApi { mApp = app; mSrv = srv; mSys = sys; - mRadioNrf = (HmRadio<>*)mApp->getRadioObj(true); + mRadioNrf = (NrfRadio<>*)mApp->getRadioObj(true); #if defined(ESP32) mRadioCmt = (CmtRadio<>*)mApp->getRadioObj(false); #endif @@ -1112,7 +1112,7 @@ class RestApi { private: IApp *mApp = nullptr; HMSYSTEM *mSys = nullptr; - HmRadio<> *mRadioNrf = nullptr; + NrfRadio<> *mRadioNrf = nullptr; #if defined(ESP32) CmtRadio<> *mRadioCmt = nullptr; #endif From 00fce38db9877a58bb1c2c0cb0d499937c1a5ec8 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 5 Apr 2024 23:59:46 +0200 Subject: [PATCH 075/201] 0.8.106 * possible fix of #1553 --- src/CHANGES.md | 1 + src/app.h | 2 +- src/defines.h | 2 +- src/hms/{hmsRadio.h => CmtRadio.h} | 0 src/hms/cmt2300a.h | 4 +--- 5 files changed, 4 insertions(+), 5 deletions(-) rename src/hms/{hmsRadio.h => CmtRadio.h} (100%) diff --git a/src/CHANGES.md b/src/CHANGES.md index bc4eb51f..23b671b4 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,7 @@ ## 0.8.106 - 2024-04-05 * fix bootloop with CMT and NRF on ESP32 #1566 #1562 +* possible fix of #1553 ## 0.8.105 - 2024-04-05 * cleanup of `defines.h` diff --git a/src/app.h b/src/app.h index 49d78f56..8861cb5b 100644 --- a/src/app.h +++ b/src/app.h @@ -19,7 +19,7 @@ #include "hm/hmSystem.h" #include "hm/NrfRadio.h" #if defined(ESP32) -#include "hms/hmsRadio.h" +#include "hms/CmtRadio.h" #endif #if defined(ENABLE_MQTT) #include "publisher/pubMqtt.h" diff --git a/src/defines.h b/src/defines.h index f3079aff..10c78548 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 105 +#define VERSION_PATCH 106 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/hms/hmsRadio.h b/src/hms/CmtRadio.h similarity index 100% rename from src/hms/hmsRadio.h rename to src/hms/CmtRadio.h diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index ed3aab54..61b26894 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -248,14 +248,12 @@ class Cmt2300a { } CmtStatus tx(uint8_t buf[], uint8_t len) { - if(mTxPending) - return CmtStatus::ERR_TX_PENDING; - if(mInRxMode) { mInRxMode = false; if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return CmtStatus::ERR_SWITCH_STATE; } + mTxPending = false; // safety mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); From 4de26c8bc419cc4d8eaa85d8d7c62553a6c7c74e Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 6 Apr 2024 01:37:06 +0200 Subject: [PATCH 076/201] 0.8.106 * change MqTT return value of power limit acknowledge from `boolean` to `float`. The value returned is the same as it was set to confirm reception (not the read back value) --- src/CHANGES.md | 1 + src/publisher/pubMqtt.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 23b671b4..9f2f020d 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -3,6 +3,7 @@ ## 0.8.106 - 2024-04-05 * fix bootloop with CMT and NRF on ESP32 #1566 #1562 * possible fix of #1553 +* change MqTT return value of power limit acknowledge from `boolean` to `float`. The value returned is the same as it was set to confirm reception (not the read back value) ## 0.8.105 - 2024-04-05 * cleanup of `defines.h` diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 2ba8ac1a..91227c05 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -243,7 +243,8 @@ class PubMqtt { void setPowerLimitAck(Inverter<> *iv) { if (NULL != iv) { snprintf(mSubTopic.data(), mSubTopic.size(), "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]); - publish(mSubTopic.data(), "true", true, true, QOS_2); + snprintf(mVal.data(), mVal.size(), "%.1f", iv->powerLimit[0]/10.0); + publish(mSubTopic.data(), mVal.data(), true, true, QOS_2); } } From 6a5643209a4118df2971a03248a046dc84c59e49 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 6 Apr 2024 01:39:21 +0200 Subject: [PATCH 077/201] 0.8.106 * change case of `radio.h` to `Radio.h` --- src/hm/{radio.h => Radio.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/hm/{radio.h => Radio.h} (100%) diff --git a/src/hm/radio.h b/src/hm/Radio.h similarity index 100% rename from src/hm/radio.h rename to src/hm/Radio.h From 435aa1748af556c914e1d8f1e6043dee8566f1a1 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 6 Apr 2024 01:45:02 +0200 Subject: [PATCH 078/201] 0.8.106 fix compile --- src/config/config.h | 2 +- src/hm/NrfRadio.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/config.h b/src/config/config.h index a4b84934..3dfac72e 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -145,7 +145,7 @@ #ifndef DEF_MOTION_SENSOR_PIN #define DEF_MOTION_SENSOR_PIN DEF_PIN_OFF #endif -#else +#else // ESP8266 #ifndef DEF_NRF_CS_PIN #define DEF_NRF_CS_PIN 15 #endif diff --git a/src/hm/NrfRadio.h b/src/hm/NrfRadio.h index 2b228fb6..21d0c676 100644 --- a/src/hm/NrfRadio.h +++ b/src/hm/NrfRadio.h @@ -38,7 +38,7 @@ class NrfRadio : public Radio { #if defined(SPI_HAL) //mNrf24.reset(new RF24()); #else - mNrf24.reset(new RF24(CE_PIN, CS_PIN, SPI_SPEED)); + mNrf24.reset(new RF24(DEF_NRF_CE_PIN, DEF_NRF_CS_PIN, SPI_SPEED)); #endif } ~NrfRadio() {} From 12b4251da9773427aea6afc809900dc870bc1192 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 8 Apr 2024 23:04:50 +0200 Subject: [PATCH 079/201] 0.8.107 * fix boot loop on `reboot on midnight` feature #1542, #1599, #1566, #1571 --- src/CHANGES.md | 3 +++ src/app.cpp | 46 +++++++++++++++++++++------------------------- src/app.h | 2 +- src/defines.h | 2 +- src/platformio.ini | 2 +- src/web/lang.json | 2 +- 6 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 9f2f020d..b22ae189 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.107 - 2024-04-08 +* fix boot loop on `reboot on midnight` feature #1542, #1599, #1566, #1571 + ## 0.8.106 - 2024-04-05 * fix bootloop with CMT and NRF on ESP32 #1566 #1562 * possible fix of #1553 diff --git a/src/app.cpp b/src/app.cpp index 0577aa8f..d00a95c2 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -162,7 +162,7 @@ void app::onNetwork(bool gotIp) { ah::Scheduler::resetTicker(); regularTickers(); //reinstall regular tickers every(std::bind(&app::tickSend, this), mConfig->inst.sendInterval, "tSend"); - mMqttReconnect = true; + mTickerInstallOnce = true; mSunrise = 0; // needs to be set to 0, to reinstall sunrise and ivComm tickers! once(std::bind(&app::tickNtpUpdate, this), 2, "ntp2"); } @@ -200,40 +200,37 @@ void app::onNtpUpdate(bool gotTime) { mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; tickCalcSunrise(); } -} -//----------------------------------------------------------------------------- -void app::updateNtp(void) { - #if defined(ENABLE_MQTT) - if (mMqttReconnect && mMqttEnabled) { - mMqtt.tickerSecond(); - everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS"); - everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt), "mqttM"); - } - #endif /*ENABLE_MQTT*/ + if (mTickerInstallOnce) { + mTickerInstallOnce = false; + #if defined(ENABLE_MQTT) + if (mMqttEnabled) { + mMqtt.tickerSecond(); + everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS"); + everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt), "mqttM"); + } + #endif /*ENABLE_MQTT*/ - // only install schedulers once even if NTP wasn't successful in first loop - if (mMqttReconnect) { // @TODO: mMqttReconnect is variable which scope has changed if (mConfig->inst.rstValsNotAvail) everyMin(std::bind(&app::tickMinute, this), "tMin"); - uint32_t localTime = gTimezone.toLocal(mTimestamp); - uint32_t midTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time - onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi"); + if(mNtpReceived) { + uint32_t localTime = gTimezone.toLocal(mTimestamp); + uint32_t midTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time + onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi"); - if (mConfig->sys.schedReboot) { - uint32_t rebootTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86410); // reboot 10 secs after midnght - if (rebootTrig <= mTimestamp) { //necessary for times other than midnight to prevent reboot loop - rebootTrig += 86400; + if (mConfig->sys.schedReboot) { + uint32_t rebootTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86410); // reboot 10 secs after midnght + onceAt(std::bind(&app::tickReboot, this), rebootTrig, "midRe"); } - onceAt(std::bind(&app::tickReboot, this), rebootTrig, "midRe"); } } +} +//----------------------------------------------------------------------------- +void app::updateNtp(void) { if(mNtpReceived) onNtpUpdate(true); - - mMqttReconnect = false; } //----------------------------------------------------------------------------- @@ -249,8 +246,6 @@ void app::tickNtpUpdate(void) { updateNtp(); - mMqttReconnect = false; - once(std::bind(&app::tickNtpUpdate, this), nxtTrig, "ntp"); } @@ -548,6 +543,7 @@ void app::resetSystem(void) { mNetworkConnected = false; mNtpReceived = false; + mTickerInstallOnce = false; } //----------------------------------------------------------------------------- diff --git a/src/app.h b/src/app.h index 8861cb5b..70a1fde2 100644 --- a/src/app.h +++ b/src/app.h @@ -447,7 +447,7 @@ class app : public IApp, public ah::Scheduler { #if defined(ENABLE_MQTT) PubMqttType mMqtt; #endif /*ENABLE_MQTT*/ - bool mMqttReconnect = false; + bool mTickerInstallOnce = false; bool mMqttEnabled = false; // sun diff --git a/src/defines.h b/src/defines.h index 10c78548..60af67f6 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 106 +#define VERSION_PATCH 107 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/platformio.ini b/src/platformio.ini index a831f7c2..a6537040 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -301,7 +301,7 @@ build_flags = ${env.build_flags} -DDEF_LED1=17 -DLED_ACTIVE_HIGH -DARDUINO_USB_MODE=1 - #-DARDUINO_USB_CDC_ON_BOOT=1 + -DARDUINO_USB_CDC_ON_BOOT=1 monitor_filters = esp32_exception_decoder, colorize diff --git a/src/web/lang.json b/src/web/lang.json index 57ded1dd..c37e1d92 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -96,7 +96,7 @@ { "token": "TRY_TO_CONNECT", "en": "AhoyDTU is trying to connect to your WiFi", - "de": "AhoyDTU versucht eine Verindung mit deinem Netzwerk herzustellen" + "de": "AhoyDTU versucht eine Verbindung mit Deinem Netzwerk herzustellen" }, { "token": "CONNECTING", From 36b17b14ae13e0582144fdae9618b8861fb4dfb2 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 8 Apr 2024 23:10:11 +0200 Subject: [PATCH 080/201] 0.8.107 * fix German translation #1569 --- src/CHANGES.md | 1 + src/web/lang.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index b22ae189..d1069c8c 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,7 @@ ## 0.8.107 - 2024-04-08 * fix boot loop on `reboot on midnight` feature #1542, #1599, #1566, #1571 +* fix German translation #1569 ## 0.8.106 - 2024-04-05 * fix bootloop with CMT and NRF on ESP32 #1566 #1562 diff --git a/src/web/lang.json b/src/web/lang.json index c37e1d92..ff0062ee 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -6,7 +6,7 @@ { "token": "NAV_WIZARD", "en": "Setup Wizard", - "de": "Daten" + "de": "Einrichtungsassitent" }, { "token": "NAV_LIVE", @@ -81,7 +81,7 @@ { "token": "BTN_NEXT", "en": "next >>", - "de": "prüfen >>" + "de": "speichern >>" }, { "token": "BTN_REBOOT", From a677079681d3a899c668a8289cb668d81bddb508 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 9 Apr 2024 00:13:34 +0200 Subject: [PATCH 081/201] 0.8.107 * improved `Wizard` --- src/CHANGES.md | 1 + src/network/AhoyNetwork.h | 7 +++-- src/network/AhoyWifiAp.h | 1 + src/web/RestApi.h | 1 + src/web/html/wizard.html | 57 ++++++++++++++++++++++----------------- src/web/web.h | 1 + 6 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index d1069c8c..61b6cc12 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -3,6 +3,7 @@ ## 0.8.107 - 2024-04-08 * fix boot loop on `reboot on midnight` feature #1542, #1599, #1566, #1571 * fix German translation #1569 +* improved `Wizard` ## 0.8.106 - 2024-04-05 * fix bootloop with CMT and NRF on ESP32 #1566 #1562 diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index 55c5d193..c0ea55c2 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -91,12 +91,10 @@ class AhoyNetwork { #if !defined(ETHERNET) bool getAvailNetworks(JsonObject obj) { - JsonArray nets = obj.createNestedArray(F("networks")); - if(!mScanActive) { mScanActive = true; - if(NetworkState::GOT_IP != mStatus) - WiFi.disconnect(); + //if(NetworkState::GOT_IP != mStatus) + // WiFi.disconnect(); WiFi.scanNetworks(true, true); return false; } @@ -106,6 +104,7 @@ class AhoyNetwork { return false; if(n > 0) { + JsonArray nets = obj.createNestedArray(F("networks")); int sort[n]; sortRSSI(&sort[0], n); for (int i = 0; i < n; ++i) { diff --git a/src/network/AhoyWifiAp.h b/src/network/AhoyWifiAp.h index ce2bbd1b..994af3de 100644 --- a/src/network/AhoyWifiAp.h +++ b/src/network/AhoyWifiAp.h @@ -44,6 +44,7 @@ class AhoyWifiAp { WiFi.softAPConfig(mIp, mIp, IPAddress(255, 255, 255, 0)); WiFi.softAP(WIFI_AP_SSID, mCfg->apPwd); + mDns.setErrorReplyCode(DNSReplyCode::NoError); mDns.start(53, "*", mIp); mEnabled = true; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index fdc54fa4..1ed5d204 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -892,6 +892,7 @@ class RestApi { #if !defined(ETHERNET) void getNetworks(JsonObject obj) { obj[F("success")] = mApp->getAvailNetworks(obj); + obj[F("ip")] = mApp->getIp(); } #endif /* !defined(ETHERNET) */ diff --git a/src/web/html/wizard.html b/src/web/html/wizard.html index 1fc8503c..a6a29bbb 100644 --- a/src/web/html/wizard.html +++ b/src/web/html/wizard.html @@ -4,7 +4,7 @@ {#NAV_WIZARD} {#HTML_HEADER} - +
@@ -14,6 +14,7 @@ var v; var found = false; var c = document.getElementById("con"); + var redirIp = "http://192.168.4.1/index" /*IF_ESP32*/ var pinList = [ @@ -206,7 +207,7 @@ ]), ...lst, ml("div", {class: "row my-4"}, ml("div", {class: "col a-r"}, ml("input", {type: "button", class:"btn", value: "{#BTN_REBOOT}", onclick: () => {saveEth()}}, null))), - ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {href: "http://192.168.4.1/"}, "{#STOP_WIZARD}"))) + ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {onclick: () => {redirect()}}, "{#STOP_WIZARD}"))) ]) } /*ELSE*/ @@ -218,7 +219,7 @@ sect("{#WIFI_MANUAL}", ml("input", {id: "man", type: "text"})), sect("{#WIFI_PASSWORD}", ml("input", {id: "pwd", type: "password"})), ml("div", {class: "row my-4"}, ml("div", {class: "col a-r"}, ml("input", {type: "button", class:"btn", value: "{#BTN_NEXT}", onclick: () => {saveWifi()}}, null))), - ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {href: "http://192.168.4.1/index"}, "{#STOP_WIZARD}"))) + ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {onclick: () => {redirect()}}, "{#STOP_WIZARD}"))) ]) } /*ENDIF_ETHERNET*/ @@ -229,13 +230,13 @@ ml("div", {class: "row"}, ml("div", {class: "col"}, ml("span", {class: "fs-5"}, "{#TEST_CONNECTION}"))), sect("{#TRY_TO_CONNECT}", ml("span", {id: "state"}, "{#CONNECTING}")), ml("div", {class: "row my-4"}, ml("div", {class: "col a-r"}, ml("input", {type: "button", class:"btn hide", id: "btn", value: "{#BTN_FINISH}", onclick: () => {redirect()}}, null))), - ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {href: "http://192.168.4.1/index"}, "{#STOP_WIZARD}"))) + ml("div", {class: "row mt-5"}, ml("div", {class: "col a-c"}, ml("a", {onclick: () => {redirect()}}, "{#STOP_WIZARD}"))) ) - v = setInterval(() => {getAjax('/api/setup/getip', printIp)}, 300); + v = setInterval(() => {getAjax('/api/setup/getip', printIp)}, 500); } function redirect() { - window.location.replace("http://192.168.4.1/") + window.location.replace(redirIp) } function printIp(obj) { @@ -266,29 +267,35 @@ } /*ENDIF_ETHERNET*/ - /*IF_ETHERNET*/ - getAjax("/api/setup", ((o) => c.append(step1(o.eth)))); - /*ELSE*/ - function nets(obj) { - if(!obj.success) - return; + function init() { + /*IF_ETHERNET*/ + getAjax("/api/setup", ((o) => c.append(step1(o.eth)))); + /*ELSE*/ + function nets(obj) { + if(!obj.success) + return; + + clearInterval(v) + v = setInterval(() => {getAjax('/api/setup/networks', nets)}, 5000) - var e = document.getElementById("net"); - if(obj.networks.length > 0) { - var a = [] - a.push(ml("option", {value: -1}, obj.networks.length + " {#NUM_NETWORKS_FOUND}")) - for(n of obj.networks) { - a.push(ml("option", {value: n.ssid}, n.ssid + " (" + n.rssi + "dBm)")) - found = true; + var e = document.getElementById("net"); + if(obj.networks.length > 0) { + var a = [] + a.push(ml("option", {value: -1}, obj.networks.length + " {#NUM_NETWORKS_FOUND}")) + for(n of obj.networks) { + a.push(ml("option", {value: n.ssid}, n.ssid + " (" + n.rssi + "dBm)")) + found = true; + } + e.replaceChildren(...a) } - e.replaceChildren(...a) + + redirIp = obj.ip + "/index" } - } - c.append(step1()) - getAjax('/api/setup/networks', nets) - v = setInterval(() => {getAjax('/api/setup/networks', nets)}, 1000) - /*ENDIF_ETHERNET*/ + c.append(step1()) + getAjax('/api/setup/networks', nets) + /*ENDIF_ETHERNET*/ + } diff --git a/src/web/web.h b/src/web/web.h index 4f93b905..e88aa813 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -76,6 +76,7 @@ class Web { mWeb.on("/setup", HTTP_GET, std::bind(&Web::onSetup, this, std::placeholders::_1)); mWeb.on("/wizard", HTTP_GET, std::bind(&Web::onWizard, this, std::placeholders::_1)); + mWeb.on("/generate_204", HTTP_GET, std::bind(&Web::onWizard, this, std::placeholders::_1)); //Android captive portal mWeb.on("/save", HTTP_POST, std::bind(&Web::showSave, this, std::placeholders::_1)); mWeb.on("/live", HTTP_ANY, std::bind(&Web::onLive, this, std::placeholders::_1)); From 668e3e667d89f879e64e37d9940d89995c71f5c3 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 9 Apr 2024 00:16:31 +0200 Subject: [PATCH 082/201] 0.8.107 * fix serial console flag --- src/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platformio.ini b/src/platformio.ini index a6537040..a831f7c2 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -301,7 +301,7 @@ build_flags = ${env.build_flags} -DDEF_LED1=17 -DLED_ACTIVE_HIGH -DARDUINO_USB_MODE=1 - -DARDUINO_USB_CDC_ON_BOOT=1 + #-DARDUINO_USB_CDC_ON_BOOT=1 monitor_filters = esp32_exception_decoder, colorize From 58c57524fb0393cc09721f7312e6d81ad96cc9d9 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 9 Apr 2024 22:15:02 +0200 Subject: [PATCH 083/201] fix NRF24 patch --- patches/RF24_Hal.patch | 95 +++++++++++++++++++++++---------------- src/CHANGES.md | 6 +++ src/defines.h | 2 +- src/network/AhoyNetwork.h | 4 +- src/platformio.ini | 3 +- 5 files changed, 68 insertions(+), 42 deletions(-) diff --git a/patches/RF24_Hal.patch b/patches/RF24_Hal.patch index ed2c5bec..88a53bf9 100644 --- a/patches/RF24_Hal.patch +++ b/patches/RF24_Hal.patch @@ -1,5 +1,5 @@ diff --git a/RF24.cpp b/RF24.cpp -index 2e500b6..af00758 100644 +index 9e5b4a8..af00758 100644 --- a/RF24.cpp +++ b/RF24.cpp @@ -12,228 +12,24 @@ @@ -605,7 +605,8 @@ index 2e500b6..af00758 100644 /****************************************************************************/ -bool RF24::begin(_SPI* spiBus, rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin) --{ ++bool RF24::begin(RF24_hal* _hal) + { - ce_pin = _cepin; - csn_pin = _cspin; - return begin(spiBus); @@ -616,8 +617,7 @@ index 2e500b6..af00758 100644 -/****************************************************************************/ - -bool RF24::begin(rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin) -+bool RF24::begin(RF24_hal* _hal) - { +-{ - ce_pin = _cepin; - csn_pin = _cspin; + hal = _hal; @@ -670,12 +670,17 @@ index 2e500b6..af00758 100644 bool RF24::_init_pins() { if (!isValid()) { -@@ -1028,41 +527,7 @@ bool RF24::_init_pins() +@@ -1028,46 +527,7 @@ bool RF24::_init_pins() return false; } -#if defined(RF24_LINUX) - +- #if defined(MRAA) +- GPIO(); +- gpio.begin(ce_pin, csn_pin); +- #endif +- - pinMode(ce_pin, OUTPUT); - ce(LOW); - delay(100); @@ -713,7 +718,7 @@ index 2e500b6..af00758 100644 } /****************************************************************************/ -@@ -1146,7 +611,7 @@ bool RF24::isChipConnected() +@@ -1151,7 +611,7 @@ bool RF24::isChipConnected() bool RF24::isValid() { @@ -722,7 +727,7 @@ index 2e500b6..af00758 100644 } /****************************************************************************/ -@@ -1670,15 +1135,8 @@ void RF24::closeReadingPipe(uint8_t pipe) +@@ -1675,15 +1135,8 @@ void RF24::closeReadingPipe(uint8_t pipe) void RF24::toggle_features(void) { @@ -740,7 +745,7 @@ index 2e500b6..af00758 100644 } /****************************************************************************/ -@@ -1866,6 +1324,11 @@ uint8_t RF24::getARC(void) +@@ -1871,6 +1324,11 @@ uint8_t RF24::getARC(void) return read_register(OBSERVE_TX) & 0x0F; } @@ -753,7 +758,7 @@ index 2e500b6..af00758 100644 bool RF24::setDataRate(rf24_datarate_e speed) diff --git a/RF24.h b/RF24.h -index c029c8e..c9d612a 100644 +index dbd32ae..74ae35d 100644 --- a/RF24.h +++ b/RF24.h @@ -16,12 +16,7 @@ @@ -770,7 +775,7 @@ index c029c8e..c9d612a 100644 /** * @defgroup PALevel Power Amplifier level -@@ -115,26 +110,8 @@ typedef enum +@@ -115,29 +110,8 @@ typedef enum class RF24 { private: @@ -779,15 +784,18 @@ index c029c8e..c9d612a 100644 -#elif defined(SPI_UART) - SPIUARTClass uspi; -#endif -+ RF24_hal *hal; - +- -#if defined(RF24_LINUX) || defined(XMEGA_D3) /* XMEGA can use SPI class */ - SPI spi; -#endif // defined (RF24_LINUX) || defined (XMEGA_D3) -#if defined(RF24_SPI_PTR) - _SPI* _spi; -#endif // defined (RF24_SPI_PTR) -- +-#if defined(MRAA) +- GPIO gpio; +-#endif ++ RF24_hal *hal; + - rf24_gpio_pin_t ce_pin; /* "Chip Enable" pin, activates the RX or TX role */ - rf24_gpio_pin_t csn_pin; /* SPI Chip select */ - uint32_t spi_speed; /* SPI Bus Speed */ @@ -798,7 +806,7 @@ index c029c8e..c9d612a 100644 uint8_t status; /* The status byte returned from every SPI transaction */ uint8_t payload_size; /* Fixed size of payloads */ uint8_t pipe0_reading_address[5]; /* Last address set on pipe 0 for reading. */ -@@ -143,16 +120,6 @@ private: +@@ -146,16 +120,6 @@ private: bool _is_p0_rx; /* For keeping track of pipe 0's usage in user-triggered RX mode. */ protected: @@ -815,7 +823,7 @@ index c029c8e..c9d612a 100644 /** Whether ack payloads are enabled. */ bool ack_payloads_enabled; /** The address width to use (3, 4 or 5 bytes). */ -@@ -195,30 +162,15 @@ public: +@@ -198,30 +162,15 @@ public: * * See [Related Pages](pages.html) for device specific information * @@ -850,7 +858,7 @@ index c029c8e..c9d612a 100644 #if defined(RF24_LINUX) virtual ~RF24() {}; -@@ -240,58 +192,16 @@ public: +@@ -243,58 +192,16 @@ public: */ bool begin(void); @@ -861,16 +869,15 @@ index c029c8e..c9d612a 100644 - * @note This function assumes the `SPI::begin()` method was called before to - * calling this function. - * - * @warning This function is for the Arduino platforms only - * +- * @warning This function is for the Arduino platforms only +- * - * @param spiBus A pointer or reference to an instantiated SPI bus object. - * The `_SPI` datatype is a "wrapped" definition that will represent - * various SPI implementations based on the specified platform. - * @see Review the [Arduino support page](md_docs_arduino.html). -+ * @param _hal A pointer to the device specific hardware abstraction layer - * - * @return same result as begin() - */ +- * +- * @return same result as begin() +- */ - bool begin(_SPI* spiBus); - - /** @@ -880,8 +887,8 @@ index c029c8e..c9d612a 100644 - * @note This function assumes the `SPI::begin()` method was called before to - * calling this function. - * -- * @warning This function is for the Arduino platforms only -- * + * @warning This function is for the Arduino platforms only + * - * @param spiBus A pointer or reference to an instantiated SPI bus object. - * The `_SPI` datatype is a "wrapped" definition that will represent - * various SPI implementations based on the specified platform. @@ -889,7 +896,8 @@ index c029c8e..c9d612a 100644 - * @param _cspin The pin attached to Chip Select (often labeled CSN) on the radio module. - * - For the Arduino Due board, the [Arduino Due extended SPI feature](https://www.arduino.cc/en/Reference/DueExtendedSPI) - * is not supported. This means that the Due's pins 4, 10, or 52 are not mandated options (can use any digital output pin) for the radio's CSN pin. -- * ++ * @param _hal A pointer to the device specific hardware abstraction layer + * - * @see Review the [Arduino support page](md_docs_arduino.html). - * - * @return same result as begin() @@ -904,14 +912,14 @@ index c029c8e..c9d612a 100644 - * @param _cspin The pin attached to Chip Select (often labeled CSN) on the radio module. - * - For the Arduino Due board, the [Arduino Due extended SPI feature](https://www.arduino.cc/en/Reference/DueExtendedSPI) - * is not supported. This means that the Due's pins 4, 10, or 52 are not mandated options (can use any digital output pin) for the radio's CSN pin. -- * @return same result as begin() -- */ + * @return same result as begin() + */ - bool begin(rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin); + bool begin(RF24_hal* _hal); /** * Checks if the chip is connected to the SPI bus -@@ -664,12 +574,12 @@ public: +@@ -667,12 +574,12 @@ public: * This function uses much less ram than other `*print*Details()` methods. * * @code @@ -926,7 +934,17 @@ index c029c8e..c9d612a 100644 * cause undefined behavior. * * Registers names and/or data corresponding to the index of the `encoded_details` array: -@@ -1641,6 +1551,7 @@ public: +@@ -704,9 +611,6 @@ public: + * | 35 | FIFO_STATUS | + * | 36 | DYNPD | + * | 37 | FEATURE | +- * | 38-39 | ce_pin | +- * | 40-41 | csn_pin | +- * | 42 | SPI speed (in MHz) or'd with (isPlusVariant << 4) | + */ + void encodeRadioDetails(uint8_t* encoded_status); + +@@ -1644,6 +1548,7 @@ public: * @return Returns values from 0 to 15. */ uint8_t getARC(void); @@ -934,7 +952,7 @@ index c029c8e..c9d612a 100644 /** * Set the transmission @ref Datarate -@@ -1893,17 +1804,6 @@ private: +@@ -1896,18 +1801,6 @@ private: */ bool _init_pins(); @@ -949,16 +967,17 @@ index c029c8e..c9d612a 100644 - * @param mode HIGH to take this unit off the SPI bus, LOW to put it on - */ - void csn(bool mode); - +- /** * Set chip enable -@@ -2412,4 +2312,4 @@ private: - * Use `ctrl+c` to quit at any time. - */ - --#endif // __RF24_H__ -\ No newline at end of file -+#endif // __RF24_H__ + * +diff --git a/RF24_hal.cpp b/RF24_hal.cpp +new file mode 100644 +index 0000000..3cc78e4 +--- /dev/null ++++ b/RF24_hal.cpp +@@ -0,0 +1 @@ ++#include "RF24_hal.h" diff --git a/RF24_hal.h b/RF24_hal.h new file mode 100644 index 0000000..baceab3 diff --git a/src/CHANGES.md b/src/CHANGES.md index 61b6cc12..b1e93d32 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,11 @@ # Development Changes +## 0.8.109 - 2024-04-09 +* fix hal patch + +## 0.8.108 - 2024-04-09 +* point to git SHA for `NRF24` library + ## 0.8.107 - 2024-04-08 * fix boot loop on `reboot on midnight` feature #1542, #1599, #1566, #1571 * fix German translation #1569 diff --git a/src/defines.h b/src/defines.h index 60af67f6..7e050bb4 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 107 +#define VERSION_PATCH 108 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index c0ea55c2..b5778f7d 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -93,8 +93,8 @@ class AhoyNetwork { bool getAvailNetworks(JsonObject obj) { if(!mScanActive) { mScanActive = true; - //if(NetworkState::GOT_IP != mStatus) - // WiFi.disconnect(); + if(NetworkState::GOT_IP != mStatus) + WiFi.disconnect(); WiFi.scanNetworks(true, true); return false; } diff --git a/src/platformio.ini b/src/platformio.ini index a831f7c2..53a56dd1 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -26,7 +26,8 @@ extra_scripts = lib_deps = https://github.com/esphome/ESPAsyncWebServer @ ^3.1.0 - https://github.com/nRF24/RF24 @ 1.4.8 + https://github.com/nRF24/RF24.git#v1.4.8 + paulstoffregen/Time @ ^1.6.1 https://github.com/bertmelis/espMqttClient#v1.6.0 bblanchon/ArduinoJson @ ^6.21.3 From 77914076604823bc0c4d6d4b3ddba07bbd1aa1a4 Mon Sep 17 00:00:00 2001 From: Sebastian Rothe Date: Thu, 11 Apr 2024 00:33:19 +0200 Subject: [PATCH 084/201] fix: add missing closing tag fix typo --- src/web/html/update.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/html/update.html b/src/web/html/update.html index 52ace5f1..ebdbb7ab 100644 --- a/src/web/html/update.html +++ b/src/web/html/update.html @@ -17,7 +17,7 @@
From c58e29c6a908634eca44aea3586bbf9ab04972f8 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 11 Apr 2024 20:37:06 +0200 Subject: [PATCH 085/201] 0.8.110 * revert CMT2300A changes #1553 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/hms/cmt2300a.h | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index b1e93d32..29a3fb41 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.110 - 2024-04-11 +* revert CMT2300A changes #1553 + ## 0.8.109 - 2024-04-09 * fix hal patch diff --git a/src/defines.h b/src/defines.h index 7e050bb4..e7eecc00 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 108 +#define VERSION_PATCH 110 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index 61b26894..ed3aab54 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -248,12 +248,14 @@ class Cmt2300a { } CmtStatus tx(uint8_t buf[], uint8_t len) { + if(mTxPending) + return CmtStatus::ERR_TX_PENDING; + if(mInRxMode) { mInRxMode = false; if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return CmtStatus::ERR_SWITCH_STATE; } - mTxPending = false; // safety mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); From e76722ad335c2e6765549657a331491249ff858c Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 11 Apr 2024 21:34:05 +0200 Subject: [PATCH 086/201] 0.8.110 * add disable retain flag #1582 --- src/CHANGES.md | 2 ++ src/config/settings.h | 4 ++++ src/publisher/pubMqtt.h | 3 +++ src/web/RestApi.h | 1 + src/web/html/setup.html | 9 +++++++-- src/web/lang.json | 5 +++++ src/web/web.h | 1 + 7 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 29a3fb41..1ad0ee1e 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,8 @@ ## 0.8.110 - 2024-04-11 * revert CMT2300A changes #1553 +* merged PR: fix closing tag #1584 +* add disable retain flag #1582 ## 0.8.109 - 2024-04-09 * fix hal patch diff --git a/src/config/settings.h b/src/config/settings.h index 2d1d2229..e97519a1 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -165,6 +165,7 @@ typedef struct { char pwd[MQTT_PWD_LEN]; char topic[MQTT_TOPIC_LEN]; uint16_t interval; + bool enableRetain; } cfgMqtt_t; typedef struct { @@ -490,6 +491,7 @@ 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.enableRetain = true; mCfg.inst.sendInterval = SEND_INTERVAL; mCfg.inst.rstYieldMidNight = false; @@ -746,6 +748,7 @@ class settings { obj[F("pwd")] = mCfg.mqtt.pwd; obj[F("topic")] = mCfg.mqtt.topic; obj[F("intvl")] = mCfg.mqtt.interval; + obj[F("retain")] = mCfg.mqtt.enableRetain; } else { getVal(obj, F("port"), &mCfg.mqtt.port); @@ -755,6 +758,7 @@ class settings { getChar(obj, F("clientId"), mCfg.mqtt.clientId, MQTT_CLIENTID_LEN); getChar(obj, F("pwd"), mCfg.mqtt.pwd, MQTT_PWD_LEN); getChar(obj, F("topic"), mCfg.mqtt.topic, MQTT_TOPIC_LEN); + getVal(obj, F("retain"), &mCfg.mqtt.enableRetain); } } diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 91227c05..8506a87c 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -205,6 +205,9 @@ class PubMqtt { else snprintf(mTopic.data(), mTopic.size(), "%s", subTopic); + if(!mCfgMqtt->enableRetain) + retained = false; + mClient.publish(mTopic.data(), qos, retained, payload); yield(); mTxCnt++; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 1ed5d204..968ea0e8 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -710,6 +710,7 @@ class RestApi { 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("retain")] = (bool)mConfig->mqtt.enableRetain; } void getNtp(JsonObject obj) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 122f5427..e0c1693a 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -246,6 +246,10 @@
+
+
{#RETAIN}
+
+
@@ -282,7 +286,7 @@
{#DISP_LUMINANCE}
-
+

{#DISP_PINOUT}

@@ -291,7 +295,7 @@

{#GRAPH_OPTIONS}

{#GRAPH_SHOW_RATIO}
-
+
@@ -922,6 +926,7 @@ function parseMqtt(obj) { for(var i of [["Addr", "broker"], ["Port", "port"], ["ClientId", "clientId"], ["User", "user"], ["Pwd", "pwd"], ["Topic", "topic"], ["Interval", "interval"]]) document.getElementsByName("mqtt"+i[0])[0].value = obj[i[1]]; + document.getElementsByName("retain")[0].checked = obj.retain } function parseNtp(obj) { diff --git a/src/web/lang.json b/src/web/lang.json index ff0062ee..42669e28 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -413,6 +413,11 @@ "en": "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)", "de": "Wechselrichterdaten in fixem Intervall schicken, auch wenn es keine Änderung gab. Ein Wert von '0' deaktiviert das fixe Intervall, die Wechselrichterdaten werden übertragen, sobald neue zur Verfügung stehen. (Standard: 0)" }, + { + "token": "RETAIN", + "en": "enable retain flag", + "de": "'Retain Flag' aktivieren" + }, { "token": "DISPLAY_CONFIG", "en": "Display Config", diff --git a/src/web/web.h b/src/web/web.h index e88aa813..7b73fe9f 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -583,6 +583,7 @@ class Web { request->arg("mqttTopic").toCharArray(mConfig->mqtt.topic, MQTT_TOPIC_LEN); mConfig->mqtt.port = request->arg("mqttPort").toInt(); mConfig->mqtt.interval = request->arg("mqttInterval").toInt(); + mConfig->mqtt.enableRetain = (request->arg("retain") == "on"); // serial console mConfig->serial.debug = (request->arg("serDbg") == "on"); From 1f86e4cedb9a50c6a91896d36d66ec9af15c90df Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 11 Apr 2024 23:12:32 +0200 Subject: [PATCH 087/201] 0.8.110 * improved `Wizard --- src/CHANGES.md | 2 ++ src/app.h | 6 +++++- src/appInterface.h | 3 +++ src/network/AhoyNetwork.h | 14 +++++++++----- src/network/AhoyWifiAp.h | 1 + src/network/AhoyWifiEsp32.h | 1 + src/web/RestApi.h | 4 +++- src/web/lang.h | 18 ++++++++++++++++++ src/web/lang.json | 2 +- 9 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 1ad0ee1e..8a41bd80 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -4,6 +4,8 @@ * revert CMT2300A changes #1553 * merged PR: fix closing tag #1584 * add disable retain flag #1582 +* fix German translation #1569 +* improved `Wizard` ## 0.8.109 - 2024-04-09 * fix hal patch diff --git a/src/app.h b/src/app.h index 70a1fde2..a7be0a55 100644 --- a/src/app.h +++ b/src/app.h @@ -168,7 +168,7 @@ class app : public IApp, public ah::Scheduler { #if !defined(ETHERNET) bool getAvailNetworks(JsonObject obj) override { - return mNetwork->getAvailNetworks(obj); + return mNetwork->getAvailNetworks(obj, this); } void setupStation(void) override { @@ -204,6 +204,10 @@ class app : public IApp, public ah::Scheduler { return mVersionModules; } + void addOnce(ah::scdCb c, uint32_t timeout, const char *name) override { + once(c, timeout, name); + } + uint32_t getSunrise() override { return mSunrise; } diff --git a/src/appInterface.h b/src/appInterface.h index a1f5cd0e..a5f4d081 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -8,6 +8,7 @@ #include "defines.h" #include "ESPAsyncWebServer.h" +#include "utils/scheduler.h" // abstract interface to App. Make members of App accessible from child class // like web or API without forward declaration @@ -25,6 +26,8 @@ class IApp { virtual const char *getVersion() = 0; virtual const char *getVersionModules() = 0; + virtual void addOnce(ah::scdCb c, uint32_t timeout, const char *name) = 0; + #if !defined(ETHERNET) virtual bool getAvailNetworks(JsonObject obj) = 0; virtual void setupStation(void) = 0; diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index b5778f7d..75b262bf 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -90,12 +90,9 @@ class AhoyNetwork { } #if !defined(ETHERNET) - bool getAvailNetworks(JsonObject obj) { + bool getAvailNetworks(JsonObject obj, IApp *app) { if(!mScanActive) { - mScanActive = true; - if(NetworkState::GOT_IP != mStatus) - WiFi.disconnect(); - WiFi.scanNetworks(true, true); + app->addOnce([this]() {scan();}, 1, F("scan")); return false; } @@ -117,6 +114,13 @@ class AhoyNetwork { return true; } + + void scan(void) { + mScanActive = true; + if(NetworkState::GOT_IP != mStatus) + WiFi.disconnect(); + WiFi.scanNetworks(true, true); + } #endif protected: diff --git a/src/network/AhoyWifiAp.h b/src/network/AhoyWifiAp.h index 994af3de..669e8ec8 100644 --- a/src/network/AhoyWifiAp.h +++ b/src/network/AhoyWifiAp.h @@ -63,6 +63,7 @@ class AhoyWifiAp { #if defined(ETHERNET) WiFi.mode(WIFI_OFF); #else + WiFi.scanDelete(); WiFi.mode(WIFI_STA); #endif diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index 6ccb077a..98b7053c 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -30,6 +30,7 @@ class AhoyWifi : public AhoyNetwork { DBGPRINT(F("connect to network '")); DBGPRINT(mConfig->sys.stationSsid); + DBGPRINTLN(F("'")); #endif } diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 968ea0e8..188afe23 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -489,7 +489,9 @@ class RestApi { void getHtmlFactory(AsyncWebServerRequest *request, JsonObject obj) { getGeneric(request, obj.createNestedObject(F("generic"))); - obj[F("html")] = F("Factory reset? yes no"); + char tmp[200]; + snprintf(tmp, 200, "%s %s %s", FACTORY_RESET, BTN_YES, BTN_NO); + obj[F("html")] = tmp; } void getHtmlFactoryTrue(AsyncWebServerRequest *request, JsonObject obj) { diff --git a/src/web/lang.h b/src/web/lang.h index fb5506ee..54ade94e 100644 --- a/src/web/lang.h +++ b/src/web/lang.h @@ -72,4 +72,22 @@ #define BTN_REBOOT "Reboot" #endif +#ifdef LANG_DE + #define BTN_REBOOT "Ahoy neustarten" +#else /*LANG_EN*/ + #define BTN_REBOOT "Reboot" +#endif + +#ifdef LANG_DE + #define BTN_YES "ja" +#else /*LANG_EN*/ + #define BTN_YES "yes" +#endif + +#ifdef LANG_DE + #define BTN_NO "nein" +#else /*LANG_EN*/ + #define BTN_NO "no" +#endif + #endif /*__LANG_H__*/ diff --git a/src/web/lang.json b/src/web/lang.json index 42669e28..34b10a25 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -106,7 +106,7 @@ { "token": "NETWORK_SUCCESS", "en": "success, got following IP in your network: ", - "de": "Verindung erfolgreich. AhoyDTU hat die folgende IP bekommen: " + "de": "Verbindung erfolgreich. AhoyDTU hat die folgende IP bekommen: " }, { "token": "BTN_FINISH", From 4587c1c2f7a508181235d1d234e86bb1631582ad Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 11 Apr 2024 23:16:17 +0200 Subject: [PATCH 088/201] 0.8.110 * fix ESP8266 compile --- src/network/AhoyNetwork.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h index 75b262bf..889fde8e 100644 --- a/src/network/AhoyNetwork.h +++ b/src/network/AhoyNetwork.h @@ -92,7 +92,7 @@ class AhoyNetwork { #if !defined(ETHERNET) bool getAvailNetworks(JsonObject obj, IApp *app) { if(!mScanActive) { - app->addOnce([this]() {scan();}, 1, F("scan")); + app->addOnce([this]() {scan();}, 1, "scan"); return false; } From 1a9da99f74b418183ffd671d14727cddb11cde1e Mon Sep 17 00:00:00 2001 From: geronet1 Date: Fri, 12 Apr 2024 11:46:46 +0200 Subject: [PATCH 089/201] =?UTF-8?q?Total=20Summe=20in=20=C3=9Cbersicht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/web/html/index.html | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/web/html/index.html b/src/web/html/index.html index 954ee012..a811dd2a 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -14,6 +14,7 @@

System Infos: +

@@ -111,6 +112,8 @@ function parseIv(obj, ts) { var p = div(["none"]); + var total = 0; + var count = 0; for(var i of obj) { var icon = iconSuccess; var cl = "icon-success"; @@ -131,7 +134,9 @@ avail += "{#NOT_PRODUCING}"; else { icon = iconSuccessFull; - avail += "{#PRODUCING} " + i.cur_pwr + "W"; + avail += "{#PRODUCING} " + i.cur_pwr + " W"; + total += i.cur_pwr; + count += 1; } } @@ -149,6 +154,12 @@ } } document.getElementById("iv").replaceChildren(p); + + if (count > 1) { + p.append(svg(iconInfo, 30, 30, "icon icon-info"), span("Total: " + total + " W"), br()); + document.getElementById("total").replaceChildren(p); + document.getElementById("total").appendChild(div(["class=\"hr\""])); + } } function parseWarn(warn) { @@ -165,7 +176,7 @@ p.append(svg(iconInfo, 30, 30, "icon icon-info"), span("{#UPDATE_AVAIL}: " + release), br()); else if(getVerInt("{#VERSION}") > getVerInt(release)) p.append(svg(iconInfo, 30, 30, "icon icon-info"), span("{#USING_DEV_VERSION} {#VERSION}. {#DEV_ISSUE_RELEASE_VERSION}: " + release), br()); - else + else p.append(svg(iconInfo, 30, 30, "icon icon-info"), span("{#RELEASE_INSTALLED}: " + release), br()); } From 806e264dc6490e293ccd5e09f916899efcee792b Mon Sep 17 00:00:00 2001 From: Patrick Bollmann Date: Sat, 13 Apr 2024 19:43:50 +0200 Subject: [PATCH 090/201] Disable upload and import buttons when no file is selected --- src/web/html/colorBright.css | 1 + src/web/html/colorDark.css | 1 + src/web/html/setup.html | 24 ++++++++++++++++++++++-- src/web/html/style.css | 8 +++++++- src/web/html/update.html | 25 +++++++++++++++++++++++-- 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/web/html/colorBright.css b/src/web/html/colorBright.css index aedd05d4..ebf4f12a 100644 --- a/src/web/html/colorBright.css +++ b/src/web/html/colorBright.css @@ -12,6 +12,7 @@ --nav-bg: #333; --primary: #006ec0; + --primary-disabled: #ccc; --primary-hover: #044e86; --secondary: #0072c8; --nav-active: #555; diff --git a/src/web/html/colorDark.css b/src/web/html/colorDark.css index b5b1a72b..23e7a2cf 100644 --- a/src/web/html/colorDark.css +++ b/src/web/html/colorDark.css @@ -12,6 +12,7 @@ --nav-bg: #333; --primary: #004d87; + --primary-disabled: #ccc; --primary-hover: #023155; --secondary: #0072c8; --nav-active: #555; diff --git a/src/web/html/setup.html b/src/web/html/setup.html index e0c1693a..a7e4d983 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -321,8 +321,8 @@
-
-
+
+
@@ -612,6 +612,26 @@ var obj = {cmd: "discovery_cfg", token: "*"} getAjax("/api/setup", apiCbMqtt, "POST", JSON.stringify(obj)); } + // Wait for the DOM to be fully loaded + document.addEventListener('DOMContentLoaded', () => { + // Get references to the file input and button elements + const fileInput = document.querySelector('#importFileInput'); + const button = document.querySelector('#importButton'); + // Initially disable the button + button.disabled = true; + button.title = "Please select a file first"; + // Listen for changes on the file input + fileInput.addEventListener('change', () => { + // Enable or disable the button based on whether a file is selected + if (fileInput.value) { + button.disabled = false; + button.title = ""; // Clear the tooltip when a file is selected + } else { + button.disabled = true; + button.title = "Please select a file first"; // Show the tooltip when no file is selected + } + }); + }); function hide() { document.getElementById("form").submit(); diff --git a/src/web/html/style.css b/src/web/html/style.css index 60805e19..2866dda1 100644 --- a/src/web/html/style.css +++ b/src/web/html/style.css @@ -563,7 +563,13 @@ input.btn { cursor: pointer; } -input.btn:hover { +input.btn:disabled { + background-color: var(--primary-disabled); + color: #888; + cursor: not-allowed; +} + +input.btn:not(:disabled):hover { background-color: #044e86; } diff --git a/src/web/html/update.html b/src/web/html/update.html index ebdbb7ab..a72c6536 100644 --- a/src/web/html/update.html +++ b/src/web/html/update.html @@ -12,8 +12,8 @@ {#SELECT_FILE} (*.bin)

{#INSTALLED_VERSION}:

- - + +
@@ -23,6 +23,27 @@
{#HTML_FOOTER} From 034cbd57b1642b9d155411f0ab3e93f423482bfe Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 6 Jun 2024 21:31:26 +0200 Subject: [PATCH 151/201] 0.8.124 * improved MqTT `OnMessage` (threadsafe) --- src/CHANGES.md | 7 ++++-- src/defines.h | 2 +- src/plugins/MaxPower.h | 2 +- src/publisher/pubMqtt.h | 54 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index f4c5d4ce..51723203 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,10 +1,13 @@ # Development Changes +## 0.8.124 - 2024-06-06 +* improved MqTT `OnMessage` (threadsafe) + ## 0.8.123 - 2024-05-30 * fix ESP8266, ESP32 static IP #1643 #1608 * update MqTT library which enhances stability #1646 -* merge PR: MQTT JSON Payload pro Kanal und total, auswählbar #1541 -* add option to publish mqtt as json +* merge PR: MqTT JSON Payload pro Kanal und total, auswählbar #1541 +* add option to publish MqTT as json * publish rssi not on ch0 any more, published on `topic/rssi` * add total power to index page (if multiple inverters are configured) * show device name in html title #1639 diff --git a/src/defines.h b/src/defines.h index ab651821..bae0df51 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 123 +#define VERSION_PATCH 124 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/plugins/MaxPower.h b/src/plugins/MaxPower.h index a8db6909..68665d61 100644 --- a/src/plugins/MaxPower.h +++ b/src/plugins/MaxPower.h @@ -50,7 +50,7 @@ class MaxPower { if((mValues[i].first + mMaxDiff) >= *mTs) val += mValues[i].second; else if(mValues[i].first > 0) - return mLast; // old data + break; // old data } if(val > mLast) mLast = val; diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index f092a159..477d942a 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -39,6 +39,9 @@ template class PubMqtt { public: PubMqtt() : SendIvData() { + mutex = xSemaphoreCreateBinaryStatic(&mutexBuffer); + xSemaphoreGive(mutex); + mLastIvState.fill(InverterStatus::OFF); mIvLastRTRpub.fill(0); @@ -50,7 +53,9 @@ class PubMqtt { mSendAlarm.fill(false); } - ~PubMqtt() { } + ~PubMqtt() { + vSemaphoreDelete(mutex); + } void setup(IApp *app, cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs, uint32_t *uptime) { mApp = app; @@ -96,6 +101,17 @@ class PubMqtt { } void loop() { + std::queue queue; + xSemaphoreTake(mutex, portMAX_DELAY); + std::swap(queue, mReceiveQueue); + xSemaphoreGive(mutex); + + while (!queue.empty()) { + message_s *entry = &queue.front(); + handleMessage(entry->topic, entry->payload, entry->len, entry->index, entry->total); + queue.pop(); + } + SendIvData.loop(); #if defined(ESP8266) @@ -301,6 +317,14 @@ class PubMqtt { void onMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) { if(len == 0) return; + + xSemaphoreTake(mutex, portMAX_DELAY); + mReceiveQueue.push(message_s(topic, payload, len, index, total)); + xSemaphoreGive(mutex); + + } + + inline void handleMessage(const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) { DPRINT(DBG_INFO, mqttStr[MQTT_STR_GOT_TOPIC]); DBGPRINTLN(String(topic)); if(NULL == mSubscriptionCb) @@ -613,6 +637,30 @@ class PubMqtt { private: enum {MQTT_STATUS_OFFLINE = 0, MQTT_STATUS_PARTIAL, MQTT_STATUS_ONLINE}; + struct message_s { + char* topic; + uint8_t* payload; + size_t len; + size_t index; + size_t total; + + message_s(const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) { + this->topic = new char[strlen(topic) + 1]; + this->payload = new uint8_t[len]; + + memcpy(this->topic, topic, strlen(topic)); + memcpy(this->payload, payload, len); + this->len = len; + this->index = index; + this->total = total; + } + + ~message_s() { + delete[] this->topic; + delete[] this->payload; + } + }; + private: espMqttClient mClient; cfgMqtt_t *mCfgMqtt = nullptr; @@ -620,6 +668,8 @@ class PubMqtt { #if defined(ESP8266) WiFiEventHandler mHWifiCon, mHWifiDiscon; #endif + SemaphoreHandle_t mutex; + StaticSemaphore_t mutexBuffer; HMSYSTEM *mSys = nullptr; PubMqttIvData SendIvData; @@ -634,6 +684,8 @@ class PubMqtt { std::array mIvLastRTRpub; uint16_t mIntervalTimeout = 0; + std::queue mReceiveQueue; + // last will topic and payload must be available through lifetime of 'espMqttClient' std::array mLwtTopic; const char *mDevName = nullptr, *mVersion = nullptr; From 10423d7476e68565a9756b62d9935ce5fe7c21d5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 7 Jun 2024 00:29:20 +0200 Subject: [PATCH 152/201] 0.8.124 * support of HERF inverters, serial number is converted in Javascript #1425 * revert buffer size in `RestAPI` for ESP8266 #1650 --- src/CHANGES.md | 2 ++ src/web/RestApi.h | 4 ++++ src/web/html/setup.html | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 51723203..ebe26f58 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,8 @@ ## 0.8.124 - 2024-06-06 * improved MqTT `OnMessage` (threadsafe) +* support of HERF inverters, serial number is converted in Javascript #1425 +* revert buffer size in `RestAPI` for ESP8266 #1650 ## 0.8.123 - 2024-05-30 * fix ESP8266, ESP32 static IP #1643 #1608 diff --git a/src/web/RestApi.h b/src/web/RestApi.h index e7f23055..d1f130d4 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -83,7 +83,11 @@ class RestApi { mHeapFrag = ESP.getHeapFragmentation(); #endif + #if defined(ESP32) AsyncJsonResponse* response = new AsyncJsonResponse(false, 8000); + #else + AsyncJsonResponse* response = new AsyncJsonResponse(false, 6000); + #endif JsonObject root = response->getRoot(); String path = request->url().substring(5); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 26b7100c..9452f0e3 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -880,11 +880,16 @@ ser.dispatchEvent(new Event('change')); function ivSave() { - var o = new Object(); + var o = {} o.cmd = "save_iv" o.token = "*" o.id = obj.id - o.ser = parseInt(document.getElementsByName("ser")[0].value, 16); + + let sn = document.getElementsByName("ser")[0].value + if(sn[0] == 'A') + sn = convHerf(sn) + o.ser = parseInt(sn, 16) + o.name = document.getElementsByName("name")[0].value; o.en = document.getElementsByName("enable")[0].checked; o.ch = []; @@ -904,6 +909,30 @@ getAjax("/api/setup", cb, "POST", JSON.stringify(o)); } + function convHerf(sn) { + let sn_int = 0n; + const CHARS = "0123456789ABCDEFGHJKLMNPRSTUVWXY"; + + for (let i = 0; i < 9; ++i) { + const pos = CHARS.indexOf(sn[i]) + const shift = 42 - 5 * i - (i <= 2 ? 0 : 2) + sn_int |= BigInt(pos) << BigInt(shift) + } + + let first4Hex = (sn_int >> 32n) & 0xFFFFn + + if (first4Hex === 0x2841n) + first4Hex = 0x1121n + else if (first4Hex === 0x2821n) + first4Hex = 0x1141n + else if (first4Hex === 0x2801n) + first4Hex = 0x1161n + + sn_int = (sn_int & ~(0xFFFFn << 32n)) | (first4Hex << 32n); + + return sn_int.toString(16) + } + function cb(obj2) { var e = document.getElementById("res"); if(!obj2.success) From 1c4722e09b0067429829b855d78509e4847eebe3 Mon Sep 17 00:00:00 2001 From: geronet1 Date: Fri, 7 Jun 2024 08:21:19 +0200 Subject: [PATCH 153/201] active_PowerLimit json fix --- src/publisher/pubMqttIvData.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 3f12afc6..7965cde6 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -197,13 +197,20 @@ class PubMqttIvData { if (!mCfg->json) { snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mIv->getValue(mPos, rec))); + } else { + if (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) { + uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0; + snprintf(mSubTopic.data(), mSubTopic.size(), "%s/%s", mIv->config->name, fields[rec->assign[mPos].fieldId]); + snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mIv->getValue(mPos, rec))); + mPublish(mSubTopic.data(), mVal.data(), retained, qos); + } } } - if ((InverterDevInform_All == mCmd) || (InverterDevInform_Simple == mCmd) || !mCfg->json) { + if ((InverterDevInform_All == mCmd) || (InverterDevInform_Simple == mCmd) || !mCfg->json) + { uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0; - if((FLD_EVT != rec->assign[mPos].fieldId) - && (FLD_LAST_ALARM_CODE != rec->assign[mPos].fieldId)) + if((FLD_EVT != rec->assign[mPos].fieldId) && (FLD_LAST_ALARM_CODE != rec->assign[mPos].fieldId)) mPublish(mSubTopic.data(), mVal.data(), retained, qos); } } From 1f9096130563d232f6dd990851131f2fa96edec3 Mon Sep 17 00:00:00 2001 From: geronet1 Date: Sat, 8 Jun 2024 23:35:52 +0200 Subject: [PATCH 154/201] wifi bugfix with config_override --- src/config/config.h | 5 ++--- src/config/config_override_example.h | 3 --- src/network/AhoyWifiEsp32.h | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/config/config.h b/src/config/config.h index 49705eb6..7a3dbb64 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -16,9 +16,8 @@ //------------------------------------- // Fallback WiFi Info -#define FB_WIFI_SSID "YOUR_WIFI_SSID" -#define FB_WIFI_PWD "YOUR_WIFI_PWD" - +#define FB_WIFI_SSID "" +#define FB_WIFI_PWD "" // Access Point Info // In case there is no WiFi Network or Ahoy can not connect to it, it will act as an Access Point diff --git a/src/config/config_override_example.h b/src/config/config_override_example.h index 44623c1f..a84c1e8a 100644 --- a/src/config/config_override_example.h +++ b/src/config/config_override_example.h @@ -6,9 +6,6 @@ #ifndef __CONFIG_OVERRIDE_H__ #define __CONFIG_OVERRIDE_H__ -// override fallback WiFi info -#define FB_WIFI_OVERRIDDEN - // each override must be preceded with an #undef statement #undef FB_WIFI_SSID #define FB_WIFI_SSID "MY_SSID" diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index 89c9bbb4..b718043a 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -17,7 +17,7 @@ class AhoyWifi : public AhoyNetwork { void begin() override { mAp.enable(); - if(String(FB_WIFI_SSID) == mConfig->sys.stationSsid) + if(strlen(mConfig->sys.stationSsid) == 0) return; // no station wifi defined WiFi.disconnect(); // clean up From 13c009608be52c114d4adf6c8ef297013e725312 Mon Sep 17 00:00:00 2001 From: geronet1 Date: Sun, 9 Jun 2024 08:12:56 +0200 Subject: [PATCH 155/201] mobile display view without line break --- src/web/html/index.html | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/web/html/index.html b/src/web/html/index.html index 442160d4..ee78ac8e 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -116,6 +116,8 @@ var p = div(["none"]); var total = 0; var count = 0; + var mobile = window.screen.width < 470; + for(var i of obj) { var icon = iconSuccess; var cl = "icon-success"; @@ -131,7 +133,8 @@ } else if(0 == i["ts_last_success"]) { avail = "{#AVAIL_NO_DATA}"; } else { - avail = "{#AVAIL} "; + if (!mobile) + avail = "{#AVAIL} "; if(false == i["is_producing"]) avail += "{#NOT_PRODUCING}"; else { @@ -142,11 +145,16 @@ } } + var text; + if (mobile) + text = "#"; + else + text = "{#INVERTER} #"; p.append( - svg(icon, 30, 30, "icon " + cl), - span("{#INVERTER} #" + i["id"] + ": " + i["name"] + " {#IS} " + avail), - br() - ); + svg(icon, 30, 30, "icon " + cl), + span(text + i["id"] + ": " + i["name"] + " {#IS} " + avail), + br() + ); if(false == i["is_avail"]) { if(i["ts_last_success"] > 0) { From 7336981c620671e1a54d04b5a6f2b57be30acec3 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 9 Jun 2024 19:17:17 +0200 Subject: [PATCH 156/201] fix compilation of ESP8266 --- src/publisher/pubMqtt.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 477d942a..20317ec6 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -11,6 +11,8 @@ #if defined(ENABLE_MQTT) #ifdef ESP8266 #include + #define xSemaphoreTake(a, b) { while(a) { yield(); } a = true; } + #define xSemaphoreGive(a) { a = false; } #elif defined(ESP32) #include #endif @@ -39,8 +41,12 @@ template class PubMqtt { public: PubMqtt() : SendIvData() { - mutex = xSemaphoreCreateBinaryStatic(&mutexBuffer); - xSemaphoreGive(mutex); + #if defined(ESP32) + mutex = xSemaphoreCreateBinaryStatic(&mutexBuffer); + xSemaphoreGive(mutex); + #else + mutex = false; + #endif mLastIvState.fill(InverterStatus::OFF); mIvLastRTRpub.fill(0); @@ -54,7 +60,9 @@ class PubMqtt { } ~PubMqtt() { + #if defined(ESP32) vSemaphoreDelete(mutex); + #endif } void setup(IApp *app, cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs, uint32_t *uptime) { @@ -667,9 +675,11 @@ class PubMqtt { IApp *mApp; #if defined(ESP8266) WiFiEventHandler mHWifiCon, mHWifiDiscon; - #endif + volatile bool mutex; + #else SemaphoreHandle_t mutex; StaticSemaphore_t mutexBuffer; + #endif HMSYSTEM *mSys = nullptr; PubMqttIvData SendIvData; From cbba44d860c53d816424e4024a66472298c110ab Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 9 Jun 2024 20:25:00 +0200 Subject: [PATCH 157/201] 0.8.125 * fix ESP8266 compilation * merge PR: active_PowerLimit #1663 --- src/CHANGES.md | 4 ++++ src/defines.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index ebe26f58..91949ced 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.8.125 - 2024-06-09 +* fix ESP8266 compilation +* merge PR: active_PowerLimit #1663 + ## 0.8.124 - 2024-06-06 * improved MqTT `OnMessage` (threadsafe) * support of HERF inverters, serial number is converted in Javascript #1425 diff --git a/src/defines.h b/src/defines.h index bae0df51..8df76207 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 124 +#define VERSION_PATCH 125 //------------------------------------- typedef struct { uint8_t ch; From 5adef54d4fae32c39ef1778825c3e28ec65ce2d1 Mon Sep 17 00:00:00 2001 From: tictrick <117273857+tictrick@users.noreply.github.com> Date: Wed, 12 Jun 2024 08:57:24 +0200 Subject: [PATCH 158/201] Update pubMqtt.h - Bugfix #1673 Ahoy reboots because MQTT receives a Topic --- src/publisher/pubMqtt.h | 47 ++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 20317ec6..f80a28bd 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -111,7 +111,7 @@ class PubMqtt { void loop() { std::queue queue; xSemaphoreTake(mutex, portMAX_DELAY); - std::swap(queue, mReceiveQueue); + queue.swap(mReceiveQueue); xSemaphoreGive(mutex); while (!queue.empty()) { @@ -645,28 +645,59 @@ class PubMqtt { private: enum {MQTT_STATUS_OFFLINE = 0, MQTT_STATUS_PARTIAL, MQTT_STATUS_ONLINE}; - struct message_s { - char* topic; - uint8_t* payload; + struct message_s + { + char *topic; + uint8_t *payload; size_t len; size_t index; size_t total; - message_s(const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) { - this->topic = new char[strlen(topic) + 1]; + message_s() : topic { nullptr }, payload { nullptr }, len { 0 }, index { 0 }, total { 0 } {} + + message_s(const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) + { + uint8_t topic_len = strlen(topic) + 1; + this->topic = new char[topic_len]; this->payload = new uint8_t[len]; - memcpy(this->topic, topic, strlen(topic)); + memcpy(this->topic, topic, topic_len); memcpy(this->payload, payload, len); this->len = len; this->index = index; this->total = total; } - ~message_s() { + message_s(const message_s &) = delete; + + message_s(message_s && other) : message_s {} + { + this->swap( other ); + } + + ~message_s() + { delete[] this->topic; delete[] this->payload; } + + message_s &operator = (const message_s &) = delete; + + message_s &operator = (message_s &&other) + { + this->swap(other); + return *this; + } + + void swap(message_s &other) + { + std::swap(this->topic, other.topic); + std::swap(this->payload, other.payload); + std::swap(this->len, other.len); + std::swap(this->index, other.index); + std::swap(this->total, other.total); + } + }; private: From 29a3843c47de96a3a21a9c4419c69d7ca7e22458 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 12 Jun 2024 21:46:12 +0200 Subject: [PATCH 159/201] code formatting --- src/publisher/pubMqtt.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index f80a28bd..28cfb358 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -653,7 +653,13 @@ class PubMqtt { size_t index; size_t total; - message_s() : topic { nullptr }, payload { nullptr }, len { 0 }, index { 0 }, total { 0 } {} + message_s() + : topic { nullptr } + , payload { nullptr } + , len { 0 } + , index { 0 } + , total { 0 } + {} message_s(const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) { From d4d97dc7951d73d9efbfef068e27cae9759b36f7 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 12 Jun 2024 22:00:01 +0200 Subject: [PATCH 160/201] 0.8.126 * merge PR: Update pubMqtt.h - Bugfix #1673 #1674 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 91949ced..ac2014e8 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.126 - 2024-06-12 +* merge PR: Update pubMqtt.h - Bugfix #1673 #1674 + ## 0.8.125 - 2024-06-09 * fix ESP8266 compilation * merge PR: active_PowerLimit #1663 diff --git a/src/defines.h b/src/defines.h index 8df76207..b44b9ce1 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 125 +#define VERSION_PATCH 126 //------------------------------------- typedef struct { uint8_t ch; From 8ae03a443f38fda7307956ea0f7a6241de5676e9 Mon Sep 17 00:00:00 2001 From: geronet1 Date: Fri, 14 Jun 2024 23:20:18 +0200 Subject: [PATCH 161/201] Bugfix Inv delete not working with password protection --- src/web/html/setup.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 9452f0e3..95777c45 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -954,6 +954,7 @@ function del() { var o = new Object(); o.cmd = "save_iv"; + o.token = "*" o.id = obj.id; o.ser = 0; o.name = ""; From 75e9022d83e03a1b5a37853433270591b88c1aa2 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 21 Jun 2024 23:25:34 +0200 Subject: [PATCH 162/201] 0.8.127 * add grid file #1677 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/web/html/grid_info.json | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index ac2014e8..f9c90d66 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.127 - 2024-06-21 +* add grid file #1677 + ## 0.8.126 - 2024-06-12 * merge PR: Update pubMqtt.h - Bugfix #1673 #1674 diff --git a/src/defines.h b/src/defines.h index b44b9ce1..202b27cb 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 126 +#define VERSION_PATCH 127 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/web/html/grid_info.json b/src/web/html/grid_info.json index efb5651d..5b5d4186 100644 --- a/src/web/html/grid_info.json +++ b/src/web/html/grid_info.json @@ -10,6 +10,7 @@ {"0x0908": "France_VFR2014"}, {"0x0a00": "DE NF_EN_50549-1:2019"}, {"0x0c00": "AT_TOR_Erzeuger_default"}, + {"0x0c03": "AT_TOR_Erzeuger_cosphi=1"}, {"0x0c04": "AT_TOR_Erzeuger_default"}, {"0x0d00": "FR_VFR2019"}, {"0x0d04": "NF_EN_50549-1:2019"}, From 8cdf3644dfa62fbda8b2c1bdef25c18a45a951e0 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 21 Jun 2024 23:27:19 +0200 Subject: [PATCH 163/201] 0.8.127 --- src/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CHANGES.md b/src/CHANGES.md index f9c90d66..a035a656 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,7 @@ ## 0.8.127 - 2024-06-21 * add grid file #1677 +* merge PR: Bugfix Inv delete not working with password protection #1678 ## 0.8.126 - 2024-06-12 * merge PR: Update pubMqtt.h - Bugfix #1673 #1674 From 82e4d84522a2cdef2b17c8da540507ca5cbf8c4f Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 2 Jul 2024 20:47:11 +0200 Subject: [PATCH 164/201] 0.8.128 * add environments for 16MB flash size ESP32-S3 aka opendtufusion --- .github/workflows/compile_development.yml | 4 +++ src/CHANGES.md | 3 ++ src/defines.h | 2 +- src/platformio.ini | 36 +++++++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index b5e0e0e1..223a7a39 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -25,6 +25,8 @@ jobs: variant: - opendtufusion - opendtufusion-ethernet + - opendtufusion-16MB + - opendtufusion-ethernet-16MB - esp8266 - esp8266-all - esp8266-minimal @@ -94,6 +96,8 @@ jobs: variant: - opendtufusion-de - opendtufusion-ethernet-de + - opendtufusion-16MB-de + - opendtufusion-ethernet-16MB-de - esp8266-de - esp8266-all-de - esp8266-prometheus-de diff --git a/src/CHANGES.md b/src/CHANGES.md index a035a656..e93e7f02 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.128 - 2024-07-02 +* add environments for 16MB flash size ESP32-S3 aka opendtufusion + ## 0.8.127 - 2024-06-21 * add grid file #1677 * merge PR: Bugfix Inv delete not working with password protection #1678 diff --git a/src/defines.h b/src/defines.h index 202b27cb..fae033d7 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 127 +#define VERSION_PATCH 128 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/platformio.ini b/src/platformio.ini index 69359aa4..7a75420b 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -353,3 +353,39 @@ build_flags = ${env:opendtufusion-ethernet.build_flags} -DLANG_DE monitor_filters = esp32_exception_decoder, colorize + +[env:opendtufusion-16MB] +platform = espressif32@6.6.0 +board = esp32-s3-devkitc-1 +board_upload.flash_size = 16MB +upload_protocol = esp-builtin +build_flags = ${env:opendtufusion.build_flags} +monitor_filters = + esp32_exception_decoder, colorize + +[env:opendtufusion-16MB-de] +platform = espressif32@6.6.0 +board = esp32-s3-devkitc-1 +upload_protocol = esp-builtin +build_flags = ${env:opendtufusion-16MB.build_flags} + -DLANG_DE +monitor_filters = + esp32_exception_decoder, colorize + +[env:opendtufusion-ethernet-16MB] +platform = espressif32@6.6.0 +board = esp32-s3-devkitc-1 +board_upload.flash_size = 16MB +upload_protocol = esp-builtin +build_flags = ${env:opendtufusion-ethernet.build_flags} +monitor_filters = + esp32_exception_decoder, colorize + +[env:opendtufusion-ethernet-16MB-de] +platform = espressif32@6.6.0 +board = esp32-s3-devkitc-1 +upload_protocol = esp-builtin +build_flags = ${env:opendtufusion-ethernet-16MB.build_flags} + -DLANG_DE +monitor_filters = + esp32_exception_decoder, colorize From 19185ae63553d7bd2d17f537dce9ed3a0a877edd Mon Sep 17 00:00:00 2001 From: Telekatz Date: Sun, 7 Jul 2024 13:28:34 +0200 Subject: [PATCH 165/201] Execute ticker immediately when timeout value is 0 --- src/utils/scheduler.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h index 0f7cea7b..5ce43a36 100644 --- a/src/utils/scheduler.h +++ b/src/utils/scheduler.h @@ -35,14 +35,21 @@ namespace ah { mMax = 0; mPrevMillis = millis(); mTsMillis = mPrevMillis % 1000; + mFastTicker = false; resetTicker(); } virtual void loop(void) { mMillis = millis(); mDiff = mMillis - mPrevMillis; - if (mDiff < 1000) + if (mDiff < 1000) { + if (mFastTicker) { + mDiffSeconds = 0; + checkTicker(); + mFastTicker = false; + } return; + } mDiffSeconds = 1; if (mDiff < 2000) @@ -127,6 +134,8 @@ namespace ah { mTicker[i].isTimestamp = isTimestamp; strncpy(mTicker[i].name, name, 5); mTicker[i].name[5]=0; + if (timeout == 0 && reload == false) + mFastTicker = true; if(mMax == i) mMax = i + 1; return i; @@ -162,6 +171,7 @@ namespace ah { uint32_t mMillis = 0, mPrevMillis = 0, mDiff = 0; uint8_t mDiffSeconds = 0; uint8_t mMax = 0; + bool mFastTicker; }; } From dcb4b49fa02909574305abfa7a1422025a34ae18 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 10 Jul 2024 23:13:43 +0200 Subject: [PATCH 166/201] 0.8.128 * add environments for 16MB flash size ESP32-S3 aka opendtufusion * prevent duplicate alarms, update end time once it is received --- src/CHANGES.md | 3 ++- src/hm/hmInverter.h | 21 ++++++++++++++++++++- src/web/html/visualization.html | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index e93e7f02..dfd4ca2a 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,7 +1,8 @@ # Development Changes -## 0.8.128 - 2024-07-02 +## 0.8.128 - 2024-07-10 * add environments for 16MB flash size ESP32-S3 aka opendtufusion +* prevent duplicate alarms, update end time once it is received ## 0.8.127 - 2024-06-21 * add grid file #1677 diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index b72ec5ab..e1b99bc8 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -670,7 +670,6 @@ class Inverter { DPRINTLN(DBG_DEBUG, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(start) + ", end: " + ah::getTimeStr(endTime)); addAlarm(pyld[startOff+1], start, endTime); - alarmCnt++; alarmLastId = alarmMesIndex; return pyld[startOff+1]; @@ -818,6 +817,26 @@ class Inverter { private: inline void addAlarm(uint16_t code, uint32_t start, uint32_t end) { + bool found = false; + uint8_t i = 0; + + if(start > end) + end = 0; + + for(; i < 10; i++) { + mAlarmNxtWrPos = (++mAlarmNxtWrPos) % 10; + + if(lastAlarm[mAlarmNxtWrPos].code == code && lastAlarm[mAlarmNxtWrPos].start == start) { + // replace with same or update end time + if(lastAlarm[mAlarmNxtWrPos].end == 0 || lastAlarm[mAlarmNxtWrPos].end == end) { + break; + } + } + } + + if(alarmCnt < 10 && alarmCnt < mAlarmNxtWrPos) + alarmCnt = mAlarmNxtWrPos + 1; + lastAlarm[mAlarmNxtWrPos] = alarm_t(code, start, end); if(++mAlarmNxtWrPos >= 10) // rolling buffer mAlarmNxtWrPos = 0; diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html index 0fdaf89e..507a6f9f 100644 --- a/src/web/html/visualization.html +++ b/src/web/html/visualization.html @@ -276,7 +276,7 @@ ml("div", {class: "col mt-3"}, String(a.str)), ml("div", {class: "col mt-3"}, String(a.code)), ml("div", {class: "col mt-3"}, String(toIsoTimeStr(new Date((a.start + offs) * 1000)))), - ml("div", {class: "col mt-3"}, String(toIsoTimeStr(new Date((a.end + offs) * 1000)))) + ml("div", {class: "col mt-3"}, (a.end == 0) ? "-" : String(toIsoTimeStr(new Date((a.end + offs) * 1000)))) ]) ); } From 3c0c8eece32b45b553a4c08456d346f0d2078504 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 11 Jul 2024 22:20:11 +0200 Subject: [PATCH 167/201] 0.8.129 * sort alarms ascending #1471 * fix alarm counter for first alarm * prevent add inverter multiple times #1700 --- src/CHANGES.md | 7 ++++++- src/defines.h | 2 +- src/hm/hmInverter.h | 2 +- src/web/RestApi.h | 34 +++++++++++++++++++++++++++++----- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index dfd4ca2a..c60bd5c4 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,8 +1,13 @@ # Development Changes +## 0.8.129 - 2024-07-11 +* sort alarms ascending #1471 +* fix alarm counter for first alarm +* prevent add inverter multiple times #1700 + ## 0.8.128 - 2024-07-10 * add environments for 16MB flash size ESP32-S3 aka opendtufusion -* prevent duplicate alarms, update end time once it is received +* prevent duplicate alarms, update end time once it is received #1471 ## 0.8.127 - 2024-06-21 * add grid file #1677 diff --git a/src/defines.h b/src/defines.h index fae033d7..5914daa2 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 128 +#define VERSION_PATCH 129 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index e1b99bc8..ff3ff9c5 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -834,7 +834,7 @@ class Inverter { } } - if(alarmCnt < 10 && alarmCnt < mAlarmNxtWrPos) + if(alarmCnt < 10 && alarmCnt <= mAlarmNxtWrPos) alarmCnt = mAlarmNxtWrPos + 1; lastAlarm[mAlarmNxtWrPos] = alarm_t(code, start, end); diff --git a/src/web/RestApi.h b/src/web/RestApi.h index d1f130d4..e02f186a 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -704,11 +704,23 @@ class RestApi { obj[F("last_id")] = iv->getChannelFieldValue(CH0, FLD_EVT, rec); JsonArray alarm = obj.createNestedArray(F("alarm")); + + // find oldest alarm + uint8_t offset = 0; + uint32_t oldestStart = 0xffffffff; + for(uint8_t i = 0; i < 10; i++) { + if((iv->lastAlarm[i].start != 0) && (iv->lastAlarm[i].start < oldestStart)) { + offset = i; + oldestStart = iv->lastAlarm[i].start; + } + } + for(uint8_t i = 0; i < 10; i++) { - alarm[i][F("code")] = iv->lastAlarm[i].code; - alarm[i][F("str")] = iv->getAlarmStr(iv->lastAlarm[i].code); - alarm[i][F("start")] = iv->lastAlarm[i].start; - alarm[i][F("end")] = iv->lastAlarm[i].end; + uint8_t pos = (i + offset) % 10; + alarm[pos][F("code")] = iv->lastAlarm[pos].code; + alarm[pos][F("str")] = iv->getAlarmStr(iv->lastAlarm[pos].code); + alarm[pos][F("start")] = iv->lastAlarm[pos].start; + alarm[pos][F("end")] = iv->lastAlarm[pos].end; } } @@ -1105,7 +1117,19 @@ class RestApi { } #endif /* !defined(ETHERNET */ else if(F("save_iv") == jsonIn[F("cmd")]) { - Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")], false); + Inverter<> *iv; + + for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { + iv = mSys->getInverterByPos(jsonIn[F("id")], true); + if(nullptr != iv) { + if((i != jsonIn[F("id")]) && (iv->config->serial.u64 == jsonIn[F("ser")])) { + jsonOut[F("error")] = F("ERR_DUPLICATE_INVERTER"); + return false; + } + } + } + + iv = mSys->getInverterByPos(jsonIn[F("id")], false); iv->config->enabled = jsonIn[F("en")]; iv->config->serial.u64 = jsonIn[F("ser")]; snprintf(iv->config->name, MAX_NAME_LENGTH, "%s", jsonIn[F("name")].as()); From 8d787f2d0d653a5e84d49898a672910e648c895b Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 12 Jul 2024 22:59:26 +0200 Subject: [PATCH 168/201] update espressif idf to 6.7.0 --- src/platformio.ini | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/platformio.ini b/src/platformio.ini index 7a75420b..c5df5512 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -149,7 +149,7 @@ monitor_filters = esp8266_exception_decoder [env:esp32-wroom32-minimal] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = lolin_d32 build_flags = ${env.build_flags} -DSPI_HAL @@ -157,7 +157,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = lolin_d32 build_flags = ${env:esp32-wroom32-minimal.build_flags} -DUSE_HSPI_FOR_EPD @@ -168,7 +168,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-de] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = lolin_d32 build_flags = ${env:esp32-wroom32.build_flags} -DLANG_DE @@ -176,7 +176,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-prometheus] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = lolin_d32 build_flags = ${env:esp32-wroom32.build_flags} -DENABLE_PROMETHEUS_EP @@ -184,7 +184,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-prometheus-de] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = lolin_d32 build_flags = ${env:esp32-wroom32-prometheus.build_flags} -DLANG_DE @@ -220,7 +220,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-s2-mini] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = lolin_s2_mini build_flags = ${env.build_flags} -DUSE_HSPI_FOR_EPD @@ -243,7 +243,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-s2-mini-de] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = lolin_s2_mini build_flags = ${env:esp32-s2-mini.build_flags} -DLANG_DE @@ -251,7 +251,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-c3-mini] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = lolin_c3_mini build_flags = ${env.build_flags} -DUSE_HSPI_FOR_EPD @@ -274,7 +274,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-c3-mini-de] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = lolin_c3_mini build_flags = ${env:esp32-c3-mini.build_flags} -DLANG_DE @@ -282,7 +282,7 @@ monitor_filters = esp32_exception_decoder [env:opendtufusion-minimal] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env.build_flags} @@ -307,7 +307,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-minimal.build_flags} @@ -318,7 +318,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-de] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion.build_flags} @@ -327,7 +327,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-ethernet] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-minimal.build_flags} @@ -346,7 +346,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-ethernet-de] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-ethernet.build_flags} @@ -355,7 +355,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-16MB] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = esp32-s3-devkitc-1 board_upload.flash_size = 16MB upload_protocol = esp-builtin @@ -364,7 +364,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-16MB-de] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-16MB.build_flags} @@ -373,7 +373,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-ethernet-16MB] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = esp32-s3-devkitc-1 board_upload.flash_size = 16MB upload_protocol = esp-builtin @@ -382,7 +382,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-ethernet-16MB-de] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-ethernet-16MB.build_flags} From 81d336f9f273ff7ef79362f1b4fa7ade7a63b86f Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 12 Jul 2024 23:09:58 +0200 Subject: [PATCH 169/201] update json library --- src/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platformio.ini b/src/platformio.ini index c5df5512..ffdbd1f7 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -30,7 +30,7 @@ lib_deps = https://github.com/nRF24/RF24.git#v1.4.8 paulstoffregen/Time @ ^1.6.1 https://github.com/bertmelis/espMqttClient#v1.7.0 - bblanchon/ArduinoJson @ ^6.21.3 + bblanchon/ArduinoJson @ ^6.21.5 https://github.com/JChristensen/Timezone @ ^1.2.4 olikraus/U8g2 @ ^2.35.9 https://github.com/zinggjm/GxEPD2#1.5.3 From 8d3f372d7e5cfb20a4e253c3a2bd1013b5601352 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 12 Jul 2024 23:54:24 +0200 Subject: [PATCH 170/201] wifi_init_default: netstack cb reg failed with 12308 --- src/config/settings.h | 6 ------ src/network/AhoyEthernet.h | 3 +-- src/network/AhoyWifiEsp32.h | 1 + 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/config/settings.h b/src/config/settings.h index dabba080..e43153d9 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -409,13 +409,11 @@ class settings { // restore temp settings if(keepWifi) memcpy(&mCfg.sys, &tmp, sizeof(cfgSys_t)); - #if !defined(ETHERNET) else { snprintf(mCfg.sys.stationSsid, SSID_LEN, FB_WIFI_SSID); snprintf(mCfg.sys.stationPwd, PWD_LEN, FB_WIFI_PWD); mCfg.sys.isHidden = false; } - #endif snprintf(mCfg.sys.apPwd, PWD_LEN, WIFI_AP_PWD); #if defined(ETHERNET) @@ -570,12 +568,10 @@ class settings { void jsonNetwork(JsonObject obj, bool set = false) { if(set) { char buf[16]; - #if !defined(ETHERNET) obj[F("ssid")] = mCfg.sys.stationSsid; obj[F("pwd")] = mCfg.sys.stationPwd; obj[F("ap_pwd")] = mCfg.sys.apPwd; obj[F("hidd")] = (bool) mCfg.sys.isHidden; - #endif /* !defined(ETHERNET) */ obj[F("dev")] = mCfg.sys.deviceName; obj[F("adm")] = mCfg.sys.adminPwd; obj[F("prot_mask")] = mCfg.sys.protectionMask; @@ -599,12 +595,10 @@ class settings { obj[F("rst")] = mCfg.sys.eth.pinRst; #endif } else { - #if !defined(ETHERNET) getChar(obj, F("ssid"), mCfg.sys.stationSsid, SSID_LEN); getChar(obj, F("pwd"), mCfg.sys.stationPwd, PWD_LEN); getChar(obj, F("ap_pwd"), mCfg.sys.apPwd, PWD_LEN); getVal(obj, F("hidd"), &mCfg.sys.isHidden); - #endif /* !defined(ETHERNET) */ getChar(obj, F("dev"), mCfg.sys.deviceName, DEVNAME_LEN); getChar(obj, F("adm"), mCfg.sys.adminPwd, PWD_LEN); getVal(obj, F("prot_mask"), &mCfg.sys.protectionMask); diff --git a/src/network/AhoyEthernet.h b/src/network/AhoyEthernet.h index 8d623444..5d59eb3c 100644 --- a/src/network/AhoyEthernet.h +++ b/src/network/AhoyEthernet.h @@ -25,14 +25,13 @@ class AhoyEthernet : public AhoyWifi { void begin() override { mMode = Mode::WIRELESS; mAp.enable(); + AhoyWifi::begin(); if(!mConfig->sys.eth.enabled) return; mEthSpi.begin(mConfig->sys.eth.pinMiso, mConfig->sys.eth.pinMosi, mConfig->sys.eth.pinSclk, mConfig->sys.eth.pinCs, mConfig->sys.eth.pinIrq, mConfig->sys.eth.pinRst); ETH.setHostname(mConfig->sys.deviceName); - - AhoyWifi::begin(); } void OnEvent(WiFiEvent_t event) { diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index aff2071a..f4792eab 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -20,6 +20,7 @@ class AhoyWifi : public AhoyNetwork { if(strlen(mConfig->sys.stationSsid) == 0) return; // no station wifi defined + WiFi.disconnect(); // clean up WiFi.setHostname(mConfig->sys.deviceName); #if !defined(AP_ONLY) From 440d7748b9fefc8333a2067e92014b22b877d754 Mon Sep 17 00:00:00 2001 From: you69man Date: Thu, 18 Jul 2024 20:50:53 +0200 Subject: [PATCH 171/201] reduce update cycle of ePaper from 5 to 10 seconds ... and fix calls to mEpaper.fullRefresh() and mEpaper.tickerSecond() if no ePaper is configured --- src/plugins/Display/Display.h | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/plugins/Display/Display.h b/src/plugins/Display/Display.h index 0ce1522c..844e403a 100644 --- a/src/plugins/Display/Display.h +++ b/src/plugins/Display/Display.h @@ -79,16 +79,25 @@ class Display { void tickerSecond() { bool request_refresh = false; - if (mMono != NULL) + if (mMono != NULL) { + // maintain LCD and OLED displays with pixel shift screensavers, at least every 5 seconds request_refresh = mMono->loop(motionSensorActive()); - - if (mNewPayload || (((++mLoopCnt) % 5) == 0) || request_refresh) { - DataScreen(); - mNewPayload = false; - mLoopCnt = 0; - } + if (mNewPayload || (((++mLoopCnt) % 5) == 0) || request_refresh) { + DataScreen(); + mNewPayload = false; + mLoopCnt = 0; + } + } #if defined(ESP32) && !defined(ETHERNET) + else if (DISP_TYPE_T10_EPAPER == mCfg->type) { + // maintain ePaper at least every 10 seconds + if (mNewPayload || (((++mLoopCnt) % 10) == 0)) { + DataScreen(); + mNewPayload = false; + mLoopCnt = 0; + } mEpaper.tickerSecond(); + } #endif } @@ -180,12 +189,14 @@ class Display { else if (DISP_TYPE_T10_EPAPER == mCfg->type) { mEpaper.loop((totalPower), totalYieldDay, totalYieldTotal, nrprod); mRefreshCycle++; - } - if (mRefreshCycle > 480) { - mEpaper.fullRefresh(); - mRefreshCycle = 0; + if (mRefreshCycle > 480) { + mEpaper.fullRefresh(); + mRefreshCycle = 0; + } + } + #endif } From ae23f15486576e1fda406b26b81853722593619a Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Fri, 26 Jul 2024 17:41:33 +0200 Subject: [PATCH 172/201] smal fix - Update setup.html some small fixes: - input type wrong (come in this commit in: https://github.com/tictrick/ahoy/commit/a44a5833cae9f1c49134e72a315e892844693d43) --- 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 95777c45..4fade8f5 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -245,7 +245,7 @@

{#MQTT_NOTE}

{#INTERVAL}
-
+
Discovery Config (homeassistant)
From b7703a11b5d86349855c7977e3fe12b8af5bf498 Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Fri, 26 Jul 2024 17:44:11 +0200 Subject: [PATCH 173/201] fix (c) footer.html --- src/web/html/includes/footer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/html/includes/footer.html b/src/web/html/includes/footer.html index 6aa89673..ce0c6852 100644 --- a/src/web/html/includes/footer.html +++ b/src/web/html/includes/footer.html @@ -1,6 +1,6 @@