mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-22 21:36:11 +02:00
parent
7ceaa7944f
commit
9cedb41ff4
9 changed files with 78 additions and 71 deletions
|
@ -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
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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_*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__*/
|
|
@ -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");
|
||||
|
|
|
@ -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…
Add table
Add a link
Reference in a new issue