Browse Source

changed calculation of start / stop communication to 1 min after last comm. stop #515

moved payload send to `payload.h`, function `ivSend` #515
pull/555/head
lumapu 2 years ago
parent
commit
19e86ebdb2
  1. 39
      src/CHANGES.md
  2. 63
      src/app.cpp
  3. 2
      src/defines.h
  4. 89
      src/hm/payload.h

39
src/CHANGES.md

@ -1,36 +1,7 @@
# Changelog v0.5.66
# Changelog
**Note:** Version `0.5.42` to `0.5.65` were development versions. Last release version was `0.5.41`
Detailed change log (development changes): https://github.com/lumapu/ahoy/blob/945a671d27d10d0f7c175ebbf2fbb2806f9cd79a/src/CHANGES.md
(starting from release version `0.5.66`)
* updated REST API and MQTT (both of them use the same functionality)
* improved stability
* Regular expressions for input fields which are used for MQTT to be compliant to MQTT
* WiFi optimization (AP Mode and STA in parallel, reconnect if local STA is unavailable)
* improved display of `/system`
* fix Update button protection (prevent double click #527)
* optimized scheduler #515
* fix of duplicates in API `/api/record/live` (#526)
* added update information to `index.html` (check for update with github.com)
* fix web logout (auto logout)
* switched MQTT library
* removed MQTT `available_text` (can be deducted from `available`)
* enhanced MQTT documentation in `User_Manual.md`
* changed MQTT topic `status` to nummeric value, check documentation in `User_Manual.md`
* added immediate (each minute) report of inverter status MQTT #522
* increased MQTT user, pwd and topic length to 64 characters + `\0`. (The string end `\0` reduces the available size by one) #516
* added disable night communication flag to MQTT #505
* added MQTT <TOPIC>/status to show status over all inverters
* added MQTT RX counter to index.html
* added protection mask to select which pages should be protected
* added monochrome display that show values also if nothing changed and in offline mode #498
* added icons to index.html, added WiFi-strength symbol on each page
* refactored communication offset (adjustable in minutes now)
* factory reset formats entire little fs
* renamed sunrise / sunset on index.html to start / stop communication
* fixed static IP save
* fix NTP with static IP
* all values are displayed on /live even if they are 0
* added NRF24 info to Systeminfo
* reordered enqueue commands after boot up to prevent same payload length for successive commands
## 0.5.67
* changed calculation of start / stop communication to 1 min after last comm. stop #515
* moved payload send to `payload.h`, function `ivSend` #515

63
src/app.cpp

@ -51,7 +51,7 @@ void app::setup() {
#endif
mSys->addInverters(&mConfig->inst);
mPayload.setup(mSys);
mPayload.setup(mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp);
mPayload.enableSerialDebug(mConfig->serial.debug);
if(!mSys->Radio.isChipConnected())
@ -115,7 +115,9 @@ void app::loop(void) {
yield();
if (rxRdy)
mPayload.process(true, mConfig->nrf.maxRetransPerPyld, &mStat);
mPayload.process(true);
mRxTicker = 0;
}
#if !defined(AP_ONLY)
@ -138,14 +140,18 @@ void app::tickNtpUpdate(void) {
//-----------------------------------------------------------------------------
void app::tickCalcSunrise(void) {
ah::calculateSunriseSunset(mTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset);
if (mSunrise == 0) // on boot/reboot calc sun values for current time
ah::calculateSunriseSunset(mTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset);
if (mTimestamp > (mSunset + mConfig->sun.offsetSec)) // current time is past communication stop, calc sun values for next day
ah::calculateSunriseSunset(mTimestamp + 86400, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset);
tickIVCommunication();
uint32_t nxtTrig = mTimestamp - ((mTimestamp + mCalculatedTimezoneOffset - 10) % 86400) + 86400;; // next midnight, -10 for safety that it is certain next day, local timezone
uint32_t nxtTrig = mSunset + mConfig->sun.offsetSec + 60; // set next trigger to communication stop, +60 for safety that it is certain past communication stop
onceAt(std::bind(&app::tickCalcSunrise, this), nxtTrig);
if (mConfig->mqtt.broker[0] > 0) {
if (mConfig->mqtt.broker[0] > 0)
mMqtt.tickerSun(mSunrise, mSunset, mConfig->sun.offsetSec, mConfig->sun.disNightCom);
}
}
//-----------------------------------------------------------------------------
@ -187,49 +193,8 @@ void app::tickSend(void) {
} while ((NULL == iv) && ((maxLoop--) > 0));
if (NULL != iv) {
if(iv->config->enabled) {
if (!mPayload.isComplete(iv))
mPayload.process(false, mConfig->nrf.maxRetransPerPyld, &mStat);
if (!mPayload.isComplete(iv)) {
if (0 == mPayload.getMaxPacketId(iv))
mStat.rxFailNoAnser++;
else
mStat.rxFail++;
iv->setQueuedCmdFinished(); // command failed
if (mConfig->serial.debug)
DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout"));
if (mConfig->serial.debug) {
DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") ");
DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload.getRetransmits(iv)) + ")");
}
}
mPayload.reset(iv, mTimestamp);
mPayload.request(iv);
yield();
if (mConfig->serial.debug) {
DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status()));
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX));
}
if (iv->devControlRequest) {
if (mConfig->serial.debug)
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0]));
mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit);
mPayload.setTxCmd(iv, iv->devControlCmd);
iv->clearCmdQueue();
iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit
} else {
uint8_t cmd = iv->getQueuedCmd();
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket"));
mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload.getTs(iv), iv->alarmMesIndex);
mPayload.setTxCmd(iv, cmd);
mRxTicker = 0;
}
}
if(iv->config->enabled)
mPayload.ivSend(iv);
}
} else {
if (mConfig->serial.debug)

2
src/defines.h

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

89
src/hm/payload.h

@ -34,45 +34,65 @@ class Payload : public Handler<payloadListenerType> {
public:
Payload() : Handler() {}
void setup(HMSYSTEM *sys) {
mSys = sys;
void setup(HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) {
mSys = sys;
mStat = stat;
mMaxRetrans = maxRetransmits;
mTimestamp = timestamp;
memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t)));
mLastPacketId = 0x00;
mSerialDebug = false;
mSerialDebug = false;
}
void enableSerialDebug(bool enable) {
mSerialDebug = enable;
}
bool isComplete(Inverter<> *iv) {
return mPayload[iv->id].complete;
}
uint8_t getMaxPacketId(Inverter<> *iv) {
return mPayload[iv->id].maxPackId;
}
uint8_t getRetransmits(Inverter<> *iv) {
return mPayload[iv->id].retransmits;
void notify(uint8_t val) {
for(typename std::list<payloadListenerType>::iterator it = mList.begin(); it != mList.end(); ++it) {
(*it)(val);
}
}
uint32_t getTs(Inverter<> *iv) {
return mPayload[iv->id].ts;
}
void ivSend(Inverter<> *iv) {
if (!mPayload[iv->id].complete)
process(false);
void request(Inverter<> *iv) {
mPayload[iv->id].requested = true;
}
if (!mPayload[iv->id].complete) {
if (0 == mPayload[iv->id].maxPackId)
mStat->rxFailNoAnser++;
else
mStat->rxFail++;
iv->setQueuedCmdFinished(); // command failed
if (mSerialDebug)
DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout"));
if (mSerialDebug) {
DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") ");
DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload[iv->id].retransmits) + ")");
}
}
void setTxCmd(Inverter<> *iv, uint8_t cmd) {
mPayload[iv->id].txCmd = cmd;
}
reset(iv);
mPayload[iv->id].requested = true;
void notify(uint8_t val) {
for(typename std::list<payloadListenerType>::iterator it = mList.begin(); it != mList.end(); ++it) {
(*it)(val);
}
yield();
if (mSerialDebug)
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX));
if (iv->devControlRequest) {
if (mSerialDebug)
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0]));
mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit);
mPayload[iv->id].txCmd = iv->devControlCmd;
iv->clearCmdQueue();
iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit
} else {
uint8_t cmd = iv->getQueuedCmd();
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket"));
mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex);
mPayload[iv->id].txCmd = cmd;
}
}
void add(packet_t *p, uint8_t len) {
@ -134,7 +154,7 @@ class Payload : public Handler<payloadListenerType> {
return (crc == crcRcv) ? true : false;
}
void process(bool retransmit, uint8_t maxRetransmits, statistics_t *stat) {
void process(bool retransmit) {
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL == iv)
@ -152,9 +172,9 @@ class Payload : public Handler<payloadListenerType> {
if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) {
// This is required to prevent retransmissions without answer.
DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm..."));
mPayload[iv->id].retransmits = maxRetransmits;
mPayload[iv->id].retransmits = mMaxRetrans;
} else {
if (mPayload[iv->id].retransmits < maxRetransmits) {
if (mPayload[iv->id].retransmits < mMaxRetrans) {
mPayload[iv->id].retransmits++;
if (mPayload[iv->id].maxPackId != 0) {
for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) {
@ -207,7 +227,7 @@ class Payload : public Handler<payloadListenerType> {
DPRINTLN(DBG_ERROR, F("record is NULL!"));
} else if ((rec->pyldLen == payloadLen) || (0 == rec->pyldLen)) {
if (mPayload[iv->id].txId == (TX_REQ_INFO + 0x80))
stat->rxSuccess++;
mStat->rxSuccess++;
rec->ts = mPayload[iv->id].ts;
for (uint8_t i = 0; i < rec->length; i++) {
@ -218,7 +238,7 @@ class Payload : public Handler<payloadListenerType> {
notify(mPayload[iv->id].txCmd);
} else {
DPRINTLN(DBG_ERROR, F("plausibility check failed, expected ") + String(rec->pyldLen) + F(" bytes"));
stat->rxFail++;
mStat->rxFail++;
}
iv->setQueuedCmdFinished();
@ -230,7 +250,7 @@ class Payload : public Handler<payloadListenerType> {
}
}
void reset(Inverter<> *iv, uint32_t utcTs) {
void reset(Inverter<> *iv) {
DPRINTLN(DBG_INFO, "resetPayload: id: " + String(iv->id));
memset(mPayload[iv->id].len, 0, MAX_PAYLOAD_ENTRIES);
mPayload[iv->id].txCmd = 0;
@ -238,11 +258,14 @@ class Payload : public Handler<payloadListenerType> {
mPayload[iv->id].maxPackId = 0;
mPayload[iv->id].complete = false;
mPayload[iv->id].requested = false;
mPayload[iv->id].ts = utcTs;
mPayload[iv->id].ts = *mTimestamp;
}
private:
HMSYSTEM *mSys;
statistics_t *mStat;
uint8_t mMaxRetrans;
uint32_t *mTimestamp;
invPayload_t mPayload[MAX_NUM_INVERTERS];
uint8_t mLastPacketId;
bool mSerialDebug;

Loading…
Cancel
Save