Browse Source

0.8.5

* 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
pull/1234/head
lumapu 11 months ago
parent
commit
8ac895f50a
  1. 8
      src/CHANGES.md
  2. 10
      src/app.cpp
  3. 11
      src/app.h
  4. 1
      src/appInterface.h
  5. 4
      src/config/settings.h
  6. 2
      src/defines.h
  7. 10
      src/hm/Communication.h
  8. 1
      src/hm/hmInverter.h
  9. 13
      src/hm/hmSystem.h
  10. 1
      src/hm/radio.h
  11. 15
      src/hms/hmsRadio.h
  12. 15
      src/web/RestApi.h
  13. 2
      src/web/html/api.js
  14. 13
      src/web/html/setup.html
  15. 7
      src/web/html/style.css

8
src/CHANGES.md

@ -1,5 +1,13 @@
# Development Changes # 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 ## 0.8.4 - 2023-11-10
* changed MqTT alarm topic, removed retained flag #1212 * changed MqTT alarm topic, removed retained flag #1212
* reduce last_success MQTT messages (#1124) * reduce last_success MQTT messages (#1124)

10
src/app.cpp

@ -63,15 +63,7 @@ void app::setup() {
mCommunication.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1, std::placeholders::_2)); mCommunication.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1, std::placeholders::_2));
mSys.setup(&mTimestamp, &mConfig->inst); mSys.setup(&mTimestamp, &mConfig->inst);
for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
mSys.addInverter(i, [this](Inverter<> *iv) { initInverter(i);
// 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
});
} }
if(mConfig->nrf.enabled) { if(mConfig->nrf.enabled) {

11
src/app.h

@ -104,6 +104,17 @@ class app : public IApp, public ah::Scheduler {
return true; 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) { bool readSettings(const char *path) {
return mSettings.readSettings(path); return mSettings.readSettings(path);
} }

1
src/appInterface.h

@ -25,6 +25,7 @@ class IApp {
public: public:
virtual ~IApp() {} virtual ~IApp() {}
virtual bool saveSettings(bool stopFs) = 0; virtual bool saveSettings(bool stopFs) = 0;
virtual void initInverter(uint8_t id) = 0;
virtual bool readSettings(const char *path) = 0; virtual bool readSettings(const char *path) = 0;
virtual bool eraseSettings(bool eraseWifi) = 0; virtual bool eraseSettings(bool eraseWifi) = 0;
virtual bool getSavePending() = 0; virtual bool getSavePending() = 0;

4
src/config/settings.h

@ -465,10 +465,10 @@ class settings {
} }
void loadAddedDefaults() { void loadAddedDefaults() {
if(0 == mCfg.configVersion) { if(0 < mCfg.configVersion) {
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
mCfg.inst.iv[i].powerLevel = 0xff; // impossible high value 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)
} }
} }
} }

2
src/defines.h

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 8 #define VERSION_MINOR 8
#define VERSION_PATCH 4 #define VERSION_PATCH 5
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

10
src/hm/Communication.h

@ -57,11 +57,21 @@ class Communication : public CommQueue<> {
mHeu.printStatus(q->iv); mHeu.printStatus(q->iv);
mHeu.getTxCh(q->iv); mHeu.getTxCh(q->iv);
mGotFragment = false; mGotFragment = false;
if(NULL == q->iv->radio)
cmdDone(true); // can't communicate while radio is not defined!
mState = States::START; mState = States::START;
break; break;
case States::START: case States::START:
setTs(mTimestamp); 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(q->isDevControl) {
if(ActivePowerContr == q->cmd) if(ActivePowerContr == q->cmd)
q->iv->powerLimitAck = false; q->iv->powerLimitAck = false;

1
src/hm/hmInverter.h

@ -149,6 +149,7 @@ class Inverter {
alarmCnt = 0; alarmCnt = 0;
alarmLastId = 0; alarmLastId = 0;
rssi = -127; rssi = -127;
radio = NULL;
memset(&radioStatistics, 0, sizeof(statistics_t)); memset(&radioStatistics, 0, sizeof(statistics_t));
memset(txRfQuality, -6, 5); memset(txRfQuality, -6, 5);

13
src/hm/hmSystem.h

@ -17,17 +17,12 @@ class HmSystem {
void setup(uint32_t *timestamp, cfgInst_t *config) { void setup(uint32_t *timestamp, cfgInst_t *config) {
mInverter[0].timestamp = timestamp; mInverter[0].timestamp = timestamp;
mInverter[0].generalConfig = config; mInverter[0].generalConfig = config;
mNumInv = 0;
} }
void addInverter(uint8_t id, std::function<void(Inverter<> *iv)> cb) { void addInverter(uint8_t id, std::function<void(Inverter<> *iv)> cb) {
DPRINTLN(DBG_VERBOSE, F("hmSystem.h:addInverter")); DPRINTLN(DBG_VERBOSE, F("hmSystem.h:addInverter"));
if(MAX_INVERTER <= mNumInv) { INVERTERTYPE *iv = &mInverter[id];
DPRINT(DBG_WARN, F("max number of inverters reached!")); iv->id = id;
return;
}
INVERTERTYPE *iv = &mInverter[mNumInv];
iv->id = mNumInv;
iv->config = &mInverter[0].generalConfig->iv[id]; iv->config = &mInverter[0].generalConfig->iv[id];
DPRINT(DBG_VERBOSE, "SERIAL: " + String(iv->config->serial.b[5], HEX)); DPRINT(DBG_VERBOSE, "SERIAL: " + String(iv->config->serial.b[5], HEX));
DPRINTLN(DBG_VERBOSE, " " + String(iv->config->serial.b[4], HEX)); DPRINTLN(DBG_VERBOSE, " " + String(iv->config->serial.b[4], HEX));
@ -73,7 +68,6 @@ class HmSystem {
iv->ivGen = IV_UNKNOWN; iv->ivGen = IV_UNKNOWN;
iv->init(); iv->init();
mNumInv ++;
if(IV_UNKNOWN == iv->ivGen) if(IV_UNKNOWN == iv->ivGen)
return; // serial is 0 return; // serial is 0
@ -99,7 +93,7 @@ class HmSystem {
INVERTERTYPE *findInverter(uint8_t buf[]) { INVERTERTYPE *findInverter(uint8_t buf[]) {
DPRINTLN(DBG_VERBOSE, F("hmSystem.h:findInverter")); DPRINTLN(DBG_VERBOSE, F("hmSystem.h:findInverter"));
INVERTERTYPE *p; INVERTERTYPE *p;
for(uint8_t i = 0; i < mNumInv; i++) { for(uint8_t i = 0; i < MAX_INVERTER; i++) {
p = &mInverter[i]; p = &mInverter[i];
if((p->config->serial.b[3] == buf[0]) if((p->config->serial.b[3] == buf[0])
&& (p->config->serial.b[2] == buf[1]) && (p->config->serial.b[2] == buf[1])
@ -134,7 +128,6 @@ class HmSystem {
private: private:
INVERTERTYPE mInverter[MAX_INVERTER]; INVERTERTYPE mInverter[MAX_INVERTER];
uint8_t mNumInv;
}; };
#endif /*__HM_SYSTEM_H__*/ #endif /*__HM_SYSTEM_H__*/

1
src/hm/radio.h

@ -23,6 +23,7 @@ class Radio {
public: public:
virtual void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) = 0; 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 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) {}; virtual void loop(void) {};
bool get() { bool get() {

15
src/hms/hmsRadio.h

@ -69,7 +69,6 @@ class CmtRadio : public Radio {
return switchFrequencyCh(iv, fromCh, toCh); return switchFrequencyCh(iv, fromCh, toCh);
} }
private:
bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) {
if((0xff == fromCh) || (0xff == toCh)) if((0xff == fromCh) || (0xff == toCh))
return false; return false;
@ -80,16 +79,12 @@ class CmtRadio : public Radio {
return true; return true;
} }
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) {
// frequency was changed during runtime // inverters have maybe different settings regarding frequency
if(iv->curCmtFreq != iv->config->frequency) { if(mCmt.getCurrentChannel() != iv->config->frequency)
if(switchFrequencyCh(iv, iv->curCmtFreq, iv->config->frequency)) mCmt.switchChannel(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);
}
updateCrcs(&len, appendCrc16); updateCrcs(&len, appendCrc16);

15
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<const char*>()); snprintf(iv->config->chName[i], MAX_NAME_LENGTH, "%s", jsonIn[F("ch")][i][F("name")].as<const char*>());
} }
switch(iv->config->serial.b[4]) { mApp->initInverter(jsonIn[F("id")]);
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;
}
iv->config->frequency = jsonIn[F("freq")]; iv->config->frequency = jsonIn[F("freq")];
iv->config->powerLevel = jsonIn[F("pa")]; iv->config->powerLevel = jsonIn[F("pa")];
mApp->saveSettings(false); // without reboot mApp->saveSettings(false); // without reboot

2
src/web/html/api.js

@ -126,7 +126,7 @@ function parseRssi(obj) {
icon = iconWifi1; icon = iconWifi1;
else if(obj["wifi_rssi"] <= -70) else if(obj["wifi_rssi"] <= -70)
icon = iconWifi2; 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) { function toIsoDateStr(d) {

13
src/web/html/setup.html

@ -149,10 +149,6 @@
<div class="col-12 col-sm-3 my-2">Interval [s]</div> <div class="col-12 col-sm-3 my-2">Interval [s]</div>
<div class="col-12 col-sm-9"><input type="number" name="invInterval" title="Invalid input"/></div> <div class="col-12 col-sm-9"><input type="number" name="invInterval" title="Invalid input"/></div>
</div> </div>
<div class="row mb-3">
<div class="col-12 col-sm-3 my-2">Max retries per Payload</div>
<div class="col-12 col-sm-9"><input type="number" name="invRetry"/></div>
</div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-8 col-sm-3 mb-2">Reset values and YieldDay at midnight</div> <div class="col-8 col-sm-3 mb-2">Reset values and YieldDay at midnight</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="invRstMid"/></div> <div class="col-4 col-sm-9"><input type="checkbox" name="invRstMid"/></div>
@ -578,7 +574,7 @@
} }
function ivGlob(obj) { 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]]; document.getElementsByName(i[0])[0].value = obj[i[1]];
for(var i of ["Mid", "ComStop", "NotAvail", "MaxMid"]) for(var i of ["Mid", "ComStop", "NotAvail", "MaxMid"])
document.getElementsByName("invRst"+i)[0].checked = obj["rst" + i]; document.getElementsByName("invRst"+i)[0].checked = obj["rst" + i];
@ -644,14 +640,17 @@
add.id = obj.inverter.length; add.id = obj.inverter.length;
add.name = ""; add.name = "";
add.enabled = true; add.enabled = true;
add.ch_max_pwr = []; add.ch_max_pwr = [400,400,400,400,400,400];
add.ch_name = []; add.ch_name = [];
add.ch_yield_cor = []; add.ch_yield_cor = [];
add.freq = 12;
add.pa = 30;
var e = document.getElementById("inverter"); var e = document.getElementById("inverter");
e.innerHTML = ""; // remove all childs e.innerHTML = ""; // remove all childs
e.append(ml("table", {class: "table"}, ml("tbody", {}, lines))); 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); ivGlob(obj);
} }

7
src/web/html/style.css

@ -98,6 +98,10 @@ svg.icon {
fill: var(--fg); fill: var(--fg);
} }
.icon-fg2 {
fill: var(--fg2);
}
.title { .title {
background-color: var(--primary); background-color: var(--primary);
color: #fff !important; color: #fff !important;
@ -817,7 +821,8 @@ ul {
} }
.nav-tabs .nav-link.active { .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 { .nav-link:hover, .nav-link:visited {

Loading…
Cancel
Save