mirror of
https://github.com/lumapu/ahoy.git
synced 2025-04-28 17:56:21 +02:00
0.8.145
* fix NTP related issues #1748 #1752 * fix MqTT discovery total #1715 * upgrade webserver version for ESP32 devices
This commit is contained in:
parent
97d978632a
commit
2a990978d8
10 changed files with 111 additions and 97 deletions
|
@ -1,5 +1,10 @@
|
|||
# Development Changes
|
||||
|
||||
## 0.8.145 - 2024-09-22
|
||||
* fix NTP related issues #1748 #1752
|
||||
* fix MqTT discovery total #1715
|
||||
* upgrade webserver version for ESP32 devices
|
||||
|
||||
## 0.8.144 - 2024-09-14
|
||||
* fix NTP lookup if internet connection is not there
|
||||
* added fallback for NTP to gateway IP
|
||||
|
|
109
src/app.cpp
109
src/app.cpp
|
@ -13,7 +13,15 @@
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
app::app() : ah::Scheduler {} {
|
||||
app::app()
|
||||
: ah::Scheduler {}
|
||||
, mSunrise {0}
|
||||
, mSunset {0}
|
||||
, idTickMqttSecond {MAX_NUM_TICKER}
|
||||
, idTickMqttMinute {MAX_NUM_TICKER}
|
||||
, idTickMidnight {MAX_NUM_TICKER}
|
||||
, idTickReboot {MAX_NUM_TICKER}
|
||||
{
|
||||
memset(mVersion, 0, sizeof(char) * 12);
|
||||
memset(mVersionModules, 0, sizeof(char) * 12);
|
||||
}
|
||||
|
@ -51,7 +59,7 @@ void app::setup() {
|
|||
#else
|
||||
mNetwork = static_cast<AhoyNetwork*>(new AhoyWifi());
|
||||
#endif
|
||||
mNetwork->setup(mConfig, &mTimestamp, [this](bool gotIp) { this->onNetwork(gotIp); }, [this](bool gotTime) { this->onNtpUpdate(gotTime); });
|
||||
mNetwork->setup(mConfig, [this](bool gotIp) { this->onNetwork(gotIp); }, [this](uint32_t gotTime) { this->onNtpUpdate(gotTime); });
|
||||
mNetwork->begin();
|
||||
|
||||
esp_task_wdt_reset();
|
||||
|
@ -151,15 +159,19 @@ void app::loop(void) {
|
|||
void app::onNetwork(bool gotIp) {
|
||||
mNetworkConnected = gotIp;
|
||||
if(gotIp) {
|
||||
ah::Scheduler::resetTicker();
|
||||
regularTickers(); //reinstall regular tickers
|
||||
mNetwork->updateNtpTime();
|
||||
if(!mConfig->inst.startWithoutTime) // already set in regularTickers
|
||||
every(std::bind(&app::tickSend, this), mConfig->inst.sendInterval, "tSend");
|
||||
mTickerInstallOnce = true;
|
||||
mSunrise = 0; // needs to be set to 0, to reinstall sunrise and ivComm tickers!
|
||||
|
||||
uint32_t nextTrig = (mTimestamp < 0x1337) ? 0 : (mConfig->ntp.interval * 60);
|
||||
once(std::bind(&app::tickNtpUpdate, this), nextTrig, "ntp");
|
||||
#if defined(ENABLE_MQTT)
|
||||
if (mMqttEnabled) {
|
||||
if(MAX_NUM_TICKER == idTickMqttSecond)
|
||||
idTickMqttSecond = everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS");
|
||||
|
||||
if(MAX_NUM_TICKER == idTickMqttMinute)
|
||||
idTickMqttMinute = everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt), "mqttM");
|
||||
}
|
||||
#endif /*ENABLE_MQTT*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,9 +182,15 @@ void app::regularTickers(void) {
|
|||
everySec([this]() { mProtection->tickSecond(); }, "prot");
|
||||
everySec([this]() {mNetwork->tickNetworkLoop(); }, "net");
|
||||
|
||||
if(mConfig->inst.startWithoutTime && !mNetworkConnected)
|
||||
if(mConfig->inst.startWithoutTime)
|
||||
every(std::bind(&app::tickSend, this), mConfig->inst.sendInterval, "tSend");
|
||||
|
||||
|
||||
every([this]() { mNetwork->updateNtpTime(); }, mConfig->ntp.interval * 60, "ntp");
|
||||
|
||||
if (mConfig->inst.rstValsNotAvail)
|
||||
everyMin(std::bind(&app::tickMinute, this), "tMin");
|
||||
|
||||
// Plugins
|
||||
#if defined(PLUGIN_DISPLAY)
|
||||
if (DISP_TYPE_T0_NONE != mConfig->plugin.display.type)
|
||||
|
@ -191,62 +209,32 @@ void app::regularTickers(void) {
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void app::onNtpUpdate(bool gotTime) {
|
||||
mNtpReceived = true;
|
||||
if ((0 == mSunrise) && (0.0 != mConfig->sun.lat) && (0.0 != mConfig->sun.lon)) {
|
||||
mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600;
|
||||
tickCalcSunrise();
|
||||
}
|
||||
void app::onNtpUpdate(uint32_t utcTimestamp) {
|
||||
if(0 == utcTimestamp) {
|
||||
// try again in 5s
|
||||
once([this]() { mNetwork->updateNtpTime(); }, 5, "ntp");
|
||||
} else {
|
||||
mTimestamp = utcTimestamp;
|
||||
DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(mTimestamp) + " UTC");
|
||||
|
||||
if (mTickerInstallOnce) {
|
||||
mTickerInstallOnce = false;
|
||||
#if defined(ENABLE_MQTT)
|
||||
if (mMqttEnabled) {
|
||||
mMqtt.tickerSecond();
|
||||
everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS");
|
||||
everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt), "mqttM");
|
||||
uint32_t localTime = gTimezone.toLocal(mTimestamp);
|
||||
uint32_t midTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time
|
||||
resetById(idTickMidnight);
|
||||
idTickMidnight = onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi");
|
||||
|
||||
if (mConfig->sys.schedReboot) {
|
||||
resetById(idTickReboot);
|
||||
uint32_t rebootTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86410); // reboot 10 secs after midnght
|
||||
idTickReboot = onceAt(std::bind(&app::tickReboot, this), rebootTrig, "midRe");
|
||||
}
|
||||
#endif /*ENABLE_MQTT*/
|
||||
|
||||
if (mConfig->inst.rstValsNotAvail)
|
||||
everyMin(std::bind(&app::tickMinute, this), "tMin");
|
||||
|
||||
if(mNtpReceived) {
|
||||
uint32_t localTime = gTimezone.toLocal(mTimestamp);
|
||||
uint32_t midTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time
|
||||
onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi");
|
||||
|
||||
if (mConfig->sys.schedReboot) {
|
||||
uint32_t rebootTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86410); // reboot 10 secs after midnght
|
||||
onceAt(std::bind(&app::tickReboot, this), rebootTrig, "midRe");
|
||||
}
|
||||
if ((0 == mSunrise) && (0.0 != mConfig->sun.lat) && (0.0 != mConfig->sun.lon)) {
|
||||
mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600;
|
||||
tickCalcSunrise();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void app::updateNtp(void) {
|
||||
if(mNtpReceived)
|
||||
onNtpUpdate(true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void app::tickNtpUpdate(void) {
|
||||
uint32_t nxtTrig = 5; // default: check again in 5 sec
|
||||
|
||||
if (!mNtpReceived)
|
||||
mNetwork->updateNtpTime();
|
||||
else {
|
||||
nxtTrig = mConfig->ntp.interval * 60; // check again in configured interval
|
||||
mNtpReceived = false;
|
||||
}
|
||||
yield();
|
||||
|
||||
updateNtp();
|
||||
|
||||
once(std::bind(&app::tickNtpUpdate, this), nxtTrig, "ntp");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void app::tickCalcSunrise(void) {
|
||||
if (mSunrise == 0) // on boot/reboot calc sun values for current time
|
||||
|
@ -528,9 +516,6 @@ void app::resetSystem(void) {
|
|||
|
||||
mAllIvNotAvail = true;
|
||||
|
||||
mSunrise = 0;
|
||||
mSunset = 0;
|
||||
|
||||
mMqttEnabled = false;
|
||||
|
||||
mSendLastIvId = 0;
|
||||
|
@ -539,8 +524,6 @@ void app::resetSystem(void) {
|
|||
mSaveReboot = false;
|
||||
|
||||
mNetworkConnected = false;
|
||||
mNtpReceived = false;
|
||||
mTickerInstallOnce = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -407,10 +407,7 @@ class app : public IApp, public ah::Scheduler {
|
|||
setRebootFlag();
|
||||
}
|
||||
|
||||
void tickNtpUpdate(void);
|
||||
void onNtpUpdate(bool gotTime);
|
||||
bool mNtpReceived = false;
|
||||
void updateNtp(void);
|
||||
void onNtpUpdate(uint32_t utcTimestamp);
|
||||
|
||||
void triggerTickSend(uint8_t id) override {
|
||||
once([this, id]() {
|
||||
|
@ -465,9 +462,11 @@ class app : public IApp, public ah::Scheduler {
|
|||
#if defined(ENABLE_MQTT)
|
||||
PubMqttType mMqtt;
|
||||
#endif
|
||||
bool mTickerInstallOnce = false;
|
||||
bool mMqttEnabled = false;
|
||||
|
||||
uint8_t idTickMqttSecond, idTickMqttMinute;
|
||||
uint8_t idTickMidnight, idTickReboot;
|
||||
|
||||
// sun
|
||||
int32_t mCalculatedTimezoneOffset = 0;
|
||||
uint32_t mSunrise = 0, mSunset = 0;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
//-------------------------------------
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 8
|
||||
#define VERSION_PATCH 144
|
||||
#define VERSION_PATCH 145
|
||||
//-------------------------------------
|
||||
typedef struct {
|
||||
uint8_t ch;
|
||||
|
|
|
@ -17,12 +17,11 @@
|
|||
class AhoyNetwork {
|
||||
public:
|
||||
typedef std::function<void(bool)> OnNetworkCB;
|
||||
typedef std::function<void(bool)> OnTimeCB;
|
||||
typedef std::function<void(uint32_t utcTimestamp)> OnTimeCB;
|
||||
|
||||
public:
|
||||
void setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNetworkCB, OnTimeCB onTimeCB) {
|
||||
void setup(settings_t *config, OnNetworkCB onNetworkCB, OnTimeCB onTimeCB) {
|
||||
mConfig = config;
|
||||
mUtcTimestamp = utcTimestamp;
|
||||
mOnNetworkCB = onNetworkCB;
|
||||
mOnTimeCB = onTimeCB;
|
||||
|
||||
|
@ -53,6 +52,19 @@ class AhoyNetwork {
|
|||
#endif
|
||||
}
|
||||
|
||||
virtual void tickNetworkLoop() {
|
||||
if(mDnsCallbackReady) {
|
||||
mDnsCallbackReady = false;
|
||||
startNtpUpdate();
|
||||
}
|
||||
|
||||
if(mNtpTimeoutSec) {
|
||||
mNtpTimeoutSec--;
|
||||
if(!mNtpTimeoutSec)
|
||||
mOnTimeCB(0); // timeout
|
||||
}
|
||||
}
|
||||
|
||||
bool isConnected() const {
|
||||
return ((mStatus == NetworkState::CONNECTED) || (mStatus == NetworkState::GOT_IP));
|
||||
}
|
||||
|
@ -66,6 +78,7 @@ class AhoyNetwork {
|
|||
obj->mNtpIp = ipaddr->addr;
|
||||
#endif
|
||||
}
|
||||
obj->mDnsCallbackReady = true;
|
||||
}
|
||||
|
||||
void updateNtpTime() {
|
||||
|
@ -74,6 +87,8 @@ class AhoyNetwork {
|
|||
return;
|
||||
}
|
||||
|
||||
mNtpTimeoutSec = 30;
|
||||
|
||||
ip_addr_t ipaddr;
|
||||
mNtpIp = WiFi.gatewayIP();
|
||||
// dns_gethostbyname runs asynchronous and sets the member mNtpIp which is then checked on
|
||||
|
@ -94,8 +109,10 @@ class AhoyNetwork {
|
|||
void startNtpUpdate() {
|
||||
DPRINTLN(DBG_INFO, F("get time from: ") + mNtpIp.toString());
|
||||
if (!mUdp.connected()) {
|
||||
if (!mUdp.connect(mNtpIp, mConfig->ntp.port))
|
||||
if (!mUdp.connect(mNtpIp, mConfig->ntp.port)) {
|
||||
mOnTimeCB(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mUdp.onPacket([this](AsyncUDPPacket packet) {
|
||||
|
@ -109,7 +126,6 @@ class AhoyNetwork {
|
|||
|
||||
public:
|
||||
virtual void begin() = 0;
|
||||
virtual void tickNetworkLoop() = 0;
|
||||
virtual String getIp(void) = 0;
|
||||
virtual String getMac(void) = 0;
|
||||
|
||||
|
@ -242,10 +258,9 @@ class AhoyNetwork {
|
|||
// this is NTP time (seconds since Jan 1 1900):
|
||||
unsigned long secsSince1900 = highWord << 16 | lowWord;
|
||||
|
||||
*mUtcTimestamp = secsSince1900 - 2208988800UL; // UTC time
|
||||
DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(*mUtcTimestamp) + " UTC");
|
||||
mOnTimeCB(true);
|
||||
mUdp.close();
|
||||
mNtpTimeoutSec = 0; // clear timeout
|
||||
mOnTimeCB(secsSince1900 - 2208988800UL);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -257,12 +272,15 @@ class AhoyNetwork {
|
|||
CONNECTING // ESP8266
|
||||
};
|
||||
|
||||
public:
|
||||
bool mDnsCallbackReady = false;
|
||||
|
||||
protected:
|
||||
settings_t *mConfig = nullptr;
|
||||
uint32_t *mUtcTimestamp = nullptr;
|
||||
bool mConnected = false;
|
||||
bool mScanActive = false;
|
||||
bool mWifiConnecting = false;
|
||||
uint8_t mNtpTimeoutSec = 0;
|
||||
|
||||
OnNetworkCB mOnNetworkCB;
|
||||
OnTimeCB mOnTimeCB;
|
||||
|
|
|
@ -37,6 +37,7 @@ class AhoyWifi : public AhoyNetwork {
|
|||
}
|
||||
|
||||
void tickNetworkLoop() override {
|
||||
AhoyNetwork::tickNetworkLoop();
|
||||
if(mAp.isEnabled())
|
||||
mAp.tickLoop();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ class AhoyWifi : public AhoyNetwork {
|
|||
}
|
||||
|
||||
void tickNetworkLoop() override {
|
||||
AhoyNetwork::tickNetworkLoop();
|
||||
if(mAp.isEnabled())
|
||||
mAp.tickLoop();
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ platform = espressif32@6.7.0
|
|||
board = lolin_d32
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
https://github.com/mathieucarbou/ESPAsyncWebServer @ ^3.1.5
|
||||
https://github.com/mathieucarbou/ESPAsyncWebServer @ ^3.3.1
|
||||
build_flags = ${env.build_flags}
|
||||
-DSPI_HAL
|
||||
monitor_filters =
|
||||
|
|
|
@ -409,20 +409,19 @@ class PubMqtt {
|
|||
bool total = (mDiscovery.lastIvId == MAX_NUM_INVERTERS);
|
||||
|
||||
Inverter<> *iv = mSys->getInverterByPos(mDiscovery.lastIvId);
|
||||
record_t<> *rec = NULL;
|
||||
if (NULL != iv) {
|
||||
record_t<> *rec = nullptr;
|
||||
if (nullptr != iv) {
|
||||
rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||
if(0 == mDiscovery.sub)
|
||||
mDiscovery.foundIvCnt++;
|
||||
mDiscovery.foundIvCnt++;
|
||||
}
|
||||
|
||||
if ((NULL != iv) || total) {
|
||||
if ((nullptr != iv) || total) {
|
||||
if (!total) {
|
||||
doc[F("name")] = iv->config->name;
|
||||
doc[F("ids")] = String(iv->config->serial.u64, HEX);
|
||||
doc[F("mdl")] = iv->config->name;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
doc[F("name")] = node_id;
|
||||
doc[F("ids")] = node_id;
|
||||
doc[F("mdl")] = node_id;
|
||||
|
@ -441,6 +440,7 @@ class PubMqtt {
|
|||
uniq_id.fill(0);
|
||||
buf.fill(0);
|
||||
const char *devCls, *stateCls;
|
||||
|
||||
if (!total) {
|
||||
if (rec->assign[mDiscovery.sub].ch == CH0)
|
||||
snprintf(name.data(), name.size(), "%s", iv->getFieldName(mDiscovery.sub, rec));
|
||||
|
@ -468,20 +468,26 @@ class PubMqtt {
|
|||
doc2[F("unit_of_meas")] = ((!total) ? (iv->getUnit(mDiscovery.sub, rec)) : (unitTotal[mDiscovery.sub]));
|
||||
doc2[F("uniq_id")] = ((!total) ? (String(iv->config->serial.u64, HEX)) : (node_id)) + "_" + uniq_id.data();
|
||||
doc2[F("dev")] = deviceObj;
|
||||
|
||||
if (!(String(stateCls) == String("total_increasing")))
|
||||
doc2[F("exp_aft")] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!?
|
||||
if (devCls != NULL)
|
||||
if (devCls != nullptr)
|
||||
doc2[F("dev_cla")] = String(devCls);
|
||||
if (stateCls != NULL)
|
||||
if (stateCls != nullptr)
|
||||
doc2[F("stat_cla")] = String(stateCls);
|
||||
|
||||
if (!total)
|
||||
snprintf(topic.data(), topic.size(), "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
|
||||
else // total values
|
||||
snprintf(topic.data(), topic.size(), "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(), fields[fldTotal[mDiscovery.sub]]);
|
||||
|
||||
size_t size = measureJson(doc2) + 1;
|
||||
serializeJson(doc2, buf.data(), size);
|
||||
if(FLD_EVT != rec->assign[mDiscovery.sub].fieldId)
|
||||
|
||||
if(nullptr != rec) {
|
||||
if(FLD_EVT != rec->assign[mDiscovery.sub].fieldId)
|
||||
publish(topic.data(), buf.data(), true, false);
|
||||
} else if(total)
|
||||
publish(topic.data(), buf.data(), true, false);
|
||||
|
||||
if(++mDiscovery.sub == ((!total) ? (rec->length) : 4)) {
|
||||
|
|
|
@ -73,21 +73,22 @@ namespace ah {
|
|||
|
||||
}
|
||||
|
||||
void once(scdCb c, uint32_t timeout, const char *name) { addTicker(c, timeout, 0, false, name); }
|
||||
void onceAt(scdCb c, uint32_t timestamp, const char *name) { addTicker(c, timestamp, 0, true, name); }
|
||||
uint8_t every(scdCb c, uint32_t interval, const char *name){ return addTicker(c, interval, interval, false, name); }
|
||||
uint8_t once(scdCb c, uint32_t timeout, const char *name) { return addTicker(c, timeout, 0, false, name); }
|
||||
uint8_t onceAt(scdCb c, uint32_t timestamp, const char *name) { return addTicker(c, timestamp, 0, true, name); }
|
||||
uint8_t every(scdCb c, uint32_t interval, const char *name) { return addTicker(c, interval, interval, false, name); }
|
||||
|
||||
void everySec(scdCb c, const char *name) { every(c, SCD_SEC, name); }
|
||||
void everyMin(scdCb c, const char *name) { every(c, SCD_MIN, name); }
|
||||
void everyHour(scdCb c, const char *name) { every(c, SCD_HOUR, name); }
|
||||
void every12h(scdCb c, const char *name) { every(c, SCD_12H, name); }
|
||||
void everyDay(scdCb c, const char *name) { every(c, SCD_DAY, name); }
|
||||
uint8_t everySec(scdCb c, const char *name) { return every(c, SCD_SEC, name); }
|
||||
uint8_t everyMin(scdCb c, const char *name) { return every(c, SCD_MIN, name); }
|
||||
uint8_t everyHour(scdCb c, const char *name) { return every(c, SCD_HOUR, name); }
|
||||
uint8_t every12h(scdCb c, const char *name) { return every(c, SCD_12H, name); }
|
||||
uint8_t everyDay(scdCb c, const char *name) { return every(c, SCD_DAY, name); }
|
||||
|
||||
virtual void setTimestamp(uint32_t ts) {
|
||||
mTimestamp = ts;
|
||||
}
|
||||
|
||||
bool resetEveryById(uint8_t id) {
|
||||
bool resetById(uint8_t id) {
|
||||
id = (id % (MAX_NUM_TICKER - 1));
|
||||
if (mTickerInUse[id] == false)
|
||||
return false;
|
||||
mTicker[id].timeout = mTicker[id].reload;
|
||||
|
|
Loading…
Add table
Reference in a new issue