From 9cedb41ff4ec19049dfde7f9e478a6a5c78d3854 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 22 Jan 2023 01:04:33 +0100 Subject: [PATCH] implemented `getNTPTime` improvements #609 partially #611 added alarm messages to MQTT #177, #600, #608 --- src/CHANGES.md | 2 ++ src/app.cpp | 10 +++++++--- src/app.h | 5 ++--- src/hm/hmInverter.h | 13 ++++++------- src/hm/payload.h | 33 +++++++++++++++++++++++++-------- src/publisher/pubMqtt.h | 27 +++++++++++++++++++++++++++ src/utils/handler.h | 33 --------------------------------- src/wifi/ahoywifi.cpp | 19 ++++--------------- src/wifi/ahoywifi.h | 7 +++++-- 9 files changed, 78 insertions(+), 71 deletions(-) delete mode 100644 src/utils/handler.h diff --git a/src/CHANGES.md b/src/CHANGES.md index f1b217ddd..1d3591298 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -5,6 +5,8 @@ ## 0.5.76 * reduce MQTT retry interval from maximum speed to one second * fixed homeassistant autodiscovery #565 +* implemented `getNTPTime` improvements #609 partially #611 +* added alarm messages to MQTT #177, #600, #608 ## 0.5.75 * fix wakeup issue, once wifi was lost during night the communication didn't start in the morning diff --git a/src/app.cpp b/src/app.cpp index 7f4071a2c..0d88847e2 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -28,7 +28,7 @@ void app::setup() { mSys = new HmSystemType(); mSys->enableDebug(); mSys->setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); - mPayload.addListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); + mPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); #if defined(AP_ONLY) mInnerLoopCb = std::bind(&app::loopStandard, this); @@ -54,6 +54,7 @@ void app::setup() { if (mMqttEnabled) { mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mTimestamp); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); + mPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } #endif setupLed(); @@ -134,6 +135,8 @@ void app::onWifi(bool gotIp) { mMqttReconnect = true; mSunrise = 0; // needs to be set to 0, to reinstall sunrise and ivComm tickers! once(std::bind(&app::tickNtpUpdate, this), 2, "ntp2"); + if(WIFI_AP == WiFi.getMode()) + everySec(std::bind(&ahoywifi::tickWifiLoop, &mWifi), "wifiL"); } else { mInnerLoopCb = std::bind(&app::loopWifi, this); @@ -154,7 +157,8 @@ void app::regularTickers(void) { //----------------------------------------------------------------------------- void app::tickNtpUpdate(void) { uint32_t nxtTrig = 5; // default: check again in 5 sec - if (mWifi.getNtpTime()) { + bool isOK = mWifi.getNtpTime(); + if (isOK || mTimestamp != 0) { if (mMqttReconnect && mMqttEnabled) { mMqtt.connect(); everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS"); @@ -166,7 +170,7 @@ void app::tickNtpUpdate(void) { mMqttReconnect = false; } - nxtTrig = 43200; // check again in 12h + nxtTrig = isOK ? 43200 : 60; // depending on NTP update success check again in 12 h or in 1 min if((mSunrise == 0) && (mConfig->sun.lat) && (mConfig->sun.lon)) { mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; diff --git a/src/app.h b/src/app.h index 0466daf87..d51c9209e 100644 --- a/src/app.h +++ b/src/app.h @@ -195,9 +195,8 @@ class app : public IApp, public ah::Scheduler { #if !defined(AP_ONLY) mMqtt.payloadEventListener(cmd); #endif - #if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) - mMonoDisplay.payloadEventListener(cmd); - #endif + if(mConfig->plugin.display.type != 0) + mMonoDisplay.payloadEventListener(cmd); } void mqttSubRxCb(JsonObject obj); diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 3cdeb101f..640aeae39 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -286,7 +286,6 @@ class Inverter { } else if (rec->assign == SystemConfigParaAssignment) { DPRINTLN(DBG_DEBUG, "add config"); - // get at least the firmware version and save it to the inverter object if (getPosByChFld(0, FLD_ACT_ACTIVE_PWR_LIMIT, rec) == pos){ actPowerLimit = rec->record[pos]; DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit, 1)); @@ -451,10 +450,10 @@ class Inverter { } } - bool parseAlarmLog(uint8_t id, uint8_t pyld[], uint8_t len) { + uint16_t parseAlarmLog(uint8_t id, uint8_t pyld[], uint8_t len, uint32_t *start, uint32_t *endTime) { uint8_t startOff = 2 + id * ALARM_LOG_ENTRY_SIZE; if((startOff + ALARM_LOG_ENTRY_SIZE) > len) - return false; + return 0; uint16_t wCode = ((uint16_t)pyld[startOff]) << 8 | pyld[startOff+1]; uint32_t startTimeOffset = 0, endTimeOffset = 0; @@ -464,11 +463,11 @@ class Inverter { if (((wCode >> 12) & 0x01) == 1) // check if is AM or PM endTimeOffset = 12 * 60 * 60; - uint32_t start = (((uint16_t)pyld[startOff + 4] << 8) | ((uint16_t)pyld[startOff + 5])) + startTimeOffset; - uint32_t end = (((uint16_t)pyld[startOff + 6] << 8) | ((uint16_t)pyld[startOff + 7])) + endTimeOffset; + *start = (((uint16_t)pyld[startOff + 4] << 8) | ((uint16_t)pyld[startOff + 5])) + startTimeOffset; + *endTime = (((uint16_t)pyld[startOff + 6] << 8) | ((uint16_t)pyld[startOff + 7])) + endTimeOffset; - DPRINTLN(DBG_INFO, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(start) + ", end: " + ah::getTimeStr(end)); - return true; + DPRINTLN(DBG_INFO, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(*start) + ", end: " + ah::getTimeStr(*endTime)); + return pyld[startOff+1]; } String getAlarmStr(uint16_t alarmCode) { diff --git a/src/hm/payload.h b/src/hm/payload.h index 093edbd3e..7e66eb764 100644 --- a/src/hm/payload.h +++ b/src/hm/payload.h @@ -8,7 +8,6 @@ #include "../utils/dbg.h" #include "../utils/crc.h" -#include "../utils/handler.h" #include "../config/config.h" #include @@ -29,12 +28,13 @@ typedef struct { typedef std::function payloadListenerType; +typedef std::function alarmListenerType; template -class Payload : public Handler { +class Payload { public: - Payload() : Handler() {} + Payload() {} void setup(IApp *app, HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { mApp = app; @@ -53,10 +53,12 @@ class Payload : public Handler { mSerialDebug = enable; } - void notify(uint8_t val) { - for(typename std::list::iterator it = mList.begin(); it != mList.end(); ++it) { - (*it)(val); - } + void addPayloadListener(payloadListenerType cb) { + mCbPayload = cb; + } + + void addAlarmListener(alarmListenerType cb) { + mCbAlarm = cb; } void loop() { @@ -258,9 +260,13 @@ class Payload : public Handler { if(AlarmData == mPayload[iv->id].txCmd) { uint8_t i = 0; + uint16_t code; + uint32_t start, end; while(1) { - if(!iv->parseAlarmLog(i++, payload, payloadLen)) + code = iv->parseAlarmLog(i++, payload, payloadLen, &start, &end); + if(0 == code) break; + (mCbAlarm)(code, start, end); yield(); } } @@ -279,6 +285,14 @@ class Payload : public Handler { } private: + void notify(uint8_t val) { + (mCbPayload)(val); + } + + void notify(uint16_t code, uint32_t start, uint32_t endTime) { + (mCbAlarm)(code, start, endTime); + } + bool build(uint8_t id, bool *complete) { DPRINTLN(DBG_VERBOSE, F("build")); uint16_t crc = 0xffff, crcRcv = 0x0000; @@ -329,6 +343,9 @@ class Payload : public Handler { invPayload_t mPayload[MAX_NUM_INVERTERS]; bool mSerialDebug; Inverter<> *mHighPrioIv; + + alarmListenerType mCbAlarm; + payloadListenerType mCbPayload; }; #endif /*__PAYLOAD_H_*/ diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 2cd175e4c..11744ab67 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -26,6 +26,13 @@ typedef std::function subscriptionCb; +struct alarm_t { + uint16_t code; + uint32_t start; + uint32_t end; + alarm_t(uint16_t c, uint32_t s, uint32_t e) : code(c), start(s), end(e) {} +}; + template class PubMqtt { public: @@ -148,6 +155,12 @@ class PubMqtt { } } + void alarmEventListener(uint16_t code, uint32_t start, uint32_t endTime) { + if(mClient.connected()) { + mAlarmList.push(alarm_t(code, start, endTime)); + } + } + void publish(const char *subTopic, const char *payload, bool retained = false, bool addTopic = true) { if(!mClient.connected()) return; @@ -436,6 +449,19 @@ class PubMqtt { return totalComplete; } + void sendAlarmData() { + if(mAlarmList.empty()) + return; + Inverter<> *iv = mSys->getInverterByPos(0, false); + while(!mAlarmList.empty()) { + alarm_t alarm = mAlarmList.front(); + publish("alarm", iv->getAlarmStr(alarm.code).c_str()); + publish("alarm_start", String(alarm.start).c_str()); + publish("alarm_end", String(alarm.end).c_str()); + mAlarmList.pop(); + } + } + void sendIvData(bool sendTotals = true) { if(mSendList.empty()) return; @@ -577,6 +603,7 @@ class PubMqtt { uint32_t *mUtcTimestamp; uint32_t mRxCnt, mTxCnt; std::queue mSendList; + std::queue mAlarmList; subscriptionCb mSubscriptionCb; bool mIvAvail; // shows if at least one inverter is available bool mReconnectRequest; diff --git a/src/utils/handler.h b/src/utils/handler.h deleted file mode 100644 index 51d64c0d2..000000000 --- a/src/utils/handler.h +++ /dev/null @@ -1,33 +0,0 @@ -//----------------------------------------------------------------------------- -// 2022 Ahoy, https://ahoydtu.de -// Lukas Pusch, lukas@lpusch.de -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ -//----------------------------------------------------------------------------- - -#ifndef __HANDLER_H__ -#define __HANDLER_H__ - -#include -#include -#include - -template -class Handler { - public: - Handler() {} - - void addListener(TYPE f) { - mList.push_back(f); - } - - /*virtual void notify(void) { - for(typename std::list::iterator it = mList.begin(); it != mList.end(); ++it) { - (*it)(); - } - }*/ - - protected: - std::list mList; -}; - -#endif /*__HANDLER_H__*/ diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 11bf5ae05..6f7725ebf 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -25,7 +25,6 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mStaConn = DISCONNECTED; mCnt = 0; mScanActive = false; - mLastNtpFailed = false; #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); @@ -70,6 +69,7 @@ void ahoywifi::tickWifiLoop() { DBGPRINTLN(F("AP client connected")); welcome(mApIp.toString()); WiFi.mode(WIFI_AP); + mAppWifiCb(true); } return; } @@ -148,25 +148,16 @@ void ahoywifi::setupStation(void) { //----------------------------------------------------------------------------- -bool ahoywifi::getNtpTime() { - if(mLastNtpFailed && (0 != *mUtcTimestamp)) { // time is available, but NTP not maybe it was set by "sync with browser" - mLastNtpFailed = false; - return true; // true is necessary to enable all timers even if NTP was not reachable - } - - if(GOT_IP != mStaConn) { - mLastNtpFailed = true; +bool ahoywifi::getNtpTime(void) { + if(GOT_IP != mStaConn) return false; - } IPAddress timeServer; uint8_t buf[NTP_PACKET_SIZE]; uint8_t retry = 0; - if (WiFi.hostByName(mConfig->ntp.addr, timeServer) != 1) { - mLastNtpFailed = true; + if (WiFi.hostByName(mConfig->ntp.addr, timeServer) != 1) return false; - } mUdp.begin(mConfig->ntp.port); sendNTPpacket(timeServer); @@ -191,7 +182,6 @@ bool ahoywifi::getNtpTime() { } DPRINTLN(DBG_INFO, F("[NTP]: getNtpTime failed")); - mLastNtpFailed = true; return false; } @@ -274,7 +264,6 @@ void ahoywifi::connectionEvent(WiFiStatus_t status) { if(mStaConn != CONNECTING) { mStaConn = DISCONNECTED; mCnt = 5; // try to reconnect in 5 sec - mLastNtpFailed = false; setupWifi(); // reconnect with AP / Station setup mAppWifiCb(false); DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 292c60747..7155a427c 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -25,7 +25,7 @@ class ahoywifi { void setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb); void tickWifiLoop(void); - bool getNtpTime(); + bool getNtpTime(void); void scanAvailNetworks(void); void getAvailNetworks(JsonObject obj); @@ -68,7 +68,10 @@ class ahoywifi { uint8_t mLoopCnt; bool mScanActive; - bool mLastNtpFailed; + + void sortRSSI(int *sort, int n); + void getBSSIDs(void); + std::list mBSSIDList; }; #endif /*__AHOYWIFI_H__*/