From 81f7c350d025710d956d2dad9d004cf4c78cb8ae Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Tue, 23 Jan 2024 11:53:50 +0100
Subject: [PATCH 01/79] dynamic retries
discord version 0.8.6401
---
src/hm/Communication.h | 10 +++++++--
src/hm/Heuristic.h | 48 ++++++++++++++++++++++++++++++++++++++++--
src/hm/HeuristicInv.h | 3 +++
src/hm/hmRadio.h | 12 +++++++++--
src/hm/radio.h | 1 +
5 files changed, 68 insertions(+), 6 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 98dd06e1..60e87918 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -148,6 +148,7 @@ class Communication : public CommQueue<> {
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 {
+ mHeu.setIvRetriesBad(q->iv);
if(IV_MI == q->iv->ivGen)
q->iv->mIvTxCnt++;
@@ -180,8 +181,11 @@ class Communication : public CommQueue<> {
q->iv->mDtuRxCnt++;
if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
- if(parseFrame(p))
+ if(parseFrame(p)) {
q->iv->curFrmCnt++;
+ if(!mIsRetransmit && p->packet[9] == 2 && p->millis < 85)
+ mHeu.setIvRetriesGood(q->iv,p->millis < 70);
+ }
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command
if(parseDevCtrl(p, q))
closeRequest(q, true);
@@ -417,6 +421,8 @@ class Communication : public CommQueue<> {
}
inline bool parseMiFrame(packet_t *p, const queue_s *q) {
+ if(!mIsRetransmit && p->packet[9] == 0x00 && p->millis < 35) //first frame is fast?
+ mHeu.setIvRetriesGood(q->iv,p->millis < 22);
if ((p->packet[0] == MI_REQ_CH1 + ALL_FRAMES)
|| (p->packet[0] == MI_REQ_CH2 + ALL_FRAMES)
|| ((p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES))
@@ -527,7 +533,7 @@ class Communication : public CommQueue<> {
len -= 2;
- DPRINT_IVID(DBG_INFO, q->iv->id);
+ //DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("Payload ("));
DBGPRINT(String(len));
if(*mPrintWholeTrace) {
diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h
index 64c78cc8..642eca13 100644
--- a/src/hm/Heuristic.h
+++ b/src/hm/Heuristic.h
@@ -23,8 +23,8 @@
class Heuristic {
public:
uint8_t getTxCh(Inverter<> *iv) {
- if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
- return 0; // not used for these inverter types
+ if(iv->ivRadioType != INV_RADIO_TYPE_NRF)
+ return 0; // not used for other than nRF inverter types
HeuristicInv *ih = &iv->heuristics;
@@ -66,6 +66,8 @@ class Heuristic {
ih->testPeriodFailCnt = 0;
}
+ iv->radio->mTxRetriesNext = getIvRetries(iv);
+
return id2Ch(ih->txRfChId);
}
@@ -155,6 +157,48 @@ class Heuristic {
DBGPRINTLN(String(iv->config->powerLevel));
}
+ uint8_t getIvRetries(Inverter<> *iv) {
+ if(iv->heuristics.rxSpeeds[0])
+ return 5;
+ if(iv->heuristics.rxSpeeds[1])
+ return 10;
+ return 15;
+ }
+
+ void setIvRetriesGood(Inverter<> *iv, bool veryGood) {
+ if(iv->ivRadioType != INV_RADIO_TYPE_NRF)
+ return; // not used for other than nRF inverter types
+
+ if(iv->heuristics.rxSpeedCnt[veryGood] > 9)
+ return;
+ iv->heuristics.rxSpeedCnt[veryGood]++;
+ iv->heuristics.rxSpeeds[veryGood] = true;
+ }
+
+ void setIvRetriesBad(Inverter<> *iv) {
+ if(iv->ivRadioType != INV_RADIO_TYPE_NRF)
+ return; // not used for other than nRF inverter types
+
+ if(iv->heuristics.rxSpeedCnt[0]) {
+ iv->heuristics.rxSpeedCnt[0]--;
+ return;
+ }
+ if(iv->heuristics.rxSpeeds[0]) {
+ iv->heuristics.rxSpeeds[0] = false;
+ return;
+ }
+
+ if(iv->heuristics.rxSpeedCnt[1]) {
+ iv->heuristics.rxSpeedCnt[1]--;
+ return;
+ }
+ if(iv->heuristics.rxSpeeds[1]) {
+ iv->heuristics.rxSpeeds[1] = false;
+ return;
+ }
+ return;
+ }
+
private:
bool isNewTxCh(HeuristicInv *ih) {
return ih->txRfChId != ih->lastBestTxChId;
diff --git a/src/hm/HeuristicInv.h b/src/hm/HeuristicInv.h
index e7ad6edd..fc782a7b 100644
--- a/src/hm/HeuristicInv.h
+++ b/src/hm/HeuristicInv.h
@@ -27,6 +27,9 @@ class HeuristicInv {
uint8_t testChId = 0;
int8_t saveOldTestQuality = -6;
uint8_t lastRxFragments = 0;
+ bool rxSpeeds[2] = {false,false}; // is inverter responding very fast respective fast?
+ uint8_t rxSpeedCnt[2] = {0,0}; // count how many messages had been received very fast respective fast (10 max)
+
};
#endif /*__HEURISTIC_INV_H__*/
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index ef37e266..d41dc36a 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -161,7 +161,7 @@ class HmRadio : public Radio {
rxPendular = false;
mNRFloopChannels = (mLastIv->ivGen == IV_MI);
- innerLoopTimeout = DURATION_TXFRAME;
+ innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME;
}
if(rx_ready) {
@@ -356,11 +356,14 @@ class HmRadio : public Radio {
mTxChIdx = iv->heuristics.txRfChId;
if(*mSerialDebug) {
+ /* remark rejoe2: imo this has no added value here.
+ As this belongs to the last tx cycle, we should print that info
+ directly when switching from tx to rx. Otherwise we might confuse users.
if(!isRetransmit) {
DPRINT(DBG_INFO, "last tx setup: ");
DBGPRINT(String(mTxSetupTime));
DBGPRINTLN("ms");
- }
+ }*/
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("TX "));
@@ -383,6 +386,10 @@ class HmRadio : public Radio {
}
mNrf24->stopListening();
+ if(!isRetransmit && mTxRetries != mTxRetriesNext) {
+ mNrf24->setRetries(3, mTxRetriesNext);
+ mTxRetries = mTxRetriesNext;
+ }
mNrf24->setChannel(mRfChLst[mTxChIdx]);
mNrf24->openWritingPipe(reinterpret_cast(&iv->radioId.u64));
mNrf24->startWrite(mTxBuf, len, false); // false = request ACK response
@@ -425,6 +432,7 @@ class HmRadio : public Radio {
bool rxPendular = false;
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
uint8_t mTxSetupTime = 0;
+ uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15);
std::unique_ptr mSpi;
std::unique_ptr mNrf24;
diff --git a/src/hm/radio.h b/src/hm/radio.h
index a71e24c7..e11d8682 100644
--- a/src/hm/radio.h
+++ b/src/hm/radio.h
@@ -78,6 +78,7 @@ class Radio {
std::queue mBufCtrl;
uint8_t mIrqOk = IRQ_UNKNOWN;
TimeMonitor mRadioWaitTime = TimeMonitor(0, true); // start as expired (due to code in RESET state)
+ uint8_t mTxRetriesNext = 15; // let heuristics tell us the next reties count (for nRF type radios only)
protected:
virtual void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) = 0;
From 8f5310ffd35dd7ea9b48af188ef5e95b1e0dc2fb Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Tue, 23 Jan 2024 12:41:41 +0100
Subject: [PATCH 02/79] reduce serial output
---
src/hm/Communication.h | 12 +++++++-----
src/hm/hmRadio.h | 12 +++++++-----
src/hm/radio.h | 4 ++--
3 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 60e87918..b02c03b7 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -134,14 +134,16 @@ class Communication : public CommQueue<> {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("request timeout: "));
DBGPRINT(String(q->iv->radio->mRadioWaitTime.getRunTime()));
- DBGPRINT(F("ms"));
- if(INV_RADIO_TYPE_NRF == q->iv->ivRadioType) {
+ DBGPRINTLN(F("ms"));
+ /*if(INV_RADIO_TYPE_NRF == q->iv->ivRadioType) {
+ DBGPRINT(F(", retries "));
+ DBGPRINTLN(String(q->iv->radio->mTxRetriesNext));
DBGPRINT(F(", ARC "));
DBGPRINT(String(q->iv->radio->getARC()));
DBGPRINT(F(", PLOS "));
DBGPRINTLN(String(q->iv->radio->getPLOS()));
} else
- DBGPRINTLN("");
+ DBGPRINTLN("");*/
}
if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
@@ -295,10 +297,10 @@ class Communication : public CommQueue<> {
DBGPRINT(String(p->millis));
DBGPRINT(F("ms | "));
DBGPRINT(String(p->len));
- DBGPRINT(F(", ARC "));
+ /*DBGPRINT(F(", ARC "));
DBGPRINT(String(p->arc));
DBGPRINT(F(", PLOS "));
- DBGPRINT(String(p->plos));
+ DBGPRINT(String(p->plos));*/
DBGPRINT(F(" |"));
if(INV_RADIO_TYPE_NRF == q->iv->ivRadioType) {
DBGPRINT(F(" CH"));
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index d41dc36a..9915a9a8 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -293,13 +293,13 @@ class HmRadio : public Radio {
return mNrf24->isPVariant();
}
- uint8_t getARC(void) {
+ /*uint8_t getARC(void) {
return mNrf24->getARC();
}
uint8_t getPLOS(void) {
return mNrf24->getPLOS();
- }
+ }*/
private:
inline bool getReceived(void) {
@@ -315,8 +315,8 @@ class HmRadio : public Radio {
p.len = (len > MAX_RF_PAYLOAD_SIZE) ? MAX_RF_PAYLOAD_SIZE : len;
p.rssi = mNrf24->testRPD() ? -64 : -75;
p.millis = millis() - mMillis;
- p.arc = mNrf24->getARC();
- p.plos = mNrf24->getPLOS();
+ //p.arc = mNrf24->getARC();
+ //p.plos = mNrf24->getPLOS();
mNrf24->read(p.packet, p.len);
if (p.packet[0] != 0x00) {
@@ -370,7 +370,9 @@ class HmRadio : public Radio {
DBGPRINT(String(len));
DBGPRINT(" CH");
DBGPRINT(String(mRfChLst[mTxChIdx]));
- DBGPRINT(F(" | "));
+ DBGPRINT(F(", "));
+ DBGPRINT(String(mTxRetriesNext));
+ DBGPRINT(F(" retries | "));
if(*mPrintWholeTrace) {
if(*mPrivacyMode)
ah::dumpBuf(mTxBuf, len, 1, 4);
diff --git a/src/hm/radio.h b/src/hm/radio.h
index e11d8682..e6baf792 100644
--- a/src/hm/radio.h
+++ b/src/hm/radio.h
@@ -29,8 +29,8 @@ class Radio {
virtual bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; }
virtual bool isChipConnected(void) { return false; }
virtual bool loop(void) = 0;
- virtual uint8_t getARC(void) { return 0xff; }
- virtual uint8_t getPLOS(void) { return 0xff; }
+ //virtual uint8_t getARC(void) { return 0xff; }
+ //virtual uint8_t getPLOS(void) { return 0xff; }
void handleIntr(void) {
mIrqRcvd = true;
From bfedf4f0c23db7161ae3aadd4995f88b5f9c815d Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Tue, 23 Jan 2024 16:09:54 +0100
Subject: [PATCH 03/79] fix 2nd frame detection
for 2ch HM
and add faster exiting CMT wait state
---
src/hm/Communication.h | 25 ++++++++++++++--------
src/hm/Heuristic.h | 48 ++++++++++++++++++++++++++++++++++++++++--
src/hm/HeuristicInv.h | 3 +++
src/hm/hmRadio.h | 24 +++++++++++++++------
src/hm/radio.h | 5 +++--
src/hms/hmsRadio.h | 5 +++--
6 files changed, 88 insertions(+), 22 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 98dd06e1..15ca3d5d 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -86,7 +86,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();
+ mFirstTry = INV_RADIO_TYPE_NRF == q->iv->ivRadioType && q->iv->isAvailable();
q->iv->mCmd = q->cmd;
q->iv->mIsSingleframeReq = false;
mFramesExpected = getFramesExpected(q); // function to get expected frame count.
@@ -134,20 +134,23 @@ class Communication : public CommQueue<> {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("request timeout: "));
DBGPRINT(String(q->iv->radio->mRadioWaitTime.getRunTime()));
- DBGPRINT(F("ms"));
- if(INV_RADIO_TYPE_NRF == q->iv->ivRadioType) {
+ DBGPRINTLN(F("ms"));
+ /*if(INV_RADIO_TYPE_NRF == q->iv->ivRadioType) {
+ DBGPRINT(F(", retries "));
+ DBGPRINTLN(String(q->iv->radio->mTxRetriesNext));
DBGPRINT(F(", ARC "));
DBGPRINT(String(q->iv->radio->getARC()));
DBGPRINT(F(", PLOS "));
DBGPRINTLN(String(q->iv->radio->getPLOS()));
} else
- DBGPRINTLN("");
+ DBGPRINTLN("");*/
}
if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
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 {
+ mHeu.setIvRetriesBad(q->iv);
if(IV_MI == q->iv->ivGen)
q->iv->mIvTxCnt++;
@@ -180,8 +183,11 @@ class Communication : public CommQueue<> {
q->iv->mDtuRxCnt++;
if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
- if(parseFrame(p))
+ if(parseFrame(p)) {
q->iv->curFrmCnt++;
+ if(!mIsRetransmit && (p->packet[9] == 0x02 || p->packet[9] == 0x82) && p->millis < 85)
+ mHeu.setIvRetriesGood(q->iv,p->millis < 70);
+ }
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command
if(parseDevCtrl(p, q))
closeRequest(q, true);
@@ -291,10 +297,10 @@ class Communication : public CommQueue<> {
DBGPRINT(String(p->millis));
DBGPRINT(F("ms | "));
DBGPRINT(String(p->len));
- DBGPRINT(F(", ARC "));
+ /*DBGPRINT(F(", ARC "));
DBGPRINT(String(p->arc));
DBGPRINT(F(", PLOS "));
- DBGPRINT(String(p->plos));
+ DBGPRINT(String(p->plos));*/
DBGPRINT(F(" |"));
if(INV_RADIO_TYPE_NRF == q->iv->ivRadioType) {
DBGPRINT(F(" CH"));
@@ -417,6 +423,8 @@ class Communication : public CommQueue<> {
}
inline bool parseMiFrame(packet_t *p, const queue_s *q) {
+ if(!mIsRetransmit && p->packet[9] == 0x00 && p->millis < 35) //first frame is fast?
+ mHeu.setIvRetriesGood(q->iv,p->millis < 22);
if ((p->packet[0] == MI_REQ_CH1 + ALL_FRAMES)
|| (p->packet[0] == MI_REQ_CH2 + ALL_FRAMES)
|| ((p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES))
@@ -436,7 +444,6 @@ class Communication : public CommQueue<> {
record_t<> *rec = q->iv->getRecordStruct(RealTimeRunData_Debug); // choose the record structure
rec->ts = q->ts;
miStsConsolidate(q, ((p->packet[0] == 0x88) ? 1 : 2), rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]);
- //mHeu.setGotFragment(q->iv); only do this when we are through the cycle?
}
return true;
@@ -527,7 +534,7 @@ class Communication : public CommQueue<> {
len -= 2;
- DPRINT_IVID(DBG_INFO, q->iv->id);
+ //DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("Payload ("));
DBGPRINT(String(len));
if(*mPrintWholeTrace) {
diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h
index 64c78cc8..642eca13 100644
--- a/src/hm/Heuristic.h
+++ b/src/hm/Heuristic.h
@@ -23,8 +23,8 @@
class Heuristic {
public:
uint8_t getTxCh(Inverter<> *iv) {
- if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
- return 0; // not used for these inverter types
+ if(iv->ivRadioType != INV_RADIO_TYPE_NRF)
+ return 0; // not used for other than nRF inverter types
HeuristicInv *ih = &iv->heuristics;
@@ -66,6 +66,8 @@ class Heuristic {
ih->testPeriodFailCnt = 0;
}
+ iv->radio->mTxRetriesNext = getIvRetries(iv);
+
return id2Ch(ih->txRfChId);
}
@@ -155,6 +157,48 @@ class Heuristic {
DBGPRINTLN(String(iv->config->powerLevel));
}
+ uint8_t getIvRetries(Inverter<> *iv) {
+ if(iv->heuristics.rxSpeeds[0])
+ return 5;
+ if(iv->heuristics.rxSpeeds[1])
+ return 10;
+ return 15;
+ }
+
+ void setIvRetriesGood(Inverter<> *iv, bool veryGood) {
+ if(iv->ivRadioType != INV_RADIO_TYPE_NRF)
+ return; // not used for other than nRF inverter types
+
+ if(iv->heuristics.rxSpeedCnt[veryGood] > 9)
+ return;
+ iv->heuristics.rxSpeedCnt[veryGood]++;
+ iv->heuristics.rxSpeeds[veryGood] = true;
+ }
+
+ void setIvRetriesBad(Inverter<> *iv) {
+ if(iv->ivRadioType != INV_RADIO_TYPE_NRF)
+ return; // not used for other than nRF inverter types
+
+ if(iv->heuristics.rxSpeedCnt[0]) {
+ iv->heuristics.rxSpeedCnt[0]--;
+ return;
+ }
+ if(iv->heuristics.rxSpeeds[0]) {
+ iv->heuristics.rxSpeeds[0] = false;
+ return;
+ }
+
+ if(iv->heuristics.rxSpeedCnt[1]) {
+ iv->heuristics.rxSpeedCnt[1]--;
+ return;
+ }
+ if(iv->heuristics.rxSpeeds[1]) {
+ iv->heuristics.rxSpeeds[1] = false;
+ return;
+ }
+ return;
+ }
+
private:
bool isNewTxCh(HeuristicInv *ih) {
return ih->txRfChId != ih->lastBestTxChId;
diff --git a/src/hm/HeuristicInv.h b/src/hm/HeuristicInv.h
index e7ad6edd..fc782a7b 100644
--- a/src/hm/HeuristicInv.h
+++ b/src/hm/HeuristicInv.h
@@ -27,6 +27,9 @@ class HeuristicInv {
uint8_t testChId = 0;
int8_t saveOldTestQuality = -6;
uint8_t lastRxFragments = 0;
+ bool rxSpeeds[2] = {false,false}; // is inverter responding very fast respective fast?
+ uint8_t rxSpeedCnt[2] = {0,0}; // count how many messages had been received very fast respective fast (10 max)
+
};
#endif /*__HEURISTIC_INV_H__*/
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index ef37e266..9915a9a8 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -161,7 +161,7 @@ class HmRadio : public Radio {
rxPendular = false;
mNRFloopChannels = (mLastIv->ivGen == IV_MI);
- innerLoopTimeout = DURATION_TXFRAME;
+ innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME;
}
if(rx_ready) {
@@ -293,13 +293,13 @@ class HmRadio : public Radio {
return mNrf24->isPVariant();
}
- uint8_t getARC(void) {
+ /*uint8_t getARC(void) {
return mNrf24->getARC();
}
uint8_t getPLOS(void) {
return mNrf24->getPLOS();
- }
+ }*/
private:
inline bool getReceived(void) {
@@ -315,8 +315,8 @@ class HmRadio : public Radio {
p.len = (len > MAX_RF_PAYLOAD_SIZE) ? MAX_RF_PAYLOAD_SIZE : len;
p.rssi = mNrf24->testRPD() ? -64 : -75;
p.millis = millis() - mMillis;
- p.arc = mNrf24->getARC();
- p.plos = mNrf24->getPLOS();
+ //p.arc = mNrf24->getARC();
+ //p.plos = mNrf24->getPLOS();
mNrf24->read(p.packet, p.len);
if (p.packet[0] != 0x00) {
@@ -356,18 +356,23 @@ class HmRadio : public Radio {
mTxChIdx = iv->heuristics.txRfChId;
if(*mSerialDebug) {
+ /* remark rejoe2: imo this has no added value here.
+ As this belongs to the last tx cycle, we should print that info
+ directly when switching from tx to rx. Otherwise we might confuse users.
if(!isRetransmit) {
DPRINT(DBG_INFO, "last tx setup: ");
DBGPRINT(String(mTxSetupTime));
DBGPRINTLN("ms");
- }
+ }*/
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("TX "));
DBGPRINT(String(len));
DBGPRINT(" CH");
DBGPRINT(String(mRfChLst[mTxChIdx]));
- DBGPRINT(F(" | "));
+ DBGPRINT(F(", "));
+ DBGPRINT(String(mTxRetriesNext));
+ DBGPRINT(F(" retries | "));
if(*mPrintWholeTrace) {
if(*mPrivacyMode)
ah::dumpBuf(mTxBuf, len, 1, 4);
@@ -383,6 +388,10 @@ class HmRadio : public Radio {
}
mNrf24->stopListening();
+ if(!isRetransmit && mTxRetries != mTxRetriesNext) {
+ mNrf24->setRetries(3, mTxRetriesNext);
+ mTxRetries = mTxRetriesNext;
+ }
mNrf24->setChannel(mRfChLst[mTxChIdx]);
mNrf24->openWritingPipe(reinterpret_cast(&iv->radioId.u64));
mNrf24->startWrite(mTxBuf, len, false); // false = request ACK response
@@ -425,6 +434,7 @@ class HmRadio : public Radio {
bool rxPendular = false;
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
uint8_t mTxSetupTime = 0;
+ uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15);
std::unique_ptr mSpi;
std::unique_ptr mNrf24;
diff --git a/src/hm/radio.h b/src/hm/radio.h
index a71e24c7..e6baf792 100644
--- a/src/hm/radio.h
+++ b/src/hm/radio.h
@@ -29,8 +29,8 @@ class Radio {
virtual bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; }
virtual bool isChipConnected(void) { return false; }
virtual bool loop(void) = 0;
- virtual uint8_t getARC(void) { return 0xff; }
- virtual uint8_t getPLOS(void) { return 0xff; }
+ //virtual uint8_t getARC(void) { return 0xff; }
+ //virtual uint8_t getPLOS(void) { return 0xff; }
void handleIntr(void) {
mIrqRcvd = true;
@@ -78,6 +78,7 @@ class Radio {
std::queue mBufCtrl;
uint8_t mIrqOk = IRQ_UNKNOWN;
TimeMonitor mRadioWaitTime = TimeMonitor(0, true); // start as expired (due to code in RESET state)
+ uint8_t mTxRetriesNext = 15; // let heuristics tell us the next reties count (for nRF type radios only)
protected:
virtual void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) = 0;
diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h
index 48ff3750..3c569e02 100644
--- a/src/hms/hmsRadio.h
+++ b/src/hms/hmsRadio.h
@@ -166,9 +166,10 @@ class CmtRadio : public Radio {
mBufCtrl.push(p);
// this code completly stops communication!
- //if(p.packet[9] > ALL_FRAMES) // indicates last frame
+ if(p.packet[9] > ALL_FRAMES) // indicates last frame
// mRadioWaitTime.stopTimeMonitor(); // we got everything we expected and can exit rx mode...
- //optionally instead: mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first get back to rx mode?
+ //optionally instead:
+ mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first get back to rx mode?
}
CmtType mCmt;
From 3fbd2c7c88e933e42af35d84dba243598bceed95 Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Tue, 23 Jan 2024 17:54:57 +0100
Subject: [PATCH 04/79] fix retransmit counter for secondtry
- try to fix "45ms"-Problem
---
src/hm/Communication.h | 4 ++--
src/hm/hmRadio.h | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 15ca3d5d..94cf23ff 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -156,9 +156,9 @@ class Communication : public CommQueue<> {
if(mFirstTry) {
mFirstTry = false;
- setAttempt();
+ //setAttempt();
mHeu.evalTxChQuality(q->iv, false, 0, 0);
- q->iv->radioStatistics.rxFailNoAnser++;
+ //q->iv->radioStatistics.rxFailNoAnser++; // should only be one of fail or retransmit.
q->iv->radioStatistics.retransmits++;
q->iv->radio->mRadioWaitTime.stopTimeMonitor();
mState = States::START;
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index 9915a9a8..54f099dd 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -167,6 +167,7 @@ class HmRadio : public Radio {
if(rx_ready) {
if (getReceived()) { // check what we got, returns true for last package
mNRFisInRX = false;
+ rx_ready = false;
mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first end his transmissions
mNrf24->stopListening();
} else {
From 444a7160128b2a6e8d7628b8d940ca14236f31d6 Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Wed, 24 Jan 2024 10:42:39 +0100
Subject: [PATCH 05/79] partly fix statistics
- add more data requests to startup phase
---
src/hm/Communication.h | 7 +++++--
src/hm/hmInverter.h | 12 ++++++++----
src/hm/hmRadio.h | 12 +++++++++---
3 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 94cf23ff..4003c13e 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -159,6 +159,7 @@ class Communication : public CommQueue<> {
//setAttempt();
mHeu.evalTxChQuality(q->iv, false, 0, 0);
//q->iv->radioStatistics.rxFailNoAnser++; // should only be one of fail or retransmit.
+ q->iv->radioStatistics.txCnt--;
q->iv->radioStatistics.retransmits++;
q->iv->radio->mRadioWaitTime.stopTimeMonitor();
mState = States::START;
@@ -835,8 +836,9 @@ class Communication : public CommQueue<> {
DBGHEXLN(cmd);
}
- if(q->iv->miMultiParts == 7)
- q->iv->radioStatistics.rxSuccess++;
+ //if(q->iv->miMultiParts > 5) //if(q->iv->miMultiParts == 7)
+ q->iv->radioStatistics.rxSuccess++;
+ q->iv->radioStatistics.ivSent++;
mFramesExpected = getFramesExpected(q);
q->iv->radio->setExpectedFrames(mFramesExpected);
@@ -861,6 +863,7 @@ class Communication : public CommQueue<> {
}
q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true);
+ q->iv->radioStatistics.retransmits++;
q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
mIsRetransmit = false;
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index b28682e5..049b5501 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -200,13 +200,17 @@ class Inverter {
cb(devControlCmd, false); // custom command which was received by API
devControlCmd = InitDataState;
mGetLossInterval = 1;
- } else if(0 == getFwVersion())
+ } else if(0 == getFwVersion()) {
+ cb(RealTimeRunData_Debug, false); // get live data
cb(InverterDevInform_All, false); // get firmware version
- else if(0 == getHwVersion())
+ }
+ else if(0 == getHwVersion()) {
+ cb(RealTimeRunData_Debug, false); // get live data
cb(InverterDevInform_Simple, false); // get hardware version
- else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0))
+ } else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0)) {
+ cb(RealTimeRunData_Debug, false); // get live data
cb(AlarmData, false); // get last alarms
- else if((0 == mGridLen) && generalConfig->readGrid) { // read grid profile
+ } else if((0 == mGridLen) && generalConfig->readGrid) { // read grid profile
cb(GridOnProFilePara, false);
} else if (mGetLossInterval > AHOY_GET_LOSS_INTERVAL) { // get loss rate
mGetLossInterval = 1;
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index 54f099dd..feb4fde5 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -113,6 +113,7 @@ class HmRadio : public Radio {
if (mRadioWaitTime.isTimeout()) { // timeout reached!
mNRFisInRX = false;
+ rx_ready = false;
return false;
}
@@ -165,7 +166,7 @@ class HmRadio : public Radio {
}
if(rx_ready) {
- if (getReceived()) { // check what we got, returns true for last package
+ if (getReceived()) { // check what we got, returns true for last package or success for single frame request
mNRFisInRX = false;
rx_ready = false;
mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first end his transmissions
@@ -183,6 +184,7 @@ class HmRadio : public Radio {
mRxChIdx = tempRxChIdx;
}
}
+ rx_ready = false; // reset
return mNRFisInRX;
} /*else if(tx_fail) {
mNRFisInRX = false;
@@ -305,6 +307,7 @@ class HmRadio : public Radio {
private:
inline bool getReceived(void) {
bool isLastPackage = false;
+ bool isRetransmitAnswer = false;
rx_ready = false; // reset for ACK case
while(mNrf24->available()) {
@@ -329,8 +332,11 @@ class HmRadio : public Radio {
mLastIv->mGotFragment = true;
mBufCtrl.push(p);
- if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command
+ if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received
+ if(mLastIv->mIsSingleframeReq) // we only expect one frame here...
+ isRetransmitAnswer = true;
+ }
if(IV_MI == mLastIv->ivGen) {
if (p.packet[0] == (0x0f + ALL_FRAMES)) // response from MI get information command
@@ -346,7 +352,7 @@ class HmRadio : public Radio {
}
if(isLastPackage)
mLastIv->mGotLastMsg = true;
- return isLastPackage;
+ return isLastPackage || isRetransmitAnswer;
}
void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) {
From d7ea4bcb892b0d63e8875bbc49a1a352d1afc1f8 Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Wed, 24 Jan 2024 17:31:58 +0100
Subject: [PATCH 06/79] fix 0 attempts in Communication
- 45ms-Problem seems to be solved
---
src/hm/Communication.h | 4 ++--
src/hm/hmRadio.h | 5 ++++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 4003c13e..38925059 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -129,7 +129,7 @@ class Communication : public CommQueue<> {
break;
case States::CHECK_FRAMES: {
- if((q->iv->radio->mBufCtrl.empty() && !mIsRetransmit) || (0 == q->attempts)) { // radio buffer empty or no more answers
+ if((q->iv->radio->mBufCtrl.empty() && !mIsRetransmit) ) { // || (0 == q->attempts)) { // radio buffer empty or no more answers
if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("request timeout: "));
@@ -259,7 +259,7 @@ class Communication : public CommQueue<> {
if(framnr) {
if(0 == q->attempts) {
DPRINT_IVID(DBG_INFO, q->iv->id);
- DBGPRINT(F("no attempts left"));
+ DBGPRINTLN(F("no attempts left"));
closeRequest(q, false);
return;
}
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index feb4fde5..0df22f5a 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -336,6 +336,8 @@ class HmRadio : public Radio {
isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received
if(mLastIv->mIsSingleframeReq) // we only expect one frame here...
isRetransmitAnswer = true;
+ if(isLastPackage)
+ mFramesExpected = p.packet[9] - ALL_FRAMES;
}
if(IV_MI == mLastIv->ivGen) {
@@ -350,8 +352,9 @@ class HmRadio : public Radio {
}
yield();
}
- if(isLastPackage)
+ if(isLastPackage) {
mLastIv->mGotLastMsg = true;
+ }
return isLastPackage || isRetransmitAnswer;
}
From 97d74d309000e8e210178ee829c51a1ad6a4545f Mon Sep 17 00:00:00 2001
From: lumapu
Date: Thu, 25 Jan 2024 00:03:49 +0100
Subject: [PATCH 07/79] 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)
---
patches/RF24.patch | 35 -----------------------------------
scripts/applyPatches.py | 6 ++----
src/CHANGES.md | 5 +++++
src/defines.h | 2 +-
src/hm/CommQueue.h | 6 ++----
src/hm/Communication.h | 14 +-------------
src/hm/hmRadio.h | 27 ++++++---------------------
src/hm/radio.h | 10 ++++------
src/hms/hmsRadio.h | 11 +++++------
src/web/lang.json | 4 ++--
10 files changed, 28 insertions(+), 92 deletions(-)
delete mode 100644 patches/RF24.patch
diff --git a/patches/RF24.patch b/patches/RF24.patch
deleted file mode 100644
index 63db8823..00000000
--- a/patches/RF24.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-diff --git a/RF24.cpp b/RF24.cpp
-index 9e5b4a8..a4de63c 100644
---- a/RF24.cpp
-+++ b/RF24.cpp
-@@ -1871,6 +1871,11 @@ uint8_t RF24::getARC(void)
- return read_register(OBSERVE_TX) & 0x0F;
- }
-
-+uint8_t RF24::getPLOS(void)
-+{
-+ return read_register(OBSERVE_TX) & 0x0F;
-+}
-+
- /****************************************************************************/
-
- bool RF24::setDataRate(rf24_datarate_e speed)
-diff --git a/RF24.h b/RF24.h
-index dbd32ae..a3d6b52 100644
---- a/RF24.h
-+++ b/RF24.h
-@@ -1644,6 +1644,7 @@ public:
- * @return Returns values from 0 to 15.
- */
- uint8_t getARC(void);
-+ uint8_t getPLOS(void);
-
- /**
- * Set the transmission @ref Datarate
-@@ -2415,4 +2416,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/scripts/applyPatches.py b/scripts/applyPatches.py
index 3289badb..147fb0f3 100644
--- a/scripts/applyPatches.py
+++ b/scripts/applyPatches.py
@@ -12,11 +12,11 @@ def applyPatch(libName, patchFile):
os.chdir('.pio/libdeps/' + env['PIOENV'] + '/' + libName)
- process = subprocess.run(['git', 'apply', '--reverse', '--check', '../../../../' + patchFile], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ process = subprocess.run(['git', 'apply', '--ignore-whitespace', '--reverse', '--check', '../../../../' + patchFile], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if (process.returncode == 0):
print('\'' + patchFile + '\' already applied')
else:
- process = subprocess.run(['git', 'apply', '../../../../' + patchFile])
+ process = subprocess.run(['git', 'apply', '--ignore-whitespace', '../../../../' + patchFile])
if (process.returncode == 0):
print('\'' + patchFile + '\' applied')
else:
@@ -32,5 +32,3 @@ if env['PIOENV'][:22] != "opendtufusion-ethernet":
if env['PIOENV'][:13] == "opendtufusion":
applyPatch("GxEPD2", "../patches/GxEPD2_SW_SPI.patch")
applyPatch("RF24", "../patches/RF24_Hal.patch")
-else:
- applyPatch("RF24", "../patches/RF24.patch")
diff --git a/src/CHANGES.md b/src/CHANGES.md
index a4942d55..b8547302 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,10 @@
# Development Changes
+## 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
diff --git a/src/defines.h b/src/defines.h
index b8ddace9..ed975b7a 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 64
+#define VERSION_PATCH 65
//-------------------------------------
typedef struct {
diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h
index d3fe1c69..0ca9279f 100644
--- a/src/hm/CommQueue.h
+++ b/src/hm/CommQueue.h
@@ -18,8 +18,6 @@
template
class CommQueue {
public:
- CommQueue() {}
-
void addImportant(Inverter<> *iv, uint8_t cmd) {
dec(&mRdPtr);
mQueue[mRdPtr] = queue_s(iv, cmd, true);
@@ -34,12 +32,12 @@ class CommQueue {
mQueue[mWrPtr] = queue_s(iv, cmd, false);
}
- uint8_t getFillState(void) {
+ uint8_t getFillState(void) const {
//DPRINTLN(DBG_INFO, "wr: " + String(mWrPtr) + ", rd: " + String(mRdPtr));
return abs(mRdPtr - mWrPtr);
}
- uint8_t getMaxFill(void) {
+ uint8_t getMaxFill(void) const {
return N;
}
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 98dd06e1..3a6fdd0b 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -134,14 +134,7 @@ class Communication : public CommQueue<> {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("request timeout: "));
DBGPRINT(String(q->iv->radio->mRadioWaitTime.getRunTime()));
- DBGPRINT(F("ms"));
- if(INV_RADIO_TYPE_NRF == q->iv->ivRadioType) {
- DBGPRINT(F(", ARC "));
- DBGPRINT(String(q->iv->radio->getARC()));
- DBGPRINT(F(", PLOS "));
- DBGPRINTLN(String(q->iv->radio->getPLOS()));
- } else
- DBGPRINTLN("");
+ DBGPRINTLN(F("ms"));
}
if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
@@ -291,11 +284,6 @@ class Communication : public CommQueue<> {
DBGPRINT(String(p->millis));
DBGPRINT(F("ms | "));
DBGPRINT(String(p->len));
- DBGPRINT(F(", ARC "));
- DBGPRINT(String(p->arc));
- DBGPRINT(F(", PLOS "));
- DBGPRINT(String(p->plos));
- DBGPRINT(F(" |"));
if(INV_RADIO_TYPE_NRF == q->iv->ivRadioType) {
DBGPRINT(F(" CH"));
if(3 == p->ch)
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index ef37e266..d73b2b0e 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -15,7 +15,6 @@
#endif
#define SPI_SPEED 1000000
-
#define RF_CHANNELS 5
const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"};
@@ -183,17 +182,13 @@ class HmRadio : public Radio {
}
}
return mNRFisInRX;
- } /*else if(tx_fail) {
- mNRFisInRX = false;
- return false;
- }*/
+ }
}
return false;
}
- bool isChipConnected(void) {
- //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:isChipConnected"));
+ bool isChipConnected(void) const {
return mNrf24->isChipConnected();
}
@@ -283,24 +278,16 @@ class HmRadio : public Radio {
sendPacket(iv, cnt, isRetransmit, (IV_MI != iv->ivGen));
}
- uint8_t getDataRate(void) {
+ uint8_t getDataRate(void) const {
if(!mNrf24->isChipConnected())
return 3; // unknown
return mNrf24->getDataRate();
}
- bool isPVariant(void) {
+ bool isPVariant(void) const {
return mNrf24->isPVariant();
}
- uint8_t getARC(void) {
- return mNrf24->getARC();
- }
-
- uint8_t getPLOS(void) {
- return mNrf24->getPLOS();
- }
-
private:
inline bool getReceived(void) {
bool isLastPackage = false;
@@ -315,8 +302,6 @@ class HmRadio : public Radio {
p.len = (len > MAX_RF_PAYLOAD_SIZE) ? MAX_RF_PAYLOAD_SIZE : len;
p.rssi = mNrf24->testRPD() ? -64 : -75;
p.millis = millis() - mMillis;
- p.arc = mNrf24->getARC();
- p.plos = mNrf24->getPLOS();
mNrf24->read(p.packet, p.len);
if (p.packet[0] != 0x00) {
@@ -393,11 +378,11 @@ class HmRadio : public Radio {
mNRFisInRX = false;
}
- uint64_t getIvId(Inverter<> *iv) {
+ uint64_t getIvId(Inverter<> *iv) const {
return iv->radioId.u64;
}
- uint8_t getIvGen(Inverter<> *iv) {
+ uint8_t getIvGen(Inverter<> *iv) const {
return iv->ivGen;
}
diff --git a/src/hm/radio.h b/src/hm/radio.h
index a71e24c7..f7d61e42 100644
--- a/src/hm/radio.h
+++ b/src/hm/radio.h
@@ -27,10 +27,8 @@ class Radio {
virtual void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) = 0;
virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; }
virtual bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; }
- virtual bool isChipConnected(void) { return false; }
+ virtual bool isChipConnected(void) const { return false; }
virtual bool loop(void) = 0;
- virtual uint8_t getARC(void) { return 0xff; }
- virtual uint8_t getPLOS(void) { return 0xff; }
void handleIntr(void) {
mIrqRcvd = true;
@@ -66,7 +64,7 @@ class Radio {
sendPacket(iv, 24, isRetransmit);
}
- uint32_t getDTUSn(void) {
+ uint32_t getDTUSn(void) const {
return mDtuSn;
}
@@ -81,8 +79,8 @@ class Radio {
protected:
virtual void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) = 0;
- virtual uint64_t getIvId(Inverter<> *iv) = 0;
- virtual uint8_t getIvGen(Inverter<> *iv) = 0;
+ virtual uint64_t getIvId(Inverter<> *iv) const = 0;
+ virtual uint8_t getIvGen(Inverter<> *iv) const = 0;
void initPacket(uint64_t ivId, uint8_t mid, uint8_t pid) {
mTxBuf[0] = mid;
diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h
index 48ff3750..2f0a5f31 100644
--- a/src/hms/hmsRadio.h
+++ b/src/hms/hmsRadio.h
@@ -14,8 +14,7 @@ class CmtRadio : public Radio {
typedef Cmt2300a CmtType;
public:
CmtRadio() {
- mDtuSn = DTU_SN;
- mCmtAvail = false;
+ mDtuSn = DTU_SN;
}
void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, bool genDtuSn = true) {
@@ -38,7 +37,7 @@ class CmtRadio : public Radio {
return false;
}
- bool isChipConnected(void) {
+ bool isChipConnected(void) const {
return mCmtAvail;
}
@@ -116,11 +115,11 @@ class CmtRadio : public Radio {
iv->mDtuTxCnt++;
}
- uint64_t getIvId(Inverter<> *iv) {
+ uint64_t getIvId(Inverter<> *iv) const {
return iv->radioId.u64;
}
- uint8_t getIvGen(Inverter<> *iv) {
+ uint8_t getIvGen(Inverter<> *iv) const {
return iv->ivGen;
}
@@ -172,7 +171,7 @@ class CmtRadio : public Radio {
}
CmtType mCmt;
- bool mCmtAvail;
+ bool mCmtAvail = false;
bool mRqstGetRx = false;
uint32_t mMillis;
};
diff --git a/src/web/lang.json b/src/web/lang.json
index 1eece937..9f3df46e 100644
--- a/src/web/lang.json
+++ b/src/web/lang.json
@@ -670,7 +670,7 @@
},
{
"token": "INV_DELETE_SURE",
- "en": "do you realy want to delete inverter?",
+ "en": "do you really want to delete inverter?",
"de": "Willst du den Wechselrichter wirklich löschen?"
},
{
@@ -1070,7 +1070,7 @@
},
{
"token": "WARN_DIFF_ENV",
- "en": "your environment does not match the update file!",
+ "en": "your environment may not match the update file!",
"de": "Die ausgewählte Firmware passt u.U. nicht zum Chipsatz!"
},
{
From d8af39820816baa94c919bb8127a5a1c63b758d8 Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Thu, 25 Jan 2024 08:22:03 +0100
Subject: [PATCH 08/79] pendular version
let rx channel change between tx+2 and tx+3
---
src/hm/Communication.h | 10 +++++-----
src/hm/Heuristic.h | 4 ++--
src/hm/hmDefines.h | 8 ++++++++
src/hm/hmRadio.h | 13 ++++++-------
4 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 38925059..924356e0 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -186,8 +186,8 @@ class Communication : public CommQueue<> {
if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
if(parseFrame(p)) {
q->iv->curFrmCnt++;
- if(!mIsRetransmit && (p->packet[9] == 0x02 || p->packet[9] == 0x82) && p->millis < 85)
- mHeu.setIvRetriesGood(q->iv,p->millis < 70);
+ if(!mIsRetransmit && (p->packet[9] == 0x02 || p->packet[9] == 0x82) && p->millis < LIMIT_FAST_IV)
+ mHeu.setIvRetriesGood(q->iv,p->millis < LIMIT_VERYFAST_IV);
}
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command
if(parseDevCtrl(p, q))
@@ -259,7 +259,7 @@ class Communication : public CommQueue<> {
if(framnr) {
if(0 == q->attempts) {
DPRINT_IVID(DBG_INFO, q->iv->id);
- DBGPRINTLN(F("no attempts left"));
+ DBGPRINTLN(F("timeout, no attempts left"));
closeRequest(q, false);
return;
}
@@ -424,8 +424,8 @@ class Communication : public CommQueue<> {
}
inline bool parseMiFrame(packet_t *p, const queue_s *q) {
- if(!mIsRetransmit && p->packet[9] == 0x00 && p->millis < 35) //first frame is fast?
- mHeu.setIvRetriesGood(q->iv,p->millis < 22);
+ if(!mIsRetransmit && p->packet[9] == 0x00 && p->millis < LIMIT_FAST_IV_MI) //first frame is fast?
+ mHeu.setIvRetriesGood(q->iv,p->millis < LIMIT_VERYFAST_IV_MI);
if ((p->packet[0] == MI_REQ_CH1 + ALL_FRAMES)
|| (p->packet[0] == MI_REQ_CH2 + ALL_FRAMES)
|| ((p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES))
diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h
index 642eca13..3fb86614 100644
--- a/src/hm/Heuristic.h
+++ b/src/hm/Heuristic.h
@@ -159,9 +159,9 @@ class Heuristic {
uint8_t getIvRetries(Inverter<> *iv) {
if(iv->heuristics.rxSpeeds[0])
- return 5;
+ return RETRIES_VERYFAST_IV;
if(iv->heuristics.rxSpeeds[1])
- return 10;
+ return RETRIES_FAST_IV;
return 15;
}
diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h
index 969e4e1b..9235b3f9 100644
--- a/src/hm/hmDefines.h
+++ b/src/hm/hmDefines.h
@@ -94,6 +94,14 @@ enum {INV_RADIO_TYPE_NRF = 0, INV_RADIO_TYPE_CMT};
#define DURATION_PAUSE_LASTFR 45 // how long to pause after last frame (ms)
const uint8_t duration_reserve[2] = {115,115};
+#define LIMIT_FAST_IV 85 // time limit to qualify an inverter as very fast answering inverter
+#define LIMIT_VERYFAST_IV 70 // time limit to qualify an inverter as very fast answering inverter
+#define LIMIT_FAST_IV_MI 35 // time limit to qualify a MI type inverter as fast answering inverter
+#define LIMIT_VERYFAST_IV_MI 22 // time limit to qualify a MI type inverter as very fast answering inverter
+#define RETRIES_FAST_IV 11 // how often shall a message be automatically retransmitted by the nRF (fast answering inverter)
+#define RETRIES_VERYFAST_IV 7 // how often shall a message be automatically retransmitted by the nRF (very fast answering inverter)
+
+
typedef struct {
uint8_t fieldId; // field id
uint8_t unitId; // uint id
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index 0df22f5a..81b27c57 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -124,7 +124,7 @@ class HmRadio : public Radio {
rxPendular = !rxPendular;
//innerLoopTimeout = (rxPendular ? 1 : 2)*DURATION_LISTEN_MIN;
- innerLoopTimeout = DURATION_LISTEN_MIN;
+ //innerLoopTimeout = DURATION_LISTEN_MIN;
if(mNRFloopChannels)
tempRxChIdx = (tempRxChIdx + 4) % RF_CHANNELS;
@@ -154,7 +154,8 @@ class HmRadio : public Radio {
if(tx_ok)
mLastIv->mAckCount++;
- mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
+ //mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
+ mRxChIdx = (mTxChIdx + 3) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening();
mTimeslotStart = millis();
@@ -162,7 +163,8 @@ class HmRadio : public Radio {
rxPendular = false;
mNRFloopChannels = (mLastIv->ivGen == IV_MI);
- innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME;
+ //innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME;
+ innerLoopTimeout = DURATION_LISTEN_MIN;
}
if(rx_ready) {
@@ -186,10 +188,7 @@ class HmRadio : public Radio {
}
rx_ready = false; // reset
return mNRFisInRX;
- } /*else if(tx_fail) {
- mNRFisInRX = false;
- return false;
- }*/
+ }
}
return false;
From 1118407019b7bc543b426a7384dd7828f77c0678 Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Thu, 25 Jan 2024 11:10:44 +0100
Subject: [PATCH 09/79] retransmit review
- look at how many frames are missing first
- more "second try" if inverter is available (dependent on attempts)
---
src/hm/CommQueue.h | 4 ++--
src/hm/Communication.h | 38 +++++++++++++++++++++++++++++---------
src/hm/hmDefines.h | 2 +-
src/hm/hmInverter.h | 28 ++++++++++++++--------------
src/hm/radio.h | 2 +-
5 files changed, 47 insertions(+), 27 deletions(-)
diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h
index d3fe1c69..227e8c33 100644
--- a/src/hm/CommQueue.h
+++ b/src/hm/CommQueue.h
@@ -12,8 +12,8 @@
#include "../utils/dbg.h"
#define DEFAULT_ATTEMPS 5
-#define MORE_ATTEMPS_ALARMDATA 8
-#define MORE_ATTEMPS_GRIDONPROFILEPARA 5
+#define MORE_ATTEMPS_ALARMDATA 0 // 8
+#define MORE_ATTEMPS_GRIDONPROFILEPARA 0 // 5
template
class CommQueue {
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 924356e0..bc7f7236 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -114,11 +114,11 @@ class Communication : public CommQueue<> {
q->iv->radioStatistics.txCnt++;
q->iv->radio->mRadioWaitTime.startTimeMonitor(mTimeout);
+ if(!mIsRetransmit && (q->cmd == AlarmData) || (q->cmd == GridOnProFilePara))
+ incrAttempt(q->cmd == AlarmData? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA);
mIsRetransmit = false;
setAttempt();
- if((q->cmd == AlarmData) || (q->cmd == GridOnProFilePara))
- incrAttempt(q->cmd == AlarmData? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA);
mState = States::WAIT;
break;
@@ -155,7 +155,8 @@ class Communication : public CommQueue<> {
q->iv->mIvTxCnt++;
if(mFirstTry) {
- mFirstTry = false;
+ if(q->attempts < 3 || !q->iv->isProducing())
+ mFirstTry = false;
//setAttempt();
mHeu.evalTxChQuality(q->iv, false, 0, 0);
//q->iv->radioStatistics.rxFailNoAnser++; // should only be one of fail or retransmit.
@@ -209,7 +210,7 @@ class Communication : public CommQueue<> {
if(q->iv->ivGen != IV_MI) {
mState = States::CHECK_PACKAGE;
} else {
- bool fastNext = true;
+ //bool fastNext = true;
if(q->iv->miMultiParts < 6) {
mState = States::WAIT;
if((q->iv->radio->mRadioWaitTime.isTimeout() && mIsRetransmit) || !mIsRetransmit) {
@@ -222,11 +223,11 @@ class Communication : public CommQueue<> {
|| ((q->cmd == MI_REQ_CH2) && (q->iv->type == INV_TYPE_2CH))
|| ((q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH))) {
miComplete(q->iv);
- fastNext = false;
+ //fastNext = false;
}
- if(fastNext)
+ /*if(fastNext)
miNextRequest(q->iv->type == INV_TYPE_4CH ? MI_REQ_4CH : MI_REQ_CH1, q);
- else
+ else*/
closeRequest(q, true);
}
}
@@ -263,6 +264,25 @@ class Communication : public CommQueue<> {
closeRequest(q, false);
return;
}
+ //count missing frames
+ if(!q->iv->mIsSingleframeReq && q->iv->ivRadioType == INV_RADIO_TYPE_NRF) { // already checked?
+ uint8_t missedFrames = 0;
+ for(uint8_t i = 0; i < q->iv->radio->mFramesExpected; i++) {
+ if(mLocalBuf[i].len == 0)
+ missedFrames++;
+ }
+ if(missedFrames > 3 || (q->cmd == RealTimeRunData_Debug && missedFrames > 1) || (missedFrames > 1 && missedFrames + 2 > q->attempts)) {
+ if(*mSerialDebug) {
+ DPRINT_IVID(DBG_INFO, q->iv->id);
+ DBGPRINT(String(missedFrames));
+ DBGPRINT(F(" frames missing "));
+ DBGPRINTLN(F("-> complete retransmit"));
+ }
+ mState = States::RESET;
+ return;
+ }
+ }
+
setAttempt();
if(*mSerialDebug) {
@@ -411,8 +431,8 @@ class Communication : public CommQueue<> {
if((*frameId & ALL_FRAMES) == ALL_FRAMES) {
mMaxFrameId = (*frameId & 0x7f);
- if(mMaxFrameId > 8) // large payloads, e.g. AlarmData
- incrAttempt(mMaxFrameId - 6);
+ /*if(mMaxFrameId > 8) // large payloads, e.g. AlarmData
+ incrAttempt(mMaxFrameId - 6);*/
}
frame_t *f = &mLocalBuf[(*frameId & 0x7f) - 1];
diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h
index 9235b3f9..6bd66e66 100644
--- a/src/hm/hmDefines.h
+++ b/src/hm/hmDefines.h
@@ -92,7 +92,7 @@ enum {INV_RADIO_TYPE_NRF = 0, INV_RADIO_TYPE_CMT};
#define DURATION_TXFRAME 85 // timeout parameter for first transmission and first expected frame (time to first channel switch from tx start!) (ms)
#define DURATION_LISTEN_MIN 5 // time to stay at least on a listening channel (ms)
#define DURATION_PAUSE_LASTFR 45 // how long to pause after last frame (ms)
-const uint8_t duration_reserve[2] = {115,115};
+const uint8_t duration_reserve[2] = {65,115};
#define LIMIT_FAST_IV 85 // time limit to qualify an inverter as very fast answering inverter
#define LIMIT_VERYFAST_IV 70 // time limit to qualify an inverter as very fast answering inverter
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index 049b5501..5ef3752d 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -220,21 +220,21 @@ class Inverter {
cb(RealTimeRunData_Debug, false); // get live data
}
} else { // MI
- if(0 == getFwVersion()) {
- mIvRxCnt +=2;
- cb(0x0f, false); // get firmware version; for MI, this makes part of polling the device software and hardware version number
- } else {
- record_t<> *rec = getRecordStruct(InverterDevInform_Simple);
- if (getChannelFieldValue(CH0, FLD_PART_NUM, rec) == 0) {
- cb(0x0f, false); // hard- and firmware version for missing HW part nr, delivered by frame 1
+ cb(((type == INV_TYPE_4CH) ? MI_REQ_4CH : MI_REQ_CH1), false);
+ mGetLossInterval++;
+ if (type != INV_TYPE_4CH)
+ mIvRxCnt++; // statistics workaround...
+ if(isAvailable()) {
+ if(0 == getFwVersion()) {
mIvRxCnt +=2;
- } else if((getChannelFieldValue(CH0, FLD_GRID_PROFILE_CODE, rec) == 0) && generalConfig->readGrid) // read grid profile
- cb(0x10, false); // legacy GPF command
- else {
- cb(((type == INV_TYPE_4CH) ? MI_REQ_4CH : MI_REQ_CH1), false);
- mGetLossInterval++;
- if (type != INV_TYPE_4CH)
- mIvRxCnt++; // statistics workaround...
+ cb(0x0f, false); // get firmware version; for MI, this makes part of polling the device software and hardware version number
+ } else {
+ record_t<> *rec = getRecordStruct(InverterDevInform_Simple);
+ if (getChannelFieldValue(CH0, FLD_PART_NUM, rec) == 0) {
+ cb(0x0f, false); // hard- and firmware version for missing HW part nr, delivered by frame 1
+ mIvRxCnt +=2;
+ } else if((getChannelFieldValue(CH0, FLD_GRID_PROFILE_CODE, rec) == 0) && generalConfig->readGrid) // read grid profile
+ cb(0x10, false); // legacy GPF command
}
}
}
diff --git a/src/hm/radio.h b/src/hm/radio.h
index e6baf792..ec087f47 100644
--- a/src/hm/radio.h
+++ b/src/hm/radio.h
@@ -79,6 +79,7 @@ class Radio {
uint8_t mIrqOk = IRQ_UNKNOWN;
TimeMonitor mRadioWaitTime = TimeMonitor(0, true); // start as expired (due to code in RESET state)
uint8_t mTxRetriesNext = 15; // let heuristics tell us the next reties count (for nRF type radios only)
+ uint8_t mFramesExpected = 0x0c;
protected:
virtual void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) = 0;
@@ -130,7 +131,6 @@ class Radio {
volatile bool mIrqRcvd;
bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace;
uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE];
- uint8_t mFramesExpected = 0x0c;
};
#endif /*__RADIO_H__*/
From 626ca86d0d14a04f4cb1081fd25cabb9539e1636 Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Fri, 26 Jan 2024 11:31:21 +0100
Subject: [PATCH 10/79] fix statistics
- based on 0.8.65!
---
src/hm/CommQueue.h | 6 ++----
src/hm/Communication.h | 41 ++++++++++++-----------------------------
src/hm/hmRadio.h | 22 +++++-----------------
src/hm/radio.h | 10 ++++------
src/hms/hmsRadio.h | 14 ++++++--------
5 files changed, 29 insertions(+), 64 deletions(-)
diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h
index 227e8c33..d7cc5642 100644
--- a/src/hm/CommQueue.h
+++ b/src/hm/CommQueue.h
@@ -18,8 +18,6 @@
template
class CommQueue {
public:
- CommQueue() {}
-
void addImportant(Inverter<> *iv, uint8_t cmd) {
dec(&mRdPtr);
mQueue[mRdPtr] = queue_s(iv, cmd, true);
@@ -34,12 +32,12 @@ class CommQueue {
mQueue[mWrPtr] = queue_s(iv, cmd, false);
}
- uint8_t getFillState(void) {
+ uint8_t getFillState(void) const {
//DPRINTLN(DBG_INFO, "wr: " + String(mWrPtr) + ", rd: " + String(mRdPtr));
return abs(mRdPtr - mWrPtr);
}
- uint8_t getMaxFill(void) {
+ uint8_t getMaxFill(void) const {
return N;
}
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index bc7f7236..bfb6a4df 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -83,6 +83,7 @@ class Communication : public CommQueue<> {
q->iv->mGotFragment = false;
q->iv->mGotLastMsg = false;
q->iv->curFrmCnt = 0;
+ q->iv->radioStatistics.txCnt++;
mIsRetransmit = false;
if(NULL == q->iv->radio)
cmdDone(false); // can't communicate while radio is not defined!
@@ -112,7 +113,7 @@ class Communication : public CommQueue<> {
} else
q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false);
- q->iv->radioStatistics.txCnt++;
+ //q->iv->radioStatistics.txCnt++;
q->iv->radio->mRadioWaitTime.startTimeMonitor(mTimeout);
if(!mIsRetransmit && (q->cmd == AlarmData) || (q->cmd == GridOnProFilePara))
incrAttempt(q->cmd == AlarmData? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA);
@@ -129,22 +130,13 @@ class Communication : public CommQueue<> {
break;
case States::CHECK_FRAMES: {
- if((q->iv->radio->mBufCtrl.empty() && !mIsRetransmit) ) { // || (0 == q->attempts)) { // radio buffer empty or no more answers
+ if((q->iv->radio->mBufCtrl.empty() && !mIsRetransmit) ) { // || (0 == q->attempts)) { // radio buffer empty. No more answers will be checked later
if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("request timeout: "));
DBGPRINT(String(q->iv->radio->mRadioWaitTime.getRunTime()));
DBGPRINTLN(F("ms"));
- /*if(INV_RADIO_TYPE_NRF == q->iv->ivRadioType) {
- DBGPRINT(F(", retries "));
- DBGPRINTLN(String(q->iv->radio->mTxRetriesNext));
- DBGPRINT(F(", ARC "));
- DBGPRINT(String(q->iv->radio->getARC()));
- DBGPRINT(F(", PLOS "));
- DBGPRINTLN(String(q->iv->radio->getPLOS()));
- } else
- DBGPRINTLN("");*/
- }
+ }
if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, (q->iv->config->frequency*FREQ_STEP_KHZ + HOY_BASE_FREQ_KHZ));
@@ -157,14 +149,13 @@ class Communication : public CommQueue<> {
if(mFirstTry) {
if(q->attempts < 3 || !q->iv->isProducing())
mFirstTry = false;
- //setAttempt();
mHeu.evalTxChQuality(q->iv, false, 0, 0);
+ mHeu.getTxCh(q->iv);
//q->iv->radioStatistics.rxFailNoAnser++; // should only be one of fail or retransmit.
- q->iv->radioStatistics.txCnt--;
+ //q->iv->radioStatistics.txCnt--;
q->iv->radioStatistics.retransmits++;
q->iv->radio->mRadioWaitTime.stopTimeMonitor();
mState = States::START;
-
return;
}
}
@@ -210,7 +201,6 @@ class Communication : public CommQueue<> {
if(q->iv->ivGen != IV_MI) {
mState = States::CHECK_PACKAGE;
} else {
- //bool fastNext = true;
if(q->iv->miMultiParts < 6) {
mState = States::WAIT;
if((q->iv->radio->mRadioWaitTime.isTimeout() && mIsRetransmit) || !mIsRetransmit) {
@@ -223,12 +213,8 @@ class Communication : public CommQueue<> {
|| ((q->cmd == MI_REQ_CH2) && (q->iv->type == INV_TYPE_2CH))
|| ((q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH))) {
miComplete(q->iv);
- //fastNext = false;
}
- /*if(fastNext)
- miNextRequest(q->iv->type == INV_TYPE_4CH ? MI_REQ_4CH : MI_REQ_CH1, q);
- else*/
- closeRequest(q, true);
+ closeRequest(q, true);
}
}
@@ -278,6 +264,8 @@ class Communication : public CommQueue<> {
DBGPRINT(F(" frames missing "));
DBGPRINTLN(F("-> complete retransmit"));
}
+ q->iv->radioStatistics.txCnt--;
+ q->iv->radioStatistics.retransmits++;
mState = States::RESET;
return;
}
@@ -318,11 +306,6 @@ class Communication : public CommQueue<> {
DBGPRINT(String(p->millis));
DBGPRINT(F("ms | "));
DBGPRINT(String(p->len));
- /*DBGPRINT(F(", ARC "));
- DBGPRINT(String(p->arc));
- DBGPRINT(F(", PLOS "));
- DBGPRINT(String(p->plos));*/
- DBGPRINT(F(" |"));
if(INV_RADIO_TYPE_NRF == q->iv->ivRadioType) {
DBGPRINT(F(" CH"));
if(3 == p->ch)
@@ -555,7 +538,7 @@ class Communication : public CommQueue<> {
len -= 2;
- //DPRINT_IVID(DBG_INFO, q->iv->id);
+ //DPRINT_IVID(DBG_INFO, q->iv->id); // it's already above "for"-loop
DBGPRINT(F("Payload ("));
DBGPRINT(String(len));
if(*mPrintWholeTrace) {
@@ -856,8 +839,8 @@ class Communication : public CommQueue<> {
DBGHEXLN(cmd);
}
- //if(q->iv->miMultiParts > 5) //if(q->iv->miMultiParts == 7)
- q->iv->radioStatistics.rxSuccess++;
+ /*if(q->iv->miMultiParts > 5) //if(q->iv->miMultiParts == 7)
+ q->iv->radioStatistics.rxSuccess++;*/
q->iv->radioStatistics.ivSent++;
mFramesExpected = getFramesExpected(q);
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index 81b27c57..bc1e3652 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -15,7 +15,6 @@
#endif
#define SPI_SPEED 1000000
-
#define RF_CHANNELS 5
const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"};
@@ -194,8 +193,7 @@ class HmRadio : public Radio {
return false;
}
- bool isChipConnected(void) {
- //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:isChipConnected"));
+ bool isChipConnected(void) const {
return mNrf24->isChipConnected();
}
@@ -285,24 +283,16 @@ class HmRadio : public Radio {
sendPacket(iv, cnt, isRetransmit, (IV_MI != iv->ivGen));
}
- uint8_t getDataRate(void) {
+ uint8_t getDataRate(void) const {
if(!mNrf24->isChipConnected())
return 3; // unknown
return mNrf24->getDataRate();
}
- bool isPVariant(void) {
+ bool isPVariant(void) const {
return mNrf24->isPVariant();
}
- /*uint8_t getARC(void) {
- return mNrf24->getARC();
- }
-
- uint8_t getPLOS(void) {
- return mNrf24->getPLOS();
- }*/
-
private:
inline bool getReceived(void) {
bool isLastPackage = false;
@@ -318,8 +308,6 @@ class HmRadio : public Radio {
p.len = (len > MAX_RF_PAYLOAD_SIZE) ? MAX_RF_PAYLOAD_SIZE : len;
p.rssi = mNrf24->testRPD() ? -64 : -75;
p.millis = millis() - mMillis;
- //p.arc = mNrf24->getARC();
- //p.plos = mNrf24->getPLOS();
mNrf24->read(p.packet, p.len);
if (p.packet[0] != 0x00) {
@@ -411,11 +399,11 @@ class HmRadio : public Radio {
mNRFisInRX = false;
}
- uint64_t getIvId(Inverter<> *iv) {
+ uint64_t getIvId(Inverter<> *iv) const {
return iv->radioId.u64;
}
- uint8_t getIvGen(Inverter<> *iv) {
+ uint8_t getIvGen(Inverter<> *iv) const {
return iv->ivGen;
}
diff --git a/src/hm/radio.h b/src/hm/radio.h
index ec087f47..ea6d8c05 100644
--- a/src/hm/radio.h
+++ b/src/hm/radio.h
@@ -27,10 +27,8 @@ class Radio {
virtual void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) = 0;
virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; }
virtual bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; }
- virtual bool isChipConnected(void) { return false; }
+ virtual bool isChipConnected(void) const { return false; }
virtual bool loop(void) = 0;
- //virtual uint8_t getARC(void) { return 0xff; }
- //virtual uint8_t getPLOS(void) { return 0xff; }
void handleIntr(void) {
mIrqRcvd = true;
@@ -66,7 +64,7 @@ class Radio {
sendPacket(iv, 24, isRetransmit);
}
- uint32_t getDTUSn(void) {
+ uint32_t getDTUSn(void) const {
return mDtuSn;
}
@@ -83,8 +81,8 @@ class Radio {
protected:
virtual void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) = 0;
- virtual uint64_t getIvId(Inverter<> *iv) = 0;
- virtual uint8_t getIvGen(Inverter<> *iv) = 0;
+ virtual uint64_t getIvId(Inverter<> *iv) const = 0;
+ virtual uint8_t getIvGen(Inverter<> *iv) const = 0;
void initPacket(uint64_t ivId, uint8_t mid, uint8_t pid) {
mTxBuf[0] = mid;
diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h
index 3c569e02..33b6a75c 100644
--- a/src/hms/hmsRadio.h
+++ b/src/hms/hmsRadio.h
@@ -14,8 +14,7 @@ class CmtRadio : public Radio {
typedef Cmt2300a CmtType;
public:
CmtRadio() {
- mDtuSn = DTU_SN;
- mCmtAvail = false;
+ mDtuSn = DTU_SN;
}
void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, bool genDtuSn = true) {
@@ -38,7 +37,7 @@ class CmtRadio : public Radio {
return false;
}
- bool isChipConnected(void) {
+ bool isChipConnected(void) const {
return mCmtAvail;
}
@@ -116,11 +115,11 @@ class CmtRadio : public Radio {
iv->mDtuTxCnt++;
}
- uint64_t getIvId(Inverter<> *iv) {
+ uint64_t getIvId(Inverter<> *iv) const {
return iv->radioId.u64;
}
- uint8_t getIvGen(Inverter<> *iv) {
+ uint8_t getIvGen(Inverter<> *iv) const {
return iv->ivGen;
}
@@ -165,11 +164,10 @@ class CmtRadio : public Radio {
if(CMT_SUCCESS == status)
mBufCtrl.push(p);
- // this code completly stops communication!
if(p.packet[9] > ALL_FRAMES) // indicates last frame
- // mRadioWaitTime.stopTimeMonitor(); // we got everything we expected and can exit rx mode...
- //optionally instead:
mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first get back to rx mode?
+ // optionally instead:
+ // mRadioWaitTime.stopTimeMonitor(); // we got everything we expected and can exit rx mode...
}
CmtType mCmt;
From 19184727bc0251c26dc606c7be2e1f10404954a5 Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Sat, 27 Jan 2024 09:37:55 +0100
Subject: [PATCH 11/79] add data request to PowerLimit update req.
---
src/hm/Communication.h | 11 ++++++++---
src/hm/hmInverter.h | 5 +++--
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index bfb6a4df..23ffe158 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -264,8 +264,10 @@ 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);
q->iv->radioStatistics.txCnt--;
q->iv->radioStatistics.retransmits++;
+ mCompleteRetry = true;
mState = States::RESET;
return;
}
@@ -511,6 +513,7 @@ class Communication : public CommQueue<> {
} else
DBGPRINTLN(F("-> complete retransmit"));
+ mCompleteRetry = true;
mState = States::RESET;
return;
}
@@ -611,7 +614,7 @@ class Communication : public CommQueue<> {
mHeu.evalTxChQuality(q->iv, crcPass, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt);
if(crcPass)
q->iv->radioStatistics.rxSuccess++;
- else if(q->iv->mGotFragment)
+ else if(q->iv->mGotFragment || mCompleteRetry)
q->iv->radioStatistics.rxFail++; // got no complete payload
else
q->iv->radioStatistics.rxFailNoAnser++; // got nothing
@@ -626,6 +629,7 @@ class Communication : public CommQueue<> {
q->iv->mGotLastMsg = false;
q->iv->miMultiParts = 0;
mIsRetransmit = false;
+ mCompleteRetry = false;
mState = States::RESET;
DBGPRINTLN(F("-----"));
}
@@ -1020,8 +1024,9 @@ class Communication : public CommQueue<> {
uint16_t *mInverterGap;
TimeMonitor mWaitTime = TimeMonitor(0, true); // start as expired (due to code in RESET state)
std::array mLocalBuf;
- bool mFirstTry = false; // see, if we should do a second try
- bool mIsRetransmit = false; // we already had waited one complete cycle
+ bool mFirstTry = false; // see, if we should do a second try
+ bool mCompleteRetry = false; // remember if we did request a complete retransmission
+ bool mIsRetransmit = false; // we already had waited one complete cycle
uint8_t mMaxFrameId;
uint8_t mFramesExpected = 12; // 0x8c was highest last frame for alarm data
uint16_t mTimeout = 0; // calculating that once should be ok
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index 5ef3752d..bcf732ea 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -194,9 +194,10 @@ class Inverter {
if(mNextLive)
cb(RealTimeRunData_Debug, false); // get live data
else {
- if(actPowerLimit == 0xffff)
+ if(actPowerLimit == 0xffff) {
cb(SystemConfigPara, false); // power limit info
- else if(InitDataState != devControlCmd) {
+ cb(RealTimeRunData_Debug, false);
+ } else if(InitDataState != devControlCmd) {
cb(devControlCmd, false); // custom command which was received by API
devControlCmd = InitDataState;
mGetLossInterval = 1;
From 1b4b5874df3c7252c2a4b7dd7f681823b07d2f27 Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Sat, 27 Jan 2024 17:52:08 +0100
Subject: [PATCH 12/79] Individual rx-channel offset
per inverter (based on serial, but unfortunately not working yet)
---
src/hm/hmInverter.h | 2 +-
src/hm/hmRadio.h | 9 ++++++---
src/hm/hmSystem.h | 2 ++
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index bcf732ea..00f05c79 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -133,6 +133,7 @@ class Inverter {
bool isConnected; // shows if inverter was successfully identified (fw version and hardware info)
InverterStatus status; // indicates the current inverter status
std::array lastAlarm; // holds last 10 alarms
+ uint8_t rxOffset; // holds the default channel offset between tx and rx channel (nRF only)
int8_t rssi; // RSSI
uint16_t alarmCnt; // counts the total number of occurred alarms
uint16_t alarmLastId; // lastId which was received
@@ -179,7 +180,6 @@ class Inverter {
tsMaxAcPower = 0;
memset(&radioStatistics, 0, sizeof(statistics_t));
- memset(heuristics.txRfQuality, -6, 5);
memset(mOffYD, 0, sizeof(float) * 6);
memset(mLastYD, 0, sizeof(float) * 6);
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index bc1e3652..fbb23b57 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -154,11 +154,11 @@ class HmRadio : public Radio {
mLastIv->mAckCount++;
//mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
- mRxChIdx = (mTxChIdx + 3) % RF_CHANNELS;
+ mRxChIdx = (mTxChIdx + mLastIv->rxOffset) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening();
mTimeslotStart = millis();
- tempRxChIdx = mRxChIdx;
+ tempRxChIdx = mRxChIdx; // might be better to start off with one channel less?
rxPendular = false;
mNRFloopChannels = (mLastIv->ivGen == IV_MI);
@@ -369,7 +369,10 @@ class HmRadio : public Radio {
DBGPRINT(String(mRfChLst[mTxChIdx]));
DBGPRINT(F(", "));
DBGPRINT(String(mTxRetriesNext));
- DBGPRINT(F(" retries | "));
+ //DBGPRINT(F(" retries | "));
+ DBGPRINT(F(" ret., rx offset: "));
+ DBGPRINT(String(iv->rxOffset));
+ DBGPRINT(F(" | "));
if(*mPrintWholeTrace) {
if(*mPrivacyMode)
ah::dumpBuf(mTxBuf, len, 1, 4);
diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h
index 8229378e..1e8641cb 100644
--- a/src/hm/hmSystem.h
+++ b/src/hm/hmSystem.h
@@ -28,6 +28,8 @@ class HmSystem {
iv->config = &mInverter[0].generalConfig->iv[id];
DPRINT(DBG_VERBOSE, "SERIAL: " + String(iv->config->serial.b[5], HEX));
DPRINTLN(DBG_VERBOSE, " " + String(iv->config->serial.b[4], HEX));
+ //iv->rxOffset = 5 - (iv->config->serial.b[2] % 5); //RF_CHANNELS;
+ iv->rxOffset = (iv->config->serial.b[1] % 5); //RF_CHANNELS;
if((iv->config->serial.b[5] == 0x11) || (iv->config->serial.b[5] == 0x10)) {
switch(iv->config->serial.b[4]) {
case 0x24: // HMS-500
From dc696d727fa0eecff28e301febe1f3f72fe8a09f Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 28 Jan 2024 23:32:44 +0100
Subject: [PATCH 13/79] 0.8.66 * added support for other regions - untested
#1271 * fix generation of DTU-ID; was computed twice without reset if two
radios are enabled
---
src/CHANGES.md | 4 +
src/app.cpp | 2 +-
src/config/settings.h | 14 ++-
src/defines.h | 2 +-
src/hm/Communication.h | 2 +-
src/hm/hmDefines.h | 8 --
src/hm/hmInverter.h | 2 -
src/hm/radio.h | 9 +-
src/hms/cmt2300a.h | 259 +++++++++++++++++++++++++---------------
src/hms/hmsRadio.h | 34 ++++--
src/web/RestApi.h | 5 +
src/web/html/setup.html | 25 +++-
src/web/lang.json | 10 ++
src/web/web.h | 3 +-
14 files changed, 251 insertions(+), 128 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index b8547302..7f544e69 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,9 @@
# Development Changes
+## 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
diff --git a/src/app.cpp b/src/app.cpp
index 9f569259..a14a8811 100644
--- a/src/app.cpp
+++ b/src/app.cpp
@@ -47,7 +47,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);
+ 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
diff --git a/src/config/settings.h b/src/config/settings.h
index d8c93b10..e074d5b1 100644
--- a/src/config/settings.h
+++ b/src/config/settings.h
@@ -30,7 +30,7 @@
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
* */
-#define CONFIG_VERSION 9
+#define CONFIG_VERSION 10
#define PROT_MASK_INDEX 0x0001
@@ -68,6 +68,8 @@ typedef struct {
uint16_t protectionMask;
bool darkMode;
bool schedReboot;
+ uint8_t region;
+ int8_t timezone;
#if !defined(ETHERNET)
// wifi
@@ -395,6 +397,8 @@ class settings {
#endif /* !defined(ETHERNET) */
snprintf(mCfg.sys.deviceName, DEVNAME_LEN, DEF_DEVICE_NAME);
+ mCfg.sys.region = 0; // Europe
+ mCfg.sys.timezone = 1;
mCfg.nrf.pinCs = DEF_NRF_CS_PIN;
mCfg.nrf.pinCe = DEF_NRF_CE_PIN;
@@ -512,6 +516,10 @@ class settings {
if(mCfg.configVersion < 9) {
mCfg.inst.gapMs = 1;
}
+ if(mCfg.configVersion < 10) {
+ mCfg.sys.region = 0; // Europe
+ mCfg.sys.timezone = 1;
+ }
}
}
@@ -537,6 +545,8 @@ class settings {
obj[F("prot_mask")] = mCfg.sys.protectionMask;
obj[F("dark")] = mCfg.sys.darkMode;
obj[F("reb")] = (bool) mCfg.sys.schedReboot;
+ obj[F("region")] = mCfg.sys.region;
+ obj[F("timezone")] = mCfg.sys.timezone;
ah::ip2Char(mCfg.sys.ip.ip, buf); obj[F("ip")] = String(buf);
ah::ip2Char(mCfg.sys.ip.mask, buf); obj[F("mask")] = String(buf);
ah::ip2Char(mCfg.sys.ip.dns1, buf); obj[F("dns1")] = String(buf);
@@ -554,6 +564,8 @@ class settings {
getVal(obj, F("prot_mask"), &mCfg.sys.protectionMask);
getVal(obj, F("dark"), &mCfg.sys.darkMode);
getVal(obj, F("reb"), &mCfg.sys.schedReboot);
+ getVal(obj, F("region"), &mCfg.sys.region);
+ getVal(obj, F("timezone"), &mCfg.sys.timezone);
if(obj.containsKey(F("ip"))) ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as());
if(obj.containsKey(F("mask"))) ah::ip2Arr(mCfg.sys.ip.mask, obj[F("mask")].as());
if(obj.containsKey(F("dns1"))) ah::ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")].as());
diff --git a/src/defines.h b/src/defines.h
index ed975b7a..786908d0 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 65
+#define VERSION_PATCH 66
//-------------------------------------
typedef struct {
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 3a6fdd0b..ae97dbb2 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -138,7 +138,7 @@ class Communication : public CommQueue<> {
}
if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
- q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, (q->iv->config->frequency*FREQ_STEP_KHZ + HOY_BASE_FREQ_KHZ));
+ q->iv->radio->switchFrequency(q->iv, q->iv->radio->getBootFreqMhz() * 1000, (q->iv->config->frequency*FREQ_STEP_KHZ + q->iv->radio->getBaseFreqMhz() * 1000));
mWaitTime.startTimeMonitor(1000);
} else {
if(IV_MI == q->iv->ivGen)
diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h
index 969e4e1b..8df06dc1 100644
--- a/src/hm/hmDefines.h
+++ b/src/hm/hmDefines.h
@@ -78,14 +78,6 @@ enum {CH0 = 0, CH1, CH2, CH3, CH4, CH5, CH6};
enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH, INV_TYPE_6CH};
enum {INV_RADIO_TYPE_NRF = 0, INV_RADIO_TYPE_CMT};
-#define WORK_FREQ_KHZ 865000 // desired work frequency between DTU and
- // inverter in kHz
-#define HOY_BASE_FREQ_KHZ 860000 // in kHz
-#define HOY_MAX_FREQ_KHZ 923500 // 0xFE * 250kHz + Base_freq
-#define HOY_BOOT_FREQ_KHZ 868000 // Hoymiles boot/init frequency after power up inverter
-#define FREQ_STEP_KHZ 250 // channel step size in kHz
-#define FREQ_WARN_MIN_KHZ 863000 // for EU 863 - 870 MHz is allowed
-#define FREQ_WARN_MAX_KHZ 870000 // for EU 863 - 870 MHz is allowed
#define DURATION_ONEFRAME 50 // timeout parameter for each expected frame (ms)
//#define DURATION_RESERVE {90,120} // timeout parameter to still wait after last expected frame (ms)
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index b28682e5..cc73cb0b 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -179,8 +179,6 @@ class Inverter {
tsMaxAcPower = 0;
memset(&radioStatistics, 0, sizeof(statistics_t));
- memset(heuristics.txRfQuality, -6, 5);
-
memset(mOffYD, 0, sizeof(float) * 6);
memset(mLastYD, 0, sizeof(float) * 6);
}
diff --git a/src/hm/radio.h b/src/hm/radio.h
index f7d61e42..907a2023 100644
--- a/src/hm/radio.h
+++ b/src/hm/radio.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
//-----------------------------------------------------------------------------
@@ -28,6 +28,9 @@ class Radio {
virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; }
virtual bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; }
virtual bool isChipConnected(void) const { return false; }
+ 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;
void handleIntr(void) {
@@ -113,6 +116,7 @@ class Radio {
chipID = ESP.getChipId();
#endif
+ mDtuSn = 0;
uint8_t t;
for(int i = 0; i < (7 << 2); i += 4) {
t = (chipID >> i) & 0x0f;
@@ -121,7 +125,8 @@ class Radio {
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;
volatile bool mIrqRcvd;
diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h
index 1ff112e2..524472f0 100644
--- a/src/hms/cmt2300a.h
+++ b/src/hms/cmt2300a.h
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
-// 2023 Ahoy, https://github.com/lumpapu/ahoy
+// 2024 Ahoy, https://github.com/lumpapu/ahoy
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
//-----------------------------------------------------------------------------
@@ -12,8 +12,23 @@
#include "esp32_3wSpi.h"
#endif
-// detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf
+#include
+
+enum class RegionCfg : uint8_t {
+ EUROPE, USA, BRAZIL, NUM
+};
+
+enum class CmtStatus : uint8_t {
+ SUCCESS = 0,
+ ERR_SWITCH_STATE,
+ ERR_TX_PENDING,
+ FIFO_EMPTY,
+ ERR_RX_IN_FIFO
+};
+
+#define FREQ_STEP_KHZ 250 // channel step size in kHz
+// detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf
#define CMT2300A_MASK_CFG_RETAIN 0x10
#define CMT2300A_MASK_RSTN_IN_EN 0x20
#define CMT2300A_MASK_LOCKING_EN 0x20
@@ -152,67 +167,6 @@
#define CMT2300A_MASK_TX_DONE_FLG 0x08
#define CMT2300A_MASK_PKT_OK_FLG 0x01
-// this list and the TX5, TX10 registers were compiled from the output of
-// HopeRF RFPDK Tool v1.54
-static uint8_t paLevelList[31][2] PROGMEM = {
- {0x17, 0x01}, // -10dBm
- {0x1a, 0x01}, // -09dBm
- {0x1d, 0x01}, // -08dBm
- {0x21, 0x01}, // -07dBm
- {0x25, 0x01}, // -06dBm
- {0x29, 0x01}, // -05dBm
- {0x2d, 0x01}, // -04dBm
- {0x33, 0x01}, // -03dBm
- {0x39, 0x02}, // -02dBm
- {0x41, 0x02}, // -01dBm
- {0x4b, 0x02}, // 00dBm
- {0x56, 0x03}, // 01dBm
- {0x63, 0x03}, // 02dBm
- {0x71, 0x04}, // 03dBm
- {0x80, 0x04}, // 04dBm
- {0x22, 0x01}, // 05dBm
- {0x27, 0x04}, // 06dBm
- {0x2c, 0x05}, // 07dBm
- {0x31, 0x06}, // 08dBm
- {0x38, 0x06}, // 09dBm
- {0x3f, 0x07}, // 10dBm
- {0x48, 0x08}, // 11dBm
- {0x52, 0x09}, // 12dBm
- {0x5d, 0x0b}, // 13dBm
- {0x6a, 0x0c}, // 14dBm
- {0x79, 0x0d}, // 15dBm
- {0x46, 0x10}, // 16dBm
- {0x51, 0x10}, // 17dBm
- {0x60, 0x12}, // 18dBm
- {0x71, 0x14}, // 19dBm
- {0x8c, 0x1c} // 20dBm
-};
-
-// default CMT parameters
-static uint8_t cmtConfig[0x60] PROGMEM {
- // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm
- 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08,
- 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00,
- // 0x10 - 0x1f
- 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81,
- 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 860MHz as default
- // 0x20 - 0x2f
- 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A,
- 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53,
- // 0x30 - 0x3f
- 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00,
- // 0x40 - 0x4f
- 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1F, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60,
- // 0x50 - 0x5f
- 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06,
- 0x00, 0x07, 0x50, 0x00, 0x5D, 0x0B, 0x3F, 0x7F // - TX 13dBm
-};
-
-
-enum {CMT_SUCCESS = 0, CMT_ERR_SWITCH_STATE, CMT_ERR_TX_PENDING, CMT_FIFO_EMPTY, CMT_ERR_RX_IN_FIFO};
-
class Cmt2300a {
public:
Cmt2300a() {}
@@ -234,12 +188,12 @@ class Cmt2300a {
}
}
- uint8_t goRx(void) {
+ CmtStatus goRx(void) {
if(mTxPending)
- return CMT_ERR_TX_PENDING;
+ return CmtStatus::ERR_TX_PENDING;
if(mInRxMode)
- return CMT_SUCCESS;
+ return CmtStatus::SUCCESS;
mSpi.readReg(CMT2300A_CUS_INT1_CTL);
mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE);
@@ -260,47 +214,47 @@ class Cmt2300a {
mSpi.writeReg(0x16, 0x0C); // [4:3]: RSSI_DET_SEL, [2:0]: RSSI_AVG_MODE
if(!cmtSwitchStatus(CMT2300A_GO_RX, CMT2300A_STA_RX))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
mInRxMode = true;
- return CMT_SUCCESS;
+ return CmtStatus::SUCCESS;
}
- uint8_t getRx(uint8_t buf[], uint8_t *rxLen, uint8_t maxlen, int8_t *rssi) {
+ CmtStatus getRx(uint8_t buf[], uint8_t *rxLen, uint8_t maxlen, int8_t *rssi) {
if(mTxPending)
- return CMT_ERR_TX_PENDING;
+ return CmtStatus::ERR_TX_PENDING;
if(0x1b != (mSpi.readReg(CMT2300A_CUS_INT_FLAG) & 0x1b))
- return CMT_FIFO_EMPTY;
+ return CmtStatus::FIFO_EMPTY;
// receive ok (pream, sync, node, crc)
if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
mSpi.readFifo(buf, rxLen, maxlen);
*rssi = mSpi.readReg(CMT2300A_CUS_RSSI_DBM) - 128;
if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
mInRxMode = false;
mCusIntFlag = mSpi.readReg(CMT2300A_CUS_INT_FLAG);
- return CMT_SUCCESS;
+ return CmtStatus::SUCCESS;
}
- uint8_t tx(uint8_t buf[], uint8_t len) {
+ CmtStatus tx(uint8_t buf[], uint8_t len) {
if(mTxPending)
- return CMT_ERR_TX_PENDING;
+ return CmtStatus::ERR_TX_PENDING;
if(mInRxMode) {
mInRxMode = false;
if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
}
mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE);
@@ -325,16 +279,17 @@ class Cmt2300a {
}
if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
// wait for tx done
mTxPending = true;
- return CMT_SUCCESS;
+ return CmtStatus::SUCCESS;
}
// initialize CMT2300A, returns true on success
- bool reset(void) {
+ bool reset(RegionCfg region) {
+ mRegionCfg = region;
mSpi.writeReg(0x7f, 0xff); // soft reset
delay(30);
@@ -346,10 +301,19 @@ class Cmt2300a {
if(mSpi.readReg(0x62) != 0x20)
return false; // not connected!
- for(uint8_t i = 0; i < 0x60; i++) {
+ for(uint8_t i = 0; i < 0x18; i++) {
+ mSpi.writeReg(i, cmtConfig[i]);
+ }
+ for(uint8_t i = 0; i < 8; i++) {
+ mSpi.writeReg(0x18 + i, mBaseFreqCfg[static_cast(region)][i]);
+ }
+ for(uint8_t i = 0x20; i < 0x60; i++) {
mSpi.writeReg(i, cmtConfig[i]);
}
+ if(RegionCfg::EUROPE != region)
+ mSpi.writeReg(0x27, 0x0B);
+
mSpi.writeReg(CMT2300A_CUS_IO_SEL, 0x20); // -> GPIO3_SEL[1:0] = 0x02
@@ -389,23 +353,14 @@ class Cmt2300a {
}
inline uint8_t freq2Chan(const uint32_t freqKhz) {
- if((freqKhz % FREQ_STEP_KHZ) != 0) {
- DPRINT(DBG_WARN, F("switch frequency to "));
- DBGPRINT(String(freqKhz));
- DBGPRINT(F("kHz not possible!"));
+ if((freqKhz % FREQ_STEP_KHZ) != 0)
return 0xff; // error
- // apply the nearest frequency
- //freqKhz = (freqKhz + FREQ_STEP_KHZ/2) / FREQ_STEP_KHZ;
- //freqKhz *= FREQ_STEP_KHZ;
- }
- if((freqKhz < HOY_BASE_FREQ_KHZ) || (freqKhz > HOY_MAX_FREQ_KHZ))
+ std::pair range = getFreqRangeMhz();
+ if((freqKhz < range.first) || (freqKhz > range.second))
return 0xff; // error
- if((freqKhz < FREQ_WARN_MIN_KHZ) || (freqKhz > FREQ_WARN_MAX_KHZ))
- DPRINTLN(DBG_WARN, F("Desired frequency is out of EU legal range! (863 - 870MHz)"));
-
- return (freqKhz - HOY_BASE_FREQ_KHZ) / FREQ_STEP_KHZ;
+ return (freqKhz - getBaseFreqMhz()) / FREQ_STEP_KHZ;
}
inline void switchChannel(uint8_t ch) {
@@ -414,9 +369,9 @@ class Cmt2300a {
inline uint32_t getFreqKhz(void) {
if(0xff != mRqstCh)
- return HOY_BASE_FREQ_KHZ + (mRqstCh * FREQ_STEP_KHZ);
+ return getBaseFreqMhz() + (mRqstCh * FREQ_STEP_KHZ);
else
- return HOY_BASE_FREQ_KHZ + (mCurCh * FREQ_STEP_KHZ);
+ return getBaseFreqMhz() + (mCurCh * FREQ_STEP_KHZ);
}
uint8_t getCurrentChannel(void) {
@@ -443,6 +398,114 @@ class Cmt2300a {
mSpi.writeReg(CMT2300A_CUS_TX9, paLevelList[level][1]);
}
+ public:
+ uint16_t getBaseFreqMhz(void) {
+ switch(mRegionCfg) {
+ default:
+ [[fallthrough]];
+ case RegionCfg::EUROPE:
+ break;
+ case RegionCfg::USA:
+ return 905;
+ case RegionCfg::BRAZIL:
+ return 915;
+ }
+ return 860;
+ }
+
+ uint16_t getBootFreqMhz(void) {
+ switch(mRegionCfg) {
+ default:
+ [[fallthrough]];
+ case RegionCfg::EUROPE:
+ break;
+ case RegionCfg::USA:
+ return 915;
+ case RegionCfg::BRAZIL:
+ return 915;
+ }
+ return 868;
+ }
+
+ std::pair getFreqRangeMhz(void) {
+ switch(mRegionCfg) {
+ default:
+ [[fallthrough]];
+ case RegionCfg::EUROPE:
+ break;
+ case RegionCfg::USA:
+ return std::make_pair(905, 925);
+ case RegionCfg::BRAZIL:
+ return std::make_pair(915, 928);
+ }
+ return std::make_pair(860, 870); // Europe
+ }
+
+ private:
+ // this list and the TX5, TX10 registers were compiled from the output of
+ // HopeRF RFPDK Tool v1.54
+ constexpr static uint8_t paLevelList[31][2] PROGMEM = {
+ {0x17, 0x01}, // -10dBm
+ {0x1a, 0x01}, // -09dBm
+ {0x1d, 0x01}, // -08dBm
+ {0x21, 0x01}, // -07dBm
+ {0x25, 0x01}, // -06dBm
+ {0x29, 0x01}, // -05dBm
+ {0x2d, 0x01}, // -04dBm
+ {0x33, 0x01}, // -03dBm
+ {0x39, 0x02}, // -02dBm
+ {0x41, 0x02}, // -01dBm
+ {0x4b, 0x02}, // 00dBm
+ {0x56, 0x03}, // 01dBm
+ {0x63, 0x03}, // 02dBm
+ {0x71, 0x04}, // 03dBm
+ {0x80, 0x04}, // 04dBm
+ {0x22, 0x01}, // 05dBm
+ {0x27, 0x04}, // 06dBm
+ {0x2c, 0x05}, // 07dBm
+ {0x31, 0x06}, // 08dBm
+ {0x38, 0x06}, // 09dBm
+ {0x3f, 0x07}, // 10dBm
+ {0x48, 0x08}, // 11dBm
+ {0x52, 0x09}, // 12dBm
+ {0x5d, 0x0b}, // 13dBm
+ {0x6a, 0x0c}, // 14dBm
+ {0x79, 0x0d}, // 15dBm
+ {0x46, 0x10}, // 16dBm
+ {0x51, 0x10}, // 17dBm
+ {0x60, 0x12}, // 18dBm
+ {0x71, 0x14}, // 19dBm
+ {0x8c, 0x1c} // 20dBm
+ };
+
+ // default CMT parameters
+ constexpr static uint8_t cmtConfig[0x60] PROGMEM {
+ // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm
+ 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08,
+ 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00,
+ // 0x10 - 0x1f
+ 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81,
+ 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 860MHz as default
+ // 0x20 - 0x2f
+ 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A,
+ 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53,
+ // 0x30 - 0x3f
+ 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00,
+ // 0x40 - 0x4f
+ 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1F, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60,
+ // 0x50 - 0x5f
+ 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06,
+ 0x00, 0x07, 0x50, 0x00, 0x5D, 0x0B, 0x3F, 0x7F // TX 13dBm
+ };
+
+ constexpr static uint8_t mBaseFreqCfg[static_cast(RegionCfg::NUM)][8] {
+ {0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12}, // 860MHz
+ {0x45, 0xA8, 0x31, 0x8A, 0x45, 0x9D, 0xD8, 0x19}, // 905MHz (USA, Indonesia)
+ {0x46, 0x6D, 0x80, 0x86, 0x46, 0x62, 0x27, 0x16} // 915MHz (Brazil)
+ };
+
private:
void init() {
mTxPending = false;
@@ -480,6 +543,7 @@ class Cmt2300a {
return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA;
}
+ private:
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
cmtHal mSpi;
#else
@@ -490,6 +554,7 @@ class Cmt2300a {
bool mInRxMode;
uint8_t mCusIntFlag;
uint8_t mRqstCh, mCurCh;
+ RegionCfg mRegionCfg = RegionCfg::EUROPE;
};
#endif /*__CMT2300A_H__*/
diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h
index 2f0a5f31..beea5829 100644
--- a/src/hms/hmsRadio.h
+++ b/src/hms/hmsRadio.h
@@ -17,9 +17,9 @@ class CmtRadio : public Radio {
mDtuSn = DTU_SN;
}
- void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, bool genDtuSn = true) {
+ void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, uint8_t region = 0, bool genDtuSn = true) {
mCmt.setup(pinSclk, pinSdio, pinCsb, pinFcsb);
- reset(genDtuSn);
+ reset(genDtuSn, static_cast(region));
mPrivacyMode = privacyMode;
mSerialDebug = serialDebug;
mPrintWholeTrace = printWholeTrace;
@@ -30,7 +30,7 @@ class CmtRadio : public Radio {
if((!mIrqRcvd) && (!mRqstGetRx))
return false;
getRx();
- if(CMT_SUCCESS == mCmt.goRx()) {
+ if(CmtStatus::SUCCESS == mCmt.goRx()) {
mIrqRcvd = false;
mRqstGetRx = false;
}
@@ -76,6 +76,18 @@ class CmtRadio : public Radio {
return true;
}
+ uint16_t getBaseFreqMhz(void) override {
+ return mCmt.getBaseFreqMhz();
+ }
+
+ uint16_t getBootFreqMhz(void) override {
+ return mCmt.getBootFreqMhz();
+ }
+
+ std::pair getFreqRangeMhz(void) override {
+ return mCmt.getFreqRangeMhz();
+ }
+
private:
void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) {
@@ -104,12 +116,12 @@ class CmtRadio : public Radio {
}
}
- uint8_t status = mCmt.tx(mTxBuf, len);
+ CmtStatus status = mCmt.tx(mTxBuf, len);
mMillis = millis();
- if(CMT_SUCCESS != status) {
+ if(CmtStatus::SUCCESS != status) {
DPRINT(DBG_WARN, F("CMT TX failed, code: "));
- DBGPRINTLN(String(status));
- if(CMT_ERR_RX_IN_FIFO == status)
+ DBGPRINTLN(String(static_cast(status)));
+ if(CmtStatus::ERR_RX_IN_FIFO == status)
mIrqRcvd = true;
}
iv->mDtuTxCnt++;
@@ -123,10 +135,10 @@ class CmtRadio : public Radio {
return iv->ivGen;
}
- inline void reset(bool genDtuSn) {
+ inline void reset(bool genDtuSn, RegionCfg region) {
if(genDtuSn)
generateDtuSn();
- if(!mCmt.reset()) {
+ if(!mCmt.reset(region)) {
mCmtAvail = false;
DPRINTLN(DBG_WARN, F("Initializing CMT2300A failed!"));
} else {
@@ -160,8 +172,8 @@ class CmtRadio : public Radio {
inline void getRx(void) {
packet_t p;
p.millis = millis() - mMillis;
- uint8_t status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi);
- if(CMT_SUCCESS == status)
+ CmtStatus status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi);
+ if(CmtStatus::SUCCESS == status)
mBufCtrl.push(p);
// this code completly stops communication!
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index 98e0afd2..9ec717c1 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -268,6 +268,8 @@ class RestApi {
obj[F("menu_protEn")] = (bool) (strlen(mConfig->sys.adminPwd) > 0);
obj[F("cst_lnk")] = String(mConfig->plugin.customLink);
obj[F("cst_lnk_txt")] = String(mConfig->plugin.customLinkText);
+ obj[F("region")] = mConfig->sys.region;
+ obj[F("timezone")] = mConfig->sys.timezone;
#if defined(ESP32)
obj[F("esp_type")] = F("ESP32");
@@ -651,6 +653,9 @@ class RestApi {
obj[F("fcsb")] = mConfig->cmt.pinFcsb;
obj[F("gpio3")] = mConfig->cmt.pinIrq;
obj[F("en")] = (bool) mConfig->cmt.enabled;
+ std::pair range = mRadioCmt->getFreqRangeMhz();
+ obj[F("freq_min")] = range.first;
+ obj[F("freq_max")] = range.second;
}
void getRadioCmtInfo(JsonObject obj) {
diff --git a/src/web/html/setup.html b/src/web/html/setup.html
index b4c72069..d4f245ef 100644
--- a/src/web/html/setup.html
+++ b/src/web/html/setup.html
@@ -26,6 +26,14 @@
{#DARK_MODE_NOTE}
+
+
{#CUSTOM_LINK}
@@ -499,9 +507,6 @@
for(var i = 0; i < 31; i++) {
esp32cmtPa.push([i, String(i-10) + " dBm"]);
}
- for(var i = 12; i < 41; i++) {
- esp32cmtFreq.push([i, freqFmt.format(860 + i*0.25) + " MHz"]);
- }
/*ENDIF_ESP32*/
var led_high_active = [
[0, "{#PIN_LOW_ACTIVE}"],
@@ -650,6 +655,14 @@
el.push(mlCb("protMask" + i, a[i], chk))
}
d.append(...el);
+
+ var tz = []
+ for(i = 0; i < 24; i += 0.5)
+ tz.push([i, ((i-12 > 0) ? "+" : "") + String(i-12)]);
+ document.getElementById("timezone").append(sel("timezone", tz, obj.timezone + 12))
+ var region = [[0, "Europe (860 - 870 MHz)"], [1, "USA, Indonesia (905 - 925 MHz)"], [2, "Brazil (915 - 928 MHz)"]]
+ document.getElementById("region").append(sel("region", region, obj.region))
+
}
function parseGeneric(obj) {
@@ -1019,6 +1032,12 @@
])
);
}
+
+ var i = 0
+ while(obj.freq_max >= (obj.freq_min + i * 0.25)) {
+ esp32cmtFreq.push([i, freqFmt.format(obj.freq_min + i * 0.25) + " MHz"])
+ i++
+ }
}
/*ENDIF_ESP32*/
diff --git a/src/web/lang.json b/src/web/lang.json
index 9f3df46e..d083ddff 100644
--- a/src/web/lang.json
+++ b/src/web/lang.json
@@ -148,6 +148,16 @@
"en": "(empty browser cache or use CTRL + F5 after reboot to apply this setting)",
"de": "(der Browser-Cache muss geleert oder STRG + F5 gedrückt werden, um diese Einstellung zu aktivieren)"
},
+ {
+ "token": "REGION",
+ "en": "Region",
+ "de": "Region"
+ },
+ {
+ "token": "TIMEZONE",
+ "en": "Timezone",
+ "de": "Zeitzone"
+ },
{
"token": "CUSTOM_LINK",
"en": "Custom link (leave empty to hide element in navigation)",
diff --git a/src/web/web.h b/src/web/web.h
index ba4540b1..6de9c877 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -481,7 +481,8 @@ class Web {
request->arg("device").toCharArray(mConfig->sys.deviceName, DEVNAME_LEN);
mConfig->sys.darkMode = (request->arg("darkMode") == "on");
mConfig->sys.schedReboot = (request->arg("schedReboot") == "on");
-
+ mConfig->sys.region = (request->arg("region")).toInt();
+ mConfig->sys.timezone = (request->arg("timezone")).toInt() - 12;
if (request->arg("cstLnk") != "") {
request->arg("cstLnk").toCharArray(mConfig->plugin.customLink, MAX_CUSTOM_LINK_LEN);
From 7655abc805e2ef7aaf8f95f423fea7f607f49269 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 28 Jan 2024 23:39:04 +0100
Subject: [PATCH 14/79] 0.8.66 fix compile
---
src/hm/Communication.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index ae97dbb2..132faeb8 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -138,8 +138,10 @@ class Communication : public CommQueue<> {
}
if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
+ #if defined(ESP32)
q->iv->radio->switchFrequency(q->iv, q->iv->radio->getBootFreqMhz() * 1000, (q->iv->config->frequency*FREQ_STEP_KHZ + q->iv->radio->getBaseFreqMhz() * 1000));
mWaitTime.startTimeMonitor(1000);
+ #endif
} else {
if(IV_MI == q->iv->ivGen)
q->iv->mIvTxCnt++;
From 6b305651affcb4753699b935ff8c3c1eb32d2622 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Mon, 29 Jan 2024 09:28:17 +0100
Subject: [PATCH 15/79] 0.8.67 * fix HMS frequency * fix display of inverter id
in serial log (was displayed twice)
---
src/CHANGES.md | 6 +++++-
src/defines.h | 2 +-
src/hm/Communication.h | 1 -
src/hms/cmt2300a.h | 6 +++---
4 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 7f544e69..651d068d 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,9 @@
# Development Changes
+## 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
@@ -169,7 +173,7 @@
## 0.8.37 - 2023-12-30
* added grid profiles
-* format version of grid profile
+* format version of grid profile
# RELEASE 0.8.36 - 2023-12-30
diff --git a/src/defines.h b/src/defines.h
index 786908d0..4ff2fc1e 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 66
+#define VERSION_PATCH 67
//-------------------------------------
typedef struct {
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 132faeb8..396a98a5 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -502,7 +502,6 @@ class Communication : public CommQueue<> {
int8_t rssi = -127;
uint8_t len = 0;
- DPRINT_IVID(DBG_INFO, q->iv->id);
for(uint8_t i = 0; i < mMaxFrameId; i++) {
if(mLocalBuf[i].len + len > MAX_BUFFER) {
DPRINTLN(DBG_ERROR, F("payload buffer to small!"));
diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h
index 524472f0..3cdc2660 100644
--- a/src/hms/cmt2300a.h
+++ b/src/hms/cmt2300a.h
@@ -360,7 +360,7 @@ class Cmt2300a {
if((freqKhz < range.first) || (freqKhz > range.second))
return 0xff; // error
- return (freqKhz - getBaseFreqMhz()) / FREQ_STEP_KHZ;
+ return (freqKhz - getBaseFreqMhz() * 1000) / FREQ_STEP_KHZ;
}
inline void switchChannel(uint8_t ch) {
@@ -369,9 +369,9 @@ class Cmt2300a {
inline uint32_t getFreqKhz(void) {
if(0xff != mRqstCh)
- return getBaseFreqMhz() + (mRqstCh * FREQ_STEP_KHZ);
+ return getBaseFreqMhz() * 1000 + (mRqstCh * FREQ_STEP_KHZ);
else
- return getBaseFreqMhz() + (mCurCh * FREQ_STEP_KHZ);
+ return getBaseFreqMhz() * 1000 + (mCurCh * FREQ_STEP_KHZ);
}
uint8_t getCurrentChannel(void) {
From e5ce1f5094592dd50ae890c440b0806eef6c044b Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Mon, 29 Jan 2024 16:44:26 +0100
Subject: [PATCH 16/79] individualize rx offset
for nRF
---
src/hm/Communication.h | 7 +-
src/hm/HeuristicInv.h | 2 +-
src/hm/hmDefines.h | 8 --
src/hm/hmInverter.h | 1 -
src/hm/hmRadio.h | 14 ++-
src/hm/hmSystem.h | 3 +-
src/hm/radio.h | 7 +-
src/hms/cmt2300a.h | 259 ++++++++++++++++++++++++++---------------
src/hms/hmsRadio.h | 36 ++++--
9 files changed, 209 insertions(+), 128 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 23ffe158..9219bb8e 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -139,8 +139,10 @@ class Communication : public CommQueue<> {
}
if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
- q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, (q->iv->config->frequency*FREQ_STEP_KHZ + HOY_BASE_FREQ_KHZ));
+ #if defined(ESP32)
+ q->iv->radio->switchFrequency(q->iv, q->iv->radio->getBootFreqMhz() * 1000, (q->iv->config->frequency*FREQ_STEP_KHZ + q->iv->radio->getBaseFreqMhz() * 1000));
mWaitTime.startTimeMonitor(1000);
+ #endif
} else {
mHeu.setIvRetriesBad(q->iv);
if(IV_MI == q->iv->ivGen)
@@ -526,7 +528,6 @@ class Communication : public CommQueue<> {
int8_t rssi = -127;
uint8_t len = 0;
- DPRINT_IVID(DBG_INFO, q->iv->id);
for(uint8_t i = 0; i < mMaxFrameId; i++) {
if(mLocalBuf[i].len + len > MAX_BUFFER) {
DPRINTLN(DBG_ERROR, F("payload buffer to small!"));
@@ -541,7 +542,7 @@ class Communication : public CommQueue<> {
len -= 2;
- //DPRINT_IVID(DBG_INFO, q->iv->id); // it's already above "for"-loop
+ DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("Payload ("));
DBGPRINT(String(len));
if(*mPrintWholeTrace) {
diff --git a/src/hm/HeuristicInv.h b/src/hm/HeuristicInv.h
index fc782a7b..e9c7084e 100644
--- a/src/hm/HeuristicInv.h
+++ b/src/hm/HeuristicInv.h
@@ -14,7 +14,7 @@
class HeuristicInv {
public:
HeuristicInv() {
- memset(txRfQuality, -6, RF_MAX_CHANNEL_ID);
+ memset(txRfQuality, 0, RF_MAX_CHANNEL_ID);
}
public:
diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h
index 6bd66e66..4705c061 100644
--- a/src/hm/hmDefines.h
+++ b/src/hm/hmDefines.h
@@ -78,14 +78,6 @@ enum {CH0 = 0, CH1, CH2, CH3, CH4, CH5, CH6};
enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH, INV_TYPE_6CH};
enum {INV_RADIO_TYPE_NRF = 0, INV_RADIO_TYPE_CMT};
-#define WORK_FREQ_KHZ 865000 // desired work frequency between DTU and
- // inverter in kHz
-#define HOY_BASE_FREQ_KHZ 860000 // in kHz
-#define HOY_MAX_FREQ_KHZ 923500 // 0xFE * 250kHz + Base_freq
-#define HOY_BOOT_FREQ_KHZ 868000 // Hoymiles boot/init frequency after power up inverter
-#define FREQ_STEP_KHZ 250 // channel step size in kHz
-#define FREQ_WARN_MIN_KHZ 863000 // for EU 863 - 870 MHz is allowed
-#define FREQ_WARN_MAX_KHZ 870000 // for EU 863 - 870 MHz is allowed
#define DURATION_ONEFRAME 50 // timeout parameter for each expected frame (ms)
//#define DURATION_RESERVE {90,120} // timeout parameter to still wait after last expected frame (ms)
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index 00f05c79..a74ad02f 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -180,7 +180,6 @@ class Inverter {
tsMaxAcPower = 0;
memset(&radioStatistics, 0, sizeof(statistics_t));
-
memset(mOffYD, 0, sizeof(float) * 6);
memset(mLastYD, 0, sizeof(float) * 6);
}
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index fbb23b57..e759576c 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -118,7 +118,7 @@ class HmRadio : public Radio {
// otherwise switch to next RX channel
mTimeslotStart = millis();
- if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME+DURATION_ONEFRAME)))
+ if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME))) //(DURATION_TXFRAME+DURATION_ONEFRAME)))
mNRFloopChannels = true;
rxPendular = !rxPendular;
@@ -163,7 +163,7 @@ class HmRadio : public Radio {
mNRFloopChannels = (mLastIv->ivGen == IV_MI);
//innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME;
- innerLoopTimeout = DURATION_LISTEN_MIN;
+ innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_LISTEN_MIN : 4;
}
if(rx_ready) {
@@ -324,7 +324,13 @@ class HmRadio : public Radio {
if(mLastIv->mIsSingleframeReq) // we only expect one frame here...
isRetransmitAnswer = true;
if(isLastPackage)
- mFramesExpected = p.packet[9] - ALL_FRAMES;
+ setExpectedFrames(p.packet[9] - ALL_FRAMES);
+ if(p.packet[9] == 1 && p.millis < DURATION_ONEFRAME)
+ mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + 1) % RF_CHANNELS;
+ else if(mNRFloopChannels && mLastIv->rxOffset > RF_CHANNELS) { // unsure setting?
+ mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + (isLastPackage ? mFramesExpected : p.packet[9])); // make clear it's not sure, start with one more offset
+ mNRFloopChannels = false;
+ }
}
if(IV_MI == mLastIv->ivGen) {
@@ -332,6 +338,8 @@ class HmRadio : public Radio {
isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received
else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore MI status messages //#0 was p.packet[0] != 0x00 &&
isLastPackage = true; // response from dev control command
+ if(p.packet[9] == 0x00 && p.millis < DURATION_ONEFRAME)
+ mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx - 1) % RF_CHANNELS;
}
rx_ready = true; //reset in case we first read messages from other inverter or ACK zero payloads
}
diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h
index 1e8641cb..26d0ea5d 100644
--- a/src/hm/hmSystem.h
+++ b/src/hm/hmSystem.h
@@ -28,8 +28,7 @@ class HmSystem {
iv->config = &mInverter[0].generalConfig->iv[id];
DPRINT(DBG_VERBOSE, "SERIAL: " + String(iv->config->serial.b[5], HEX));
DPRINTLN(DBG_VERBOSE, " " + String(iv->config->serial.b[4], HEX));
- //iv->rxOffset = 5 - (iv->config->serial.b[2] % 5); //RF_CHANNELS;
- iv->rxOffset = (iv->config->serial.b[1] % 5); //RF_CHANNELS;
+ iv->rxOffset = 13; // effective 3, but can easily be recognized as default setting
if((iv->config->serial.b[5] == 0x11) || (iv->config->serial.b[5] == 0x10)) {
switch(iv->config->serial.b[4]) {
case 0x24: // HMS-500
diff --git a/src/hm/radio.h b/src/hm/radio.h
index ea6d8c05..9702c304 100644
--- a/src/hm/radio.h
+++ b/src/hm/radio.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
//-----------------------------------------------------------------------------
@@ -28,6 +28,9 @@ class Radio {
virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; }
virtual bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; }
virtual bool isChipConnected(void) const { return false; }
+ 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;
void handleIntr(void) {
@@ -115,6 +118,7 @@ class Radio {
chipID = ESP.getChipId();
#endif
+ mDtuSn = 0;
uint8_t t;
for(int i = 0; i < (7 << 2); i += 4) {
t = (chipID >> i) & 0x0f;
@@ -125,6 +129,7 @@ class Radio {
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;
volatile bool mIrqRcvd;
bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace;
diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h
index 1ff112e2..3cdc2660 100644
--- a/src/hms/cmt2300a.h
+++ b/src/hms/cmt2300a.h
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
-// 2023 Ahoy, https://github.com/lumpapu/ahoy
+// 2024 Ahoy, https://github.com/lumpapu/ahoy
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
//-----------------------------------------------------------------------------
@@ -12,8 +12,23 @@
#include "esp32_3wSpi.h"
#endif
-// detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf
+#include
+
+enum class RegionCfg : uint8_t {
+ EUROPE, USA, BRAZIL, NUM
+};
+
+enum class CmtStatus : uint8_t {
+ SUCCESS = 0,
+ ERR_SWITCH_STATE,
+ ERR_TX_PENDING,
+ FIFO_EMPTY,
+ ERR_RX_IN_FIFO
+};
+
+#define FREQ_STEP_KHZ 250 // channel step size in kHz
+// detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf
#define CMT2300A_MASK_CFG_RETAIN 0x10
#define CMT2300A_MASK_RSTN_IN_EN 0x20
#define CMT2300A_MASK_LOCKING_EN 0x20
@@ -152,67 +167,6 @@
#define CMT2300A_MASK_TX_DONE_FLG 0x08
#define CMT2300A_MASK_PKT_OK_FLG 0x01
-// this list and the TX5, TX10 registers were compiled from the output of
-// HopeRF RFPDK Tool v1.54
-static uint8_t paLevelList[31][2] PROGMEM = {
- {0x17, 0x01}, // -10dBm
- {0x1a, 0x01}, // -09dBm
- {0x1d, 0x01}, // -08dBm
- {0x21, 0x01}, // -07dBm
- {0x25, 0x01}, // -06dBm
- {0x29, 0x01}, // -05dBm
- {0x2d, 0x01}, // -04dBm
- {0x33, 0x01}, // -03dBm
- {0x39, 0x02}, // -02dBm
- {0x41, 0x02}, // -01dBm
- {0x4b, 0x02}, // 00dBm
- {0x56, 0x03}, // 01dBm
- {0x63, 0x03}, // 02dBm
- {0x71, 0x04}, // 03dBm
- {0x80, 0x04}, // 04dBm
- {0x22, 0x01}, // 05dBm
- {0x27, 0x04}, // 06dBm
- {0x2c, 0x05}, // 07dBm
- {0x31, 0x06}, // 08dBm
- {0x38, 0x06}, // 09dBm
- {0x3f, 0x07}, // 10dBm
- {0x48, 0x08}, // 11dBm
- {0x52, 0x09}, // 12dBm
- {0x5d, 0x0b}, // 13dBm
- {0x6a, 0x0c}, // 14dBm
- {0x79, 0x0d}, // 15dBm
- {0x46, 0x10}, // 16dBm
- {0x51, 0x10}, // 17dBm
- {0x60, 0x12}, // 18dBm
- {0x71, 0x14}, // 19dBm
- {0x8c, 0x1c} // 20dBm
-};
-
-// default CMT parameters
-static uint8_t cmtConfig[0x60] PROGMEM {
- // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm
- 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08,
- 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00,
- // 0x10 - 0x1f
- 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81,
- 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 860MHz as default
- // 0x20 - 0x2f
- 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A,
- 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53,
- // 0x30 - 0x3f
- 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00,
- // 0x40 - 0x4f
- 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1F, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60,
- // 0x50 - 0x5f
- 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06,
- 0x00, 0x07, 0x50, 0x00, 0x5D, 0x0B, 0x3F, 0x7F // - TX 13dBm
-};
-
-
-enum {CMT_SUCCESS = 0, CMT_ERR_SWITCH_STATE, CMT_ERR_TX_PENDING, CMT_FIFO_EMPTY, CMT_ERR_RX_IN_FIFO};
-
class Cmt2300a {
public:
Cmt2300a() {}
@@ -234,12 +188,12 @@ class Cmt2300a {
}
}
- uint8_t goRx(void) {
+ CmtStatus goRx(void) {
if(mTxPending)
- return CMT_ERR_TX_PENDING;
+ return CmtStatus::ERR_TX_PENDING;
if(mInRxMode)
- return CMT_SUCCESS;
+ return CmtStatus::SUCCESS;
mSpi.readReg(CMT2300A_CUS_INT1_CTL);
mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE);
@@ -260,47 +214,47 @@ class Cmt2300a {
mSpi.writeReg(0x16, 0x0C); // [4:3]: RSSI_DET_SEL, [2:0]: RSSI_AVG_MODE
if(!cmtSwitchStatus(CMT2300A_GO_RX, CMT2300A_STA_RX))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
mInRxMode = true;
- return CMT_SUCCESS;
+ return CmtStatus::SUCCESS;
}
- uint8_t getRx(uint8_t buf[], uint8_t *rxLen, uint8_t maxlen, int8_t *rssi) {
+ CmtStatus getRx(uint8_t buf[], uint8_t *rxLen, uint8_t maxlen, int8_t *rssi) {
if(mTxPending)
- return CMT_ERR_TX_PENDING;
+ return CmtStatus::ERR_TX_PENDING;
if(0x1b != (mSpi.readReg(CMT2300A_CUS_INT_FLAG) & 0x1b))
- return CMT_FIFO_EMPTY;
+ return CmtStatus::FIFO_EMPTY;
// receive ok (pream, sync, node, crc)
if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
mSpi.readFifo(buf, rxLen, maxlen);
*rssi = mSpi.readReg(CMT2300A_CUS_RSSI_DBM) - 128;
if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
mInRxMode = false;
mCusIntFlag = mSpi.readReg(CMT2300A_CUS_INT_FLAG);
- return CMT_SUCCESS;
+ return CmtStatus::SUCCESS;
}
- uint8_t tx(uint8_t buf[], uint8_t len) {
+ CmtStatus tx(uint8_t buf[], uint8_t len) {
if(mTxPending)
- return CMT_ERR_TX_PENDING;
+ return CmtStatus::ERR_TX_PENDING;
if(mInRxMode) {
mInRxMode = false;
if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
}
mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE);
@@ -325,16 +279,17 @@ class Cmt2300a {
}
if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX))
- return CMT_ERR_SWITCH_STATE;
+ return CmtStatus::ERR_SWITCH_STATE;
// wait for tx done
mTxPending = true;
- return CMT_SUCCESS;
+ return CmtStatus::SUCCESS;
}
// initialize CMT2300A, returns true on success
- bool reset(void) {
+ bool reset(RegionCfg region) {
+ mRegionCfg = region;
mSpi.writeReg(0x7f, 0xff); // soft reset
delay(30);
@@ -346,10 +301,19 @@ class Cmt2300a {
if(mSpi.readReg(0x62) != 0x20)
return false; // not connected!
- for(uint8_t i = 0; i < 0x60; i++) {
+ for(uint8_t i = 0; i < 0x18; i++) {
+ mSpi.writeReg(i, cmtConfig[i]);
+ }
+ for(uint8_t i = 0; i < 8; i++) {
+ mSpi.writeReg(0x18 + i, mBaseFreqCfg[static_cast(region)][i]);
+ }
+ for(uint8_t i = 0x20; i < 0x60; i++) {
mSpi.writeReg(i, cmtConfig[i]);
}
+ if(RegionCfg::EUROPE != region)
+ mSpi.writeReg(0x27, 0x0B);
+
mSpi.writeReg(CMT2300A_CUS_IO_SEL, 0x20); // -> GPIO3_SEL[1:0] = 0x02
@@ -389,23 +353,14 @@ class Cmt2300a {
}
inline uint8_t freq2Chan(const uint32_t freqKhz) {
- if((freqKhz % FREQ_STEP_KHZ) != 0) {
- DPRINT(DBG_WARN, F("switch frequency to "));
- DBGPRINT(String(freqKhz));
- DBGPRINT(F("kHz not possible!"));
+ if((freqKhz % FREQ_STEP_KHZ) != 0)
return 0xff; // error
- // apply the nearest frequency
- //freqKhz = (freqKhz + FREQ_STEP_KHZ/2) / FREQ_STEP_KHZ;
- //freqKhz *= FREQ_STEP_KHZ;
- }
- if((freqKhz < HOY_BASE_FREQ_KHZ) || (freqKhz > HOY_MAX_FREQ_KHZ))
+ std::pair range = getFreqRangeMhz();
+ if((freqKhz < range.first) || (freqKhz > range.second))
return 0xff; // error
- if((freqKhz < FREQ_WARN_MIN_KHZ) || (freqKhz > FREQ_WARN_MAX_KHZ))
- DPRINTLN(DBG_WARN, F("Desired frequency is out of EU legal range! (863 - 870MHz)"));
-
- return (freqKhz - HOY_BASE_FREQ_KHZ) / FREQ_STEP_KHZ;
+ return (freqKhz - getBaseFreqMhz() * 1000) / FREQ_STEP_KHZ;
}
inline void switchChannel(uint8_t ch) {
@@ -414,9 +369,9 @@ class Cmt2300a {
inline uint32_t getFreqKhz(void) {
if(0xff != mRqstCh)
- return HOY_BASE_FREQ_KHZ + (mRqstCh * FREQ_STEP_KHZ);
+ return getBaseFreqMhz() * 1000 + (mRqstCh * FREQ_STEP_KHZ);
else
- return HOY_BASE_FREQ_KHZ + (mCurCh * FREQ_STEP_KHZ);
+ return getBaseFreqMhz() * 1000 + (mCurCh * FREQ_STEP_KHZ);
}
uint8_t getCurrentChannel(void) {
@@ -443,6 +398,114 @@ class Cmt2300a {
mSpi.writeReg(CMT2300A_CUS_TX9, paLevelList[level][1]);
}
+ public:
+ uint16_t getBaseFreqMhz(void) {
+ switch(mRegionCfg) {
+ default:
+ [[fallthrough]];
+ case RegionCfg::EUROPE:
+ break;
+ case RegionCfg::USA:
+ return 905;
+ case RegionCfg::BRAZIL:
+ return 915;
+ }
+ return 860;
+ }
+
+ uint16_t getBootFreqMhz(void) {
+ switch(mRegionCfg) {
+ default:
+ [[fallthrough]];
+ case RegionCfg::EUROPE:
+ break;
+ case RegionCfg::USA:
+ return 915;
+ case RegionCfg::BRAZIL:
+ return 915;
+ }
+ return 868;
+ }
+
+ std::pair getFreqRangeMhz(void) {
+ switch(mRegionCfg) {
+ default:
+ [[fallthrough]];
+ case RegionCfg::EUROPE:
+ break;
+ case RegionCfg::USA:
+ return std::make_pair(905, 925);
+ case RegionCfg::BRAZIL:
+ return std::make_pair(915, 928);
+ }
+ return std::make_pair(860, 870); // Europe
+ }
+
+ private:
+ // this list and the TX5, TX10 registers were compiled from the output of
+ // HopeRF RFPDK Tool v1.54
+ constexpr static uint8_t paLevelList[31][2] PROGMEM = {
+ {0x17, 0x01}, // -10dBm
+ {0x1a, 0x01}, // -09dBm
+ {0x1d, 0x01}, // -08dBm
+ {0x21, 0x01}, // -07dBm
+ {0x25, 0x01}, // -06dBm
+ {0x29, 0x01}, // -05dBm
+ {0x2d, 0x01}, // -04dBm
+ {0x33, 0x01}, // -03dBm
+ {0x39, 0x02}, // -02dBm
+ {0x41, 0x02}, // -01dBm
+ {0x4b, 0x02}, // 00dBm
+ {0x56, 0x03}, // 01dBm
+ {0x63, 0x03}, // 02dBm
+ {0x71, 0x04}, // 03dBm
+ {0x80, 0x04}, // 04dBm
+ {0x22, 0x01}, // 05dBm
+ {0x27, 0x04}, // 06dBm
+ {0x2c, 0x05}, // 07dBm
+ {0x31, 0x06}, // 08dBm
+ {0x38, 0x06}, // 09dBm
+ {0x3f, 0x07}, // 10dBm
+ {0x48, 0x08}, // 11dBm
+ {0x52, 0x09}, // 12dBm
+ {0x5d, 0x0b}, // 13dBm
+ {0x6a, 0x0c}, // 14dBm
+ {0x79, 0x0d}, // 15dBm
+ {0x46, 0x10}, // 16dBm
+ {0x51, 0x10}, // 17dBm
+ {0x60, 0x12}, // 18dBm
+ {0x71, 0x14}, // 19dBm
+ {0x8c, 0x1c} // 20dBm
+ };
+
+ // default CMT parameters
+ constexpr static uint8_t cmtConfig[0x60] PROGMEM {
+ // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm
+ 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08,
+ 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00,
+ // 0x10 - 0x1f
+ 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81,
+ 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 860MHz as default
+ // 0x20 - 0x2f
+ 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A,
+ 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53,
+ // 0x30 - 0x3f
+ 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00,
+ // 0x40 - 0x4f
+ 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1F, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60,
+ // 0x50 - 0x5f
+ 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06,
+ 0x00, 0x07, 0x50, 0x00, 0x5D, 0x0B, 0x3F, 0x7F // TX 13dBm
+ };
+
+ constexpr static uint8_t mBaseFreqCfg[static_cast(RegionCfg::NUM)][8] {
+ {0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12}, // 860MHz
+ {0x45, 0xA8, 0x31, 0x8A, 0x45, 0x9D, 0xD8, 0x19}, // 905MHz (USA, Indonesia)
+ {0x46, 0x6D, 0x80, 0x86, 0x46, 0x62, 0x27, 0x16} // 915MHz (Brazil)
+ };
+
private:
void init() {
mTxPending = false;
@@ -480,6 +543,7 @@ class Cmt2300a {
return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA;
}
+ private:
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
cmtHal mSpi;
#else
@@ -490,6 +554,7 @@ class Cmt2300a {
bool mInRxMode;
uint8_t mCusIntFlag;
uint8_t mRqstCh, mCurCh;
+ RegionCfg mRegionCfg = RegionCfg::EUROPE;
};
#endif /*__CMT2300A_H__*/
diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h
index 33b6a75c..07afd4b8 100644
--- a/src/hms/hmsRadio.h
+++ b/src/hms/hmsRadio.h
@@ -17,9 +17,9 @@ class CmtRadio : public Radio {
mDtuSn = DTU_SN;
}
- void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, bool genDtuSn = true) {
+ void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, uint8_t region = 0, bool genDtuSn = true) {
mCmt.setup(pinSclk, pinSdio, pinCsb, pinFcsb);
- reset(genDtuSn);
+ reset(genDtuSn, static_cast(region));
mPrivacyMode = privacyMode;
mSerialDebug = serialDebug;
mPrintWholeTrace = printWholeTrace;
@@ -30,7 +30,7 @@ class CmtRadio : public Radio {
if((!mIrqRcvd) && (!mRqstGetRx))
return false;
getRx();
- if(CMT_SUCCESS == mCmt.goRx()) {
+ if(CmtStatus::SUCCESS == mCmt.goRx()) {
mIrqRcvd = false;
mRqstGetRx = false;
}
@@ -76,6 +76,18 @@ class CmtRadio : public Radio {
return true;
}
+uint16_t getBaseFreqMhz(void) override {
+ return mCmt.getBaseFreqMhz();
+ }
+
+ uint16_t getBootFreqMhz(void) override {
+ return mCmt.getBootFreqMhz();
+ }
+
+ std::pair getFreqRangeMhz(void) override {
+ return mCmt.getFreqRangeMhz();
+ }
+
private:
void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) {
@@ -104,12 +116,12 @@ class CmtRadio : public Radio {
}
}
- uint8_t status = mCmt.tx(mTxBuf, len);
+ CmtStatus status = mCmt.tx(mTxBuf, len);
mMillis = millis();
- if(CMT_SUCCESS != status) {
+ if(CmtStatus::SUCCESS != status) {
DPRINT(DBG_WARN, F("CMT TX failed, code: "));
- DBGPRINTLN(String(status));
- if(CMT_ERR_RX_IN_FIFO == status)
+ DBGPRINTLN(String(static_cast(status)));
+ if(CmtStatus::ERR_RX_IN_FIFO == status)
mIrqRcvd = true;
}
iv->mDtuTxCnt++;
@@ -123,10 +135,10 @@ class CmtRadio : public Radio {
return iv->ivGen;
}
- inline void reset(bool genDtuSn) {
+ inline void reset(bool genDtuSn, RegionCfg region) {
if(genDtuSn)
generateDtuSn();
- if(!mCmt.reset()) {
+ if(!mCmt.reset(region)) {
mCmtAvail = false;
DPRINTLN(DBG_WARN, F("Initializing CMT2300A failed!"));
} else {
@@ -160,8 +172,8 @@ class CmtRadio : public Radio {
inline void getRx(void) {
packet_t p;
p.millis = millis() - mMillis;
- uint8_t status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi);
- if(CMT_SUCCESS == status)
+ CmtStatus status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi);
+ if(CmtStatus::SUCCESS == status)
mBufCtrl.push(p);
if(p.packet[9] > ALL_FRAMES) // indicates last frame
@@ -171,7 +183,7 @@ class CmtRadio : public Radio {
}
CmtType mCmt;
- bool mCmtAvail;
+ bool mCmtAvail = false;
bool mRqstGetRx = false;
uint32_t mMillis;
};
From 163a9e485ef7f01cd85548d41aeb575fbc15146b Mon Sep 17 00:00:00 2001
From: lumapu
Date: Mon, 29 Jan 2024 21:51:49 +0100
Subject: [PATCH 17/79] 0.8.68 * 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
---
src/CHANGES.md | 6 ++++++
src/app.h | 4 ++++
src/appInterface.h | 1 +
src/defines.h | 2 +-
src/hm/Communication.h | 5 ++++-
src/hm/HeuristicInv.h | 19 +++++++++++++++++--
src/hm/hmInverter.h | 9 +++++++++
src/hm/hmRadio.h | 26 ++++++++++++++------------
src/hms/cmt2300a.h | 6 +++---
src/web/RestApi.h | 6 ++++++
src/web/lang.h | 6 ++++++
src/wifi/ahoywifi.cpp | 2 ++
src/wifi/ahoywifi.h | 5 +++++
13 files changed, 78 insertions(+), 19 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 651d068d..f690b192 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,11 @@
# Development Changes
+## 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)
diff --git a/src/app.h b/src/app.h
index 851ad3c8..ccf46297 100644
--- a/src/app.h
+++ b/src/app.h
@@ -182,6 +182,10 @@ class app : public IApp, public ah::Scheduler {
return mWifi.getStationIp();
}
+ bool getWasInCh12to14(void) const {
+ return mWifi.getWasInCh12to14();
+ }
+
#endif /* !defined(ETHERNET) */
void setRebootFlag() {
diff --git a/src/appInterface.h b/src/appInterface.h
index ad38f756..f98fb0cb 100644
--- a/src/appInterface.h
+++ b/src/appInterface.h
@@ -35,6 +35,7 @@ class IApp {
virtual void setupStation(void) = 0;
virtual void setStopApAllowedMode(bool allowed) = 0;
virtual String getStationIp(void) = 0;
+ virtual bool getWasInCh12to14(void) const = 0;
#endif /* defined(ETHERNET) */
virtual uint32_t getUptime() = 0;
diff --git a/src/defines.h b/src/defines.h
index 4ff2fc1e..442008ff 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 67
+#define VERSION_PATCH 68
//-------------------------------------
typedef struct {
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 396a98a5..b74f689d 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -139,7 +139,10 @@ class Communication : public CommQueue<> {
if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
#if defined(ESP32)
- q->iv->radio->switchFrequency(q->iv, q->iv->radio->getBootFreqMhz() * 1000, (q->iv->config->frequency*FREQ_STEP_KHZ + q->iv->radio->getBaseFreqMhz() * 1000));
+ if(!q->iv->radio->switchFrequency(q->iv, q->iv->radio->getBootFreqMhz() * 1000, (q->iv->config->frequency*FREQ_STEP_KHZ + q->iv->radio->getBaseFreqMhz() * 1000))) {
+ DPRINT_IVID(DBG_INFO, q->iv->id);
+ DBGPRINTLN(F("switch frequency failed!"));
+ }
mWaitTime.startTimeMonitor(1000);
#endif
} else {
diff --git a/src/hm/HeuristicInv.h b/src/hm/HeuristicInv.h
index e7ad6edd..0391e758 100644
--- a/src/hm/HeuristicInv.h
+++ b/src/hm/HeuristicInv.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
//-----------------------------------------------------------------------------
@@ -14,7 +14,22 @@
class HeuristicInv {
public:
HeuristicInv() {
- memset(txRfQuality, -6, RF_MAX_CHANNEL_ID);
+ clear();
+ }
+
+ void clear() {
+ memset(txRfQuality, 0, RF_MAX_CHANNEL_ID);
+ txRfChId = 0;
+ lastBestTxChId = 0;
+ testPeriodSendCnt = 0;
+ testPeriodFailCnt = 0;
+ testChId = 0;
+ saveOldTestQuality = -6;
+ lastRxFragments = 0;
+ }
+
+ bool isTxAtMax(void) const {
+ return (RF_MAX_QUALITY == txRfQuality[txRfChId]);
}
public:
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index cc73cb0b..f63fa688 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -192,6 +192,14 @@ class Inverter {
if(mNextLive)
cb(RealTimeRunData_Debug, false); // get live data
else {
+ if(INV_RADIO_TYPE_NRF == ivRadioType) {
+ // get live data until quility reaches maximum
+ if(!heuristics.isTxAtMax()) {
+ cb(RealTimeRunData_Debug, false); // get live data
+ return;
+ }
+ }
+
if(actPowerLimit == 0xffff)
cb(SystemConfigPara, false); // power limit info
else if(InitDataState != devControlCmd) {
@@ -449,6 +457,7 @@ class Inverter {
status = InverterStatus::OFF;
actPowerLimit = 0xffff; // power limit will be read once inverter becomes available
alarmMesIndex = 0;
+ heuristics.clear();
}
else
status = InverterStatus::WAS_ON;
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index d73b2b0e..5730c492 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, 15); // wait 3*250 = 750us, 16 * 250us -> 4000us = 4ms
+ mNrf24->setRetries(3, 9); // wait 3*250 = 750us, 16 * 250us -> 4000us = 4ms
mNrf24->setDataRate(RF24_250KBPS);
//mNrf24->setAutoAck(true); // enabled by default
@@ -120,14 +120,14 @@ class HmRadio : public Radio {
if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME+DURATION_ONEFRAME)))
mNRFloopChannels = true;
- rxPendular = !rxPendular;
- //innerLoopTimeout = (rxPendular ? 1 : 2)*DURATION_LISTEN_MIN;
+ mRxPendular = !mRxPendular;
+ //innerLoopTimeout = (mRxPendular ? 1 : 2)*DURATION_LISTEN_MIN;
innerLoopTimeout = DURATION_LISTEN_MIN;
if(mNRFloopChannels)
tempRxChIdx = (tempRxChIdx + 4) % RF_CHANNELS;
else
- tempRxChIdx = (mRxChIdx + rxPendular*4) % RF_CHANNELS;
+ tempRxChIdx = (mRxChIdx + mRxPendular*4) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[tempRxChIdx]);
isRxInit = false;
@@ -141,7 +141,7 @@ class HmRadio : public Radio {
if(tx_ok || tx_fail) { // tx related interrupt, basically we should start listening
mNrf24->flush_tx(); // empty TX FIFO
- mTxSetupTime = millis() - mMillis;
+ //mTxSetupTime = millis() - mMillis;
if(mNRFisInRX) {
DPRINTLN(DBG_WARN, F("unexpected tx irq!"));
@@ -157,7 +157,7 @@ class HmRadio : public Radio {
mNrf24->startListening();
mTimeslotStart = millis();
tempRxChIdx = mRxChIdx;
- rxPendular = false;
+ mRxPendular = false;
mNRFloopChannels = (mLastIv->ivGen == IV_MI);
innerLoopTimeout = DURATION_TXFRAME;
@@ -168,11 +168,12 @@ class HmRadio : public Radio {
mNRFisInRX = false;
mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first end his transmissions
mNrf24->stopListening();
+ return false;
} else {
innerLoopTimeout = DURATION_LISTEN_MIN;
mTimeslotStart = millis();
if (!mNRFloopChannels) {
- //rxPendular = true; // stay longer on the next rx channel
+ //mRxPendular = true; // stay longer on the next rx channel
if (isRxInit) {
isRxInit = false;
tempRxChIdx = (mRxChIdx + 4) % RF_CHANNELS;
@@ -180,8 +181,8 @@ class HmRadio : public Radio {
} else
mRxChIdx = tempRxChIdx;
}
+ return true;
}
- return mNRFisInRX;
}
}
@@ -341,11 +342,11 @@ class HmRadio : public Radio {
mTxChIdx = iv->heuristics.txRfChId;
if(*mSerialDebug) {
- if(!isRetransmit) {
+ /*if(!isRetransmit) {
DPRINT(DBG_INFO, "last tx setup: ");
DBGPRINT(String(mTxSetupTime));
DBGPRINTLN("ms");
- }
+ }*/
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("TX "));
@@ -368,6 +369,7 @@ class HmRadio : public Radio {
}
mNrf24->stopListening();
+ mNrf24->flush_rx();
mNrf24->setChannel(mRfChLst[mTxChIdx]);
mNrf24->openWritingPipe(reinterpret_cast(&iv->radioId.u64));
mNrf24->startWrite(mTxBuf, len, false); // false = request ACK response
@@ -407,9 +409,9 @@ class HmRadio : public Radio {
bool mNRFloopChannels = false;
bool mNRFisInRX = false;
bool isRxInit = true;
- bool rxPendular = false;
+ bool mRxPendular = false;
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
- uint8_t mTxSetupTime = 0;
+ //uint8_t mTxSetupTime = 0;
std::unique_ptr mSpi;
std::unique_ptr mNrf24;
diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h
index 3cdc2660..e6456f5b 100644
--- a/src/hms/cmt2300a.h
+++ b/src/hms/cmt2300a.h
@@ -356,11 +356,11 @@ class Cmt2300a {
if((freqKhz % FREQ_STEP_KHZ) != 0)
return 0xff; // error
- std::pair range = getFreqRangeMhz();
- if((freqKhz < range.first) || (freqKhz > range.second))
+ std::pair range = getFreqRangeMhz();
+ if((freqKhz < (range.first * 1000)) || (freqKhz > (range.second * 1000)))
return 0xff; // error
- return (freqKhz - getBaseFreqMhz() * 1000) / FREQ_STEP_KHZ;
+ return (freqKhz - (getBaseFreqMhz() * 1000)) / FREQ_STEP_KHZ;
}
inline void switchChannel(uint8_t ch) {
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index 9ec717c1..ccdc8747 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -754,6 +754,12 @@ class RestApi {
warn.add(F(REBOOT_ESP_APPLY_CHANGES));
if(0 == mApp->getTimestamp())
warn.add(F(TIME_NOT_SET));
+ #if !defined(ETHERNET)
+ #if !defined(ESP32)
+ if(mApp->getWasInCh12to14())
+ warn.add(F(WAS_IN_CH_12_TO_14));
+ #endif
+ #endif
}
void getSetup(AsyncWebServerRequest *request, JsonObject obj) {
diff --git a/src/web/lang.h b/src/web/lang.h
index 546399aa..e55493eb 100644
--- a/src/web/lang.h
+++ b/src/web/lang.h
@@ -18,6 +18,12 @@
#define TIME_NOT_SET "time not set. No communication to inverter possible"
#endif
+#ifdef LANG_DE
+ #define WAS_IN_CH_12_TO_14 "Der ESP war in WLAN Kanal 12 bis 14, was uU. zu Abstürzen führt"
+#else /*LANG_EN*/
+ #define WAS_IN_CH_12_TO_14 "Your ESP was in wifi channel 12 to 14. It may cause reboots of your AhoyDTU"
+#endif
+
#ifdef LANG_DE
#define INV_INDEX_INVALID "Wechselrichterindex ungültig; "
#else /*LANG_EN*/
diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp
index defca5bc..9bcbdadc 100644
--- a/src/wifi/ahoywifi.cpp
+++ b/src/wifi/ahoywifi.cpp
@@ -92,6 +92,8 @@ void ahoywifi::tickWifiLoop() {
}
#if !defined(ESP32)
MDNS.update();
+ if(WiFi.channel() > 11)
+ mWasInCh12to14 = true;
#endif
return;
case IN_AP_MODE:
diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h
index 7fb62a20..709c08c4 100644
--- a/src/wifi/ahoywifi.h
+++ b/src/wifi/ahoywifi.h
@@ -37,6 +37,10 @@ class ahoywifi {
}
void setupStation(void);
+ bool getWasInCh12to14() const {
+ return mWasInCh12to14;
+ }
+
private:
typedef enum WiFiStatus {
DISCONNECTED = 0,
@@ -86,6 +90,7 @@ class ahoywifi {
bool mGotDisconnect;
std::list mBSSIDList;
bool mStopApAllowed;
+ bool mWasInCh12to14 = false;
};
#endif /*__AHOYWIFI_H__*/
From bba82d8b3a9a634381dfdf128f1fa11e72b163a8 Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Tue, 30 Jan 2024 13:32:55 +0100
Subject: [PATCH 18/79] different tx-offests for 4ch HM
* discord 0.8.6803
* tx+3 for 4ch-HM, tx+2 for other Inverters
---
src/hm/CommQueue.h | 2 +-
src/hm/Communication.h | 9 ++++++---
src/hm/HeuristicInv.h | 15 +++++++++++++++
src/hm/hmInverter.h | 21 ++++++++++++++++++---
src/hm/hmRadio.h | 43 ++++++++++++++++++++++++++----------------
src/hm/hmSystem.h | 7 ++++++-
src/hms/cmt2300a.h | 6 +++---
7 files changed, 76 insertions(+), 27 deletions(-)
diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h
index d7cc5642..acbe9a35 100644
--- a/src/hm/CommQueue.h
+++ b/src/hm/CommQueue.h
@@ -12,7 +12,7 @@
#include "../utils/dbg.h"
#define DEFAULT_ATTEMPS 5
-#define MORE_ATTEMPS_ALARMDATA 0 // 8
+#define MORE_ATTEMPS_ALARMDATA 3 // 8
#define MORE_ATTEMPS_GRIDONPROFILEPARA 0 // 5
template
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 9219bb8e..8887a4a2 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -140,7 +140,10 @@ class Communication : public CommQueue<> {
if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
#if defined(ESP32)
- q->iv->radio->switchFrequency(q->iv, q->iv->radio->getBootFreqMhz() * 1000, (q->iv->config->frequency*FREQ_STEP_KHZ + q->iv->radio->getBaseFreqMhz() * 1000));
+ if(!q->iv->radio->switchFrequency(q->iv, q->iv->radio->getBootFreqMhz() * 1000, (q->iv->config->frequency*FREQ_STEP_KHZ + q->iv->radio->getBaseFreqMhz() * 1000))) {
+ DPRINT_IVID(DBG_INFO, q->iv->id);
+ DBGPRINTLN(F("switch frequency failed!"));
+ }
mWaitTime.startTimeMonitor(1000);
#endif
} else {
@@ -418,8 +421,8 @@ class Communication : public CommQueue<> {
if((*frameId & ALL_FRAMES) == ALL_FRAMES) {
mMaxFrameId = (*frameId & 0x7f);
- /*if(mMaxFrameId > 8) // large payloads, e.g. AlarmData
- incrAttempt(mMaxFrameId - 6);*/
+ if(mMaxFrameId > 8) // large payloads, e.g. AlarmData
+ incrAttempt(mMaxFrameId - 6);
}
frame_t *f = &mLocalBuf[(*frameId & 0x7f) - 1];
diff --git a/src/hm/HeuristicInv.h b/src/hm/HeuristicInv.h
index e9c7084e..505562e3 100644
--- a/src/hm/HeuristicInv.h
+++ b/src/hm/HeuristicInv.h
@@ -14,7 +14,22 @@
class HeuristicInv {
public:
HeuristicInv() {
+ clear();
+ }
+
+ void clear() {
memset(txRfQuality, 0, RF_MAX_CHANNEL_ID);
+ txRfChId = 0;
+ lastBestTxChId = 0;
+ testPeriodSendCnt = 0;
+ testPeriodFailCnt = 0;
+ testChId = 0;
+ saveOldTestQuality = -6;
+ lastRxFragments = 0;
+ }
+
+ bool isTxAtMax(void) const {
+ return (RF_MAX_QUALITY == txRfQuality[txRfChId]);
}
public:
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index a74ad02f..e6e22fb7 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -193,6 +193,14 @@ class Inverter {
if(mNextLive)
cb(RealTimeRunData_Debug, false); // get live data
else {
+ if(INV_RADIO_TYPE_NRF == ivRadioType) {
+ // get live data until quality reaches maximum
+ if(!heuristics.isTxAtMax()) {
+ cb(RealTimeRunData_Debug, false); // get live data
+ return;
+ }
+ }
+
if(actPowerLimit == 0xffff) {
cb(SystemConfigPara, false); // power limit info
cb(RealTimeRunData_Debug, false);
@@ -201,17 +209,18 @@ class Inverter {
devControlCmd = InitDataState;
mGetLossInterval = 1;
} else if(0 == getFwVersion()) {
- cb(RealTimeRunData_Debug, false); // get live data
cb(InverterDevInform_All, false); // get firmware version
+ cb(RealTimeRunData_Debug, false); // get live data
}
else if(0 == getHwVersion()) {
- cb(RealTimeRunData_Debug, false); // get live data
cb(InverterDevInform_Simple, false); // get hardware version
- } else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0)) {
cb(RealTimeRunData_Debug, false); // get live data
+ } else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0)) {
cb(AlarmData, false); // get last alarms
+ cb(RealTimeRunData_Debug, false); // get live data
} else if((0 == mGridLen) && generalConfig->readGrid) { // read grid profile
cb(GridOnProFilePara, false);
+ cb(RealTimeRunData_Debug, false); // get live data
} else if (mGetLossInterval > AHOY_GET_LOSS_INTERVAL) { // get loss rate
mGetLossInterval = 1;
cb(RealTimeRunData_Debug, false); // get live data
@@ -455,6 +464,12 @@ class Inverter {
status = InverterStatus::OFF;
actPowerLimit = 0xffff; // power limit will be read once inverter becomes available
alarmMesIndex = 0;
+ if(ivRadioType == INV_RADIO_TYPE_NRF) {
+ heuristics.clear();
+ #ifdef DYNAMIC_OFFSET
+ rxOffset = ivGen == IV_HM ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
+ #endif
+ }
}
else
status = InverterStatus::WAS_ON;
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index e759576c..0dcbccb3 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -121,14 +121,14 @@ class HmRadio : public Radio {
if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME))) //(DURATION_TXFRAME+DURATION_ONEFRAME)))
mNRFloopChannels = true;
- rxPendular = !rxPendular;
+ mRxPendular = !mRxPendular;
//innerLoopTimeout = (rxPendular ? 1 : 2)*DURATION_LISTEN_MIN;
- //innerLoopTimeout = DURATION_LISTEN_MIN;
+ innerLoopTimeout = DURATION_LISTEN_MIN;
if(mNRFloopChannels)
tempRxChIdx = (tempRxChIdx + 4) % RF_CHANNELS;
else
- tempRxChIdx = (mRxChIdx + rxPendular*4) % RF_CHANNELS;
+ tempRxChIdx = (mRxChIdx + mRxPendular*4) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[tempRxChIdx]);
isRxInit = false;
@@ -142,7 +142,7 @@ class HmRadio : public Radio {
if(tx_ok || tx_fail) { // tx related interrupt, basically we should start listening
mNrf24->flush_tx(); // empty TX FIFO
- mTxSetupTime = millis() - mMillis;
+ //mTxSetupTime = millis() - mMillis;
if(mNRFisInRX) {
DPRINTLN(DBG_WARN, F("unexpected tx irq!"));
@@ -153,17 +153,21 @@ class HmRadio : public Radio {
if(tx_ok)
mLastIv->mAckCount++;
- //mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
+ //#ifdef DYNAMIC_OFFSET
mRxChIdx = (mTxChIdx + mLastIv->rxOffset) % RF_CHANNELS;
+ /*#else
+ mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
+ #endif*/
mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening();
mTimeslotStart = millis();
tempRxChIdx = mRxChIdx; // might be better to start off with one channel less?
- rxPendular = false;
+ mRxPendular = false;
mNRFloopChannels = (mLastIv->ivGen == IV_MI);
//innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME;
- innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_LISTEN_MIN : 4;
+ //innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_LISTEN_MIN : 4;
+ innerLoopTimeout = (mLastIv->mIsSingleframeReq || mLastIv->ivGen == IV_MI) ? DURATION_LISTEN_MIN : DURATION_TXFRAME;
}
if(rx_ready) {
@@ -176,7 +180,7 @@ class HmRadio : public Radio {
innerLoopTimeout = DURATION_LISTEN_MIN;
mTimeslotStart = millis();
if (!mNRFloopChannels) {
- //rxPendular = true; // stay longer on the next rx channel
+ //mRxPendular = true; // stay longer on the next rx channel
if (isRxInit) {
isRxInit = false;
tempRxChIdx = (mRxChIdx + 4) % RF_CHANNELS;
@@ -325,12 +329,14 @@ class HmRadio : public Radio {
isRetransmitAnswer = true;
if(isLastPackage)
setExpectedFrames(p.packet[9] - ALL_FRAMES);
+ #ifdef DYNAMIC_OFFSET
if(p.packet[9] == 1 && p.millis < DURATION_ONEFRAME)
mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + 1) % RF_CHANNELS;
else if(mNRFloopChannels && mLastIv->rxOffset > RF_CHANNELS) { // unsure setting?
mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + (isLastPackage ? mFramesExpected : p.packet[9])); // make clear it's not sure, start with one more offset
mNRFloopChannels = false;
}
+ #endif
}
if(IV_MI == mLastIv->ivGen) {
@@ -338,8 +344,10 @@ class HmRadio : public Radio {
isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received
else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore MI status messages //#0 was p.packet[0] != 0x00 &&
isLastPackage = true; // response from dev control command
+ #ifdef DYNAMIC_OFFSET
if(p.packet[9] == 0x00 && p.millis < DURATION_ONEFRAME)
mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx - 1) % RF_CHANNELS;
+ #endif
}
rx_ready = true; //reset in case we first read messages from other inverter or ACK zero payloads
}
@@ -347,9 +355,8 @@ class HmRadio : public Radio {
}
yield();
}
- if(isLastPackage) {
+ if(isLastPackage)
mLastIv->mGotLastMsg = true;
- }
return isLastPackage || isRetransmitAnswer;
}
@@ -361,10 +368,7 @@ class HmRadio : public Radio {
mTxChIdx = iv->heuristics.txRfChId;
if(*mSerialDebug) {
- /* remark rejoe2: imo this has no added value here.
- As this belongs to the last tx cycle, we should print that info
- directly when switching from tx to rx. Otherwise we might confuse users.
- if(!isRetransmit) {
+ /*if(!isRetransmit) {
DPRINT(DBG_INFO, "last tx setup: ");
DBGPRINT(String(mTxSetupTime));
DBGPRINTLN("ms");
@@ -374,13 +378,19 @@ class HmRadio : public Radio {
DBGPRINT(F("TX "));
DBGPRINT(String(len));
DBGPRINT(" CH");
+ if(mTxChIdx == 0)
+ DBGPRINT("0");
DBGPRINT(String(mRfChLst[mTxChIdx]));
DBGPRINT(F(", "));
DBGPRINT(String(mTxRetriesNext));
//DBGPRINT(F(" retries | "));
+ //#ifdef DYNAMIC_OFFSET
DBGPRINT(F(" ret., rx offset: "));
DBGPRINT(String(iv->rxOffset));
DBGPRINT(F(" | "));
+ /*#else
+ DBGPRINT(F(" ret. | "));
+ #endif*/
if(*mPrintWholeTrace) {
if(*mPrivacyMode)
ah::dumpBuf(mTxBuf, len, 1, 4);
@@ -396,6 +406,7 @@ class HmRadio : public Radio {
}
mNrf24->stopListening();
+ mNrf24->flush_rx();
if(!isRetransmit && mTxRetries != mTxRetriesNext) {
mNrf24->setRetries(3, mTxRetriesNext);
mTxRetries = mTxRetriesNext;
@@ -439,9 +450,9 @@ class HmRadio : public Radio {
bool mNRFloopChannels = false;
bool mNRFisInRX = false;
bool isRxInit = true;
- bool rxPendular = false;
+ bool mRxPendular = false;
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
- uint8_t mTxSetupTime = 0;
+ //uint8_t mTxSetupTime = 0;
uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15);
std::unique_ptr mSpi;
diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h
index 26d0ea5d..b727e0bb 100644
--- a/src/hm/hmSystem.h
+++ b/src/hm/hmSystem.h
@@ -28,7 +28,6 @@ class HmSystem {
iv->config = &mInverter[0].generalConfig->iv[id];
DPRINT(DBG_VERBOSE, "SERIAL: " + String(iv->config->serial.b[5], HEX));
DPRINTLN(DBG_VERBOSE, " " + String(iv->config->serial.b[4], HEX));
- iv->rxOffset = 13; // effective 3, but can easily be recognized as default setting
if((iv->config->serial.b[5] == 0x11) || (iv->config->serial.b[5] == 0x10)) {
switch(iv->config->serial.b[4]) {
case 0x24: // HMS-500
@@ -96,6 +95,12 @@ class HmSystem {
if((iv->config->serial.b[5] == 0x10) && ((iv->config->serial.b[4] & 0x03) == 0x01))
DPRINTLN(DBG_WARN, F("MI Inverter, has some restrictions!"));
+ #ifdef DYNAMIC_OFFSET
+ iv->rxOffset = iv->ivGen == IV_HM ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
+ #else
+ iv->rxOffset = (iv->ivGen == IV_HM && iv->type == INV_TYPE_4CH) ? 3 : 2; // effective 3 (or 2), but can easily be recognized as default setting
+ #endif
+
cb(iv);
}
diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h
index 3cdc2660..e6456f5b 100644
--- a/src/hms/cmt2300a.h
+++ b/src/hms/cmt2300a.h
@@ -356,11 +356,11 @@ class Cmt2300a {
if((freqKhz % FREQ_STEP_KHZ) != 0)
return 0xff; // error
- std::pair range = getFreqRangeMhz();
- if((freqKhz < range.first) || (freqKhz > range.second))
+ std::pair range = getFreqRangeMhz();
+ if((freqKhz < (range.first * 1000)) || (freqKhz > (range.second * 1000)))
return 0xff; // error
- return (freqKhz - getBaseFreqMhz() * 1000) / FREQ_STEP_KHZ;
+ return (freqKhz - (getBaseFreqMhz() * 1000)) / FREQ_STEP_KHZ;
}
inline void switchChannel(uint8_t ch) {
From fddd03af6b98f75c73ba1b93a29cec88358ef527 Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Tue, 30 Jan 2024 15:37:40 +0100
Subject: [PATCH 19/79] re-flexibilisize rx-channels
also for HM 2ch devices
---
src/hm/hmDefines.h | 4 ++--
src/hm/hmRadio.h | 5 ++---
src/hm/hmSystem.h | 3 ++-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h
index 4705c061..f06c06fe 100644
--- a/src/hm/hmDefines.h
+++ b/src/hm/hmDefines.h
@@ -90,8 +90,8 @@ const uint8_t duration_reserve[2] = {65,115};
#define LIMIT_VERYFAST_IV 70 // time limit to qualify an inverter as very fast answering inverter
#define LIMIT_FAST_IV_MI 35 // time limit to qualify a MI type inverter as fast answering inverter
#define LIMIT_VERYFAST_IV_MI 22 // time limit to qualify a MI type inverter as very fast answering inverter
-#define RETRIES_FAST_IV 11 // how often shall a message be automatically retransmitted by the nRF (fast answering inverter)
-#define RETRIES_VERYFAST_IV 7 // how often shall a message be automatically retransmitted by the nRF (very fast answering inverter)
+#define RETRIES_FAST_IV 12 // how often shall a message be automatically retransmitted by the nRF (fast answering inverter)
+#define RETRIES_VERYFAST_IV 9 // how often shall a message be automatically retransmitted by the nRF (very fast answering inverter)
typedef struct {
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index 0dcbccb3..a88e43c6 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -122,7 +122,6 @@ class HmRadio : public Radio {
mNRFloopChannels = true;
mRxPendular = !mRxPendular;
- //innerLoopTimeout = (rxPendular ? 1 : 2)*DURATION_LISTEN_MIN;
innerLoopTimeout = DURATION_LISTEN_MIN;
if(mNRFloopChannels)
@@ -167,7 +166,8 @@ class HmRadio : public Radio {
//innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME;
//innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_LISTEN_MIN : 4;
- innerLoopTimeout = (mLastIv->mIsSingleframeReq || mLastIv->ivGen == IV_MI) ? DURATION_LISTEN_MIN : DURATION_TXFRAME;
+ //innerLoopTimeout = (mLastIv->mIsSingleframeReq || mLastIv->ivGen == IV_MI) ? DURATION_LISTEN_MIN : DURATION_TXFRAME;
+ innerLoopTimeout = DURATION_LISTEN_MIN;
}
if(rx_ready) {
@@ -180,7 +180,6 @@ class HmRadio : public Radio {
innerLoopTimeout = DURATION_LISTEN_MIN;
mTimeslotStart = millis();
if (!mNRFloopChannels) {
- //mRxPendular = true; // stay longer on the next rx channel
if (isRxInit) {
isRxInit = false;
tempRxChIdx = (mRxChIdx + 4) % RF_CHANNELS;
diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h
index b727e0bb..aa5d7492 100644
--- a/src/hm/hmSystem.h
+++ b/src/hm/hmSystem.h
@@ -98,7 +98,8 @@ class HmSystem {
#ifdef DYNAMIC_OFFSET
iv->rxOffset = iv->ivGen == IV_HM ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
#else
- iv->rxOffset = (iv->ivGen == IV_HM && iv->type == INV_TYPE_4CH) ? 3 : 2; // effective 3 (or 2), but can easily be recognized as default setting
+ iv->rxOffset = (iv->ivGen == IV_HM && iv->type == INV_TYPE_4CH) ? 3 : 2;
+ iv->rxOffset = iv->ivGen == IV_HM ? 3 : 2;
#endif
cb(iv);
From 349184a11331463b6e80363ea11b6f59e376d9a8 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Wed, 31 Jan 2024 22:24:08 +0100
Subject: [PATCH 20/79] 0.8.69 * fix brackets
---
src/hm/Communication.h | 12 ++++++------
src/hm/Heuristic.h | 2 +-
src/hm/HeuristicInv.h | 10 +++++++---
src/hm/hmDefines.h | 2 +-
src/hm/hmInverter.h | 2 +-
src/hm/hmRadio.h | 9 +++++----
src/hm/hmSystem.h | 6 +++---
7 files changed, 24 insertions(+), 19 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 5725f2ec..923bffe1 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -87,7 +87,7 @@ class Communication : public CommQueue<> {
mIsRetransmit = false;
if(NULL == q->iv->radio)
cmdDone(false); // can't communicate while radio is not defined!
- mFirstTry = INV_RADIO_TYPE_NRF == q->iv->ivRadioType && q->iv->isAvailable();
+ mFirstTry = (INV_RADIO_TYPE_NRF == q->iv->ivRadioType) && (q->iv->isAvailable());
q->iv->mCmd = q->cmd;
q->iv->mIsSingleframeReq = false;
mFramesExpected = getFramesExpected(q); // function to get expected frame count.
@@ -116,7 +116,7 @@ class Communication : public CommQueue<> {
//q->iv->radioStatistics.txCnt++;
q->iv->radio->mRadioWaitTime.startTimeMonitor(mTimeout);
if(!mIsRetransmit && (q->cmd == AlarmData) || (q->cmd == GridOnProFilePara))
- incrAttempt(q->cmd == AlarmData? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA);
+ incrAttempt((q->cmd == AlarmData)? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA);
mIsRetransmit = false;
setAttempt();
@@ -184,7 +184,7 @@ class Communication : public CommQueue<> {
if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
if(parseFrame(p)) {
q->iv->curFrmCnt++;
- if(!mIsRetransmit && (p->packet[9] == 0x02 || p->packet[9] == 0x82) && p->millis < LIMIT_FAST_IV)
+ if(!mIsRetransmit && ((p->packet[9] == 0x02) || (p->packet[9] == 0x82)) && (p->millis < LIMIT_FAST_IV))
mHeu.setIvRetriesGood(q->iv,p->millis < LIMIT_VERYFAST_IV);
}
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command
@@ -257,13 +257,13 @@ class Communication : public CommQueue<> {
return;
}
//count missing frames
- if(!q->iv->mIsSingleframeReq && q->iv->ivRadioType == INV_RADIO_TYPE_NRF) { // already checked?
+ if(!q->iv->mIsSingleframeReq && (q->iv->ivRadioType == INV_RADIO_TYPE_NRF)) { // already checked?
uint8_t missedFrames = 0;
for(uint8_t i = 0; i < q->iv->radio->mFramesExpected; i++) {
if(mLocalBuf[i].len == 0)
missedFrames++;
}
- if(missedFrames > 3 || (q->cmd == RealTimeRunData_Debug && missedFrames > 1) || (missedFrames > 1 && missedFrames + 2 > q->attempts)) {
+ if(missedFrames > 3 || (q->cmd == RealTimeRunData_Debug && missedFrames > 1) || ((missedFrames > 1) && ((missedFrames + 2) > q->attempts))) {
if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(String(missedFrames));
@@ -435,7 +435,7 @@ class Communication : public CommQueue<> {
}
inline bool parseMiFrame(packet_t *p, const queue_s *q) {
- if(!mIsRetransmit && p->packet[9] == 0x00 && p->millis < LIMIT_FAST_IV_MI) //first frame is fast?
+ if((!mIsRetransmit && p->packet[9] == 0x00) && (p->millis < LIMIT_FAST_IV_MI)) //first frame is fast?
mHeu.setIvRetriesGood(q->iv,p->millis < LIMIT_VERYFAST_IV_MI);
if ((p->packet[0] == MI_REQ_CH1 + ALL_FRAMES)
|| (p->packet[0] == MI_REQ_CH2 + ALL_FRAMES)
diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h
index 3fb86614..fa4512b5 100644
--- a/src/hm/Heuristic.h
+++ b/src/hm/Heuristic.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
//-----------------------------------------------------------------------------
diff --git a/src/hm/HeuristicInv.h b/src/hm/HeuristicInv.h
index 89099ca8..913732bc 100644
--- a/src/hm/HeuristicInv.h
+++ b/src/hm/HeuristicInv.h
@@ -26,6 +26,11 @@ class HeuristicInv {
testChId = 0;
saveOldTestQuality = -6;
lastRxFragments = 0;
+
+ rxSpeeds[0] = false;
+ rxSpeeds[1] = false;
+ rxSpeedCnt[0] = 0;
+ rxSpeedCnt[1] = 0;
}
bool isTxAtMax(void) const {
@@ -42,9 +47,8 @@ class HeuristicInv {
uint8_t testChId = 0;
int8_t saveOldTestQuality = -6;
uint8_t lastRxFragments = 0;
- bool rxSpeeds[2] = {false,false}; // is inverter responding very fast respective fast?
- uint8_t rxSpeedCnt[2] = {0,0}; // count how many messages had been received very fast respective fast (10 max)
-
+ bool rxSpeeds[2] = {false, false}; // is inverter responding very fast respective fast?
+ uint8_t rxSpeedCnt[2] = {0, 0}; // count how many messages had been received very fast respective fast (10 max)
};
#endif /*__HEURISTIC_INV_H__*/
diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h
index f06c06fe..0b42aeae 100644
--- a/src/hm/hmDefines.h
+++ b/src/hm/hmDefines.h
@@ -84,7 +84,7 @@ enum {INV_RADIO_TYPE_NRF = 0, INV_RADIO_TYPE_CMT};
#define DURATION_TXFRAME 85 // timeout parameter for first transmission and first expected frame (time to first channel switch from tx start!) (ms)
#define DURATION_LISTEN_MIN 5 // time to stay at least on a listening channel (ms)
#define DURATION_PAUSE_LASTFR 45 // how long to pause after last frame (ms)
-const uint8_t duration_reserve[2] = {65,115};
+const uint8_t duration_reserve[2] = {65, 115};
#define LIMIT_FAST_IV 85 // time limit to qualify an inverter as very fast answering inverter
#define LIMIT_VERYFAST_IV 70 // time limit to qualify an inverter as very fast answering inverter
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index e6e22fb7..e4015110 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -464,7 +464,7 @@ class Inverter {
status = InverterStatus::OFF;
actPowerLimit = 0xffff; // power limit will be read once inverter becomes available
alarmMesIndex = 0;
- if(ivRadioType == INV_RADIO_TYPE_NRF) {
+ if(INV_RADIO_TYPE_NRF == ivRadioType) {
heuristics.clear();
#ifdef DYNAMIC_OFFSET
rxOffset = ivGen == IV_HM ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index d1dd42d5..ca96a333 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -328,12 +328,13 @@ class HmRadio : public Radio {
isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received
if(mLastIv->mIsSingleframeReq) // we only expect one frame here...
isRetransmitAnswer = true;
+
if(isLastPackage)
setExpectedFrames(p.packet[9] - ALL_FRAMES);
#ifdef DYNAMIC_OFFSET
- if(p.packet[9] == 1 && p.millis < DURATION_ONEFRAME)
+ if((p.packet[9] == 1) && (p.millis < DURATION_ONEFRAME))
mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + 1) % RF_CHANNELS;
- else if(mNRFloopChannels && mLastIv->rxOffset > RF_CHANNELS) { // unsure setting?
+ else if(mNRFloopChannels && (mLastIv->rxOffset > RF_CHANNELS)) { // unsure setting?
mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + (isLastPackage ? mFramesExpected : p.packet[9])); // make clear it's not sure, start with one more offset
mNRFloopChannels = false;
}
@@ -346,7 +347,7 @@ class HmRadio : public Radio {
else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore MI status messages //#0 was p.packet[0] != 0x00 &&
isLastPackage = true; // response from dev control command
#ifdef DYNAMIC_OFFSET
- if(p.packet[9] == 0x00 && p.millis < DURATION_ONEFRAME)
+ if((p.packet[9] == 0x00) && (p.millis < DURATION_ONEFRAME))
mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx - 1) % RF_CHANNELS;
#endif
}
@@ -408,7 +409,7 @@ class HmRadio : public Radio {
mNrf24->stopListening();
mNrf24->flush_rx();
- if(!isRetransmit && mTxRetries != mTxRetriesNext) {
+ if(!isRetransmit && (mTxRetries != mTxRetriesNext)) {
mNrf24->setRetries(3, mTxRetriesNext);
mTxRetries = mTxRetriesNext;
}
diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h
index aa5d7492..aa2910e5 100644
--- a/src/hm/hmSystem.h
+++ b/src/hm/hmSystem.h
@@ -96,10 +96,10 @@ class HmSystem {
DPRINTLN(DBG_WARN, F("MI Inverter, has some restrictions!"));
#ifdef DYNAMIC_OFFSET
- iv->rxOffset = iv->ivGen == IV_HM ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
+ iv->rxOffset = (iv->ivGen == IV_HM) ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
#else
- iv->rxOffset = (iv->ivGen == IV_HM && iv->type == INV_TYPE_4CH) ? 3 : 2;
- iv->rxOffset = iv->ivGen == IV_HM ? 3 : 2;
+ iv->rxOffset = ((iv->ivGen == IV_HM) && (iv->type == INV_TYPE_4CH)) ? 3 : 2;
+ iv->rxOffset = (iv->ivGen == IV_HM) ? 3 : 2;
#endif
cb(iv);
From f89fd66dbf3951513475bb1eb03f8a92a9736c00 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Wed, 31 Jan 2024 22:46:41 +0100
Subject: [PATCH 21/79] 0.8.69 * merge PR: Dynamic retries, pendular first rx
chan #1394
---
src/CHANGES.md | 3 ++
src/defines.h | 4 +--
src/hm/hmInverter.h | 69 ++++++++++++++++++---------------------------
src/web/lang.json | 2 +-
4 files changed, 33 insertions(+), 45 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index f690b192..4de7afa4 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,8 @@
# Development Changes
+## 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
diff --git a/src/defines.h b/src/defines.h
index 442008ff..a4a1d6bd 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 68
+#define VERSION_PATCH 69
//-------------------------------------
typedef struct {
@@ -22,8 +22,6 @@ typedef struct {
int8_t rssi;
uint8_t packet[MAX_RF_PAYLOAD_SIZE];
uint16_t millis;
- uint8_t arc;
- uint8_t plos;
} packet_t;
typedef enum {
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index e4015110..1ceed42e 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -190,44 +190,37 @@ class Inverter {
mDevControlRequest = false;
} else if (IV_MI != ivGen) { // HM / HMS / HMT
mGetLossInterval++;
- if(mNextLive)
- cb(RealTimeRunData_Debug, false); // get live data
- else {
- if(INV_RADIO_TYPE_NRF == ivRadioType) {
- // get live data until quality reaches maximum
- if(!heuristics.isTxAtMax()) {
- cb(RealTimeRunData_Debug, false); // get live data
- return;
- }
- }
-
- if(actPowerLimit == 0xffff) {
- cb(SystemConfigPara, false); // power limit info
- cb(RealTimeRunData_Debug, false);
- } else if(InitDataState != devControlCmd) {
- cb(devControlCmd, false); // custom command which was received by API
- devControlCmd = InitDataState;
- mGetLossInterval = 1;
- } else if(0 == getFwVersion()) {
- cb(InverterDevInform_All, false); // get firmware version
+ if(INV_RADIO_TYPE_NRF == ivRadioType) {
+ // get live data until quality reaches maximum
+ if(!heuristics.isTxAtMax()) {
cb(RealTimeRunData_Debug, false); // get live data
+ return;
}
- else if(0 == getHwVersion()) {
- cb(InverterDevInform_Simple, false); // get hardware version
- cb(RealTimeRunData_Debug, false); // get live data
- } else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0)) {
- cb(AlarmData, false); // get last alarms
- cb(RealTimeRunData_Debug, false); // get live data
- } else if((0 == mGridLen) && generalConfig->readGrid) { // read grid profile
- cb(GridOnProFilePara, false);
- cb(RealTimeRunData_Debug, false); // get live data
- } else if (mGetLossInterval > AHOY_GET_LOSS_INTERVAL) { // get loss rate
- mGetLossInterval = 1;
- cb(RealTimeRunData_Debug, false); // get live data
- cb(GetLossRate, false);
- } else
- cb(RealTimeRunData_Debug, false); // get live data
}
+
+ if(actPowerLimit == 0xffff) {
+ cb(SystemConfigPara, false); // power limit info
+ } else if(InitDataState != devControlCmd) {
+ cb(devControlCmd, false); // custom command which was received by API
+ devControlCmd = InitDataState;
+ mGetLossInterval = 1;
+ return;
+ } else if(0 == getFwVersion()) {
+ cb(InverterDevInform_All, false); // get firmware version
+ } else if(0 == getHwVersion()) {
+ cb(InverterDevInform_Simple, false); // get hardware version
+ } else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0)) {
+ cb(AlarmData, false); // get last alarms
+ } else if((0 == mGridLen) && generalConfig->readGrid) { // read grid profile
+ cb(GridOnProFilePara, false);
+ } else if (mGetLossInterval > AHOY_GET_LOSS_INTERVAL) { // get loss rate
+ mGetLossInterval = 1;
+ cb(RealTimeRunData_Debug, false); // get live data
+ cb(GetLossRate, false);
+ return;
+ }
+
+ cb(RealTimeRunData_Debug, false); // get live data
} else { // MI
cb(((type == INV_TYPE_4CH) ? MI_REQ_4CH : MI_REQ_CH1), false);
mGetLossInterval++;
@@ -279,21 +272,18 @@ class Inverter {
}
const char *getFieldName(uint8_t pos, record_t<> *rec) {
- DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getFieldName"));
if(NULL != rec)
return fields[rec->assign[pos].fieldId];
return notAvail;
}
const char *getUnit(uint8_t pos, record_t<> *rec) {
- DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getUnit"));
if(NULL != rec)
return units[rec->assign[pos].unitId];
return notAvail;
}
uint8_t getChannel(uint8_t pos, record_t<> *rec) {
- DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getChannel"));
if(NULL != rec)
return rec->assign[pos].ch;
return 0;
@@ -350,7 +340,6 @@ class Inverter {
}
if(rec == &recordMeas) {
- mNextLive = false; // live data received
DPRINTLN(DBG_VERBOSE, "add real time");
// get last alarm message index and save it in the inverter object
if (getPosByChFld(0, FLD_EVT, rec) == pos) {
@@ -363,7 +352,6 @@ class Inverter {
}
}
else {
- mNextLive = true;
if (rec->assign == InfoAssignment) {
DPRINTLN(DBG_DEBUG, "add info");
// eg. fw version ...
@@ -868,7 +856,6 @@ class Inverter {
uint8_t mGridLen = 0;
uint8_t mGridProfile[MAX_GRID_LENGTH];
uint8_t mAlarmNxtWrPos = 0; // indicates the position in array (rolling buffer)
- bool mNextLive = true; // first read live data after booting up then version etc.
public:
uint16_t mDtuRxCnt = 0;
diff --git a/src/web/lang.json b/src/web/lang.json
index d083ddff..1617658a 100644
--- a/src/web/lang.json
+++ b/src/web/lang.json
@@ -1396,7 +1396,7 @@
{
"token": "CMD_RECEIVED_WAIT_ACK",
"en": "received command, waiting for inverter acknowledge ...",
- "de": "Befehl erhalten, warte auf Bestäigung von Wechselrichter ..."
+ "de": "Befehl erhalten, warte auf Bestäigung vom Wechselrichter ..."
},
{
"token": "COMMAND_RECEIVED",
From ae799b4c2130c8b12c6b96994bd2238ec7695657 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Thu, 1 Feb 2024 21:38:07 +0100
Subject: [PATCH 22/79] 0.8.70 * prevent sending commands to inverter which
isn't active #1387
---
.github/workflows/compile_development.yml | 12 ++++-----
src/CHANGES.md | 3 +++
src/hm/Communication.h | 1 -
src/hm/hmInverter.h | 31 +++++++++++------------
4 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml
index 7eaf9b34..67fa6f0a 100644
--- a/.github/workflows/compile_development.yml
+++ b/.github/workflows/compile_development.yml
@@ -12,7 +12,7 @@ jobs:
if: github.repository == 'lumapu/ahoy' && github.ref_name == 'development03'
continue-on-error: true
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
build-en:
needs: check
@@ -32,7 +32,7 @@ jobs:
- opendtufusion
- opendtufusion-ethernet
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- uses: benjlevesque/short-sha@v2.1
id: short-sha
with:
@@ -53,7 +53,7 @@ jobs:
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- name: Setup Python
- uses: actions/setup-python@v4.3.0
+ uses: actions/setup-python@v5
with:
python-version: "3.x"
@@ -92,7 +92,7 @@ jobs:
- opendtufusion-de
- opendtufusion-ethernet-de
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- uses: benjlevesque/short-sha@v2.1
id: short-sha
with:
@@ -113,7 +113,7 @@ jobs:
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- name: Setup Python
- uses: actions/setup-python@v4.3.0
+ uses: actions/setup-python@v5
with:
python-version: "3.x"
@@ -138,7 +138,7 @@ jobs:
needs: [build-en, build-de]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
#- name: Copy boot_app0.bin
# run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin src/.pio/build/opendtufusion/ota.bin
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 4de7afa4..4b6eda8e 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,8 @@
# Development Changes
+## 0.8.70 - 2024-02-01
+* prevent sending commands to inverter which isn't active #1387
+
## 0.8.69 - 2024-01-31
* merge PR: Dynamic retries, pendular first rx chan #1394
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 923bffe1..4895d2e7 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -681,7 +681,6 @@ class Communication : public CommQueue<> {
for (uint8_t i = 0; i < 5; i++) {
q->iv->setValue(i, rec, (float) ((p->packet[(12+2*i)] << 8) + p->packet[(13+2*i)])/1);
}
- q->iv->isConnected = true;
if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("HW_VER is "));
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index 1ceed42e..a5276880 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -130,7 +130,6 @@ class Inverter {
record_t recordHwInfo; // structure for simple (hardware) info values
record_t recordConfig; // structure for system config values
record_t recordAlarm; // structure for alarm values
- bool isConnected; // shows if inverter was successfully identified (fw version and hardware info)
InverterStatus status; // indicates the current inverter status
std::array lastAlarm; // holds last 10 alarms
uint8_t rxOffset; // holds the default channel offset between tx and rx channel (nRF only)
@@ -166,7 +165,6 @@ class Inverter {
mDevControlRequest = false;
devControlCmd = InitDataState;
alarmMesIndex = 0;
- isConnected = false;
status = InverterStatus::OFF;
alarmCnt = 0;
alarmLastId = 0;
@@ -186,7 +184,10 @@ class Inverter {
void tickSend(std::function cb) {
if(mDevControlRequest) {
- cb(devControlCmd, true);
+ if(InverterStatus::PRODUCING == status)
+ cb(devControlCmd, true);
+ else
+ DPRINTLN(DBG_WARN, F("Inverter is not avail"));
mDevControlRequest = false;
} else if (IV_MI != ivGen) { // HM / HMS / HMT
mGetLossInterval++;
@@ -262,8 +263,7 @@ class Inverter {
break;
}
return (pos >= rec->length) ? 0xff : pos;
- }
- else
+ } else
return 0xff;
}
@@ -290,18 +290,18 @@ class Inverter {
}
bool setDevControlRequest(uint8_t cmd) {
- if(isConnected) {
+ if(InverterStatus::PRODUCING == status) {
mDevControlRequest = true;
devControlCmd = cmd;
//app->triggerTickSend(); // done in RestApi.h, because of "chicken-and-egg problem ;-)"
}
- return isConnected;
+ return (InverterStatus::PRODUCING == status);
}
bool setDevCommand(uint8_t cmd) {
- if(isConnected)
+ if(InverterStatus::PRODUCING == status)
devControlCmd = cmd;
- return isConnected;
+ return (InverterStatus::PRODUCING == status);
}
void addValue(uint8_t pos, uint8_t buf[], record_t<> *rec) {
@@ -318,6 +318,7 @@ class Inverter {
val <<= 8;
val |= buf[ptr];
} while(++ptr != end);
+
if ((FLD_T == rec->assign[pos].fieldId) || (FLD_Q == rec->assign[pos].fieldId) || (FLD_PF == rec->assign[pos].fieldId)) {
// temperature, Qvar, and power factor are a signed values
rec->record[pos] = ((REC_TYP)((int16_t)val)) / (REC_TYP)(div);
@@ -350,12 +351,10 @@ class Inverter {
DBGPRINTLN(String(alarmMesIndex));
}
}
- }
- else {
+ } else {
if (rec->assign == InfoAssignment) {
DPRINTLN(DBG_DEBUG, "add info");
// eg. fw version ...
- isConnected = true;
} else if (rec->assign == SimpleInfoAssignment) {
DPRINTLN(DBG_DEBUG, "add simple info");
// eg. hw version ...
@@ -371,8 +370,7 @@ class Inverter {
} else
DPRINTLN(DBG_WARN, F("add with unknown assignment"));
}
- }
- else
+ } else
DPRINTLN(DBG_ERROR, F("addValue: assignment not found with cmd 0x"));
// update status state-machine
@@ -396,12 +394,12 @@ class Inverter {
if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId))
break;
}
+
if(pos >= rec->length)
return 0;
return rec->record[pos];
- }
- else
+ } else
return 0;
}
@@ -477,6 +475,7 @@ class Inverter {
else if(InverterStatus::PRODUCING == status)
status = InverterStatus::WAS_PRODUCING;
}
+
return producing;
}
From 4d7362fa6b1b1538933d476344036274523db748 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Thu, 1 Feb 2024 23:27:54 +0100
Subject: [PATCH 23/79] 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
---
src/CHANGES.md | 1 +
src/app.cpp | 5 ++-
src/app.h | 22 +++++++++-
src/appInterface.h | 6 ++-
src/defines.h | 2 +-
src/utils/spiPatcher.cpp | 4 +-
src/utils/spiPatcher.h | 4 +-
src/web/Protection.cpp | 7 +++
src/web/Protection.h | 93 ++++++++++++++++++++++++++++++++++++++++
src/web/RestApi.h | 15 +++++--
src/web/lang.h | 6 +++
src/web/web.h | 49 +++------------------
12 files changed, 156 insertions(+), 58 deletions(-)
create mode 100644 src/web/Protection.cpp
create mode 100644 src/web/Protection.h
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 4b6eda8e..9835873c 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -2,6 +2,7 @@
## 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
diff --git a/src/app.cpp b/src/app.cpp
index a14a8811..8b770989 100644
--- a/src/app.cpp
+++ b/src/app.cpp
@@ -97,9 +97,8 @@ void app::setup() {
esp_task_wdt_reset();
mWeb.setup(this, &mSys, mConfig);
- mWeb.setProtection(strlen(mConfig->sys.adminPwd) != 0);
-
mApi.setup(this, &mSys, mWeb.getWebSrvPtr(), mConfig);
+ mProtection = Protection::getInstance(mConfig->sys.adminPwd);
#ifdef ENABLE_SYSLOG
mDbgSyslog.setup(mConfig); // be sure to init after mWeb.setup (webSerial uses also debug callback)
@@ -182,6 +181,8 @@ void app::onNetwork(bool gotIp) {
void app::regularTickers(void) {
DPRINTLN(DBG_DEBUG, F("regularTickers"));
everySec(std::bind(&WebType::tickSecond, &mWeb), "webSc");
+ everySec([this]() { mProtection->tickSecond(); }, "prot");
+
// Plugins
#if defined(PLUGIN_DISPLAY)
if (DISP_TYPE_T0_NONE != mConfig->plugin.display.type)
diff --git a/src/app.h b/src/app.h
index ccf46297..b44d3781 100644
--- a/src/app.h
+++ b/src/app.h
@@ -30,6 +30,7 @@
#include "utils/scheduler.h"
#include "utils/syslog.h"
#include "web/RestApi.h"
+#include "web/Protection.h"
#if defined(ENABLE_HISTORY)
#include "plugins/history.h"
#endif /*ENABLE_HISTORY*/
@@ -246,8 +247,24 @@ class app : public IApp, public ah::Scheduler {
#endif
}
- bool getProtection(AsyncWebServerRequest *request) {
- return mWeb.isProtected(request);
+ void lock(void) override {
+ mProtection->lock();
+ }
+
+ void unlock(const char *clientIp) override {
+ mProtection->unlock(clientIp);
+ }
+
+ void resetLockTimeout(void) override {
+ mProtection->resetLockTimeout();
+ }
+
+ bool isProtected(void) const override {
+ return mProtection->isProtected();
+ }
+
+ bool isProtected(const char *clientIp) const override {
+ return mProtection->isProtected(clientIp);
}
bool getNrfEnabled(void) {
@@ -387,6 +404,7 @@ class app : public IApp, public ah::Scheduler {
#endif /* defined(ETHERNET) */
WebType mWeb;
RestApiType mApi;
+ Protection *mProtection;
#ifdef ENABLE_SYSLOG
DbgSyslog mDbgSyslog;
#endif
diff --git a/src/appInterface.h b/src/appInterface.h
index f98fb0cb..9930c51e 100644
--- a/src/appInterface.h
+++ b/src/appInterface.h
@@ -61,7 +61,11 @@ class IApp {
virtual uint32_t getMqttRxCnt() = 0;
virtual uint32_t getMqttTxCnt() = 0;
- virtual bool getProtection(AsyncWebServerRequest *request) = 0;
+ virtual void lock(void) = 0;
+ virtual void unlock(const char *clientIp) = 0;
+ virtual void resetLockTimeout(void) = 0;
+ virtual bool isProtected(void) const = 0;
+ virtual bool isProtected(const char *clientIp) const = 0;
virtual uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0;
virtual uint16_t getHistoryMaxDay() = 0;
diff --git a/src/defines.h b/src/defines.h
index a4a1d6bd..6d350add 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 69
+#define VERSION_PATCH 70
//-------------------------------------
typedef struct {
diff --git a/src/utils/spiPatcher.cpp b/src/utils/spiPatcher.cpp
index 0470b476..3b7b5681 100644
--- a/src/utils/spiPatcher.cpp
+++ b/src/utils/spiPatcher.cpp
@@ -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 - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
//-----------------------------------------------------------------------------
#if defined(ESP32)
diff --git a/src/utils/spiPatcher.h b/src/utils/spiPatcher.h
index 14cb138c..2f8ce616 100644
--- a/src/utils/spiPatcher.h
+++ b/src/utils/spiPatcher.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 - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
//-----------------------------------------------------------------------------
#ifndef __SPI_PATCHER_H__
diff --git a/src/web/Protection.cpp b/src/web/Protection.cpp
new file mode 100644
index 00000000..b822fb6a
--- /dev/null
+++ b/src/web/Protection.cpp
@@ -0,0 +1,7 @@
+//-----------------------------------------------------------------------------
+// 2024 Ahoy, https://github.com/lumpapu/ahoy
+// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
+//-----------------------------------------------------------------------------
+
+#include "Protection.h"
+Protection *Protection::mInstance = nullptr;
diff --git a/src/web/Protection.h b/src/web/Protection.h
new file mode 100644
index 00000000..44926752
--- /dev/null
+++ b/src/web/Protection.h
@@ -0,0 +1,93 @@
+//-----------------------------------------------------------------------------
+// 2024 Ahoy, https://github.com/lumpapu/ahoy
+// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
+//-----------------------------------------------------------------------------
+
+#ifndef __PROTECTION_H__
+#define __PROTECTION_H__
+#pragma once
+
+#include
+#include
+
+#include "../config/config.h"
+#include "../utils/helper.h"
+
+class Protection {
+ protected:
+ Protection(const char *pwd) {
+ mPwd = pwd;
+ mLogoutTimeout = 0;
+ mLoginIp.fill(0);
+
+ // no password set - unlock
+ if(pwd[0] == '\0')
+ mProtected = false;
+ }
+
+ public:
+ Protection(Protection &other) = delete;
+ void operator=(const Protection &) = delete;
+
+ static Protection* getInstance(const char *pwd) {
+ if(nullptr == mInstance)
+ mInstance = new Protection(pwd);
+ return mInstance;
+ }
+
+ void tickSecond() {
+ // auto logout
+ if(0 != mLogoutTimeout) {
+ if (0 == --mLogoutTimeout) {
+ if(mPwd[0] == '\0')
+ mProtected = true;
+ }
+ }
+ }
+
+ void lock(void) {
+ mProtected = true;
+ mLoginIp.fill(0);
+ }
+
+ void unlock(const char *clientIp) {
+ mProtected = false;
+ ah::ip2Arr(static_cast(mLoginIp.data()), clientIp);
+ }
+
+ void resetLockTimeout(void) {
+ mLogoutTimeout = LOGOUT_TIMEOUT;
+ }
+
+ bool isProtected(void) const {
+ return mProtected;
+ }
+
+ bool isProtected(const char *clientIp) const {
+ if(mProtected)
+ return true;
+
+ if(mPwd[0] == '\0')
+ return false;
+
+ uint8_t ip[4];
+ ah::ip2Arr(ip, clientIp);
+ for(uint8_t i = 0; i < 4; i++) {
+ if(mLoginIp[i] != ip[i])
+ return true;
+ }
+
+ return true;
+ }
+
+ protected:
+ static Protection *mInstance;
+
+ private:
+ const char *mPwd;
+ bool mProtected = true;
+ uint16_t mLogoutTimeout = LOGOUT_TIMEOUT;
+ std::array mLoginIp;
+};
+
+#endif /*__PROTECTION_H__*/
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index ccdc8747..5438566c 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -68,7 +68,7 @@ class RestApi {
DynamicJsonDocument json(128);
JsonObject dummy = json.as();
if(obj[F("path")] == "ctrl")
- setCtrl(obj, dummy);
+ setCtrl(obj, dummy, "api");
else if(obj[F("path")] == "setup")
setSetup(obj, dummy);
}
@@ -168,7 +168,7 @@ class RestApi {
if(!err) {
String path = request->url().substring(5);
if(path == "ctrl")
- root[F("success")] = setCtrl(obj, root);
+ root[F("success")] = setCtrl(obj, root, request->client()->remoteIP().toString().c_str());
else if(path == "setup")
root[F("success")] = setSetup(obj, root);
else {
@@ -263,7 +263,7 @@ class RestApi {
obj[F("modules")] = String(mApp->getVersionModules());
obj[F("build")] = String(AUTO_GIT_HASH);
obj[F("env")] = String(ENV_NAME);
- obj[F("menu_prot")] = mApp->getProtection(request);
+ obj[F("menu_prot")] = mApp->isProtected(request->client()->remoteIP().toString().c_str());
obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask );
obj[F("menu_protEn")] = (bool) (strlen(mConfig->sys.adminPwd) > 0);
obj[F("cst_lnk")] = String(mConfig->plugin.customLink);
@@ -847,7 +847,7 @@ class RestApi {
}
- bool setCtrl(JsonObject jsonIn, JsonObject jsonOut) {
+ bool setCtrl(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
bool accepted = true;
if(NULL == iv) {
@@ -856,6 +856,13 @@ class RestApi {
}
jsonOut[F("id")] = jsonIn[F("id")];
+ if(strncmp("api", clientIP, 3) != 0) {
+ if(mApp->isProtected(clientIP)) {
+ jsonOut[F("error")] = F(INV_IS_PROTECTED);
+ return false;
+ }
+ }
+
if(F("power") == jsonIn[F("cmd")])
accepted = iv->setDevControlRequest((jsonIn[F("val")] == 1) ? TurnOn : TurnOff);
else if(F("restart") == jsonIn[F("cmd")])
diff --git a/src/web/lang.h b/src/web/lang.h
index e55493eb..6cddbc12 100644
--- a/src/web/lang.h
+++ b/src/web/lang.h
@@ -36,6 +36,12 @@
#define UNKNOWN_CMD "unknown cmd: '"
#endif
+#ifdef LANG_DE
+ #define INV_IS_PROTECTED "nicht angemeldet, Kommando nicht möglich!"
+#else /*LANG_EN*/
+ #define INV_IS_PROTECTED "not logged in, command not possible!"
+#endif
+
#ifdef LANG_DE
#define INV_DOES_NOT_ACCEPT_LIMIT_AT_MOMENT "Leistungsbegrenzung / Ansteuerung aktuell nicht möglich"
#else /*LANG_EN*/
diff --git a/src/web/web.h b/src/web/web.h
index 6de9c877..01e48f74 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -47,9 +47,6 @@ template
class Web {
public:
Web(void) : mWeb(80), mEvts("/events") {
- mProtected = true;
- mLogoutTimeout = 0;
-
memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE);
mSerialBufFill = 0;
mSerialAddTime = true;
@@ -110,16 +107,6 @@ class Web {
}
void tickSecond() {
- if (0 != mLogoutTimeout) {
- mLogoutTimeout -= 1;
- if (0 == mLogoutTimeout) {
- if (strlen(mConfig->sys.adminPwd) > 0)
- mProtected = true;
- }
-
- DPRINTLN(DBG_DEBUG, "auto logout in " + String(mLogoutTimeout));
- }
-
if (mSerialClientConnnected) {
if (mSerialBufFill > 0) {
mEvts.send(mSerialBuf, "serial", millis());
@@ -133,27 +120,6 @@ class Web {
return &mWeb;
}
- void setProtection(bool protect) {
- mProtected = protect;
- }
-
- bool isProtected(AsyncWebServerRequest *request) {
- bool prot;
- prot = mProtected;
- if(!prot) {
- if(strlen(mConfig->sys.adminPwd) > 0) {
- uint8_t ip[4];
- ah::ip2Arr(ip, request->client()->remoteIP().toString().c_str());
- for(uint8_t i = 0; i < 4; i++) {
- if(mLoginIp[i] != ip[i])
- prot = true;
- }
- }
- }
-
- return prot;
- }
-
void showUpdate2(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
if (!index) {
Serial.printf("Update Start: %s\n", filename.c_str());
@@ -264,7 +230,7 @@ class Web {
}
void checkProtection(AsyncWebServerRequest *request) {
- if(isProtected(request)) {
+ if(mApp->isProtected(request->client()->remoteIP().toString().c_str())) {
checkRedirect(request);
return;
}
@@ -351,8 +317,7 @@ class Web {
if (request->args() > 0) {
if (String(request->arg("pwd")) == String(mConfig->sys.adminPwd)) {
- mProtected = false;
- ah::ip2Arr(mLoginIp, request->client()->remoteIP().toString().c_str());
+ mApp->unlock(request->client()->remoteIP().toString().c_str());
request->redirect("/");
}
}
@@ -366,8 +331,7 @@ class Web {
DPRINTLN(DBG_VERBOSE, F("onLogout"));
checkProtection(request);
-
- mProtected = true;
+ mApp->lock();
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), system_html, system_html_len);
response->addHeader(F("Content-Encoding"), "gzip");
@@ -390,7 +354,6 @@ class Web {
void onCss(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onCss"));
- mLogoutTimeout = LOGOUT_TIMEOUT;
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/css"), style_css, style_css_len);
response->addHeader(F("Content-Encoding"), "gzip");
if(request->hasParam("v")) {
@@ -424,6 +387,7 @@ class Web {
AsyncWebServerResponse *response = request->beginResponse_P(200, favicon_type, favicon_ico, favicon_ico_len);
response->addHeader(F("Content-Encoding"), "gzip");
request->send(response);
+ mApp->resetLockTimeout();
}
void showNotFound(AsyncWebServerRequest *request) {
@@ -495,7 +459,7 @@ class Web {
// protection
if (request->arg("adminpwd") != "{PWD}") {
request->arg("adminpwd").toCharArray(mConfig->sys.adminPwd, PWD_LEN);
- mProtected = (strlen(mConfig->sys.adminPwd) > 0);
+ mApp->lock();
}
mConfig->sys.protectionMask = 0x0000;
for (uint8_t i = 0; i < 7; i++) {
@@ -945,9 +909,6 @@ class Web {
#endif
AsyncWebServer mWeb;
AsyncEventSource mEvts;
- bool mProtected;
- uint32_t mLogoutTimeout;
- uint8_t mLoginIp[4];
IApp *mApp;
HMSYSTEM *mSys;
From 9065ff5b9852d574118ab7639c8dccef04d78a72 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Thu, 1 Feb 2024 23:45:21 +0100
Subject: [PATCH 24/79] 0.8.70 * fix login * fix github actions Node.js 16
warnings
---
.github/workflows/compile_development.yml | 12 ++++++------
src/web/Protection.h | 11 +++++++----
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml
index 67fa6f0a..4b5a0e1a 100644
--- a/.github/workflows/compile_development.yml
+++ b/.github/workflows/compile_development.yml
@@ -33,13 +33,13 @@ jobs:
- opendtufusion-ethernet
steps:
- uses: actions/checkout@v4
- - uses: benjlevesque/short-sha@v2.1
+ - uses: benjlevesque/short-sha@v2.2
id: short-sha
with:
length: 7
- name: Cache Pip
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
@@ -47,7 +47,7 @@ jobs:
${{ runner.os }}-pip-
- name: Cache PlatformIO
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
@@ -93,13 +93,13 @@ jobs:
- opendtufusion-ethernet-de
steps:
- uses: actions/checkout@v4
- - uses: benjlevesque/short-sha@v2.1
+ - uses: benjlevesque/short-sha@v2.2
id: short-sha
with:
length: 7
- name: Cache Pip
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
@@ -107,7 +107,7 @@ jobs:
${{ runner.os }}-pip-
- name: Cache PlatformIO
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
diff --git a/src/web/Protection.h b/src/web/Protection.h
index 44926752..d0c73a9e 100644
--- a/src/web/Protection.h
+++ b/src/web/Protection.h
@@ -51,6 +51,7 @@ class Protection {
}
void unlock(const char *clientIp) {
+ mLogoutTimeout = LOGOUT_TIMEOUT;
mProtected = false;
ah::ip2Arr(static_cast(mLoginIp.data()), clientIp);
}
@@ -70,14 +71,16 @@ class Protection {
if(mPwd[0] == '\0')
return false;
- uint8_t ip[4];
- ah::ip2Arr(ip, clientIp);
+ std::array ip;
+ ah::ip2Arr(static_cast(ip.data()), clientIp);
for(uint8_t i = 0; i < 4; i++) {
- if(mLoginIp[i] != ip[i])
+ if(mLoginIp[i] != ip[i]) {
+ DPRINTLN(DBG_INFO, "ip nicht gleich!");
return true;
+ }
}
- return true;
+ return false;
}
protected:
From 91e816e9413f5c3750d2ae0dbfea6f425e57d45f Mon Sep 17 00:00:00 2001
From: lumapu
Date: Thu, 1 Feb 2024 23:46:39 +0100
Subject: [PATCH 25/79] 0.8.70
---
src/web/Protection.h | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/web/Protection.h b/src/web/Protection.h
index d0c73a9e..710ba8b3 100644
--- a/src/web/Protection.h
+++ b/src/web/Protection.h
@@ -74,10 +74,8 @@ class Protection {
std::array ip;
ah::ip2Arr(static_cast(ip.data()), clientIp);
for(uint8_t i = 0; i < 4; i++) {
- if(mLoginIp[i] != ip[i]) {
- DPRINTLN(DBG_INFO, "ip nicht gleich!");
+ if(mLoginIp[i] != ip[i])
return true;
- }
}
return false;
From d9696dc70427fb1e7b56c94bbffe9cce45624fd9 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sat, 3 Feb 2024 23:31:17 +0100
Subject: [PATCH 26/79] 0.8.71 * 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
---
src/CHANGES.md | 8 ++++++++
src/app.cpp | 2 +-
src/appInterface.h | 2 +-
src/config/config.h | 2 +-
src/config/settings.h | 16 ----------------
src/defines.h | 2 +-
src/hm/Communication.h | 10 ++--------
src/hm/hmInverter.h | 19 ++++++++-----------
src/hms/hmsRadio.h | 4 +++-
src/publisher/pubMqttIvData.h | 30 ++++++++++++++----------------
src/web/RestApi.h | 6 +++---
src/web/html/setup.html | 14 +-------------
src/web/lang.json | 10 ----------
src/web/web.h | 1 -
14 files changed, 43 insertions(+), 83 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 9835873c..863b6fba 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,13 @@
# Development Changes
+## 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
+
## 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
diff --git a/src/app.cpp b/src/app.cpp
index 8b770989..4f49d93b 100644
--- a/src/app.cpp
+++ b/src/app.cpp
@@ -64,7 +64,7 @@ void app::setup() {
esp_task_wdt_reset();
- mCommunication.setup(&mTimestamp, &mConfig->serial.debug, &mConfig->serial.privacyLog, &mConfig->serial.printWholeTrace, &mConfig->inst.gapMs);
+ mCommunication.setup(&mTimestamp, &mConfig->serial.debug, &mConfig->serial.privacyLog, &mConfig->serial.printWholeTrace);
mCommunication.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1, std::placeholders::_2));
#if defined(ENABLE_MQTT)
mCommunication.addPowerLimitAckListener([this] (Inverter<> *iv) { mMqtt.setPowerLimitAck(iv); });
diff --git a/src/appInterface.h b/src/appInterface.h
index 9930c51e..6703b5bf 100644
--- a/src/appInterface.h
+++ b/src/appInterface.h
@@ -18,7 +18,7 @@
class IApp {
public:
virtual ~IApp() {}
- virtual bool saveSettings(bool stopFs) = 0;
+ virtual bool saveSettings(bool reboot) = 0;
virtual void initInverter(uint8_t id) = 0;
virtual bool readSettings(const char *path) = 0;
virtual bool eraseSettings(bool eraseWifi) = 0;
diff --git a/src/config/config.h b/src/config/config.h
index a633f3af..9e59f146 100644
--- a/src/config/config.h
+++ b/src/config/config.h
@@ -215,7 +215,7 @@
#define INVERTER_OFF_THRES_SEC 15*60
// threshold of minimum power on which the inverter is marked as inactive
-#define INACT_PWR_THRESH 1
+#define INACT_PWR_THRESH 0
// Timezone
#define TIMEZONE 1
diff --git a/src/config/settings.h b/src/config/settings.h
index e074d5b1..ec9712ea 100644
--- a/src/config/settings.h
+++ b/src/config/settings.h
@@ -147,7 +147,6 @@ typedef struct {
uint8_t frequency;
uint8_t powerLevel;
bool disNightCom; // disable night communication
- bool add2Total; // add values to total values - useful if one inverter is on battery to turn off
} cfgIv_t;
typedef struct {
@@ -161,7 +160,6 @@ typedef struct {
bool rstMaxValsMidNight;
bool startWithoutTime;
float yieldEffiency;
- uint16_t gapMs;
bool readGrid;
} cfgInst_t;
@@ -452,14 +450,12 @@ class settings {
mCfg.inst.startWithoutTime = false;
mCfg.inst.rstMaxValsMidNight = false;
mCfg.inst.yieldEffiency = 1.0f;
- mCfg.inst.gapMs = 1;
mCfg.inst.readGrid = true;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
mCfg.inst.iv[i].powerLevel = 0xff; // impossible high value
mCfg.inst.iv[i].frequency = 0x12; // 863MHz (minimum allowed frequency)
mCfg.inst.iv[i].disNightCom = false;
- mCfg.inst.iv[i].add2Total = true;
}
mCfg.led.led[0] = DEF_LED0;
@@ -491,20 +487,15 @@ class settings {
}
if(mCfg.configVersion < 2) {
mCfg.inst.iv[i].disNightCom = false;
- mCfg.inst.iv[i].add2Total = true;
}
if(mCfg.configVersion < 3) {
mCfg.serial.printWholeTrace = false;
}
- if(mCfg.configVersion < 4) {
- mCfg.inst.gapMs = 500;
- }
if(mCfg.configVersion < 5) {
mCfg.inst.sendInterval = SEND_INTERVAL;
mCfg.serial.printWholeTrace = false;
}
if(mCfg.configVersion < 6) {
- mCfg.inst.gapMs = 500;
mCfg.inst.readGrid = true;
}
if(mCfg.configVersion < 7) {
@@ -513,9 +504,6 @@ class settings {
if(mCfg.configVersion < 8) {
mCfg.sun.offsetSecEvening = mCfg.sun.offsetSecMorning;
}
- if(mCfg.configVersion < 9) {
- mCfg.inst.gapMs = 1;
- }
if(mCfg.configVersion < 10) {
mCfg.sys.region = 0; // Europe
mCfg.sys.timezone = 1;
@@ -768,7 +756,6 @@ class settings {
obj[F("strtWthtTime")] = (bool)mCfg.inst.startWithoutTime;
obj[F("rstMaxMidNight")] = (bool)mCfg.inst.rstMaxValsMidNight;
obj[F("yldEff")] = mCfg.inst.yieldEffiency;
- obj[F("gap")] = mCfg.inst.gapMs;
obj[F("rdGrid")] = (bool)mCfg.inst.readGrid;
}
else {
@@ -780,7 +767,6 @@ class settings {
getVal(obj, F("strtWthtTime"), &mCfg.inst.startWithoutTime);
getVal(obj, F("rstMaxMidNight"), &mCfg.inst.rstMaxValsMidNight);
getVal(obj, F("yldEff"), &mCfg.inst.yieldEffiency);
- getVal(obj, F("gap"), &mCfg.inst.gapMs);
getVal(obj, F("rdGrid"), &mCfg.inst.readGrid);
if(mCfg.inst.yieldEffiency < 0.5)
@@ -809,7 +795,6 @@ class settings {
obj[F("freq")] = cfg->frequency;
obj[F("pa")] = cfg->powerLevel;
obj[F("dis")] = cfg->disNightCom;
- obj[F("add")] = cfg->add2Total;
for(uint8_t i = 0; i < 6; i++) {
obj[F("yield")][i] = cfg->yieldCor[i];
obj[F("pwr")][i] = cfg->chMaxPwr[i];
@@ -822,7 +807,6 @@ class settings {
getVal(obj, F("freq"), &cfg->frequency);
getVal(obj, F("pa"), &cfg->powerLevel);
getVal(obj, F("dis"), &cfg->disNightCom);
- getVal(obj, F("add"), &cfg->add2Total);
uint8_t size = 4;
if(obj.containsKey(F("pwr")))
size = obj[F("pwr")].size();
diff --git a/src/defines.h b/src/defines.h
index 6d350add..6fbc5ff1 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 70
+#define VERSION_PATCH 71
//-------------------------------------
typedef struct {
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 4895d2e7..4350eac7 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -20,12 +20,11 @@ typedef std::function *)> alarmListenerType;
class Communication : public CommQueue<> {
public:
- void setup(uint32_t *timestamp, bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint16_t *inverterGap) {
+ void setup(uint32_t *timestamp, bool *serialDebug, bool *privacyMode, bool *printWholeTrace) {
mTimestamp = timestamp;
mPrivacyMode = privacyMode;
mSerialDebug = serialDebug;
mPrintWholeTrace = printWholeTrace;
- mInverterGap = inverterGap;
}
void addImportant(Inverter<> *iv, uint8_t cmd) {
@@ -524,10 +523,6 @@ class Communication : public CommQueue<> {
return;
}
- /*DPRINT_IVID(DBG_INFO, q->iv->id);
- DBGPRINT(F("procPyld: cmd: 0x"));
- DBGHEXLN(q->cmd);*/
-
memset(mPayload, 0, MAX_BUFFER);
int8_t rssi = -127;
uint8_t len = 0;
@@ -623,7 +618,7 @@ class Communication : public CommQueue<> {
q->iv->radioStatistics.rxFail++; // got no complete payload
else
q->iv->radioStatistics.rxFailNoAnser++; // got nothing
- mWaitTime.startTimeMonitor(*mInverterGap);
+ mWaitTime.startTimeMonitor(1); // maybe remove, side effects unknown
bool keep = false;
if(q->isDevControl)
@@ -1025,7 +1020,6 @@ class Communication : public CommQueue<> {
States mState = States::RESET;
uint32_t *mTimestamp;
bool *mPrivacyMode, *mSerialDebug, *mPrintWholeTrace;
- uint16_t *mInverterGap;
TimeMonitor mWaitTime = TimeMonitor(0, true); // start as expired (due to code in RESET state)
std::array mLocalBuf;
bool mFirstTry = false; // see, if we should do a second try
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index a5276880..d9db0b7f 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -184,7 +184,7 @@ class Inverter {
void tickSend(std::function cb) {
if(mDevControlRequest) {
- if(InverterStatus::PRODUCING == status)
+ if(InverterStatus::OFF != status)
cb(devControlCmd, true);
else
DPRINTLN(DBG_WARN, F("Inverter is not avail"));
@@ -447,17 +447,14 @@ class Inverter {
status = InverterStatus::STARTING;
} else {
if((*timestamp - recordMeas.ts) > INVERTER_OFF_THRES_SEC) {
- status = InverterStatus::OFF;
- actPowerLimit = 0xffff; // power limit will be read once inverter becomes available
- alarmMesIndex = 0;
- if(INV_RADIO_TYPE_NRF == ivRadioType) {
- heuristics.clear();
- #ifdef DYNAMIC_OFFSET
- rxOffset = ivGen == IV_HM ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
- #endif
+ if(status != InverterStatus::OFF) {
+ status = InverterStatus::OFF;
+ actPowerLimit = 0xffff; // power limit will be read once inverter becomes available
+ alarmMesIndex = 0;
+ if(INV_RADIO_TYPE_NRF == ivRadioType)
+ heuristics.clear();
}
- }
- else
+ } else
status = InverterStatus::WAS_ON;
}
diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h
index ae9fd369..dd9af3ac 100644
--- a/src/hms/hmsRadio.h
+++ b/src/hms/hmsRadio.h
@@ -176,8 +176,10 @@ class CmtRadio : public Radio {
if(CmtStatus::SUCCESS == status)
mBufCtrl.push(p);
- if(p.packet[9] > ALL_FRAMES) // indicates last frame
+ 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?
+ }
// optionally instead:
// mRadioWaitTime.stopTimeMonitor(); // we got everything we expected and can exit rx mode...
}
diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h
index a096ebc6..64f72e1e 100644
--- a/src/publisher/pubMqttIvData.h
+++ b/src/publisher/pubMqttIvData.h
@@ -149,23 +149,21 @@ class PubMqttIvData {
// calculate total values for RealTimeRunData_Debug
if (CH0 == rec->assign[mPos].ch) {
if(mIv->getStatus() != InverterStatus::OFF) {
- if(mIv->config->add2Total) {
- mTotalFound = true;
- switch (rec->assign[mPos].fieldId) {
- case FLD_PAC:
- mTotal[0] += mIv->getValue(mPos, rec);
- break;
- case FLD_YT:
- mTotal[1] += mIv->getValue(mPos, rec);
- break;
- case FLD_YD: {
- mTotal[2] += mIv->getValue(mPos, rec);
- break;
- }
- case FLD_PDC:
- mTotal[3] += mIv->getValue(mPos, rec);
- break;
+ mTotalFound = true;
+ switch (rec->assign[mPos].fieldId) {
+ case FLD_PAC:
+ mTotal[0] += mIv->getValue(mPos, rec);
+ break;
+ case FLD_YT:
+ mTotal[1] += mIv->getValue(mPos, rec);
+ break;
+ case FLD_YD: {
+ mTotal[2] += mIv->getValue(mPos, rec);
+ break;
}
+ case FLD_PDC:
+ mTotal[3] += mIv->getValue(mPos, rec);
+ break;
}
} else
mAllTotalFound = false;
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index 5438566c..b2041ee7 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -216,6 +216,9 @@ class RestApi {
void onDwnldSetup(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response;
+ // save settings to have latest firmware changes in export
+ mApp->saveSettings(false);
+
File fp = LittleFS.open("/settings.json", "r");
if(!fp) {
DPRINTLN(DBG_ERROR, F("failed to load settings"));
@@ -459,7 +462,6 @@ class RestApi {
obj2[F("channels")] = iv->channels;
obj2[F("freq")] = iv->config->frequency;
obj2[F("disnightcom")] = (bool)iv->config->disNightCom;
- obj2[F("add2total")] = (bool)iv->config->add2Total;
if(0xff == iv->config->powerLevel) {
if((IV_HMT == iv->ivGen) || (IV_HMS == iv->ivGen))
obj2[F("pa")] = 30; // 20dBm
@@ -483,7 +485,6 @@ class RestApi {
obj[F("rdGrid")] = (bool)mConfig->inst.readGrid;
obj[F("rstMaxMid")] = (bool)mConfig->inst.rstMaxValsMidNight;
obj[F("yldEff")] = mConfig->inst.yieldEffiency;
- obj[F("gap")] = mConfig->inst.gapMs;
}
void getInverter(JsonObject obj, uint8_t id) {
@@ -936,7 +937,6 @@ class RestApi {
iv->config->frequency = jsonIn[F("freq")];
iv->config->powerLevel = jsonIn[F("pa")];
iv->config->disNightCom = jsonIn[F("disnightcom")];
- iv->config->add2Total = jsonIn[F("add2total")];
mApp->saveSettings(false); // without reboot
} else {
jsonOut[F("error")] = F(UNKNOWN_CMD);
diff --git a/src/web/html/setup.html b/src/web/html/setup.html
index d4f245ef..dec62830 100644
--- a/src/web/html/setup.html
+++ b/src/web/html/setup.html
@@ -149,10 +149,6 @@
{#INTERVAL} [s]
-
{#INV_RESET_MIDNIGHT}
@@ -630,7 +626,7 @@
}
function ivGlob(obj) {
- for(var i of [["invInterval", "interval"], ["yldEff", "yldEff"], ["invGap", "gap"]])
+ for(var i of [["invInterval", "interval"], ["yldEff", "yldEff"]])
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];
@@ -715,7 +711,6 @@
add.ch_yield_cor = [];
add.freq = 12;
add.pa = 30;
- add.add2total = true;
var e = document.getElementById("inverter");
e.innerHTML = ""; // remove all childs
@@ -746,10 +741,8 @@
var cbEn = ml("input", {name: "enable", type: "checkbox"}, null);
var cbDisNightCom = ml("input", {name: "disnightcom", type: "checkbox"}, null);
- var cbAddTotal = ml("input", {name: "add2total", type: "checkbox"}, null);
cbEn.checked = (obj.enabled);
cbDisNightCom.checked = (obj.disnightcom);
- cbAddTotal.checked = (obj.add2total);
var ser = ml("input", {name: "ser", class: "text", type: "number", max: 138999999999, value: obj.serial}, null);
var html = ml("div", {}, [
@@ -798,10 +791,6 @@
ml("div", {class: "row mb-3"}, [
ml("div", {class: "col-10"}, "{#INV_PAUSE_DURING_NIGHT}"),
ml("div", {class: "col-2"}, cbDisNightCom)
- ]),
- ml("div", {class: "row mb-3"}, [
- ml("div", {class: "col-10"}, "{#INV_INCLUDE_MQTT_SUM}"),
- ml("div", {class: "col-2"}, cbAddTotal)
])
]),
ml("div", {class: "row mt-5"}, [
@@ -867,7 +856,6 @@
o.pa = document.getElementsByName("cmtpa")[0].value;
o.freq = document.getElementsByName("freq")[0].value;
o.disnightcom = document.getElementsByName("disnightcom")[0].checked;
- o.add2total = document.getElementsByName("add2total")[0].checked;
getAjax("/api/setup", cb, "POST", JSON.stringify(o));
}
diff --git a/src/web/lang.json b/src/web/lang.json
index 1617658a..92f046a5 100644
--- a/src/web/lang.json
+++ b/src/web/lang.json
@@ -288,11 +288,6 @@
"en": "Interval",
"de": "Intervall"
},
- {
- "token": "INV_GAP",
- "en": "Communication Gap",
- "de": "Kommunikationslücke"
- },
{
"token": "INV_RESET_MIDNIGHT",
"en": "Reset values and YieldDay at midnight",
@@ -663,11 +658,6 @@
"en": "Pause communication during night (lat. and lon. need to be set)",
"de": "Kommunikation während der Nacht pausieren (Breiten- und Längengrad müssen gesetzt sein"
},
- {
- "token": "INV_INCLUDE_MQTT_SUM",
- "en": "Include inverter to sum of total (should be checked by default, MqTT only)",
- "de": "Wechselrichter in Liste der aufzuaddierenden Wechselrichter aufnehmen (nur MqTT)"
- },
{
"token": "BTN_SAVE",
"en": "save",
diff --git a/src/web/web.h b/src/web/web.h
index 01e48f74..77a059cb 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -488,7 +488,6 @@ class Web {
mConfig->inst.readGrid = (request->arg("rdGrid") == "on");
mConfig->inst.rstMaxValsMidNight = (request->arg("invRstMaxMid") == "on");
mConfig->inst.yieldEffiency = (request->arg("yldEff")).toFloat();
- mConfig->inst.gapMs = (request->arg("invGap")).toInt();
// pinout
From 80d07ae6fee47d27b86526873b77087a2159e906 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 4 Feb 2024 00:19:26 +0100
Subject: [PATCH 27/79] 0.8.71 * fix autologin bug if no password is set *
translated `/serial`
---
src/CHANGES.md | 2 ++
src/web/Protection.h | 2 +-
src/web/RestApi.h | 4 +++-
src/web/html/serial.html | 10 +++++-----
src/web/lang.json | 30 ++++++++++++++++++++++++++++++
src/web/web.h | 1 -
6 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 863b6fba..b661b8d2 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -7,6 +7,8 @@
* 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`
## 0.8.70 - 2024-02-01
* prevent sending commands to inverter which isn't active #1387
diff --git a/src/web/Protection.h b/src/web/Protection.h
index 710ba8b3..0c7b8379 100644
--- a/src/web/Protection.h
+++ b/src/web/Protection.h
@@ -39,7 +39,7 @@ class Protection {
// auto logout
if(0 != mLogoutTimeout) {
if (0 == --mLogoutTimeout) {
- if(mPwd[0] == '\0')
+ if(mPwd[0] != '\0')
mProtected = true;
}
}
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index b2041ee7..e6760390 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -259,6 +259,8 @@ class RestApi {
}
void getGeneric(AsyncWebServerRequest *request, JsonObject obj) {
+ mApp->resetLockTimeout();
+
obj[F("wifi_rssi")] = (WiFi.status() != WL_CONNECTED) ? 0 : WiFi.RSSI();
obj[F("ts_uptime")] = mApp->getUptime();
obj[F("ts_now")] = mApp->getTimestamp();
@@ -268,7 +270,7 @@ class RestApi {
obj[F("env")] = String(ENV_NAME);
obj[F("menu_prot")] = mApp->isProtected(request->client()->remoteIP().toString().c_str());
obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask );
- obj[F("menu_protEn")] = (bool) (strlen(mConfig->sys.adminPwd) > 0);
+ obj[F("menu_protEn")] = (bool) (mConfig->sys.adminPwd[0] != '\0');
obj[F("cst_lnk")] = String(mConfig->plugin.customLink);
obj[F("cst_lnk_txt")] = String(mConfig->plugin.customLinkText);
obj[F("region")] = mConfig->sys.region;
diff --git a/src/web/html/serial.html b/src/web/html/serial.html
index 25940eb0..83e614c8 100644
--- a/src/web/html/serial.html
+++ b/src/web/html/serial.html
@@ -12,12 +12,12 @@
diff --git a/src/web/lang.json b/src/web/lang.json
index 92f046a5..78c7d653 100644
--- a/src/web/lang.json
+++ b/src/web/lang.json
@@ -865,6 +865,36 @@
}
]
},
+ {
+ "name": "serial.html",
+ "list": [
+ {
+ "token": "BTN_CLEAR",
+ "en": "clear",
+ "de": "l&ouuml;schen"
+ },
+ {
+ "token": "BTN_AUTOSCROLL",
+ "en": "autoscroll",
+ "de": "automatisch scrollen"
+ },
+ {
+ "token": "BTN_COPY",
+ "en": "copy",
+ "de": "kopieren"
+ },
+ {
+ "token": "CONSOLE_ACTIVE",
+ "en": "console active",
+ "de": "Konsole aktiv"
+ },
+ {
+ "token": "UPTIME",
+ "en": "uptime",
+ "de": "Laufzeit"
+ }
+ ]
+ },
{
"name": "index.html",
"list": [
diff --git a/src/web/web.h b/src/web/web.h
index 77a059cb..0ffd0594 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -387,7 +387,6 @@ class Web {
AsyncWebServerResponse *response = request->beginResponse_P(200, favicon_type, favicon_ico, favicon_ico_len);
response->addHeader(F("Content-Encoding"), "gzip");
request->send(response);
- mApp->resetLockTimeout();
}
void showNotFound(AsyncWebServerRequest *request) {
From 2e94f2844137dcac147adebafe2c5acf5d6721a0 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 4 Feb 2024 00:24:44 +0100
Subject: [PATCH 28/79] 0.8.71 * removed "yield day" history
---
src/CHANGES.md | 1 +
src/plugins/history.h | 13 +++++++------
src/web/RestApi.h | 20 --------------------
src/web/html/history.html | 22 ----------------------
4 files changed, 8 insertions(+), 48 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index b661b8d2..4a2e91f6 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -9,6 +9,7 @@
* 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
diff --git a/src/plugins/history.h b/src/plugins/history.h
index da57800f..7a938284 100644
--- a/src/plugins/history.h
+++ b/src/plugins/history.h
@@ -52,8 +52,8 @@ class HistoryData {
mCurPwr.reset();
mCurPwr.refreshCycle = mConfig->inst.sendInterval;
- mYieldDay.reset();
- mYieldDay.refreshCycle = 60;
+ //mYieldDay.reset();
+ //mYieldDay.refreshCycle = 60;
}
void tickerSecond() {
@@ -80,7 +80,7 @@ class HistoryData {
mMaximumDay = roundf(maxPwr);
}
- if((++mYieldDay.loopCnt % mYieldDay.refreshCycle) == 0) {
+ /*if((++mYieldDay.loopCnt % mYieldDay.refreshCycle) == 0) {
if (*mTs > mApp->getSunset()) {
if ((!mDayStored) && (yldDay > 0)) {
addValue(&mYieldDay, roundf(yldDay));
@@ -88,11 +88,12 @@ class HistoryData {
}
} 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 = (HistoryStorageType::POWER == type) ? &mCurPwr : &mYieldDay;
+ storage_t *s = &mCurPwr;
uint16_t idx = (s->dispIdx + i) % HISTORY_DATA_ARR_LENGTH;
return s->data[idx];
}
@@ -119,7 +120,7 @@ class HistoryData {
uint32_t *mTs;
storage_t mCurPwr;
- storage_t mYieldDay;
+ //storage_t mYieldDay;
bool mDayStored = false;
uint16_t mMaximumDay = 0;
};
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index e6760390..240a18f2 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -107,7 +107,6 @@ class RestApi {
#endif /* !defined(ETHERNET) */
else if(path == "live") getLive(request,root);
else if (path == "powerHistory") getPowerHistory(request, root);
- else if (path == "yieldDayHistory") getYieldDayHistory(request, root);
else {
if(path.substring(0, 12) == "inverter/id/")
getInverter(root, request->url().substring(17).toInt());
@@ -208,7 +207,6 @@ class RestApi {
ep[F("live")] = url + F("live");
#if defined(ENABLE_HISTORY)
ep[F("powerHistory")] = url + F("powerHistory");
- ep[F("yieldDayHistory")] = url + F("yieldDayHistory");
#endif
}
@@ -832,24 +830,6 @@ class RestApi {
#endif /*ENABLE_HISTORY*/
}
- void getYieldDayHistory(AsyncWebServerRequest *request, JsonObject obj) {
- getGeneric(request, obj.createNestedObject(F("generic")));
- #if defined(ENABLE_HISTORY)
- obj[F("refresh")] = 86400; // 1 day
- 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;
- #else
- obj[F("refresh")] = 86400; // 1 day
- #endif /*ENABLE_HISTORY*/
- }
-
-
bool setCtrl(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
bool accepted = true;
diff --git a/src/web/html/history.html b/src/web/html/history.html
index 975a02ed..b553a19f 100644
--- a/src/web/html/history.html
+++ b/src/web/html/history.html
@@ -20,14 +20,6 @@
{#MAXIMUM}: W. {#UPDATED} {#SECONDS}
- {#TOTAL_YIELD_PER_DAY}
-
-
-
- {#MAXIMUM}: Wh
- {#UPDATED} {#SECONDS}
-
-
{#HTML_FOOTER}
@@ -94,20 +86,6 @@
if (pwrExeOnce) {
pwrExeOnce = false;
window.setInterval("getAjax('/api/powerHistory', parsePowerHistory)", mRefresh * 1000);
-
- setTimeout(() => {
- getAjax("/api/yieldDayHistory", parseYieldDayHistory);
- } , 20);
- }
- }
- function parseYieldDayHistory(obj) {
- if (null != obj) {
- parseNav(obj.generic);
- parseHistory(obj, "yd", ydExeOnce)
- }
- if (ydExeOnce) {
- ydExeOnce = false;
- window.setInterval("getAjax('/api/yieldDayHistory', parseYieldDayHistory)", mRefresh * 500);
}
}
From 883aefbe643ce04c6fe45882479f560ecd33db16 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 4 Feb 2024 00:31:39 +0100
Subject: [PATCH 29/79] 0.8.71 * fix html
---
src/web/html/history.html | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/web/html/history.html b/src/web/html/history.html
index b553a19f..7e317b59 100644
--- a/src/web/html/history.html
+++ b/src/web/html/history.html
@@ -79,6 +79,7 @@
function parsePowerHistory(obj){
if (null != obj) {
+ parseNav(obj.generic);
parseHistory(obj,"pwr", pwrExeOnce)
document.getElementById("pwrLast").innerHTML = mLastValue
document.getElementById("pwrMaxDay").innerHTML = obj.maxDay
From 14c5a7ad3227c3701ecaef8b2dea8bea13dfbd9d Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 4 Feb 2024 13:21:02 +0100
Subject: [PATCH 30/79] 0.8.72 * 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)
---
src/CHANGES.md | 5 +++++
src/defines.h | 2 +-
src/hm/hmInverter.h | 9 ++++-----
src/hms/hmsRadio.h | 12 ++++++++++--
src/web/RestApi.h | 12 +++++++-----
src/web/lang.json | 2 +-
6 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 4a2e91f6..82a6ed45 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,10 @@
# Development Changes
+## 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
diff --git a/src/defines.h b/src/defines.h
index 6fbc5ff1..f0ec528d 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 71
+#define VERSION_PATCH 72
//-------------------------------------
typedef struct {
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index d9db0b7f..b62e985a 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -152,7 +152,6 @@ class Inverter {
static uint32_t *timestamp; // system timestamp
static cfgInst_t *generalConfig; // general inverter configuration from setup
- //static IApp *app; // pointer to app interface
public:
@@ -290,18 +289,18 @@ class Inverter {
}
bool setDevControlRequest(uint8_t cmd) {
- if(InverterStatus::PRODUCING == status) {
+ if(InverterStatus::OFF != status) {
mDevControlRequest = true;
devControlCmd = cmd;
//app->triggerTickSend(); // done in RestApi.h, because of "chicken-and-egg problem ;-)"
}
- return (InverterStatus::PRODUCING == status);
+ return (InverterStatus::OFF != status);
}
bool setDevCommand(uint8_t cmd) {
- if(InverterStatus::PRODUCING == status)
+ if(InverterStatus::OFF != status)
devControlCmd = cmd;
- return (InverterStatus::PRODUCING == status);
+ return (InverterStatus::OFF != status);
}
void addValue(uint8_t pos, uint8_t buf[], record_t<> *rec) {
diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h
index dd9af3ac..0fa1b6ab 100644
--- a/src/hms/hmsRadio.h
+++ b/src/hms/hmsRadio.h
@@ -9,6 +9,8 @@
#include "cmt2300a.h"
#include "../hm/radio.h"
+#define CMT_SWITCH_CHANNEL_CYCLE 5
+
template
class CmtRadio : public Radio {
typedef Cmt2300a CmtType;
@@ -151,6 +153,10 @@ class CmtRadio : public Radio {
}
inline void sendSwitchChCmd(Inverter<> *iv, uint8_t ch) {
+ if(CMT_SWITCH_CHANNEL_CYCLE > ++mSwitchCycle)
+ return;
+ mSwitchCycle = 0;
+
/** ch:
* 0x00: 860.00 MHz
* 0x01: 860.25 MHz
@@ -172,9 +178,10 @@ class CmtRadio : public Radio {
inline void getRx(void) {
packet_t p;
p.millis = millis() - mMillis;
- CmtStatus status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi);
- if(CmtStatus::SUCCESS == status)
+ if(CmtStatus::SUCCESS == mCmt.getRx(p.packet, &p.len, 28, &p.rssi)) {
+ mSwitchCycle = 0;
mBufCtrl.push(p);
+ }
if(p.packet[9] > ALL_FRAMES) { // indicates last frame
setExpectedFrames(p.packet[9] - ALL_FRAMES);
@@ -188,6 +195,7 @@ class CmtRadio : public Radio {
bool mCmtAvail = false;
bool mRqstGetRx = false;
uint32_t mMillis;
+ uint8_t mSwitchCycle = 0;
};
#endif /*__HMS_RADIO_H__*/
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index 240a18f2..564d6c62 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -68,7 +68,7 @@ class RestApi {
DynamicJsonDocument json(128);
JsonObject dummy = json.as();
if(obj[F("path")] == "ctrl")
- setCtrl(obj, dummy, "api");
+ setCtrl(obj, dummy, "*");
else if(obj[F("path")] == "setup")
setSetup(obj, dummy);
}
@@ -839,10 +839,12 @@ class RestApi {
}
jsonOut[F("id")] = jsonIn[F("id")];
- if(strncmp("api", clientIP, 3) != 0) {
- if(mApp->isProtected(clientIP)) {
- jsonOut[F("error")] = F(INV_IS_PROTECTED);
- return false;
+ if(mConfig->sys.adminPwd[0] != '\0') {
+ if(strncmp("*", clientIP, 1) != 0) { // no call from API (MqTT)
+ if(mApp->isProtected(clientIP)) {
+ jsonOut[F("error")] = F(INV_IS_PROTECTED);
+ return false;
+ }
}
}
diff --git a/src/web/lang.json b/src/web/lang.json
index 78c7d653..689fbb06 100644
--- a/src/web/lang.json
+++ b/src/web/lang.json
@@ -871,7 +871,7 @@
{
"token": "BTN_CLEAR",
"en": "clear",
- "de": "l&ouuml;schen"
+ "de": "löschen"
},
{
"token": "BTN_AUTOSCROLL",
From 6b5435a2467bb1ba745d40213f1b7e4d0db359e6 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 4 Feb 2024 21:26:48 +0100
Subject: [PATCH 31/79] 0.8.73 * fix nullpointer during communication #1401 *
added `max_power` to MqTT total values #1375
---
src/CHANGES.md | 4 ++++
src/defines.h | 2 +-
src/hm/Communication.h | 33 ++++++++++++++++-----------------
src/publisher/pubMqttIvData.h | 13 ++++++++++---
4 files changed, 31 insertions(+), 21 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 82a6ed45..813f1708 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,9 @@
# Development Changes
+## 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
diff --git a/src/defines.h b/src/defines.h
index f0ec528d..b71a1d25 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 72
+#define VERSION_PATCH 73
//-------------------------------------
typedef struct {
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 4350eac7..d1521f81 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -295,12 +295,14 @@ class Communication : public CommQueue<> {
return;
}
- compilePayload(q);
+ if(compilePayload(q)) {
+ if((NULL != mCbPayload) && (GridOnProFilePara != q->cmd) && (GetLossRate != q->cmd))
+ (mCbPayload)(q->cmd, q->iv);
- if((NULL != mCbPayload) && (GridOnProFilePara != q->cmd) && (GetLossRate != q->cmd))
- (mCbPayload)(q->cmd, q->iv);
+ closeRequest(q, true);
+ } else
+ closeRequest(q, false);
- closeRequest(q, true);
break;
}
}
@@ -498,7 +500,7 @@ class Communication : public CommQueue<> {
return accepted;
}
- inline void compilePayload(const queue_s *q) {
+ inline bool compilePayload(const queue_s *q) {
uint16_t crc = 0xffff, crcRcv = 0x0000;
for(uint8_t i = 0; i < mMaxFrameId; i++) {
if(i == (mMaxFrameId - 1)) {
@@ -514,13 +516,12 @@ class Communication : public CommQueue<> {
DBGPRINT(F("CRC Error "));
if(q->attempts == 0) {
DBGPRINTLN(F("-> Fail"));
- closeRequest(q, false);
} else
DBGPRINTLN(F("-> complete retransmit"));
mCompleteRetry = true;
mState = States::RESET;
- return;
+ return false;
}
memset(mPayload, 0, MAX_BUFFER);
@@ -530,7 +531,7 @@ class Communication : public CommQueue<> {
for(uint8_t i = 0; i < mMaxFrameId; i++) {
if(mLocalBuf[i].len + len > MAX_BUFFER) {
DPRINTLN(DBG_ERROR, F("payload buffer to small!"));
- return;
+ return true;
}
memcpy(&mPayload[len], mLocalBuf[i].buf, mLocalBuf[i].len);
len += mLocalBuf[i].len;
@@ -552,19 +553,18 @@ class Communication : public CommQueue<> {
if(GridOnProFilePara == q->cmd) {
q->iv->addGridProfile(mPayload, len);
- return;
+ return true;
}
record_t<> *rec = q->iv->getRecordStruct(q->cmd);
if(NULL == rec) {
if(GetLossRate == q->cmd) {
q->iv->parseGetLossRate(mPayload, len);
- return;
- } else {
+ return true;
+ } else
DPRINTLN(DBG_ERROR, F("record is NULL!"));
- closeRequest(q, false);
- }
- return;
+
+ return false;
}
if((rec->pyldLen != len) && (0 != rec->pyldLen)) {
if(*mSerialDebug) {
@@ -572,10 +572,8 @@ class Communication : public CommQueue<> {
DBGPRINT(String(rec->pyldLen));
DBGPRINTLN(F(" bytes"));
}
- /*q->iv->radioStatistics.rxFail++;*/
- closeRequest(q, false);
- return;
+ return false;
}
rec->ts = q->ts;
@@ -597,6 +595,7 @@ class Communication : public CommQueue<> {
yield();
}
}
+ return true;
}
void sendRetransmit(const queue_s *q, uint8_t i) {
diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h
index 64f72e1e..cfed38b9 100644
--- a/src/publisher/pubMqttIvData.h
+++ b/src/publisher/pubMqttIvData.h
@@ -78,7 +78,7 @@ class PubMqttIvData {
if((RealTimeRunData_Debug != mCmd) || !mRTRDataHasBeenSent) { // send RealTimeRunData only once
mSendTotals = (RealTimeRunData_Debug == mCmd);
- memset(mTotal, 0, sizeof(float) * 4);
+ memset(mTotal, 0, sizeof(float) * 5);
mState = FIND_NXT_IV;
} else
mSendList->pop();
@@ -164,6 +164,9 @@ class PubMqttIvData {
case FLD_PDC:
mTotal[3] += mIv->getValue(mPos, rec);
break;
+ case FLD_MP:
+ mTotal[4] += mIv->getValue(mPos, rec);
+ break;
}
} else
mAllTotalFound = false;
@@ -204,7 +207,7 @@ class PubMqttIvData {
void stateSendTotals() {
uint8_t fieldId;
mRTRDataHasBeenSent = true;
- if(mPos < 4) {
+ if(mPos < 5) {
bool retained = true;
switch (mPos) {
default:
@@ -230,6 +233,10 @@ class PubMqttIvData {
fieldId = FLD_PDC;
retained = false;
break;
+ case 4:
+ fieldId = FLD_MP;
+ retained = false;
+ break;
}
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]);
snprintf(mVal, 40, "%g", ah::round3(mTotal[mPos]));
@@ -251,7 +258,7 @@ class PubMqttIvData {
uint8_t mCmd;
uint8_t mLastIvId;
bool mSendTotals, mTotalFound, mAllTotalFound, mSendTotalYd;
- float mTotal[4], mYldTotalStore;
+ float mTotal[5], mYldTotalStore;
Inverter<> *mIv, *mIvSend;
uint8_t mPos;
From 3740a09d2a04e46da340d98cb3479a54a55b0f61 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Mon, 5 Feb 2024 23:58:52 +0100
Subject: [PATCH 32/79] 0.8.74 * reduced cppcheck linter warnings significantly
---
src/CHANGES.md | 3 +
src/app.cpp | 15 ++-
src/app.h | 100 ++++++++---------
src/config/settings.h | 7 +-
src/defines.h | 2 +-
src/hm/CommQueue.h | 2 +-
src/hm/Communication.h | 39 ++++---
src/hm/Heuristic.h | 7 +-
src/hm/hmDefines.h | 2 +-
src/hm/hmInverter.h | 141 ++++++++++-------------
src/hm/hmRadio.h | 27 +++--
src/hm/hmSystem.h | 14 +--
src/hm/nrfHal.h | 2 +-
src/hm/radio.h | 8 +-
src/hms/cmt2300a.h | 15 +--
src/hms/cmtHal.h | 2 +-
src/hms/esp32_3wSpi.h | 7 +-
src/hms/hmsRadio.h | 25 ++---
src/plugins/Display/Display.h | 11 +-
src/plugins/Display/Display_Mono.h | 12 +-
src/plugins/history.h | 33 ++----
src/publisher/pubMqtt.h | 172 +++++++++++++++--------------
src/publisher/pubMqttIvData.h | 2 +-
src/publisher/pubSerial.h | 12 +-
src/utils/improv.h | 16 +--
src/utils/scheduler.h | 16 ++-
src/utils/spiPatcher.h | 2 +-
src/utils/timemonitor.h | 6 +-
src/web/RestApi.h | 24 ++--
src/web/web.h | 48 ++++----
src/wifi/ahoywifi.h | 16 +--
31 files changed, 375 insertions(+), 413 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 813f1708..f0491335 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,8 @@
# Development Changes
+## 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
diff --git a/src/app.cpp b/src/app.cpp
index 4f49d93b..d9b0f933 100644
--- a/src/app.cpp
+++ b/src/app.cpp
@@ -13,7 +13,10 @@
//-----------------------------------------------------------------------------
-app::app() : ah::Scheduler {} {}
+app::app() : ah::Scheduler {} {
+ memset(mVersion, 0, sizeof(char) * 12);
+ memset(mVersionModules, 0, sizeof(char) * 12);
+}
//-----------------------------------------------------------------------------
@@ -228,7 +231,6 @@ void app::updateNtp(void) {
onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi");
if (mConfig->sys.schedReboot) {
- uint32_t localTime = gTimezone.toLocal(mTimestamp);
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;
@@ -301,9 +303,8 @@ void app::tickIVCommunication(void) {
bool zeroValues = false;
uint32_t nxtTrig = 0;
- Inverter<> *iv;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
- iv = mSys.getInverterByPos(i);
+ Inverter<> *iv = mSys.getInverterByPos(i);
if(NULL == iv)
continue;
@@ -390,10 +391,9 @@ void app::tickMidnight(void) {
// clear max values
if(mConfig->inst.rstMaxValsMidNight) {
- uint8_t pos;
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
for(uint8_t i = 0; i <= iv->channels; i++) {
- pos = iv->getPosByChFld(i, FLD_MP, rec);
+ uint8_t pos = iv->getPosByChFld(i, FLD_MP, rec);
iv->setValue(pos, rec, 0.0f);
}
}
@@ -592,9 +592,8 @@ void app::updateLed(void) {
uint8_t led_on = (mConfig->led.high_active) ? (mConfig->led.luminance) : (255-mConfig->led.luminance);
if (mConfig->led.led[0] != DEF_PIN_OFF) {
- Inverter<> *iv;
for (uint8_t id = 0; id < mSys.getNumInverters(); id++) {
- iv = mSys.getInverterByPos(id);
+ Inverter<> *iv = mSys.getInverterByPos(id);
if (NULL != iv) {
if (iv->isProducing()) {
// turn on when at least one inverter is producing
diff --git a/src/app.h b/src/app.h
index b44d3781..60be4d1d 100644
--- a/src/app.h
+++ b/src/app.h
@@ -90,7 +90,7 @@ class app : public IApp, public ah::Scheduler {
void handleIntr(void) {
mNrfRadio.handleIntr();
}
- void* getRadioObj(bool nrf) {
+ void* getRadioObj(bool nrf) override {
if(nrf)
return (void*)&mNrfRadio;
else {
@@ -108,19 +108,19 @@ class app : public IApp, public ah::Scheduler {
}
#endif
- uint32_t getUptime() {
+ uint32_t getUptime() override {
return Scheduler::getUptime();
}
- uint32_t getTimestamp() {
+ uint32_t getTimestamp() override {
return Scheduler::mTimestamp;
}
- uint64_t getTimestampMs() {
+ uint64_t getTimestampMs() override {
return ((uint64_t)Scheduler::mTimestamp * 1000) + ((uint64_t)millis() - (uint64_t)Scheduler::mTsMillis) % 1000;
}
- bool saveSettings(bool reboot) {
+ bool saveSettings(bool reboot) override {
mShowRebootRequest = true; // only message on index, no reboot
mSavePending = true;
mSaveReboot = reboot;
@@ -131,7 +131,7 @@ class app : public IApp, public ah::Scheduler {
return true;
}
- void initInverter(uint8_t id) {
+ void initInverter(uint8_t id) override {
mSys.addInverter(id, [this](Inverter<> *iv) {
if((IV_MI == iv->ivGen) || (IV_HM == iv->ivGen))
iv->radio = &mNrfRadio;
@@ -142,7 +142,7 @@ class app : public IApp, public ah::Scheduler {
});
}
- bool readSettings(const char *path) {
+ bool readSettings(const char *path) override {
return mSettings.readSettings(path);
}
@@ -150,80 +150,80 @@ class app : public IApp, public ah::Scheduler {
return mSettings.eraseSettings(eraseWifi);
}
- bool getSavePending() {
+ bool getSavePending() override {
return mSavePending;
}
- bool getLastSaveSucceed() {
+ bool getLastSaveSucceed() override {
return mSettings.getLastSaveSucceed();
}
- bool getShouldReboot() {
+ bool getShouldReboot() override {
return mSaveReboot;
}
#if !defined(ETHERNET)
- void scanAvailNetworks() {
+ void scanAvailNetworks() override {
mWifi.scanAvailNetworks();
}
- bool getAvailNetworks(JsonObject obj) {
+ bool getAvailNetworks(JsonObject obj) override {
return mWifi.getAvailNetworks(obj);
}
- void setupStation(void) {
+ void setupStation(void) override {
mWifi.setupStation();
}
- void setStopApAllowedMode(bool allowed) {
+ void setStopApAllowedMode(bool allowed) override {
mWifi.setStopApAllowedMode(allowed);
}
- String getStationIp(void) {
+ String getStationIp(void) override {
return mWifi.getStationIp();
}
- bool getWasInCh12to14(void) const {
+ bool getWasInCh12to14(void) const override {
return mWifi.getWasInCh12to14();
}
#endif /* !defined(ETHERNET) */
- void setRebootFlag() {
+ void setRebootFlag() override {
once(std::bind(&app::tickReboot, this), 3, "rboot");
}
- const char *getVersion() {
+ const char *getVersion() override {
return mVersion;
}
- const char *getVersionModules() {
+ const char *getVersionModules() override {
return mVersionModules;
}
- uint32_t getSunrise() {
+ uint32_t getSunrise() override {
return mSunrise;
}
- uint32_t getSunset() {
+ uint32_t getSunset() override {
return mSunset;
}
- bool getSettingsValid() {
+ bool getSettingsValid() override {
return mSettings.getValid();
}
- bool getRebootRequestState() {
+ bool getRebootRequestState() override {
return mShowRebootRequest;
}
- void setMqttDiscoveryFlag() {
+ void setMqttDiscoveryFlag() override {
#if defined(ENABLE_MQTT)
once(std::bind(&PubMqttType::sendDiscoveryConfig, &mMqtt), 1, "disCf");
#endif
}
- bool getMqttIsConnected() {
+ bool getMqttIsConnected() override {
#if defined(ENABLE_MQTT)
return mMqtt.isConnected();
#else
@@ -231,7 +231,7 @@ class app : public IApp, public ah::Scheduler {
#endif
}
- uint32_t getMqttTxCnt() {
+ uint32_t getMqttTxCnt() override {
#if defined(ENABLE_MQTT)
return mMqtt.getTxCnt();
#else
@@ -239,7 +239,7 @@ class app : public IApp, public ah::Scheduler {
#endif
}
- uint32_t getMqttRxCnt() {
+ uint32_t getMqttRxCnt() override {
#if defined(ENABLE_MQTT)
return mMqtt.getRxCnt();
#else
@@ -267,11 +267,11 @@ class app : public IApp, public ah::Scheduler {
return mProtection->isProtected(clientIp);
}
- bool getNrfEnabled(void) {
+ bool getNrfEnabled(void) override {
return mConfig->nrf.enabled;
}
- bool getCmtEnabled(void) {
+ bool getCmtEnabled(void) override {
return mConfig->cmt.enabled;
}
@@ -283,19 +283,19 @@ class app : public IApp, public ah::Scheduler {
return mConfig->cmt.pinIrq;
}
- uint32_t getTimezoneOffset() {
+ uint32_t getTimezoneOffset() override {
return mApi.getTimezoneOffset();
}
- void getSchedulerInfo(uint8_t *max) {
+ void getSchedulerInfo(uint8_t *max) override {
getStat(max);
}
- void getSchedulerNames(void) {
+ void getSchedulerNames(void) override {
printSchedulers();
}
- void setTimestamp(uint32_t newTime) {
+ void setTimestamp(uint32_t newTime) override {
DPRINT(DBG_DEBUG, F("setTimestamp: "));
DBGPRINTLN(String(newTime));
if(0 == newTime)
@@ -310,7 +310,7 @@ class app : public IApp, public ah::Scheduler {
Scheduler::setTimestamp(newTime);
}
- uint16_t getHistoryValue(uint8_t type, uint16_t i) {
+ uint16_t getHistoryValue(uint8_t type, uint16_t i) override {
#if defined(ENABLE_HISTORY)
return mHistory.valueAt((HistoryStorageType)type, i);
#else
@@ -318,7 +318,7 @@ class app : public IApp, public ah::Scheduler {
#endif
}
- uint16_t getHistoryMaxDay() {
+ uint16_t getHistoryMaxDay() override {
#if defined(ENABLE_HISTORY)
return mHistory.getMaximumDay();
#else
@@ -372,11 +372,11 @@ class app : public IApp, public ah::Scheduler {
void tickNtpUpdate(void);
#if defined(ETHERNET)
void onNtpUpdate(bool gotTime);
- bool mNtpReceived;
+ bool mNtpReceived = false;
#endif /* defined(ETHERNET) */
void updateNtp(void);
- void triggerTickSend() {
+ void triggerTickSend() override {
once(std::bind(&app::tickSend, this), 0, "tSend");
}
@@ -395,7 +395,7 @@ class app : public IApp, public ah::Scheduler {
HmRadio<> mNrfRadio;
Communication mCommunication;
- bool mShowRebootRequest;
+ bool mShowRebootRequest = false;
#if defined(ETHERNET)
ahoyeth mEth;
@@ -404,7 +404,7 @@ class app : public IApp, public ah::Scheduler {
#endif /* defined(ETHERNET) */
WebType mWeb;
RestApiType mApi;
- Protection *mProtection;
+ Protection *mProtection = nullptr;
#ifdef ENABLE_SYSLOG
DbgSyslog mDbgSyslog;
#endif
@@ -421,26 +421,26 @@ class app : public IApp, public ah::Scheduler {
char mVersion[12];
char mVersionModules[12];
settings mSettings;
- settings_t *mConfig;
- bool mSavePending;
- bool mSaveReboot;
+ settings_t *mConfig = nullptr;
+ bool mSavePending = false;
+ bool mSaveReboot = false;
- uint8_t mSendLastIvId;
- bool mSendFirst;
- bool mAllIvNotAvail;
+ uint8_t mSendLastIvId = 0;
+ bool mSendFirst = false;
+ bool mAllIvNotAvail = false;
- bool mNetworkConnected;
+ bool mNetworkConnected = false;
// mqtt
#if defined(ENABLE_MQTT)
PubMqttType mMqtt;
#endif /*ENABLE_MQTT*/
- bool mMqttReconnect;
- bool mMqttEnabled;
+ bool mMqttReconnect = false;
+ bool mMqttEnabled = false;
// sun
- int32_t mCalculatedTimezoneOffset;
- uint32_t mSunrise, mSunset;
+ int32_t mCalculatedTimezoneOffset = 0;
+ uint32_t mSunrise = 0, mSunset = 0;
// plugins
#if defined(PLUGIN_DISPLAY)
diff --git a/src/config/settings.h b/src/config/settings.h
index ec9712ea..0cb9ed4e 100644
--- a/src/config/settings.h
+++ b/src/config/settings.h
@@ -13,6 +13,7 @@
#include
#include
+#include
#include
#include "../defines.h"
@@ -206,7 +207,7 @@ typedef struct {
class settings {
public:
settings() {
- mLastSaveSucceed = false;
+ std::fill(reinterpret_cast(&mCfg), reinterpret_cast(&mCfg) + sizeof(mCfg), 0);
}
void setup() {
@@ -377,7 +378,7 @@ class settings {
memcpy(&tmp, &mCfg.sys, sizeof(cfgSys_t));
}
// erase all settings and reset to default
- memset(&mCfg, 0, sizeof(settings_t));
+ std::fill(reinterpret_cast(&mCfg), reinterpret_cast(&mCfg) + sizeof(mCfg), 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;
mCfg.sys.darkMode = false;
@@ -847,7 +848,7 @@ class settings {
#endif
settings_t mCfg;
- bool mLastSaveSucceed;
+ bool mLastSaveSucceed = 0;
};
#endif /*__SETTINGS_H__*/
diff --git a/src/defines.h b/src/defines.h
index b71a1d25..bc9d2452 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 73
+#define VERSION_PATCH 74
//-------------------------------------
typedef struct {
diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h
index acbe9a35..328309ac 100644
--- a/src/hm/CommQueue.h
+++ b/src/hm/CommQueue.h
@@ -91,7 +91,7 @@ class CommQueue {
inc(&mRdPtr);
}
- void setTs(uint32_t *ts) {
+ void setTs(const uint32_t *ts) {
mQueue[mRdPtr].ts = *ts;
}
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index d1521f81..326fb57e 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -6,6 +6,7 @@
#ifndef __COMMUNICATION_H__
#define __COMMUNICATION_H__
+#include
#include "CommQueue.h"
#include
#include "../utils/crc.h"
@@ -194,8 +195,8 @@ class Communication : public CommQueue<> {
q->iv->radio->mBufCtrl.pop();
return; // don't wait for empty buffer
} else if(IV_MI == q->iv->ivGen) {
- if(parseMiFrame(p, q))
- q->iv->curFrmCnt++;
+ parseMiFrame(p, q);
+ q->iv->curFrmCnt++;
}
} //else -> serial does not match
@@ -385,7 +386,7 @@ class Communication : public CommQueue<> {
}
}
- inline bool validateIvSerial(uint8_t buf[], Inverter<> *iv) {
+ inline bool validateIvSerial(const uint8_t buf[], Inverter<> *iv) {
uint8_t tmp[4];
CP_U32_BigEndian(tmp, iv->radioId.u64 >> 8);
for(uint8_t i = 0; i < 4; i++) {
@@ -435,7 +436,7 @@ class Communication : public CommQueue<> {
return true;
}
- inline bool parseMiFrame(packet_t *p, const queue_s *q) {
+ inline void parseMiFrame(packet_t *p, const queue_s *q) {
if((!mIsRetransmit && p->packet[9] == 0x00) && (p->millis < LIMIT_FAST_IV_MI)) //first frame is fast?
mHeu.setIvRetriesGood(q->iv,p->millis < LIMIT_VERYFAST_IV_MI);
if ((p->packet[0] == MI_REQ_CH1 + ALL_FRAMES)
@@ -458,11 +459,9 @@ class Communication : public CommQueue<> {
rec->ts = q->ts;
miStsConsolidate(q, ((p->packet[0] == 0x88) ? 1 : 2), rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]);
}
-
- return true;
}
- inline bool parseDevCtrl(packet_t *p, const queue_s *q) {
+ inline bool parseDevCtrl(const packet_t *p, const queue_s *q) {
switch(p->packet[12]) {
case ActivePowerContr:
if(p->packet[13] != 0x00)
@@ -524,7 +523,7 @@ class Communication : public CommQueue<> {
return false;
}
- memset(mPayload, 0, MAX_BUFFER);
+ mPayload.fill(0);
int8_t rssi = -127;
uint8_t len = 0;
@@ -547,19 +546,19 @@ class Communication : public CommQueue<> {
DBGPRINT(String(len));
if(*mPrintWholeTrace) {
DBGPRINT(F("): "));
- ah::dumpBuf(mPayload, len);
+ ah::dumpBuf(mPayload.data(), len);
} else
DBGPRINTLN(F(")"));
if(GridOnProFilePara == q->cmd) {
- q->iv->addGridProfile(mPayload, len);
+ q->iv->addGridProfile(mPayload.data(), len);
return true;
}
record_t<> *rec = q->iv->getRecordStruct(q->cmd);
if(NULL == rec) {
if(GetLossRate == q->cmd) {
- q->iv->parseGetLossRate(mPayload, len);
+ q->iv->parseGetLossRate(mPayload.data(), len);
return true;
} else
DPRINTLN(DBG_ERROR, F("record is NULL!"));
@@ -578,7 +577,7 @@ class Communication : public CommQueue<> {
rec->ts = q->ts;
for (uint8_t i = 0; i < rec->length; i++) {
- q->iv->addValue(i, mPayload, rec);
+ q->iv->addValue(i, mPayload.data(), rec);
}
rec->mqttSentStatus = MqttSentStatus::NEW_DATA;
@@ -588,7 +587,7 @@ class Communication : public CommQueue<> {
if(AlarmData == q->cmd) {
uint8_t i = 0;
while(1) {
- if(0 == q->iv->parseAlarmLog(i++, mPayload, len))
+ if(0 == q->iv->parseAlarmLog(i++, mPayload.data(), len))
break;
if (NULL != mCbAlarm)
(mCbAlarm)(q->iv);
@@ -670,7 +669,7 @@ class Communication : public CommQueue<> {
};
*/
- if ( p->packet[9] == 0x00 ) {//first frame
+ if ( p->packet[9] == 0x00 ) { //first frame
//FLD_FW_VERSION
for (uint8_t i = 0; i < 5; i++) {
q->iv->setValue(i, rec, (float) ((p->packet[(12+2*i)] << 8) + p->packet[(13+2*i)])/1);
@@ -680,7 +679,7 @@ class Communication : public CommQueue<> {
DBGPRINT(F("HW_VER is "));
DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25]));
}
- record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure
+ rec = q->iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure
rec->ts = q->ts;
q->iv->setValue(1, rec, (uint32_t) ((p->packet[24] << 8) + p->packet[25])/1);
q->iv->miMultiParts +=4;
@@ -894,7 +893,7 @@ class Communication : public CommQueue<> {
statusMi = 8310; //trick?
}
- uint16_t prntsts = statusMi == 3 ? 1 : statusMi;
+ 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...
@@ -1017,17 +1016,17 @@ class Communication : public CommQueue<> {
private:
States mState = States::RESET;
- uint32_t *mTimestamp;
- bool *mPrivacyMode, *mSerialDebug, *mPrintWholeTrace;
+ uint32_t *mTimestamp = nullptr;
+ bool *mPrivacyMode = nullptr, *mSerialDebug = nullptr, *mPrintWholeTrace = nullptr;
TimeMonitor mWaitTime = TimeMonitor(0, true); // start as expired (due to code in RESET state)
std::array mLocalBuf;
bool mFirstTry = false; // see, if we should do a second try
bool mCompleteRetry = false; // remember if we did request a complete retransmission
bool mIsRetransmit = false; // we already had waited one complete cycle
- uint8_t mMaxFrameId;
+ uint8_t mMaxFrameId = 0;
uint8_t mFramesExpected = 12; // 0x8c was highest last frame for alarm data
uint16_t mTimeout = 0; // calculating that once should be ok
- uint8_t mPayload[MAX_BUFFER];
+ std::array mPayload;
payloadListenerType mCbPayload = NULL;
powerLimitAckListenerType mCbPwrAck = NULL;
alarmListenerType mCbAlarm = NULL;
diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h
index fa4512b5..2a36bc78 100644
--- a/src/hm/Heuristic.h
+++ b/src/hm/Heuristic.h
@@ -157,7 +157,7 @@ class Heuristic {
DBGPRINTLN(String(iv->config->powerLevel));
}
- uint8_t getIvRetries(Inverter<> *iv) {
+ uint8_t getIvRetries(const Inverter<> *iv) const {
if(iv->heuristics.rxSpeeds[0])
return RETRIES_VERYFAST_IV;
if(iv->heuristics.rxSpeeds[1])
@@ -200,7 +200,7 @@ class Heuristic {
}
private:
- bool isNewTxCh(HeuristicInv *ih) {
+ bool isNewTxCh(const HeuristicInv *ih) const {
return ih->txRfChId != ih->lastBestTxChId;
}
@@ -222,9 +222,6 @@ class Heuristic {
}
return 3; // standard
}
-
- private:
- uint8_t mChList[5] = {03, 23, 40, 61, 75};
};
diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h
index 0b42aeae..8fc4f71f 100644
--- a/src/hm/hmDefines.h
+++ b/src/hm/hmDefines.h
@@ -76,7 +76,7 @@ enum {CMD_CALC = 0xffff};
enum {CH0 = 0, CH1, CH2, CH3, CH4, CH5, CH6};
enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH, INV_TYPE_6CH};
-enum {INV_RADIO_TYPE_NRF = 0, INV_RADIO_TYPE_CMT};
+enum {INV_RADIO_TYPE_UNKNOWN = 0, INV_RADIO_TYPE_NRF, INV_RADIO_TYPE_CMT};
#define DURATION_ONEFRAME 50 // timeout parameter for each expected frame (ms)
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index b62e985a..275fce2c 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -81,12 +81,12 @@ enum class InverterStatus : uint8_t {
template
struct record_t {
- byteAssign_t* assign; // assignment of bytes in payload
- uint8_t length; // length of the assignment list
- T *record; // data pointer
- uint32_t ts; // timestamp of last received payload
- uint8_t pyldLen; // expected payload length for plausibility check
- MqttSentStatus mqttSentStatus; // indicates the current MqTT sent status
+ byteAssign_t* assign = nullptr; // assignment of bytes in payload
+ uint8_t length = 0; // length of the assignment list
+ T *record = nullptr; // data pointer
+ uint32_t ts = 0; // timestamp of last received payload
+ uint8_t pyldLen = 0; // expected payload length for plausibility check
+ MqttSentStatus mqttSentStatus = MqttSentStatus:: NEW_DATA; // indicates the current MqTT sent status
};
struct alarm_t {
@@ -113,42 +113,42 @@ const calcFunc_t calcFunctions[] = {
template
class Inverter {
public:
- uint8_t ivGen; // generation of inverter (HM / MI)
- uint8_t ivRadioType; // refers to used radio (nRF24 / CMT)
- cfgIv_t *config; // stored settings
- uint8_t id; // unique id
- uint8_t type; // integer which refers to inverter type
- uint16_t alarmMesIndex; // Last recorded Alarm Message Index
- uint16_t powerLimit[2]; // limit power output (multiplied by 10)
- float actPowerLimit; // actual power limit
- bool powerLimitAck; // acknowledged power limit (default: false)
- uint8_t devControlCmd; // carries the requested cmd
- serial_u radioId; // id converted to modbus
- uint8_t channels; // number of PV channels (1-4)
- record_t recordMeas; // structure for measured values
- record_t recordInfo; // structure for info values
- record_t recordHwInfo; // structure for simple (hardware) info values
- record_t recordConfig; // structure for system config values
- record_t recordAlarm; // structure for alarm values
- InverterStatus status; // indicates the current inverter status
- std::array lastAlarm; // holds last 10 alarms
- uint8_t rxOffset; // holds the default channel offset between tx and rx channel (nRF only)
- int8_t rssi; // RSSI
- uint16_t alarmCnt; // counts the total number of occurred alarms
- uint16_t alarmLastId; // lastId which was received
- uint8_t mCmd; // holds the command to send
- bool mGotFragment; // shows if inverter has sent at least one fragment
- uint8_t miMultiParts; // helper info for MI multiframe msgs
- uint8_t outstandingFrames; // helper info to count difference between expected and received frames
- uint8_t curFrmCnt; // count received frames in current loop
- bool mGotLastMsg; // shows if inverter has already finished transmission cycle
- bool mIsSingleframeReq; // indicates this is a missing single frame request
- Radio *radio; // pointer to associated radio class
- statistics_t radioStatistics; // information about transmitted, failed, ... packets
- HeuristicInv heuristics; // heuristic information / logic
- uint8_t curCmtFreq; // current used CMT frequency, used to check if freq. was changed during runtime
- bool commEnabled; // 'pause night communication' sets this field to false
- uint32_t tsMaxAcPower; // holds the timestamp when the MaxAC power was seen
+ uint8_t ivGen = IV_UNKNOWN; // generation of inverter (HM / MI)
+ uint8_t ivRadioType = INV_RADIO_TYPE_UNKNOWN; // refers to used radio (nRF24 / CMT)
+ cfgIv_t *config = nullptr; // stored settings
+ uint8_t id = 0; // unique id
+ uint8_t type = INV_TYPE_1CH; // integer which refers to inverter type
+ uint16_t alarmMesIndex = 0; // Last recorded Alarm Message Index
+ uint16_t powerLimit[2] = {0xffff, AbsolutNonPersistent}; // limit power output (multiplied by 10)
+ float actPowerLimit = -1; // actual power limit
+ bool powerLimitAck = false; // acknowledged power limit
+ uint8_t devControlCmd = InitDataState; // carries the requested cmd
+ serial_u radioId; // id converted to modbus
+ uint8_t channels = 1; // number of PV channels (1-4)
+ record_t recordMeas; // structure for measured values
+ record_t recordInfo; // structure for info values
+ record_t recordHwInfo; // structure for simple (hardware) info values
+ record_t recordConfig; // structure for system config values
+ record_t recordAlarm; // structure for alarm values
+ InverterStatus status = InverterStatus::OFF; // indicates the current inverter status
+ std::array lastAlarm; // holds last 10 alarms
+ uint8_t rxOffset = 0; // holds the default channel offset between tx and rx channel (nRF only)
+ int8_t rssi = 0; // RSSI
+ uint16_t alarmCnt = 0; // counts the total number of occurred alarms
+ uint16_t alarmLastId = 0; // lastId which was received
+ uint8_t mCmd = InitDataState; // holds the command to send
+ bool mGotFragment = false; // shows if inverter has sent at least one fragment
+ uint8_t miMultiParts = 0; // helper info for MI multiframe msgs
+ uint8_t outstandingFrames = 0; // helper info to count difference between expected and received frames
+ uint8_t curFrmCnt = 0; // count received frames in current loop
+ bool mGotLastMsg = false; // shows if inverter has already finished transmission cycle
+ bool mIsSingleframeReq = false; // indicates this is a missing single frame request
+ Radio *radio = nullptr; // pointer to associated radio class
+ statistics_t radioStatistics; // information about transmitted, failed, ... packets
+ 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
+ bool commEnabled = true; // 'pause night communication' sets this field to false
static uint32_t *timestamp; // system timestamp
static cfgInst_t *generalConfig; // general inverter configuration from setup
@@ -156,29 +156,10 @@ class Inverter {
public:
Inverter() {
- ivGen = IV_HM;
- powerLimit[0] = 0xffff; // 6553.5 W Limit -> unlimited
- powerLimit[1] = AbsolutNonPersistent; // default power limit setting
- powerLimitAck = false;
- actPowerLimit = 0xffff; // init feedback from inverter to -1
- mDevControlRequest = false;
- devControlCmd = InitDataState;
- alarmMesIndex = 0;
- status = InverterStatus::OFF;
- alarmCnt = 0;
- alarmLastId = 0;
- rssi = -127;
- miMultiParts = 0;
- mGotLastMsg = false;
- mCmd = InitDataState;
- mIsSingleframeReq = false;
- radio = NULL;
- commEnabled = true;
- tsMaxAcPower = 0;
-
memset(&radioStatistics, 0, sizeof(statistics_t));
memset(mOffYD, 0, sizeof(float) * 6);
memset(mLastYD, 0, sizeof(float) * 6);
+ mGridProfile.fill(0);
}
void tickSend(std::function cb) {
@@ -255,8 +236,8 @@ class Inverter {
uint8_t getPosByChFld(uint8_t channel, uint8_t fieldId, record_t<> *rec) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getPosByChFld"));
- uint8_t pos = 0;
if(NULL != rec) {
+ uint8_t pos = 0;
for(; pos < rec->length; pos++) {
if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId))
break;
@@ -303,7 +284,7 @@ class Inverter {
return (InverterStatus::OFF != status);
}
- void addValue(uint8_t pos, uint8_t buf[], record_t<> *rec) {
+ void addValue(uint8_t pos, const uint8_t buf[], record_t<> *rec) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:addValue"));
if(NULL != rec) {
uint8_t ptr = rec->assign[pos].start;
@@ -387,8 +368,8 @@ class Inverter {
}
REC_TYP getChannelFieldValue(uint8_t channel, uint8_t fieldId, record_t<> *rec) {
- uint8_t pos = 0;
if(NULL != rec) {
+ uint8_t pos = 0;
for(; pos < rec->length; pos++) {
if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId))
break;
@@ -529,11 +510,11 @@ class Inverter {
if (INV_TYPE_1CH == type) {
if((IV_HM == ivGen) || (IV_MI == ivGen)) {
rec->length = (uint8_t)(HM1CH_LIST_LEN);
- rec->assign = (byteAssign_t *)hm1chAssignment;
+ rec->assign = reinterpret_cast(const_cast(hm1chAssignment));
rec->pyldLen = HM1CH_PAYLOAD_LEN;
} else if(IV_HMS == ivGen) {
rec->length = (uint8_t)(HMS1CH_LIST_LEN);
- rec->assign = (byteAssign_t *)hms1chAssignment;
+ rec->assign = reinterpret_cast(const_cast(hms1chAssignment));
rec->pyldLen = HMS1CH_PAYLOAD_LEN;
}
channels = 1;
@@ -541,11 +522,11 @@ class Inverter {
else if (INV_TYPE_2CH == type) {
if((IV_HM == ivGen) || (IV_MI == ivGen)) {
rec->length = (uint8_t)(HM2CH_LIST_LEN);
- rec->assign = (byteAssign_t *)hm2chAssignment;
+ rec->assign = reinterpret_cast(const_cast(hm2chAssignment));
rec->pyldLen = HM2CH_PAYLOAD_LEN;
} else if(IV_HMS == ivGen) {
rec->length = (uint8_t)(HMS2CH_LIST_LEN);
- rec->assign = (byteAssign_t *)hms2chAssignment;
+ rec->assign = reinterpret_cast(const_cast(hms2chAssignment));
rec->pyldLen = HMS2CH_PAYLOAD_LEN;
}
channels = 2;
@@ -553,18 +534,18 @@ class Inverter {
else if (INV_TYPE_4CH == type) {
if((IV_HM == ivGen) || (IV_MI == ivGen)) {
rec->length = (uint8_t)(HM4CH_LIST_LEN);
- rec->assign = (byteAssign_t *)hm4chAssignment;
+ rec->assign = reinterpret_cast(const_cast(hm4chAssignment));
rec->pyldLen = HM4CH_PAYLOAD_LEN;
} else if(IV_HMS == ivGen) {
rec->length = (uint8_t)(HMS4CH_LIST_LEN);
- rec->assign = (byteAssign_t *)hms4chAssignment;
+ rec->assign = reinterpret_cast(const_cast(hms4chAssignment));
rec->pyldLen = HMS4CH_PAYLOAD_LEN;
}
channels = 4;
}
else if (INV_TYPE_6CH == type) {
rec->length = (uint8_t)(HMT6CH_LIST_LEN);
- rec->assign = (byteAssign_t *)hmt6chAssignment;
+ rec->assign = reinterpret_cast(const_cast(hmt6chAssignment));
rec->pyldLen = HMT6CH_PAYLOAD_LEN;
channels = 6;
}
@@ -577,22 +558,22 @@ class Inverter {
break;
case InverterDevInform_All:
rec->length = (uint8_t)(HMINFO_LIST_LEN);
- rec->assign = (byteAssign_t *)InfoAssignment;
+ rec->assign = reinterpret_cast(const_cast(InfoAssignment));
rec->pyldLen = HMINFO_PAYLOAD_LEN;
break;
case InverterDevInform_Simple:
rec->length = (uint8_t)(HMSIMPLE_INFO_LIST_LEN);
- rec->assign = (byteAssign_t *)SimpleInfoAssignment;
+ rec->assign = reinterpret_cast(const_cast(SimpleInfoAssignment));
rec->pyldLen = HMSIMPLE_INFO_PAYLOAD_LEN;
break;
case SystemConfigPara:
rec->length = (uint8_t)(HMSYSTEM_LIST_LEN);
- rec->assign = (byteAssign_t *)SystemConfigParaAssignment;
+ rec->assign = reinterpret_cast(const_cast(SystemConfigParaAssignment));
rec->pyldLen = HMSYSTEM_PAYLOAD_LEN;
break;
case AlarmData:
rec->length = (uint8_t)(HMALARMDATA_LIST_LEN);
- rec->assign = (byteAssign_t *)AlarmDataAssignment;
+ rec->assign = reinterpret_cast(const_cast(AlarmDataAssignment));
rec->pyldLen = HMALARMDATA_PAYLOAD_LEN;
break;
default:
@@ -616,7 +597,7 @@ class Inverter {
memset(mLastYD, 0, sizeof(float) * 6);
}
- bool parseGetLossRate(uint8_t pyld[], uint8_t len) {
+ bool parseGetLossRate(const uint8_t pyld[], uint8_t len) {
if (len == HMGETLOSSRATE_PAYLOAD_LEN) {
uint16_t rxCnt = (pyld[0] << 8) + pyld[1];
uint16_t txCnt = (pyld[2] << 8) + pyld[3];
@@ -815,7 +796,7 @@ class Inverter {
void addGridProfile(uint8_t buf[], uint8_t length) {
mGridLen = (length > MAX_GRID_LENGTH) ? MAX_GRID_LENGTH : length;
- std::copy(buf, &buf[mGridLen], mGridProfile);
+ std::copy(buf, &buf[mGridLen], mGridProfile.data());
}
String getGridProfile(void) {
@@ -847,9 +828,9 @@ class Inverter {
private:
float mOffYD[6], mLastYD[6];
- bool mDevControlRequest; // true if change needed
+ bool mDevControlRequest = false; // true if change needed
uint8_t mGridLen = 0;
- uint8_t mGridProfile[MAX_GRID_LENGTH];
+ std::array mGridProfile;
uint8_t mAlarmNxtWrPos = 0; // indicates the position in array (rolling buffer)
public:
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index ca96a333..aef4f49d 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -52,7 +52,7 @@ class HmRadio : public Radio {
mPrintWholeTrace = printWholeTrace;
generateDtuSn();
- DTU_RADIO_ID = ((uint64_t)(((mDtuSn >> 24) & 0xFF) | ((mDtuSn >> 8) & 0xFF00) | ((mDtuSn << 8) & 0xFF0000) | ((mDtuSn << 24) & 0xFF000000)) << 8) | 0x01;
+ 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)
@@ -85,7 +85,7 @@ class HmRadio : public Radio {
mNrf24->enableDynamicPayloads();
mNrf24->setCRCLength(RF24_CRC_16);
mNrf24->setAddressWidth(5);
- mNrf24->openReadingPipe(1, reinterpret_cast(&DTU_RADIO_ID));
+ mNrf24->openReadingPipe(1, reinterpret_cast(&mDtuRadioId));
mNrf24->maskIRQ(false, false, false); // enable all receiving interrupts
mNrf24->setPALevel(1); // low is default
@@ -99,7 +99,7 @@ class HmRadio : public Radio {
}
// returns true if communication is active
- bool loop(void) {
+ bool loop(void) override {
if (!mIrqRcvd && !mNRFisInRX)
return false; // first quick check => nothing to do at all here
@@ -198,11 +198,11 @@ class HmRadio : public Radio {
return false;
}
- bool isChipConnected(void) const {
+ bool isChipConnected(void) const override {
return mNrf24->isChipConnected();
}
- void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) {
+ void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) override {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("sendControlPacket cmd: "));
DBGHEXLN(cmd);
@@ -423,15 +423,15 @@ class HmRadio : public Radio {
mNRFisInRX = false;
}
- uint64_t getIvId(Inverter<> *iv) const {
+ uint64_t getIvId(Inverter<> *iv) const override {
return iv->radioId.u64;
}
- uint8_t getIvGen(Inverter<> *iv) const {
+ uint8_t getIvGen(Inverter<> *iv) const override {
return iv->ivGen;
}
- inline bool checkIvSerial(uint8_t buf[], Inverter<> *iv) {
+ inline bool checkIvSerial(const uint8_t buf[], Inverter<> *iv) {
for(uint8_t i = 1; i < 5; i++) {
if(buf[i] != iv->radioId.b[i])
return false;
@@ -439,14 +439,14 @@ class HmRadio : public Radio {
return true;
}
- uint64_t DTU_RADIO_ID;
- uint8_t mRfChLst[RF_CHANNELS] = {03, 23, 40, 61, 75}; // channel List:2403, 2423, 2440, 2461, 2475MHz
+ uint64_t mDtuRadioId = 0ULL;
+ 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;
- uint8_t tempRxChIdx = mRxChIdx;
+ uint8_t tempRxChIdx = 0;
bool mGotLastMsg = false;
- uint32_t mMillis;
- bool tx_ok, tx_fail, rx_ready = false;
+ uint32_t mMillis = 0;
+ bool tx_ok = false, tx_fail = false, rx_ready = false;
unsigned long mTimeslotStart = 0;
unsigned long mLastIrqTime = 0;
bool mNRFloopChannels = false;
@@ -454,7 +454,6 @@ class HmRadio : public Radio {
bool isRxInit = true;
bool mRxPendular = false;
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
- //uint8_t mTxSetupTime = 0;
uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15);
std::unique_ptr mSpi;
diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h
index aa2910e5..0266a948 100644
--- a/src/hm/hmSystem.h
+++ b/src/hm/hmSystem.h
@@ -98,35 +98,33 @@ class HmSystem {
#ifdef DYNAMIC_OFFSET
iv->rxOffset = (iv->ivGen == IV_HM) ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
#else
- iv->rxOffset = ((iv->ivGen == IV_HM) && (iv->type == INV_TYPE_4CH)) ? 3 : 2;
+ //iv->rxOffset = ((iv->ivGen == IV_HM) && (iv->type == INV_TYPE_4CH)) ? 3 : 2;
iv->rxOffset = (iv->ivGen == IV_HM) ? 3 : 2;
#endif
cb(iv);
}
- INVERTERTYPE *findInverter(uint8_t buf[]) {
- DPRINTLN(DBG_VERBOSE, F("hmSystem.h:findInverter"));
- INVERTERTYPE *p;
+ INVERTERTYPE *findInverter(const uint8_t buf[]) {
for(uint8_t i = 0; i < MAX_INVERTER; i++) {
- p = &mInverter[i];
+ INVERTERTYPE *p = &mInverter[i];
if((p->config->serial.b[3] == buf[0])
&& (p->config->serial.b[2] == buf[1])
&& (p->config->serial.b[1] == buf[2])
&& (p->config->serial.b[0] == buf[3]))
return p;
}
- return NULL;
+ return nullptr;
}
INVERTERTYPE *getInverterByPos(uint8_t pos, bool check = true) {
DPRINTLN(DBG_VERBOSE, F("hmSystem.h:getInverterByPos"));
if(pos >= MAX_INVERTER)
- return NULL;
+ return nullptr;
else if((mInverter[pos].config->serial.u64 != 0ULL) || (false == check))
return &mInverter[pos];
else
- return NULL;
+ return nullptr;
}
uint8_t getNumInverters(void) {
diff --git a/src/hm/nrfHal.h b/src/hm/nrfHal.h
index 0532a524..b9265626 100644
--- a/src/hm/nrfHal.h
+++ b/src/hm/nrfHal.h
@@ -142,7 +142,7 @@ 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];
+ uint8_t data[NRF_MAX_TRANSFER_SZ + 1];
data[0] = cmd;
if(len > NRF_MAX_TRANSFER_SZ)
len = NRF_MAX_TRANSFER_SZ;
diff --git a/src/hm/radio.h b/src/hm/radio.h
index 7bbb42bc..db694b54 100644
--- a/src/hm/radio.h
+++ b/src/hm/radio.h
@@ -11,6 +11,7 @@
#define ALL_FRAMES 0x80
#define SINGLE_FRAME 0x81
+#include
#include "../utils/dbg.h"
#include "../utils/crc.h"
#include "../utils/timemonitor.h"
@@ -119,9 +120,8 @@ class Radio {
#endif
mDtuSn = 0;
- uint8_t t;
for(int i = 0; i < (7 << 2); i += 4) {
- t = (chipID >> i) & 0x0f;
+ uint8_t t = (chipID >> i) & 0x0f;
if(t > 0x09)
t -= 6;
mDtuSn |= (t << i);
@@ -132,8 +132,8 @@ class Radio {
uint32_t mDtuSn;
- volatile bool mIrqRcvd;
- bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace;
+ std::atomic mIrqRcvd;
+ bool *mSerialDebug = nullptr, *mPrivacyMode = nullptr, *mPrintWholeTrace = nullptr;
uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE];
};
diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h
index e6456f5b..23911b15 100644
--- a/src/hms/cmt2300a.h
+++ b/src/hms/cmt2300a.h
@@ -529,7 +529,8 @@ class Cmt2300a {
return false;
}
- inline bool switchDtuFreq(const uint32_t freqKhz) {
+ // maybe used in future
+ /*inline bool switchDtuFreq(const uint32_t freqKhz) {
uint8_t toCh = freq2Chan(freqKhz);
if(0xff == toCh)
return false;
@@ -537,7 +538,7 @@ class Cmt2300a {
switchChannel(toCh);
return true;
- }
+ }*/
inline uint8_t getChipStatus(void) {
return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA;
@@ -549,11 +550,11 @@ class Cmt2300a {
#else
esp32_3wSpi mSpi;
#endif
- uint8_t mCnt;
- bool mTxPending;
- bool mInRxMode;
- uint8_t mCusIntFlag;
- uint8_t mRqstCh, mCurCh;
+ uint8_t mCnt = 0;
+ bool mTxPending = false;
+ bool mInRxMode = false;
+ uint8_t mCusIntFlag = 0;
+ uint8_t mRqstCh = 0, mCurCh = 0;
RegionCfg mRegionCfg = RegionCfg::EUROPE;
};
diff --git a/src/hms/cmtHal.h b/src/hms/cmtHal.h
index 768b8da5..a4bec587 100644
--- a/src/hms/cmtHal.h
+++ b/src/hms/cmtHal.h
@@ -89,7 +89,7 @@ class cmtHal : public SpiPatcherHandle {
}
uint8_t readReg(uint8_t addr) {
- uint8_t data;
+ uint8_t data = 0;
request_spi();
diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h
index c562671a..a0366b23 100644
--- a/src/hms/esp32_3wSpi.h
+++ b/src/hms/esp32_3wSpi.h
@@ -10,6 +10,7 @@
#if defined(ESP32)
#include "driver/spi_master.h"
#include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal
+#include "../config/config.h"
#define SPI_CLK 1 * 1000 * 1000 // 1MHz
@@ -104,7 +105,7 @@ class esp32_3wSpi {
if(!mInitialized)
return 0;
- uint8_t rx_data;
+ uint8_t rx_data = 0;
spi_transaction_t t = {
.cmd = 0,
.addr = (uint64_t)(~addr),
@@ -121,7 +122,7 @@ class esp32_3wSpi {
return rx_data;
}
- void writeFifo(uint8_t buf[], uint8_t len) {
+ void writeFifo(const uint8_t buf[], uint8_t len) {
if(!mInitialized)
return;
uint8_t tx_data;
@@ -144,7 +145,7 @@ class esp32_3wSpi {
void readFifo(uint8_t buf[], uint8_t *len, uint8_t maxlen) {
if(!mInitialized)
return;
- uint8_t rx_data;
+ uint8_t rx_data = 0;
spi_transaction_t t = {
.length = 8,
diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h
index 0fa1b6ab..66e312d7 100644
--- a/src/hms/hmsRadio.h
+++ b/src/hms/hmsRadio.h
@@ -15,10 +15,6 @@ template
class CmtRadio : public Radio {
typedef Cmt2300a CmtType;
public:
- CmtRadio() {
- mDtuSn = DTU_SN;
- }
-
void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, uint8_t region = 0, bool genDtuSn = true) {
mCmt.setup(pinSclk, pinSdio, pinCsb, pinFcsb);
reset(genDtuSn, static_cast(region));
@@ -27,7 +23,7 @@ class CmtRadio : public Radio {
mPrintWholeTrace = printWholeTrace;
}
- bool loop() {
+ bool loop() override {
mCmt.loop();
if((!mIrqRcvd) && (!mRqstGetRx))
return false;
@@ -39,11 +35,11 @@ class CmtRadio : public Radio {
return false;
}
- bool isChipConnected(void) const {
+ bool isChipConnected(void) const override {
return mCmtAvail;
}
- void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) {
+ void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) override {
DPRINT(DBG_INFO, F("sendControlPacket cmd: "));
DBGHEXLN(cmd);
initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME);
@@ -61,14 +57,14 @@ class CmtRadio : public Radio {
sendPacket(iv, cnt, isRetransmit);
}
- bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) {
+ bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) override {
uint8_t fromCh = mCmt.freq2Chan(fromkHz);
uint8_t toCh = mCmt.freq2Chan(tokHz);
return switchFrequencyCh(iv, fromCh, toCh);
}
- bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) {
+ bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) override {
if((0xff == fromCh) || (0xff == toCh))
return false;
@@ -92,7 +88,7 @@ class CmtRadio : public Radio {
private:
- void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) {
+ void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) override {
// inverters have maybe different settings regarding frequency
if(mCmt.getCurrentChannel() != iv->config->frequency)
mCmt.switchChannel(iv->config->frequency);
@@ -129,11 +125,11 @@ class CmtRadio : public Radio {
iv->mDtuTxCnt++;
}
- uint64_t getIvId(Inverter<> *iv) const {
+ uint64_t getIvId(Inverter<> *iv) const override {
return iv->radioId.u64;
}
- uint8_t getIvGen(Inverter<> *iv) const {
+ uint8_t getIvGen(Inverter<> *iv) const override {
return iv->ivGen;
}
@@ -180,6 +176,7 @@ class CmtRadio : public Radio {
p.millis = millis() - mMillis;
if(CmtStatus::SUCCESS == mCmt.getRx(p.packet, &p.len, 28, &p.rssi)) {
mSwitchCycle = 0;
+ p.ch = 0; // not used for CMT inverters
mBufCtrl.push(p);
}
@@ -187,14 +184,12 @@ class CmtRadio : public Radio {
setExpectedFrames(p.packet[9] - ALL_FRAMES);
mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first get back to rx mode?
}
- // optionally instead:
- // mRadioWaitTime.stopTimeMonitor(); // we got everything we expected and can exit rx mode...
}
CmtType mCmt;
bool mCmtAvail = false;
bool mRqstGetRx = false;
- uint32_t mMillis;
+ uint32_t mMillis = 0;
uint8_t mSwitchCycle = 0;
};
diff --git a/src/plugins/Display/Display.h b/src/plugins/Display/Display.h
index 862e452b..c59a56b6 100644
--- a/src/plugins/Display/Display.h
+++ b/src/plugins/Display/Display.h
@@ -192,15 +192,14 @@ class Display {
if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF)) {
#if defined(ESP8266)
if (mCfg->pirPin == A0)
- return((analogRead(A0) >= 512));
+ return (analogRead(A0) >= 512);
else
- return(digitalRead(mCfg->pirPin));
+ return digitalRead(mCfg->pirPin);
#elif defined(ESP32)
- return(digitalRead(mCfg->pirPin));
+ return digitalRead(mCfg->pirPin);
#endif
- }
- else
- return(false);
+ } else
+ return false;
}
// approximate RSSI in dB by invQuality levels from heuristic function (very unscientific but better than nothing :-) )
diff --git a/src/plugins/Display/Display_Mono.h b/src/plugins/Display/Display_Mono.h
index 2c1fc935..e855eeb9 100644
--- a/src/plugins/Display/Display_Mono.h
+++ b/src/plugins/Display/Display_Mono.h
@@ -24,8 +24,6 @@
class DisplayMono {
public:
- DisplayMono() {};
-
virtual void init(DisplayData *displayData) = 0;
virtual void config(display_t *cfg) = 0;
virtual void disp(void) = 0;
@@ -289,11 +287,11 @@ class DisplayMono {
DispSwitchState mDispSwitchState = DispSwitchState::TEXT;
uint16_t mDispWidth;
- uint8_t mExtra;
+ uint8_t mExtra = 0;
int8_t mPixelshift=0;
char mFmtText[DISP_FMT_TEXT_LEN];
- uint8_t mLineXOffsets[5] = {};
- uint8_t mLineYOffsets[5] = {};
+ uint8_t mLineXOffsets[5] = {0, 0, 0, 0, 0};
+ uint8_t mLineYOffsets[5] = {0, 0, 0, 0, 0};
uint8_t mPgWidth = 0;
@@ -308,8 +306,8 @@ class DisplayMono {
uint32_t mPgLastTime = 0;
PowerGraphState mPgState = PowerGraphState::NO_TIME_SYNC;
- uint16_t mDispHeight;
- uint8_t mLuminance;
+ uint16_t mDispHeight = 0;
+ uint8_t mLuminance = 0;
TimeMonitor mDisplayTime = TimeMonitor(1000 * DISP_DEFAULT_TIMEOUT, true);
TimeMonitor mDispSwitchTime = TimeMonitor();
diff --git a/src/plugins/history.h b/src/plugins/history.h
index 7a938284..7e415675 100644
--- a/src/plugins/history.h
+++ b/src/plugins/history.h
@@ -24,23 +24,15 @@ template
class HistoryData {
private:
struct storage_t {
- uint16_t refreshCycle;
- uint16_t loopCnt;
- uint16_t listIdx; // index for next Element to write into WattArr
- uint16_t dispIdx; // index for 1st Element to display from WattArr
- bool wrapped;
+ 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;
// ring buffer for watt history
std::array data;
- void reset() {
- loopCnt = 0;
- listIdx = 0;
- dispIdx = 0;
- wrapped = false;
- for(uint16_t i = 0; i < (HISTORY_DATA_ARR_LENGTH + 1); i++) {
- data[i] = 0;
- }
- }
+ storage_t() { data.fill(0); }
};
public:
@@ -50,9 +42,7 @@ class HistoryData {
mConfig = config;
mTs = ts;
- mCurPwr.reset();
mCurPwr.refreshCycle = mConfig->inst.sendInterval;
- //mYieldDay.reset();
//mYieldDay.refreshCycle = 60;
}
@@ -113,14 +103,13 @@ class HistoryData {
}
private:
- IApp *mApp;
- HMSYSTEM *mSys;
- settings *mSettings;
- settings_t *mConfig;
- uint32_t *mTs;
+ IApp *mApp = nullptr;
+ HMSYSTEM *mSys = nullptr;
+ settings *mSettings = nullptr;
+ settings_t *mConfig = nullptr;
+ uint32_t *mTs = nullptr;
storage_t mCurPwr;
- //storage_t mYieldDay;
bool mDayStored = false;
uint16_t mMaximumDay = 0;
};
diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h
index 865c76b5..7799b6d2 100644
--- a/src/publisher/pubMqtt.h
+++ b/src/publisher/pubMqtt.h
@@ -15,6 +15,7 @@
#include
#endif
+#include
#include "../utils/dbg.h"
#include "../config/config.h"
#include
@@ -38,12 +39,15 @@ template
class PubMqtt {
public:
PubMqtt() {
- mRxCnt = 0;
- mTxCnt = 0;
- mSubscriptionCb = NULL;
- memset(mLastIvState, (uint8_t)InverterStatus::OFF, MAX_NUM_INVERTERS);
- memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * 4);
- mLastAnyAvail = false;
+ mLastIvState.fill(InverterStatus::OFF);
+ mIvLastRTRpub.fill(0);
+
+ mVal.fill(0);
+ mTopic.fill(0);
+ mSubTopic.fill(0);
+ mClientId.fill(0);
+ mLwtTopic.fill(0);
+ mSendAlarm.fill(false);
}
~PubMqtt() { }
@@ -63,16 +67,16 @@ class PubMqtt {
});
mDiscovery.running = false;
- snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic);
+ snprintf(mLwtTopic.data(), mLwtTopic.size(), "%s/mqtt", mCfgMqtt->topic);
if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0))
mClient.setCredentials(mCfgMqtt->user, mCfgMqtt->pwd);
if(strlen(mCfgMqtt->clientId) > 0)
- snprintf(mClientId, 23, "%s", mCfgMqtt->clientId);
+ snprintf(mClientId.data(), mClientId.size(), "%s", mCfgMqtt->clientId);
else {
- snprintf(mClientId, 23, "%s-", mDevName);
- uint8_t pos = strlen(mClientId);
+ snprintf(mClientId.data(), mClientId.size(), "%s-", mDevName);
+ uint8_t pos = strlen(mClientId.data());
mClientId[pos++] = WiFi.macAddress().substring( 9, 10).c_str()[0];
mClientId[pos++] = WiFi.macAddress().substring(10, 11).c_str()[0];
mClientId[pos++] = WiFi.macAddress().substring(12, 13).c_str()[0];
@@ -82,9 +86,9 @@ class PubMqtt {
mClientId[pos++] = '\0';
}
- mClient.setClientId(mClientId);
+ mClient.setClientId(mClientId.data());
mClient.setServer(mCfgMqtt->broker, mCfgMqtt->port);
- mClient.setWill(mLwtTopic, QOS_0, true, mqttStr[MQTT_STR_LWT_NOT_CONN]);
+ mClient.setWill(mLwtTopic.data(), QOS_0, true, mqttStr[MQTT_STR_LWT_NOT_CONN]);
mClient.onConnect(std::bind(&PubMqtt::onConnect, this, std::placeholders::_1));
mClient.onDisconnect(std::bind(&PubMqtt::onDisconnect, this, std::placeholders::_1));
mClient.onMessage(std::bind(&PubMqtt::onMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
@@ -125,8 +129,8 @@ class PubMqtt {
}
void tickerMinute() {
- snprintf(mVal, 40, "%d", (*mUptime));
- publish(subtopics[MQTT_UPTIME], mVal);
+ snprintf(mVal.data(), mVal.size(), "%u", (*mUptime));
+ publish(subtopics[MQTT_UPTIME], mVal.data());
publish(subtopics[MQTT_RSSI], String(WiFi.RSSI()).c_str());
publish(subtopics[MQTT_FREE_HEAP], String(ESP.getFreeHeap()).c_str());
#ifndef ESP32
@@ -143,18 +147,17 @@ class PubMqtt {
publish(subtopics[MQTT_COMM_START], String(sunrise + offsM).c_str(), true);
publish(subtopics[MQTT_COMM_STOP], String(sunset + offsE).c_str(), true);
- Inverter<> *iv;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
- iv = mSys->getInverterByPos(i);
+ Inverter<> *iv = mSys->getInverterByPos(i);
if(NULL == iv)
continue;
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/dis_night_comm", iv->config->name);
- publish(mSubTopic, ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/dis_night_comm", iv->config->name);
+ publish(mSubTopic.data(), ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
}
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "comm_disabled");
- publish(mSubTopic, (((*mUtcTimestamp > (sunset + offsE)) || (*mUtcTimestamp < (sunrise + offsM))) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "comm_disabled");
+ publish(mSubTopic.data(), (((*mUtcTimestamp > (sunset + offsE)) || (*mUtcTimestamp < (sunrise + offsM))) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
return true;
}
@@ -176,9 +179,9 @@ class PubMqtt {
void tickerMidnight() {
// set Total YieldDay to zero
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[FLD_YD]);
- snprintf(mVal, 2, "0");
- publish(mSubTopic, mVal, true);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[FLD_YD]);
+ snprintf(mVal.data(), mVal.size(), "0");
+ publish(mSubTopic.data(), mVal.data(), true);
}
void payloadEventListener(uint8_t cmd, Inverter<> *iv) {
@@ -197,11 +200,11 @@ class PubMqtt {
return;
if(addTopic)
- snprintf(mTopic, MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1, "%s/%s", mCfgMqtt->topic, subTopic);
+ snprintf(mTopic.data(), mTopic.size(), "%s/%s", mCfgMqtt->topic, subTopic);
else
- snprintf(mTopic, MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1, "%s", subTopic);
+ snprintf(mTopic.data(), mTopic.size(), "%s", subTopic);
- mClient.publish(mTopic, qos, retained, payload);
+ mClient.publish(mTopic.data(), qos, retained, payload);
yield();
mTxCnt++;
}
@@ -238,8 +241,8 @@ class PubMqtt {
void setPowerLimitAck(Inverter<> *iv) {
if (NULL != iv) {
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]);
- publish(mSubTopic, "true", true, true, QOS_2);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]);
+ publish(mSubTopic.data(), "true", true, true, QOS_2);
}
}
@@ -255,15 +258,15 @@ class PubMqtt {
publish(subtopics[MQTT_IP_ADDR], WiFi.localIP().toString().c_str(), true);
#endif
tickerMinute();
- publish(mLwtTopic, mqttStr[MQTT_STR_LWT_CONN], true, false);
+ publish(mLwtTopic.data(), mqttStr[MQTT_STR_LWT_CONN], true, false);
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
- snprintf(mVal, 20, "ctrl/limit/%d", i);
- subscribe(mVal, QOS_2);
- snprintf(mVal, 20, "ctrl/restart/%d", i);
- subscribe(mVal);
- snprintf(mVal, 20, "ctrl/power/%d", i);
- subscribe(mVal);
+ snprintf(mVal.data(), mVal.size(), "ctrl/limit/%d", i);
+ subscribe(mVal.data(), QOS_2);
+ snprintf(mVal.data(), mVal.size(), "ctrl/restart/%d", i);
+ subscribe(mVal.data());
+ snprintf(mVal.data(), mVal.size(), "ctrl/power/%d", i);
+ subscribe(mVal.data());
}
subscribe(subscr[MQTT_SUBS_SET_TIME]);
}
@@ -359,11 +362,9 @@ class PubMqtt {
}
void discoveryConfigLoop(void) {
- char topic[64], name[32], uniq_id[32], buf[350];
DynamicJsonDocument doc(256);
- uint8_t fldTotal[4] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC};
- const char* unitTotal[4] = {"W", "kWh", "Wh", "W"};
+ constexpr static uint8_t fldTotal[] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC};
String node_id = String(mDevName) + "_TOTAL";
bool total = (mDiscovery.lastIvId == MAX_NUM_INVERTERS);
@@ -392,32 +393,37 @@ class PubMqtt {
doc[F("mf")] = F("Hoymiles");
JsonObject deviceObj = doc.as(); // deviceObj is only pointer!?
+ std::array topic;
+ std::array name;
+ std::array uniq_id;
+ std::array buf;
const char *devCls, *stateCls;
if (!total) {
if (rec->assign[mDiscovery.sub].ch == CH0)
- snprintf(name, 32, "%s", iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(name.data(), name.size(), "%s", iv->getFieldName(mDiscovery.sub, rec));
else
- snprintf(name, 32, "CH%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
- snprintf(topic, 64, "/ch%d/%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
- snprintf(uniq_id, 32, "ch%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(name.data(), name.size(), "CH%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(topic.data(), name.size(), "/ch%d/%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(uniq_id.data(), uniq_id.size(), "ch%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
devCls = getFieldDeviceClass(rec->assign[mDiscovery.sub].fieldId);
stateCls = getFieldStateClass(rec->assign[mDiscovery.sub].fieldId);
}
else { // total values
- snprintf(name, 32, "Total %s", fields[fldTotal[mDiscovery.sub]]);
- snprintf(topic, 64, "/%s", fields[fldTotal[mDiscovery.sub]]);
- snprintf(uniq_id, 32, "total_%s", fields[fldTotal[mDiscovery.sub]]);
+ snprintf(name.data(), name.size(), "Total %s", fields[fldTotal[mDiscovery.sub]]);
+ snprintf(topic.data(), topic.size(), "/%s", fields[fldTotal[mDiscovery.sub]]);
+ snprintf(uniq_id.data(), uniq_id.size(), "total_%s", fields[fldTotal[mDiscovery.sub]]);
devCls = getFieldDeviceClass(fldTotal[mDiscovery.sub]);
stateCls = getFieldStateClass(fldTotal[mDiscovery.sub]);
}
DynamicJsonDocument doc2(512);
+ constexpr static char* unitTotal[] = {"W", "kWh", "Wh", "W"};
doc2[F("name")] = name;
- doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + ((!total) ? String(iv->config->name) : "total" ) + String(topic);
+ 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;
+ doc2[F("uniq_id")] = ((!total) ? (String(iv->config->serial.u64, HEX)) : (node_id)) + "_" + uniq_id.data();
doc2[F("dev")] = deviceObj;
if (!(String(stateCls) == String("total_increasing")))
doc2[F("exp_aft")] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!?
@@ -427,13 +433,13 @@ class PubMqtt {
doc2[F("stat_cla")] = String(stateCls);
if (!total)
- snprintf(topic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(topic.data(), topic.size(), "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
else // total values
- snprintf(topic, 64, "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(), fields[fldTotal[mDiscovery.sub]]);
+ 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;
- memset(buf, 0, size);
- serializeJson(doc2, buf, size);
- publish(topic, buf, true, false);
+ buf.fill(0);
+ serializeJson(doc2, buf.data(), size);
+ publish(topic.data(), buf.data(), true, false);
if(++mDiscovery.sub == ((!total) ? (rec->length) : 4)) {
mDiscovery.sub = 0;
@@ -503,15 +509,15 @@ class PubMqtt {
mLastIvState[id] = status;
changed = true;
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name);
- snprintf(mVal, 40, "%d", (uint8_t)status);
- publish(mSubTopic, mVal, true);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/available", iv->config->name);
+ snprintf(mVal.data(), mVal.size(), "%d", (uint8_t)status);
+ publish(mSubTopic.data(), mVal.data(), true);
}
}
if(changed) {
- snprintf(mVal, 32, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE)));
- publish("status", mVal, true);
+ snprintf(mVal.data(), mVal.size(), "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE)));
+ publish("status", mVal.data(), true);
}
return anyAvail;
@@ -533,19 +539,19 @@ class PubMqtt {
mSendAlarm[i] = false;
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/alarm/cnt", iv->config->name);
- snprintf(mVal, 40, "%d", iv->alarmCnt);
- publish(mSubTopic, mVal, false);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/alarm/cnt", iv->config->name);
+ snprintf(mVal.data(), mVal.size(), "%d", iv->alarmCnt);
+ publish(mSubTopic.data(), mVal.data(), false);
for(uint8_t j = 0; j < 10; j++) {
if(0 != iv->lastAlarm[j].code) {
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/alarm/%d", iv->config->name, j);
- snprintf(mVal, 100, "{\"code\":%d,\"str\":\"%s\",\"start\":%d,\"end\":%d}",
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/alarm/%d", iv->config->name, j);
+ snprintf(mVal.data(), mVal.size(), "{\"code\":%d,\"str\":\"%s\",\"start\":%d,\"end\":%d}",
iv->lastAlarm[j].code,
iv->getAlarmStr(iv->lastAlarm[j].code).c_str(),
iv->lastAlarm[j].start + lastMidnight,
iv->lastAlarm[j].end + lastMidnight);
- publish(mSubTopic, mVal, false);
+ publish(mSubTopic.data(), mVal.data(), false);
yield();
}
}
@@ -575,9 +581,9 @@ class PubMqtt {
}
}
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
- snprintf(mVal, 40, "%g", ah::round3(iv->getValue(i, rec)));
- publish(mSubTopic, mVal, retained);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
+ snprintf(mVal.data(), mVal.size(), "%g", ah::round3(iv->getValue(i, rec)));
+ publish(mSubTopic.data(), mVal.data(), retained);
yield();
}
@@ -597,33 +603,33 @@ class PubMqtt {
}
espMqttClient mClient;
- cfgMqtt_t *mCfgMqtt;
+ cfgMqtt_t *mCfgMqtt = nullptr;
#if defined(ESP8266)
WiFiEventHandler mHWifiCon, mHWifiDiscon;
#endif
- HMSYSTEM *mSys;
+ HMSYSTEM *mSys = nullptr;
PubMqttIvData mSendIvData;
- uint32_t *mUtcTimestamp, *mUptime;
- uint32_t mRxCnt, mTxCnt;
+ uint32_t *mUtcTimestamp = nullptr, *mUptime = nullptr;
+ uint32_t mRxCnt = 0, mTxCnt = 0;
std::queue mSendList;
- std::array mSendAlarm{};
- subscriptionCb mSubscriptionCb;
- bool mLastAnyAvail;
- InverterStatus mLastIvState[MAX_NUM_INVERTERS];
- uint32_t mIvLastRTRpub[MAX_NUM_INVERTERS];
- uint16_t mIntervalTimeout;
+ std::array mSendAlarm;
+ subscriptionCb mSubscriptionCb = nullptr;
+ bool mLastAnyAvail = false;
+ std::array mLastIvState;
+ std::array mIvLastRTRpub;
+ uint16_t mIntervalTimeout = 0;
// last will topic and payload must be available through lifetime of 'espMqttClient'
- char mLwtTopic[MQTT_TOPIC_LEN+5];
- const char *mDevName, *mVersion;
- char mClientId[24]; // number of chars is limited to 23 up to v3.1 of MQTT
+ std::array mLwtTopic;
+ const char *mDevName = nullptr, *mVersion = nullptr;
+ std::array mClientId; // number of chars is limited to 23 up to v3.1 of MQTT
// global buffer for mqtt topic. Used when publishing mqtt messages.
- char mTopic[MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1];
- char mSubTopic[32 + MAX_NAME_LENGTH + 1];
- char mVal[100];
- discovery_t mDiscovery;
+ std::array mTopic;
+ std::array mSubTopic;
+ std::array mVal;
+ discovery_t mDiscovery = {true, 0, 0, 0};
};
#endif /*ENABLE_MQTT*/
diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h
index cfed38b9..4405d037 100644
--- a/src/publisher/pubMqttIvData.h
+++ b/src/publisher/pubMqttIvData.h
@@ -205,9 +205,9 @@ class PubMqttIvData {
}
void stateSendTotals() {
- uint8_t fieldId;
mRTRDataHasBeenSent = true;
if(mPos < 5) {
+ uint8_t fieldId;
bool retained = true;
switch (mPos) {
default:
diff --git a/src/publisher/pubSerial.h b/src/publisher/pubSerial.h
index 34dc64f2..9ac24593 100644
--- a/src/publisher/pubSerial.h
+++ b/src/publisher/pubSerial.h
@@ -1,6 +1,6 @@
//-----------------------------------------------------------------------------
-// 2022 Ahoy, https://ahoydtu.de
-// 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 __PUB_SERIAL_H__
@@ -13,8 +13,6 @@
template
class PubSerial {
public:
- PubSerial() {}
-
void setup(settings_t *cfg, HMSYSTEM *sys, uint32_t *utcTs) {
mCfg = cfg;
mSys = sys;
@@ -46,9 +44,9 @@ class PubSerial {
}
private:
- settings_t *mCfg;
- HMSYSTEM *mSys;
- uint32_t *mUtcTimestamp;
+ settings_t *mCfg = nullptr;
+ HMSYSTEM *mSys = nullptr;
+ uint32_t *mUtcTimestamp = nullptr;
};
diff --git a/src/utils/improv.h b/src/utils/improv.h
index d5a9ae74..32bc403c 100644
--- a/src/utils/improv.h
+++ b/src/utils/improv.h
@@ -10,6 +10,7 @@
#include
#include "dbg.h"
#include "AsyncJson.h"
+#include "../appInterface.h"
// https://www.improv-wifi.com/serial/
// https://github.com/jnthas/improv-wifi-demo/blob/main/src/esp32-wifiimprov/esp32-wifiimprov.ino
@@ -78,7 +79,7 @@ class Improv {
DBGPRINTLN("");
}
- inline uint8_t buildChecksum(uint8_t buf[], uint8_t len) {
+ inline uint8_t buildChecksum(const uint8_t buf[], uint8_t len) {
uint8_t calc = 0;
for(uint8_t i = 0; i < len; i++) {
calc += buf[i];
@@ -86,7 +87,7 @@ class Improv {
return calc;
}
- inline bool checkChecksum(uint8_t buf[], uint8_t len) {
+ inline bool checkChecksum(const uint8_t buf[], uint8_t len) {
/*DHEX(buf[len], false);
DBGPRINT(F(" == "), false);
DBGHEXLN(buildChecksum(buf, len), false);*/
@@ -97,7 +98,7 @@ class Improv {
if(len < 11)
return false;
- if(0 != strncmp((char*)buf, "IMPROV", 6))
+ if(0 != strncmp(reinterpret_cast(buf), "IMPROV", 6))
return false;
// version check (only version 1 is supported!)
@@ -199,7 +200,7 @@ class Improv {
dumpBuf(buf, len);
}
- void parsePayload(uint8_t type, uint8_t buf[], uint8_t len) {
+ void parsePayload(uint8_t type, const uint8_t buf[], uint8_t len) {
if(TYPE_RPC == type) {
if(GET_CURRENT_STATE == buf[0]) {
setDebugEn(false);
@@ -212,9 +213,10 @@ class Improv {
}
}
- IApp *mApp;
- const char *mDevName, *mVersion;
- bool mScanRunning;
+ IApp *mApp = nullptr;
+ const char *mDevName = nullptr;
+ const char *mVersion = nullptr;
+ bool mScanRunning = false;
};
#endif
diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h
index 751550df..16009778 100644
--- a/src/utils/scheduler.h
+++ b/src/utils/scheduler.h
@@ -7,6 +7,7 @@
#define __SCHEDULER_H__
#include
+#include
#include "dbg.h"
namespace ah {
@@ -28,8 +29,6 @@ namespace ah {
class Scheduler {
public:
- Scheduler() {}
-
void setup(bool directStart) {
mUptime = 0;
mTimestamp = (directStart) ? 1 : 0;
@@ -93,8 +92,7 @@ namespace ah {
}
inline void resetTicker(void) {
- for (uint8_t i = 0; i < MAX_NUM_TICKER; i++)
- mTickerInUse[i] = false;
+ mTickerInUse.fill(false);
}
void getStat(uint8_t *max) {
@@ -159,11 +157,11 @@ namespace ah {
}
}
- sP mTicker[MAX_NUM_TICKER];
- bool mTickerInUse[MAX_NUM_TICKER];
- uint32_t mMillis, mPrevMillis, mDiff;
- uint8_t mDiffSeconds;
- uint8_t mMax;
+ std::array mTicker;
+ std::array mTickerInUse;
+ uint32_t mMillis = 0, mPrevMillis = 0, mDiff = 0;
+ uint8_t mDiffSeconds = 0;
+ uint8_t mMax = 0;
};
}
diff --git a/src/utils/spiPatcher.h b/src/utils/spiPatcher.h
index 2f8ce616..210b2a09 100644
--- a/src/utils/spiPatcher.h
+++ b/src/utils/spiPatcher.h
@@ -16,7 +16,7 @@
class SpiPatcher {
protected:
- SpiPatcher(spi_host_device_t dev) :
+ explicit SpiPatcher(spi_host_device_t dev) :
mHostDevice(dev), mCurHandle(nullptr) {
// Use binary semaphore instead of mutex for performance reasons
mutex = xSemaphoreCreateBinaryStatic(&mutex_buffer);
diff --git a/src/utils/timemonitor.h b/src/utils/timemonitor.h
index 9f99cc92..18ab51d9 100644
--- a/src/utils/timemonitor.h
+++ b/src/utils/timemonitor.h
@@ -22,14 +22,14 @@ class TimeMonitor {
/**
* A constructor for creating a TimeMonitor object
*/
- TimeMonitor(void) {}
+ TimeMonitor() {}
/**
* A constructor for initializing a TimeMonitor object
* @param timeout timeout in ms
* @param start (optional) if true, start TimeMonitor immediately
*/
- TimeMonitor(uint32_t timeout, bool start = false) {
+ explicit TimeMonitor(uint32_t timeout, bool start = false) {
if (start)
startTimeMonitor(timeout);
else
@@ -80,7 +80,7 @@ class TimeMonitor {
* true: TimeMonitor already timed out
* false: TimeMonitor still in time or TimeMonitor was stopped
*/
- bool isTimeout(void) {
+ bool isTimeout(void) const {
if ((mStarted) && ((millis() - mStartTime) >= mTimeout))
return true;
else
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index 564d6c62..acd085f3 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -141,7 +141,7 @@ class RestApi {
#endif
}
- void onApiPostBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
+ void onApiPostBody(AsyncWebServerRequest *request, const uint8_t *data, size_t len, size_t index, size_t total) {
DPRINTLN(DBG_VERBOSE, "onApiPostBody");
if(0 == index) {
@@ -158,7 +158,7 @@ class RestApi {
DynamicJsonDocument json(1000);
- DeserializationError err = deserializeJson(json, (const char *)mTmpBuf, mTmpSize);
+ DeserializationError err = deserializeJson(json, reinterpret_cast(mTmpBuf), mTmpSize);
JsonObject obj = json.as();
AsyncJsonResponse* response = new AsyncJsonResponse(false, 200);
@@ -930,20 +930,20 @@ class RestApi {
return true;
}
- IApp *mApp;
- HMSYSTEM *mSys;
- HmRadio<> *mRadioNrf;
+ IApp *mApp = nullptr;
+ HMSYSTEM *mSys = nullptr;
+ HmRadio<> *mRadioNrf = nullptr;
#if defined(ESP32)
- CmtRadio<> *mRadioCmt;
+ CmtRadio<> *mRadioCmt = nullptr;
#endif
- AsyncWebServer *mSrv;
- settings_t *mConfig;
+ AsyncWebServer *mSrv = nullptr;
+ settings_t *mConfig = nullptr;
- uint32_t mTimezoneOffset;
- uint32_t mHeapFree, mHeapFreeBlk;
- uint8_t mHeapFrag;
+ uint32_t mTimezoneOffset = 0;
+ uint32_t mHeapFree = 0, mHeapFreeBlk = 0;
+ uint8_t mHeapFrag = 0;
uint8_t *mTmpBuf = NULL;
- uint32_t mTmpSize;
+ uint32_t mTmpSize = 0;
};
#endif /*__WEB_API_H__*/
diff --git a/src/web/web.h b/src/web/web.h
index 0ffd0594..a166377f 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -48,9 +48,6 @@ class Web {
public:
Web(void) : mWeb(80), mEvts("/events") {
memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE);
- mSerialBufFill = 0;
- mSerialAddTime = true;
- mSerialClientConnnected = false;
}
void setup(IApp *app, HMSYSTEM *sys, settings_t *config) {
@@ -490,9 +487,8 @@ class Web {
// pinout
- uint8_t pin;
for (uint8_t i = 0; i < 16; i++) {
- pin = request->arg(String(pinArgNames[i])).toInt();
+ uint8_t pin = request->arg(String(pinArgNames[i])).toInt();
switch(i) {
case 0: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_NRF_CS_PIN); break;
case 1: mConfig->nrf.pinCe = ((pin != 0xff) ? pin : DEF_NRF_CE_PIN); break;
@@ -633,8 +629,8 @@ class Web {
// NOTE: Grouping for fields with channels and totals is currently not working
// TODO: Handle grouping and sorting for independant from channel number
// NOTE: Check packetsize for MAX_NUM_INVERTERS. Successfully Tested with 4 Inverters (each with 4 channels)
- const char * metricConstPrefix = "ahoy_solar_";
- const char * metricConstInverterFormat = " {inverter=\"%s\"} %d\n";
+ const char* metricConstPrefix = "ahoy_solar_";
+ const char* metricConstInverterFormat = " {inverter=\"%s\"} %d\n";
typedef enum {
metricsStateInverterInfo=0, metricsStateInverterEnabled=1, metricsStateInverterAvailable=2,
metricsStateInverterProducing=3, metricsStateInverterPowerLimitRead=4, metricsStateInverterPowerLimitAck=5,
@@ -648,7 +644,7 @@ class Web {
metricsStateStart,
metricsStateEnd
} MetricStep_t;
- MetricStep_t metricsStep;
+ MetricStep_t metricsStep = metricsStateInverterInfo;
typedef struct {
const char *topic;
const char *type;
@@ -674,9 +670,6 @@ class Web {
{ "radio_dtu_loss_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.dtuLoss;} },
{ "radio_dtu_sent_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.dtuSent;} }
};
- int metricsInverterId;
- uint8_t metricsFieldId;
- bool metricDeclared, metricTotalDeclard;
void showMetrics(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("web::showMetrics"));
@@ -715,7 +708,7 @@ class Web {
snprintf(topic,sizeof(topic),"%swifi_rssi_db{devicename=\"%s\"} %d\n",metricConstPrefix, mConfig->sys.deviceName, WiFi.RSSI());
metrics += String(type) + String(topic);
- len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str());
+ len = snprintf(reinterpret_cast(buffer), maxLen,"%s",metrics.c_str());
// Next is Inverter information
metricsStep = metricsStateInverterInfo;
break;
@@ -743,7 +736,7 @@ class Web {
(String("ahoy_solar_inverter_") + inverterMetrics[metricsStep].topic +
inverterMetrics[metricsStep].format).c_str(),
inverterMetrics[metricsStep].valueFunc);
- len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str());
+ len = snprintf(reinterpret_cast(buffer), maxLen, "%s", metrics.c_str());
// ugly hack to increment the enum
metricsStep = static_cast( static_cast(metricsStep) + 1);
// Prepare Realtime Field loop, which may be startet next
@@ -763,7 +756,7 @@ class Web {
metrics = "# Info: all realtime fields processed\n";
metricsStep = metricsStateAlarmData;
}
- len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str());
+ len = snprintf(reinterpret_cast(buffer), maxLen, "%s", metrics.c_str());
break;
case metricStateRealtimeInverterId: // Iterate over all inverters for this field
@@ -837,7 +830,7 @@ class Web {
metricsFieldId++; // Process next field Id
metricsStep = metricStateRealtimeFieldId;
}
- len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str());
+ len = snprintf(reinterpret_cast(buffer), maxLen, "%s", metrics.c_str());
break;
case metricsStateAlarmData: // Alarm Info loop : fit to one packet
@@ -861,7 +854,7 @@ class Web {
}
}
}
- len = snprintf((char*)buffer,maxLen,"%s",metrics.c_str());
+ len = snprintf(reinterpret_cast(buffer), maxLen, "%s", metrics.c_str());
metricsStep = metricsStateEnd;
break;
@@ -880,10 +873,9 @@ class Web {
// Traverse all inverters and collect the metric via valueFunc
String inverterMetric(char *buffer, size_t len, const char *format, std::function *iv)> valueFunc) {
- Inverter<> *iv;
String metric = "";
for (int metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) {
- iv = mSys->getInverterByPos(metricsInverterId);
+ Inverter<> *iv = mSys->getInverterByPos(metricsInverterId);
if (NULL != iv) {
snprintf(buffer,len,format,iv->config->name, valueFunc(iv));
metric += String(buffer);
@@ -904,21 +896,27 @@ class Web {
if(shortUnit == "Hz") return {"_hertz", "gauge"};
return {"", "gauge"};
}
+
+ private:
+ int metricsInverterId = 0;
+ uint8_t metricsFieldId = 0;
+ bool metricDeclared = false, metricTotalDeclard = false;
#endif
+ private:
AsyncWebServer mWeb;
AsyncEventSource mEvts;
- IApp *mApp;
- HMSYSTEM *mSys;
+ IApp *mApp = nullptr;
+ HMSYSTEM *mSys = nullptr;
- settings_t *mConfig;
+ settings_t *mConfig = nullptr;
- bool mSerialAddTime;
+ bool mSerialAddTime = true;
char mSerialBuf[WEB_SERIAL_BUF_SIZE];
- uint16_t mSerialBufFill;
- bool mSerialClientConnnected;
+ uint16_t mSerialBufFill = 0;
+ bool mSerialClientConnnected = false;
File mUploadFp;
- bool mUploadFail;
+ bool mUploadFail = false;
};
#endif /*__WEB_H__*/
diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h
index 709c08c4..d38701aa 100644
--- a/src/wifi/ahoywifi.h
+++ b/src/wifi/ahoywifi.h
@@ -71,7 +71,7 @@ class ahoywifi {
void welcome(String ip, String mode);
- settings_t *mConfig = NULL;
+ settings_t *mConfig = nullptr;
appWifiCb mAppWifiCb;
DNSServer mDns;
@@ -81,15 +81,15 @@ class ahoywifi {
WiFiEventHandler wifiConnectHandler, wifiDisconnectHandler, wifiGotIPHandler;
#endif
- WiFiStatus_t mStaConn;
- uint8_t mCnt;
- uint32_t *mUtcTimestamp;
+ WiFiStatus_t mStaConn = DISCONNECTED;
+ uint8_t mCnt = 0;
+ uint32_t *mUtcTimestamp = nullptr;
- uint8_t mScanCnt;
- bool mScanActive;
- bool mGotDisconnect;
+ uint8_t mScanCnt = 0;
+ bool mScanActive = false;
+ bool mGotDisconnect = false;
std::list mBSSIDList;
- bool mStopApAllowed;
+ bool mStopApAllowed = false;
bool mWasInCh12to14 = false;
};
From 1f0b15c5beece854c02df929835aa274369762e3 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Tue, 6 Feb 2024 00:01:45 +0100
Subject: [PATCH 33/79] 0.8.74
---
.github/workflows/compile_development.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml
index 4b5a0e1a..66dbf74b 100644
--- a/.github/workflows/compile_development.yml
+++ b/.github/workflows/compile_development.yml
@@ -33,7 +33,7 @@ jobs:
- opendtufusion-ethernet
steps:
- uses: actions/checkout@v4
- - uses: benjlevesque/short-sha@v2.2
+ - uses: benjlevesque/short-sha@v3.0
id: short-sha
with:
length: 7
@@ -93,7 +93,7 @@ jobs:
- opendtufusion-ethernet-de
steps:
- uses: actions/checkout@v4
- - uses: benjlevesque/short-sha@v2.2
+ - uses: benjlevesque/short-sha@v3.0
id: short-sha
with:
length: 7
From 90d4df4b916a1b1c873d305d6529c528ae06f7c3 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Tue, 6 Feb 2024 23:04:10 +0100
Subject: [PATCH 34/79] 0.8.75 * fix active power control value #1406, #1409 *
update Mqtt lib to version `1.6.0` * take care of null terminator of chars
#1410, #1411
---
src/CHANGES.md | 5 ++++
src/defines.h | 2 +-
src/hm/hmInverter.h | 2 +-
src/platformio.ini | 10 +++----
src/publisher/pubMqtt.h | 64 ++++++++++++++++++++---------------------
src/web/RestApi.h | 2 +-
src/web/web.h | 20 ++++++-------
7 files changed, 55 insertions(+), 50 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index f0491335..c01127ce 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,10 @@
# Development Changes
+## 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
diff --git a/src/defines.h b/src/defines.h
index bc9d2452..cdbeee42 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 74
+#define VERSION_PATCH 75
//-------------------------------------
typedef struct {
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index 275fce2c..51cb0d6d 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -120,7 +120,7 @@ class Inverter {
uint8_t type = INV_TYPE_1CH; // integer which refers to inverter type
uint16_t alarmMesIndex = 0; // Last recorded Alarm Message Index
uint16_t powerLimit[2] = {0xffff, AbsolutNonPersistent}; // limit power output (multiplied by 10)
- float actPowerLimit = -1; // actual power limit
+ uint16_t actPowerLimit = 0xffff; // actual power limit
bool powerLimitAck = false; // acknowledged power limit
uint8_t devControlCmd = InitDataState; // carries the requested cmd
serial_u radioId; // id converted to modbus
diff --git a/src/platformio.ini b/src/platformio.ini
index 9b97e018..f949aa37 100644
--- a/src/platformio.ini
+++ b/src/platformio.ini
@@ -28,7 +28,7 @@ lib_deps =
https://github.com/yubox-node-org/ESPAsyncWebServer
https://github.com/nRF24/RF24 @ 1.4.8
paulstoffregen/Time @ ^1.6.1
- https://github.com/bertmelis/espMqttClient#v1.5.0
+ 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
@@ -197,7 +197,7 @@ lib_deps =
khoih-prog/AsyncUDP_ESP32_W5500
https://github.com/nRF24/RF24 @ ^1.4.8
paulstoffregen/Time @ ^1.6.1
- https://github.com/bertmelis/espMqttClient#v1.5.0
+ 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
@@ -220,7 +220,7 @@ lib_deps =
khoih-prog/AsyncUDP_ESP32_W5500
https://github.com/nRF24/RF24 @ ^1.4.8
paulstoffregen/Time @ ^1.6.1
- https://github.com/bertmelis/espMqttClient#v1.5.0
+ 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
@@ -414,7 +414,7 @@ lib_deps =
khoih-prog/AsyncUDP_ESP32_W5500
https://github.com/nrf24/RF24 @ ^1.4.8
paulstoffregen/Time @ ^1.6.1
- https://github.com/bertmelis/espMqttClient#v1.5.0
+ 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
@@ -459,7 +459,7 @@ lib_deps =
khoih-prog/AsyncUDP_ESP32_W5500
https://github.com/nrf24/RF24 @ ^1.4.8
paulstoffregen/Time @ ^1.6.1
- https://github.com/bertmelis/espMqttClient#v1.5.0
+ 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
diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h
index 7799b6d2..0e10e688 100644
--- a/src/publisher/pubMqtt.h
+++ b/src/publisher/pubMqtt.h
@@ -67,15 +67,15 @@ class PubMqtt {
});
mDiscovery.running = false;
- snprintf(mLwtTopic.data(), mLwtTopic.size(), "%s/mqtt", mCfgMqtt->topic);
+ snprintf(mLwtTopic.data(), mLwtTopic.size() - 1, "%s/mqtt", mCfgMqtt->topic);
if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0))
mClient.setCredentials(mCfgMqtt->user, mCfgMqtt->pwd);
if(strlen(mCfgMqtt->clientId) > 0)
- snprintf(mClientId.data(), mClientId.size(), "%s", mCfgMqtt->clientId);
+ snprintf(mClientId.data(), mClientId.size() - 1, "%s", mCfgMqtt->clientId);
else {
- snprintf(mClientId.data(), mClientId.size(), "%s-", mDevName);
+ snprintf(mClientId.data(), mClientId.size() - 1, "%s-", mDevName);
uint8_t pos = strlen(mClientId.data());
mClientId[pos++] = WiFi.macAddress().substring( 9, 10).c_str()[0];
mClientId[pos++] = WiFi.macAddress().substring(10, 11).c_str()[0];
@@ -129,7 +129,7 @@ class PubMqtt {
}
void tickerMinute() {
- snprintf(mVal.data(), mVal.size(), "%u", (*mUptime));
+ snprintf(mVal.data(), mVal.size() - 1, "%u", (*mUptime));
publish(subtopics[MQTT_UPTIME], mVal.data());
publish(subtopics[MQTT_RSSI], String(WiFi.RSSI()).c_str());
publish(subtopics[MQTT_FREE_HEAP], String(ESP.getFreeHeap()).c_str());
@@ -152,11 +152,11 @@ class PubMqtt {
if(NULL == iv)
continue;
- snprintf(mSubTopic.data(), mSubTopic.size(), "%s/dis_night_comm", iv->config->name);
+ snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/dis_night_comm", iv->config->name);
publish(mSubTopic.data(), ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
}
- snprintf(mSubTopic.data(), mSubTopic.size(), "comm_disabled");
+ snprintf(mSubTopic.data(), mSubTopic.size() - 1, "comm_disabled");
publish(mSubTopic.data(), (((*mUtcTimestamp > (sunset + offsE)) || (*mUtcTimestamp < (sunrise + offsM))) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
return true;
@@ -179,8 +179,8 @@ class PubMqtt {
void tickerMidnight() {
// set Total YieldDay to zero
- snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[FLD_YD]);
- snprintf(mVal.data(), mVal.size(), "0");
+ snprintf(mSubTopic.data(), mSubTopic.size() - 1, "total/%s", fields[FLD_YD]);
+ snprintf(mVal.data(), mVal.size() - 1, "0");
publish(mSubTopic.data(), mVal.data(), true);
}
@@ -200,9 +200,9 @@ class PubMqtt {
return;
if(addTopic)
- snprintf(mTopic.data(), mTopic.size(), "%s/%s", mCfgMqtt->topic, subTopic);
+ snprintf(mTopic.data(), mTopic.size() - 1, "%s/%s", mCfgMqtt->topic, subTopic);
else
- snprintf(mTopic.data(), mTopic.size(), "%s", subTopic);
+ snprintf(mTopic.data(), mTopic.size() - 1, "%s", subTopic);
mClient.publish(mTopic.data(), qos, retained, payload);
yield();
@@ -241,7 +241,7 @@ class PubMqtt {
void setPowerLimitAck(Inverter<> *iv) {
if (NULL != iv) {
- snprintf(mSubTopic.data(), mSubTopic.size(), "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]);
+ snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]);
publish(mSubTopic.data(), "true", true, true, QOS_2);
}
}
@@ -261,11 +261,11 @@ class PubMqtt {
publish(mLwtTopic.data(), mqttStr[MQTT_STR_LWT_CONN], true, false);
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
- snprintf(mVal.data(), mVal.size(), "ctrl/limit/%d", i);
+ snprintf(mVal.data(), mVal.size() - 1, "ctrl/limit/%d", i);
subscribe(mVal.data(), QOS_2);
- snprintf(mVal.data(), mVal.size(), "ctrl/restart/%d", i);
+ snprintf(mVal.data(), mVal.size() - 1, "ctrl/restart/%d", i);
subscribe(mVal.data());
- snprintf(mVal.data(), mVal.size(), "ctrl/power/%d", i);
+ snprintf(mVal.data(), mVal.size() - 1, "ctrl/power/%d", i);
subscribe(mVal.data());
}
subscribe(subscr[MQTT_SUBS_SET_TIME]);
@@ -400,20 +400,20 @@ class PubMqtt {
const char *devCls, *stateCls;
if (!total) {
if (rec->assign[mDiscovery.sub].ch == CH0)
- snprintf(name.data(), name.size(), "%s", iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(name.data(), name.size() - 1, "%s", iv->getFieldName(mDiscovery.sub, rec));
else
- snprintf(name.data(), name.size(), "CH%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
- snprintf(topic.data(), name.size(), "/ch%d/%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
- snprintf(uniq_id.data(), uniq_id.size(), "ch%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(name.data(), name.size() - 1, "CH%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(topic.data(), name.size() - 1, "/ch%d/%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(uniq_id.data(), uniq_id.size() - 1, "ch%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
devCls = getFieldDeviceClass(rec->assign[mDiscovery.sub].fieldId);
stateCls = getFieldStateClass(rec->assign[mDiscovery.sub].fieldId);
}
else { // total values
- snprintf(name.data(), name.size(), "Total %s", fields[fldTotal[mDiscovery.sub]]);
- snprintf(topic.data(), topic.size(), "/%s", fields[fldTotal[mDiscovery.sub]]);
- snprintf(uniq_id.data(), uniq_id.size(), "total_%s", fields[fldTotal[mDiscovery.sub]]);
+ snprintf(name.data(), name.size() - 1, "Total %s", fields[fldTotal[mDiscovery.sub]]);
+ snprintf(topic.data(), topic.size() - 1, "/%s", fields[fldTotal[mDiscovery.sub]]);
+ snprintf(uniq_id.data(), uniq_id.size() - 1, "total_%s", fields[fldTotal[mDiscovery.sub]]);
devCls = getFieldDeviceClass(fldTotal[mDiscovery.sub]);
stateCls = getFieldStateClass(fldTotal[mDiscovery.sub]);
}
@@ -433,9 +433,9 @@ class PubMqtt {
doc2[F("stat_cla")] = String(stateCls);
if (!total)
- snprintf(topic.data(), topic.size(), "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(topic.data(), topic.size() - 1, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
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]]);
+ snprintf(topic.data(), topic.size() - 1, "%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);
@@ -509,14 +509,14 @@ class PubMqtt {
mLastIvState[id] = status;
changed = true;
- snprintf(mSubTopic.data(), mSubTopic.size(), "%s/available", iv->config->name);
- snprintf(mVal.data(), mVal.size(), "%d", (uint8_t)status);
+ snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/available", iv->config->name);
+ snprintf(mVal.data(), mVal.size() - 1, "%d", (uint8_t)status);
publish(mSubTopic.data(), mVal.data(), true);
}
}
if(changed) {
- snprintf(mVal.data(), mVal.size(), "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE)));
+ snprintf(mVal.data(), mVal.size() - 1, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE)));
publish("status", mVal.data(), true);
}
@@ -539,14 +539,14 @@ class PubMqtt {
mSendAlarm[i] = false;
- snprintf(mSubTopic.data(), mSubTopic.size(), "%s/alarm/cnt", iv->config->name);
- snprintf(mVal.data(), mVal.size(), "%d", iv->alarmCnt);
+ snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/alarm/cnt", iv->config->name);
+ snprintf(mVal.data(), mVal.size() - 1, "%d", iv->alarmCnt);
publish(mSubTopic.data(), mVal.data(), false);
for(uint8_t j = 0; j < 10; j++) {
if(0 != iv->lastAlarm[j].code) {
- snprintf(mSubTopic.data(), mSubTopic.size(), "%s/alarm/%d", iv->config->name, j);
- snprintf(mVal.data(), mVal.size(), "{\"code\":%d,\"str\":\"%s\",\"start\":%d,\"end\":%d}",
+ snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/alarm/%d", iv->config->name, j);
+ snprintf(mVal.data(), mVal.size() - 1, "{\"code\":%d,\"str\":\"%s\",\"start\":%d,\"end\":%d}",
iv->lastAlarm[j].code,
iv->getAlarmStr(iv->lastAlarm[j].code).c_str(),
iv->lastAlarm[j].start + lastMidnight,
@@ -581,8 +581,8 @@ class PubMqtt {
}
}
- snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
- snprintf(mVal.data(), mVal.size(), "%g", ah::round3(iv->getValue(i, rec)));
+ snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
+ snprintf(mVal.data(), mVal.size() - 1, "%g", ah::round3(iv->getValue(i, rec)));
publish(mSubTopic.data(), mVal.data(), retained);
yield();
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index acd085f3..ce580dd5 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -500,7 +500,7 @@ class RestApi {
obj[F("name")] = String(iv->config->name);
obj[F("serial")] = String(iv->config->serial.u64, HEX);
obj[F("version")] = String(iv->getFwVersion());
- obj[F("power_limit_read")] = ah::round3(iv->actPowerLimit);
+ obj[F("power_limit_read")] = iv->actPowerLimit;
obj[F("power_limit_ack")] = iv->powerLimitAck;
obj[F("max_pwr")] = iv->getMaxPower();
obj[F("ts_last_success")] = rec->ts;
diff --git a/src/web/web.h b/src/web/web.h
index a166377f..c40c817c 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -656,7 +656,7 @@ class Web {
{ "is_enabled", "gauge", metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->config->enabled;} },
{ "is_available", "gauge", metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->isAvailable();} },
{ "is_producing", "gauge", metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->isProducing();} },
- { "power_limit_read", "gauge", metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return (int64_t)ah::round3(iv->actPowerLimit);} },
+ { "power_limit_read", "gauge", metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->actPowerLimit;} },
{ "power_limit_ack", "gauge", metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return (iv->powerLimitAck)?1:0;} },
{ "max_power", "gauge", metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->getMaxPower();} },
{ "radio_rx_success", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxSuccess;} },
@@ -786,14 +786,14 @@ class Web {
char total[7];
if (metricDeclared) {
// A declaration and value for channels have been delivered. So declare and deliver a _total metric
- strncpy(total, "_total", 6);
+ snprintf(total, sizeof(total)-1, "_total");
}
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());
+ snprintf(type, sizeof(type)-1, "# TYPE %s%s%s%s %s\n",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total, promType.c_str());
metrics += type;
metricTotalDeclard = true;
}
- snprintf(topic, sizeof(topic), "%s%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total,iv->config->name);
+ snprintf(topic, sizeof(topic)-1, "%s%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total,iv->config->name);
} else {
// Report (non zero) channel value
// Use a fallback channel name (ch0, ch1, ...)if non is given by user
@@ -801,11 +801,11 @@ class Web {
if (iv->config->chName[channel-1][0] != 0) {
strncpy(chName, iv->config->chName[channel-1], sizeof(chName));
} else {
- snprintf(chName,sizeof(chName),"ch%1d",channel);
+ snprintf(chName,sizeof(chName)-1,"ch%1d",channel);
}
- snprintf(topic, sizeof(topic), "%s%s%s{inverter=\"%s\",channel=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name,chName);
+ snprintf(topic, sizeof(topic)-1, "%s%s%s{inverter=\"%s\",channel=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name,chName);
}
- snprintf(val, sizeof(val), " %.3f\n", iv->getValue(metricsChannelId, rec));
+ snprintf(val, sizeof(val)-1, " %.3f\n", iv->getValue(metricsChannelId, rec));
metrics += topic;
metrics += val;
}
@@ -835,7 +835,7 @@ class Web {
case metricsStateAlarmData: // Alarm Info loop : fit to one packet
// Perform grouping on metrics according to Prometheus exposition format specification
- snprintf(type, sizeof(type),"# TYPE %s%s gauge\n",metricConstPrefix,fields[FLD_LAST_ALARM_CODE]);
+ snprintf(type, sizeof(type)-1,"# TYPE %s%s gauge\n",metricConstPrefix,fields[FLD_LAST_ALARM_CODE]);
metrics = type;
for (metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) {
@@ -847,8 +847,8 @@ class Web {
alarmChannelId = 0;
if (alarmChannelId < rec->length) {
std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(alarmChannelId, rec));
- snprintf(topic, sizeof(topic), "%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(alarmChannelId, rec), promUnit.c_str(), iv->config->name);
- snprintf(val, sizeof(val), " %.3f\n", iv->getValue(alarmChannelId, rec));
+ snprintf(topic, sizeof(topic)-1, "%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(alarmChannelId, rec), promUnit.c_str(), iv->config->name);
+ snprintf(val, sizeof(val)-1, " %.3f\n", iv->getValue(alarmChannelId, rec));
metrics += topic;
metrics += val;
}
From 716c3da3df6483047754ad154819f70b8ec009b1 Mon Sep 17 00:00:00 2001
From: tictrick <117273857+tictrick@users.noreply.github.com>
Date: Wed, 7 Feb 2024 11:36:57 +0100
Subject: [PATCH 35/79] Bugfix: HMT would not start
Am Morgen wollten die HMTs nicht starten.
---
src/hm/hmSystem.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h
index 0266a948..22318347 100644
--- a/src/hm/hmSystem.h
+++ b/src/hm/hmSystem.h
@@ -69,6 +69,7 @@ class HmSystem {
} else if(iv->config->serial.b[5] == 0x13) {
iv->ivGen = IV_HMT;
iv->type = INV_TYPE_6CH;
+ iv->ivRadioType = INV_RADIO_TYPE_CMT;
} else if(iv->config->serial.u64 != 0ULL) {
DPRINTLN(DBG_ERROR, F("inverter type can't be detected!"));
return;
From 7c532ca1cc63bfda9a68cfb9b7baf23d1d17f94b Mon Sep 17 00:00:00 2001
From: lumapu
Date: Wed, 7 Feb 2024 22:50:13 +0100
Subject: [PATCH 36/79] 0.8.76 * revert changes from yesterday regarding
snprintf and its size #1410, #1411 * reduced cppcheck linter warnings
significantly * try to improve ePaper (ghosting) #1107
---
src/CHANGES.md | 5 ++
src/app.cpp | 5 +-
src/defines.h | 2 +-
src/hm/Communication.h | 14 ++--
src/hm/Heuristic.h | 2 +-
src/hm/hmRadio.h | 6 +-
src/hm/radio.h | 14 ++--
src/hm/simulator.h | 6 +-
src/hms/hmsRadio.h | 7 +-
src/plugins/Display/Display.h | 20 +++---
src/plugins/Display/Display_Mono_128X32.h | 6 +-
src/plugins/Display/Display_Mono_128X64.h | 39 +++++-------
src/plugins/Display/Display_Mono_64X48.h | 6 +-
src/plugins/Display/Display_Mono_84X48.h | 27 ++++----
src/plugins/Display/Display_ePaper.cpp | 17 +++--
src/plugins/history.h | 7 +-
src/publisher/pubMqtt.h | 78 +++++++++++------------
src/publisher/pubMqttIvData.h | 26 ++++----
src/utils/improv.h | 2 +-
src/utils/syslog.cpp | 1 +
src/utils/syslog.h | 5 +-
src/web/Protection.h | 2 +-
src/web/web.h | 25 ++++----
23 files changed, 164 insertions(+), 158 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index c01127ce..a9301d44 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,10 @@
# Development Changes
+## 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`
diff --git a/src/app.cpp b/src/app.cpp
index d9b0f933..c93be777 100644
--- a/src/app.cpp
+++ b/src/app.cpp
@@ -264,11 +264,10 @@ void app::tickNtpUpdate(void) {
#endif
if (isOK) {
this->updateNtp();
-
- nxtTrig = isOK ? (mConfig->ntp.interval * 60) : 60; // depending on NTP update success check again in 12h (depends on setting) or in 1 min
+ nxtTrig = mConfig->ntp.interval * 60; // check again in 12h
// immediately start communicating
- if (isOK && mSendFirst) {
+ if (mSendFirst) {
mSendFirst = false;
once(std::bind(&app::tickSend, this), 1, "senOn");
}
diff --git a/src/defines.h b/src/defines.h
index cdbeee42..9ea3834c 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 75
+#define VERSION_PATCH 76
//-------------------------------------
typedef struct {
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 326fb57e..21b78405 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -698,7 +698,7 @@ class Communication : public CommQueue<> {
byte[23] to byte[26] Matching_APPFW_PN*/
DPRINT(DBG_INFO,F("HW_PartNo "));
DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13]));
- record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure
+ 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;
@@ -899,14 +899,16 @@ class Communication : public CommQueue<> {
q->iv->alarmCnt = 1; // minimum...
stsok = false;
//sth is or was wrong?
- if ( (q->iv->type != INV_TYPE_1CH) && ( (statusMi != 3)
- || ((q->iv->lastAlarm[stschan].code) && (statusMi == 3) && (q->iv->lastAlarm[stschan].code != 1)))
+ 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) && (statusMi == 3) && (q->iv->lastAlarm[stschan].code != 1)))
+ } 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)
@@ -962,7 +964,7 @@ class Communication : public CommQueue<> {
iv->radioStatistics.ivLoss = iv->radioStatistics.ivSent - iv->mDtuRxCnt; // this is what we didn't receive
iv->radioStatistics.dtuLoss = iv->mIvTxCnt; // this is somehow the requests w/o answers in that periode
iv->radioStatistics.dtuSent = iv->mDtuTxCnt;
- if (mSerialDebug) {
+ if (*mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN("DTU loss: " +
String (iv->radioStatistics.ivLoss) + "/" +
diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h
index 2a36bc78..ecf82aa7 100644
--- a/src/hm/Heuristic.h
+++ b/src/hm/Heuristic.h
@@ -132,7 +132,7 @@ class Heuristic {
ih->lastRxFragments = rxFragments;
}
- void printStatus(Inverter<> *iv) {
+ void printStatus(const Inverter<> *iv) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("Radio infos:"));
if((IV_HMS != iv->ivGen) && (IV_HMT != iv->ivGen)) {
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index aef4f49d..df6a18b4 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -395,9 +395,9 @@ class HmRadio : public Radio {
#endif*/
if(*mPrintWholeTrace) {
if(*mPrivacyMode)
- ah::dumpBuf(mTxBuf, len, 1, 4);
+ ah::dumpBuf(mTxBuf.data(), len, 1, 4);
else
- ah::dumpBuf(mTxBuf, len);
+ ah::dumpBuf(mTxBuf.data(), len);
} else {
DHEX(mTxBuf[0]);
DBGPRINT(F(" "));
@@ -415,7 +415,7 @@ class HmRadio : public Radio {
}
mNrf24->setChannel(mRfChLst[mTxChIdx]);
mNrf24->openWritingPipe(reinterpret_cast(&iv->radioId.u64));
- mNrf24->startWrite(mTxBuf, len, false); // false = request ACK response
+ mNrf24->startWrite(mTxBuf.data(), len, false); // false = request ACK response
mMillis = millis();
mLastIv = iv;
diff --git a/src/hm/radio.h b/src/hm/radio.h
index db694b54..31643980 100644
--- a/src/hm/radio.h
+++ b/src/hm/radio.h
@@ -11,6 +11,7 @@
#define ALL_FRAMES 0x80
#define SINGLE_FRAME 0x81
+#include
#include
#include "../utils/dbg.h"
#include "../utils/crc.h"
@@ -34,6 +35,8 @@ class Radio {
virtual std::pair getFreqRangeMhz(void) { return std::make_pair(0, 0); }
virtual bool loop(void) = 0;
+ Radio() : mTxBuf{} {}
+
void handleIntr(void) {
mIrqRcvd = true;
mIrqOk = IRQ_OK;
@@ -107,7 +110,7 @@ class Radio {
mTxBuf[(*len)++] = (crc ) & 0xff;
}
// crc over all
- mTxBuf[*len] = ah::crc8(mTxBuf, *len);
+ mTxBuf[*len] = ah::crc8(mTxBuf.data(), *len);
(*len)++;
}
@@ -129,12 +132,11 @@ class Radio {
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;
- std::atomic mIrqRcvd;
+ protected:
+ uint32_t mDtuSn = 0;
+ std::atomic mIrqRcvd = false;
bool *mSerialDebug = nullptr, *mPrivacyMode = nullptr, *mPrintWholeTrace = nullptr;
- uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE];
+ std::array mTxBuf;
};
#endif /*__RADIO_H__*/
diff --git a/src/hm/simulator.h b/src/hm/simulator.h
index 4e06062e..3d0b43d7 100644
--- a/src/hm/simulator.h
+++ b/src/hm/simulator.h
@@ -118,9 +118,9 @@ class Simulator {
}
private:
- HMSYSTEM *mSys;
- uint8_t mIvId;
- uint32_t *mTimestamp;
+ HMSYSTEM *mSys = nullptr;
+ uint8_t mIvId = 0;
+ uint32_t *mTimestamp = nullptr;
payloadListenerType mCbPayload = nullptr;
uint8_t payloadCtrl = 0;
diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h
index 66e312d7..cb181b0b 100644
--- a/src/hms/hmsRadio.h
+++ b/src/hms/hmsRadio.h
@@ -21,6 +21,7 @@ class CmtRadio : public Radio {
mPrivacyMode = privacyMode;
mSerialDebug = serialDebug;
mPrintWholeTrace = printWholeTrace;
+ mTxBuf.fill(0);
}
bool loop() override {
@@ -102,9 +103,9 @@ class CmtRadio : public Radio {
DBGPRINT(F("Mhz | "));
if(*mPrintWholeTrace) {
if(*mPrivacyMode)
- ah::dumpBuf(mTxBuf, len, 1, 4);
+ ah::dumpBuf(mTxBuf.data(), len, 1, 4);
else
- ah::dumpBuf(mTxBuf, len);
+ ah::dumpBuf(mTxBuf.data(), len);
} else {
DHEX(mTxBuf[0]);
DBGPRINT(F(" "));
@@ -114,7 +115,7 @@ class CmtRadio : public Radio {
}
}
- CmtStatus status = mCmt.tx(mTxBuf, len);
+ CmtStatus status = mCmt.tx(mTxBuf.data(), len);
mMillis = millis();
if(CmtStatus::SUCCESS != status) {
DPRINT(DBG_WARN, F("CMT TX failed, code: "));
diff --git a/src/plugins/Display/Display.h b/src/plugins/Display/Display.h
index c59a56b6..b2c88b05 100644
--- a/src/plugins/Display/Display.h
+++ b/src/plugins/Display/Display.h
@@ -223,21 +223,21 @@ class Display {
}
// private member variables
- IApp *mApp;
+ IApp *mApp = nullptr;
DisplayData mDisplayData;
- bool mNewPayload;
- uint8_t mLoopCnt;
- uint32_t *mUtcTs;
- display_t *mCfg;
- HMSYSTEM *mSys;
- RADIO *mHmRadio;
- RADIO *mHmsRadio;
- uint16_t mRefreshCycle;
+ bool mNewPayload = false;
+ uint8_t mLoopCnt = 0;
+ uint32_t *mUtcTs = nullptr;
+ display_t *mCfg = nullptr;
+ HMSYSTEM *mSys = nullptr;
+ RADIO *mHmRadio = nullptr;
+ RADIO *mHmsRadio = nullptr;
+ uint16_t mRefreshCycle = 0;
#if defined(ESP32) && !defined(ETHERNET)
DisplayEPaper mEpaper;
#endif
- DisplayMono *mMono;
+ DisplayMono *mMono = nullptr;
};
#endif /*PLUGIN_DISPLAY*/
diff --git a/src/plugins/Display/Display_Mono_128X32.h b/src/plugins/Display/Display_Mono_128X32.h
index 3e5a1762..6262e3f6 100644
--- a/src/plugins/Display/Display_Mono_128X32.h
+++ b/src/plugins/Display/Display_Mono_128X32.h
@@ -12,11 +12,11 @@ class DisplayMono128X32 : public DisplayMono {
mExtra = 0;
}
- void config(display_t *cfg) {
+ void config(display_t *cfg) override {
mCfg = cfg;
}
- void init(DisplayData *displayData) {
+ void init(DisplayData *displayData) override {
u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0);
monoInit(new U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C(rot, 0xff, mCfg->disp_clk, mCfg->disp_data), displayData);
calcLinePositions();
@@ -26,7 +26,7 @@ class DisplayMono128X32 : public DisplayMono {
mDisplay->sendBuffer();
}
- void disp(void) {
+ void disp(void) override {
mDisplay->clearBuffer();
// calculate current pixelshift for pixelshift screensaver
diff --git a/src/plugins/Display/Display_Mono_128X64.h b/src/plugins/Display/Display_Mono_128X64.h
index 69afae04..c63f0b22 100644
--- a/src/plugins/Display/Display_Mono_128X64.h
+++ b/src/plugins/Display/Display_Mono_128X64.h
@@ -13,11 +13,11 @@ class DisplayMono128X64 : public DisplayMono {
mExtra = 0;
}
- void config(display_t *cfg) {
+ void config(display_t *cfg) override {
mCfg = cfg;
}
- void init(DisplayData *displayData) {
+ void init(DisplayData *displayData) override {
u8g2_cb_t *rot = (u8g2_cb_t *)(( mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0);
switch (mCfg->type) {
case DISP_TYPE_T1_SSD1306_128X64:
@@ -68,9 +68,7 @@ class DisplayMono128X64 : public DisplayMono {
mDisplay->sendBuffer();
}
- void disp(void) {
- uint8_t pos, sun_pos, moon_pos;
-
+ void disp(void) override {
mDisplay->clearBuffer();
// Layout-Test
@@ -106,8 +104,8 @@ class DisplayMono128X64 : public DisplayMono {
}
// print status of inverters
else {
- sun_pos = -1;
- moon_pos = -1;
+ int8_t sun_pos = -1;
+ int8_t moon_pos = -1;
setLineFont(l_Status);
if (0 == mDisplayData->nrSleeping + mDisplayData->nrProducing)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "no inverter");
@@ -128,11 +126,11 @@ class DisplayMono128X64 : public DisplayMono {
}
printText(mFmtText, l_Status, 0xff);
- pos = (mDispWidth - mDisplay->getStrWidth(mFmtText)) / 2;
+ uint8_t pos = (mDispWidth - mDisplay->getStrWidth(mFmtText)) / 2;
mDisplay->setFont(u8g2_font_ncenB08_symbols8_ahoy);
- if (sun_pos!=-1)
+ if (sun_pos != -1)
mDisplay->drawStr(pos + sun_pos + mPixelshift, mLineYOffsets[l_Status], "G"); // sun symbol
- if (moon_pos!=-1)
+ if (moon_pos != -1)
mDisplay->drawStr(pos + moon_pos + mPixelshift, mLineYOffsets[l_Status], "H"); // moon symbol
}
}
@@ -181,12 +179,11 @@ class DisplayMono128X64 : public DisplayMono {
// draw dynamic RSSI bars
int rssi_bar_height = 9;
for (int i = 0; i < 4; i++) {
- int radio_rssi_threshold = -60 - i * 10;
- int wifi_rssi_threshold = -60 - i * 10;
+ int rssi_threshold = -60 - i * 10;
uint8_t barwidth = std::min(4 - i, 3);
- if (mDisplayData->RadioRSSI > radio_rssi_threshold)
+ if (mDisplayData->RadioRSSI > rssi_threshold)
mDisplay->drawBox(widthShrink / 2 + mPixelshift, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height);
- if (mDisplayData->WifiRSSI > wifi_rssi_threshold)
+ if (mDisplayData->WifiRSSI > rssi_threshold)
mDisplay->drawBox(mDispWidth - barwidth - widthShrink / 2 + mPixelshift, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height);
}
// draw dynamic antenna and WiFi symbols
@@ -223,23 +220,22 @@ class DisplayMono128X64 : public DisplayMono {
l_MAX_LINES = 5,
};
- uint8_t graph_first_line;
- uint8_t graph_last_line;
+ uint8_t graph_first_line = 0;
+ uint8_t graph_last_line = 0;
const uint8_t pixelShiftRange = 11; // number of pixels to shift from left to right (centered -> must be odd!)
- uint8_t widthShrink;
+ uint8_t widthShrink = 0;
void calcLinePositions() {
uint8_t yOff = 0;
uint8_t i = 0;
- uint8_t asc, dsc;
do {
setLineFont(i);
- asc = mDisplay->getAscent();
+ uint8_t asc = mDisplay->getAscent();
yOff += asc;
mLineYOffsets[i] = yOff;
- dsc = mDisplay->getDescent();
+ uint8_t dsc = mDisplay->getDescent();
yOff -= dsc;
if (l_Time == i) // prevent time and status line to touch
yOff++; // -> one pixels space
@@ -248,8 +244,7 @@ class DisplayMono128X64 : public DisplayMono {
}
inline void setLineFont(uint8_t line) {
- if ((line == l_TotalPower) ||
- (line == l_Ahoy))
+ if (line == l_TotalPower) // || (line == l_Ahoy) -> l_TotalPower == l_Ahoy == 2
mDisplay->setFont(u8g2_font_ncenB14_tr);
else if ((line == l_YieldDay) ||
(line == l_YieldTotal))
diff --git a/src/plugins/Display/Display_Mono_64X48.h b/src/plugins/Display/Display_Mono_64X48.h
index 84e40126..7f98cae5 100644
--- a/src/plugins/Display/Display_Mono_64X48.h
+++ b/src/plugins/Display/Display_Mono_64X48.h
@@ -12,11 +12,11 @@ class DisplayMono64X48 : public DisplayMono {
mExtra = 0;
}
- void config(display_t *cfg) {
+ void config(display_t *cfg) override {
mCfg = cfg;
}
- void init(DisplayData *displayData) {
+ void init(DisplayData *displayData) override {
u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0);
// Wemos OLed Shield is not defined in u8 lib -> use nearest compatible
monoInit(new U8G2_SSD1306_64X48_ER_F_HW_I2C(rot, 0xff, mCfg->disp_clk, mCfg->disp_data), displayData);
@@ -28,7 +28,7 @@ class DisplayMono64X48 : public DisplayMono {
mDisplay->sendBuffer();
}
- void disp(void) {
+ void disp(void) override {
mDisplay->clearBuffer();
// calculate current pixelshift for pixelshift screensaver
diff --git a/src/plugins/Display/Display_Mono_84X48.h b/src/plugins/Display/Display_Mono_84X48.h
index d3be1f31..b5daacd5 100644
--- a/src/plugins/Display/Display_Mono_84X48.h
+++ b/src/plugins/Display/Display_Mono_84X48.h
@@ -12,11 +12,11 @@ class DisplayMono84X48 : public DisplayMono {
mExtra = 0;
}
- void config(display_t *cfg) {
+ void config(display_t *cfg) override {
mCfg = cfg;
}
- void init(DisplayData *displayData) {
+ void init(DisplayData *displayData) override {
u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0);
monoInit(new U8G2_PCD8544_84X48_F_4W_SW_SPI(rot, mCfg->disp_clk, mCfg->disp_data, mCfg->disp_cs, mCfg->disp_dc, 0xff), displayData);
@@ -55,7 +55,7 @@ class DisplayMono84X48 : public DisplayMono {
mDisplay->sendBuffer();
}
- void disp(void) {
+ void disp(void) override {
mDisplay->clearBuffer();
// Layout-Test
@@ -143,12 +143,11 @@ class DisplayMono84X48 : public DisplayMono {
// draw dynamic RSSI bars
int rssi_bar_height = 7;
for (int i = 0; i < 4; i++) {
- int radio_rssi_threshold = -60 - i * 10;
- int wifi_rssi_threshold = -60 - i * 10;
+ int rssi_threshold = -60 - i * 10;
uint8_t barwidth = std::min(4 - i, 3);
- if (mDisplayData->RadioRSSI > radio_rssi_threshold)
+ if (mDisplayData->RadioRSSI > rssi_threshold)
mDisplay->drawBox(0, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height);
- if (mDisplayData->WifiRSSI > wifi_rssi_threshold)
+ if (mDisplayData->WifiRSSI > rssi_threshold)
mDisplay->drawBox(mDispWidth - barwidth, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height);
}
@@ -184,30 +183,28 @@ class DisplayMono84X48 : public DisplayMono {
l_MAX_LINES = 5,
};
- uint8_t graph_first_line;
- uint8_t graph_last_line;
+ uint8_t graph_first_line = 0;
+ uint8_t graph_last_line = 0;
void calcLinePositions() {
uint8_t yOff = 0;
uint8_t i = 0;
- uint8_t asc, dsc;
do {
setLineFont(i);
- asc = mDisplay->getAscent();
+ uint8_t asc = mDisplay->getAscent();
yOff += asc;
mLineYOffsets[i] = yOff;
- dsc = mDisplay->getDescent();
+ uint8_t dsc = mDisplay->getDescent();
if (l_TotalPower != i) // power line needs no descent spacing
yOff -= dsc;
yOff++; // instead lets spend one pixel space between all lines
i++;
- } while(l_MAX_LINES>i);
+ } while(l_MAX_LINES > i);
}
inline void setLineFont(uint8_t line) {
- if ((line == l_TotalPower) ||
- (line == l_Ahoy))
+ if (line == l_TotalPower) // || (line == l_Ahoy) -> l_TotalPower == l_Ahoy == 2
mDisplay->setFont(u8g2_font_logisoso16_tr);
else
mDisplay->setFont(u8g2_font_5x8_symbols_ahoy);
diff --git a/src/plugins/Display/Display_ePaper.cpp b/src/plugins/Display/Display_ePaper.cpp
index fdcec767..087d784b 100644
--- a/src/plugins/Display/Display_ePaper.cpp
+++ b/src/plugins/Display/Display_ePaper.cpp
@@ -67,7 +67,7 @@ void DisplayEPaper::refreshLoop() {
case RefreshStatus::LOGO:
_display->fillScreen(GxEPD_BLACK);
_display->drawBitmap(0, 0, logo, 200, 200, GxEPD_WHITE);
- _display->display(false); // full update
+ mSecondCnt = 2;
mNextRefreshState = RefreshStatus::PARTITIALS;
mRefreshState = RefreshStatus::WAIT;
break;
@@ -79,11 +79,11 @@ void DisplayEPaper::refreshLoop() {
break;
case RefreshStatus::WHITE:
- if(mSecondCnt == 0) {
- _display->fillScreen(GxEPD_WHITE);
- mNextRefreshState = RefreshStatus::PARTITIALS;
- mRefreshState = RefreshStatus::WAIT;
- }
+ if(0 != mSecondCnt)
+ break;
+ _display->fillScreen(GxEPD_WHITE);
+ mNextRefreshState = RefreshStatus::PARTITIALS;
+ mRefreshState = RefreshStatus::WAIT;
break;
case RefreshStatus::WAIT:
@@ -92,10 +92,13 @@ void DisplayEPaper::refreshLoop() {
break;
case RefreshStatus::PARTITIALS:
+ if(0 != mSecondCnt)
+ break;
headlineIP();
versionFooter();
mSecondCnt = 4; // display Logo time during boot up
- mRefreshState = RefreshStatus::DONE;
+ mNextRefreshState = RefreshStatus::DONE;
+ mRefreshState = RefreshStatus::WAIT;
break;
default: // RefreshStatus::DONE
diff --git a/src/plugins/history.h b/src/plugins/history.h
index 7e415675..5076e295 100644
--- a/src/plugins/history.h
+++ b/src/plugins/history.h
@@ -47,14 +47,13 @@ class HistoryData {
}
void tickerSecond() {
- Inverter<> *iv;
- record_t<> *rec;
+ ;
float curPwr = 0;
float maxPwr = 0;
float yldDay = -0.1;
for (uint8_t i = 0; i < mSys->getNumInverters(); i++) {
- iv = mSys->getInverterByPos(i);
- rec = iv->getRecordStruct(RealTimeRunData_Debug);
+ Inverter<> *iv = mSys->getInverterByPos(i);
+ record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
if (iv == NULL)
continue;
curPwr += iv->getChannelFieldValue(CH0, FLD_PAC, rec);
diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h
index 0e10e688..1b9e35ef 100644
--- a/src/publisher/pubMqtt.h
+++ b/src/publisher/pubMqtt.h
@@ -38,7 +38,7 @@ typedef struct {
template
class PubMqtt {
public:
- PubMqtt() {
+ PubMqtt() : SendIvData() {
mLastIvState.fill(InverterStatus::OFF);
mIvLastRTRpub.fill(0);
@@ -61,21 +61,21 @@ class PubMqtt {
mUptime = uptime;
mIntervalTimeout = 1;
- mSendIvData.setup(sys, utcTs, &mSendList);
- mSendIvData.setPublishFunc([this](const char *subTopic, const char *payload, bool retained, uint8_t qos) {
+ SendIvData.setup(sys, utcTs, &mSendList);
+ SendIvData.setPublishFunc([this](const char *subTopic, const char *payload, bool retained, uint8_t qos) {
publish(subTopic, payload, retained, true, qos);
});
mDiscovery.running = false;
- snprintf(mLwtTopic.data(), mLwtTopic.size() - 1, "%s/mqtt", mCfgMqtt->topic);
+ snprintf(mLwtTopic.data(), mLwtTopic.size(), "%s/mqtt", mCfgMqtt->topic);
if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0))
mClient.setCredentials(mCfgMqtt->user, mCfgMqtt->pwd);
if(strlen(mCfgMqtt->clientId) > 0)
- snprintf(mClientId.data(), mClientId.size() - 1, "%s", mCfgMqtt->clientId);
+ snprintf(mClientId.data(), mClientId.size(), "%s", mCfgMqtt->clientId);
else {
- snprintf(mClientId.data(), mClientId.size() - 1, "%s-", mDevName);
+ snprintf(mClientId.data(), mClientId.size(), "%s-", mDevName);
uint8_t pos = strlen(mClientId.data());
mClientId[pos++] = WiFi.macAddress().substring( 9, 10).c_str()[0];
mClientId[pos++] = WiFi.macAddress().substring(10, 11).c_str()[0];
@@ -95,7 +95,7 @@ class PubMqtt {
}
void loop() {
- mSendIvData.loop();
+ SendIvData.loop();
#if defined(ESP8266)
mClient.loop();
@@ -129,7 +129,7 @@ class PubMqtt {
}
void tickerMinute() {
- snprintf(mVal.data(), mVal.size() - 1, "%u", (*mUptime));
+ snprintf(mVal.data(), mVal.size(), "%u", (*mUptime));
publish(subtopics[MQTT_UPTIME], mVal.data());
publish(subtopics[MQTT_RSSI], String(WiFi.RSSI()).c_str());
publish(subtopics[MQTT_FREE_HEAP], String(ESP.getFreeHeap()).c_str());
@@ -152,11 +152,11 @@ class PubMqtt {
if(NULL == iv)
continue;
- snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/dis_night_comm", iv->config->name);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/dis_night_comm", iv->config->name);
publish(mSubTopic.data(), ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
}
- snprintf(mSubTopic.data(), mSubTopic.size() - 1, "comm_disabled");
+ snprintf(mSubTopic.data(), mSubTopic.size(), "comm_disabled");
publish(mSubTopic.data(), (((*mUtcTimestamp > (sunset + offsE)) || (*mUtcTimestamp < (sunrise + offsM))) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
return true;
@@ -164,7 +164,7 @@ class PubMqtt {
void notAvailChanged(bool allNotAvail) {
if(!allNotAvail)
- mSendIvData.resetYieldDay();
+ SendIvData.resetYieldDay();
}
bool tickerComm(bool disabled) {
@@ -179,8 +179,8 @@ class PubMqtt {
void tickerMidnight() {
// set Total YieldDay to zero
- snprintf(mSubTopic.data(), mSubTopic.size() - 1, "total/%s", fields[FLD_YD]);
- snprintf(mVal.data(), mVal.size() - 1, "0");
+ snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[FLD_YD]);
+ snprintf(mVal.data(), mVal.size(), "0");
publish(mSubTopic.data(), mVal.data(), true);
}
@@ -200,9 +200,9 @@ class PubMqtt {
return;
if(addTopic)
- snprintf(mTopic.data(), mTopic.size() - 1, "%s/%s", mCfgMqtt->topic, subTopic);
+ snprintf(mTopic.data(), mTopic.size(), "%s/%s", mCfgMqtt->topic, subTopic);
else
- snprintf(mTopic.data(), mTopic.size() - 1, "%s", subTopic);
+ snprintf(mTopic.data(), mTopic.size(), "%s", subTopic);
mClient.publish(mTopic.data(), qos, retained, payload);
yield();
@@ -241,7 +241,7 @@ class PubMqtt {
void setPowerLimitAck(Inverter<> *iv) {
if (NULL != iv) {
- snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]);
publish(mSubTopic.data(), "true", true, true, QOS_2);
}
}
@@ -261,11 +261,11 @@ class PubMqtt {
publish(mLwtTopic.data(), mqttStr[MQTT_STR_LWT_CONN], true, false);
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
- snprintf(mVal.data(), mVal.size() - 1, "ctrl/limit/%d", i);
+ snprintf(mVal.data(), mVal.size(), "ctrl/limit/%d", i);
subscribe(mVal.data(), QOS_2);
- snprintf(mVal.data(), mVal.size() - 1, "ctrl/restart/%d", i);
+ snprintf(mVal.data(), mVal.size(), "ctrl/restart/%d", i);
subscribe(mVal.data());
- snprintf(mVal.data(), mVal.size() - 1, "ctrl/power/%d", i);
+ snprintf(mVal.data(), mVal.size(), "ctrl/power/%d", i);
subscribe(mVal.data());
}
subscribe(subscr[MQTT_SUBS_SET_TIME]);
@@ -400,20 +400,20 @@ class PubMqtt {
const char *devCls, *stateCls;
if (!total) {
if (rec->assign[mDiscovery.sub].ch == CH0)
- snprintf(name.data(), name.size() - 1, "%s", iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(name.data(), name.size(), "%s", iv->getFieldName(mDiscovery.sub, rec));
else
- snprintf(name.data(), name.size() - 1, "CH%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
- snprintf(topic.data(), name.size() - 1, "/ch%d/%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
- snprintf(uniq_id.data(), uniq_id.size() - 1, "ch%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(name.data(), name.size(), "CH%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(topic.data(), name.size(), "/ch%d/%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(uniq_id.data(), uniq_id.size(), "ch%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
devCls = getFieldDeviceClass(rec->assign[mDiscovery.sub].fieldId);
stateCls = getFieldStateClass(rec->assign[mDiscovery.sub].fieldId);
}
else { // total values
- snprintf(name.data(), name.size() - 1, "Total %s", fields[fldTotal[mDiscovery.sub]]);
- snprintf(topic.data(), topic.size() - 1, "/%s", fields[fldTotal[mDiscovery.sub]]);
- snprintf(uniq_id.data(), uniq_id.size() - 1, "total_%s", fields[fldTotal[mDiscovery.sub]]);
+ snprintf(name.data(), name.size(), "Total %s", fields[fldTotal[mDiscovery.sub]]);
+ snprintf(topic.data(), topic.size(), "/%s", fields[fldTotal[mDiscovery.sub]]);
+ snprintf(uniq_id.data(), uniq_id.size(), "total_%s", fields[fldTotal[mDiscovery.sub]]);
devCls = getFieldDeviceClass(fldTotal[mDiscovery.sub]);
stateCls = getFieldStateClass(fldTotal[mDiscovery.sub]);
}
@@ -433,9 +433,9 @@ class PubMqtt {
doc2[F("stat_cla")] = String(stateCls);
if (!total)
- snprintf(topic.data(), topic.size() - 1, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
+ snprintf(topic.data(), topic.size(), "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
else // total values
- snprintf(topic.data(), topic.size() - 1, "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(), fields[fldTotal[mDiscovery.sub]]);
+ 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);
@@ -509,14 +509,14 @@ class PubMqtt {
mLastIvState[id] = status;
changed = true;
- snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/available", iv->config->name);
- snprintf(mVal.data(), mVal.size() - 1, "%d", (uint8_t)status);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/available", iv->config->name);
+ snprintf(mVal.data(), mVal.size(), "%d", (uint8_t)status);
publish(mSubTopic.data(), mVal.data(), true);
}
}
if(changed) {
- snprintf(mVal.data(), mVal.size() - 1, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE)));
+ snprintf(mVal.data(), mVal.size(), "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE)));
publish("status", mVal.data(), true);
}
@@ -539,14 +539,14 @@ class PubMqtt {
mSendAlarm[i] = false;
- snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/alarm/cnt", iv->config->name);
- snprintf(mVal.data(), mVal.size() - 1, "%d", iv->alarmCnt);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/alarm/cnt", iv->config->name);
+ snprintf(mVal.data(), mVal.size(), "%d", iv->alarmCnt);
publish(mSubTopic.data(), mVal.data(), false);
for(uint8_t j = 0; j < 10; j++) {
if(0 != iv->lastAlarm[j].code) {
- snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/alarm/%d", iv->config->name, j);
- snprintf(mVal.data(), mVal.size() - 1, "{\"code\":%d,\"str\":\"%s\",\"start\":%d,\"end\":%d}",
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/alarm/%d", iv->config->name, j);
+ snprintf(mVal.data(), mVal.size(), "{\"code\":%d,\"str\":\"%s\",\"start\":%d,\"end\":%d}",
iv->lastAlarm[j].code,
iv->getAlarmStr(iv->lastAlarm[j].code).c_str(),
iv->lastAlarm[j].start + lastMidnight,
@@ -581,8 +581,8 @@ class PubMqtt {
}
}
- snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
- snprintf(mVal.data(), mVal.size() - 1, "%g", ah::round3(iv->getValue(i, rec)));
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
+ snprintf(mVal.data(), mVal.size(), "%g", ah::round3(iv->getValue(i, rec)));
publish(mSubTopic.data(), mVal.data(), retained);
yield();
@@ -598,7 +598,7 @@ class PubMqtt {
if(mSendList.empty())
return;
- mSendIvData.start();
+ SendIvData.start();
mLastAnyAvail = anyAvail;
}
@@ -609,7 +609,7 @@ class PubMqtt {
#endif
HMSYSTEM *mSys = nullptr;
- PubMqttIvData mSendIvData;
+ PubMqttIvData SendIvData;
uint32_t *mUtcTimestamp = nullptr, *mUptime = nullptr;
uint32_t mRxCnt = 0, mTxCnt = 0;
diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h
index 4405d037..5f38768d 100644
--- a/src/publisher/pubMqttIvData.h
+++ b/src/publisher/pubMqttIvData.h
@@ -1,4 +1,4 @@
-//-----------------------------------------------------------------------------
+ //-----------------------------------------------------------------------------
// 2024 Ahoy, https://ahoydtu.de
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
//-----------------------------------------------------------------------------
@@ -21,6 +21,8 @@ struct sendListCmdIv {
template
class PubMqttIvData {
public:
+ PubMqttIvData() : mTotal{}, mSubTopic{}, mVal{} {}
+
void setup(HMSYSTEM *sys, uint32_t *utcTs, std::queue *sendList) {
mSys = sys;
mUtcTimestamp = utcTs;
@@ -249,25 +251,25 @@ class PubMqttIvData {
}
}
- HMSYSTEM *mSys;
- uint32_t *mUtcTimestamp;
+ HMSYSTEM *mSys = nullptr;
+ uint32_t *mUtcTimestamp = nullptr;
pubMqttPublisherType mPublish;
- State mState;
+ State mState = IDLE;
StateFunction mTable[NUM_STATES];
- uint8_t mCmd;
- uint8_t mLastIvId;
- bool mSendTotals, mTotalFound, mAllTotalFound, mSendTotalYd;
- float mTotal[5], mYldTotalStore;
+ uint8_t mCmd = 0;
+ uint8_t mLastIvId = 0;
+ bool mSendTotals = false, mTotalFound = false, mAllTotalFound = false, mSendTotalYd = false;
+ float mTotal[5], mYldTotalStore = 0;
- Inverter<> *mIv, *mIvSend;
- uint8_t mPos;
- bool mRTRDataHasBeenSent;
+ Inverter<> *mIv = nullptr, *mIvSend = nullptr;
+ uint8_t mPos = 0;
+ bool mRTRDataHasBeenSent = false;
char mSubTopic[32 + MAX_NAME_LENGTH + 1];
char mVal[140];
- std::queue *mSendList;
+ std::queue *mSendList = nullptr;
};
#endif /*__PUB_MQTT_IV_DATA_H__*/
diff --git a/src/utils/improv.h b/src/utils/improv.h
index 32bc403c..20b2bcad 100644
--- a/src/utils/improv.h
+++ b/src/utils/improv.h
@@ -71,7 +71,7 @@ class Improv {
TYPE_RPC_RESPONSE = 0x04
};
- void dumpBuf(uint8_t buf[], uint8_t len) {
+ void dumpBuf(const uint8_t buf[], uint8_t len) {
for(uint8_t i = 0; i < len; i++) {
DHEX(buf[i]);
DBGPRINT(F(" "));
diff --git a/src/utils/syslog.cpp b/src/utils/syslog.cpp
index 9c4bf93b..c251e899 100644
--- a/src/utils/syslog.cpp
+++ b/src/utils/syslog.cpp
@@ -10,6 +10,7 @@
#define SYSLOG_MAX_PACKET_SIZE 256
+DbgSyslog::DbgSyslog() : mSyslogBuffer{} {}
//-----------------------------------------------------------------------------
void DbgSyslog::setup(settings_t *config) {
diff --git a/src/utils/syslog.h b/src/utils/syslog.h
index 37bdc524..ec7f4f6e 100644
--- a/src/utils/syslog.h
+++ b/src/utils/syslog.h
@@ -36,6 +36,7 @@
class DbgSyslog {
public:
+ DbgSyslog();
void setup (settings_t *config);
void syslogCb(String msg);
void log(const char *hostname, uint8_t facility, uint8_t severity, char* msg);
@@ -43,7 +44,7 @@ class DbgSyslog {
private:
WiFiUDP mSyslogUdp;
IPAddress mSyslogIP;
- settings_t *mConfig;
+ settings_t *mConfig = nullptr;
char mSyslogBuffer[SYSLOG_BUF_SIZE+1];
uint16_t mSyslogBufFill = 0;
int mSyslogSeverity = PRI_NOTICE;
@@ -51,4 +52,4 @@ class DbgSyslog {
#endif /*ENABLE_SYSLOG*/
-#endif /*__SYSLOG_H__*/
\ No newline at end of file
+#endif /*__SYSLOG_H__*/
diff --git a/src/web/Protection.h b/src/web/Protection.h
index 0c7b8379..6b079e82 100644
--- a/src/web/Protection.h
+++ b/src/web/Protection.h
@@ -15,7 +15,7 @@
class Protection {
protected:
- Protection(const char *pwd) {
+ explicit Protection(const char *pwd) {
mPwd = pwd;
mLogoutTimeout = 0;
mLoginIp.fill(0);
diff --git a/src/web/web.h b/src/web/web.h
index c40c817c..a85e4b0a 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -684,7 +684,6 @@ class Web {
char type[60], topic[100], val[25];
size_t len = 0;
int alarmChannelId;
- int metricsChannelId;
// Perform grouping on metrics according to format specification
// Each step must return at least one character. Otherwise the processing of AsyncWebServerResponse stops.
@@ -766,7 +765,7 @@ class Web {
iv = mSys->getInverterByPos(metricsInverterId);
if (NULL != iv) {
rec = iv->getRecordStruct(RealTimeRunData_Debug);
- for (metricsChannelId=0; metricsChannelId < rec->length;metricsChannelId++) {
+ for (int metricsChannelId=0; metricsChannelId < rec->length;metricsChannelId++) {
uint8_t channel = rec->assign[metricsChannelId].ch;
// Try inverter channel (channel 0) or any channel with maxPwr > 0
@@ -786,14 +785,14 @@ class Web {
char total[7];
if (metricDeclared) {
// A declaration and value for channels have been delivered. So declare and deliver a _total metric
- snprintf(total, sizeof(total)-1, "_total");
+ snprintf(total, sizeof(total), "_total");
}
if (!metricTotalDeclard) {
- snprintf(type, sizeof(type)-1, "# TYPE %s%s%s%s %s\n",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total, promType.c_str());
+ snprintf(type, sizeof(type), "# TYPE %s%s%s%s %s\n",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total, promType.c_str());
metrics += type;
metricTotalDeclard = true;
}
- snprintf(topic, sizeof(topic)-1, "%s%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total,iv->config->name);
+ snprintf(topic, sizeof(topic), "%s%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total,iv->config->name);
} else {
// Report (non zero) channel value
// Use a fallback channel name (ch0, ch1, ...)if non is given by user
@@ -801,11 +800,11 @@ class Web {
if (iv->config->chName[channel-1][0] != 0) {
strncpy(chName, iv->config->chName[channel-1], sizeof(chName));
} else {
- snprintf(chName,sizeof(chName)-1,"ch%1d",channel);
+ snprintf(chName,sizeof(chName),"ch%1d",channel);
}
- snprintf(topic, sizeof(topic)-1, "%s%s%s{inverter=\"%s\",channel=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name,chName);
+ snprintf(topic, sizeof(topic), "%s%s%s{inverter=\"%s\",channel=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name,chName);
}
- snprintf(val, sizeof(val)-1, " %.3f\n", iv->getValue(metricsChannelId, rec));
+ snprintf(val, sizeof(val), " %.3f\n", iv->getValue(metricsChannelId, rec));
metrics += topic;
metrics += val;
}
@@ -835,7 +834,7 @@ class Web {
case metricsStateAlarmData: // Alarm Info loop : fit to one packet
// Perform grouping on metrics according to Prometheus exposition format specification
- snprintf(type, sizeof(type)-1,"# TYPE %s%s gauge\n",metricConstPrefix,fields[FLD_LAST_ALARM_CODE]);
+ snprintf(type, sizeof(type),"# TYPE %s%s gauge\n",metricConstPrefix,fields[FLD_LAST_ALARM_CODE]);
metrics = type;
for (metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) {
@@ -847,8 +846,8 @@ class Web {
alarmChannelId = 0;
if (alarmChannelId < rec->length) {
std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(alarmChannelId, rec));
- snprintf(topic, sizeof(topic)-1, "%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(alarmChannelId, rec), promUnit.c_str(), iv->config->name);
- snprintf(val, sizeof(val)-1, " %.3f\n", iv->getValue(alarmChannelId, rec));
+ snprintf(topic, sizeof(topic), "%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(alarmChannelId, rec), promUnit.c_str(), iv->config->name);
+ snprintf(val, sizeof(val), " %.3f\n", iv->getValue(alarmChannelId, rec));
metrics += topic;
metrics += val;
}
@@ -874,8 +873,8 @@ class Web {
// Traverse all inverters and collect the metric via valueFunc
String inverterMetric(char *buffer, size_t len, const char *format, std::function *iv)> valueFunc) {
String metric = "";
- for (int metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) {
- Inverter<> *iv = mSys->getInverterByPos(metricsInverterId);
+ for (int id = 0; id < mSys->getNumInverters();id++) {
+ Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL != iv) {
snprintf(buffer,len,format,iv->config->name, valueFunc(iv));
metric += String(buffer);
From d4a4f9cfb6616135d7cdb8a1c6954aa44d102f44 Mon Sep 17 00:00:00 2001
From: tictrick <117273857+tictrick@users.noreply.github.com>
Date: Thu, 8 Feb 2024 08:38:11 +0100
Subject: [PATCH 37/79] BugFix: ACK
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Die Funktion startWrite() der RF24 Bibliothek ist ungeeignet für den Empfang von ACKs, da der Verstärker während des Sendens statt in den RX-Modus Ausgeschaltet wird.
---
src/hm/hmRadio.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index df6a18b4..09500826 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -415,7 +415,7 @@ class HmRadio : public Radio {
}
mNrf24->setChannel(mRfChLst[mTxChIdx]);
mNrf24->openWritingPipe(reinterpret_cast(&iv->radioId.u64));
- mNrf24->startWrite(mTxBuf.data(), len, false); // false = request ACK response
+ mNrf24->startFastWrite(mTxBuf.data(), len, false); // false = request ACK response
mMillis = millis();
mLastIv = iv;
From 15349520d26538cee0dba501ea69b54e7fe8a66f Mon Sep 17 00:00:00 2001
From: lumapu
Date: Fri, 9 Feb 2024 00:05:54 +0100
Subject: [PATCH 38/79] 0.8.77 * merge PR: BugFix: ACK #1414 * fix suspicious
if condition #1416 * prepared API token for access, not functional #1415
---
src/CHANGES.md | 5 ++++
src/app.cpp | 2 +-
src/app.h | 8 +++++--
src/appInterface.h | 3 ++-
src/defines.h | 2 +-
src/web/Protection.h | 34 ++++++++++++++++++++++++---
src/web/RestApi.h | 55 ++++++++++++++++++++++++++++++++++----------
src/web/lang.h | 10 ++++++--
src/web/web.h | 2 +-
9 files changed, 98 insertions(+), 23 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index a9301d44..b75ba2b3 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,10 @@
# Development Changes
+## 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
diff --git a/src/app.cpp b/src/app.cpp
index c93be777..bee12387 100644
--- a/src/app.cpp
+++ b/src/app.cpp
@@ -239,7 +239,7 @@ void app::updateNtp(void) {
}
}
- if ((mSunrise == 0) && (mConfig->sun.lat) && (mConfig->sun.lon)) {
+ 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();
}
diff --git a/src/app.h b/src/app.h
index 60be4d1d..be20f26f 100644
--- a/src/app.h
+++ b/src/app.h
@@ -251,8 +251,8 @@ class app : public IApp, public ah::Scheduler {
mProtection->lock();
}
- void unlock(const char *clientIp) override {
- mProtection->unlock(clientIp);
+ char *unlock(const char *clientIp) override {
+ return mProtection->unlock(clientIp);
}
void resetLockTimeout(void) override {
@@ -267,6 +267,10 @@ class app : public IApp, public ah::Scheduler {
return mProtection->isProtected(clientIp);
}
+ bool isProtected(const char *clientIp, const char *token) const override {
+ return mProtection->isProtected(clientIp, token);
+ }
+
bool getNrfEnabled(void) override {
return mConfig->nrf.enabled;
}
diff --git a/src/appInterface.h b/src/appInterface.h
index 6703b5bf..937908e2 100644
--- a/src/appInterface.h
+++ b/src/appInterface.h
@@ -62,10 +62,11 @@ class IApp {
virtual uint32_t getMqttTxCnt() = 0;
virtual void lock(void) = 0;
- virtual void unlock(const char *clientIp) = 0;
+ virtual char *unlock(const char *clientIp) = 0;
virtual void resetLockTimeout(void) = 0;
virtual bool isProtected(void) const = 0;
virtual bool isProtected(const char *clientIp) const = 0;
+ virtual bool isProtected(const char *clientIp, const char *token) const = 0;
virtual uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0;
virtual uint16_t getHistoryMaxDay() = 0;
diff --git a/src/defines.h b/src/defines.h
index 9ea3834c..46be8dac 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 76
+#define VERSION_PATCH 77
//-------------------------------------
typedef struct {
diff --git a/src/web/Protection.h b/src/web/Protection.h
index 6b079e82..f62f1380 100644
--- a/src/web/Protection.h
+++ b/src/web/Protection.h
@@ -19,6 +19,7 @@ class Protection {
mPwd = pwd;
mLogoutTimeout = 0;
mLoginIp.fill(0);
+ mToken.fill(0);
// no password set - unlock
if(pwd[0] == '\0')
@@ -50,20 +51,34 @@ class Protection {
mLoginIp.fill(0);
}
- void unlock(const char *clientIp) {
+ char *unlock(const char *clientIp) {
mLogoutTimeout = LOGOUT_TIMEOUT;
mProtected = false;
ah::ip2Arr(static_cast(mLoginIp.data()), clientIp);
+ genToken();
+
+ return reinterpret_cast(mToken.data());
}
void resetLockTimeout(void) {
- mLogoutTimeout = LOGOUT_TIMEOUT;
+ if(0 != mLogoutTimeout)
+ mLogoutTimeout = LOGOUT_TIMEOUT;
}
bool isProtected(void) const {
return mProtected;
}
+ bool isProtected(const char *clientIp, const char *token) const {
+ if(isProtected(clientIp))
+ return true;
+
+ if(0 == mToken[0]) // token is zero
+ return true;
+
+ return (0 != strncmp(token, mToken.data(), 16));
+ }
+
bool isProtected(const char *clientIp) const {
if(mProtected)
return true;
@@ -81,14 +96,27 @@ class Protection {
return false;
}
+ private:
+ void genToken() {
+ mToken.fill(0);
+ for(uint8_t i = 0; i < 16; i++) {
+ mToken[i] = random(1, 35);
+ if(mToken[i] < 10)
+ mToken[i] += 0x30; // convert to ascii number 1-9 (zero isn't allowed)
+ else
+ mToken[i] += 0x37; // convert to ascii upper case character
+ }
+ }
+
protected:
static Protection *mInstance;
private:
const char *mPwd;
bool mProtected = true;
- uint16_t mLogoutTimeout = LOGOUT_TIMEOUT;
+ uint16_t mLogoutTimeout = 0;
std::array mLoginIp;
+ std::array mToken;
};
#endif /*__PROTECTION_H__*/
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index ce580dd5..59b786d7 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -70,7 +70,7 @@ class RestApi {
if(obj[F("path")] == "ctrl")
setCtrl(obj, dummy, "*");
else if(obj[F("path")] == "setup")
- setSetup(obj, dummy);
+ setSetup(obj, dummy, "*");
}
private:
@@ -169,7 +169,7 @@ class RestApi {
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);
+ 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;
@@ -831,23 +831,44 @@ class RestApi {
}
bool setCtrl(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
- Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
- bool accepted = true;
- if(NULL == iv) {
- jsonOut[F("error")] = F(INV_INDEX_INVALID) + jsonIn[F("id")].as();
- return false;
+ if(F("auth") == jsonIn[F("cmd")]) {
+ if(String(jsonIn["val"]) == String(mConfig->sys.adminPwd))
+ jsonOut["token"] = mApp->unlock(clientIP);
+ else {
+ jsonOut[F("error")] = F(AUTH_ERROR);
+ return false;
+ }
+ return true;
}
- jsonOut[F("id")] = jsonIn[F("id")];
- if(mConfig->sys.adminPwd[0] != '\0') {
- if(strncmp("*", clientIP, 1) != 0) { // no call from API (MqTT)
+ /*if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
+ if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
+ const char* token = jsonIn["token"];
+ if(mApp->isProtected(clientIP, token)) {
+ jsonOut[F("error")] = F(IS_PROTECTED);
+ jsonOut[F("bla")] = String(token);
+ return false;
+ }
+ }
+ }*/
+
+ if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
+ if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
if(mApp->isProtected(clientIP)) {
- jsonOut[F("error")] = F(INV_IS_PROTECTED);
+ jsonOut[F("error")] = F(IS_PROTECTED);
return false;
}
}
}
+ Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
+ bool accepted = true;
+ if(NULL == iv) {
+ jsonOut[F("error")] = F(INV_INDEX_INVALID) + jsonIn[F("id")].as();
+ return false;
+ }
+ jsonOut[F("id")] = jsonIn[F("id")];
+
if(F("power") == jsonIn[F("cmd")])
accepted = iv->setDevControlRequest((jsonIn[F("val")] == 1) ? TurnOn : TurnOff);
else if(F("restart") == jsonIn[F("cmd")])
@@ -882,7 +903,17 @@ class RestApi {
return true;
}
- bool setSetup(JsonObject jsonIn, JsonObject jsonOut) {
+ bool setSetup(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
+ /*if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
+ if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
+ const char* token = jsonIn["token"];
+ if(mApp->isProtected(clientIP, token)) {
+ jsonOut[F("error")] = F(IS_PROTECTED);
+ return false;
+ }
+ }
+ }*/
+
#if !defined(ETHERNET)
if(F("scan_wifi") == jsonIn[F("cmd")])
mApp->scanAvailNetworks();
diff --git a/src/web/lang.h b/src/web/lang.h
index 6cddbc12..1e066928 100644
--- a/src/web/lang.h
+++ b/src/web/lang.h
@@ -30,6 +30,12 @@
#define INV_INDEX_INVALID "inverter index invalid: "
#endif
+#ifdef LANG_DE
+ #define AUTH_ERROR "Authentifizierungsfehler"
+#else /*LANG_EN*/
+ #define AUTH_ERROR "authentication error"
+#endif
+
#ifdef LANG_DE
#define UNKNOWN_CMD "unbekanntes Kommando: '"
#else /*LANG_EN*/
@@ -37,9 +43,9 @@
#endif
#ifdef LANG_DE
- #define INV_IS_PROTECTED "nicht angemeldet, Kommando nicht möglich!"
+ #define IS_PROTECTED "nicht angemeldet, Kommando nicht möglich!"
#else /*LANG_EN*/
- #define INV_IS_PROTECTED "not logged in, command not possible!"
+ #define IS_PROTECTED "not logged in, command not possible!"
#endif
#ifdef LANG_DE
diff --git a/src/web/web.h b/src/web/web.h
index a85e4b0a..76503f0b 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -782,7 +782,7 @@ class Web {
// report value
if (0 == channel) {
// Report a _total value if also channel values were reported. Otherwise report without _total
- char total[7];
+ char total[7] = {0};
if (metricDeclared) {
// A declaration and value for channels have been delivered. So declare and deliver a _total metric
snprintf(total, sizeof(total), "_total");
From 8b2db4abfa24a9a6d596661860a4bd9dd3e52502 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Fri, 9 Feb 2024 00:25:25 +0100
Subject: [PATCH 39/79] 0.8.78 * try to finalize API token protection
---
src/CHANGES.md | 3 +++
src/app.h | 12 ++++--------
src/appInterface.h | 5 ++---
src/web/Protection.h | 40 +++++++++++++++++++++-------------------
src/web/RestApi.h | 24 +++++++-----------------
src/web/web.h | 4 ++--
6 files changed, 39 insertions(+), 49 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index b75ba2b3..ea067bd2 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,8 @@
# Development Changes
+## 0.8.78 - 2024-02-09
+* finalized API token access #1415
+
## 0.8.77 - 2024-02-08
* merge PR: BugFix: ACK #1414
* fix suspicious if condition #1416
diff --git a/src/app.h b/src/app.h
index be20f26f..1a4e780d 100644
--- a/src/app.h
+++ b/src/app.h
@@ -251,8 +251,8 @@ class app : public IApp, public ah::Scheduler {
mProtection->lock();
}
- char *unlock(const char *clientIp) override {
- return mProtection->unlock(clientIp);
+ char *unlock(const char *clientIp, bool loginFromWeb) override {
+ return mProtection->unlock(clientIp, loginFromWeb);
}
void resetLockTimeout(void) override {
@@ -263,12 +263,8 @@ class app : public IApp, public ah::Scheduler {
return mProtection->isProtected();
}
- bool isProtected(const char *clientIp) const override {
- return mProtection->isProtected(clientIp);
- }
-
- bool isProtected(const char *clientIp, const char *token) const override {
- return mProtection->isProtected(clientIp, token);
+ bool isProtected(const char *token, bool askedFromWeb) const override {
+ return mProtection->isProtected(token, askedFromWeb);
}
bool getNrfEnabled(void) override {
diff --git a/src/appInterface.h b/src/appInterface.h
index 937908e2..f0d2b2a0 100644
--- a/src/appInterface.h
+++ b/src/appInterface.h
@@ -62,11 +62,10 @@ class IApp {
virtual uint32_t getMqttTxCnt() = 0;
virtual void lock(void) = 0;
- virtual char *unlock(const char *clientIp) = 0;
+ virtual char *unlock(const char *clientIp, bool loginFromWeb) = 0;
virtual void resetLockTimeout(void) = 0;
virtual bool isProtected(void) const = 0;
- virtual bool isProtected(const char *clientIp) const = 0;
- virtual bool isProtected(const char *clientIp, const char *token) const = 0;
+ virtual bool isProtected(const char *token, bool askedFromWeb) const = 0;
virtual uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0;
virtual uint16_t getHistoryMaxDay() = 0;
diff --git a/src/web/Protection.h b/src/web/Protection.h
index f62f1380..b9eeef95 100644
--- a/src/web/Protection.h
+++ b/src/web/Protection.h
@@ -40,8 +40,9 @@ class Protection {
// auto logout
if(0 != mLogoutTimeout) {
if (0 == --mLogoutTimeout) {
- if(mPwd[0] != '\0')
+ if(mPwd[0] != '\0') {
mProtected = true;
+ }
}
}
}
@@ -49,13 +50,17 @@ class Protection {
void lock(void) {
mProtected = true;
mLoginIp.fill(0);
+ mToken.fill(0);
}
- char *unlock(const char *clientIp) {
+ char *unlock(const char *clientIp, bool loginFromWeb) {
mLogoutTimeout = LOGOUT_TIMEOUT;
mProtected = false;
- ah::ip2Arr(static_cast(mLoginIp.data()), clientIp);
- genToken();
+
+ if(loginFromWeb)
+ ah::ip2Arr(static_cast(mLoginIp.data()), clientIp);
+ else
+ genToken();
return reinterpret_cast(mToken.data());
}
@@ -69,28 +74,25 @@ class Protection {
return mProtected;
}
- bool isProtected(const char *clientIp, const char *token) const {
- if(isProtected(clientIp))
- return true;
-
- if(0 == mToken[0]) // token is zero
- return true;
-
- return (0 != strncmp(token, mToken.data(), 16));
- }
-
- bool isProtected(const char *clientIp) const {
+ bool isProtected(const char *token, bool askedFromWeb) const { // token == clientIp
if(mProtected)
return true;
if(mPwd[0] == '\0')
return false;
- std::array ip;
- ah::ip2Arr(static_cast(ip.data()), clientIp);
- for(uint8_t i = 0; i < 4; i++) {
- if(mLoginIp[i] != ip[i])
+ if(askedFromWeb) { // check IP address
+ std::array ip;
+ ah::ip2Arr(static_cast(ip.data()), token);
+ for(uint8_t i = 0; i < 4; i++) {
+ if(mLoginIp[i] != ip[i])
+ return true;
+ }
+ } else { // API call - check token
+ if(0 == mToken[0]) // token is zero
return true;
+
+ return (0 != strncmp(token, mToken.data(), 16));
}
return false;
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index 59b786d7..5103f3ba 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -266,7 +266,7 @@ class RestApi {
obj[F("modules")] = String(mApp->getVersionModules());
obj[F("build")] = String(AUTO_GIT_HASH);
obj[F("env")] = String(ENV_NAME);
- obj[F("menu_prot")] = mApp->isProtected(request->client()->remoteIP().toString().c_str());
+ obj[F("menu_prot")] = mApp->isProtected(request->client()->remoteIP().toString().c_str(), true);
obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask );
obj[F("menu_protEn")] = (bool) (mConfig->sys.adminPwd[0] != '\0');
obj[F("cst_lnk")] = String(mConfig->plugin.customLink);
@@ -833,7 +833,7 @@ class RestApi {
bool setCtrl(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
if(F("auth") == jsonIn[F("cmd")]) {
if(String(jsonIn["val"]) == String(mConfig->sys.adminPwd))
- jsonOut["token"] = mApp->unlock(clientIP);
+ jsonOut["token"] = mApp->unlock(clientIP, false);
else {
jsonOut[F("error")] = F(AUTH_ERROR);
return false;
@@ -841,20 +841,10 @@ class RestApi {
return true;
}
- /*if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
- if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
- const char* token = jsonIn["token"];
- if(mApp->isProtected(clientIP, token)) {
- jsonOut[F("error")] = F(IS_PROTECTED);
- jsonOut[F("bla")] = String(token);
- return false;
- }
- }
- }*/
-
if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
- if(mApp->isProtected(clientIP)) {
+ const char* token = jsonIn["token"];
+ if(mApp->isProtected(token, false)) {
jsonOut[F("error")] = F(IS_PROTECTED);
return false;
}
@@ -904,15 +894,15 @@ class RestApi {
}
bool setSetup(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
- /*if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
+ if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
const char* token = jsonIn["token"];
- if(mApp->isProtected(clientIP, token)) {
+ if(mApp->isProtected(token, false)) {
jsonOut[F("error")] = F(IS_PROTECTED);
return false;
}
}
- }*/
+ }
#if !defined(ETHERNET)
if(F("scan_wifi") == jsonIn[F("cmd")])
diff --git a/src/web/web.h b/src/web/web.h
index 76503f0b..7ed41f92 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -227,7 +227,7 @@ class Web {
}
void checkProtection(AsyncWebServerRequest *request) {
- if(mApp->isProtected(request->client()->remoteIP().toString().c_str())) {
+ if(mApp->isProtected(request->client()->remoteIP().toString().c_str(), true)) {
checkRedirect(request);
return;
}
@@ -314,7 +314,7 @@ class Web {
if (request->args() > 0) {
if (String(request->arg("pwd")) == String(mConfig->sys.adminPwd)) {
- mApp->unlock(request->client()->remoteIP().toString().c_str());
+ mApp->unlock(request->client()->remoteIP().toString().c_str(), true);
request->redirect("/");
}
}
From d15e75dbabe222f206bf16b6d29b5f3d1e27c1aa Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Fri, 9 Feb 2024 11:53:20 +0100
Subject: [PATCH 40/79] simplify rxOffset logic
- Code cleanup
- fix "nRF CE keep high" code (missing argument)
---
src/hm/Communication.h | 91 +++++++++++++++++++++---------------------
src/hm/hmDefines.h | 2 +-
src/hm/hmInverter.h | 1 -
src/hm/hmRadio.h | 42 ++++---------------
src/hm/hmSystem.h | 10 +----
5 files changed, 55 insertions(+), 91 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 21b78405..a37bcdb2 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -13,7 +13,7 @@
#include "../utils/timemonitor.h"
#include "Heuristic.h"
-#define MAX_BUFFER 250
+#define MAX_BUFFER 200
typedef std::function *)> payloadListenerType;
typedef std::function *)> powerLimitAckListenerType;
@@ -92,6 +92,8 @@ class Communication : public CommQueue<> {
q->iv->mIsSingleframeReq = false;
mFramesExpected = getFramesExpected(q); // function to get expected frame count.
mTimeout = DURATION_TXFRAME + mFramesExpected*DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType];
+ if((q->iv->ivGen == IV_MI) && ((q->cmd == MI_REQ_CH1) || (q->cmd == MI_REQ_4CH)))
+ incrAttempt(q->iv->channels); // 2 more attempts for 2ch, 4 more for 4ch
mState = States::START;
break;
@@ -209,7 +211,7 @@ class Communication : public CommQueue<> {
} else {
if(q->iv->miMultiParts < 6) {
mState = States::WAIT;
- if((q->iv->radio->mRadioWaitTime.isTimeout() && mIsRetransmit) || !mIsRetransmit) {
+ if(q->iv->radio->mRadioWaitTime.isTimeout() && q->attempts) {
miRepeatRequest(q);
return;
}
@@ -220,6 +222,10 @@ class Communication : public CommQueue<> {
|| ((q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH))) {
miComplete(q->iv);
}
+ if(*mSerialDebug) {
+ DPRINT_IVID(DBG_INFO, q->iv->id);
+ DBGPRINTLN(F("Payload (MI got all)"));
+ }
closeRequest(q, true);
}
}
@@ -443,9 +449,8 @@ class Communication : public CommQueue<> {
|| (p->packet[0] == MI_REQ_CH2 + ALL_FRAMES)
|| ((p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES))
&& (p->packet[0] < (0x39 + SINGLE_FRAME))
- )) { //&& (p->packet[0] != (0x0f + ALL_FRAMES)))) {
+ )) {
// small MI or MI 1500 data responses to 0x09, 0x11, 0x36, 0x37, 0x38 and 0x39
- //mPayload[iv->id].txId = p->packet[0];
miDataDecode(p, q);
} else if (p->packet[0] == (0x0f + ALL_FRAMES)) {
miHwDecode(p, q);
@@ -541,14 +546,16 @@ class Communication : public CommQueue<> {
len -= 2;
- DPRINT_IVID(DBG_INFO, q->iv->id);
- DBGPRINT(F("Payload ("));
- DBGPRINT(String(len));
- if(*mPrintWholeTrace) {
- DBGPRINT(F("): "));
- ah::dumpBuf(mPayload.data(), len);
- } else
- DBGPRINTLN(F(")"));
+ if(*mSerialDebug) {
+ DPRINT_IVID(DBG_INFO, q->iv->id);
+ DBGPRINT(F("Payload ("));
+ DBGPRINT(String(len));
+ if(*mPrintWholeTrace) {
+ DBGPRINT(F("): "));
+ ah::dumpBuf(mPayload.data(), len);
+ } else
+ DBGPRINTLN(F(")"));
+ }
if(GridOnProFilePara == q->cmd) {
q->iv->addGridProfile(mPayload.data(), len);
@@ -813,35 +820,21 @@ class Communication : public CommQueue<> {
miStsConsolidate(q, datachan, rec, p->packet[23], p->packet[24]);
if (p->packet[0] < (0x39 + ALL_FRAMES) ) {
- mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), 1);
miNextRequest((p->packet[0] - ALL_FRAMES + 1), q);
} else {
q->iv->miMultiParts = 7; // indicate we are ready
}
} else if((p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES)) && (q->iv->type == INV_TYPE_2CH)) {
- //addImportant(q->iv, MI_REQ_CH2);
miNextRequest(MI_REQ_CH2, q);
- mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt);
- q->iv->mIvRxCnt++; // statistics workaround...
+ q->iv->mIvRxCnt++; // statistics workaround...
- } else { // first data msg for 1ch, 2nd for 2ch
+ } else // first data msg for 1ch, 2nd for 2ch
q->iv->miMultiParts += 6; // indicate we are ready
-
- }
}
void miNextRequest(uint8_t cmd, const queue_s *q) {
- incrAttempt(); // if function is called, we got something, and we necessarily need more transmissions for MI types...
- if(*mSerialDebug) {
- DPRINT_IVID(DBG_WARN, q->iv->id);
- DBGPRINT(F("next request ("));
- DBGPRINT(String(q->attempts));
- DBGPRINT(F(" attempts left): 0x"));
- DBGHEXLN(cmd);
- }
-
- /*if(q->iv->miMultiParts > 5) //if(q->iv->miMultiParts == 7)
- q->iv->radioStatistics.rxSuccess++;*/
+ mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt);
+ mHeu.getTxCh(q->iv);
q->iv->radioStatistics.ivSent++;
mFramesExpected = getFramesExpected(q);
@@ -851,6 +844,13 @@ class Communication : public CommQueue<> {
q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
q->iv->miMultiParts = 0;
q->iv->mGotFragment = 0;
+ if(*mSerialDebug) {
+ DPRINT_IVID(DBG_INFO, q->iv->id);
+ DBGPRINT(F("next: ("));
+ DBGPRINT(String(q->attempts));
+ DBGPRINT(F(" attempts left): 0x"));
+ DBGHEXLN(cmd);
+ }
mIsRetransmit = true;
chgCmd(cmd);
//mState = States::WAIT;
@@ -858,19 +858,17 @@ class Communication : public CommQueue<> {
void miRepeatRequest(const queue_s *q) {
setAttempt(); // if function is called, we got something, and we necessarily need more transmissions for MI types...
+ q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true);
+ q->iv->radioStatistics.retransmits++;
+ q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
if(*mSerialDebug) {
- DPRINT_IVID(DBG_WARN, q->iv->id);
+ DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("resend request ("));
DBGPRINT(String(q->attempts));
DBGPRINT(F(" attempts left): 0x"));
DBGHEXLN(q->cmd);
}
-
- q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true);
- q->iv->radioStatistics.retransmits++;
-
- q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
- mIsRetransmit = false;
+ //mIsRetransmit = false;
}
void miStsConsolidate(const queue_s *q, uint8_t stschan, record_t<> *rec, uint8_t uState, uint8_t uEnum, uint8_t lState = 0, uint8_t lEnum = 0) {
@@ -953,11 +951,6 @@ class Communication : public CommQueue<> {
void miComplete(Inverter<> *iv) {
- if (*mSerialDebug) {
- DPRINT_IVID(DBG_INFO, iv->id);
- DBGPRINTLN(F("got all data msgs"));
- }
-
if (iv->mGetLossInterval >= AHOY_GET_LOSS_INTERVAL) { // initially mIvRxCnt = mIvTxCnt = 0
iv->mGetLossInterval = 1;
iv->radioStatistics.ivSent = iv->mIvRxCnt + iv->mDtuTxCnt; // iv->mIvRxCnt is the nr. of additional answer frames, default we expect one frame per request
@@ -966,10 +959,16 @@ class Communication : public CommQueue<> {
iv->radioStatistics.dtuSent = iv->mDtuTxCnt;
if (*mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id);
- DBGPRINTLN("DTU loss: " +
- String (iv->radioStatistics.ivLoss) + "/" +
- String (iv->radioStatistics.ivSent) + " frames for " +
- String (iv->radioStatistics.dtuSent) + " requests");
+ DBGPRINT(F("DTU loss: ") +
+ String (iv->radioStatistics.ivLoss) + F("/") +
+ String (iv->radioStatistics.ivSent) + F(" frames for ") +
+ String (iv->radioStatistics.dtuSent) + F(" requests"));
+ if(iv->mAckCount) {
+ DBGPRINT(F(". ACKs: "));
+ DBGPRINTLN(String(iv->mAckCount));
+ iv->mAckCount = 0;
+ } else
+ DBGPRINTLN(F(""));
}
iv->mIvRxCnt = 0; // start new interval, iVRxCnt is abused to collect additional possible frames
iv->mIvTxCnt = 0; // start new interval, iVTxCnt is abused to collect nr. of unanswered requests
diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h
index 8fc4f71f..6ba92774 100644
--- a/src/hm/hmDefines.h
+++ b/src/hm/hmDefines.h
@@ -89,7 +89,7 @@ const uint8_t duration_reserve[2] = {65, 115};
#define LIMIT_FAST_IV 85 // time limit to qualify an inverter as very fast answering inverter
#define LIMIT_VERYFAST_IV 70 // time limit to qualify an inverter as very fast answering inverter
#define LIMIT_FAST_IV_MI 35 // time limit to qualify a MI type inverter as fast answering inverter
-#define LIMIT_VERYFAST_IV_MI 22 // time limit to qualify a MI type inverter as very fast answering inverter
+#define LIMIT_VERYFAST_IV_MI 25 // time limit to qualify a MI type inverter as very fast answering inverter
#define RETRIES_FAST_IV 12 // how often shall a message be automatically retransmitted by the nRF (fast answering inverter)
#define RETRIES_VERYFAST_IV 9 // how often shall a message be automatically retransmitted by the nRF (very fast answering inverter)
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index 51cb0d6d..b6dc93fa 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -132,7 +132,6 @@ class Inverter {
record_t recordAlarm; // structure for alarm values
InverterStatus status = InverterStatus::OFF; // indicates the current inverter status
std::array lastAlarm; // holds last 10 alarms
- uint8_t rxOffset = 0; // holds the default channel offset between tx and rx channel (nRF only)
int8_t rssi = 0; // RSSI
uint16_t alarmCnt = 0; // counts the total number of occurred alarms
uint16_t alarmLastId = 0; // lastId which was received
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index 09500826..b01df277 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -152,31 +152,22 @@ class HmRadio : public Radio {
if(tx_ok)
mLastIv->mAckCount++;
- //#ifdef DYNAMIC_OFFSET
- mRxChIdx = (mTxChIdx + mLastIv->rxOffset) % RF_CHANNELS;
- /*#else
- mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
- #endif*/
+ rxOffset = mLastIv->ivGen == IV_HM ? 3 : 2; // holds the default channel offset between tx and rx channel (nRF only)
+ mRxChIdx = (mTxChIdx + rxOffset) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening();
mTimeslotStart = millis();
tempRxChIdx = mRxChIdx; // might be better to start off with one channel less?
mRxPendular = false;
- mNRFloopChannels = (mLastIv->ivGen == IV_MI);
-
- //innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME;
- //innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_LISTEN_MIN : 4;
- //innerLoopTimeout = (mLastIv->mIsSingleframeReq || mLastIv->ivGen == IV_MI) ? DURATION_LISTEN_MIN : DURATION_TXFRAME;
+ mNRFloopChannels = (mLastIv->mCmd == MI_REQ_CH1 || mLastIv->mCmd == MI_REQ_CH1);
innerLoopTimeout = DURATION_LISTEN_MIN;
}
if(rx_ready) {
if (getReceived()) { // check what we got, returns true for last package or success for single frame request
mNRFisInRX = false;
- rx_ready = false;
mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first end his transmissions
mNrf24->stopListening();
- return false;
} else {
innerLoopTimeout = DURATION_LISTEN_MIN;
mTimeslotStart = millis();
@@ -188,7 +179,6 @@ class HmRadio : public Radio {
} else
mRxChIdx = tempRxChIdx;
}
- return true;
}
rx_ready = false; // reset
return mNRFisInRX;
@@ -317,9 +307,11 @@ class HmRadio : public Radio {
if (p.packet[0] != 0x00) {
if(!checkIvSerial(p.packet, mLastIv)) {
- DPRINT(DBG_WARN, "RX other inverter ");
+ DPRINT(DBG_WARN, F("RX other inverter "));
if(!*mPrivacyMode)
ah::dumpBuf(p.packet, p.len);
+ else
+ DBGPRINTLN(F(""));
} else {
mLastIv->mGotFragment = true;
mBufCtrl.push(p);
@@ -331,14 +323,6 @@ class HmRadio : public Radio {
if(isLastPackage)
setExpectedFrames(p.packet[9] - ALL_FRAMES);
- #ifdef DYNAMIC_OFFSET
- if((p.packet[9] == 1) && (p.millis < DURATION_ONEFRAME))
- mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + 1) % RF_CHANNELS;
- else if(mNRFloopChannels && (mLastIv->rxOffset > RF_CHANNELS)) { // unsure setting?
- mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + (isLastPackage ? mFramesExpected : p.packet[9])); // make clear it's not sure, start with one more offset
- mNRFloopChannels = false;
- }
- #endif
}
if(IV_MI == mLastIv->ivGen) {
@@ -346,10 +330,6 @@ class HmRadio : public Radio {
isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received
else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore MI status messages //#0 was p.packet[0] != 0x00 &&
isLastPackage = true; // response from dev control command
- #ifdef DYNAMIC_OFFSET
- if((p.packet[9] == 0x00) && (p.millis < DURATION_ONEFRAME))
- mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx - 1) % RF_CHANNELS;
- #endif
}
rx_ready = true; //reset in case we first read messages from other inverter or ACK zero payloads
}
@@ -385,14 +365,7 @@ class HmRadio : public Radio {
DBGPRINT(String(mRfChLst[mTxChIdx]));
DBGPRINT(F(", "));
DBGPRINT(String(mTxRetriesNext));
- //DBGPRINT(F(" retries | "));
- //#ifdef DYNAMIC_OFFSET
- DBGPRINT(F(" ret., rx offset: "));
- DBGPRINT(String(iv->rxOffset));
- DBGPRINT(F(" | "));
- /*#else
DBGPRINT(F(" ret. | "));
- #endif*/
if(*mPrintWholeTrace) {
if(*mPrivacyMode)
ah::dumpBuf(mTxBuf.data(), len, 1, 4);
@@ -415,7 +388,7 @@ class HmRadio : public Radio {
}
mNrf24->setChannel(mRfChLst[mTxChIdx]);
mNrf24->openWritingPipe(reinterpret_cast(&iv->radioId.u64));
- mNrf24->startFastWrite(mTxBuf.data(), len, false); // false = request ACK response
+ mNrf24->startFastWrite(mTxBuf.data(), len, false, true); // false (3) = request ACK response; true (4) reset CE to high after transmission
mMillis = millis();
mLastIv = iv;
@@ -455,6 +428,7 @@ class HmRadio : public Radio {
bool mRxPendular = false;
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15);
+ uint8_t rxOffset = 3; // holds the channel offset between tx and rx channel used for actual inverter
std::unique_ptr mSpi;
std::unique_ptr mNrf24;
diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h
index 22318347..7e79f30a 100644
--- a/src/hm/hmSystem.h
+++ b/src/hm/hmSystem.h
@@ -93,16 +93,8 @@ class HmSystem {
DBGPRINTLN(String(iv->config->serial.u64, HEX));
- if((iv->config->serial.b[5] == 0x10) && ((iv->config->serial.b[4] & 0x03) == 0x01))
+ if(IV_MI == iv->ivGen)
DPRINTLN(DBG_WARN, F("MI Inverter, has some restrictions!"));
-
- #ifdef DYNAMIC_OFFSET
- iv->rxOffset = (iv->ivGen == IV_HM) ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
- #else
- //iv->rxOffset = ((iv->ivGen == IV_HM) && (iv->type == INV_TYPE_4CH)) ? 3 : 2;
- iv->rxOffset = (iv->ivGen == IV_HM) ? 3 : 2;
- #endif
-
cb(iv);
}
From b8cc3bcfe9cb4c7f614b26c7b4389fae9ae9d148 Mon Sep 17 00:00:00 2001
From: Frank
Date: Fri, 9 Feb 2024 16:37:08 +0100
Subject: [PATCH 41/79] Add 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 689fbb06..1e79f8bf 100644
--- a/src/web/lang.json
+++ b/src/web/lang.json
@@ -290,8 +290,8 @@
},
{
"token": "INV_RESET_MIDNIGHT",
- "en": "Reset values and YieldDay at midnight",
- "de": "Werte und Gesamtertrag um Mitternacht zurücksetzen"
+ "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)"
},
{
"token": "INV_PAUSE_SUNSET",
From d5cecbb5b017349ece28431ed9b44ad724887039 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sat, 10 Feb 2024 13:03:29 +0100
Subject: [PATCH 42/79] 0.8.78 * fixed protection
---
src/CHANGES.md | 2 +-
src/app.h | 12 +++-----
src/appInterface.h | 5 ++-
src/defines.h | 2 +-
src/web/Protection.h | 72 +++++++++++++++++++++-----------------------
src/web/RestApi.h | 6 ++--
src/web/web.h | 6 ++--
7 files changed, 49 insertions(+), 56 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index ea067bd2..ce0adc6b 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,6 +1,6 @@
# Development Changes
-## 0.8.78 - 2024-02-09
+## 0.8.78 - 2024-02-10
* finalized API token access #1415
## 0.8.77 - 2024-02-08
diff --git a/src/app.h b/src/app.h
index 1a4e780d..b16d7aeb 100644
--- a/src/app.h
+++ b/src/app.h
@@ -247,8 +247,8 @@ class app : public IApp, public ah::Scheduler {
#endif
}
- void lock(void) override {
- mProtection->lock();
+ void lock(bool fromWeb) override {
+ mProtection->lock(fromWeb);
}
char *unlock(const char *clientIp, bool loginFromWeb) override {
@@ -259,12 +259,8 @@ class app : public IApp, public ah::Scheduler {
mProtection->resetLockTimeout();
}
- bool isProtected(void) const override {
- return mProtection->isProtected();
- }
-
- bool isProtected(const char *token, bool askedFromWeb) const override {
- return mProtection->isProtected(token, askedFromWeb);
+ bool isProtected(const char *clientIp, const char *token, bool askedFromWeb) const override {
+ return mProtection->isProtected(clientIp, token, askedFromWeb);
}
bool getNrfEnabled(void) override {
diff --git a/src/appInterface.h b/src/appInterface.h
index f0d2b2a0..536455e0 100644
--- a/src/appInterface.h
+++ b/src/appInterface.h
@@ -61,11 +61,10 @@ class IApp {
virtual uint32_t getMqttRxCnt() = 0;
virtual uint32_t getMqttTxCnt() = 0;
- virtual void lock(void) = 0;
+ virtual void lock(bool fromWeb) = 0;
virtual char *unlock(const char *clientIp, bool loginFromWeb) = 0;
virtual void resetLockTimeout(void) = 0;
- virtual bool isProtected(void) const = 0;
- virtual bool isProtected(const char *token, bool askedFromWeb) const = 0;
+ 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 uint16_t getHistoryMaxDay() = 0;
diff --git a/src/defines.h b/src/defines.h
index 46be8dac..ab685698 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 77
+#define VERSION_PATCH 78
//-------------------------------------
typedef struct {
diff --git a/src/web/Protection.h b/src/web/Protection.h
index b9eeef95..7c1ff71e 100644
--- a/src/web/Protection.h
+++ b/src/web/Protection.h
@@ -18,12 +18,9 @@ class Protection {
explicit Protection(const char *pwd) {
mPwd = pwd;
mLogoutTimeout = 0;
- mLoginIp.fill(0);
+ mWebIp.fill(0);
+ mApiIp.fill(0);
mToken.fill(0);
-
- // no password set - unlock
- if(pwd[0] == '\0')
- mProtected = false;
}
public:
@@ -40,27 +37,30 @@ class Protection {
// auto logout
if(0 != mLogoutTimeout) {
if (0 == --mLogoutTimeout) {
- if(mPwd[0] != '\0') {
- mProtected = true;
- }
+ if(mPwd[0] != '\0')
+ lock(false);
}
}
}
- void lock(void) {
- mProtected = true;
- mLoginIp.fill(0);
+ void lock(bool fromWeb) {
+ mWebIp.fill(0);
+ if(fromWeb)
+ return;
+
+ mApiIp.fill(0);
mToken.fill(0);
}
char *unlock(const char *clientIp, bool loginFromWeb) {
mLogoutTimeout = LOGOUT_TIMEOUT;
- mProtected = false;
if(loginFromWeb)
- ah::ip2Arr(static_cast(mLoginIp.data()), clientIp);
- else
+ ah::ip2Arr(static_cast(mWebIp.data()), clientIp);
+ else {
+ ah::ip2Arr(static_cast(mApiIp.data()), clientIp);
genToken();
+ }
return reinterpret_cast(mToken.data());
}
@@ -70,30 +70,19 @@ class Protection {
mLogoutTimeout = LOGOUT_TIMEOUT;
}
- bool isProtected(void) const {
- return mProtected;
- }
-
- bool isProtected(const char *token, bool askedFromWeb) const { // token == clientIp
- if(mProtected)
- return true;
-
- if(mPwd[0] == '\0')
+ bool isProtected(const char *clientIp, const char *token, bool askedFromWeb) const {
+ if(mPwd[0] == '\0') // no password set
return false;
- if(askedFromWeb) { // check IP address
- std::array ip;
- ah::ip2Arr(static_cast(ip.data()), token);
- for(uint8_t i = 0; i < 4; i++) {
- if(mLoginIp[i] != ip[i])
- return true;
- }
- } else { // API call - check token
- if(0 == mToken[0]) // token is zero
- return true;
+ if(askedFromWeb)
+ return !isIdentical(clientIp, mWebIp);
+
+ // API call
+ if(0 == mToken[0]) // token is zero, from WebUi (logged in)
+ return !isIdentical(clientIp, mWebIp);
+ if(isIdentical(clientIp, mApiIp))
return (0 != strncmp(token, mToken.data(), 16));
- }
return false;
}
@@ -106,8 +95,18 @@ class Protection {
if(mToken[i] < 10)
mToken[i] += 0x30; // convert to ascii number 1-9 (zero isn't allowed)
else
- mToken[i] += 0x37; // convert to ascii upper case character
+ mToken[i] += 0x37; // convert to ascii upper case character A-Z
+ }
+ }
+
+ bool isIdentical(const char *clientIp, const std::array cmp) const {
+ std::array ip;
+ ah::ip2Arr(static_cast(ip.data()), clientIp);
+ for(uint8_t i = 0; i < 4; i++) {
+ if(cmp[i] != ip[i])
+ return false;
}
+ return true;
}
protected:
@@ -115,9 +114,8 @@ class Protection {
private:
const char *mPwd;
- bool mProtected = true;
uint16_t mLogoutTimeout = 0;
- std::array mLoginIp;
+ std::array mWebIp, mApiIp;
std::array mToken;
};
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index 5103f3ba..53b604b5 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -266,7 +266,7 @@ class RestApi {
obj[F("modules")] = String(mApp->getVersionModules());
obj[F("build")] = String(AUTO_GIT_HASH);
obj[F("env")] = String(ENV_NAME);
- obj[F("menu_prot")] = mApp->isProtected(request->client()->remoteIP().toString().c_str(), true);
+ obj[F("menu_prot")] = mApp->isProtected(request->client()->remoteIP().toString().c_str(), "", true);
obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask );
obj[F("menu_protEn")] = (bool) (mConfig->sys.adminPwd[0] != '\0');
obj[F("cst_lnk")] = String(mConfig->plugin.customLink);
@@ -844,7 +844,7 @@ class RestApi {
if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
const char* token = jsonIn["token"];
- if(mApp->isProtected(token, false)) {
+ if(mApp->isProtected(clientIP, token, false)) {
jsonOut[F("error")] = F(IS_PROTECTED);
return false;
}
@@ -897,7 +897,7 @@ class RestApi {
if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
const char* token = jsonIn["token"];
- if(mApp->isProtected(token, false)) {
+ if(mApp->isProtected(clientIP, token, false)) {
jsonOut[F("error")] = F(IS_PROTECTED);
return false;
}
diff --git a/src/web/web.h b/src/web/web.h
index 7ed41f92..692dd779 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -227,7 +227,7 @@ class Web {
}
void checkProtection(AsyncWebServerRequest *request) {
- if(mApp->isProtected(request->client()->remoteIP().toString().c_str(), true)) {
+ if(mApp->isProtected(request->client()->remoteIP().toString().c_str(), "", true)) {
checkRedirect(request);
return;
}
@@ -328,7 +328,7 @@ class Web {
DPRINTLN(DBG_VERBOSE, F("onLogout"));
checkProtection(request);
- mApp->lock();
+ mApp->lock(true);
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), system_html, system_html_len);
response->addHeader(F("Content-Encoding"), "gzip");
@@ -455,7 +455,7 @@ class Web {
// protection
if (request->arg("adminpwd") != "{PWD}") {
request->arg("adminpwd").toCharArray(mConfig->sys.adminPwd, PWD_LEN);
- mApp->lock();
+ mApp->lock(false);
}
mConfig->sys.protectionMask = 0x0000;
for (uint8_t i = 0; i < 7; i++) {
From a51a7612155cb7d13f15c4cb4f9b6e33ac894229 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 11 Feb 2024 00:07:20 +0100
Subject: [PATCH 43/79] 0.8.78 * finalized API token access #1415
---
src/platformio.ini | 2 +-
src/web/Protection.h | 16 ++++++-------
src/web/RestApi.h | 41 ++++++++++++++++++---------------
src/web/html/index.html | 23 ++++++++----------
src/web/html/setup.html | 28 ++++++++++------------
src/web/html/visualization.html | 18 ++++++++-------
6 files changed, 64 insertions(+), 64 deletions(-)
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/web/Protection.h b/src/web/Protection.h
index 7c1ff71e..82e4be49 100644
--- a/src/web/Protection.h
+++ b/src/web/Protection.h
@@ -33,8 +33,7 @@ class Protection {
return mInstance;
}
- void tickSecond() {
- // auto logout
+ void tickSecond() { // auto logout
if(0 != mLogoutTimeout) {
if (0 == --mLogoutTimeout) {
if(mPwd[0] != '\0')
@@ -77,8 +76,10 @@ class Protection {
if(askedFromWeb)
return !isIdentical(clientIp, mWebIp);
- // API call
- if(0 == mToken[0]) // token is zero, from WebUi (logged in)
+ if(nullptr == token)
+ return true;
+
+ if('*' == token[0]) // call from WebUI
return !isIdentical(clientIp, mWebIp);
if(isIdentical(clientIp, mApiIp))
@@ -92,10 +93,9 @@ class Protection {
mToken.fill(0);
for(uint8_t i = 0; i < 16; i++) {
mToken[i] = random(1, 35);
- if(mToken[i] < 10)
- mToken[i] += 0x30; // convert to ascii number 1-9 (zero isn't allowed)
- else
- mToken[i] += 0x37; // convert to ascii upper case character A-Z
+ // convert to ascii number 1-9 (zero isn't allowed) or upper
+ // case character A-Z
+ mToken[i] += (mToken[i] < 10) ? 0x30 : 0x37;
}
}
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index 53b604b5..fadd7277 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -841,15 +841,8 @@ class RestApi {
return true;
}
- if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
- if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
- const char* token = jsonIn["token"];
- if(mApp->isProtected(clientIP, token, false)) {
- jsonOut[F("error")] = F(IS_PROTECTED);
- return false;
- }
- }
- }
+ if(isProtected(jsonIn, jsonOut, clientIP))
+ return false;
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
bool accepted = true;
@@ -894,15 +887,8 @@ class RestApi {
}
bool setSetup(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
- if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
- if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
- const char* token = jsonIn["token"];
- if(mApp->isProtected(clientIP, token, false)) {
- jsonOut[F("error")] = F(IS_PROTECTED);
- return false;
- }
- }
- }
+ if(isProtected(jsonIn, jsonOut, clientIP))
+ return false;
#if !defined(ETHERNET)
if(F("scan_wifi") == jsonIn[F("cmd")])
@@ -951,6 +937,25 @@ class RestApi {
return true;
}
+ bool isProtected(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
+ if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
+ if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
+ const char* token = nullptr;
+ if(jsonIn.containsKey(F("token")))
+ token = jsonIn["token"];
+
+ if(!mApp->isProtected(clientIP, token, false))
+ return false;
+
+ jsonOut[F("error")] = F(IS_PROTECTED);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private:
IApp *mApp = nullptr;
HMSYSTEM *mSys = nullptr;
HmRadio<> *mRadioNrf = nullptr;
diff --git a/src/web/html/index.html b/src/web/html/index.html
index e7b7afc4..2611db5b 100644
--- a/src/web/html/index.html
+++ b/src/web/html/index.html
@@ -41,27 +41,24 @@
var release = null;
function apiCb(obj) {
- var e = document.getElementById("apiResult");
+ var e = document.getElementById("apiResult")
if(obj.success) {
- e.innerHTML = " {#COMMAND_EXE}";
- getAjax("/api/index", parse);
- }
- else
- e.innerHTML = " {#ERROR}: " + obj.error;
+ e.innerHTML = " {#COMMAND_EXE}"
+ getAjax("/api/index", parse)
+ } else
+ e.innerHTML = " {#ERROR}: " + obj.error
}
function setTime() {
- var date = new Date();
- var obj = new Object();
- obj.cmd = "set_time";
- obj.val = parseInt(date.getTime() / 1000);
- getAjax("/api/setup", apiCb, "POST", JSON.stringify(obj));
+ var date = new Date()
+ var obj = {cmd: "set_time", token: "*", val: parseInt(date.getTime() / 1000)}
+ getAjax("/api/setup", apiCb, "POST", JSON.stringify(obj))
}
function parseGeneric(obj) {
if(exeOnce)
- parseESP(obj);
- parseRssi(obj);
+ parseESP(obj)
+ parseRssi(obj)
}
function parseSys(obj) {
diff --git a/src/web/html/setup.html b/src/web/html/setup.html
index dec62830..4859fe34 100644
--- a/src/web/html/setup.html
+++ b/src/web/html/setup.html
@@ -559,31 +559,26 @@
}
function setTime() {
- var date = new Date();
- var obj = new Object();
- obj.cmd = "set_time";
- obj.val = parseInt(date.getTime() / 1000);
- getAjax("/api/setup", apiCbNtp, "POST", JSON.stringify(obj));
- setTimeout(function() {getAjax('/api/index', apiCbNtp2)}, 2000);
+ var date = new Date()
+ var obj = {cmd: "set_time", token: "*", val: parseInt(date.getTime() / 1000)}
+ getAjax("/api/setup", apiCbNtp, "POST", JSON.stringify(obj))
+ setTimeout(function() {getAjax('/api/index', apiCbNtp2)}, 2000)
}
function scan() {
- var obj = new Object();
- obj.cmd = "scan_wifi";
+ 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 = new Object();
- obj.cmd = "sync_ntp";
- getAjax("/api/setup", apiCbNtp, "POST", JSON.stringify(obj));
- setTimeout(function() {getAjax('/api/index', apiCbNtp2)}, 2000);
+ var obj = {cmd: "sync_ntp", token: "*"}
+ getAjax("/api/setup", apiCbNtp, "POST", JSON.stringify(obj))
+ setTimeout(function() {getAjax('/api/index', apiCbNtp2)}, 2000)
}
function sendDiscoveryConfig() {
- var obj = new Object();
- obj.cmd = "discovery_cfg";
+ var obj = {cmd: "discovery_cfg", token: "*"}
getAjax("/api/setup", apiCbMqtt, "POST", JSON.stringify(obj));
}
@@ -837,8 +832,9 @@
function ivSave() {
var o = new Object();
- o.cmd = "save_iv";
- o.id = obj.id;
+ o.cmd = "save_iv"
+ o.token = "*"
+ o.id = obj.id
o.ser = parseInt(document.getElementsByName("ser")[0].value, 16);
o.name = document.getElementsByName("name")[0].value;
o.en = document.getElementsByName("enable")[0].checked;
diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html
index 3b90a028..1ce4e264 100644
--- a/src/web/html/visualization.html
+++ b/src/web/html/visualization.html
@@ -454,18 +454,20 @@
val = 100;
var obj = new Object();
- obj.id = id;
- obj.cmd = cmd;
- obj.val = Math.round(val*10);
- getAjax("/api/ctrl", ctrlCb, "POST", JSON.stringify(obj));
+ obj.id = id
+ obj.token = "*"
+ obj.cmd = cmd
+ obj.val = Math.round(val*10)
+ getAjax("/api/ctrl", ctrlCb, "POST", JSON.stringify(obj))
}
function applyCtrl(id, cmd, val=0) {
var obj = new Object();
- obj.id = id;
- obj.cmd = cmd;
- obj.val = val;
- getAjax("/api/ctrl", ctrlCb2, "POST", JSON.stringify(obj));
+ obj.id = id
+ obj.token = "*"
+ obj.cmd = cmd
+ obj.val = val
+ getAjax("/api/ctrl", ctrlCb2, "POST", JSON.stringify(obj))
}
function ctrlCb(obj) {
From e73e31b1ccf39f05b85c6129f3f285c9ffcb91f1 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 11 Feb 2024 00:17:33 +0100
Subject: [PATCH 44/79] 0.8.78 * possible fix of MqTT fix "total values are
sent to often" #1421
---
src/CHANGES.md | 1 +
src/publisher/pubMqttIvData.h | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index ce0adc6b..dab588ed 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -2,6 +2,7 @@
## 0.8.78 - 2024-02-10
* finalized API token access #1415
+* possible fix of MqTT fix "total values are sent to often" #1421
## 0.8.77 - 2024-02-08
* merge PR: BugFix: ACK #1414
diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h
index 5f38768d..06f8e629 100644
--- a/src/publisher/pubMqttIvData.h
+++ b/src/publisher/pubMqttIvData.h
@@ -246,7 +246,7 @@ class PubMqttIvData {
mPos++;
} else {
mSendList->pop();
- mPos = 0;
+ mSendTotals = false;
mState = IDLE;
}
}
From 493c583b79fea184aeb899b6db052ee58e24d134 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 11 Feb 2024 00:21:47 +0100
Subject: [PATCH 45/79] 0.8.78 * removed `switchCycle` from `hmsRadio.h` #1412
---
src/CHANGES.md | 1 +
src/hms/hmsRadio.h | 12 ++++++------
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index dab588ed..be5e011c 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -3,6 +3,7 @@
## 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
## 0.8.77 - 2024-02-08
* merge PR: BugFix: ACK #1414
diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h
index cb181b0b..d074442b 100644
--- a/src/hms/hmsRadio.h
+++ b/src/hms/hmsRadio.h
@@ -9,7 +9,7 @@
#include "cmt2300a.h"
#include "../hm/radio.h"
-#define CMT_SWITCH_CHANNEL_CYCLE 5
+//#define CMT_SWITCH_CHANNEL_CYCLE 5
template
class CmtRadio : public Radio {
@@ -150,9 +150,9 @@ class CmtRadio : public Radio {
}
inline void sendSwitchChCmd(Inverter<> *iv, uint8_t ch) {
- if(CMT_SWITCH_CHANNEL_CYCLE > ++mSwitchCycle)
- return;
- mSwitchCycle = 0;
+ //if(CMT_SWITCH_CHANNEL_CYCLE > ++mSwitchCycle)
+ // return;
+ //mSwitchCycle = 0;
/** ch:
* 0x00: 860.00 MHz
@@ -176,7 +176,7 @@ class CmtRadio : public Radio {
packet_t p;
p.millis = millis() - mMillis;
if(CmtStatus::SUCCESS == mCmt.getRx(p.packet, &p.len, 28, &p.rssi)) {
- mSwitchCycle = 0;
+ //mSwitchCycle = 0;
p.ch = 0; // not used for CMT inverters
mBufCtrl.push(p);
}
@@ -191,7 +191,7 @@ class CmtRadio : public Radio {
bool mCmtAvail = false;
bool mRqstGetRx = false;
uint32_t mMillis = 0;
- uint8_t mSwitchCycle = 0;
+ //uint8_t mSwitchCycle = 0;
};
#endif /*__HMS_RADIO_H__*/
From c2902737901d59895306fa6a3239193b036d3c1f Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 11 Feb 2024 01:07:07 +0100
Subject: [PATCH 46/79] 0.8.78 * merge PR: Add hint to INV_RESET_MIDNIGHT resp.
INV_PAUSE_DURING_NIGHT #1418 * merge PR: simplify rxOffset logic #1417 * code
quality improvments
---
src/CHANGES.md | 3 +++
src/eth/ahoyeth.h | 2 +-
src/utils/helper.cpp | 6 ++----
src/utils/syslog.cpp | 3 +--
src/web/html/colorBright.css | 6 +++---
src/web/html/colorDark.css | 16 ++++++++--------
src/web/html/style.css | 21 +++++++++++----------
7 files changed, 29 insertions(+), 28 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index be5e011c..aa63153f 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -4,6 +4,9 @@
* 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
diff --git a/src/eth/ahoyeth.h b/src/eth/ahoyeth.h
index ef8d0751..ebd91c67 100644
--- a/src/eth/ahoyeth.h
+++ b/src/eth/ahoyeth.h
@@ -49,7 +49,7 @@ class ahoyeth {
#if defined(CONFIG_IDF_TARGET_ESP32S3)
EthSpi mEthSpi;
#endif
- settings_t *mConfig = NULL;
+ settings_t *mConfig = nullptr;
uint32_t *mUtcTimestamp;
AsyncUDP mUdp; // for time server
diff --git a/src/utils/helper.cpp b/src/utils/helper.cpp
index b3f53a23..24a4d9ee 100644
--- a/src/utils/helper.cpp
+++ b/src/utils/helper.cpp
@@ -72,11 +72,10 @@ namespace ah {
String getTimeStrMs(uint64_t t) {
char str[13];
- uint16_t m;
if(0 == t)
sprintf(str, "n/a");
else {
- m = t % 1000;
+ uint16_t m = t % 1000;
t = t / 1000;
sprintf(str, "%02d:%02d:%02d.%03d", hour(t), minute(t), second(t), m);
}
@@ -86,14 +85,13 @@ namespace ah {
uint64_t Serial2u64(const char *val) {
char tmp[3];
uint64_t ret = 0ULL;
- uint64_t u64;
memset(tmp, 0, 3);
for(uint8_t i = 0; i < 6; i++) {
tmp[0] = val[i*2];
tmp[1] = val[i*2 + 1];
if((tmp[0] == '\0') || (tmp[1] == '\0'))
break;
- u64 = strtol(tmp, NULL, 16);
+ uint64_t u64 = strtol(tmp, NULL, 16);
ret |= (u64 << ((5-i) << 3));
}
return ret;
diff --git a/src/utils/syslog.cpp b/src/utils/syslog.cpp
index c251e899..d02e25ed 100644
--- a/src/utils/syslog.cpp
+++ b/src/utils/syslog.cpp
@@ -68,12 +68,11 @@ void DbgSyslog::syslogCb (String msg)
// Send mSyslogBuffer in chunks because mSyslogBuffer is larger than syslog packet size
int packetStart = 0;
int packetSize = 122; // syslog payload depends also on hostname and app
- char saveChar;
if (isEolFound) {
mSyslogBuffer[mSyslogBufFill-2]=0; // skip \r\n
}
while(packetStart < mSyslogBufFill) {
- saveChar = mSyslogBuffer[packetStart+packetSize];
+ char saveChar = mSyslogBuffer[packetStart+packetSize];
mSyslogBuffer[packetStart+packetSize] = 0;
log(mConfig->sys.deviceName,SYSLOG_FACILITY, mSyslogSeverity, &mSyslogBuffer[packetStart]);
mSyslogBuffer[packetStart+packetSize] = saveChar;
diff --git a/src/web/html/colorBright.css b/src/web/html/colorBright.css
index 47382daa..2e676029 100644
--- a/src/web/html/colorBright.css
+++ b/src/web/html/colorBright.css
@@ -3,9 +3,9 @@
--fg: #000;
--fg2: #fff;
- --info: #0000dd;
- --warn: #ff7700;
- --success: #009900;
+ --info: #00d;
+ --warn: #f70;
+ --success: #090;
--input-bg: #eee;
--table-border: #ccc;
diff --git a/src/web/html/colorDark.css b/src/web/html/colorDark.css
index 65100721..40bd4cf3 100644
--- a/src/web/html/colorDark.css
+++ b/src/web/html/colorDark.css
@@ -4,8 +4,8 @@
--fg2: #fff;
--info: #0072c8;
- --warn: #ffaa00;
- --success: #00bb00;
+ --warn: #fa0;
+ --success: #0b0;
--input-bg: #333;
--table-border: #333;
@@ -20,14 +20,14 @@
--invalid-bg: #400;
- --total-head-title: #555511;
- --total-bg: #666622;
- --iv-head-title: #115511;
- --iv-head-bg: #226622;
+ --total-head-title: #551;
+ --total-bg: #662;
+ --iv-head-title: #151;
+ --iv-head-bg: #262;
--iv-dis-title: #333;
--iv-dis: #444;
- --ch-head-title: #112255;
- --ch-head-bg: #223366;
+ --ch-head-title: #125;
+ --ch-head-bg: #236;
--ts-head: #333;
--ts-bg: #555;
}
diff --git a/src/web/html/style.css b/src/web/html/style.css
index 395fcb99..2d6a03c7 100644
--- a/src/web/html/style.css
+++ b/src/web/html/style.css
@@ -16,11 +16,11 @@ span, li, h3, label, fieldset {
color: var(--fg);
}
-fieldset, input[type=submit], .btn {
+fieldset, input[type="submit"], .btn {
border-radius: 4px;
}
-input[type=file] {
+input[type="file"] {
width: 100%;
}
@@ -33,7 +33,7 @@ textarea {
color: var(--fg2);
}
-svg rect {fill: #0000AA;}
+svg rect {fill: #00A;}
svg.chart {
background: #f2f2f2;
border: 2px solid gray;
@@ -44,6 +44,7 @@ div.chartDivContainer {
padding: 1px;
margin: 1px;
}
+
div.chartdivContainer span {
color: var(--fg2);
}
@@ -95,7 +96,7 @@ svg.icon {
vertical-align: middle;
display: inline-block;
margin-top:-4x;
- padding: 5px 7px 5px 0px;
+ padding: 5px 7px 5px 0;
}
.icon-info {
@@ -141,7 +142,7 @@ svg.icon {
span.seperator {
width: 100%;
height: 1px;
- margin: 5px 0px 5px;
+ margin: 5px 0 5px;
background-color: #494949;
display: block;
}
@@ -391,7 +392,7 @@ th {
#footer .left {
color: #bbb;
- margin: 23px 0px 0px 25px;
+ margin: 23px 0 0 25px;
}
#footer ul {
@@ -525,7 +526,7 @@ input, select {
font-size: 13pt;
}
-input[type=text], input[type=password], select, input[type=number] {
+input[type="text"], input[type="password"], select, input[type="number"] {
width: 100%;
box-sizing: border-box;
border: 1px solid #ccc;
@@ -551,7 +552,7 @@ input.btnDel {
input.btn {
background-color: var(--primary);
color: #fff;
- border: 0px;
+ border: 0;
padding: 7px 20px 7px 20px;
margin-bottom: 10px;
text-transform: uppercase;
@@ -572,7 +573,7 @@ label {
display: inline-block;
font-size: 12pt;
padding-right: 10px;
- margin: 10px 0px 0px 15px;
+ margin: 10px 0 0 15px;
vertical-align: top;
}
@@ -601,7 +602,7 @@ div.ModPwr, div.ModName, div.YieldCor {
div.hr {
height: 1px;
border-top: 1px solid #ccc;
- margin: 10px 0px 10px;
+ margin: 10px 0 10px;
}
#note {
From 3e533e82af88471f358af3a4651a39ff8b5c0c26 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 11 Feb 2024 01:37:55 +0100
Subject: [PATCH 47/79] updated GxEPD2 to 1.5.5
---
patches/GxEPD2_SW_SPI.patch | 56 +++++++++++++------------------------
src/platformio.ini | 10 +++----
2 files changed, 25 insertions(+), 41 deletions(-)
diff --git a/patches/GxEPD2_SW_SPI.patch b/patches/GxEPD2_SW_SPI.patch
index dc3fa9ca..87458cce 100644
--- a/patches/GxEPD2_SW_SPI.patch
+++ b/patches/GxEPD2_SW_SPI.patch
@@ -1,5 +1,5 @@
diff --git a/src/GxEPD2_EPD.cpp b/src/GxEPD2_EPD.cpp
-index 8df8bef..91d7f49 100644
+index 40b1b13..d0dbdba 100644
--- a/src/GxEPD2_EPD.cpp
+++ b/src/GxEPD2_EPD.cpp
@@ -19,9 +19,9 @@
@@ -14,29 +14,25 @@ index 8df8bef..91d7f49 100644
{
_initial_write = true;
_initial_refresh = true;
-@@ -71,27 +71,30 @@ void GxEPD2_EPD::init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset
+@@ -61,7 +61,6 @@ void GxEPD2_EPD::init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset
+ digitalWrite(_cs, HIGH); // set (needed e.g. for RP2040)
+ }
+ _reset();
+- _pSPIx->begin(); // may steal _rst pin (Waveshare Pico-ePaper-2.9)
+ if (_rst >= 0)
+ {
+ digitalWrite(_rst, HIGH); // preset (less glitch for any analyzer)
+@@ -84,14 +83,30 @@ void GxEPD2_EPD::init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset
{
pinMode(_busy, INPUT);
}
-- _pSPIx->begin();
-- if (_busy == MISO) // may be overridden
-- {
-- pinMode(_busy, INPUT);
-- }
-- if (_dc == MISO) // may be overridden, TTGO T5 V2.66
-- {
-- pinMode(_dc, OUTPUT);
-- }
-- if (_cs == MISO) // may be overridden
+ if (_sck < 0) SPI.begin();
+}
+
+void GxEPD2_EPD::init(int16_t sck, int16_t mosi, uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration, bool pulldown_rst_mode)
+{
+ if ((sck >= 0) && (mosi >= 0))
- {
-- pinMode(_cs, INPUT);
-- }
++ {
+ _sck = sck;
+ _mosi = mosi;
+ digitalWrite(_sck, LOW);
@@ -58,7 +54,7 @@ index 8df8bef..91d7f49 100644
}
void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void* busy_callback_parameter)
-@@ -100,12 +103,6 @@ void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void*
+@@ -100,12 +115,6 @@ void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void*
_busy_callback_parameter = busy_callback_parameter;
}
@@ -71,7 +67,7 @@ index 8df8bef..91d7f49 100644
void GxEPD2_EPD::_reset()
{
if (_rst >= 0)
-@@ -174,115 +171,201 @@ void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time)
+@@ -174,115 +183,201 @@ void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time)
void GxEPD2_EPD::_writeCommand(uint8_t c)
{
@@ -304,21 +300,10 @@ index 8df8bef..91d7f49 100644
+ _endTransaction();
}
diff --git a/src/GxEPD2_EPD.h b/src/GxEPD2_EPD.h
-index 34c1145..c480b7d 100644
+index 3daf37e..96198c2 100644
--- a/src/GxEPD2_EPD.h
+++ b/src/GxEPD2_EPD.h
-@@ -8,6 +8,10 @@
- // Version: see library.properties
- //
- // Library: https://github.com/ZinggJM/GxEPD2
-+// To use SW SPI with GxEPD2:
-+// add the special call to the added init method BEFORE the normal init method:
-+// display.epd2.init(SW_SCK, SW_MOSI, 115200, true, 20, false); // define or replace SW_SCK, SW_MOSI
-+// display.init(115200); // needed to init upper level
-
- #ifndef _GxEPD2_EPD_H_
- #define _GxEPD2_EPD_H_
-@@ -35,6 +39,7 @@ class GxEPD2_EPD
+@@ -35,6 +35,7 @@ class GxEPD2_EPD
uint16_t w, uint16_t h, GxEPD2::Panel p, bool c, bool pu, bool fpu);
virtual void init(uint32_t serial_diag_bitrate = 0); // serial_diag_bitrate = 0 : disabled
virtual void init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration = 10, bool pulldown_rst_mode = false);
@@ -326,7 +311,7 @@ index 34c1145..c480b7d 100644
virtual void end(); // release SPI and control pins
// Support for Bitmaps (Sprites) to Controller Buffer and to Screen
virtual void clearScreen(uint8_t value) = 0; // init controller memory and screen (default white)
-@@ -97,7 +102,6 @@ class GxEPD2_EPD
+@@ -97,7 +98,6 @@ class GxEPD2_EPD
{
return (a > b ? a : b);
};
@@ -334,7 +319,7 @@ index 34c1145..c480b7d 100644
protected:
void _reset();
void _waitWhileBusy(const char* comment = 0, uint16_t busy_time = 5000);
-@@ -111,17 +115,22 @@ class GxEPD2_EPD
+@@ -111,8 +111,14 @@ class GxEPD2_EPD
void _startTransfer();
void _transfer(uint8_t value);
void _endTransfer();
@@ -346,12 +331,11 @@ index 34c1145..c480b7d 100644
+ void _readData(uint8_t* data, uint16_t n);
protected:
- int16_t _cs, _dc, _rst, _busy, _busy_level;
-+ int16_t _cs, _dc, _rst, _busy, _busy_level, _sck, _mosi;;
++ int16_t _cs, _dc, _rst, _busy, _busy_level, _sck, _mosi;
uint32_t _busy_timeout;
bool _diag_enabled, _pulldown_rst_mode;
-- SPIClass* _pSPIx;
- SPISettings _spi_settings;
- bool _initial_write, _initial_refresh;
+ SPIClass* _pSPIx;
+@@ -121,7 +127,7 @@ class GxEPD2_EPD
bool _power_is_on, _using_partial_mode, _hibernating;
bool _init_display_done;
uint16_t _reset_duration;
diff --git a/src/platformio.ini b/src/platformio.ini
index 7130bf4c..0a76a59d 100644
--- a/src/platformio.ini
+++ b/src/platformio.ini
@@ -32,7 +32,7 @@ lib_deps =
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
+ https://github.com/zinggjm/GxEPD2#1.5.5
build_flags =
-std=c++17
-std=gnu++17
@@ -201,7 +201,7 @@ lib_deps =
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
+ https://github.com/zinggjm/GxEPD2#1.5.5
build_flags = ${env.build_flags}
-D ETHERNET
-DRELEASE
@@ -224,7 +224,7 @@ lib_deps =
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
+ https://github.com/zinggjm/GxEPD2#1.5.5
build_flags = ${env.build_flags}
-D ETHERNET
-DRELEASE
@@ -418,7 +418,7 @@ lib_deps =
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
+ https://github.com/zinggjm/GxEPD2#1.5.5
upload_protocol = esp-builtin
build_flags = ${env.build_flags}
-DETHERNET
@@ -463,7 +463,7 @@ lib_deps =
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
+ https://github.com/zinggjm/GxEPD2#1.5.5
upload_protocol = esp-builtin
build_flags = ${env.build_flags}
-DETHERNET
From 315541ea51d5573a48b78c09e0e73a07b607868c Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sun, 11 Feb 2024 22:44:32 +0100
Subject: [PATCH 48/79] 0.8.79 * fix `opendtufusion` build (started only once
USB-console was connected) * code quality improvments
---
patches/GxEPD2_SW_SPI.patch | 56 ++++++++++++++++++++++++-------------
src/CHANGES.md | 4 +++
src/defines.h | 2 +-
src/hm/hmRadio.h | 2 +-
src/platformio.ini | 12 ++++----
5 files changed, 48 insertions(+), 28 deletions(-)
diff --git a/patches/GxEPD2_SW_SPI.patch b/patches/GxEPD2_SW_SPI.patch
index 87458cce..dc3fa9ca 100644
--- a/patches/GxEPD2_SW_SPI.patch
+++ b/patches/GxEPD2_SW_SPI.patch
@@ -1,5 +1,5 @@
diff --git a/src/GxEPD2_EPD.cpp b/src/GxEPD2_EPD.cpp
-index 40b1b13..d0dbdba 100644
+index 8df8bef..91d7f49 100644
--- a/src/GxEPD2_EPD.cpp
+++ b/src/GxEPD2_EPD.cpp
@@ -19,9 +19,9 @@
@@ -14,25 +14,29 @@ index 40b1b13..d0dbdba 100644
{
_initial_write = true;
_initial_refresh = true;
-@@ -61,7 +61,6 @@ void GxEPD2_EPD::init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset
- digitalWrite(_cs, HIGH); // set (needed e.g. for RP2040)
- }
- _reset();
-- _pSPIx->begin(); // may steal _rst pin (Waveshare Pico-ePaper-2.9)
- if (_rst >= 0)
- {
- digitalWrite(_rst, HIGH); // preset (less glitch for any analyzer)
-@@ -84,14 +83,30 @@ void GxEPD2_EPD::init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset
+@@ -71,27 +71,30 @@ void GxEPD2_EPD::init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset
{
pinMode(_busy, INPUT);
}
+- _pSPIx->begin();
+- if (_busy == MISO) // may be overridden
+- {
+- pinMode(_busy, INPUT);
+- }
+- if (_dc == MISO) // may be overridden, TTGO T5 V2.66
+- {
+- pinMode(_dc, OUTPUT);
+- }
+- if (_cs == MISO) // may be overridden
+ if (_sck < 0) SPI.begin();
+}
+
+void GxEPD2_EPD::init(int16_t sck, int16_t mosi, uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration, bool pulldown_rst_mode)
+{
+ if ((sck >= 0) && (mosi >= 0))
-+ {
+ {
+- pinMode(_cs, INPUT);
+- }
+ _sck = sck;
+ _mosi = mosi;
+ digitalWrite(_sck, LOW);
@@ -54,7 +58,7 @@ index 40b1b13..d0dbdba 100644
}
void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void* busy_callback_parameter)
-@@ -100,12 +115,6 @@ void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void*
+@@ -100,12 +103,6 @@ void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void*
_busy_callback_parameter = busy_callback_parameter;
}
@@ -67,7 +71,7 @@ index 40b1b13..d0dbdba 100644
void GxEPD2_EPD::_reset()
{
if (_rst >= 0)
-@@ -174,115 +183,201 @@ void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time)
+@@ -174,115 +171,201 @@ void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time)
void GxEPD2_EPD::_writeCommand(uint8_t c)
{
@@ -300,10 +304,21 @@ index 40b1b13..d0dbdba 100644
+ _endTransaction();
}
diff --git a/src/GxEPD2_EPD.h b/src/GxEPD2_EPD.h
-index 3daf37e..96198c2 100644
+index 34c1145..c480b7d 100644
--- a/src/GxEPD2_EPD.h
+++ b/src/GxEPD2_EPD.h
-@@ -35,6 +35,7 @@ class GxEPD2_EPD
+@@ -8,6 +8,10 @@
+ // Version: see library.properties
+ //
+ // Library: https://github.com/ZinggJM/GxEPD2
++// To use SW SPI with GxEPD2:
++// add the special call to the added init method BEFORE the normal init method:
++// display.epd2.init(SW_SCK, SW_MOSI, 115200, true, 20, false); // define or replace SW_SCK, SW_MOSI
++// display.init(115200); // needed to init upper level
+
+ #ifndef _GxEPD2_EPD_H_
+ #define _GxEPD2_EPD_H_
+@@ -35,6 +39,7 @@ class GxEPD2_EPD
uint16_t w, uint16_t h, GxEPD2::Panel p, bool c, bool pu, bool fpu);
virtual void init(uint32_t serial_diag_bitrate = 0); // serial_diag_bitrate = 0 : disabled
virtual void init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration = 10, bool pulldown_rst_mode = false);
@@ -311,7 +326,7 @@ index 3daf37e..96198c2 100644
virtual void end(); // release SPI and control pins
// Support for Bitmaps (Sprites) to Controller Buffer and to Screen
virtual void clearScreen(uint8_t value) = 0; // init controller memory and screen (default white)
-@@ -97,7 +98,6 @@ class GxEPD2_EPD
+@@ -97,7 +102,6 @@ class GxEPD2_EPD
{
return (a > b ? a : b);
};
@@ -319,7 +334,7 @@ index 3daf37e..96198c2 100644
protected:
void _reset();
void _waitWhileBusy(const char* comment = 0, uint16_t busy_time = 5000);
-@@ -111,8 +111,14 @@ class GxEPD2_EPD
+@@ -111,17 +115,22 @@ class GxEPD2_EPD
void _startTransfer();
void _transfer(uint8_t value);
void _endTransfer();
@@ -331,11 +346,12 @@ index 3daf37e..96198c2 100644
+ void _readData(uint8_t* data, uint16_t n);
protected:
- int16_t _cs, _dc, _rst, _busy, _busy_level;
-+ int16_t _cs, _dc, _rst, _busy, _busy_level, _sck, _mosi;
++ int16_t _cs, _dc, _rst, _busy, _busy_level, _sck, _mosi;;
uint32_t _busy_timeout;
bool _diag_enabled, _pulldown_rst_mode;
- SPIClass* _pSPIx;
-@@ -121,7 +127,7 @@ class GxEPD2_EPD
+- SPIClass* _pSPIx;
+ SPISettings _spi_settings;
+ bool _initial_write, _initial_refresh;
bool _power_is_on, _using_partial_mode, _hibernating;
bool _init_display_done;
uint16_t _reset_duration;
diff --git a/src/CHANGES.md b/src/CHANGES.md
index aa63153f..dff1bb30 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,9 @@
# Development Changes
+## 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
diff --git a/src/defines.h b/src/defines.h
index ab685698..40084c47 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 78
+#define VERSION_PATCH 79
//-------------------------------------
typedef struct {
diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index b01df277..d1d24364 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -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 || mLastIv->mCmd == MI_REQ_CH1);
+ mNRFloopChannels = (mLastIv->mCmd == MI_REQ_CH1);
innerLoopTimeout = DURATION_LISTEN_MIN;
}
diff --git a/src/platformio.ini b/src/platformio.ini
index 0a76a59d..f949aa37 100644
--- a/src/platformio.ini
+++ b/src/platformio.ini
@@ -32,7 +32,7 @@ lib_deps =
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.5
+ https://github.com/zinggjm/GxEPD2#1.5.3
build_flags =
-std=c++17
-std=gnu++17
@@ -201,7 +201,7 @@ lib_deps =
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.5
+ https://github.com/zinggjm/GxEPD2#1.5.3
build_flags = ${env.build_flags}
-D ETHERNET
-DRELEASE
@@ -224,7 +224,7 @@ lib_deps =
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.5
+ https://github.com/zinggjm/GxEPD2#1.5.3
build_flags = ${env.build_flags}
-D ETHERNET
-DRELEASE
@@ -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
@@ -418,7 +418,7 @@ lib_deps =
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.5
+ https://github.com/zinggjm/GxEPD2#1.5.3
upload_protocol = esp-builtin
build_flags = ${env.build_flags}
-DETHERNET
@@ -463,7 +463,7 @@ lib_deps =
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.5
+ https://github.com/zinggjm/GxEPD2#1.5.3
upload_protocol = esp-builtin
build_flags = ${env.build_flags}
-DETHERNET
From 31232bfd80b4f4405a2f8faed0f0cc468ad5dcf5 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Mon, 12 Feb 2024 22:32:13 +0100
Subject: [PATCH 49/79] 0.8.80 * 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
---
README.md | 8 ++---
manual/User_Manual.md | 55 +++++++++++++++++++++++++--------
src/CHANGES.md | 7 +++++
src/defines.h | 2 +-
src/hm/hmInverter.h | 5 +--
src/publisher/pubMqtt.h | 2 +-
src/web/RestApi.h | 37 ++++++++++++----------
src/web/html/visualization.html | 15 +++++++--
src/web/lang.h | 30 ------------------
src/web/lang.json | 25 +++++++++++++++
10 files changed, 116 insertions(+), 70 deletions(-)
diff --git a/README.md b/README.md
index 7a51a98a..16b2a256 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ Table of approaches:
| Board | MI | HM | HMS/HMT | comment | HowTo start |
| ------ | -- | -- | ------- | ------- | ---------- |
-| [ESP8266/ESP32, C++](Getting_Started.md) | ✔️ | ✔️ | ✔️ | 👈 the most effort is spent here | [create your own DTU](https://ahoydtu.de/getting_started/) |
+| [ESP8266/ESP32, C++](manual/Getting_Started.md) | ✔️ | ✔️ | ✔️ | 👈 the most effort is spent here | [create your own DTU](https://ahoydtu.de/getting_started/) |
| [Arduino Nano, C++](tools/nano/NRF24_SendRcv/) | ❌ | ✔️ | ❌ | |
| [Raspberry Pi, Python](tools/rpi/) | ❌ | ✔️ | ❌ | |
| [Others, C/C++](tools/nano/NRF24_SendRcv/) | ❌ | ✔️ | ❌ | |
@@ -39,11 +39,11 @@ Table of approaches:
⚠️ **Warning: HMS-XXXXW-2T WiFi inverters are not supported. They have a 'W' in their name and a DTU serial number on its sticker**
## Getting Started
-1. [Guide how to start with a ESP module](Getting_Started.md)
+1. [Guide how to start with a ESP module](manual/Getting_Started.md)
2. [ESP Webinstaller (Edge / Chrome Browser only)](https://ahoydtu.de/web_install)
-3. [Ahoy Configuration ](ahoy_config.md)
+3. [Ahoy Configuration ](manual/ahoy_config.md)
## Our Website
[https://ahoydtu.de](https://ahoydtu.de)
@@ -64,4 +64,4 @@ If you encounter any problems, use the issue tracker on Github. Provide a detail
- [OpenDTU](https://github.com/tbnobody/OpenDTU)
<- Our sister project ✨ for Hoymiles HM- and HMS-/HMT-series (for ESP32 only!)
- [hms-mqtt-publisher](https://github.com/DennisOSRM/hms-mqtt-publisher)
- <- a project which can handle WiFi inverters like HMS-XXXXW-2T
\ No newline at end of file
+ <- a project which can handle WiFi inverters like HMS-XXXXW-2T
diff --git a/manual/User_Manual.md b/manual/User_Manual.md
index 53da34f4..b5cf5a7e 100644
--- a/manual/User_Manual.md
+++ b/manual/User_Manual.md
@@ -166,6 +166,8 @@ inverter/ctrl/limit/0 600W
### Power Limit persistent
This feature was removed. The persisten limit should not be modified cyclic by a script because of potential wearout of the flash inside the inverter.
+
+
## Control via REST API
### Generic Information
@@ -174,6 +176,46 @@ The rest API works with *JSON* POST requests. All the following instructions mus
👆 `` is the number of the specific inverter in the setup page.
+### Authentication (new for versions > `0.8.79`)
+
+The authentication is only needed if a password was set.
+To authenticate from API you have to add the following `JSON` to your request:
+
+```json
+{
+ "auth":
+}
+```
+`` is your DTU password in plain text.
+
+As Response you get the following `JSON` if successful:
+
+```json
+{
+ "success": true,
+ "token": ""
+}
+```
+Where `` is a random token with a length of 16 characters.
+
+For all following commands you have only to include the token into your `JSON`:
+```json
+{
+ "token": ""
+}
+```
+
+ℹ️ Do not pass the plain text password with each command. Authenticate once and then use the token for all following commands. The token expires once the token wasn't sent for 20 minutes.
+
+If the authentication fails or the token is expired you will receive the following `JSON`:
+
+```json
+{
+ "success": false,
+ "error": "ERR_PROTECTED"
+}
+```
+
### Inverter Power (On / Off)
```json
@@ -245,19 +287,6 @@ The `VALUE` represents a percent number in a range of `[2.0 .. 100.0]`
The `VALUE` represents watts in a range of `[1.0 .. 6553.5]`
-
-### Developer Information REST API (obsolete)
-In the same approach as for MQTT any other SubCmd and also MainCmd can be applied and the response payload can be observed in the serial logs. Eg. request the Alarm-Data from the Alarm-Index 5 from inverter 0 will look like this:
-```json
-{
- "inverter":0,
- "tx_request": 21,
- "cmd": 17,
- "payload": 5,
- "payload2": 0
-}
-```
-
## Zero Export Control (needs rework)
* You can use the mqtt topic `/devcontrol//11` with a number as payload (eg. 300 -> 300 Watt) to set the power limit to the published number in Watt. (In regular cases the inverter will use the new set point within one intervall period; to verify this see next bullet)
* You can check the inverter set point for the power limit control on the topic `//ch0/PowerLimit` 👆 This value is ALWAYS in percent of the maximum power limit of the inverter. In regular cases this value will be updated within approx. 15 seconds. (depends on request intervall)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index dff1bb30..714dc8cc 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,12 @@
# Development Changes
+## 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
diff --git a/src/defines.h b/src/defines.h
index 40084c47..8913db5e 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 79
+#define VERSION_PATCH 80
//-------------------------------------
typedef struct {
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index b6dc93fa..f608908e 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -163,9 +163,10 @@ class Inverter {
void tickSend(std::function cb) {
if(mDevControlRequest) {
- if(InverterStatus::OFF != status)
+ if(InverterStatus::OFF != status) {
cb(devControlCmd, true);
- else
+ devControlCmd = InitDataState;
+ } else
DPRINTLN(DBG_WARN, F("Inverter is not avail"));
mDevControlRequest = false;
} else if (IV_MI != ivGen) { // HM / HMS / HMT
diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h
index 1b9e35ef..369d9ead 100644
--- a/src/publisher/pubMqtt.h
+++ b/src/publisher/pubMqtt.h
@@ -316,7 +316,7 @@ class PubMqtt {
if(NULL == strstr(topic, "limit"))
root[F("val")] = atoi(pyld);
else
- root[F("val")] = (int)(atof(pyld) * 10.0f);
+ root[F("val")] = atof(pyld);
if(pyld[len-1] == 'W')
limitAbs = true;
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index fadd7277..37e988c0 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -30,10 +30,6 @@
#define F(sl) (sl)
#endif
-const 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};
-const 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};
-const uint8_t dcList[] = {FLD_UDC, FLD_IDC, FLD_PDC, FLD_YD, FLD_YT, FLD_IRR, FLD_MP};
-
template
class RestApi {
public:
@@ -831,14 +827,16 @@ class RestApi {
}
bool setCtrl(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
- if(F("auth") == jsonIn[F("cmd")]) {
- if(String(jsonIn["val"]) == String(mConfig->sys.adminPwd))
- jsonOut["token"] = mApp->unlock(clientIP, false);
- else {
- jsonOut[F("error")] = F(AUTH_ERROR);
+ if(jsonIn.containsKey(F("auth"))) {
+ if(String(jsonIn[F("auth")]) == String(mConfig->sys.adminPwd)) {
+ jsonOut[F("token")] = mApp->unlock(clientIP, false);
+ jsonIn[F("token")] = jsonOut[F("token")];
+ } else {
+ jsonOut[F("error")] = F("ERR_AUTH");
return false;
}
- return true;
+ if(!jsonIn.containsKey(F("cmd")))
+ return true;
}
if(isProtected(jsonIn, jsonOut, clientIP))
@@ -847,7 +845,7 @@ class RestApi {
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
bool accepted = true;
if(NULL == iv) {
- jsonOut[F("error")] = F(INV_INDEX_INVALID) + jsonIn[F("id")].as();
+ jsonOut[F("error")] = F("ERR_INDEX");
return false;
}
jsonOut[F("id")] = jsonIn[F("id")];
@@ -857,7 +855,7 @@ class RestApi {
else if(F("restart") == jsonIn[F("cmd")])
accepted = iv->setDevControlRequest(Restart);
else if(0 == strncmp("limit_", jsonIn[F("cmd")].as(), 6)) {
- iv->powerLimit[0] = jsonIn["val"];
+ iv->powerLimit[0] = static_cast(jsonIn["val"].as() * 10.0);
if(F("limit_persistent_relative") == jsonIn[F("cmd")])
iv->powerLimit[1] = RelativPersistent;
else if(F("limit_persistent_absolute") == jsonIn[F("cmd")])
@@ -874,12 +872,12 @@ class RestApi {
DPRINTLN(DBG_INFO, F("dev cmd"));
iv->setDevCommand(jsonIn[F("val")].as());
} else {
- jsonOut[F("error")] = F(UNKNOWN_CMD) + jsonIn["cmd"].as() + "'";
+ jsonOut[F("error")] = F("ERR_UNKNOWN_CMD");
return false;
}
if(!accepted) {
- jsonOut[F("error")] = F(INV_DOES_NOT_ACCEPT_LIMIT_AT_MOMENT);
+ jsonOut[F("error")] = F("ERR_LIMIT_NOT_ACCEPT");
return false;
}
@@ -930,7 +928,7 @@ class RestApi {
iv->config->disNightCom = jsonIn[F("disnightcom")];
mApp->saveSettings(false); // without reboot
} else {
- jsonOut[F("error")] = F(UNKNOWN_CMD);
+ jsonOut[F("error")] = F("ERR_UNKNOWN_CMD");
return false;
}
@@ -947,7 +945,7 @@ class RestApi {
if(!mApp->isProtected(clientIP, token, false))
return false;
- jsonOut[F("error")] = F(IS_PROTECTED);
+ jsonOut[F("error")] = F("ERR_PROTECTED");
return true;
}
}
@@ -955,6 +953,13 @@ class RestApi {
return false;
}
+ 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};
+ 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};
+ constexpr static uint8_t dcList[] = {FLD_UDC, FLD_IDC, FLD_PDC, FLD_YD, FLD_YT, FLD_IRR, FLD_MP};
+
private:
IApp *mApp = nullptr;
HMSYSTEM *mSys = nullptr;
diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html
index 1ce4e264..81962add 100644
--- a/src/web/html/visualization.html
+++ b/src/web/html/visualization.html
@@ -22,6 +22,15 @@
var total = Array(6).fill(0);
var tPwrAck;
+ function getErrStr(code) {
+ if("ERR_AUTH") return "{#ERR_AUTH}"
+ if("ERR_INDEX") return "{#ERR_INDEX}"
+ if("ERR_UNKNOWN_CMD") return "{#ERR_UNKNOWN_CMD}"
+ if("ERR_LIMIT_NOT_ACCEPT") return "{#ERR_LIMIT_NOT_ACCEPT}"
+ if("ERR_UNKNOWN_CMD") return "{#ERR_AUTH}"
+ return "n/a"
+ }
+
function parseGeneric(obj) {
if(true == exeOnce){
parseNav(obj);
@@ -457,7 +466,7 @@
obj.id = id
obj.token = "*"
obj.cmd = cmd
- obj.val = Math.round(val*10)
+ obj.val = val
getAjax("/api/ctrl", ctrlCb, "POST", JSON.stringify(obj))
}
@@ -477,7 +486,7 @@
tPwrAck = window.setInterval("getAjax('/api/inverter/pwrack/" + obj.id + "', updatePwrAck)", 1000);
}
else
- e.innerHTML = "{#ERROR}: " + obj["error"];
+ e.innerHTML = "{#ERROR}: " + getErrStr(obj.error);
}
function ctrlCb2(obj) {
@@ -485,7 +494,7 @@
if(obj.success)
e.innerHTML = "{#COMMAND_RECEIVED}";
else
- e.innerHTML = "{#ERROR}: " + obj["error"];
+ e.innerHTML = "{#ERROR}: " + getErrStr(obj.error);
}
function updatePwrAck(obj) {
diff --git a/src/web/lang.h b/src/web/lang.h
index 1e066928..fb5506ee 100644
--- a/src/web/lang.h
+++ b/src/web/lang.h
@@ -24,36 +24,6 @@
#define WAS_IN_CH_12_TO_14 "Your ESP was in wifi channel 12 to 14. It may cause reboots of your AhoyDTU"
#endif
-#ifdef LANG_DE
- #define INV_INDEX_INVALID "Wechselrichterindex ungültig; "
-#else /*LANG_EN*/
- #define INV_INDEX_INVALID "inverter index invalid: "
-#endif
-
-#ifdef LANG_DE
- #define AUTH_ERROR "Authentifizierungsfehler"
-#else /*LANG_EN*/
- #define AUTH_ERROR "authentication error"
-#endif
-
-#ifdef LANG_DE
- #define UNKNOWN_CMD "unbekanntes Kommando: '"
-#else /*LANG_EN*/
- #define UNKNOWN_CMD "unknown cmd: '"
-#endif
-
-#ifdef LANG_DE
- #define IS_PROTECTED "nicht angemeldet, Kommando nicht möglich!"
-#else /*LANG_EN*/
- #define IS_PROTECTED "not logged in, command not possible!"
-#endif
-
-#ifdef LANG_DE
- #define INV_DOES_NOT_ACCEPT_LIMIT_AT_MOMENT "Leistungsbegrenzung / Ansteuerung aktuell nicht möglich"
-#else /*LANG_EN*/
- #define INV_DOES_NOT_ACCEPT_LIMIT_AT_MOMENT "inverter does not accept dev control request at this moment"
-#endif
-
#ifdef LANG_DE
#define PATH_NOT_FOUND "Pfad nicht gefunden: "
#else /*LANG_EN*/
diff --git a/src/web/lang.json b/src/web/lang.json
index 1e79f8bf..335f0d2a 100644
--- a/src/web/lang.json
+++ b/src/web/lang.json
@@ -1432,6 +1432,31 @@
"token": "INV_ACK",
"en": "inverter acknowledged active power control command",
"de": "Wechselrichter hat die Leistungsbegrenzung akzeptiert"
+ },
+ {
+ "token": "ERR_AUTH",
+ "en": "authentication error",
+ "de": "Authentifizierungsfehler"
+ },
+ {
+ "token": "ERR_INDEX",
+ "en": "inverter index invalid",
+ "de": "Wechselrichterindex ungültig"
+ },
+ {
+ "token": "ERR_UNKNOWN_CMD",
+ "en": "unknown cmd",
+ "de": "unbekanntes Kommando"
+ },
+ {
+ "token": "ERR_LIMIT_NOT_ACCEPT",
+ "en": "inverter does not accept dev control request at this moment",
+ "de": "Leistungsbegrenzung / Ansteuerung aktuell nicht möglich"
+ },
+ {
+ "token": "ERR_PROTECTED",
+ "en": "not logged in, command not possible!",
+ "de": "nicht angemeldet, Kommando nicht möglich!"
}
]
},
From 9d1147b3716f98856f4129f19bfeecb6bbd14c9a Mon Sep 17 00:00:00 2001
From: rejoe2
Date: Tue, 13 Feb 2024 12:13:53 +0100
Subject: [PATCH 50/79] 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 bd532805a66f64bae723b5a62f38668e84b7fb34 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Tue, 13 Feb 2024 23:46:15 +0100
Subject: [PATCH 51/79] 0.8.81 * 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
---
src/CHANGES.md | 5 +++
src/config/settings.h | 9 ++++-
src/defines.h | 2 +-
src/publisher/pubMqttIvData.h | 59 +++++++++++++++++++---------
src/web/Protection.h | 2 +-
src/web/RestApi.h | 1 +
src/web/html/setup.html | 73 +++++++++++++----------------------
src/web/lang.json | 5 +++
src/web/web.h | 1 +
9 files changed, 90 insertions(+), 67 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 714dc8cc..f39a5640 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,10 @@
# Development Changes
+## 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
diff --git a/src/config/settings.h b/src/config/settings.h
index 0cb9ed4e..18725b48 100644
--- a/src/config/settings.h
+++ b/src/config/settings.h
@@ -31,7 +31,7 @@
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
* */
-#define CONFIG_VERSION 10
+#define CONFIG_VERSION 11
#define PROT_MASK_INDEX 0x0001
@@ -120,6 +120,7 @@ typedef struct {
bool debug;
bool privacyLog;
bool printWholeTrace;
+ bool log2mqtt;
} cfgSerial_t;
typedef struct {
@@ -436,6 +437,7 @@ class settings {
mCfg.serial.debug = false;
mCfg.serial.privacyLog = true;
mCfg.serial.printWholeTrace = false;
+ mCfg.serial.log2mqtt = false;
mCfg.mqtt.port = DEF_MQTT_PORT;
snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", DEF_MQTT_BROKER);
@@ -509,6 +511,9 @@ class settings {
mCfg.sys.region = 0; // Europe
mCfg.sys.timezone = 1;
}
+ if(mCfg.configVersion < 11) {
+ mCfg.serial.log2mqtt = false;
+ }
}
}
@@ -658,11 +663,13 @@ class settings {
obj[F("debug")] = mCfg.serial.debug;
obj[F("prv")] = (bool) mCfg.serial.privacyLog;
obj[F("trc")] = (bool) mCfg.serial.printWholeTrace;
+ obj[F("mqtt")] = (bool) mCfg.serial.log2mqtt;
} else {
getVal(obj, F("show"), &mCfg.serial.showIv);
getVal(obj, F("debug"), &mCfg.serial.debug);
getVal(obj, F("prv"), &mCfg.serial.privacyLog);
getVal(obj, F("trc"), &mCfg.serial.printWholeTrace);
+ getVal(obj, F("mqtt"), &mCfg.serial.log2mqtt);
}
}
diff --git a/src/defines.h b/src/defines.h
index 8913db5e..200c2561 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 80
+#define VERSION_PATCH 81
//-------------------------------------
typedef struct {
diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h
index 06f8e629..c430da85 100644
--- a/src/publisher/pubMqttIvData.h
+++ b/src/publisher/pubMqttIvData.h
@@ -6,6 +6,7 @@
#ifndef __PUB_MQTT_IV_DATA_H__
#define __PUB_MQTT_IV_DATA_H__
+#include
#include "../utils/dbg.h"
#include "../hm/hmSystem.h"
#include "pubMqttDefs.h"
@@ -107,14 +108,14 @@ class PubMqttIvData {
if(found) {
record_t<> *rec = mIv->getRecordStruct(mCmd);
if(MqttSentStatus::NEW_DATA == rec->mqttSentStatus) {
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/last_success", mIv->config->name);
- snprintf(mVal, 40, "%d", mIv->getLastTs(rec));
- mPublish(mSubTopic, mVal, true, QOS_0);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/last_success", mIv->config->name);
+ snprintf(mVal.data(), mVal.size(), "%d", mIv->getLastTs(rec));
+ mPublish(mSubTopic.data(), mVal.data(), true, QOS_0);
if((mIv->ivGen == IV_HMS) || (mIv->ivGen == IV_HMT)) {
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch0/rssi", mIv->config->name);
- snprintf(mVal, 40, "%d", mIv->rssi);
- mPublish(mSubTopic, mVal, false, QOS_0);
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch0/rssi", mIv->config->name);
+ snprintf(mVal.data(), mVal.size(), "%d", mIv->rssi);
+ mPublish(mSubTopic.data(), mVal.data(), false, QOS_0);
}
rec->mqttSentStatus = MqttSentStatus::LAST_SUCCESS_SENT;
}
@@ -144,7 +145,7 @@ class PubMqttIvData {
if(mPos < rec->length) {
bool retained = false;
- if (mCmd == RealTimeRunData_Debug) {
+ if (RealTimeRunData_Debug == mCmd) {
if((FLD_YT == rec->assign[mPos].fieldId) || (FLD_YD == rec->assign[mPos].fieldId))
retained = true;
@@ -176,10 +177,32 @@ class PubMqttIvData {
}
if (MqttSentStatus::LAST_SUCCESS_SENT == rec->mqttSentStatus) {
+ if(InverterDevInform_All == mCmd) {
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/firmware", mIv->config->name);
+ snprintf(mVal.data(), mVal.size(), "{\"version\":%d,\"build_year\":\"%s\",\"build_month_day\":%d,\"build_hour_min\":%d,\"bootloader\":%d}",
+ mIv->getChannelFieldValue(CH0, FLD_FW_VERSION, rec),
+ mIv->getChannelFieldValue(CH0, FLD_FW_BUILD_YEAR, rec),
+ mIv->getChannelFieldValue(CH0, FLD_FW_BUILD_MONTH_DAY, rec),
+ mIv->getChannelFieldValue(CH0, FLD_FW_BUILD_HOUR_MINUTE, rec),
+ 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\":\"%s\",\"grid_profile_code\":%d,\"grid_profile_version\":%d}",
+ mIv->getChannelFieldValue(CH0, FLD_PART_NUM, rec),
+ mIv->getChannelFieldValue(CH0, FLD_HW_VERSION, rec),
+ mIv->getChannelFieldValue(CH0, FLD_GRID_PROFILE_CODE, rec),
+ 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)));
+ }
+
uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0;
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]);
- snprintf(mVal, 40, "%g", ah::round3(mIv->getValue(mPos, rec)));
- mPublish(mSubTopic, mVal, retained, qos);
+ if((FLD_EVT != rec->assign[mPos].fieldId)
+ && (FLD_LAST_ALARM_CODE != rec->assign[mPos].fieldId))
+ mPublish(mSubTopic.data(), mVal.data(), retained, qos);
}
mPos++;
} else {
@@ -192,8 +215,8 @@ class PubMqttIvData {
}
inline void sendRadioStat(uint8_t start) {
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/radio_stat", mIv->config->name);
- snprintf(mVal, 140, "{\"tx\":%d,\"success\":%d,\"fail\":%d,\"no_answer\":%d,\"retransmits\":%d,\"lossIvRx\":%d,\"lossIvTx\":%d,\"lossDtuRx\":%d,\"lossDtuTx\":%d}",
+ snprintf(mSubTopic.data(), mSubTopic.size(), "%s/radio_stat", mIv->config->name);
+ snprintf(mVal.data(), mVal.size(), "{\"tx\":%d,\"success\":%d,\"fail\":%d,\"no_answer\":%d,\"retransmits\":%d,\"lossIvRx\":%d,\"lossIvTx\":%d,\"lossDtuRx\":%d,\"lossDtuTx\":%d}",
mIv->radioStatistics.txCnt,
mIv->radioStatistics.rxSuccess,
mIv->radioStatistics.rxFail,
@@ -203,7 +226,7 @@ class PubMqttIvData {
mIv->radioStatistics.ivSent,
mIv->radioStatistics.dtuLoss,
mIv->radioStatistics.dtuSent);
- mPublish(mSubTopic, mVal, false, QOS_0);
+ mPublish(mSubTopic.data(), mVal.data(), false, QOS_0);
}
void stateSendTotals() {
@@ -240,9 +263,9 @@ class PubMqttIvData {
retained = false;
break;
}
- snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]);
- snprintf(mVal, 40, "%g", ah::round3(mTotal[mPos]));
- mPublish(mSubTopic, mVal, retained, QOS_0);
+ 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 {
mSendList->pop();
@@ -266,8 +289,8 @@ class PubMqttIvData {
uint8_t mPos = 0;
bool mRTRDataHasBeenSent = false;
- char mSubTopic[32 + MAX_NAME_LENGTH + 1];
- char mVal[140];
+ std::array mSubTopic;
+ std::array mVal;
std::queue *mSendList = nullptr;
};
diff --git a/src/web/Protection.h b/src/web/Protection.h
index 82e4be49..74f04b52 100644
--- a/src/web/Protection.h
+++ b/src/web/Protection.h
@@ -85,7 +85,7 @@ class Protection {
if(isIdentical(clientIp, mApiIp))
return (0 != strncmp(token, mToken.data(), 16));
- return false;
+ return true;
}
private:
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index 37e988c0..09bba06e 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -680,6 +680,7 @@ class RestApi {
obj[F("debug")] = mConfig->serial.debug;
obj[F("priv")] = mConfig->serial.privacyLog;
obj[F("wholeTrace")] = mConfig->serial.printWholeTrace;
+ obj[F("log2mqtt")] = mConfig->serial.log2mqtt;
}
void getStaticIp(JsonObject obj) {
diff --git a/src/web/html/setup.html b/src/web/html/setup.html
index 4859fe34..47d935b9 100644
--- a/src/web/html/setup.html
+++ b/src/web/html/setup.html
@@ -43,24 +43,8 @@
-
@@ -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 70/79] 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 71/79] 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 58044c34aa16d1ffa08e935d0c5fe3c1261e104b Mon Sep 17 00:00:00 2001
From: Wusaweki
Date: Sun, 3 Dec 2023 15:51:33 +0100
Subject: [PATCH 72/79] remove redundant check for nullpointer
(cherry picked from commit a1de637793bdc14627c68fc1b03d61d5189758cd)
(cherry picked from commit 7ba88180c50d7d0b6c971a477987bb5ded5aa9d8)
(cherry picked from commit 6888d571834ad5cf4b32a00536501e88112f7049)
(cherry picked from commit 8a8b8a61f354992823a77feca3a5193f8c53880e)
---
src/hm/hmInverter.h | 50 ++++++++++++++++++++++-----------------------
1 file changed, 24 insertions(+), 26 deletions(-)
diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h
index 1890d142..4252800d 100644
--- a/src/hm/hmInverter.h
+++ b/src/hm/hmInverter.h
@@ -288,32 +288,30 @@ class Inverter {
uint8_t end = ptr + rec->assign[pos].num;
uint16_t div = rec->assign[pos].div;
- if(NULL != rec) {
- if(CMD_CALC != div) {
- uint32_t val = 0;
- do {
- val <<= 8;
- val |= buf[ptr];
- } while(++ptr != end);
-
- if ((FLD_T == rec->assign[pos].fieldId) || (FLD_Q == rec->assign[pos].fieldId) || (FLD_PF == rec->assign[pos].fieldId)) {
- // 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)) + ((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);
- uint8_t idx = rec->assign[pos].ch - 1;
- if (mLastYD[idx] > actYD)
- mOffYD[idx] += mLastYD[idx];
- mLastYD[idx] = actYD;
- rec->record[pos] = mOffYD[idx] + actYD;
- } else {
- if ((REC_TYP)(div) > 1)
- rec->record[pos] = (REC_TYP)(val) / (REC_TYP)(div);
- else
- rec->record[pos] = (REC_TYP)(val);
- }
+ if(CMD_CALC != div) {
+ uint32_t val = 0;
+ do {
+ val <<= 8;
+ val |= buf[ptr];
+ } while(++ptr != end);
+
+ if ((FLD_T == rec->assign[pos].fieldId) || (FLD_Q == rec->assign[pos].fieldId) || (FLD_PF == rec->assign[pos].fieldId)) {
+ // 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)) + ((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);
+ uint8_t idx = rec->assign[pos].ch - 1;
+ if (mLastYD[idx] > actYD)
+ mOffYD[idx] += mLastYD[idx];
+ mLastYD[idx] = actYD;
+ rec->record[pos] = mOffYD[idx] + actYD;
+ } else {
+ if ((REC_TYP)(div) > 1)
+ rec->record[pos] = (REC_TYP)(val) / (REC_TYP)(div);
+ else
+ rec->record[pos] = (REC_TYP)(val);
}
}
From 199d4b38732d00380e40f8d2065a279b526398f5 Mon Sep 17 00:00:00 2001
From: you69man
Date: Fri, 8 Dec 2023 15:49:12 +0100
Subject: [PATCH 73/79] use mChList[] instead of switch-case
(cherry picked from commit fdaf80e964a6ecb2423b0c1d8d03bb0184904ab8)
(cherry picked from commit 48c832be5eb05a96204fa1ec70fdf198e06ac94d)
(cherry picked from commit effe05a616615d709455d32c46c2254c8cfe399e)
---
src/hm/Heuristic.h | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h
index cc42df4f..59c35aec 100644
--- a/src/hm/Heuristic.h
+++ b/src/hm/Heuristic.h
@@ -217,15 +217,12 @@ class Heuristic {
}
inline uint8_t id2Ch(uint8_t id) {
- switch(id) {
- case 0: return 3;
- case 1: return 23;
- case 2: return 40;
- case 3: return 61;
- case 4: return 75;
- }
- return 3; // standard
+ if (id < RF_MAX_CHANNEL_ID)
+ return mChList[id];
+ else
+ return 3; // standard
}
+ uint8_t mChList[RF_MAX_CHANNEL_ID] = {03, 23, 40, 61, 75};
};
From 363aac5d0227a8c70d5a4d09c2cf37d83e43f140 Mon Sep 17 00:00:00 2001
From: you69man
Date: Sun, 17 Dec 2023 12:11:49 +0100
Subject: [PATCH 74/79] used INVERTERTYPE:: instead of mInverter[0] for global
setup
---
src/hm/hmSystem.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h
index e9b839be..c4219435 100644
--- a/src/hm/hmSystem.h
+++ b/src/hm/hmSystem.h
@@ -16,8 +16,8 @@ class HmSystem {
HmSystem() {}
void setup(uint32_t *timestamp, cfgInst_t *config, IApp *app) {
- mInverter[0].timestamp = timestamp;
- mInverter[0].generalConfig = config;
+ INVERTERTYPE::timestamp = timestamp;
+ INVERTERTYPE::generalConfig = config;
//mInverter[0].app = app;
}
From c9a9d6b7733a18d4efb1aeaa190cae091ceaad07 Mon Sep 17 00:00:00 2001
From: you69man
Date: Sat, 23 Dec 2023 12:31:47 +0100
Subject: [PATCH 75/79] remove unnecessary config entry 'enabled' for cfgInst_t
---
src/config/settings.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/config/settings.h b/src/config/settings.h
index 9c9b48c2..fe0053a9 100644
--- a/src/config/settings.h
+++ b/src/config/settings.h
@@ -152,7 +152,7 @@ typedef struct {
} cfgIv_t;
typedef struct {
- bool enabled;
+// bool enabled;
cfgIv_t iv[MAX_NUM_INVERTERS];
uint16_t sendInterval;
@@ -755,7 +755,7 @@ class settings {
void jsonInst(JsonObject obj, bool set = false) {
if(set) {
obj[F("intvl")] = mCfg.inst.sendInterval;
- obj[F("en")] = (bool)mCfg.inst.enabled;
+// obj[F("en")] = (bool)mCfg.inst.enabled;
obj[F("rstMidNight")] = (bool)mCfg.inst.rstYieldMidNight;
obj[F("rstNotAvail")] = (bool)mCfg.inst.rstValsNotAvail;
obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop;
@@ -765,7 +765,7 @@ class settings {
}
else {
getVal(obj, F("intvl"), &mCfg.inst.sendInterval);
- getVal(obj, F("en"), &mCfg.inst.enabled);
+// getVal(obj, F("en"), &mCfg.inst.enabled);
getVal(obj, F("rstMidNight"), &mCfg.inst.rstYieldMidNight);
getVal(obj, F("rstNotAvail"), &mCfg.inst.rstValsNotAvail);
getVal(obj, F("rstComStop"), &mCfg.inst.rstValsCommStop);
From b143eb371b2d88333704c626108fd4d5651092af Mon Sep 17 00:00:00 2001
From: you69man
Date: Sat, 23 Dec 2023 16:16:36 +0100
Subject: [PATCH 76/79] remove strncpy warning in scheduler.h Warning was:
output truncated before terminating nul copying 5 bytes from a string of the
same length
---
src/utils/scheduler.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h
index 16009778..0f7cea7b 100644
--- a/src/utils/scheduler.h
+++ b/src/utils/scheduler.h
@@ -125,8 +125,8 @@ namespace ah {
mTicker[i].timeout = timeout;
mTicker[i].reload = reload;
mTicker[i].isTimestamp = isTimestamp;
- memset(mTicker[i].name, 0, 6);
- strncpy(mTicker[i].name, name, (strlen(name) < 6) ? strlen(name) : 5);
+ strncpy(mTicker[i].name, name, 5);
+ mTicker[i].name[5]=0;
if(mMax == i)
mMax = i + 1;
return i;
From dd8f8c138b72aecb796992637052237edc8c0138 Mon Sep 17 00:00:00 2001
From: Wusaweki
Date: Sun, 3 Dec 2023 16:37:18 +0100
Subject: [PATCH 77/79] fix typos
---
src/CHANGES.md | 4 ++--
src/defines.h | 2 +-
src/hm/Communication.h | 2 +-
src/hm/Heuristic.h | 2 +-
src/publisher/pubMqttIvData.h | 2 +-
src/web/RestApi.h | 2 +-
src/web/html/includes/nav.html | 6 +++---
src/web/html/style.css | 2 +-
src/web/web.h | 2 +-
9 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 2cd2300f..09ba13f2 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -265,7 +265,7 @@
## 0.8.39 - 2024-01-01
* fix MqTT dis_night_comm in the morning #1309 #1286
-* seperated offset for sunrise and sunset #1308
+* separated 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
@@ -478,7 +478,7 @@
## 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`
+* moved radio statistics into the inverter - each inverter has now separate statistics which can be accessed by click on the footer in `/live`
* fix compiler warnings #1191
* fix ePaper logo during night time #1151
diff --git a/src/defines.h b/src/defines.h
index 8dcfe988..67e902bd 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -109,7 +109,7 @@ enum {
typedef struct {
uint32_t rxFail;
- uint32_t rxFailNoAnser;
+ uint32_t rxFailNoAnswer;
uint32_t rxSuccess;
uint32_t frmCnt;
uint32_t txCnt;
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index 8c7fbe6d..b616f317 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -622,7 +622,7 @@ class Communication : public CommQueue<> {
else if(q->iv->mGotFragment || mCompleteRetry)
q->iv->radioStatistics.rxFail++; // got no complete payload
else
- q->iv->radioStatistics.rxFailNoAnser++; // got nothing
+ q->iv->radioStatistics.rxFailNoAnswer++; // got nothing
mWaitTime.startTimeMonitor(1); // maybe remove, side effects unknown
bool keep = false;
diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h
index 59c35aec..1220692e 100644
--- a/src/hm/Heuristic.h
+++ b/src/hm/Heuristic.h
@@ -153,7 +153,7 @@ class Heuristic {
DBGPRINT(F(", f: "));
DBGPRINT(String(iv->radioStatistics.rxFail));
DBGPRINT(F(", n: "));
- DBGPRINT(String(iv->radioStatistics.rxFailNoAnser));
+ DBGPRINT(String(iv->radioStatistics.rxFailNoAnswer));
DBGPRINT(F(" | p: ")); // better debugging for helpers...
if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
DBGPRINTLN(String(iv->config->powerLevel-10));
diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h
index ac8b3bf0..6ddd63a9 100644
--- a/src/publisher/pubMqttIvData.h
+++ b/src/publisher/pubMqttIvData.h
@@ -222,7 +222,7 @@ class PubMqttIvData {
mIv->radioStatistics.txCnt,
mIv->radioStatistics.rxSuccess,
mIv->radioStatistics.rxFail,
- mIv->radioStatistics.rxFailNoAnser,
+ mIv->radioStatistics.rxFailNoAnswer,
mIv->radioStatistics.retransmits,
mIv->radioStatistics.ivLoss,
mIv->radioStatistics.ivSent,
diff --git a/src/web/RestApi.h b/src/web/RestApi.h
index 0120375a..f6917077 100644
--- a/src/web/RestApi.h
+++ b/src/web/RestApi.h
@@ -426,7 +426,7 @@ class RestApi {
obj[F("name")] = String(iv->config->name);
obj[F("rx_success")] = iv->radioStatistics.rxSuccess;
obj[F("rx_fail")] = iv->radioStatistics.rxFail;
- obj[F("rx_fail_answer")] = iv->radioStatistics.rxFailNoAnser;
+ obj[F("rx_fail_answer")] = iv->radioStatistics.rxFailNoAnswer;
obj[F("frame_cnt")] = iv->radioStatistics.frmCnt;
obj[F("tx_cnt")] = iv->radioStatistics.txCnt;
obj[F("retransmits")] = iv->radioStatistics.retransmits;
diff --git a/src/web/html/includes/nav.html b/src/web/html/includes/nav.html
index 447bf411..bab64829 100644
--- a/src/web/html/includes/nav.html
+++ b/src/web/html/includes/nav.html
@@ -10,15 +10,15 @@
{#NAV_HISTORY}
{#NAV_WEBSERIAL}
{#NAV_SETTINGS}
-
+
Update
System
-
+
REST API
{#NAV_DOCUMENTATION}
{#NAV_ABOUT}
Custom Link
-
+
Login
Logout
diff --git a/src/web/html/style.css b/src/web/html/style.css
index 2d6a03c7..74cf4e8e 100644
--- a/src/web/html/style.css
+++ b/src/web/html/style.css
@@ -139,7 +139,7 @@ svg.icon {
background-color: var(--nav-active);
}
-span.seperator {
+span.separator {
width: 100%;
height: 1px;
margin: 5px 0 5px;
diff --git a/src/web/web.h b/src/web/web.h
index de4938f1..0a4f0ed5 100644
--- a/src/web/web.h
+++ b/src/web/web.h
@@ -661,7 +661,7 @@ class Web {
{ "max_power", "gauge", metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->getMaxPower();} },
{ "radio_rx_success", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxSuccess;} },
{ "radio_rx_fail", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxFail;} },
- { "radio_rx_fail_answer", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxFailNoAnser;} },
+ { "radio_rx_fail_answer", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxFailNoAnswer;} },
{ "radio_frame_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.frmCnt;} },
{ "radio_tx_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.txCnt;} },
{ "radio_retransmits", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.retransmits;} },
From 49508ba78e694476883d3bf96207ec4305ee93ed Mon Sep 17 00:00:00 2001
From: you69man
Date: Sat, 24 Feb 2024 14:20:07 +0100
Subject: [PATCH 78/79] fix two warnings1) C++ forbids converting a string
constant to 'char*'
2) suggest paranthesis around '&&' within '||'
---
src/hm/Communication.h | 2 +-
src/publisher/pubMqtt.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/hm/Communication.h b/src/hm/Communication.h
index b616f317..5fd3b487 100644
--- a/src/hm/Communication.h
+++ b/src/hm/Communication.h
@@ -117,7 +117,7 @@ class Communication : public CommQueue<> {
//q->iv->radioStatistics.txCnt++;
q->iv->radio->mRadioWaitTime.startTimeMonitor(mTimeout);
- if(!mIsRetransmit && (q->cmd == AlarmData) || (q->cmd == GridOnProFilePara))
+ if((!mIsRetransmit && (q->cmd == AlarmData)) || (q->cmd == GridOnProFilePara))
incrAttempt((q->cmd == AlarmData)? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA);
mIsRetransmit = false;
diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h
index ea6f331e..4b09b649 100644
--- a/src/publisher/pubMqtt.h
+++ b/src/publisher/pubMqtt.h
@@ -423,7 +423,7 @@ class PubMqtt {
}
DynamicJsonDocument doc2(512);
- constexpr static char* unitTotal[] = {"W", "kWh", "Wh", "W"};
+ constexpr static const char* unitTotal[] = {"W", "kWh", "Wh", "W"};
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]));
From 0d7c67dbcecaee200ccee505a5a2a8a4b3153c62 Mon Sep 17 00:00:00 2001
From: lumapu
Date: Sat, 2 Mar 2024 01:25:59 +0100
Subject: [PATCH 79/79] 0.8.89 * merge PR: Collection of small fixes #1465 *
fix: show esp type on `/history` #1463 * improved HMS-400-1T support (serial
number 1125...) #1460
---
src/CHANGES.md | 5 +++++
src/defines.h | 2 +-
src/hm/hmSystem.h | 3 ++-
src/web/html/history.html | 1 +
4 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/CHANGES.md b/src/CHANGES.md
index 09ba13f2..f5aa9cd9 100644
--- a/src/CHANGES.md
+++ b/src/CHANGES.md
@@ -1,5 +1,10 @@
# Development Changes
+## 0.8.89 - 2024-03-02
+* merge PR: Collection of small fixes #1465
+* fix: show esp type on `/history` #1463
+* improved HMS-400-1T support (serial number 1125...) #1460
+
## 0.8.88 - 2024-02-28
* fix MqTT statistic data overflow #1458
* add HMS-400-1T support (serial number 1125...) #1460
diff --git a/src/defines.h b/src/defines.h
index 67e902bd..b7ee4406 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
-#define VERSION_PATCH 88
+#define VERSION_PATCH 89
//-------------------------------------
typedef struct {
diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h
index c4219435..3b43b9f0 100644
--- a/src/hm/hmSystem.h
+++ b/src/hm/hmSystem.h
@@ -31,11 +31,12 @@ 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;
+ case 0x25: // HMS-400 - 1 channel but payload like 2ch
+
case 0x44: // HMS-1000
case 0x42:
case 0x41: iv->type = INV_TYPE_2CH;
diff --git a/src/web/html/history.html b/src/web/html/history.html
index 7e317b59..6372ab82 100644
--- a/src/web/html/history.html
+++ b/src/web/html/history.html
@@ -80,6 +80,7 @@
function parsePowerHistory(obj){
if (null != obj) {
parseNav(obj.generic);
+ parseESP(obj.generic);
parseHistory(obj,"pwr", pwrExeOnce)
document.getElementById("pwrLast").innerHTML = mLastValue
document.getElementById("pwrMaxDay").innerHTML = obj.maxDay