From d9696dc70427fb1e7b56c94bbffe9cce45624fd9 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 3 Feb 2024 23:31:17 +0100 Subject: [PATCH] 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_GAP} [ms]
-
-
{#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