mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-28 00:06:12 +02:00
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
This commit is contained in:
parent
efdac9634f
commit
8ac895f50a
15 changed files with 58 additions and 55 deletions
|
@ -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
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
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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__*/
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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…
Add table
Add a link
Reference in a new issue