mirror of
https://github.com/lumapu/ahoy.git
synced 2025-06-12 07:31:42 +02:00
changed calculation of start / stop communication to 1 min after last comm. stop #515
moved payload send to `payload.h`, function `ivSend` #515
This commit is contained in:
parent
f8fe044e1b
commit
19e86ebdb2
4 changed files with 77 additions and 118 deletions
|
@ -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`
|
(starting from release version `0.5.66`)
|
||||||
Detailed change log (development changes): https://github.com/lumapu/ahoy/blob/945a671d27d10d0f7c175ebbf2fbb2806f9cd79a/src/CHANGES.md
|
|
||||||
|
|
||||||
|
## 0.5.67
|
||||||
* updated REST API and MQTT (both of them use the same functionality)
|
* changed calculation of start / stop communication to 1 min after last comm. stop #515
|
||||||
* improved stability
|
* moved payload send to `payload.h`, function `ivSend` #515
|
||||||
* 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
|
|
||||||
|
|
61
src/app.cpp
61
src/app.cpp
|
@ -51,7 +51,7 @@ void app::setup() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mSys->addInverters(&mConfig->inst);
|
mSys->addInverters(&mConfig->inst);
|
||||||
mPayload.setup(mSys);
|
mPayload.setup(mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp);
|
||||||
mPayload.enableSerialDebug(mConfig->serial.debug);
|
mPayload.enableSerialDebug(mConfig->serial.debug);
|
||||||
|
|
||||||
if(!mSys->Radio.isChipConnected())
|
if(!mSys->Radio.isChipConnected())
|
||||||
|
@ -115,7 +115,9 @@ void app::loop(void) {
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
if (rxRdy)
|
if (rxRdy)
|
||||||
mPayload.process(true, mConfig->nrf.maxRetransPerPyld, &mStat);
|
mPayload.process(true);
|
||||||
|
|
||||||
|
mRxTicker = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(AP_ONLY)
|
#if !defined(AP_ONLY)
|
||||||
|
@ -138,14 +140,18 @@ void app::tickNtpUpdate(void) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::tickCalcSunrise(void) {
|
void app::tickCalcSunrise(void) {
|
||||||
|
if (mSunrise == 0) // on boot/reboot calc sun values for current time
|
||||||
ah::calculateSunriseSunset(mTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset);
|
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();
|
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);
|
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);
|
mMqtt.tickerSun(mSunrise, mSunset, mConfig->sun.offsetSec, mConfig->sun.disNightCom);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -187,49 +193,8 @@ void app::tickSend(void) {
|
||||||
} while ((NULL == iv) && ((maxLoop--) > 0));
|
} while ((NULL == iv) && ((maxLoop--) > 0));
|
||||||
|
|
||||||
if (NULL != iv) {
|
if (NULL != iv) {
|
||||||
if(iv->config->enabled) {
|
if(iv->config->enabled)
|
||||||
if (!mPayload.isComplete(iv))
|
mPayload.ivSend(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mConfig->serial.debug)
|
if (mConfig->serial.debug)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 5
|
#define VERSION_MINOR 5
|
||||||
#define VERSION_PATCH 66
|
#define VERSION_PATCH 67
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -34,8 +34,11 @@ class Payload : public Handler<payloadListenerType> {
|
||||||
public:
|
public:
|
||||||
Payload() : Handler() {}
|
Payload() : Handler() {}
|
||||||
|
|
||||||
void setup(HMSYSTEM *sys) {
|
void setup(HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) {
|
||||||
mSys = sys;
|
mSys = sys;
|
||||||
|
mStat = stat;
|
||||||
|
mMaxRetrans = maxRetransmits;
|
||||||
|
mTimestamp = timestamp;
|
||||||
memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t)));
|
memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t)));
|
||||||
mLastPacketId = 0x00;
|
mLastPacketId = 0x00;
|
||||||
mSerialDebug = false;
|
mSerialDebug = false;
|
||||||
|
@ -45,36 +48,53 @@ class Payload : public Handler<payloadListenerType> {
|
||||||
mSerialDebug = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getTs(Inverter<> *iv) {
|
|
||||||
return mPayload[iv->id].ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
void request(Inverter<> *iv) {
|
|
||||||
mPayload[iv->id].requested = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTxCmd(Inverter<> *iv, uint8_t cmd) {
|
|
||||||
mPayload[iv->id].txCmd = cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void notify(uint8_t val) {
|
void notify(uint8_t val) {
|
||||||
for(typename std::list<payloadListenerType>::iterator it = mList.begin(); it != mList.end(); ++it) {
|
for(typename std::list<payloadListenerType>::iterator it = mList.begin(); it != mList.end(); ++it) {
|
||||||
(*it)(val);
|
(*it)(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ivSend(Inverter<> *iv) {
|
||||||
|
if (!mPayload[iv->id].complete)
|
||||||
|
process(false);
|
||||||
|
|
||||||
|
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) + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(iv);
|
||||||
|
mPayload[iv->id].requested = true;
|
||||||
|
|
||||||
|
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) {
|
void add(packet_t *p, uint8_t len) {
|
||||||
Inverter<> *iv = mSys->findInverter(&p->packet[1]);
|
Inverter<> *iv = mSys->findInverter(&p->packet[1]);
|
||||||
if ((NULL != iv) && (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES))) { // response from get information command
|
if ((NULL != iv) && (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES))) { // response from get information command
|
||||||
|
@ -134,7 +154,7 @@ class Payload : public Handler<payloadListenerType> {
|
||||||
return (crc == crcRcv) ? true : false;
|
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++) {
|
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
|
||||||
Inverter<> *iv = mSys->getInverterByPos(id);
|
Inverter<> *iv = mSys->getInverterByPos(id);
|
||||||
if (NULL == iv)
|
if (NULL == iv)
|
||||||
|
@ -152,9 +172,9 @@ class Payload : public Handler<payloadListenerType> {
|
||||||
if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) {
|
if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) {
|
||||||
// This is required to prevent retransmissions without answer.
|
// This is required to prevent retransmissions without answer.
|
||||||
DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm..."));
|
DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm..."));
|
||||||
mPayload[iv->id].retransmits = maxRetransmits;
|
mPayload[iv->id].retransmits = mMaxRetrans;
|
||||||
} else {
|
} else {
|
||||||
if (mPayload[iv->id].retransmits < maxRetransmits) {
|
if (mPayload[iv->id].retransmits < mMaxRetrans) {
|
||||||
mPayload[iv->id].retransmits++;
|
mPayload[iv->id].retransmits++;
|
||||||
if (mPayload[iv->id].maxPackId != 0) {
|
if (mPayload[iv->id].maxPackId != 0) {
|
||||||
for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) {
|
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!"));
|
DPRINTLN(DBG_ERROR, F("record is NULL!"));
|
||||||
} else if ((rec->pyldLen == payloadLen) || (0 == rec->pyldLen)) {
|
} else if ((rec->pyldLen == payloadLen) || (0 == rec->pyldLen)) {
|
||||||
if (mPayload[iv->id].txId == (TX_REQ_INFO + 0x80))
|
if (mPayload[iv->id].txId == (TX_REQ_INFO + 0x80))
|
||||||
stat->rxSuccess++;
|
mStat->rxSuccess++;
|
||||||
|
|
||||||
rec->ts = mPayload[iv->id].ts;
|
rec->ts = mPayload[iv->id].ts;
|
||||||
for (uint8_t i = 0; i < rec->length; i++) {
|
for (uint8_t i = 0; i < rec->length; i++) {
|
||||||
|
@ -218,7 +238,7 @@ class Payload : public Handler<payloadListenerType> {
|
||||||
notify(mPayload[iv->id].txCmd);
|
notify(mPayload[iv->id].txCmd);
|
||||||
} else {
|
} else {
|
||||||
DPRINTLN(DBG_ERROR, F("plausibility check failed, expected ") + String(rec->pyldLen) + F(" bytes"));
|
DPRINTLN(DBG_ERROR, F("plausibility check failed, expected ") + String(rec->pyldLen) + F(" bytes"));
|
||||||
stat->rxFail++;
|
mStat->rxFail++;
|
||||||
}
|
}
|
||||||
|
|
||||||
iv->setQueuedCmdFinished();
|
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));
|
DPRINTLN(DBG_INFO, "resetPayload: id: " + String(iv->id));
|
||||||
memset(mPayload[iv->id].len, 0, MAX_PAYLOAD_ENTRIES);
|
memset(mPayload[iv->id].len, 0, MAX_PAYLOAD_ENTRIES);
|
||||||
mPayload[iv->id].txCmd = 0;
|
mPayload[iv->id].txCmd = 0;
|
||||||
|
@ -238,11 +258,14 @@ class Payload : public Handler<payloadListenerType> {
|
||||||
mPayload[iv->id].maxPackId = 0;
|
mPayload[iv->id].maxPackId = 0;
|
||||||
mPayload[iv->id].complete = false;
|
mPayload[iv->id].complete = false;
|
||||||
mPayload[iv->id].requested = false;
|
mPayload[iv->id].requested = false;
|
||||||
mPayload[iv->id].ts = utcTs;
|
mPayload[iv->id].ts = *mTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HMSYSTEM *mSys;
|
HMSYSTEM *mSys;
|
||||||
|
statistics_t *mStat;
|
||||||
|
uint8_t mMaxRetrans;
|
||||||
|
uint32_t *mTimestamp;
|
||||||
invPayload_t mPayload[MAX_NUM_INVERTERS];
|
invPayload_t mPayload[MAX_NUM_INVERTERS];
|
||||||
uint8_t mLastPacketId;
|
uint8_t mLastPacketId;
|
||||||
bool mSerialDebug;
|
bool mSerialDebug;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue