Browse Source

implemented `getNTPTime` improvements #609 partially #611

added alarm messages to MQTT #177, #600, #608
pull/635/head
lumapu 2 years ago
parent
commit
9cedb41ff4
  1. 2
      src/CHANGES.md
  2. 10
      src/app.cpp
  3. 5
      src/app.h
  4. 13
      src/hm/hmInverter.h
  5. 33
      src/hm/payload.h
  6. 27
      src/publisher/pubMqtt.h
  7. 33
      src/utils/handler.h
  8. 19
      src/wifi/ahoywifi.cpp
  9. 7
      src/wifi/ahoywifi.h

2
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

10
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;

5
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);

13
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) {

33
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 <Arduino.h>
@ -29,12 +28,13 @@ typedef struct {
typedef std::function<void(uint8_t)> payloadListenerType;
typedef std::function<void(uint16_t alarmCode, uint32_t start, uint32_t end)> alarmListenerType;
template<class HMSYSTEM>
class Payload : public Handler<payloadListenerType> {
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<payloadListenerType> {
mSerialDebug = enable;
}
void notify(uint8_t val) {
for(typename std::list<payloadListenerType>::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<payloadListenerType> {
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<payloadListenerType> {
}
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<payloadListenerType> {
invPayload_t mPayload[MAX_NUM_INVERTERS];
bool mSerialDebug;
Inverter<> *mHighPrioIv;
alarmListenerType mCbAlarm;
payloadListenerType mCbPayload;
};
#endif /*__PAYLOAD_H_*/

27
src/publisher/pubMqtt.h

@ -26,6 +26,13 @@
typedef std::function<void(JsonObject)> 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 HMSYSTEM>
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<uint8_t> mSendList;
std::queue<alarm_t> mAlarmList;
subscriptionCb mSubscriptionCb;
bool mIvAvail; // shows if at least one inverter is available
bool mReconnectRequest;

33
src/utils/handler.h

@ -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 <memory>
#include <functional>
#include <list>
template<class TYPE>
class Handler {
public:
Handler() {}
void addListener(TYPE f) {
mList.push_back(f);
}
/*virtual void notify(void) {
for(typename std::list<TYPE>::iterator it = mList.begin(); it != mList.end(); ++it) {
(*it)();
}
}*/
protected:
std::list<TYPE> mList;
};
#endif /*__HANDLER_H__*/

19
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");

7
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<uint8_t> mBSSIDList;
};
#endif /*__AHOYWIFI_H__*/

Loading…
Cancel
Save