diff --git a/src/CHANGES.md b/src/CHANGES.md index 3dc4a7237..6c4f0a6d2 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,13 @@ # Development Changes +## 0.8.5 - 2023-11-12 +* fixed endless loop while switching CMT frequency +* removed obsolete "retries" field from settings #1224 +* fixed crash while defining new invertes #1224 +* fixed default frequency settings +* added default input power to `400` while adding new inverters +* fixed color of wifi RSSI icon #1224 + ## 0.8.4 - 2023-11-10 * changed MqTT alarm topic, removed retained flag #1212 * reduce last_success MQTT messages (#1124) diff --git a/src/app.cpp b/src/app.cpp index 38f31e070..838c375fd 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -63,15 +63,7 @@ void app::setup() { mCommunication.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1, std::placeholders::_2)); mSys.setup(&mTimestamp, &mConfig->inst); for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { - mSys.addInverter(i, [this](Inverter<> *iv) { - // will be only called for valid inverters - if((IV_MI == iv->ivGen) || (IV_HM == iv->ivGen)) - iv->radio = &mNrfRadio; - #if defined(ESP32) - else if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen)) - iv->radio = &mCmtRadio; - #endif - }); + initInverter(i); } if(mConfig->nrf.enabled) { diff --git a/src/app.h b/src/app.h index c257d83db..0bb1c1706 100644 --- a/src/app.h +++ b/src/app.h @@ -104,6 +104,17 @@ class app : public IApp, public ah::Scheduler { return true; } + void initInverter(uint8_t id) { + mSys.addInverter(id, [this](Inverter<> *iv) { + if((IV_MI == iv->ivGen) || (IV_HM == iv->ivGen)) + iv->radio = &mNrfRadio; + #if defined(ESP32) + else if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen)) + iv->radio = &mCmtRadio; + #endif + }); + } + bool readSettings(const char *path) { return mSettings.readSettings(path); } diff --git a/src/appInterface.h b/src/appInterface.h index 4bfc3b0ca..802f21e6e 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -25,6 +25,7 @@ class IApp { public: virtual ~IApp() {} virtual bool saveSettings(bool stopFs) = 0; + virtual void initInverter(uint8_t id) = 0; virtual bool readSettings(const char *path) = 0; virtual bool eraseSettings(bool eraseWifi) = 0; virtual bool getSavePending() = 0; diff --git a/src/config/settings.h b/src/config/settings.h index d46e5687e..27aaf9530 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -465,10 +465,10 @@ class settings { } void loadAddedDefaults() { - if(0 == mCfg.configVersion) { + if(0 < mCfg.configVersion) { 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].frequency = 0x0; // 860MHz (backward compatibility) } } } diff --git a/src/defines.h b/src/defines.h index add9623d4..eeee3574f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 4 +#define VERSION_PATCH 5 //------------------------------------- typedef struct { diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 2675d1a27..ea7602000 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -57,11 +57,21 @@ class Communication : public CommQueue<> { mHeu.printStatus(q->iv); mHeu.getTxCh(q->iv); mGotFragment = false; + if(NULL == q->iv->radio) + cmdDone(true); // can't communicate while radio is not defined! mState = States::START; break; case States::START: setTs(mTimestamp); + if((IV_HMS == q->iv->ivGen) || (IV_HMT == q->iv->ivGen)) { + // frequency was changed during runtime + if(q->iv->curCmtFreq != q->iv->config->frequency) { + if(q->iv->radio->switchFrequencyCh(q->iv, q->iv->curCmtFreq, q->iv->config->frequency)) + q->iv->curCmtFreq = q->iv->config->frequency; + } + } + if(q->isDevControl) { if(ActivePowerContr == q->cmd) q->iv->powerLimitAck = false; diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 52b7c5dd5..f52bafe92 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -149,6 +149,7 @@ class Inverter { alarmCnt = 0; alarmLastId = 0; rssi = -127; + radio = NULL; memset(&radioStatistics, 0, sizeof(statistics_t)); memset(txRfQuality, -6, 5); diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index de0d5911a..b86f8d08b 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -17,17 +17,12 @@ class HmSystem { void setup(uint32_t *timestamp, cfgInst_t *config) { mInverter[0].timestamp = timestamp; mInverter[0].generalConfig = config; - mNumInv = 0; } void addInverter(uint8_t id, std::function *iv)> cb) { DPRINTLN(DBG_VERBOSE, F("hmSystem.h:addInverter")); - if(MAX_INVERTER <= mNumInv) { - DPRINT(DBG_WARN, F("max number of inverters reached!")); - return; - } - INVERTERTYPE *iv = &mInverter[mNumInv]; - iv->id = mNumInv; + INVERTERTYPE *iv = &mInverter[id]; + iv->id = id; 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)); @@ -73,7 +68,6 @@ class HmSystem { iv->ivGen = IV_UNKNOWN; iv->init(); - mNumInv ++; if(IV_UNKNOWN == iv->ivGen) return; // serial is 0 @@ -99,7 +93,7 @@ class HmSystem { INVERTERTYPE *findInverter(uint8_t buf[]) { DPRINTLN(DBG_VERBOSE, F("hmSystem.h:findInverter")); INVERTERTYPE *p; - for(uint8_t i = 0; i < mNumInv; i++) { + for(uint8_t i = 0; i < MAX_INVERTER; i++) { p = &mInverter[i]; if((p->config->serial.b[3] == buf[0]) && (p->config->serial.b[2] == buf[1]) @@ -134,7 +128,6 @@ class HmSystem { private: INVERTERTYPE mInverter[MAX_INVERTER]; - uint8_t mNumInv; }; #endif /*__HM_SYSTEM_H__*/ diff --git a/src/hm/radio.h b/src/hm/radio.h index 792390223..07317e8c9 100644 --- a/src/hm/radio.h +++ b/src/hm/radio.h @@ -23,6 +23,7 @@ class Radio { public: 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 void loop(void) {}; bool get() { diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 811c60d2b..bcb08c3fd 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -69,7 +69,6 @@ class CmtRadio : public Radio { return switchFrequencyCh(iv, fromCh, toCh); } - private: bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { if((0xff == fromCh) || (0xff == toCh)) return false; @@ -80,16 +79,12 @@ class CmtRadio : public Radio { return true; } + private: + void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) { - // frequency was changed during runtime - if(iv->curCmtFreq != iv->config->frequency) { - if(switchFrequencyCh(iv, iv->curCmtFreq, iv->config->frequency)) - iv->curCmtFreq = iv->config->frequency; - } else { - // inverters have maybe different settings regarding frequency - if(mCmt.getCurrentChannel() != iv->config->frequency) - mCmt.switchChannel(iv->config->frequency); - } + // inverters have maybe different settings regarding frequency + if(mCmt.getCurrentChannel() != iv->config->frequency) + mCmt.switchChannel(iv->config->frequency); updateCrcs(&len, appendCrc16); diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 6e977309e..53adb23fa 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -728,20 +728,7 @@ class RestApi { snprintf(iv->config->chName[i], MAX_NAME_LENGTH, "%s", jsonIn[F("ch")][i][F("name")].as()); } - switch(iv->config->serial.b[4]) { - case 0x24: - case 0x22: - case 0x21: iv->type = INV_TYPE_1CH; iv->channels = 1; break; - - case 0x44: - case 0x42: - case 0x41: iv->type = INV_TYPE_2CH; iv->channels = 2; break; - - case 0x64: - case 0x62: - case 0x61: iv->type = INV_TYPE_4CH; iv->channels = 4; break; - default: break; - } + mApp->initInverter(jsonIn[F("id")]); iv->config->frequency = jsonIn[F("freq")]; iv->config->powerLevel = jsonIn[F("pa")]; mApp->saveSettings(false); // without reboot diff --git a/src/web/html/api.js b/src/web/html/api.js index 11db6c45f..2eea8d942 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -126,7 +126,7 @@ function parseRssi(obj) { icon = iconWifi1; else if(obj["wifi_rssi"] <= -70) icon = iconWifi2; - document.getElementById("wifiicon").replaceChildren(svg(icon, 32, 32, "icon-fg", obj["wifi_rssi"])); + document.getElementById("wifiicon").replaceChildren(svg(icon, 32, 32, "icon-fg2", obj["wifi_rssi"])); } function toIsoDateStr(d) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 1ca46ced0..a21aa0738 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -149,10 +149,6 @@
Interval [s]
-
-
Max retries per Payload
-
-
Reset values and YieldDay at midnight
@@ -578,7 +574,7 @@ } function ivGlob(obj) { - for(var i of [["invInterval", "interval"], ["invRetry", "retries"], ["yldEff", "yldEff"]]) + 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]; @@ -644,14 +640,17 @@ add.id = obj.inverter.length; add.name = ""; add.enabled = true; - add.ch_max_pwr = []; + add.ch_max_pwr = [400,400,400,400,400,400]; add.ch_name = []; add.ch_yield_cor = []; + add.freq = 12; + add.pa = 30; var e = document.getElementById("inverter"); e.innerHTML = ""; // remove all childs e.append(ml("table", {class: "table"}, ml("tbody", {}, lines))); - e.append(ml("div", {class: "row my-3"}, ml("div", {class: "col a-r"}, ml("input", {type: "button", value: "add Inverter", class: "btn", onclick: function() { ivModal(add); }}, null)))); + if(obj.max_num_inverters > obj.inverter.length) + e.append(ml("div", {class: "row my-3"}, ml("div", {class: "col a-r"}, ml("input", {type: "button", value: "add Inverter", class: "btn", onclick: function() { ivModal(add); }}, null)))); ivGlob(obj); } diff --git a/src/web/html/style.css b/src/web/html/style.css index 064819f53..b31ae7c93 100644 --- a/src/web/html/style.css +++ b/src/web/html/style.css @@ -98,6 +98,10 @@ svg.icon { fill: var(--fg); } +.icon-fg2 { + fill: var(--fg2); +} + .title { background-color: var(--primary); color: #fff !important; @@ -817,7 +821,8 @@ ul { } .nav-tabs .nav-link.active { - border-color: var(--fg) var(--fg) var(--bg); + border-color: var(--primary) var(--fg) var(--bg); + border-top-width: 4px; } .nav-link:hover, .nav-link:visited {