diff --git a/src/.vscode/settings.json b/src/.vscode/settings.json index fa166086..8930e87f 100644 --- a/src/.vscode/settings.json +++ b/src/.vscode/settings.json @@ -84,5 +84,5 @@ }, "cmake.configureOnOpen": false, "editor.formatOnSave": false, - "cmake.sourceDirectory": "C:/lpusch/github/ahoy/src/.pio/libdeps/esp32-wroom32-release-prometheus/Adafruit BusIO", -} \ No newline at end of file + "cmake.sourceDirectory": "C:/lpusch/github/ahoy/src/.pio/libdeps/esp32-wroom32-release-prometheus/Adafruit BusIO" +} diff --git a/src/CHANGES.md b/src/CHANGES.md index 23f0e685..a20c20be 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 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 diff --git a/src/app.cpp b/src/app.cpp index feeffc57..7ef64b45 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -143,22 +143,20 @@ void app::loop(void) { esp_task_wdt_reset(); if(mConfig->nrf.enabled) - mNrfActive = mNrfRadio.loop(); + mNrfRadio.loop(); - if(!mNrfActive) { - #if defined(ESP32) - if(mConfig->cmt.enabled) - mNrfActive = mCmtRadio.loop(); - #endif + #if defined(ESP32) + if(mConfig->cmt.enabled) + mCmtRadio.loop(); + #endif - ah::Scheduler::loop(); - mCommunication.loop(); + ah::Scheduler::loop(); + mCommunication.loop(); - #if defined(ENABLE_MQTT) - if (mMqttEnabled && mNetworkConnected) - mMqtt.loop(); - #endif - } + #if defined(ENABLE_MQTT) + if (mMqttEnabled && mNetworkConnected) + mMqtt.loop(); + #endif yield(); } diff --git a/src/app.h b/src/app.h index 7922edfb..2f965087 100644 --- a/src/app.h +++ b/src/app.h @@ -82,7 +82,7 @@ class app : public IApp, public ah::Scheduler { ~app() {} void setup(void); - void loop(void); + void loop(void) override; void onNetwork(bool gotIp); void regularTickers(void); @@ -405,7 +405,6 @@ class app : public IApp, public ah::Scheduler { uint8_t mSendLastIvId; bool mSendFirst; bool mAllIvNotAvail; - bool mNrfActive = false; bool mNetworkConnected; diff --git a/src/config/settings.h b/src/config/settings.h index ee9615c1..d8c93b10 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -824,8 +824,10 @@ class settings { #if defined(ESP32) void getChar(JsonObject obj, const char *key, char *dst, int maxLen) { - if(obj.containsKey(key)) + if(obj.containsKey(key)) { snprintf(dst, maxLen, "%s", obj[key].as()); + dst[maxLen-1] = '\0'; + } } template @@ -835,8 +837,10 @@ class settings { } #else void getChar(JsonObject obj, const __FlashStringHelper *key, char *dst, int maxLen) { - if(obj.containsKey(key)) + if(obj.containsKey(key)) { snprintf(dst, maxLen, "%s", obj[key].as()); + dst[maxLen-1] = '\0'; + } } template diff --git a/src/defines.h b/src/defines.h index c614103e..77ea6726 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 62 +#define VERSION_PATCH 63 //------------------------------------- typedef struct { diff --git a/src/eth/ahoyeth.h b/src/eth/ahoyeth.h index 157a9c76..ef8d0751 100644 --- a/src/eth/ahoyeth.h +++ b/src/eth/ahoyeth.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- -// 2023 Ahoy, https://www.mikrocontroller.net/topic/525778 -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// 2024 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #if defined(ETHERNET) @@ -49,7 +49,7 @@ class ahoyeth { #if defined(CONFIG_IDF_TARGET_ESP32S3) EthSpi mEthSpi; #endif - settings_t *mConfig; + settings_t *mConfig = NULL; uint32_t *mUtcTimestamp; AsyncUDP mUdp; // for time server diff --git a/src/hm/nrfHal.h b/src/hm/nrfHal.h index c9fbcdc7..0532a524 100644 --- a/src/hm/nrfHal.h +++ b/src/hm/nrfHal.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- -// 2023 Ahoy, https://www.mikrocontroller.net/topic/525778 -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// 2024 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #ifndef __NRF_HAL_H__ @@ -144,6 +144,8 @@ class nrfHal: public RF24_hal, public SpiPatcherHandle { uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t len) override { uint8_t data[NRF_MAX_TRANSFER_SZ]; data[0] = cmd; + if(len > NRF_MAX_TRANSFER_SZ) + len = NRF_MAX_TRANSFER_SZ; memset(&data[1], 0xff, len); request_spi(); @@ -168,13 +170,16 @@ class nrfHal: public RF24_hal, public SpiPatcherHandle { } uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t data_len, uint8_t blank_len) override { - uint8_t data[NRF_MAX_TRANSFER_SZ]; + uint8_t data[NRF_MAX_TRANSFER_SZ + 1]; + uint8_t len = data_len + blank_len; data[0] = cmd; - memset(&data[1], 0xff, (data_len + blank_len)); + if(len > (NRF_MAX_TRANSFER_SZ + 1)) + len = (NRF_MAX_TRANSFER_SZ + 1); + memset(&data[1], 0xff, len); request_spi(); - size_t spiLen = (static_cast(data_len) + static_cast(blank_len) + 1u) << 3; + size_t spiLen = (static_cast(len) + 1u) << 3; spi_transaction_t t = { .flags = 0, .cmd = 0, diff --git a/src/plugins/Display/Display.h b/src/plugins/Display/Display.h index 6b7fa12b..862e452b 100644 --- a/src/plugins/Display/Display.h +++ b/src/plugins/Display/Display.h @@ -19,226 +19,226 @@ template class Display { - public: - Display() { - mMono = NULL; - } - - void setup(IApp *app, display_t *cfg, HMSYSTEM *sys, RADIO *hmradio, RADIO *hmsradio, uint32_t *utcTs) { - mApp = app; - mHmRadio = hmradio; - mHmsRadio = hmsradio; - mCfg = cfg; - mSys = sys; - mUtcTs = utcTs; - mNewPayload = false; - mLoopCnt = 0; - - mDisplayData.version = app->getVersion(); // version never changes, so only set once - - switch (mCfg->type) { - case DISP_TYPE_T0_NONE: mMono = NULL; break; // None - case DISP_TYPE_T1_SSD1306_128X64: mMono = new DisplayMono128X64(); break; // SSD1306_128X64 (0.96", 1.54") - case DISP_TYPE_T2_SH1106_128X64: mMono = new DisplayMono128X64(); break; // SH1106_128X64 (1.3") - case DISP_TYPE_T3_PCD8544_84X48: mMono = new DisplayMono84X48(); break; // PCD8544_84X48 (1.6" - Nokia 5110) - case DISP_TYPE_T4_SSD1306_128X32: mMono = new DisplayMono128X32(); break; // SSD1306_128X32 (0.91") - case DISP_TYPE_T5_SSD1306_64X48: mMono = new DisplayMono64X48(); break; // SSD1306_64X48 (0.66" - Wemos OLED Shield) - case DISP_TYPE_T6_SSD1309_128X64: mMono = new DisplayMono128X64(); break; // SSD1309_128X64 (2.42") -#if defined(ESP32) && !defined(ETHERNET) - case DISP_TYPE_T10_EPAPER: - mMono = NULL; // ePaper does not use this - mRefreshCycle = 0; - mEpaper.config(mCfg->rot, mCfg->pwrSaveAtIvOffline); - mEpaper.init(mCfg->type, mCfg->disp_cs, mCfg->disp_dc, mCfg->disp_reset, mCfg->disp_busy, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mDisplayData.version); - break; -#endif - default: mMono = NULL; break; - } - if(mMono) { - mMono->config(mCfg); - mMono->init(&mDisplayData); + public: + Display() { + mMono = NULL; } - // setup PIR pin for motion sensor -#ifdef ESP32 - if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF)) - pinMode(mCfg->pirPin, INPUT); -#endif -#ifdef ESP8266 - if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF) && (mCfg->pirPin != A0)) - pinMode(mCfg->pirPin, INPUT); -#endif - - } + void setup(IApp *app, display_t *cfg, HMSYSTEM *sys, RADIO *hmradio, RADIO *hmsradio, uint32_t *utcTs) { + mApp = app; + mHmRadio = hmradio; + mHmsRadio = hmsradio; + mCfg = cfg; + mSys = sys; + mUtcTs = utcTs; + mNewPayload = false; + mLoopCnt = 0; - void payloadEventListener(uint8_t cmd) { - mNewPayload = true; - } + mDisplayData.version = app->getVersion(); // version never changes, so only set once + + switch (mCfg->type) { + case DISP_TYPE_T0_NONE: mMono = NULL; break; // None + case DISP_TYPE_T1_SSD1306_128X64: mMono = new DisplayMono128X64(); break; // SSD1306_128X64 (0.96", 1.54") + case DISP_TYPE_T2_SH1106_128X64: mMono = new DisplayMono128X64(); break; // SH1106_128X64 (1.3") + case DISP_TYPE_T3_PCD8544_84X48: mMono = new DisplayMono84X48(); break; // PCD8544_84X48 (1.6" - Nokia 5110) + case DISP_TYPE_T4_SSD1306_128X32: mMono = new DisplayMono128X32(); break; // SSD1306_128X32 (0.91") + case DISP_TYPE_T5_SSD1306_64X48: mMono = new DisplayMono64X48(); break; // SSD1306_64X48 (0.66" - Wemos OLED Shield) + case DISP_TYPE_T6_SSD1309_128X64: mMono = new DisplayMono128X64(); break; // SSD1309_128X64 (2.42") + #if defined(ESP32) && !defined(ETHERNET) + case DISP_TYPE_T10_EPAPER: + mMono = NULL; // ePaper does not use this + mRefreshCycle = 0; + mEpaper.config(mCfg->rot, mCfg->pwrSaveAtIvOffline); + mEpaper.init(mCfg->type, mCfg->disp_cs, mCfg->disp_dc, mCfg->disp_reset, mCfg->disp_busy, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mDisplayData.version); + break; + #endif + default: mMono = NULL; break; + } + if(mMono) { + mMono->config(mCfg); + mMono->init(&mDisplayData); + } - void tickerSecond() { - bool request_refresh = false; + // setup PIR pin for motion sensor + #ifdef ESP32 + if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF)) + pinMode(mCfg->pirPin, INPUT); + #endif + #ifdef ESP8266 + if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF) && (mCfg->pirPin != A0)) + pinMode(mCfg->pirPin, INPUT); + #endif - if (mMono != NULL) - request_refresh = mMono->loop(motionSensorActive()); + } - if (mNewPayload || (((++mLoopCnt) % 5) == 0) || request_refresh) { - DataScreen(); - mNewPayload = false; - mLoopCnt = 0; + void payloadEventListener(uint8_t cmd) { + mNewPayload = true; } - #if defined(ESP32) && !defined(ETHERNET) - mEpaper.tickerSecond(); - #endif - } - private: - void DataScreen() { - if (DISP_TYPE_T0_NONE == mCfg->type) - return; - - float totalPower = 0.0; - float totalYieldDay = 0.0; - float totalYieldTotal = 0.0; - - uint8_t nrprod = 0; - uint8_t nrsleep = 0; - int8_t minQAllInv = 4; - - Inverter<> *iv; - record_t<> *rec; - bool allOff = true; - uint8_t nInv = mSys->getNumInverters(); - for (uint8_t i = 0; i < nInv; i++) { - iv = mSys->getInverterByPos(i); - if (iv == NULL) - continue; - - if (iv->isProducing()) // also updates inverter state engine - nrprod++; - else - nrsleep++; + void tickerSecond() { + bool request_refresh = false; - rec = iv->getRecordStruct(RealTimeRunData_Debug); + if (mMono != NULL) + request_refresh = mMono->loop(motionSensorActive()); - if (iv->isAvailable()) { // consider only radio quality of inverters still communicating - int8_t maxQInv = -6; - for(uint8_t ch = 0; ch < RF_MAX_CHANNEL_ID; ch++) { - int8_t q = iv->heuristics.txRfQuality[ch]; - if (q > maxQInv) - maxQInv = q; + if (mNewPayload || (((++mLoopCnt) % 5) == 0) || request_refresh) { + DataScreen(); + mNewPayload = false; + mLoopCnt = 0; + } + #if defined(ESP32) && !defined(ETHERNET) + mEpaper.tickerSecond(); + #endif + } + + private: + void DataScreen() { + if (DISP_TYPE_T0_NONE == mCfg->type) + return; + + float totalPower = 0.0; + float totalYieldDay = 0.0; + float totalYieldTotal = 0.0; + + uint8_t nrprod = 0; + uint8_t nrsleep = 0; + int8_t minQAllInv = 4; + + Inverter<> *iv; + record_t<> *rec; + bool allOff = true; + uint8_t nInv = mSys->getNumInverters(); + for (uint8_t i = 0; i < nInv; i++) { + iv = mSys->getInverterByPos(i); + if (iv == NULL) + continue; + + if (iv->isProducing()) // also updates inverter state engine + nrprod++; + else + nrsleep++; + + rec = iv->getRecordStruct(RealTimeRunData_Debug); + + if (iv->isAvailable()) { // consider only radio quality of inverters still communicating + int8_t maxQInv = -6; + for(uint8_t ch = 0; ch < RF_MAX_CHANNEL_ID; ch++) { + int8_t q = iv->heuristics.txRfQuality[ch]; + if (q > maxQInv) + maxQInv = q; + } + if (maxQInv < minQAllInv) + minQAllInv = maxQInv; + + totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec); // add only FLD_PAC from inverters still communicating + allOff = false; } - if (maxQInv < minQAllInv) - minQAllInv = maxQInv; - totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec); // add only FLD_PAC from inverters still communicating - allOff = false; + totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec); + totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec); } - totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec); - totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec); - } + if (allOff) + minQAllInv = -6; + + // prepare display data + mDisplayData.nrProducing = nrprod; + mDisplayData.nrSleeping = nrsleep; + mDisplayData.totalPower = totalPower; + mDisplayData.totalYieldDay = totalYieldDay; + mDisplayData.totalYieldTotal = totalYieldTotal; + bool nrf_en = mApp->getNrfEnabled(); + bool nrf_ok = nrf_en && mHmRadio->isChipConnected(); + #if defined(ESP32) + bool cmt_en = mApp->getCmtEnabled(); + bool cmt_ok = cmt_en && mHmsRadio->isChipConnected(); + #else + bool cmt_en = false; + bool cmt_ok = false; + #endif + mDisplayData.RadioSymbol = (nrf_ok && !cmt_en) || (cmt_ok && !nrf_en) || (nrf_ok && cmt_ok); + mDisplayData.WifiSymbol = (WiFi.status() == WL_CONNECTED); + mDisplayData.MQTTSymbol = mApp->getMqttIsConnected(); + mDisplayData.RadioRSSI = ivQuality2RadioRSSI(minQAllInv); // Workaround as NRF24 has no RSSI. Approximation by quality levels from heuristic function + mDisplayData.WifiRSSI = (WiFi.status() == WL_CONNECTED) ? WiFi.RSSI() : SCHAR_MIN; + mDisplayData.ipAddress = WiFi.localIP(); + + // provide localized times to display classes + time_t utc= mApp->getTimestamp(); + if (year(utc) > 2020) + mDisplayData.utcTs = gTimezone.toLocal(utc); + else + mDisplayData.utcTs = 0; + mDisplayData.pGraphStartTime = gTimezone.toLocal(mApp->getSunrise()); + mDisplayData.pGraphEndTime = gTimezone.toLocal(mApp->getSunset()); - if (allOff) - minQAllInv = -6; - - // prepare display data - mDisplayData.nrProducing = nrprod; - mDisplayData.nrSleeping = nrsleep; - mDisplayData.totalPower = totalPower; - mDisplayData.totalYieldDay = totalYieldDay; - mDisplayData.totalYieldTotal = totalYieldTotal; - bool nrf_en = mApp->getNrfEnabled(); - bool nrf_ok = nrf_en && mHmRadio->isChipConnected(); - #if defined(ESP32) - bool cmt_en = mApp->getCmtEnabled(); - bool cmt_ok = cmt_en && mHmsRadio->isChipConnected(); - #else - bool cmt_en = false; - bool cmt_ok = false; - #endif - mDisplayData.RadioSymbol = (nrf_ok && !cmt_en) || (cmt_ok && !nrf_en) || (nrf_ok && cmt_ok); - mDisplayData.WifiSymbol = (WiFi.status() == WL_CONNECTED); - mDisplayData.MQTTSymbol = mApp->getMqttIsConnected(); - mDisplayData.RadioRSSI = ivQuality2RadioRSSI(minQAllInv); // Workaround as NRF24 has no RSSI. Approximation by quality levels from heuristic function - mDisplayData.WifiRSSI = (WiFi.status() == WL_CONNECTED) ? WiFi.RSSI() : SCHAR_MIN; - mDisplayData.ipAddress = WiFi.localIP(); - - // provide localized times to display classes - time_t utc= mApp->getTimestamp(); - if (year(utc) > 2020) - mDisplayData.utcTs = gTimezone.toLocal(utc); - else - mDisplayData.utcTs = 0; - mDisplayData.pGraphStartTime = gTimezone.toLocal(mApp->getSunrise()); - mDisplayData.pGraphEndTime = gTimezone.toLocal(mApp->getSunset()); - - if (mMono ) { - mMono->disp(); - } -#if defined(ESP32) && !defined(ETHERNET) - else if (DISP_TYPE_T10_EPAPER == mCfg->type) { - mEpaper.loop((totalPower), totalYieldDay, totalYieldTotal, nrprod); - mRefreshCycle++; - } + if (mMono ) { + mMono->disp(); + } + #if defined(ESP32) && !defined(ETHERNET) + 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 } -#endif - } - - bool motionSensorActive() { - if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF)) { -#if defined(ESP8266) - if (mCfg->pirPin == A0) - return((analogRead(A0) >= 512)); - else + + bool motionSensorActive() { + if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF)) { + #if defined(ESP8266) + if (mCfg->pirPin == A0) + return((analogRead(A0) >= 512)); + else + return(digitalRead(mCfg->pirPin)); + #elif defined(ESP32) return(digitalRead(mCfg->pirPin)); -#elif defined(ESP32) - return(digitalRead(mCfg->pirPin)); -#endif + #endif + } + else + return(false); } - else - return(false); - } - - // approximate RSSI in dB by invQuality levels from heuristic function (very unscientific but better than nothing :-) ) - int8_t ivQuality2RadioRSSI(int8_t invQuality) { - int8_t pseudoRSSIdB; - switch(invQuality) { - case 4: pseudoRSSIdB = -55; break; - case 3: - case 2: - case 1: pseudoRSSIdB = -65; break; - case 0: - case -1: - case -2: pseudoRSSIdB = -75; break; - case -3: - case -4: - case -5: pseudoRSSIdB = -85; break; - case -6: - default: pseudoRSSIdB = -95; break; + + // approximate RSSI in dB by invQuality levels from heuristic function (very unscientific but better than nothing :-) ) + int8_t ivQuality2RadioRSSI(int8_t invQuality) { + int8_t pseudoRSSIdB; + switch(invQuality) { + case 4: pseudoRSSIdB = -55; break; + case 3: + case 2: + case 1: pseudoRSSIdB = -65; break; + case 0: + case -1: + case -2: pseudoRSSIdB = -75; break; + case -3: + case -4: + case -5: pseudoRSSIdB = -85; break; + case -6: + default: pseudoRSSIdB = -95; break; + } + return (pseudoRSSIdB); } - return (pseudoRSSIdB); - } - - // private member variables - IApp *mApp; - DisplayData mDisplayData; - bool mNewPayload; - uint8_t mLoopCnt; - uint32_t *mUtcTs; - display_t *mCfg; - HMSYSTEM *mSys; - RADIO *mHmRadio; - RADIO *mHmsRadio; - uint16_t mRefreshCycle; - -#if defined(ESP32) && !defined(ETHERNET) - DisplayEPaper mEpaper; -#endif - DisplayMono *mMono; + + // private member variables + IApp *mApp; + DisplayData mDisplayData; + bool mNewPayload; + uint8_t mLoopCnt; + uint32_t *mUtcTs; + display_t *mCfg; + HMSYSTEM *mSys; + RADIO *mHmRadio; + RADIO *mHmsRadio; + uint16_t mRefreshCycle; + + #if defined(ESP32) && !defined(ETHERNET) + DisplayEPaper mEpaper; + #endif + DisplayMono *mMono; }; #endif /*PLUGIN_DISPLAY*/ diff --git a/src/plugins/Display/Display_ePaper.cpp b/src/plugins/Display/Display_ePaper.cpp index 964034ea..fdcec767 100644 --- a/src/plugins/Display/Display_ePaper.cpp +++ b/src/plugins/Display/Display_ePaper.cpp @@ -20,6 +20,7 @@ SPIClass hspi(HSPI); DisplayEPaper::DisplayEPaper() { mDisplayRotation = 2; mHeadFootPadding = 16; + memset(_fmtText, 0, EPAPER_MAX_TEXT_LEN); } @@ -114,9 +115,9 @@ void DisplayEPaper::headlineIP() { do { if ((WiFi.isConnected() == true) && (WiFi.localIP() > 0)) { - snprintf(_fmtText, sizeof(_fmtText), "%s", WiFi.localIP().toString().c_str()); + snprintf(_fmtText, EPAPER_MAX_TEXT_LEN, "%s", WiFi.localIP().toString().c_str()); } else { - snprintf(_fmtText, sizeof(_fmtText), "WiFi not connected"); + snprintf(_fmtText, EPAPER_MAX_TEXT_LEN, "WiFi not connected"); } _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); uint16_t x = ((_display->width() - tbw) / 2) - tbx; @@ -137,7 +138,7 @@ void DisplayEPaper::lastUpdatePaged() { _display->fillScreen(GxEPD_BLACK); do { if (NULL != mUtcTs) { - snprintf(_fmtText, sizeof(_fmtText), ah::getDateTimeStr(gTimezone.toLocal(*mUtcTs)).c_str()); + snprintf(_fmtText, EPAPER_MAX_TEXT_LEN, ah::getDateTimeStr(gTimezone.toLocal(*mUtcTs)).c_str()); _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); uint16_t x = ((_display->width() - tbw) / 2) - tbx; @@ -158,7 +159,7 @@ void DisplayEPaper::versionFooter() { _display->setPartialWindow(0, _display->height() - mHeadFootPadding, _display->width(), mHeadFootPadding); _display->fillScreen(GxEPD_BLACK); do { - snprintf(_fmtText, sizeof(_fmtText), "Version: %s", _version); + snprintf(_fmtText, EPAPER_MAX_TEXT_LEN, "Version: %s", _version); _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); uint16_t x = ((_display->width() - tbw) / 2) - tbx; @@ -179,7 +180,7 @@ void DisplayEPaper::offlineFooter() { _display->fillScreen(GxEPD_BLACK); do { if (NULL != mUtcTs) { - snprintf(_fmtText, sizeof(_fmtText), "offline"); + snprintf(_fmtText, EPAPER_MAX_TEXT_LEN, "offline"); _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); uint16_t x = ((_display->width() - tbw) / 2) - tbx; @@ -203,13 +204,13 @@ void DisplayEPaper::actualPowerPaged(float totalPower, float totalYieldDay, floa do { // actual Production if (totalPower > 9999) { - snprintf(_fmtText, sizeof(_fmtText), "%.1f kW", (totalPower / 1000)); + snprintf(_fmtText, EPAPER_MAX_TEXT_LEN, "%.1f kW", (totalPower / 1000)); _changed = true; } else if ((totalPower > 0) && (totalPower <= 9999)) { - snprintf(_fmtText, sizeof(_fmtText), "%.0f W", totalPower); + snprintf(_fmtText, EPAPER_MAX_TEXT_LEN, "%.0f W", totalPower); _changed = true; } else - snprintf(_fmtText, sizeof(_fmtText), "offline"); + snprintf(_fmtText, EPAPER_MAX_TEXT_LEN, "offline"); if ((totalPower == 0) && (mEnPowerSave)) { _display->fillRect(0, mHeadFootPadding, 200, 200, GxEPD_BLACK); @@ -264,7 +265,7 @@ void DisplayEPaper::actualPowerPaged(float totalPower, float totalYieldDay, floa // Inverter online _display->setFont(&FreeSans12pt7b); y = _display->height() - (mHeadFootPadding + 10); - snprintf(_fmtText, sizeof(_fmtText), " %d online", isprod); + snprintf(_fmtText, EPAPER_MAX_TEXT_LEN, " %d online", isprod); _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); _display->drawInvertedBitmap(10, y - tbh, myWR, 20, 20, GxEPD_BLACK); x = ((_display->width() - tbw - 20) / 2) - tbx; diff --git a/src/plugins/Display/Display_ePaper.h b/src/plugins/Display/Display_ePaper.h index 0e077601..c26d3b42 100644 --- a/src/plugins/Display/Display_ePaper.h +++ b/src/plugins/Display/Display_ePaper.h @@ -9,6 +9,8 @@ // enable GxEPD2_GFX base class #define ENABLE_GxEPD2_GFX 1 +#define EPAPER_MAX_TEXT_LEN 35 + #include #include @@ -49,7 +51,7 @@ class DisplayEPaper { uint8_t mDisplayRotation; bool _changed = false; - char _fmtText[35]; + char _fmtText[EPAPER_MAX_TEXT_LEN]; String _settedIP; uint8_t mHeadFootPadding; GxEPD2_GFX* _display; diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index bfab381b..865c76b5 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -70,8 +70,8 @@ class PubMqtt { if(strlen(mCfgMqtt->clientId) > 0) snprintf(mClientId, 23, "%s", mCfgMqtt->clientId); - else{ - snprintf(mClientId, 24, "%s-", mDevName); + else { + snprintf(mClientId, 23, "%s-", mDevName); uint8_t pos = strlen(mClientId); mClientId[pos++] = WiFi.macAddress().substring( 9, 10).c_str()[0]; mClientId[pos++] = WiFi.macAddress().substring(10, 11).c_str()[0]; @@ -308,7 +308,7 @@ class PubMqtt { bool limitAbs = false; if(len > 0) { char *pyld = new char[len + 1]; - strncpy(pyld, (const char*)payload, len); + memcpy(pyld, payload, len); pyld[len] = '\0'; if(NULL == strstr(topic, "limit")) root[F("val")] = atoi(pyld); @@ -326,7 +326,7 @@ class PubMqtt { while(1) { if(('/' == p[pos]) || ('\0' == p[pos])) { - strncpy(tmp, p, pos); + memcpy(tmp, p, pos); tmp[pos] = '\0'; switch(elm++) { case 1: root[F("path")] = String(tmp); break; diff --git a/src/utils/crc.cpp b/src/utils/crc.cpp index 6e341924..08d1f103 100644 --- a/src/utils/crc.cpp +++ b/src/utils/crc.cpp @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- -// 2022 Ahoy, https://github.com/lumpapu/ahoy -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// 2024 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #include "crc.h" @@ -19,7 +19,7 @@ namespace ah { uint16_t crc16(uint8_t buf[], uint8_t len, uint16_t start) { uint16_t crc = start; - uint8_t shift = 0; + uint8_t shift; for(uint8_t i = 0; i < len; i ++) { crc = crc ^ buf[i]; diff --git a/src/utils/improv.h b/src/utils/improv.h index 02165239..d5a9ae74 100644 --- a/src/utils/improv.h +++ b/src/utils/improv.h @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2023 Ahoy, https://github.com/lumpapu/ahoy +// 2024 Ahoy, https://github.com/lumpapu/ahoy // Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- @@ -72,10 +72,10 @@ class Improv { void dumpBuf(uint8_t buf[], uint8_t len) { for(uint8_t i = 0; i < len; i++) { - DHEX(buf[i], false); - DBGPRINT(" ", false); + DHEX(buf[i]); + DBGPRINT(F(" ")); } - DBGPRINTLN("", false); + DBGPRINTLN(""); } inline uint8_t buildChecksum(uint8_t buf[], uint8_t len) { diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h index bb393bcb..751550df 100644 --- a/src/utils/scheduler.h +++ b/src/utils/scheduler.h @@ -1,7 +1,6 @@ //----------------------------------------------------------------------------- -// 2023 Ahoy, https://ahoydtu.de -// Lukas Pusch, lukas@lpusch.de -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #ifndef __SCHEDULER_H__ @@ -40,7 +39,7 @@ namespace ah { resetTicker(); } - void loop(void) { + virtual void loop(void) { mMillis = millis(); mDiff = mMillis - mPrevMillis; if (mDiff < 1000) diff --git a/src/utils/syslog.cpp b/src/utils/syslog.cpp index 5e73f287..9c4bf93b 100644 --- a/src/utils/syslog.cpp +++ b/src/utils/syslog.cpp @@ -1,3 +1,8 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + #include #include "syslog.h" @@ -87,7 +92,7 @@ void DbgSyslog::log(const char *hostname, uint8_t facility, uint8_t severity, ch // This is a unit8 instead of a char because that's what udp.write() wants uint8_t buffer[SYSLOG_MAX_PACKET_SIZE]; - int len = snprintf((char*)buffer, SYSLOG_MAX_PACKET_SIZE, "<%d>%s %s: %s", priority, hostname, SYSLOG_APP, msg); + int len = snprintf(static_cast(buffer), SYSLOG_MAX_PACKET_SIZE, "<%d>%s %s: %s", priority, hostname, SYSLOG_APP, msg); //printf("syslog::log %s\n",mSyslogIP.toString().c_str()); //printf("syslog::log %d %s\n",len,buffer); // Send the raw UDP packet @@ -96,4 +101,4 @@ void DbgSyslog::log(const char *hostname, uint8_t facility, uint8_t severity, ch mSyslogUdp.endPacket(); } -#endif \ No newline at end of file +#endif diff --git a/src/web/html/api.js b/src/web/html/api.js index 83a009a5..5cce4206 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -1,42 +1,42 @@ /* SVG ICONS - https://icons.getbootstrap.com */ -iconWifi1 = [ +var iconWifi1 = [ "M11.046 10.454c.226-.226.185-.605-.1-.75A6.473 6.473 0 0 0 8 9c-1.06 0-2.062.254-2.946.704-.285.145-.326.524-.1.75l.015.015c.16.16.407.19.611.09A5.478 5.478 0 0 1 8 10c.868 0 1.69.201 2.42.56.203.1.45.07.611-.091l.015-.015zM9.06 12.44c.196-.196.198-.52-.04-.66A1.99 1.99 0 0 0 8 11.5a1.99 1.99 0 0 0-1.02.28c-.238.14-.236.464-.04.66l.706.706a.5.5 0 0 0 .707 0l.708-.707z" ]; -iconWifi2 = [ +var iconWifi2 = [ "M13.229 8.271c.216-.216.194-.578-.063-.745A9.456 9.456 0 0 0 8 6c-1.905 0-3.68.56-5.166 1.526a.48.48 0 0 0-.063.745.525.525 0 0 0 .652.065A8.46 8.46 0 0 1 8 7a8.46 8.46 0 0 1 4.577 1.336c.205.132.48.108.652-.065zm-2.183 2.183c.226-.226.185-.605-.1-.75A6.473 6.473 0 0 0 8 9c-1.06 0-2.062.254-2.946.704-.285.145-.326.524-.1.75l.015.015c.16.16.408.19.611.09A5.478 5.478 0 0 1 8 10c.868 0 1.69.201 2.42.56.203.1.45.07.611-.091l.015-.015zM9.06 12.44c.196-.196.198-.52-.04-.66A1.99 1.99 0 0 0 8 11.5a1.99 1.99 0 0 0-1.02.28c-.238.14-.236.464-.04.66l.706.706a.5.5 0 0 0 .708 0l.707-.707z" ]; -iconWifi3 = [ +var iconWifi3 = [ "M15.384 6.115a.485.485 0 0 0-.047-.736A12.444 12.444 0 0 0 8 3C5.259 3 2.723 3.882.663 5.379a.485.485 0 0 0-.048.736.518.518 0 0 0 .668.05A11.448 11.448 0 0 1 8 4c2.507 0 4.827.802 6.716 2.164.205.148.49.13.668-.049z", "M13.229 8.271a.482.482 0 0 0-.063-.745A9.455 9.455 0 0 0 8 6c-1.905 0-3.68.56-5.166 1.526a.48.48 0 0 0-.063.745.525.525 0 0 0 .652.065A8.46 8.46 0 0 1 8 7a8.46 8.46 0 0 1 4.576 1.336c.206.132.48.108.653-.065zm-2.183 2.183c.226-.226.185-.605-.1-.75A6.473 6.473 0 0 0 8 9c-1.06 0-2.062.254-2.946.704-.285.145-.326.524-.1.75l.015.015c.16.16.407.19.611.09A5.478 5.478 0 0 1 8 10c.868 0 1.69.201 2.42.56.203.1.45.07.61-.091l.016-.015zM9.06 12.44c.196-.196.198-.52-.04-.66A1.99 1.99 0 0 0 8 11.5a1.99 1.99 0 0 0-1.02.28c-.238.14-.236.464-.04.66l.706.706a.5.5 0 0 0 .707 0l.707-.707z" ]; -iconWarn = [ +var iconWarn = [ "M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.146.146 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.163.163 0 0 1-.054.06.116.116 0 0 1-.066.017H1.146a.115.115 0 0 1-.066-.017.163.163 0 0 1-.054-.06.176.176 0 0 1 .002-.183L7.884 2.073a.147.147 0 0 1 .054-.057zm1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566z", "M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995z" ]; -iconInfo = [ +var iconInfo = [ "M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z", "m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z" ]; -iconSuccess = [ +var iconSuccess = [ "M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z", "M10.97 4.97a.235.235 0 0 0-.02.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-1.071-1.05z" ]; -iconSuccessFull = [ +var iconSuccessFull = [ "M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z" ]; -iconGear = [ +var iconGear = [ "M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z" ]; -iconDel = [ +var iconDel = [ "M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z", "M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z" ]; diff --git a/src/web/lang.json b/src/web/lang.json index 4eee86a9..1eece937 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -280,7 +280,7 @@ }, { "token": "INV_GAP", - "en": "Communication Gap [ms]", + "en": "Communication Gap", "de": "Kommunikationslücke" }, { diff --git a/src/web/web.h b/src/web/web.h index a6db6a71..ba4540b1 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -828,10 +828,9 @@ class Web { if (0 == channel) { // Report a _total value if also channel values were reported. Otherwise report without _total char total[7]; - total[0] = 0; if (metricDeclared) { // A declaration and value for channels have been delivered. So declare and deliver a _total metric - strncpy(total,"_total",sizeof(total)); + strncpy(total, "_total", 6); } if (!metricTotalDeclard) { snprintf(type, sizeof(type), "# TYPE %s%s%s%s %s\n",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total, promType.c_str()); diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 4ab7ee92..defca5bc 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2023 Ahoy, https://ahoydtu.de +// 2024 Ahoy, https://ahoydtu.de // Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- @@ -293,7 +293,7 @@ bool ahoywifi::getNtpTime(void) { if(NTP_PACKET_SIZE <= mUdp.parsePacket()) { uint64_t secsSince1900; mUdp.read(buf, NTP_PACKET_SIZE); - secsSince1900 = (buf[40] << 24); + secsSince1900 = ((uint64_t)buf[40] << 24); secsSince1900 |= (buf[41] << 16); secsSince1900 |= (buf[42] << 8); secsSince1900 |= (buf[43] ); diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 36837600..7fb62a20 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -1,7 +1,8 @@ +//------------------------------------//----------------------------------------------------------------------------- +// 2024 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- -// 2023 Ahoy, https://www.mikrocontroller.net/topic/525778 -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ -//----------------------------------------------------------------------------- + #if !defined(ETHERNET) #ifndef __AHOYWIFI_H__ #define __AHOYWIFI_H__ @@ -66,7 +67,7 @@ class ahoywifi { void welcome(String ip, String mode); - settings_t *mConfig; + settings_t *mConfig = NULL; appWifiCb mAppWifiCb; DNSServer mDns;