mirror of
https://github.com/lumapu/ahoy.git
synced 2025-06-01 10:11:37 +02:00
fix power-limit was not checked for max retransmits #667
fix blue LED lights up all the time #672 fix installing schedulers if NTP server isn't available improved zero values on triggers #671 hardcoded MQTT subtopics, because wildcard `#` leads to errors rephrased some messages on webif, thx to @Argafal #638
This commit is contained in:
parent
1dd1b3be21
commit
026df8a09b
10 changed files with 76 additions and 56 deletions
|
@ -2,6 +2,14 @@
|
||||||
|
|
||||||
(starting from release version `0.5.66`)
|
(starting from release version `0.5.66`)
|
||||||
|
|
||||||
|
## 0.5.85
|
||||||
|
* fix power-limit was not checked for max retransmits #667
|
||||||
|
* fix blue LED lights up all the time #672
|
||||||
|
* fix installing schedulers if NTP server isn't available
|
||||||
|
* improved zero values on triggers #671
|
||||||
|
* hardcoded MQTT subtopics, because wildcard `#` leads to errors
|
||||||
|
* rephrased some messages on webif, thx to @Argafal #638
|
||||||
|
|
||||||
## 0.5.84
|
## 0.5.84
|
||||||
* fix blue LED lights up all the time #672
|
* fix blue LED lights up all the time #672
|
||||||
* added an instant start communication (once NTP is synced)
|
* added an instant start communication (once NTP is synced)
|
||||||
|
|
44
src/app.cpp
44
src/app.cpp
|
@ -161,14 +161,16 @@ void app::tickNtpUpdate(void) {
|
||||||
mMqtt.connect();
|
mMqtt.connect();
|
||||||
everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS");
|
everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS");
|
||||||
everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt), "mqttM");
|
everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt), "mqttM");
|
||||||
mMqttReconnect = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mConfig->inst.rstValsNotAvail)
|
// only install schedulers once even if NTP wasn't successful in first loop
|
||||||
everyMin(std::bind(&app::tickMinute, this), "tMin");
|
if(mMqttReconnect) { // @TODO: mMqttReconnect is wrong name here
|
||||||
if(mConfig->inst.rstYieldMidNight) {
|
if(mConfig->inst.rstValsNotAvail)
|
||||||
uint32_t midTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight
|
everyMin(std::bind(&app::tickMinute, this), "tMin");
|
||||||
onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi");
|
if(mConfig->inst.rstYieldMidNight) {
|
||||||
|
uint32_t midTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight
|
||||||
|
onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nxtTrig = isOK ? 43200 : 60; // depending on NTP update success check again in 12 h or in 1 min
|
nxtTrig = isOK ? 43200 : 60; // depending on NTP update success check again in 12 h or in 1 min
|
||||||
|
@ -183,6 +185,8 @@ void app::tickNtpUpdate(void) {
|
||||||
mSendFirst = false;
|
mSendFirst = false;
|
||||||
once(std::bind(&app::tickSend, this), 2, "senOn");
|
once(std::bind(&app::tickSend, this), 2, "senOn");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mMqttReconnect = false;
|
||||||
}
|
}
|
||||||
once(std::bind(&app::tickNtpUpdate, this), nxtTrig, "ntp");
|
once(std::bind(&app::tickNtpUpdate, this), nxtTrig, "ntp");
|
||||||
}
|
}
|
||||||
|
@ -233,17 +237,8 @@ void app::tickSun(void) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::tickComm(void) {
|
void app::tickComm(void) {
|
||||||
if(!mIVCommunicationOn && (mConfig->inst.rstValsCommStop)) {
|
if((!mIVCommunicationOn) && (mConfig->inst.rstValsCommStop))
|
||||||
Inverter<> *iv;
|
once(std::bind(&app::tickZeroValues, this), mConfig->nrf.sendInterval, "tZero");
|
||||||
// set values to zero, except yields
|
|
||||||
for (uint8_t id = 0; id < mSys.getNumInverters(); id++) {
|
|
||||||
iv = mSys.getInverterByPos(id);
|
|
||||||
if (NULL == iv)
|
|
||||||
continue; // skip to next inverter
|
|
||||||
|
|
||||||
mPayload.zeroInverterValues(iv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mMqttEnabled) {
|
if (mMqttEnabled) {
|
||||||
if (!mMqtt.tickerComm(!mIVCommunicationOn))
|
if (!mMqtt.tickerComm(!mIVCommunicationOn))
|
||||||
|
@ -251,6 +246,19 @@ void app::tickComm(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void app::tickZeroValues(void) {
|
||||||
|
Inverter<> *iv;
|
||||||
|
// set values to zero, except yields
|
||||||
|
for (uint8_t id = 0; id < mSys.getNumInverters(); id++) {
|
||||||
|
iv = mSys.getInverterByPos(id);
|
||||||
|
if (NULL == iv)
|
||||||
|
continue; // skip to next inverter
|
||||||
|
|
||||||
|
mPayload.zeroInverterValues(iv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::tickMinute(void) {
|
void app::tickMinute(void) {
|
||||||
// only triggered if 'reset values on no avail is enabled'
|
// only triggered if 'reset values on no avail is enabled'
|
||||||
|
@ -273,6 +281,8 @@ void app::tickMidnight(void) {
|
||||||
uint32_t nxtTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight
|
uint32_t nxtTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight
|
||||||
onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2");
|
onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2");
|
||||||
|
|
||||||
|
DPRINTLN(DBG_INFO, "tickMidnight " + String(nxtTrig));
|
||||||
|
|
||||||
Inverter<> *iv;
|
Inverter<> *iv;
|
||||||
// set values to zero, except yield total
|
// set values to zero, except yield total
|
||||||
for (uint8_t id = 0; id < mSys.getNumInverters(); id++) {
|
for (uint8_t id = 0; id < mSys.getNumInverters(); id++) {
|
||||||
|
|
|
@ -223,6 +223,7 @@ class app : public IApp, public ah::Scheduler {
|
||||||
void tickComm(void);
|
void tickComm(void);
|
||||||
void tickSend(void);
|
void tickSend(void);
|
||||||
void tickMinute(void);
|
void tickMinute(void);
|
||||||
|
void tickZeroValues(void);
|
||||||
void tickMidnight(void);
|
void tickMidnight(void);
|
||||||
/*void tickSerial(void) {
|
/*void tickSerial(void) {
|
||||||
if(Serial.available() == 0)
|
if(Serial.available() == 0)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 5
|
#define VERSION_MINOR 5
|
||||||
#define VERSION_PATCH 84
|
#define VERSION_PATCH 85
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -71,36 +71,31 @@ class HmPayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
void zeroYieldDay(Inverter<> *iv) {
|
void zeroYieldDay(Inverter<> *iv) {
|
||||||
|
DPRINTLN(DBG_INFO, "zeroYieldDay");
|
||||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
uint8_t pos = iv->getPosByChFld(CH0, FLD_YD, rec);
|
uint8_t pos;
|
||||||
iv->setValue(pos, rec, 0.0f);
|
for(uint8_t ch = 0; ch < iv->channels; ch++) {
|
||||||
|
pos = iv->getPosByChFld(CH0, FLD_YD, rec);
|
||||||
|
iv->setValue(pos, rec, 0.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void zeroInverterValues(Inverter<> *iv) {
|
void zeroInverterValues(Inverter<> *iv) {
|
||||||
|
DPRINTLN(DBG_INFO, "zeroInverterValues");
|
||||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
for(uint8_t ch = 0; ch <= iv->channels; ch++) {
|
for(uint8_t ch = 0; ch <= iv->channels; ch++) {
|
||||||
uint8_t pos = 0;
|
uint8_t pos = 0;
|
||||||
uint8_t fld = 0;
|
for(uint8_t fld = 0; fld < FLD_EVT; fld++) {
|
||||||
while(0xff != pos) {
|
|
||||||
switch(fld) {
|
switch(fld) {
|
||||||
case FLD_YD:
|
case FLD_YD:
|
||||||
case FLD_YT:
|
case FLD_YT:
|
||||||
case FLD_FW_VERSION:
|
|
||||||
case FLD_FW_BUILD_YEAR:
|
|
||||||
case FLD_FW_BUILD_MONTH_DAY:
|
|
||||||
case FLD_FW_BUILD_HOUR_MINUTE:
|
|
||||||
case FLD_HW_ID:
|
|
||||||
case FLD_ACT_ACTIVE_PWR_LIMIT:
|
|
||||||
fld++;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
pos = iv->getPosByChFld(ch, fld, rec);
|
pos = iv->getPosByChFld(ch, fld, rec);
|
||||||
iv->setValue(pos, rec, 0.0f);
|
iv->setValue(pos, rec, 0.0f);
|
||||||
fld++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iv->doCalculations();
|
|
||||||
notify(RealTimeRunData_Debug);
|
notify(RealTimeRunData_Debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,16 +212,16 @@ class HmPayload {
|
||||||
crcPass = build(iv->id, &pyldComplete);
|
crcPass = build(iv->id, &pyldComplete);
|
||||||
if (!crcPass && !pyldComplete) { // payload not complete
|
if (!crcPass && !pyldComplete) { // payload not complete
|
||||||
if ((mPayload[iv->id].requested) && (retransmit)) {
|
if ((mPayload[iv->id].requested) && (retransmit)) {
|
||||||
if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) {
|
if (mPayload[iv->id].retransmits < mMaxRetrans) {
|
||||||
// This is required to prevent retransmissions without answer.
|
mPayload[iv->id].retransmits++;
|
||||||
DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm..."));
|
if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) {
|
||||||
mPayload[iv->id].retransmits = mMaxRetrans;
|
// This is required to prevent retransmissions without answer.
|
||||||
} else if(iv->devControlCmd == ActivePowerContr) {
|
DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm..."));
|
||||||
DPRINTLN(DBG_INFO, F("retransmit power limit"));
|
mPayload[iv->id].retransmits = mMaxRetrans;
|
||||||
mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true);
|
} else if(iv->devControlCmd == ActivePowerContr) {
|
||||||
} else {
|
DPRINTLN(DBG_INFO, F("retransmit power limit"));
|
||||||
if (mPayload[iv->id].retransmits < mMaxRetrans) {
|
mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true);
|
||||||
mPayload[iv->id].retransmits++;
|
} else {
|
||||||
if(false == mPayload[iv->id].gotFragment) {
|
if(false == mPayload[iv->id].gotFragment) {
|
||||||
/*
|
/*
|
||||||
DPRINTLN(DBG_WARN, F("nothing received: Request Complete Retransmit"));
|
DPRINTLN(DBG_WARN, F("nothing received: Request Complete Retransmit"));
|
||||||
|
|
|
@ -104,6 +104,7 @@ class HmRadio {
|
||||||
mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms
|
mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms
|
||||||
|
|
||||||
mNrf24.setChannel(mRfChLst[mRxChIdx]);
|
mNrf24.setChannel(mRfChLst[mRxChIdx]);
|
||||||
|
mNrf24.startListening();
|
||||||
mNrf24.setDataRate(RF24_250KBPS);
|
mNrf24.setDataRate(RF24_250KBPS);
|
||||||
mNrf24.setAutoAck(true);
|
mNrf24.setAutoAck(true);
|
||||||
mNrf24.enableDynamicPayloads();
|
mNrf24.enableDynamicPayloads();
|
||||||
|
@ -118,8 +119,6 @@ class HmRadio {
|
||||||
DPRINTLN(DBG_INFO, String(rf24AmpPowerNames[ampPwr]));
|
DPRINTLN(DBG_INFO, String(rf24AmpPowerNames[ampPwr]));
|
||||||
mNrf24.setPALevel(ampPwr & 0x03);
|
mNrf24.setPALevel(ampPwr & 0x03);
|
||||||
|
|
||||||
mNrf24.startListening();
|
|
||||||
|
|
||||||
if(mNrf24.isChipConnected()) {
|
if(mNrf24.isChipConnected()) {
|
||||||
DPRINTLN(DBG_INFO, F("Radio Config:"));
|
DPRINTLN(DBG_INFO, F("Radio Config:"));
|
||||||
mNrf24.printPrettyDetails();
|
mNrf24.printPrettyDetails();
|
||||||
|
@ -140,6 +139,7 @@ class HmRadio {
|
||||||
// start listening on the default RX channel
|
// start listening on the default RX channel
|
||||||
mRxChIdx = 0;
|
mRxChIdx = 0;
|
||||||
mNrf24.setChannel(mRfChLst[mRxChIdx]);
|
mNrf24.setChannel(mRfChLst[mRxChIdx]);
|
||||||
|
mNrf24.startListening();
|
||||||
|
|
||||||
//uint32_t debug_ms = millis();
|
//uint32_t debug_ms = millis();
|
||||||
uint16_t cnt = 300; // that is 60 times 5 channels
|
uint16_t cnt = 300; // that is 60 times 5 channels
|
||||||
|
@ -150,7 +150,6 @@ class HmRadio {
|
||||||
mIrqRcvd = false;
|
mIrqRcvd = false;
|
||||||
if (getReceived()) { // everything received
|
if (getReceived()) { // everything received
|
||||||
//DBGPRINTLN("RX finished Cnt: " + String(300-cnt) + " time used: " + String(millis()-debug_ms)+ " ms");
|
//DBGPRINTLN("RX finished Cnt: " + String(300-cnt) + " time used: " + String(millis()-debug_ms)+ " ms");
|
||||||
mNrf24.stopListening();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ class PubMqtt {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect() {
|
inline void connect() {
|
||||||
mReconnectRequest = false;
|
mReconnectRequest = false;
|
||||||
if(!mClient.connected())
|
if(!mClient.connected())
|
||||||
mClient.connect();
|
mClient.connect();
|
||||||
|
@ -136,6 +136,7 @@ class PubMqtt {
|
||||||
}
|
}
|
||||||
|
|
||||||
void payloadEventListener(uint8_t cmd) {
|
void payloadEventListener(uint8_t cmd) {
|
||||||
|
connect();
|
||||||
if(mClient.connected()) { // prevent overflow if MQTT broker is not reachable but set
|
if(mClient.connected()) { // prevent overflow if MQTT broker is not reachable but set
|
||||||
if((0 == mCfgMqtt->interval) || (RealTimeRunData_Debug != cmd)) // no interval or no live data
|
if((0 == mCfgMqtt->interval) || (RealTimeRunData_Debug != cmd)) // no interval or no live data
|
||||||
mSendList.push(cmd);
|
mSendList.push(cmd);
|
||||||
|
@ -302,8 +303,12 @@ class PubMqtt {
|
||||||
tickerMinute();
|
tickerMinute();
|
||||||
publish(mLwtTopic, mLwtOnline, true, false);
|
publish(mLwtTopic, mLwtOnline, true, false);
|
||||||
|
|
||||||
subscribe("ctrl/#");
|
subscribe("ctrl/limit_persistent_relative");
|
||||||
subscribe("setup/#");
|
subscribe("ctrl/limit_persistent_absolute");
|
||||||
|
subscribe("ctrl/limit_nonpersistent_relative");
|
||||||
|
subscribe("ctrl/limit_nonpersistent_absolute");
|
||||||
|
subscribe("setup/set_time");
|
||||||
|
subscribe("setup/sync_ntp");
|
||||||
//subscribe("status/#");
|
//subscribe("status/#");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,12 +145,12 @@
|
||||||
if(obj["ts_sunrise"] > 0) {
|
if(obj["ts_sunrise"] > 0) {
|
||||||
if(((obj["ts_sunrise"] - obj["ts_offset"]) < obj["ts_now"])
|
if(((obj["ts_sunrise"] - obj["ts_offset"]) < obj["ts_now"])
|
||||||
&& ((obj["ts_sunset"] + obj["ts_offset"]) > obj["ts_now"])) {
|
&& ((obj["ts_sunset"] + obj["ts_offset"]) > obj["ts_now"])) {
|
||||||
commInfo = "Polling inverter(s), will stop at " + (new Date((obj["ts_sunset"] + obj["ts_offset"]) * 1000).toLocaleString('de-DE'));
|
commInfo = "Polling inverter(s), will stop at sunset " + (new Date((obj["ts_sunset"] + obj["ts_offset"]) * 1000).toLocaleString('de-DE'));
|
||||||
}
|
}
|
||||||
else if(obj["disNightComm"]) {
|
else if(obj["disNightComm"]) {
|
||||||
commInfo = "Night time, no Communication to Inverter, ";
|
commInfo = "Night time, inverter polling disabled, ";
|
||||||
if(obj["ts_now"] > (obj["ts_sunrise"] - obj["ts_offset"])) {
|
if(obj["ts_now"] > (obj["ts_sunrise"] - obj["ts_offset"])) {
|
||||||
commInfo += "stopped polling at " + (new Date((obj["ts_sunset"] + obj["ts_offset"]) * 1000).toLocaleString('de-DE'));
|
commInfo += "stopped at " + (new Date((obj["ts_sunset"] + obj["ts_offset"]) * 1000).toLocaleString('de-DE'));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
commInfo += "will start polling at " + (new Date((obj["ts_sunrise"] - obj["ts_offset"]) * 1000).toLocaleString('de-DE'));
|
commInfo += "will start polling at " + (new Date((obj["ts_sunrise"] - obj["ts_offset"]) * 1000).toLocaleString('de-DE'));
|
||||||
|
|
|
@ -96,11 +96,12 @@
|
||||||
<label for="invRetry">Max retries per Payload</label>
|
<label for="invRetry">Max retries per Payload</label>
|
||||||
<input type="text" class="text" name="invRetry"/>
|
<input type="text" class="text" name="invRetry"/>
|
||||||
|
|
||||||
<label for="invRstMid">Reset Values and YieldDay at Midnight</label>
|
|
||||||
|
<label for="invRstMid">Reset values and YieldDay at midnight</label>
|
||||||
<input type="checkbox" class="cb" name="invRstMid"/><br/>
|
<input type="checkbox" class="cb" name="invRstMid"/><br/>
|
||||||
<label for="invRstComStop">Reset Values at Communication stop</label>
|
<label for="invRstComStop">Reset values when inverter polling stops at sunset</label>
|
||||||
<input type="checkbox" class="cb" name="invRstComStop"/><br/>
|
<input type="checkbox" class="cb" name="invRstComStop"/><br/>
|
||||||
<label for="invRstNotAvail">Reset Values on 'not available'</label>
|
<label for="invRstNotAvail">Reset values when inverter status is 'not available'</label>
|
||||||
<input type="checkbox" class="cb" name="invRstNotAvail"/><br/>
|
<input type="checkbox" class="cb" name="invRstNotAvail"/><br/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
@ -125,7 +126,7 @@
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend class="des">Sunrise & Sunset</legend>
|
<legend class="des">Sunrise & Sunset</legend>
|
||||||
<p>
|
<p>
|
||||||
Latitude and Longitude must be set to be stored! decimal separator: '.' (dot)
|
Use a decimal separator: '.' (dot) for Latitude and Longitude
|
||||||
</p>
|
</p>
|
||||||
<label for="sunLat">Latitude (decimal)</label>
|
<label for="sunLat">Latitude (decimal)</label>
|
||||||
<input type="text" class="text" name="sunLat"/>
|
<input type="text" class="text" name="sunLat"/>
|
||||||
|
@ -134,7 +135,7 @@
|
||||||
<label for="sunOffs">Offset (pre sunrise, post sunset)</label>
|
<label for="sunOffs">Offset (pre sunrise, post sunset)</label>
|
||||||
<select name="sunOffs"></select>
|
<select name="sunOffs"></select>
|
||||||
<br>
|
<br>
|
||||||
<label for="sunDisNightCom">disable night communication</label>
|
<label for="sunDisNightCom">Stop polling inverters during night</label>
|
||||||
<input type="checkbox" class="cb" name="sunDisNightCom"/><br/>
|
<input type="checkbox" class="cb" name="sunDisNightCom"/><br/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -282,7 +282,8 @@ input.btn:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
input.cb {
|
input.cb {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 15px;
|
||||||
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue