From d31f39286ee570b2f373a03934115455dad7b63b Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 18 Dec 2023 13:55:49 +0100 Subject: [PATCH 1/8] 0.8.27 * fix set power limit #1276 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/hm/CommQueue.h | 23 +++++++++++------------ src/hm/Communication.h | 22 ++++++++++++---------- src/hm/hmRadio.h | 2 +- 5 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index d57c90d6..95265968 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.27 - 2023-12-18 +* fix set power limit #1276 + ## 0.8.26 - 2023-12-17 * read grid profile as HEX (`live` -> click inverter name -> `show grid profile`) diff --git a/src/defines.h b/src/defines.h index 4d94bc95..b6e5b8aa 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 26 +#define VERSION_PATCH 27 //------------------------------------- typedef struct { diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h index d1beedfc..37ffda62 100644 --- a/src/hm/CommQueue.h +++ b/src/hm/CommQueue.h @@ -16,22 +16,22 @@ class CommQueue { public: CommQueue() {} - void addImportant(Inverter<> *iv, uint8_t cmd, bool delOnPop = true) { + void addImportant(Inverter<> *iv, uint8_t cmd) { dec(&mRdPtr); - mQueue[mRdPtr] = queue_s(iv, cmd, delOnPop, true); + mQueue[mRdPtr] = queue_s(iv, cmd, true); } - void add(Inverter<> *iv, uint8_t cmd, bool delOnPop = true) { - mQueue[mWrPtr] = queue_s(iv, cmd, delOnPop, false); + void add(Inverter<> *iv, uint8_t cmd) { + mQueue[mWrPtr] = queue_s(iv, cmd, false); inc(&mWrPtr); } - void chgCmd(Inverter<> *iv, uint8_t cmd, bool delOnPop = true) { - mQueue[mWrPtr] = queue_s(iv, cmd, delOnPop, false); + void chgCmd(Inverter<> *iv, uint8_t cmd) { + mQueue[mWrPtr] = queue_s(iv, cmd, false); } uint8_t getFillState(void) { - DPRINTLN(DBG_INFO, "wr: " + String(mWrPtr) + ", rd: " + String(mRdPtr)); + //DPRINTLN(DBG_INFO, "wr: " + String(mWrPtr) + ", rd: " + String(mRdPtr)); return abs(mRdPtr - mWrPtr); } @@ -45,11 +45,10 @@ class CommQueue { uint8_t cmd; uint8_t attempts; uint32_t ts; - bool delOnPop; bool isDevControl; queue_s() {} - queue_s(Inverter<> *i, uint8_t c, bool d, bool dev) : - iv(i), cmd(c), attempts(5), ts(0), delOnPop(d), isDevControl(dev) {} + queue_s(Inverter<> *i, uint8_t c, bool dev) : + iv(i), cmd(c), attempts(5), ts(0), isDevControl(dev) {} }; protected: @@ -78,8 +77,8 @@ class CommQueue { cb(true, &mQueue[mRdPtr]); } - void cmdDone(bool force = false) { - if(!mQueue[mRdPtr].delOnPop && !force) { + void cmdDone(bool keep = false) { + if(keep) { mQueue[mRdPtr].attempts = 5; add(mQueue[mRdPtr]); // add to the end again } diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 3e95b665..23254922 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -30,9 +30,9 @@ class Communication : public CommQueue<> { mInverterGap = inverterGap; } - void addImportant(Inverter<> *iv, uint8_t cmd, bool delOnPop = true) { + void addImportant(Inverter<> *iv, uint8_t cmd) { mState = States::RESET; // cancel current operation - CommQueue::addImportant(iv, cmd, delOnPop); + CommQueue::addImportant(iv, cmd); } void addPayloadListener(payloadListenerType cb) { @@ -84,7 +84,7 @@ class Communication : public CommQueue<> { q->iv->curFrmCnt = 0; mIsRetransmit = false; if(NULL == q->iv->radio) - cmdDone(true); // can't communicate while radio is not defined! + cmdDone(false); // can't communicate while radio is not defined! mState = States::START; break; @@ -177,6 +177,7 @@ class Communication : public CommQueue<> { closeRequest(q, true); else closeRequest(q, false); + q->iv->radio->mBufCtrl.pop(); return; // don't wait for empty buffer } else if(IV_MI == q->iv->ivGen) { if(parseMiFrame(p, q)) @@ -399,8 +400,6 @@ class Communication : public CommQueue<> { DBGPRINT(F("CRC Error ")); if(q->attempts == 0) { DBGPRINTLN(F("-> Fail")); - /*q->iv->radioStatistics.rxFail++; // got fragments but not complete response - cmdDone();*/ closeRequest(q, false); } else @@ -502,16 +501,19 @@ class Communication : public CommQueue<> { q->iv->radioStatistics.rxSuccess++; else if(q->iv->mGotFragment) q->iv->radioStatistics.rxFail++; // got no complete payload - else { + else q->iv->radioStatistics.rxFailNoAnser++; // got nothing - } mWaitTimeout = millis() + *mInverterGap; - cmdDone(q->delOnPop); + bool keep = false; + if(q->isDevControl) + keep = !crcPass; + + cmdDone(keep); q->iv->mGotFragment = false; q->iv->mGotLastMsg = false; q->iv->miMultiParts = 0; - mIsRetransmit = false; + mIsRetransmit = false; mFirstTry = false; // for correct reset mState = States::RESET; DBGPRINTLN(F("-----")); @@ -836,7 +838,7 @@ class Communication : public CommQueue<> { //closeRequest(iv, iv->miMultiParts > 5); //mHeu.setGotAll(iv); - //cmdDone(true); + //cmdDone(false); if(NULL != mCbPayload) (mCbPayload)(RealTimeRunData_Debug, iv); diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 4fe3ea58..d0387aa4 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -138,7 +138,7 @@ class HmRadio : public Radio { startMicros = micros(); } // not finished but time is over - mRxChIdx = 1; + mRxChIdx = (mRxChIdx + 1) % RF_CHANNELS; return; } From b3ceadadd4a533a95f4a016afe3157d686be8092 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 23 Dec 2023 14:53:47 +0100 Subject: [PATCH 2/8] 0.8.28 * fix bug heuristic * add version information to clipboard once 'copy' was clicked --- src/CHANGES.md | 4 ++++ src/defines.h | 2 +- src/hm/hmRadio.h | 6 +++--- src/web/html/serial.html | 2 ++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 95265968..83917be9 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.8.28 - 2023-12-23 +* fix bug heuristic +* add version information to clipboard once 'copy' was clicked + ## 0.8.27 - 2023-12-18 * fix set power limit #1276 diff --git a/src/defines.h b/src/defines.h index b6e5b8aa..b7ab4e55 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 27 +#define VERSION_PATCH 28 //------------------------------------- typedef struct { diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index d0387aa4..dd83544f 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -290,14 +290,14 @@ class HmRadio : public Radio { updateCrcs(&len, appendCrc16); // set TX and RX channels - mTxChIdx = mRfChLst[iv->heuristics.txRfChId]; + mTxChIdx = iv->heuristics.txRfChId; if(*mSerialDebug) { DPRINT_IVID(DBG_INFO, iv->id); DBGPRINT(F("TX ")); DBGPRINT(String(len)); DBGPRINT(" CH"); - DBGPRINT(String(mTxChIdx)); + DBGPRINT(String(mRfChLst[mTxChIdx])); DBGPRINT(F(" | ")); if(*mPrintWholeTrace) { if(*mPrivacyMode) @@ -309,7 +309,7 @@ class HmRadio : public Radio { } mNrf24->stopListening(); - mNrf24->setChannel(mTxChIdx); + mNrf24->setChannel(mRfChLst[mTxChIdx]); mNrf24->openWritingPipe(reinterpret_cast(&iv->radioId.u64)); mNrf24->startWrite(mTxBuf, len, false); // false = request ACK response mMillis = millis(); diff --git a/src/web/html/serial.html b/src/web/html/serial.html index 675ee668..966ffecd 100644 --- a/src/web/html/serial.html +++ b/src/web/html/serial.html @@ -27,6 +27,7 @@ var mAutoScroll = true; var con = document.getElementById("serial"); var exeOnce = true; + var version, build; function parseGeneric(obj) { var up = obj["ts_uptime"]; @@ -65,6 +66,7 @@ this.value = (mAutoScroll) ? "autoscroll" : "manual scroll"; }); document.getElementById("copy").addEventListener("click", function() { + con.value = version + " - " + build + "\n---------------\n" + con.value; if (window.clipboardData && window.clipboardData.setData) { return window.clipboardData.setData("Text", text); } else if (document.queryCommandSupported && document.queryCommandSupported("copy")) { From 5a52677cbda98775c04ea3abd3a17d4503131609 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 23 Dec 2023 15:57:40 +0100 Subject: [PATCH 3/8] 0.8.28 * add get loss rate @rejoe2 * improve communication @rejoe2 --- src/CHANGES.md | 2 ++ src/hm/CommQueue.h | 4 +-- src/hm/Communication.h | 65 ++++++++++++++++++++++++++++++----- src/hm/hmDefines.h | 2 ++ src/hm/hmInverter.h | 42 ++++++++++++++++++++++ src/hm/hmRadio.h | 17 ++++++--- src/hms/hmsRadio.h | 8 ++++- src/publisher/pubMqttIvData.h | 5 +++ src/web/html/serial.html | 2 ++ 9 files changed, 131 insertions(+), 16 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 83917be9..95fcae66 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -3,6 +3,8 @@ ## 0.8.28 - 2023-12-23 * fix bug heuristic * add version information to clipboard once 'copy' was clicked +* add get loss rate @rejoe2 +* improve communication @rejoe2 ## 0.8.27 - 2023-12-18 * fix set power limit #1276 diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h index 37ffda62..bb815a7e 100644 --- a/src/hm/CommQueue.h +++ b/src/hm/CommQueue.h @@ -94,8 +94,8 @@ class CommQueue { mQueue[mRdPtr].attempts--; } - void incrAttempt(void) { - mQueue[mRdPtr].attempts++; + void incrAttempt(uint8_t attempts = 1) { + mQueue[mRdPtr].attempts += attempts; } void inc(uint8_t *ptr) { diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 23254922..818b396d 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -14,7 +14,7 @@ #define MI_TIMEOUT 250 // timeout for MI type requests #define FRSTMSG_TIMEOUT 150 // how long to wait for first msg to be received #define DEFAULT_TIMEOUT 500 // timeout for regular requests -#define SINGLEFR_TIMEOUT 65 // timeout for single frame requests +#define SINGLEFR_TIMEOUT 100 // timeout for single frame requests #define MAX_BUFFER 250 typedef std::function *)> payloadListenerType; @@ -59,7 +59,7 @@ class Communication : public CommQueue<> { mLastEmptyQueueMillis = millis(); mPrintSequenceDuration = true; - uint16_t timeout = (q->iv->ivGen == IV_MI) ? MI_TIMEOUT : ((q->iv->mGotFragment && q->iv->mGotLastMsg) || mIsRetransmit) ? SINGLEFR_TIMEOUT : DEFAULT_TIMEOUT; + uint16_t timeout = (q->iv->ivGen == IV_MI) ? MI_TIMEOUT : (((q->iv->mGotFragment && q->iv->mGotLastMsg) || mIsRetransmit) ? SINGLEFR_TIMEOUT : ((q->cmd != AlarmData) ? DEFAULT_TIMEOUT : (1.5 * DEFAULT_TIMEOUT))); uint16_t timeout_min = (q->iv->ivGen == IV_MI) ? MI_TIMEOUT : ((q->iv->mGotFragment || mIsRetransmit)) ? SINGLEFR_TIMEOUT : FRSTMSG_TIMEOUT; /*if(mDebugState != mState) { @@ -85,6 +85,8 @@ class Communication : public CommQueue<> { mIsRetransmit = false; if(NULL == q->iv->radio) cmdDone(false); // can't communicate while radio is not defined! + q->iv->mCmd = q->cmd; + q->iv->mIsSingleframeReq = false; mState = States::START; break; @@ -159,8 +161,9 @@ class Communication : public CommQueue<> { closeRequest(q, false); break; } - mIsRetransmit = false; mFirstTry = false; // for correct reset + if((IV_MI != q->iv->ivGen) || (0 == q->attempts)) + mIsRetransmit = false; while(!q->iv->radio->mBufCtrl.empty()) { packet_t *p = &q->iv->radio->mBufCtrl.front(); @@ -168,6 +171,7 @@ class Communication : public CommQueue<> { if(validateIvSerial(&p->packet[1], q->iv)) { q->iv->radioStatistics.frmCnt++; + q->iv->mDtuRxCnt++; if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command if(parseFrame(p)) @@ -197,15 +201,25 @@ 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((millis() > mWaitTimeout && mIsRetransmit) || !mIsRetransmit) { + miRepeatRequest(q); + return; + } } else { + mHeu.evalTxChQuality(q->iv, true, (4 - q->attempts), q->iv->curFrmCnt); if(((q->cmd == 0x39) && (q->iv->type == INV_TYPE_4CH)) || ((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; } - closeRequest(q, true); + if(fastNext) + miNextRequest(q->iv->type == INV_TYPE_4CH ? MI_REQ_4CH : MI_REQ_CH1, q); + else + closeRequest(q, true); } } @@ -247,6 +261,8 @@ class Communication : public CommQueue<> { DBGPRINT(String(q->attempts)); DBGPRINTLN(F(" attempts left)")); } + if (!mIsRetransmit) + q->iv->mIsSingleframeReq = true; sendRetransmit(q, (framnr-1)); mIsRetransmit = true; mlastTO_min = timeout_min; @@ -290,7 +306,9 @@ class Communication : public CommQueue<> { else ah::dumpBuf(p->packet, p->len); } else { - DBGPRINT(F("| ")); + DBGPRINT(F("| 0x")); + DHEX(p->packet[0]); + DBGPRINT(F(" ")); DBGHEXLN(p->packet[9]); } } @@ -331,8 +349,11 @@ class Communication : public CommQueue<> { return false; // CRC8 is wrong, frame invalid } - if((*frameId & ALL_FRAMES) == ALL_FRAMES) + if((*frameId & ALL_FRAMES) == ALL_FRAMES) { mMaxFrameId = (*frameId & 0x7f); + if(mMaxFrameId > 8) // large payloads, e.g. AlarmData + incrAttempt(mMaxFrameId - 6); + } frame_t *f = &mLocalBuf[(*frameId & 0x7f) - 1]; memcpy(f->buf, &p->packet[10], p->len-11); @@ -373,7 +394,7 @@ class Communication : public CommQueue<> { accepted = false; DPRINT_IVID(DBG_INFO, q->iv->id); - DBGPRINT(F(" has ")); + DBGPRINT(F("has ")); if(!accepted) DBGPRINT(F("not ")); DBGPRINT(F("accepted power limit set point ")); DBGPRINT(String(q->iv->powerLimit[0])); @@ -446,8 +467,14 @@ class Communication : public CommQueue<> { record_t<> *rec = q->iv->getRecordStruct(q->cmd); if(NULL == rec) { - DPRINTLN(DBG_ERROR, F("record is NULL!")); - closeRequest(q, false); + if(GetLossRate == q->cmd) { + q->iv->parseGetLossRate(mPayload, len); + //closeRequest(q, true); //@lumapu: Activating would crash most esp's! + return; + } else { + DPRINTLN(DBG_ERROR, F("record is NULL!")); + closeRequest(q, false); + } return; } if((rec->pyldLen != len) && (0 != rec->pyldLen)) { @@ -688,6 +715,7 @@ 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, (4 - q->attempts), 1); miNextRequest((p->packet[0] - ALL_FRAMES + 1), q); } else { q->iv->miMultiParts = 7; // indicate we are ready @@ -696,6 +724,7 @@ class Communication : public CommQueue<> { } 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, (4 - q->attempts), q->iv->curFrmCnt); //use also miMultiParts here for better statistics? //mHeu.setGotFragment(q->iv); } else { // first data msg for 1ch, 2nd for 2ch @@ -732,6 +761,24 @@ class Communication : public CommQueue<> { //mState = States::WAIT; } + void miRepeatRequest(const queue_s *q) { + setAttempt(); // 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("resend request (")); + DBGPRINT(String(q->attempts)); + DBGPRINT(F(" attempts left): 0x")); + DBGHEXLN(q->cmd); + } + + q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true); + + mWaitTimeout = millis() + MI_TIMEOUT; + mWaitTimeout_min = mWaitTimeout; + //mState = States::WAIT; + 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) { //uint8_t status = (p->packet[11] << 8) + p->packet[12]; uint16_t statusMi = 3; // regular status for MI, change to 1 later? diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index c00f4940..55259289 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -139,6 +139,8 @@ const byteAssign_t AlarmDataAssignment[] = { #define HMALARMDATA_PAYLOAD_LEN 0 // 0: means check is off #define ALARM_LOG_ENTRY_SIZE 12 +#define HMGETLOSSRATE_PAYLOAD_LEN 4 +#define AHOY_GET_LOSS_INTERVAL 10 //------------------------------------- // HM300, HM350, HM400 diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 66496340..2ae60e10 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -133,12 +133,20 @@ class Inverter { bool mGotFragment; // shows if inverter has sent at least one fragment uint8_t curFrmCnt; // count received frames in current loop bool mGotLastMsg; // shows if inverter has already finished transmission cycle + uint8_t mCmd; // holds the command to send + 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 + uint16_t mIvRxCnt; // last iv rx frames (from GetLossRate) + uint16_t mIvTxCnt; // last iv tx frames (from GetLossRate) + uint16_t mDtuRxCnt; // cur dtu rx frames (since last GetLossRate) + uint16_t mDtuTxCnt; // cur dtu tx frames (since last getLoassRate) + uint8_t mGetLossInterval; // request iv every AHOY_GET_LOSS_INTERVAL RealTimeRunData_Debu + static uint32_t *timestamp; // system timestamp static cfgInst_t *generalConfig; // general inverter configuration from setup @@ -159,8 +167,14 @@ class Inverter { rssi = -127; miMultiParts = 0; mGotLastMsg = false; + mCmd = InitDataState; + mIsSingleframeReq = false; radio = NULL; commEnabled = true; + mIvRxCnt = 0; + mIvTxCnt = 0; + mDtuRxCnt = 0; + mDtuTxCnt = 0; memset(&radioStatistics, 0, sizeof(statistics_t)); memset(heuristics.txRfQuality, -6, 5); @@ -174,6 +188,7 @@ class Inverter { cb(devControlCmd, true); mDevControlRequest = false; } else if (IV_MI != ivGen) { + mGetLossInterval++; if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0)) cb(AlarmData, false); // get last alarms else if(0 == getFwVersion()) @@ -185,8 +200,12 @@ class Inverter { else if(InitDataState != devControlCmd) { cb(devControlCmd, false); // custom command which was received by API devControlCmd = InitDataState; + mGetLossInterval = 1; } 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(GetLossRate, false); } else cb(RealTimeRunData_Debug, false); // get live data } else { @@ -574,6 +593,29 @@ class Inverter { memset(mLastYD, 0, sizeof(float) * 6); } + bool parseGetLossRate(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]; + + if (mIvRxCnt || mIvTxCnt) { // there was successful GetLossRate in the past + DPRINT_IVID(DBG_INFO, id); + DBGPRINTLN("Inv loss: " + + String (mDtuTxCnt - (rxCnt - mIvRxCnt)) + " of " + + String (mDtuTxCnt) + ", DTU loss: " + + String (txCnt - mIvTxCnt - mDtuRxCnt) + " of " + + String (txCnt - mIvTxCnt)); + } + + mIvRxCnt = rxCnt; + mIvTxCnt = txCnt; + mDtuRxCnt = 0; // start new interval + mDtuTxCnt = 0; // start new interval + return true; + } + return false; + } + uint16_t parseAlarmLog(uint8_t id, uint8_t pyld[], uint8_t len) { uint8_t startOff = 2 + id * ALARM_LOG_ENTRY_SIZE; if((startOff + ALARM_LOG_ENTRY_SIZE) > len) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index dd83544f..6db39d7f 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -119,9 +119,11 @@ class HmRadio : public Radio { if(NULL == mLastIv) // prevent reading on NULL object! return; - uint32_t startMicros = micros(); - uint32_t loopMillis = millis(); - while ((millis() - loopMillis) < 400) { + uint32_t startMicros = micros(); + uint32_t loopMillis = millis(); + uint32_t outerLoopTimeout = (mLastIv->mIsSingleframeReq) ? 100 : ((mLastIv->mCmd != AlarmData) ? 400 : 600); + + while ((millis() - loopMillis) < outerLoopTimeout) { while ((micros() - startMicros) < 5110) { // listen (4088us or?) 5110us to each channel if (mIrqRcvd) { mIrqRcvd = false; @@ -304,8 +306,14 @@ class HmRadio : public Radio { ah::dumpBuf(mTxBuf, len, 1, 4); else ah::dumpBuf(mTxBuf, len); - } else + } else { + DBGPRINT(F("0x")); + DHEX(mTxBuf[0]); + DBGPRINT(F(" 0x")); + DHEX(mTxBuf[10]); + DBGPRINT(F(" ")); DBGHEXLN(mTxBuf[9]); + } } mNrf24->stopListening(); @@ -315,6 +323,7 @@ class HmRadio : public Radio { mMillis = millis(); mLastIv = iv; + iv->mDtuTxCnt++; } uint64_t getIvId(Inverter<> *iv) { diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 40200085..80a2ecd9 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -95,8 +95,13 @@ class CmtRadio : public Radio { ah::dumpBuf(mTxBuf, len, 1, 4); else ah::dumpBuf(mTxBuf, len); - } else + } else { + DBGPRINT(F("0x")); + DHEX(mTxBuf[0]); + DBGPRINT(F(" 0x")); + DHEX(mTxBuf[10]); DBGHEXLN(mTxBuf[9]); + } } uint8_t status = mCmt.tx(mTxBuf, len); @@ -107,6 +112,7 @@ class CmtRadio : public Radio { if(CMT_ERR_RX_IN_FIFO == status) mIrqRcvd = true; } + iv->mDtuTxCnt++; } uint64_t getIvId(Inverter<> *iv) { diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 0ac6d306..3600e22c 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -127,6 +127,11 @@ class PubMqttIvData { void stateSend() { record_t<> *rec = mIv->getRecordStruct(mCmd); + if(rec == NULL) { + if (mCmd != GetLossRate) + DPRINT(DBG_WARN, "unknown record to publish!"); + return; + } uint32_t lastTs = mIv->getLastTs(rec); bool pubData = (lastTs > 0); if (mCmd == RealTimeRunData_Debug) diff --git a/src/web/html/serial.html b/src/web/html/serial.html index 966ffecd..ef7aa4c3 100644 --- a/src/web/html/serial.html +++ b/src/web/html/serial.html @@ -48,6 +48,8 @@ exeOnce = false; setTimeOffset(); } + version = obj.version; + build = obj.build; } function setTimeOffset() { From 8b379f768e281030545e9796da0f80d1dde7af42 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 23 Dec 2023 16:47:07 +0100 Subject: [PATCH 4/8] 0.8.29 * fix MqTT generic topic `comm_disabled` #1265 #1286 * potential fix of #1285 (reset yield day) * fix fraction of yield correction #1280 --- src/CHANGES.md | 5 +++++ src/app.cpp | 2 +- src/defines.h | 2 +- src/hm/hmInverter.h | 5 +++++ src/publisher/pubMqtt.h | 14 +++++++++----- src/publisher/pubMqttIvData.h | 2 +- src/web/RestApi.h | 2 +- src/web/html/setup.html | 2 +- 8 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 95fcae66..e9563510 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.8.29 - 2023-12-23 +* fix MqTT generic topic `comm_disabled` #1265 #1286 +* potential fix of #1285 (reset yield day) +* fix fraction of yield correction #1280 + ## 0.8.28 - 2023-12-23 * fix bug heuristic * add version information to clipboard once 'copy' was clicked diff --git a/src/app.cpp b/src/app.cpp index 5a183cf4..88065e20 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -305,7 +305,7 @@ void app::tickMidnight(void) { continue; // skip to next inverter // reset alarms - if(InverterStatus::OFF == iv->status) + if(InverterStatus::OFF == iv->getStatus()) iv->resetAlarms(); // clear max values diff --git a/src/defines.h b/src/defines.h index b7ab4e55..2b304f9f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 28 +#define VERSION_PATCH 29 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 2ae60e10..776b9c6f 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -458,6 +458,11 @@ class Inverter { return producing; } + InverterStatus getStatus(){ + isProducing(); // recalculate status + return status; + } + uint16_t getFwVersion() { record_t<> *rec = getRecordStruct(InverterDevInform_All); return getChannelFieldValue(CH0, FLD_FW_VERSION, rec); diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 92f5de2f..e062439c 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -153,6 +153,10 @@ class PubMqtt { publish(mSubTopic, ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true); } + + snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "comm_disabled"); + publish(mSubTopic, (((*mUtcTimestamp > (sunset + offs)) || (*mUtcTimestamp < (sunrise - offs))) ? dict[STR_TRUE] : dict[STR_FALSE]), true); + return true; } @@ -483,22 +487,22 @@ class PubMqtt { continue; // skip to next inverter // inverter status - iv->isProducing(); // recalculate status - if (InverterStatus::OFF < iv->status) + InverterStatus status = iv->getStatus(); + if (InverterStatus::OFF < status) anyAvail = true; else // inverter is enabled but not available allAvail = false; - if(mLastIvState[id] != iv->status) { + if(mLastIvState[id] != status) { // if status changed from producing to not producing send last data immediately if (InverterStatus::WAS_PRODUCING == mLastIvState[id]) sendData(iv, RealTimeRunData_Debug); - mLastIvState[id] = iv->status; + mLastIvState[id] = status; changed = true; snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name); - snprintf(mVal, 40, "%d", (uint8_t)iv->status); + snprintf(mVal, 40, "%d", (uint8_t)status); publish(mSubTopic, mVal, true); } } diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 3600e22c..9a364ec9 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -146,7 +146,7 @@ class PubMqttIvData { // calculate total values for RealTimeRunData_Debug if (CH0 == rec->assign[mPos].ch) { - if(mIv->status > InverterStatus::STARTING) { + if(mIv->getStatus() > InverterStatus::STARTING) { if(mIv->config->add2Total) { mTotalFound = true; switch (rec->assign[mPos].fieldId) { diff --git a/src/web/RestApi.h b/src/web/RestApi.h index e98b00fe..990f3e92 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -421,7 +421,7 @@ class RestApi { obj[F("max_pwr")] = iv->getMaxPower(); obj[F("ts_last_success")] = rec->ts; obj[F("generation")] = iv->ivGen; - obj[F("status")] = (uint8_t)iv->status; + obj[F("status")] = (uint8_t)iv->getStatus(); obj[F("alarm_cnt")] = iv->alarmCnt; obj[F("rssi")] = iv->rssi; diff --git a/src/web/html/setup.html b/src/web/html/setup.html index a1e42a5c..8187fe3b 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -676,7 +676,7 @@ ml("td", {}, String(i+1)), ml("td", {}, ml("input", {name: "ch_p"+i, class: "text", type: "number", max: 999, value: obj.ch_max_pwr[i]}, null)), ml("td", {}, ml("input", {name: "ch_n"+i, class: "text", type: "text", maxlength: 15, value: (undefined === obj.ch_name[i]) ? "" : obj.ch_name[i]}, null)), - ml("td", {}, ml("input", {name: "yld_c"+i, class: "text", type: "number", max: 999999, value: obj.ch_yield_cor[i]}, null)) + ml("td", {}, ml("input", {name: "yld_c"+i, class: "text", type: "number", max: 999999, value: obj.ch_yield_cor[i], step: "0.001"}, null)) ])); } From e5176b7430ab131cca5dd0800820d103dc99d049 Mon Sep 17 00:00:00 2001 From: kscholty Date: Sat, 23 Dec 2023 17:33:00 +0100 Subject: [PATCH 5/8] Added ESP32-C3 chip --- src/platformio.ini | 15 ++++++++++++ src/web/html/setup.html | 53 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/platformio.ini b/src/platformio.ini index 54b63a22..2b4b25cf 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -123,6 +123,21 @@ build_flags = ${env.build_flags} monitor_filters = esp32_exception_decoder +[env:esp32-c3-mini] +platform = espressif32@6.4.0 +board = lolin_c3_mini +build_flags = ${env.build_flags} + -DUSE_HSPI_FOR_EPD + -DDEF_NRF_CS_PIN=5 + -DDEF_NRF_CE_PIN=0 + -DDEF_NRF_IRQ_PIN=1 + -DDEF_NRF_MISO_PIN=3 + -DDEF_NRF_MOSI_PIN=4 + -DDEF_NRF_SCLK_PIN=2 +monitor_filters = + esp32_exception_decoder + + [env:opendtufusion] platform = espressif32@6.4.0 board = esp32-s3-devkitc-1 diff --git a/src/web/html/setup.html b/src/web/html/setup.html index a1e42a5c..638ef8e0 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -435,6 +435,31 @@ [47, "GPIO47"], [48, "GPIO48"], ]; + var esp32c3pins = [ + [255, "off / default"], + [0, "GPIO0"], + [1, "GPIO1"], + [2, "GPIO2"], + [3, "GPIO3"], + [4, "GPIO4"], + [5, "GPIO5"], + [6, "GPIO6"], + [7, "GPIO7"], + [8, "GPIO8"], + [9, "GPIO9"], + [10, "GPIO10"], + [11, "GPIO11"], + [12, "GPIO12 (PSRAM/FLASH)"], + [13, "GPIO13 (PSRAM/FLASH)"], + [14, "GPIO14 (PSRAM/FLASH)"], + [15, "GPIO15 (PSRAM/FLASH)"], + [16, "GPIO16 (PSRAM/FLASH)"], + [17, "GPIO17 (PSRAM/FLASH)"], + [18, "GPIO18 (DONT USE - USB-)"], + [19, "GPIO19 (DONT USE - USB+)"], + [20, "GPIO20 (RX)"], + [21, "GPIO21 (TX)"], + ]; /*ENDIF_ESP32*/ var nrfPa = [ [0, "MIN (recommended)"], @@ -872,13 +897,17 @@ function parsePinout(obj, type, system) { var e = document.getElementById("pinout"); + var pinList = esp32pins; + if("ESP8266" == type) pinList = esp8266pins; + else if ("ESP32-S3" == system["chip_model"]) pinList = esp32s3pins; + else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins; pins = [['led0', 'pinLed0', 'At least one inverter is producing'], ['led1', 'pinLed1', 'MqTT connected']]; for(p of pins) { e.append( ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, p[2]), ml("div", {class: "col-12 col-sm-9"}, - sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj[p[0]]) + sel(p[1], pinList, obj[p[0]]) ) ]) ); @@ -898,6 +927,11 @@ var en = inp("nrfEnable", null, null, ["cb"], "nrfEnable", "checkbox"); en.checked = obj["en"]; + var pinList = esp32pins; + if("ESP8266" == type) pinList = esp8266pins; + else if ("ESP32-S3" == system["chip_model"]) pinList = esp32s3pins; + else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins; + e.replaceChildren ( ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-8 col-sm-3 my-2"}, "NRF24 Enable"), @@ -915,7 +949,7 @@ ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), ml("div", {class: "col-12 col-sm-9"}, - sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, objPin[p[0]]) + sel(p[1], pinList, objPin[p[0]]) ) ]) ); @@ -926,6 +960,10 @@ function parseCmtRadio(obj, type, system) { var e = document.getElementById("cmt"); var en = inp("cmtEnable", null, null, ["cb"], "cmtEnable", "checkbox"); + var pinList = esp32pins; + if ("ESP32-S3" == system["chip_model"]) pinList = esp32s3pins; + else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins; + en.checked = obj["en"]; e.replaceChildren ( @@ -940,7 +978,7 @@ ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), ml("div", {class: "col-12 col-sm-9"}, - sel(p[1], (("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins), obj[p[0]]) + sel(p[1], pinList, obj[p[0]]) ) ]) ); @@ -954,6 +992,11 @@ } function parseDisplay(obj, type, system) { + var pinList = esp32pins; + if("ESP8266" == type) pinList = esp8266pirpins; + else if ("ESP32-S3" == system["chip_model"]) pinList = esp32s3pins; + else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins; + for(var i of ["disp_pwr"]) document.getElementsByName(i)[0].checked = obj[i]; @@ -968,7 +1011,7 @@ ml("div", {class: "row mb-3", id: "row_" + p[1]}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), ml("div", {class: "col-12 col-sm-9"}, - sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj[p[1]]) + sel(p[1], pinList, obj[p[1]]) ) ]) ); @@ -1018,7 +1061,7 @@ document.getElementById("pirPin").append( ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, "PIR sensor"), - ml("div", {class: "col-12 col-sm-9"}, sel("pir_pin", ("ESP8266" == type) ? esp8266pirpins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj["pir_pin"])) + ml("div", {class: "col-12 col-sm-9"}, sel("pir_pin", pinList, obj["pir_pin"])) ]) ); From 4f75ce7dd1ab528018644d285bf6571c1d543e3c Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 28 Dec 2023 02:21:37 +0100 Subject: [PATCH 6/8] 0.8.29 * fix crash if `getLossRate` was read from inverter #1288 #1290 * reduce reload time for opendtufusion ethernet variant to 5 seconds * added basic grid parser --- scripts/convertHtml.py | 2 +- src/CHANGES.md | 5 +- src/hm/Communication.h | 29 +- src/hm/hmRadio.h | 7 +- src/hms/hmsRadio.h | 5 +- src/web/RestApi.h | 11 +- src/web/html/api.js | 8 + src/web/html/grid_info.json | 764 ++++++++++++++++++++++++++++++++ src/web/html/save.html | 4 +- src/web/html/visualization.html | 75 +++- src/web/web.h | 12 + 11 files changed, 876 insertions(+), 46 deletions(-) create mode 100644 src/web/html/grid_info.json diff --git a/scripts/convertHtml.py b/scripts/convertHtml.py index 70d5f6e2..6eaa92a3 100644 --- a/scripts/convertHtml.py +++ b/scripts/convertHtml.py @@ -159,7 +159,7 @@ if os.path.exists(wd): # grab all files with following extensions os.chdir('./web/html') -types = ('*.html', '*.css', '*.js', '*.ico') # the tuple of file types +types = ('*.html', '*.css', '*.js', '*.ico', '*.json') # the tuple of file types files_grabbed = [] for files in types: files_grabbed.extend(glob.glob(files)) diff --git a/src/CHANGES.md b/src/CHANGES.md index e9563510..99b7dc64 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,9 +1,12 @@ # Development Changes -## 0.8.29 - 2023-12-23 +## 0.8.29 - 2023-12-27 * fix MqTT generic topic `comm_disabled` #1265 #1286 * potential fix of #1285 (reset yield day) * fix fraction of yield correction #1280 +* fix crash if `getLossRate` was read from inverter #1288 #1290 +* reduce reload time for opendtufusion ethernet variant to 5 seconds +* added basic grid parser ## 0.8.28 - 2023-12-23 * fix bug heuristic diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 818b396d..23d20004 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -117,28 +117,6 @@ class Communication : public CommQueue<> { break; case States::WAIT: - /*if(millis() > mWaitTimeout_min) { - if(mIsRetransmit) { // we already have been through... - mWaitTimeout = mWaitTimeout_min; - } else if(q->iv->mGotFragment) { // nothing received yet? - if(q->iv->mGotLastMsg) { - //mState = States::CHECK_FRAMES; - mWaitTimeout = mWaitTimeout_min; - } - } else if(mFirstTry) { - if(*mSerialDebug) { - DPRINT_IVID(DBG_INFO, q->iv->id); - DBGPRINT(String(millis() - mWaitTimeout_min + mlastTO_min)); - DBGPRINTLN(F("ms - second try")); - } - mFirstTry = false; - mlastTO_min = timeout_min; - q->iv->radioStatistics.retransmits++; // got nothing - mState = States::START; - break; - } - - }*/ if(millis() < mWaitTimeout) return; mState = States::CHECK_FRAMES; @@ -187,7 +165,7 @@ class Communication : public CommQueue<> { if(parseMiFrame(p, q)) q->iv->curFrmCnt++; } - } //else // serial does not match + } //else -> serial does not match q->iv->radio->mBufCtrl.pop(); yield(); @@ -221,7 +199,6 @@ class Communication : public CommQueue<> { else closeRequest(q, true); } - } } @@ -271,7 +248,7 @@ class Communication : public CommQueue<> { compilePayload(q); - if((NULL != mCbPayload) && (GridOnProFilePara != q->cmd)) + if((NULL != mCbPayload) && (GridOnProFilePara != q->cmd) && (GetLossRate != q->cmd)) (mCbPayload)(q->cmd, q->iv); closeRequest(q, true); @@ -306,7 +283,7 @@ class Communication : public CommQueue<> { else ah::dumpBuf(p->packet, p->len); } else { - DBGPRINT(F("| 0x")); + DBGPRINT(F("| ")); DHEX(p->packet[0]); DBGPRINT(F(" ")); DBGHEXLN(p->packet[9]); diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 6db39d7f..1c4e26e9 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -98,7 +98,7 @@ class HmRadio : public Radio { if(mNrf24->isChipConnected()) { DPRINTLN(DBG_INFO, F("Radio Config:")); mNrf24->printPrettyDetails(); - DPRINT(DBG_INFO, F("DTU_SN: 0x")); + DPRINT(DBG_INFO, F("DTU_SN: ")); DBGPRINTLN(String(mDtuSn, HEX)); } else DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); @@ -152,7 +152,7 @@ class HmRadio : public Radio { void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) { DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINT(F("sendControlPacket cmd: 0x")); + DBGPRINT(F("sendControlPacket cmd: ")); DBGHEXLN(cmd); initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME); uint8_t cnt = 10; @@ -307,9 +307,8 @@ class HmRadio : public Radio { else ah::dumpBuf(mTxBuf, len); } else { - DBGPRINT(F("0x")); DHEX(mTxBuf[0]); - DBGPRINT(F(" 0x")); + DBGPRINT(F(" ")); DHEX(mTxBuf[10]); DBGPRINT(F(" ")); DBGHEXLN(mTxBuf[9]); diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 80a2ecd9..2b147107 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -42,7 +42,7 @@ class CmtRadio : public Radio { } void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) { - DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x")); + DPRINT(DBG_INFO, F("sendControlPacket cmd: ")); DBGHEXLN(cmd); initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME); uint8_t cnt = 10; @@ -96,9 +96,8 @@ class CmtRadio : public Radio { else ah::dumpBuf(mTxBuf, len); } else { - DBGPRINT(F("0x")); DHEX(mTxBuf[0]); - DBGPRINT(F(" 0x")); + DBGPRINT(F(" ")); DHEX(mTxBuf[10]); DBGHEXLN(mTxBuf[9]); } diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 990f3e92..f2c193cd 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -323,9 +323,14 @@ class RestApi { void getHtmlSave(AsyncWebServerRequest *request, JsonObject obj) { getGeneric(request, obj.createNestedObject(F("generic"))); - obj["pending"] = (bool)mApp->getSavePending(); - obj["success"] = (bool)mApp->getLastSaveSucceed(); - obj["reboot"] = (bool)mApp->getShouldReboot(); + obj[F("pending")] = (bool)mApp->getSavePending(); + obj[F("success")] = (bool)mApp->getLastSaveSucceed(); + obj[F("reboot")] = (bool)mApp->getShouldReboot(); + #if defined(ETHERNET) && defined(CONFIG_IDF_TARGET_ESP32S3) + obj[F("reload")] = 5; + #else + obj[F("reload")] = 20; + #endif } void getReboot(AsyncWebServerRequest *request, JsonObject obj) { diff --git a/src/web/html/api.js b/src/web/html/api.js index e76aab2c..b059cc69 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -175,6 +175,14 @@ function getAjax(url, ptr, method="GET", json=null) { } } +const getJSON = async url => { + const re = await fetch(url); + if(!re.ok) + throw new Error(re.statusText); + const data = re.json(); + return data; +} + /** * CREATE DOM FUNCTIONS */ diff --git a/src/web/html/grid_info.json b/src/web/html/grid_info.json new file mode 100644 index 00000000..adb68393 --- /dev/null +++ b/src/web/html/grid_info.json @@ -0,0 +1,764 @@ +{ + "type": [ + {"0x0300": "DE_VDE4105_2018"}, + {"0x0a00": "DE NF_EN_50549-1:2019"}, + {"0x0c00": "AT_TOR_Erzeuger_default"}, + {"0x0d04": "France NF_EN_50549-1:2019"}, + {"0x1200": "2.0.4 (EU_EN50438)"}, + {"0x3700": "2.0.0 (CH_NA EEA-NE7–CH2020)"} + ], + "grp_codes": [ + {"0x00": "Voltage H/LVRT"}, + {"0x10": "Frequency H/LFRT"}, + {"0x20": "Islanding Detection"}, + {"0x30": "Reconnection"}, + {"0x40": "Ramp Rates"}, + {"0x50": "Frequency Watt"}, + {"0x60": "Volt Watt"}, + {"0x70": "Active Power Control"}, + {"0x80": "Volt Var"}, + {"0x90": "Specified Power Factor"}, + {"0xa0": "Reactive Power Control"}, + {"0xb0": "Watt Power Factor"} + ], + "group": [ + { + "0x0003": [ + { + "name": "Nominal Voltage", + "div": 10, + "def": 230, + "unit": "V" + }, + { + "name": "Low Voltage 1", + "div": 10, + "min": 180, + "max": 207, + "def": 184, + "unit": "V" + }, + { + "name": "LV1 Maximum Trip Time", + "div": 10, + "def": 1.5, + "unit": "s" + }, + { + "name": "High Voltage 1", + "div": 10, + "min": 250, + "max": 270, + "def": 253, + "unit": "V" + }, + { + "name": "HV1 Maximum Trip Time", + "div": 10, + "min": 0.1, + "max": 100, + "def": 0.1, + "unit": "s" + }, + { + "name": "Low Voltage 2", + "div": 10, + "min": 80, + "max": 161, + "def": 104, + "unit": "V" + }, + { + "name": "LV2 Maximum Trip Time", + "div": 100, + "min": 0.1, + "max": 5, + "def": 0.3, + "unit": "s" + }, + { + "name": "High Voltage 2", + "div": 10, + "min": 230, + "max": 299, + "def": 276, + "unit": "V" + }, + { + "name": "HV2 Maximum Trip Time", + "div": 100, + "min": 0, + "max": 5, + "def": 0.05, + "unit": "s" + } + ] + }, + { + "0x000a": [ + { + "name": "Nominal Voltage", + "div": 10, + "def": 230, + "unit": "V" + }, + { + "name": "Low Voltage 1", + "div": 10, + "min": 160, + "max": 195.5, + "def": 184, + "unit": "V" + }, + { + "name": "LV1 Maximum Trip Time", + "div": 10, + "def": 3, + "unit": "s" + }, + { + "name": "High Voltage 1", + "div": 10, + "min": 270, + "max": 287.5, + "def": 287.5, + "unit": "V" + }, + { + "name": "HV1 Maximum Trip Time", + "div": 10, + "def": 0.1, + "unit": "s" + }, + { + "name": "Low Voltage 2", + "div": 10, + "max": 150, + "min": 100, + "def": 103.5, + "unit": "V" + }, + { + "name": "LV2 Maximum Trip Time", + "div": 100, + "def": 0.3, + "unit": "s" + }, + { + "name": "10 mins Average High Voltage", + "div": 10, + "min": 250, + "max": 270, + "def": 253, + "unit": "V" + } + ] + }, + { + "0x000c": [ + { + "name": "Nominal Voltage", + "div": 10, + "unit": "V" + }, + { + "name": "Low Voltage 1", + "div": 10, + "min": 180, + "max": 207, + "def": 184, + "unit": "V" + }, + { + "name": "LV1 Maximum Trip Time", + "div": 10, + "min": 0.1, + "max": 5, + "def": 1.5, + "unit": "s" + }, + { + "name": "High Voltage 1", + "div": 10, + "min": 250, + "max": 270, + "def": 253, + "unit": "V" + }, + { + "name": "HV1 Maximum Trip Time", + "div": 10, + "min": 0.1, + "max": 100, + "def": 3, + "unit": "s" + }, + { + "name": "Low Voltage 2", + "div": 10, + "min": 80, + "max": 161, + "def": 161, + "unit": "V" + }, + { + "name": "LV2 Maximum Trip Time", + "div": 100, + "min": 0.1, + "max": 5, + "def": 0.2, + "unit": "s" + }, + { + "name": "High Voltage 2", + "div": 10, + "min": 230, + "max": 299, + "def": 264.5, + "unit": "V" + }, + { + "name": "HV2 Maximum Trip Time", + "div": 100, + "min": 0.1, + "max": 5, + "def": 0.2, + "unit": "s" + }, + { + "name": "High Voltage 3", + "div": 10, + "def": 276, + "unit": "V" + }, + { + "name": "HV3 Maximum Trip Time", + "div": 100, + "min": 0.1, + "max": 10, + "def": 0.1, + "unit": "s" + }, + { + "name": "10 mins Average High Voltage", + "div": 10, + "def": 253, + "unit": "V" + } + ] + }, + { + "0x1000": [ + { + "name": "Nominal Frequency", + "div": 100, + "def": 50, + "unit": "Hz" + }, + { + "name": "Low Frequency 1", + "div": 100, + "min": 47.5, + "max": 49.9, + "def": 47.5, + "unit": "Hz" + }, + { + "name": "LF1 Maximum Trip Time", + "div": 10, + "def": 0.1, + "unit": "s" + }, + { + "name": "High Frequency 1", + "div": 100, + "min": 50.1, + "max": 51.5, + "def": 51.5, + "unit": "Hz" + }, + { + "name": "HF1 Maximum Trip Time", + "div": 10, + "def": 0.1, + "unit": "s" + } + ] + }, + { + "0x1003": [ + { + "name": "Nominal Frequency", + "div": 100, + "def": 50, + "unit": "Hz" + }, + { + "name": "Low Frequency 1", + "div": 100, + "min": 45, + "max": 49.9, + "def": 48, + "unit": "Hz" + }, + { + "name": "LF1 Maximum Trip Time", + "div": 100, + "min": 0.1, + "max": 20, + "def": 2, + "unit": "s" + }, + { + "name": "High Frequency 1", + "div": 100, + "min": 50, + "max": 53, + "def": 51, + "unit": "Hz" + }, + { + "name": "HF1 Maximum Trip time", + "div": 10, + "min": 0.1, + "max": 20, + "def": 2, + "unit": "s" + }, + { + "name": "Low Frequency 2", + "div": 100, + "min": 45, + "max": 50, + "def": 47.5, + "unit": "Hz" + }, + { + "name": "LF2 Maximum Trip Time", + "div": 10, + "min": 0.1, + "max": 5, + "def": 0.5, + "unit": "s" + }, + { + "name": "High Frequency 2", + "div": 100, + "min": 50, + "max": 52, + "def": 52, + "unit": "Hz" + }, + { + "name": "HF2 Maximum Trip time", + "div": 10, + "min": 0.1, + "max": 5, + "def": 0.5, + "unit": "s" + } + ] + }, + { + "0x2000": [ + { + "name": "Island Detection Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 1 + } + ] + }, + { + "0x3003": [ + { + "name": "Reconnect Time", + "div": 10, + "min": 10, + "max": 300, + "def": 60, + "unit": "s" + }, + { + "name": "Reconnect High Voltage", + "div": 10, + "min": 240, + "max": 276, + "def": 253, + "unit": "V" + }, + { + "name": "Reconnect Low Voltage", + "div": 10, + "min": 195.5, + "max": 210, + "def": 195.5, + "unit": "V" + }, + { + "name": "Reconnect High Frequency", + "div": 100, + "max": 50.9, + "min": 50.1, + "def": 50.2, + "unit": "Hz" + }, + { + "name": "Reconnect Low Frequency", + "div": 100, + "min": 47.5, + "max": 49.9, + "def": 49.5, + "unit": "Hz" + } + ] + }, + { + "0x4000": [ + { + "name": "Normal Ramp up Rate", + "div": 100, + "min": 0.1, + "max": 100, + "def": 20, + "unit": "Rated%/s" + }, + { + "name": "Soft Start Ramp up Rate ", + "div": 100, + "min": 0.1, + "max": 10, + "def": 0.16, + "unit": "Rated%/s" + } + ] + }, + { + "0x5001": [ + { + "name": "FW Function Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 1 + }, + { + "name": "Start of Frequency Watt Droop", + "div": 100, + "min": 50.2, + "max": 53, + "def": 50.2, + "unit": "Hz" + }, + { + "name": "FW Droop Slope", + "div": 10, + "min": 16.7, + "max": 100, + "def": 40, + "unit": "Pn%/Hz" + }, + { + "name": "Recovery Ramp Rate", + "div": 100, + "min": 0.1, + "max": 100, + "def": 0.16, + "unit": "Pn%/s" + + }, + { + "name": "FW Setting Time", + "div": 10, + "min": 0, + "max": 2, + "def": 0, + "unit": "s" + } + ] + }, + { + "0x5008": [ + { + "name": "FW Function Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 1 + }, + { + "name": "Start of Frequency Watt Droop", + "div": 100, + "min": 50.2, + "max": 52, + "def": 50.2, + "unit": "Hz" + }, + { + "name": "FW Droop Slope", + "div": 10, + "min": 16.7, + "max": 100, + "def": 40, + "unit": "Pn%/Hz" + }, + { + "name": "Recovery Ramp Rate", + "div": 100, + "min": 0.1, + "max": 50, + "def": 0.16, + "unit": "Pn%/s" + }, + { + "name": "Recovery High Frequency", + "div": 10, + "min": 50.1, + "max": 52, + "def": 50.2, + "unit": "Hz" + }, + { + "name": "Recovery Low Frequency", + "div": 100, + "min": 49, + "max": 49.9, + "def": 49.8, + "unit": "Hz" + } + ] + }, + { + "0x6000": [ + { + "name": "VW Function Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 1 + }, + { + "name": "Start of Voltage Watt Droop", + "div": 10, + "def": 253, + "unit": "V" + }, + { + "name": "End of Voltage Watt Droop", + "div": 10, + "min": 258, + "max": 270, + "def": 265, + "unit": "V" + }, + { + "name": "VW Droop Slope", + "div": 100, + "min": 5, + "max": 18, + "def": 5.33, + "unit": "Pn%/V" + } + ] + }, + { + "0x7002": [ + { + "name": "APC Function Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 1 + }, + { + "name": "Power Ramp Rate", + "div": 100, + "min": 0.33, + "max": 100, + "def": 100, + "unit": "Pn%/s" + } + ] + }, + { + "0x8000": [ + { + "name": "VV Function Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 0 + }, + { + "name": "Voltage Set Point V1", + "div": 10, + "min": 184, + "max": 230, + "def": 213.9, + "unit": "V" + }, + { + "name": "Reactive Set Point Q1", + "div": 10, + "min": 0, + "max": 100, + "def": 30, + "unit": "%Pn" + }, + { + "name": "Voltage Set Point V2", + "div": 10, + "min": 210, + "max": 240, + "def": 223.1, + "unit": "V" + }, + { + "name": "Voltage Set Point V3", + "div": 10, + "min": 220, + "max": 240, + "def": 236.9, + "unit": "V" + }, + { + "name": "Voltage Set Point V4", + "div": 10, + "min": 230, + "max": 253, + "def": 246.1, + "unit": "V" + }, + { + "name": "Reactive Set Point Q4", + "div": 10, + "min": 0, + "max": 100, + "def": 30, + "unit": "%Pn" + } + ] + }, + { + "0x8001": [ + { + "name": "VV Function Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 0 + }, + { + "name": "Voltage Set Point V1", + "div": 10, + "def": 213.9, + "unit": "V" + }, + { + "name": "Reactive Set Point Q1", + "div": 10, + "min": 0, + "max": 100, + "def": 30, + "unit": "%Pn" + }, + { + "name": "Voltage Set Point V2", + "div": 10, + "def": 223.1, + "unit": "V" + }, + { + "name": "Voltage Set Point V3", + "div": 10, + "def": 236.9, + "unit": "V" + }, + { + "name": "Voltage Set Point V4", + "div": 10, + "def": 246.1, + "unit": "V" + }, + { + "name": "Reactive Set Point Q4", + "div": 10, + "min": 0, + "max": 100, + "def": 30, + "unit": "%Pn" + }, + { + "name": "VV Setting Time", + "div": 10, + "min": 0, + "max": 60, + "def": 10, + "unit": "s" + } + ] + }, + { + "0x9000": [ + { + "name": "Specified Power Factor Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 0 + }, + { + "name": "Power Factor", + "div": 100, + "min": 0.9, + "max": 1, + "def": 0.95 + } + ] + }, + { + "0xa002": [ + { + "name": "RPC Function Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 0 + }, + { + "name": "Reactive Power", + "div": 100, + "min": 0, + "max": 50, + "def": 0, + "unit": "%Sn" + } + ] + }, + { + "0xb000": [ + { + "name": "WPF Function Activated", + "div": 1, + "min": 0, + "max": 1, + "def": 0 + }, + { + "name": "Start of Power of WPF", + "div": 10, + "def": 50, + "unit": "%Pn" + }, + { + "name": "Power Factor ar Rated Power", + "div": 100, + "min": 0.8, + "max": 1, + "def": 0.95 + } + ] + } + ] +} diff --git a/src/web/html/save.html b/src/web/html/save.html index ce50c6ca..9b5b4864 100644 --- a/src/web/html/save.html +++ b/src/web/html/save.html @@ -34,8 +34,8 @@ html = "Settings successfully saved. Automatic page reload in 3 seconds."; meta.content = 3; } else { - html = "Settings successfully saved. Rebooting. Automatic redirect in 20 seconds."; - meta.content = 20 + "; URL=/"; + html = "Settings successfully saved. Rebooting. Automatic redirect in " + obj.reload + " seconds."; + meta.content = obj.reload + "; URL=/"; } document.getElementsByTagName('head')[0].appendChild(meta); } else { diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html index faf76432..b561d5cc 100644 --- a/src/web/html/visualization.html +++ b/src/web/html/visualization.html @@ -295,13 +295,76 @@ getAjax("/api/inverter/grid/" + obj.id, showGridProfile); }}, null)) ]) - ]); - modal("Info for inverter " + obj.name, ml("div", {}, html)); + ]) + modal("Info for inverter " + obj.name, ml("div", {}, html)) + } + + function getGridValue(g) { + var val = (parseInt(g.grid.substring(g.offs*3, g.offs*3+2), 16) * 256) + + parseInt(g.grid.substring(g.offs*3+3, g.offs*3+5), 16) + g.offs += 2 + return val + } + + function getGridIdentifier(g) { + return "0x" + getGridValue(g).toString(16).padStart(4, '0') + } + + function getGridType(t, id) { + for(e of t) { + if(undefined !== e[id]) + return e[id] + } + return null + } + + function parseGridGroup(g) { + var id = getGridIdentifier(g) + var type = getGridType(g.info.grp_codes, id.substring(0, 4)) + var content = [] + content.push(ml("div", {class: "row"}, + ml("div", {class: "col head p-2 mt-3"}, + ml("div", {class: "col a-c"}, type + " (Code " + id + ")") + ) + )) + content.push(ml("div", {class: "row my-2"}, [ + ml("div", {class: "col-4"}, ml("b", {}, "Name")), + ml("div", {class: "col-3"}, ml("b", {}, "Value")), + ml("div", {class: "col-3"}, ml("b", {}, "Range")), + ml("div", {class: "col-2"}, ml("b", {}, "Default")) + ])) + for(e of g.info.group) { + if(Array.isArray(e[id])) { + for(e of e[id]) { + var v = String(getGridValue(g) / e.div); + var vt = (v !== String(e.def)) ? "b" : "span"; + content.push(ml("div", {class: "row mt-2"}, [ + ml("div", {class: "col-4"}, e.name), + ml("div", {class: "col-3"}, ml(vt, {}, v + ((undefined !== e.unit) ? " [" + e.unit + "]" : ""))), + ml("div", {class: "col-3"}, (undefined !== e.min) ? (e.min + " - " + e.max) : "n/a"), + ml("div", {class: "col-2"}, String(e.def)) + ])) + } + } + } + + return ml("div", {class: "col"}, [...content]) } function showGridProfile(obj) { - var html = ml("pre", {}, obj.grid); - modal("Grid Profile for inverter " + obj.name, ml("div", {}, html)); + getJSON("/grid_info.json").then(data => { + var glob = {offs:0, grid:obj.grid, info: data} + var content = []; + content.push(ml("div", {class: "row"}, + ml("div", {class: "col my-3"}, ml("h5", {}, getGridType(glob.info.type, getGridIdentifier(glob)) + " (Version " + getGridValue(glob).toString(16) + ")")) + )) + + while((glob.offs*3) < glob.grid.length) { + content.push(parseGridGroup(glob)) + } + + modal("Grid Profile for inverter " + obj.name, ml("div", {}, ml("div", {class: "col mb-2"}, [...content]))) + }) } @@ -315,8 +378,8 @@ tr2(["RX fragments", obj.frame_cnt, ""]), tr2(["TX retransmits", obj.retransmits, ""]) ]) - ]); - modal("Radio statistics for inverter " + obj.name, ml("div", {}, html)); + ]) + modal("Radio statistics for inverter " + obj.name, ml("div", {}, html)) } function limitModal(obj) { diff --git a/src/web/web.h b/src/web/web.h index b104e9fd..451dc656 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -25,6 +25,7 @@ #include "html/h/colorBright_css.h" #include "html/h/colorDark_css.h" #include "html/h/favicon_ico.h" +#include "html/h/grid_info_json.h" #include "html/h/index_html.h" #include "html/h/login_html.h" #include "html/h/serial_html.h" @@ -65,6 +66,7 @@ class Web { mWeb.on("/colors.css", HTTP_GET, std::bind(&Web::onColor, this, std::placeholders::_1)); mWeb.on("/style.css", HTTP_GET, std::bind(&Web::onCss, this, std::placeholders::_1)); mWeb.on("/api.js", HTTP_GET, std::bind(&Web::onApiJs, this, std::placeholders::_1)); + mWeb.on("/grid_info.json", HTTP_GET, std::bind(&Web::onGridInfoJson, this, std::placeholders::_1)); mWeb.on("/favicon.ico", HTTP_GET, std::bind(&Web::onFavicon, this, std::placeholders::_1)); mWeb.onNotFound ( std::bind(&Web::showNotFound, this, std::placeholders::_1)); mWeb.on("/reboot", HTTP_ANY, std::bind(&Web::onReboot, this, std::placeholders::_1)); @@ -389,6 +391,16 @@ class Web { request->send(response); } + void onGridInfoJson(AsyncWebServerRequest *request) { + DPRINTLN(DBG_VERBOSE, F("onGridInfoJson")); + + AsyncWebServerResponse *response = request->beginResponse_P(200, F("application/json; charset=utf-8"), grid_info_json, grid_info_json_len); + response->addHeader(F("Content-Encoding"), "gzip"); + if(request->hasParam("v")) + response->addHeader(F("Cache-Control"), F("max-age=604800")); + request->send(response); + } + void onFavicon(AsyncWebServerRequest *request) { static const char favicon_type[] PROGMEM = "image/x-icon"; AsyncWebServerResponse *response = request->beginResponse_P(200, favicon_type, favicon_ico, favicon_ico_len); From cbb93cfd5a849c1d41ba8a0e993947256d28a290 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 28 Dec 2023 02:30:13 +0100 Subject: [PATCH 7/8] 0.8.29 * added ESP32-C3 mini environment #1289 --- .github/workflows/compile_development.yml | 2 +- .github/workflows/compile_release.yml | 2 +- scripts/getVersion.py | 13 +++++++++++++ src/CHANGES.md | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index 31049c21..6eba4879 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -43,7 +43,7 @@ jobs: pip install --upgrade platformio - name: Run PlatformIO - run: pio run -d src --environment esp8266 --environment esp8266-prometheus --environment esp8285 --environment esp32-wroom32 --environment esp32-wroom32-prometheus --environment esp32-wroom32-ethernet --environment esp32-s2-mini --environment opendtufusion --environment opendtufusion-ethernet + run: pio run -d src --environment esp8266 --environment esp8266-prometheus --environment esp8285 --environment esp32-wroom32 --environment esp32-wroom32-prometheus --environment esp32-wroom32-ethernet --environment esp32-s2-mini --environment esp32-c3-mini --environment opendtufusion --environment opendtufusion-ethernet - 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/.github/workflows/compile_release.yml b/.github/workflows/compile_release.yml index 8f493100..61c920b3 100644 --- a/.github/workflows/compile_release.yml +++ b/.github/workflows/compile_release.yml @@ -47,7 +47,7 @@ jobs: pip install --upgrade platformio - name: Run PlatformIO - run: pio run -d src --environment esp8266 --environment esp8266-prometheus --environment esp8285 --environment esp32-wroom32 --environment esp32-wroom32-prometheus --environment esp32-wroom32-ethernet --environment esp32-s2-mini --environment opendtufusion --environment opendtufusion-ethernet + run: pio run -d src --environment esp8266 --environment esp8266-prometheus --environment esp8285 --environment esp32-wroom32 --environment esp32-wroom32-prometheus --environment esp32-wroom32-ethernet --environment esp32-s2-mini --environment esp32-c3-mini --environment opendtufusion --environment opendtufusion-ethernet - 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/scripts/getVersion.py b/scripts/getVersion.py index 4ea74d71..cdb39ae8 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -55,6 +55,7 @@ def readVersion(path, infile): os.mkdir(path + "firmware/ESP32/") os.mkdir(path + "firmware/ESP32-S2/") os.mkdir(path + "firmware/ESP32-S3/") + os.mkdir(path + "firmware/ESP32-C3/") os.mkdir(path + "firmware/ESP32-S3-ETH/") sha = os.getenv("SHA",default="sha") @@ -94,6 +95,11 @@ def readVersion(path, infile): dst = path + "firmware/ESP32-S2/" + versionout os.rename(src, dst) + versionout = version[:-1] + "_" + sha + "_esp32c3-mini.bin" + src = path + ".pio/build/esp32-c3-mini/firmware.bin" + dst = path + "firmware/ESP32-C3/" + versionout + os.rename(src, dst) + versionout = version[:-1] + "_" + sha + "_esp32s3.bin" src = path + ".pio/build/opendtufusion/firmware.bin" dst = path + "firmware/ESP32-S3/" + versionout @@ -118,6 +124,13 @@ def readVersion(path, infile): os.rename(src + "partitions.bin", dst + "partitions.bin") genOtaBin(dst) + # other ESP32-C3 bin files + src = path + ".pio/build/esp32-c3-mini/" + dst = path + "firmware/ESP32-C3/" + os.rename(src + "bootloader.bin", dst + "bootloader.bin") + os.rename(src + "partitions.bin", dst + "partitions.bin") + genOtaBin(dst) + # other ESP32-S3 bin files src = path + ".pio/build/opendtufusion/" dst = path + "firmware/ESP32-S3/" diff --git a/src/CHANGES.md b/src/CHANGES.md index 99b7dc64..fc8566cc 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -7,6 +7,7 @@ * fix crash if `getLossRate` was read from inverter #1288 #1290 * reduce reload time for opendtufusion ethernet variant to 5 seconds * added basic grid parser +* added ESP32-C3 mini environment #1289 ## 0.8.28 - 2023-12-23 * fix bug heuristic From 4e277e20c8b0b1663f365dd1d1c14fd6432311c5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 28 Dec 2023 10:29:55 +0100 Subject: [PATCH 8/8] 0.8.29 * fix compile for ESP32-C3 --- patches/AsyncWeb_Prometheus.patch | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/patches/AsyncWeb_Prometheus.patch b/patches/AsyncWeb_Prometheus.patch index 7fb9209a..21fe22cd 100644 --- a/patches/AsyncWeb_Prometheus.patch +++ b/patches/AsyncWeb_Prometheus.patch @@ -1,3 +1,16 @@ +diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp +index 12be5f8..cffeed7 100644 +--- a/src/AsyncWebSocket.cpp ++++ b/src/AsyncWebSocket.cpp +@@ -737,7 +737,7 @@ void AsyncWebSocketClient::binary(const __FlashStringHelper *data, size_t len) + IPAddress AsyncWebSocketClient::remoteIP() const + { + if (!_client) +- return IPAddress(0U); ++ return IPAddress(); + + return _client->remoteIP(); + } diff --git a/src/WebResponses.cpp b/src/WebResponses.cpp index 22a549f..e0b36b3 100644 --- a/src/WebResponses.cpp