From e44e72231530a818f1c949ca3b90fa7c581ebfeb Mon Sep 17 00:00:00 2001 From: rejoe2 <rejoe2@users.noreply.github.com> Date: Mon, 15 Jan 2024 13:09:23 +0100 Subject: [PATCH 1/6] MI-MQTT and last retransmit - fix MI not sending data over MQTT (discord https://discord.com/channels/984173303147155506/1144045244166443159/1196092306873397351) - change logic for last retransmit (discord https://discord.com/channels/984173303147155506/1144045244166443159/1196098984167608360) --- src/hm/CommQueue.h | 6 +++--- src/hm/Communication.h | 31 +++++++++++++++++++------------ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h index 4e73d53a..d62efe07 100644 --- a/src/hm/CommQueue.h +++ b/src/hm/CommQueue.h @@ -12,9 +12,9 @@ #include "../utils/dbg.h" // needs a '+1' because the comparison does not send if attempts is equal 0 -#define DEFAULT_ATTEMPS 5 + 1 -#define MORE_ATTEMPS_ALARMDATA 15 + 1 -#define MORE_ATTEMPS_GRIDONPROFILEPARA 15 + 1 +#define DEFAULT_ATTEMPS 5 +#define MORE_ATTEMPS_ALARMDATA 15 +#define MORE_ATTEMPS_GRIDONPROFILEPARA 15 template <uint8_t N=100> class CommQueue { diff --git a/src/hm/Communication.h b/src/hm/Communication.h index a8a46e1a..5f14a5af 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -178,11 +178,11 @@ class Communication : public CommQueue<> { yield(); } - if(0 == q->attempts) { + /*if(0 == q->attempts) { DPRINT_IVID(DBG_INFO, q->iv->id); DBGPRINT(F("no attempts left")); closeRequest(q, false); - } else { + } else {*/ if(q->iv->ivGen != IV_MI) { mState = States::CHECK_PACKAGE; } else { @@ -207,7 +207,7 @@ class Communication : public CommQueue<> { closeRequest(q, true); } } - } + //} } break; @@ -235,6 +235,12 @@ class Communication : public CommQueue<> { } if(framnr) { + if(0 == q->attempts) { + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINT(F("no attempts left")); + closeRequest(q, false); + return; + } setAttempt(); if(*mSerialDebug) { @@ -516,15 +522,15 @@ class Communication : public CommQueue<> { } void sendRetransmit(const queue_s *q, uint8_t i) { - if(q->attempts) { + //if(q->attempts) { q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (SINGLE_FRAME + i), true); q->iv->radioStatistics.retransmits++; mWaitTime.startTimeMonitor(SINGLEFR_TIMEOUT); // timeout mState = States::WAIT; - } else { + /*} else { //add(q, true); closeRequest(q, false); - } + }*/ } private: @@ -604,6 +610,8 @@ class Communication : public CommQueue<> { rec->ts = q->ts; q->iv->setValue(1, rec, (uint32_t) ((p->packet[24] << 8) + p->packet[25])/1); q->iv->miMultiParts +=4; + rec->mqttSentStatus = MqttSentStatus::NEW_DATA; + } else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10 DPRINT_IVID(DBG_INFO, q->iv->id); if ( p->packet[9] == 0x01 ) { @@ -620,6 +628,7 @@ class Communication : public CommQueue<> { record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure rec->ts = q->ts; q->iv->setValue(0, rec, (uint32_t) ((((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])/1); + rec->mqttSentStatus = MqttSentStatus::NEW_DATA; if(*mSerialDebug) { DPRINT(DBG_INFO,F("HW_FB_TLmValue ")); @@ -667,6 +676,7 @@ class Communication : public CommQueue<> { inline void miGPFDecode(packet_t *p, const queue_s *q) { record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure rec->ts = q->ts; + rec->mqttSentStatus = MqttSentStatus::NEW_DATA; q->iv->setValue(2, rec, (uint32_t) (((p->packet[10] << 8) | p->packet[11]))); //FLD_GRID_PROFILE_CODE q->iv->setValue(3, rec, (uint32_t) (((p->packet[12] << 8) | p->packet[13]))); //FLD_GRID_PROFILE_VERSION @@ -849,6 +859,8 @@ class Communication : public CommQueue<> { if (!stsok) { q->iv->setValue(q->iv->getPosByChFld(0, FLD_EVT, rec), rec, prntsts); q->iv->lastAlarm[0] = alarm_t(prntsts, q->ts, 0); + rec->ts = q->ts; + rec->mqttSentStatus = MqttSentStatus::NEW_DATA; } if (q->iv->alarmMesIndex < rec->record[q->iv->getPosByChFld(0, FLD_EVT, rec)]) { @@ -907,17 +919,12 @@ class Communication : public CommQueue<> { iv->setValue(iv->getPosByChFld(0, FLD_PAC, rec), rec, (float) ac_pow/10); iv->doCalculations(); + rec->mqttSentStatus = MqttSentStatus::NEW_DATA; // update status state-machine, if (ac_pow) iv->isProducing(); - //closeRequest(iv, iv->miMultiParts > 5); - - //mHeu.setGotAll(iv); - //cmdDone(false); if(NULL != mCbPayload) (mCbPayload)(RealTimeRunData_Debug, iv); - - //mState = States::RESET; // everything ok, next request } private: From ac2f772b74ed8c9fa4439ba01acde517eb5ee748 Mon Sep 17 00:00:00 2001 From: you69man <maschin@gmx.net> Date: Sun, 14 Jan 2024 17:16:32 +0100 Subject: [PATCH 2/6] fix immediate clearing of display after sunset --- src/plugins/Display/Display_Mono.h | 121 ++++++++++++++-------- src/plugins/Display/Display_Mono_128X64.h | 3 +- 2 files changed, 79 insertions(+), 45 deletions(-) diff --git a/src/plugins/Display/Display_Mono.h b/src/plugins/Display/Display_Mono.h index c8d25f8b..e0a03c61 100644 --- a/src/plugins/Display/Display_Mono.h +++ b/src/plugins/Display/Display_Mono.h @@ -81,7 +81,7 @@ class DisplayMono { mDispWidth = mDisplay->getDisplayWidth(); mDispHeight = mDisplay->getDisplayHeight(); mDispSwitchTime.stopTimeMonitor(); - if (mCfg->graph_ratio == 100) // if graph ratio is 100% start in graph mode + if (100 == mCfg->graph_ratio) // if graph ratio is 100% start in graph mode mDispSwitchState = DispSwitchState::GRAPH; else if (mCfg->graph_ratio != 0) mDispSwitchTime.startTimeMonitor(150 * (100 - mCfg->graph_ratio)); // start display mode change only if ratio is neither 0 nor 100 @@ -90,39 +90,70 @@ class DisplayMono { // pixelshift screensaver with wipe effect void calcPixelShift(int range) { int8_t mod = (millis() / 10000) % ((range >> 1) << 2); - mPixelshift = mCfg->screenSaver == 1 ? ((mod < range) ? mod - (range >> 1) : -(mod - range - (range >> 1) + 1)) : 0; + mPixelshift = (1 == mCfg->screenSaver) ? ((mod < range) ? mod - (range >> 1) : -(mod - range - (range >> 1) + 1)) : 0; } + protected: + enum class PowerGraphState { + NO_TIME_SYNC, + IN_PERIOD, + WAIT_4_NEW_PERIOD, + WAIT_4_RESTART + }; + + // initialize power graph and allocate data buffer based on pixel width void initPowerGraph(uint8_t width, uint8_t height) { DBGPRINTLN(F("---- Init Power Graph ----")); mPgWidth = width; mPgHeight = height; mPgData = new float[mPgWidth]; + mPgState = PowerGraphState::NO_TIME_SYNC; resetPowerGraph(); -/* - Inverter<> *iv; - mPgMaxAvailPower = 0; - uint8_t nInv = mSys->getNumInverters(); - for (uint8_t i = 0; i < nInv; i++) { - iv = mSys->getInverterByPos(i); - if (iv == NULL) - continue; - for (uint8_t ch = 0; ch < 6; ch++) { - mPgMaxAvailPower += iv->config->chMaxPwr[ch]; - } - } - DBGPRINTLN("max. Power = " + String(mPgMaxAvailPower));*/ } + // add new value to power graph and maintain state engine for period times void addPowerGraphEntry(float val) { - if ((nullptr != mPgData) && (mDisplayData->utcTs > 0)) { // precondition: power graph initialized and utc time available - calcPowerGraphValues(); - //mPgData[mPgLastPos] = std::max(mPgData[mPgLastPos], (uint8_t) (val * 255.0 / mPgMaxAvailPower)); // normalizing of data to 0-255 - mPgData[mPgLastPos] = std::max(mPgData[mPgLastPos], val); - mPgMaxPwr = std::max(mPgMaxPwr, val); // max value of stored data for scaling of y-axis + if (nullptr == mPgData) // power graph not initialized + return; + + bool store_entry = false; + switch(mPgState) { + case PowerGraphState::NO_TIME_SYNC: + if ((mDisplayData->pGraphStartTime > 0) && (mDisplayData->pGraphEndTime > 0) && // wait until period data is available ... + (mDisplayData->utcTs >= mDisplayData->pGraphStartTime) && (mDisplayData->utcTs < mDisplayData->pGraphEndTime)) { // and current time is in period + storeStartEndTimes(); // period was received -> store + store_entry = true; + mPgState = PowerGraphState::IN_PERIOD; + } + break; + case PowerGraphState::IN_PERIOD: + if (mDisplayData->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 != mDisplayData->pGraphStartTime) || (mPgEndTime != mDisplayData->pGraphEndTime)) { // wait until new time period was received ... + storeStartEndTimes(); // and store it for next period + mPgState = PowerGraphState::WAIT_4_RESTART; + } + break; + case PowerGraphState::WAIT_4_RESTART: + if ((mDisplayData->utcTs >= mPgStartTime) && (mDisplayData->utcTs < mPgEndTime)) { // wait until current time is in period again ... + resetPowerGraph(); // then reset power graph data + store_entry = true; + mPgState = PowerGraphState::IN_PERIOD; + } + break; + } + if (store_entry) { + mPgLastPos = std::min((uint8_t) sss2PgPos(mDisplayData->utcTs - mPgStartTime), (uint8_t) (mPgWidth - 1)); // current datapoint based on seconds since start + mPgData[mPgLastPos] = std::max(mPgData[mPgLastPos], val); // update current datapoint to maximum of all seen values + mPgMaxPwr = std::max(mPgMaxPwr, val); // update max value of stored data for scaling of y-axis } } + // plot power graph to given display offset void plotPowerGraph(uint8_t xoff, uint8_t yoff) { if (nullptr == mPgData) // power graph not initialized return; @@ -146,7 +177,7 @@ class DisplayMono { tm.Minute = 0; tm.Second = 0; for (; tm.Hour <= endHour; tm.Hour++) { - uint8_t x_pos_screen = getPowerGraphXpos(sss2pgpos((uint32_t) makeTime(tm) - mDisplayData->pGraphStartTime)); // scale horizontal axis + uint8_t x_pos_screen = getPowerGraphXpos(sss2PgPos((uint32_t) makeTime(tm) - mDisplayData->pGraphStartTime)); // scale horizontal axis mDisplay->drawPixel(xoff + x_pos_screen, yoff - 1); } @@ -163,8 +194,8 @@ class DisplayMono { // draw curve for (uint8_t i = 1; i <= mPgLastPos; i++) { - mDisplay->drawLine(xoff + getPowerGraphXpos(i - 1), yoff - getPowerGraphYpos(i - 1), - xoff + getPowerGraphXpos(i), yoff - getPowerGraphYpos(i)); + mDisplay->drawLine(xoff + getPowerGraphXpos(i - 1), yoff - getPowerGraphValueYpos(i - 1), + xoff + getPowerGraphXpos(i), yoff - getPowerGraphValueYpos(i)); } // print max power value @@ -195,6 +226,7 @@ class DisplayMono { return change; } + // reset power graph void resetPowerGraph() { if (mPgData != nullptr) { mPgMaxPwr = 0.0; @@ -205,34 +237,35 @@ class DisplayMono { } } - uint8_t sss2pgpos(uint seconds_since_start) { - uint32_t diff = (mDisplayData->pGraphEndTime - mDisplayData->pGraphStartTime); - if(diff) - return (seconds_since_start * (mPgWidth - 1) / diff); - return 0; + // store start and end times of current time period and calculate period length + void storeStartEndTimes() { + mPgStartTime = mDisplayData->pGraphStartTime; + mPgEndTime = mDisplayData->pGraphEndTime; + mPgPeriod = mDisplayData->pGraphEndTime - mDisplayData->pGraphStartTime; // time period of power graph in sec for scaling of x-axis } - void calcPowerGraphValues() { - mPgPeriod = mDisplayData->pGraphEndTime - mDisplayData->pGraphStartTime; // length of power graph for scaling of x-axis - uint32_t oldTimeOfDay = mPgTimeOfDay; - mPgTimeOfDay = (mDisplayData->utcTs > mDisplayData->pGraphStartTime) ? mDisplayData->utcTs - mDisplayData->pGraphStartTime : 0; // current time of day with respect to current sunrise time - if (oldTimeOfDay > mPgTimeOfDay) // new day -> reset old data - resetPowerGraph(); - if(0 == mPgPeriod) - mPgPeriod = 1; - mPgLastPos = std::min((uint8_t) (mPgTimeOfDay * (mPgWidth - 1) / mPgPeriod), (uint8_t) (mPgWidth - 1)); // current datapoint based on currenct time of day + // get power graph datapoint index, scaled to current time period, by seconds since start + uint8_t sss2PgPos(uint seconds_since_start) { + if(mPgPeriod) + return (seconds_since_start * (mPgWidth - 1) / mPgPeriod); + else + return 0; } - uint8_t getPowerGraphXpos(uint8_t p) { + // get X-position of power graph, scaled to lastpos, by according data point index + uint8_t getPowerGraphXpos(uint8_t p) { if ((p <= mPgLastPos) && (mPgLastPos > 0)) return((p * (mPgWidth - 1)) / mPgLastPos); // scaling of x-axis - return 0; + else + return 0; } - uint8_t getPowerGraphYpos(uint8_t p) { + // get Y-position of power graph, scaled to maximum value, by according datapoint index + uint8_t getPowerGraphValueYpos(uint8_t p) { if ((p < mPgWidth) && (mPgMaxPwr > 0)) return((mPgData[p] * (uint32_t) mPgHeight / mPgMaxPwr)); // scaling of data to graph height - return 0; + else + return 0; } protected: @@ -254,9 +287,11 @@ class DisplayMono { float *mPgData = nullptr; uint8_t mPgHeight = 0; float mPgMaxPwr = 0.0; - uint32_t mPgPeriod = 0; // seconds - uint32_t mPgTimeOfDay = 0; + uint32_t mPgStartTime = 0; + uint32_t mPgEndTime = 0; + uint32_t mPgPeriod = 0; // seconds uint8_t mPgLastPos = 0; + PowerGraphState mPgState = PowerGraphState::NO_TIME_SYNC; uint16_t mDispHeight; uint8_t mLuminance; diff --git a/src/plugins/Display/Display_Mono_128X64.h b/src/plugins/Display/Display_Mono_128X64.h index 34f35834..b4aa08cc 100644 --- a/src/plugins/Display/Display_Mono_128X64.h +++ b/src/plugins/Display/Display_Mono_128X64.h @@ -89,9 +89,8 @@ class DisplayMono128X64 : public DisplayMono { calcPixelShift(pixelShiftRange); // add new power data to power graph - if (mDisplayData->nrProducing > 0) { + if (mDisplayData->nrProducing > 0) addPowerGraphEntry(mDisplayData->totalPower); - } // print Date and time if (0 != mDisplayData->utcTs) From 9d29276c06de2296bcc4b2d2f46770697ea8e62d Mon Sep 17 00:00:00 2001 From: rejoe2 <rejoe2@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:12:51 +0100 Subject: [PATCH 3/6] Add "second try" - serial info deactivated - first tx is counted as retransmit --- src/hm/Communication.h | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 5f14a5af..9e383b6a 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -91,6 +91,7 @@ class Communication : public CommQueue<> { mIsRetransmit = false; if(NULL == q->iv->radio) cmdDone(false); // can't communicate while radio is not defined! + mFirstTry = q->iv->isAvailable(); q->iv->mCmd = q->cmd; q->iv->mIsSingleframeReq = false; mState = States::START; @@ -140,8 +141,25 @@ class Communication : public CommQueue<> { if((IV_HMS == q->iv->ivGen) || (IV_HMT == q->iv->ivGen)) { q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, (q->iv->config->frequency*FREQ_STEP_KHZ + HOY_BASE_FREQ_KHZ)); mWaitTime.startTimeMonitor(1000); - } else if(IV_MI == q->iv->ivGen) - q->iv->mIvTxCnt++; + } else { + if(IV_MI == q->iv->ivGen) + q->iv->mIvTxCnt++; + if(mFirstTry){ + mFirstTry = false; + mState = States::START; + setAttempt(); + mHeu.evalTxChQuality(q->iv, false, 0, 0); + //q->iv->radioStatistics.rxFailNoAnser++; + q->iv->radioStatistics.retransmits++; + mWaitTime.stopTimeMonitor(); + + /*if(*mSerialDebug) { + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINTLN(F("second try")); + }*/ + return; + } + } } closeRequest(q, false); break; @@ -553,7 +571,6 @@ class Communication : public CommQueue<> { q->iv->mGotLastMsg = false; q->iv->miMultiParts = 0; mIsRetransmit = false; - mFirstTry = false; // for correct reset mState = States::RESET; DBGPRINTLN(F("-----")); } From 1ac920d52d8b5768f0be26db5b5959543af84e38 Mon Sep 17 00:00:00 2001 From: lumapu <lp@lufami.de> Date: Mon, 15 Jan 2024 21:38:54 +0100 Subject: [PATCH 4/6] 0.8.57 * merge PR: fix immediate clearing of display after sunset #1364 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/plugins/Display/Display_Mono.h | 27 ++++++++++++++++----------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index d566216a..2032f009 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.57 - 2024-01-15 +* merge PR: fix immediate clearing of display after sunset #1364 + ## 0.8.56 - 2024-01-15 * potential fix of update problems and random reboots #1359 #1354 diff --git a/src/defines.h b/src/defines.h index 46c9a249..528aa714 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 56 +#define VERSION_PATCH 57 //------------------------------------- typedef struct { diff --git a/src/plugins/Display/Display_Mono.h b/src/plugins/Display/Display_Mono.h index e0a03c61..58b4224f 100644 --- a/src/plugins/Display/Display_Mono.h +++ b/src/plugins/Display/Display_Mono.h @@ -116,12 +116,16 @@ class DisplayMono { if (nullptr == mPgData) // power graph not initialized return; + bool storeStartEndTimes = false; bool store_entry = false; switch(mPgState) { case PowerGraphState::NO_TIME_SYNC: - if ((mDisplayData->pGraphStartTime > 0) && (mDisplayData->pGraphEndTime > 0) && // wait until period data is available ... - (mDisplayData->utcTs >= mDisplayData->pGraphStartTime) && (mDisplayData->utcTs < mDisplayData->pGraphEndTime)) { // and current time is in period - storeStartEndTimes(); // period was received -> store + if ((mDisplayData->pGraphStartTime > 0) + && (mDisplayData->pGraphEndTime > 0) // wait until period data is available ... + && (mDisplayData->utcTs >= mDisplayData->pGraphStartTime) + && (mDisplayData->utcTs < mDisplayData->pGraphEndTime)) // and current time is in period + { + storeStartEndTimes = true; // period was received -> store store_entry = true; mPgState = PowerGraphState::IN_PERIOD; } @@ -134,7 +138,7 @@ class DisplayMono { break; case PowerGraphState::WAIT_4_NEW_PERIOD: if ((mPgStartTime != mDisplayData->pGraphStartTime) || (mPgEndTime != mDisplayData->pGraphEndTime)) { // wait until new time period was received ... - storeStartEndTimes(); // and store it for next period + storeStartEndTimes = true; // and store it for next period mPgState = PowerGraphState::WAIT_4_RESTART; } break; @@ -146,6 +150,14 @@ class DisplayMono { } break; } + + // store start and end times of current time period and calculate period length + if (storeStartEndTimes) { + mPgStartTime = mDisplayData->pGraphStartTime; + mPgEndTime = mDisplayData->pGraphEndTime; + mPgPeriod = mDisplayData->pGraphEndTime - mDisplayData->pGraphStartTime; // time period of power graph in sec for scaling of x-axis + } + if (store_entry) { mPgLastPos = std::min((uint8_t) sss2PgPos(mDisplayData->utcTs - mPgStartTime), (uint8_t) (mPgWidth - 1)); // current datapoint based on seconds since start mPgData[mPgLastPos] = std::max(mPgData[mPgLastPos], val); // update current datapoint to maximum of all seen values @@ -237,13 +249,6 @@ class DisplayMono { } } - // store start and end times of current time period and calculate period length - void storeStartEndTimes() { - mPgStartTime = mDisplayData->pGraphStartTime; - mPgEndTime = mDisplayData->pGraphEndTime; - mPgPeriod = mDisplayData->pGraphEndTime - mDisplayData->pGraphStartTime; // time period of power graph in sec for scaling of x-axis - } - // get power graph datapoint index, scaled to current time period, by seconds since start uint8_t sss2PgPos(uint seconds_since_start) { if(mPgPeriod) From 358344ad6d0f23f20aa5f52a0c493b473decb182 Mon Sep 17 00:00:00 2001 From: lumapu <lp@lufami.de> Date: Mon, 15 Jan 2024 22:55:56 +0100 Subject: [PATCH 5/6] 0.8.57 * 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 --- src/CHANGES.md | 3 +++ src/hm/CommQueue.h | 1 - src/hm/Communication.h | 4 ++-- src/hm/radio.h | 15 +++++++++------ src/web/html/update.html | 2 +- src/web/lang.h | 8 ++++---- src/web/lang.json | 2 +- 7 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 2032f009..15dcfba2 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,9 @@ ## 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 ## 0.8.56 - 2024-01-15 * potential fix of update problems and random reboots #1359 #1354 diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h index d62efe07..13decc01 100644 --- a/src/hm/CommQueue.h +++ b/src/hm/CommQueue.h @@ -11,7 +11,6 @@ #include "hmInverter.h" #include "../utils/dbg.h" -// needs a '+1' because the comparison does not send if attempts is equal 0 #define DEFAULT_ATTEMPS 5 #define MORE_ATTEMPS_ALARMDATA 15 #define MORE_ATTEMPS_GRIDONPROFILEPARA 15 diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 9e383b6a..7b5c84f9 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -144,14 +144,14 @@ class Communication : public CommQueue<> { } else { if(IV_MI == q->iv->ivGen) q->iv->mIvTxCnt++; - if(mFirstTry){ + if(mFirstTry) { mFirstTry = false; - mState = States::START; setAttempt(); mHeu.evalTxChQuality(q->iv, false, 0, 0); //q->iv->radioStatistics.rxFailNoAnser++; q->iv->radioStatistics.retransmits++; mWaitTime.stopTimeMonitor(); + mState = States::START; /*if(*mSerialDebug) { DPRINT_IVID(DBG_INFO, q->iv->id); diff --git a/src/hm/radio.h b/src/hm/radio.h index e5eda128..1422b285 100644 --- a/src/hm/radio.h +++ b/src/hm/radio.h @@ -103,16 +103,19 @@ class Radio { void generateDtuSn(void) { uint32_t chipID = 0; #ifdef ESP32 - uint64_t MAC = ESP.getEfuseMac(); - chipID = ((MAC >> 8) & 0xFF0000) | ((MAC >> 24) & 0xFF00) | ((MAC >> 40) & 0xFF); + chipID = (ESP.getEfuseMac() & 0xffffffff); #else chipID = ESP.getChipId(); #endif - mDtuSn = 0x80000000; // the first digit is an 8 for DTU production year 2022, the rest is filled with the ESP chipID in decimal - for(int i = 0; i < 7; i++) { - mDtuSn |= (chipID % 10) << (i * 4); - chipID /= 10; + + uint8_t t; + for(int i = 0; i < (7 << 2); i += 4) { + t = (chipID >> i) & 0x0f; + if(t > 0x09) + t -= 6; + mDtuSn |= (t << i); } + mDtuSn |= 0x80000000; // the first digit is an 8 for DTU production year 2022, the rest is filled with the ESP chipID in decimal } uint32_t mDtuSn; diff --git a/src/web/html/update.html b/src/web/html/update.html index 3fed75a5..800d9dfe 100644 --- a/src/web/html/update.html +++ b/src/web/html/update.html @@ -10,7 +10,7 @@ <div id="content"> <fieldset> <legend class="des">{#SELECT_FILE} (*.bin)</legend> - <p>{#INSTALLED_VERSION}: <span id="version" style="background-color: var(--input-bg); padding: 7px;"></span></p> + <p>{#INSTALLED_VERSION}:<br/><span id="version" style="background-color: var(--input-bg); padding: 7px; display: block; margin: 3px;"></span></p> <form id="form" method="POST" action="/update" enctype="multipart/form-data" accept-charset="utf-8"> <input type="file" name="update"> <input type="button" class="btn my-4" value="{#BTN_UPDATE}" onclick="hide()"> diff --git a/src/web/lang.h b/src/web/lang.h index 3c3cd631..546399aa 100644 --- a/src/web/lang.h +++ b/src/web/lang.h @@ -73,15 +73,15 @@ #endif #ifdef LANG_DE - #define FACTORY_RESET "Ahoy Factory Reset" -#else /*LANG_EN*/ #define FACTORY_RESET "Ahoy auf Werkseinstellungen zurücksetzen" +#else /*LANG_EN*/ + #define FACTORY_RESET "Ahoy Factory Reset" #endif #ifdef LANG_DE - #define BTN_REBOOT "Reboot" -#else /*LANG_EN*/ #define BTN_REBOOT "Ahoy neustarten" +#else /*LANG_EN*/ + #define BTN_REBOOT "Reboot" #endif #endif /*__LANG_H__*/ diff --git a/src/web/lang.json b/src/web/lang.json index c910650e..ae8c0ca2 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -781,7 +781,7 @@ { "token": "IRQ_WORKING", "en": "Interrupt Pin working", - "de": "Interrupt Pin funktoniert" + "de": "Interrupt Pin funktioniert" }, { "token": "NRF24_DATA_RATE", From f503516c9feba7a7cc6fb427954165ce05cd7746 Mon Sep 17 00:00:00 2001 From: lumapu <lp@lufami.de> Date: Tue, 16 Jan 2024 00:11:34 +0100 Subject: [PATCH 6/6] 0.8.57 * added protection to prevent update to wrong firmware (environment check) --- ahoy.code-workspace | 45 ++++++++++++++++++++++++++++++++++++++++ src/CHANGES.md | 1 + src/app.cpp | 2 +- src/web/RestApi.h | 4 ++-- src/web/html/update.html | 29 ++++++++++++++++++++------ src/web/lang.json | 20 ++++++++++++++++++ 6 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 ahoy.code-workspace diff --git a/ahoy.code-workspace b/ahoy.code-workspace new file mode 100644 index 00000000..20d5909e --- /dev/null +++ b/ahoy.code-workspace @@ -0,0 +1,45 @@ +{ + "folders": [ + { + "path": "." + }, + { + "path": "src" + } + ], + "settings": { + "files.associations": { + "algorithm": "cpp", + "array": "cpp", + "chrono": "cpp", + "deque": "cpp", + "format": "cpp", + "forward_list": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "iterator": "cpp", + "list": "cpp", + "memory": "cpp", + "queue": "cpp", + "random": "cpp", + "regex": "cpp", + "vector": "cpp", + "xhash": "cpp", + "xlocmon": "cpp", + "xlocnum": "cpp", + "xmemory": "cpp", + "xstring": "cpp", + "xtree": "cpp", + "xutility": "cpp", + "*.tcc": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "string_view": "cpp", + "sstream": "cpp", + "istream": "cpp", + "ostream": "cpp" + }, + "editor.formatOnSave": false + } +} \ No newline at end of file diff --git a/src/CHANGES.md b/src/CHANGES.md index 15dcfba2..316224ab 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -5,6 +5,7 @@ * 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 diff --git a/src/app.cpp b/src/app.cpp index 6350e990..8dfcdb4d 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -35,7 +35,7 @@ void app::setup() { } #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, false); + mCmtRadio.setup(&mConfig->serial.debug, &mConfig->serial.privacyLog, &mConfig->serial.printWholeTrace, mConfig->cmt.pinSclk, mConfig->cmt.pinSdio, mConfig->cmt.pinCsb, mConfig->cmt.pinFcsb); } #endif #ifdef ETHERNET diff --git a/src/web/RestApi.h b/src/web/RestApi.h index edf92a97..097adac3 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -326,8 +326,8 @@ class RestApi { void getHtmlSystem(AsyncWebServerRequest *request, JsonObject obj) { getSysInfo(request, obj.createNestedObject(F("system"))); getGeneric(request, obj.createNestedObject(F("generic"))); - char tmp[100]; - snprintf(tmp, 100, "<a href=\"/factory\" class=\"btn\">%s</a><br/><br/><a href=\"/reboot\" class=\"btn\">%s</a>", FACTORY_RESET, BTN_REBOOT); + char tmp[200]; + snprintf(tmp, 200, "<a href=\"/factory\" class=\"btn\">%s</a><br/><br/><a href=\"/reboot\" class=\"btn\">%s</a>", FACTORY_RESET, BTN_REBOOT); obj[F("html")] = String(tmp); } diff --git a/src/web/html/update.html b/src/web/html/update.html index 800d9dfe..52ace5f1 100644 --- a/src/web/html/update.html +++ b/src/web/html/update.html @@ -23,17 +23,34 @@ </div> {#HTML_FOOTER} <script type="text/javascript"> + var env; function parseGeneric(obj) { - parseNav(obj); - parseESP(obj); - parseRssi(obj); + parseNav(obj) + parseESP(obj) + parseRssi(obj) + env = obj.env document.getElementById("version").innerHTML = "{#VERSION_FULL}_" + obj.env + ".bin" } function hide() { - document.getElementById("form").submit(); - var e = document.getElementById("content"); - e.replaceChildren(span("{#UPDATE_STARTED}")); + var bin = document.getElementsByName("update")[0].value.slice(-env.length-4, -4) + if (bin !== env) { + var html = ml("div", {class: "row"}, [ + ml("div", {class: "row my-3"}, "{#WARN_DIFF_ENV}"), + ml("div", {class: "row"}, [ + ml("div", {class: "col-6"}, ml("input", {type: "button", class: "btn", value: "{#CANCEL}", onclick: function() { modalClose(); }}, null)), + ml("div", {class: "col-6"}, ml("input", {type: "button", class: "btn", value: "{#CONTIUE}", onclick: function() { start(); modalClose(); }}, null)) + ]) + ]) + modal("{#UPDATE_MODAL}", html) + } else + start() + } + + function start() { + document.getElementById("form").submit() + var e = document.getElementById("content") + e.replaceChildren(span("{#UPDATE_STARTED}")) } getAjax("/api/generic", parseGeneric); diff --git a/src/web/lang.json b/src/web/lang.json index ae8c0ca2..316ca67b 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -1052,6 +1052,26 @@ "token": "UPDATE_STARTED", "en": "update started", "de": "Aktualisierung gestartet" + }, + { + "token": "UPDATE_MODAL", + "en": "Warning", + "de": "Warnung" + }, + { + "token": "WARN_DIFF_ENV", + "en": "your environment does not match the update file!", + "de": "Die ausgewählte Firmware passt uU. nicht zum Chipsatz!" + }, + { + "token": "CONTIUE", + "en": "continue", + "de": "fortfahren" + }, + { + "token": "CANCEL", + "en": "cancel", + "de": "abbrechen" } ] },