Browse Source

0.8.145

* fix NTP related issues #1748 #1752
* fix MqTT discovery total #1715
* upgrade webserver version for ESP32 devices
pull/1759/head
lumapu 4 months ago
parent
commit
2a990978d8
  1. 5
      src/CHANGES.md
  2. 111
      src/app.cpp
  3. 9
      src/app.h
  4. 2
      src/defines.h
  5. 36
      src/network/AhoyNetwork.h
  6. 1
      src/network/AhoyWifiEsp32.h
  7. 1
      src/network/AhoyWifiEsp8266.h
  8. 2
      src/platformio.ini
  9. 24
      src/publisher/pubMqtt.h
  10. 19
      src/utils/scheduler.h

5
src/CHANGES.md

@ -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

111
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();
}
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");
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");
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;
}
//-----------------------------------------------------------------------------

9
src/app.h

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

2
src/defines.h

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

36
src/network/AhoyNetwork.h

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

1
src/network/AhoyWifiEsp32.h

@ -37,6 +37,7 @@ class AhoyWifi : public AhoyNetwork {
}
void tickNetworkLoop() override {
AhoyNetwork::tickNetworkLoop();
if(mAp.isEnabled())
mAp.tickLoop();
}

1
src/network/AhoyWifiEsp8266.h

@ -23,6 +23,7 @@ class AhoyWifi : public AhoyNetwork {
}
void tickNetworkLoop() override {
AhoyNetwork::tickNetworkLoop();
if(mAp.isEnabled())
mAp.tickLoop();

2
src/platformio.ini

@ -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 =

24
src/publisher/pubMqtt.h

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

19
src/utils/scheduler.h

@ -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…
Cancel
Save