From d9290d9fdf1c666b92214aa97afbb3ee23286cc1 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 8 Dec 2022 17:44:34 +0100 Subject: [PATCH] fix #480 AP Mode on fresh ESP included #483 improvements fix #468 last_success MQTT fix #468 update available status at sunset fix #447 reorderd enqueue commands to not have same payload length in a row added ssd1306 and nokia display to build script --- .github/workflows/compile_development.yml | 2 +- .github/workflows/compile_esp8266.yml | 2 +- src/app.cpp | 53 ++--- src/app.h | 2 +- src/config/settings.h | 8 +- src/defines.h | 2 +- src/hm/hmInverter.h | 9 +- src/main.cpp | 2 +- src/publisher/pubMqtt.h | 3 +- src/publisher/pubSerial.h | 37 ++-- src/utils/llist.h | 108 ++++++++++ src/utils/scheduler.h | 238 ++++++++++------------ src/utils/sun.h | 2 +- src/web/html/index.html | 14 +- src/wifi/ahoywifi.cpp | 9 +- 15 files changed, 285 insertions(+), 206 deletions(-) create mode 100644 src/utils/llist.h diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index ec435880..8188e6d1 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -47,7 +47,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release + run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release - name: Rename Binary files id: rename-binary-files diff --git a/.github/workflows/compile_esp8266.yml b/.github/workflows/compile_esp8266.yml index cf61b1f9..ab902f74 100644 --- a/.github/workflows/compile_esp8266.yml +++ b/.github/workflows/compile_esp8266.yml @@ -49,7 +49,7 @@ jobs: working-directory: src/web/html run: python convert.py - name: Run PlatformIO - run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release + run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release - name: Rename Binary files id: rename-binary-files diff --git a/src/app.cpp b/src/app.cpp index 81a75980..7b7c6e0e 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -19,24 +19,29 @@ app::app() : ah::Scheduler() { //----------------------------------------------------------------------------- -void app::setup(uint32_t timeout) { +void app::setup() { Serial.begin(115200); while (!Serial) yield(); + ah::Scheduler::setup(); + resetSystem(); mSettings.setup(); mSettings.getPtr(mConfig); DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false"))); - addListener(EVERY_SEC, std::bind(&app::tickSecond, this)); - addListener(EVERY_MIN, std::bind(&app::tickMinute, this)); - addListener(EVERY_12H, std::bind(&app::tickNtpUpdate, this)); - once(mConfig->nrf.sendInterval, std::bind(&app::tickSend, this), "tickSend"); - if((mConfig->sun.lat) && (mConfig->sun.lon)) { - once(5, std::bind(&app::tickCalcSunrise, this)); - mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; - } + + everySec(std::bind(&app::tickSecond, this)); + everyMin(std::bind(&app::tickMinute, this)); + every12h(std::bind(&app::tickNtpUpdate, this)); + every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval); + #if !defined(AP_ONLY) + if((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; + once(std::bind(&app::tickCalcSunrise, this), 5); + } + #endif mSys = new HmSystemType(); mSys->enableDebug(); @@ -54,10 +59,9 @@ void app::setup(uint32_t timeout) { #if !defined(AP_ONLY) if (mConfig->mqtt.broker[0] > 0) { mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1)); - addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt)); - addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt)); + everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt)); + everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt)); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); - } #endif setupLed(); @@ -65,16 +69,17 @@ void app::setup(uint32_t timeout) { mWeb = new web(this, mConfig, &mStat, mVersion); mWeb->setup(); mWeb->setProtection(strlen(mConfig->sys.adminPwd) != 0); - addListener(EVERY_SEC, std::bind(&web::tickSecond, mWeb)); + everySec(std::bind(&web::tickSecond, mWeb)); // Plugins #if defined(ENA_NOKIA) || defined(ENA_SSD1306) mMonoDisplay.setup(mSys, &mTimestamp); mPayload.addListener(std::bind(&MonoDisplayType::payloadEventListener, &mMonoDisplay, std::placeholders::_1)); - addListener(EVERY_SEC, std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay)); + everySec(std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay)); #endif - //addListener(EVERY_MIN, std::bind(&PubSerialType::tickerMinute, &mPubSerial)); + mPubSerial.setup(mConfig, mSys, &mTimestamp); + every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval); } //----------------------------------------------------------------------------- @@ -129,27 +134,26 @@ void app::loop(void) { //----------------------------------------------------------------------------- void app::tickCalcSunrise(void) { if (0 == mTimestamp) { - once(5, std::bind(&app::tickCalcSunrise, this)); // check again in 5 secs + once(std::bind(&app::tickCalcSunrise, this), 5); // check again in 5 secs return; } ah::calculateSunriseSunset(mTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset); uint32_t nxtTrig = mTimestamp - (mTimestamp % 86400) + 86400; // next midnight - onceAt(nxtTrig, std::bind(&app::tickCalcSunrise, this), "calc sunrise"); - onceAt(mSunrise, std::bind(&app::tickSend, this), "tickSend"); // register next event + onceAt(std::bind(&app::tickCalcSunrise, this), nxtTrig); if (mConfig->mqtt.broker[0] > 0) { - once(1, std::bind(&PubMqttType::tickerSun, &mMqtt), "MQTT-tickerSun"); - onceAt(mSunset, std::bind(&PubMqttType::tickSunset, &mMqtt)); + once(std::bind(&PubMqttType::tickerSun, &mMqtt), 1); + onceAt(std::bind(&PubMqttType::tickSunset, &mMqtt), mSunset); } } //----------------------------------------------------------------------------- void app::tickSend(void) { + if(!mSys->Radio.isChipConnected()) { + DPRINTLN(DBG_WARN, "NRF24 not connected!"); + return; + } if ((mTimestamp > 0) && (!mConfig->sun.disNightCom || (mTimestamp >= mSunrise && mTimestamp <= mSunset))) { // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set) - once(mConfig->nrf.sendInterval, std::bind(&app::tickSend, this), "tickSend"); // register next event - if (mConfig->serial.debug) - DPRINTLN(DBG_DEBUG, F("Free heap: 0x") + String(ESP.getFreeHeap(), HEX)); - if (!mSys->BufCtrl.empty()) { if (mConfig->serial.debug) DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->BufCtrl.getFill())); @@ -206,7 +210,6 @@ void app::tickSend(void) { } } } else { - once(3600, std::bind(&app::tickSend, this), "tickSend"); // register next event (one hour) if (mConfig->serial.debug) DPRINTLN(DBG_WARN, F("Time not set or it is night time, therefore no communication to the inverter!")); } diff --git a/src/app.h b/src/app.h index 08c2e3fe..e494cf91 100644 --- a/src/app.h +++ b/src/app.h @@ -52,7 +52,7 @@ class app : public ah::Scheduler { app(); ~app() {} - void setup(uint32_t timeout); + void setup(void); void loop(void); void handleIntr(void); void cbMqtt(char* topic, byte* payload, unsigned int length); diff --git a/src/config/settings.h b/src/config/settings.h index 1895cd12..01d2b8c1 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -98,6 +98,7 @@ typedef struct { cfgMqtt_t mqtt; cfgLed_t led; cfgInst_t inst; + bool valid; } settings_t; class settings { @@ -107,7 +108,7 @@ class settings { void setup() { DPRINTLN(DBG_INFO, F("Initializing FS ..")); - mValid = false; + mCfg.valid = false; #if !defined(ESP32) LittleFSConfig cfg; cfg.setAutoFormat(false); @@ -145,7 +146,7 @@ class settings { } bool getValid(void) { - return mValid; + return mCfg.valid; } void getInfo(uint32_t *used, uint32_t *size) { @@ -173,7 +174,7 @@ class settings { DynamicJsonDocument root(4096); DeserializationError err = deserializeJson(root, fp); if(!err) { - mValid = true; + mCfg.valid = true; jsonWifi(root["wifi"]); jsonNrf(root["nrf"]); jsonNtp(root["ntp"]); @@ -409,7 +410,6 @@ class settings { } settings_t mCfg; - bool mValid; }; #endif /*__SETTINGS_H__*/ diff --git a/src/defines.h b/src/defines.h index d2f9b98f..d0c7a85f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 48 +#define VERSION_PATCH 49 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index f38a36cb..2494a979 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -160,17 +160,12 @@ class Inverter { } uint8_t getQueuedCmd() { - if (_commandQueue.empty()){ - // Fill with default commands - enqueCommand(RealTimeRunData_Debug); + if (_commandQueue.empty()) { if (fwVersion == 0) - { // info needed maybe after "one night" (=> DC>0 to DC=0 and to DC>0) or reboot enqueCommand(InverterDevInform_All); - } + enqueCommand(RealTimeRunData_Debug); if (actPowerLimit == 0xffff) - { // info needed maybe after "one nigth" (=> DC>0 to DC=0 and to DC>0) or reboot enqueCommand(SystemConfigPara); - } } return _commandQueue.front().get()->getCmd(); } diff --git a/src/main.cpp b/src/main.cpp index ea708282..c585d0f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,7 @@ IRAM_ATTR void handleIntr(void) { //----------------------------------------------------------------------------- void setup() { - myApp.setup(WIFI_TRY_CONNECT_TIME); + myApp.setup(); // TODO: move to HmRadio attachInterrupt(digitalPinToInterrupt(myApp.getIrqPin()), handleIntr, FALLING); diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index e1dc1acd..dbea4957 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -95,6 +95,7 @@ class PubMqtt { } void tickSunset() { + printf("tickSunset\n"); char topic[MAX_NAME_LENGTH + 15], val[32]; for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); @@ -387,7 +388,7 @@ class PubMqtt { publish(topic, val, true); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name); - snprintf(val, 40, "%i", iv->getLastTs(rec) * 1000); + snprintf(val, 40, "%d", iv->getLastTs(rec)); publish(topic, val, true); } diff --git a/src/publisher/pubSerial.h b/src/publisher/pubSerial.h index ef4fb88f..d1cc55aa 100644 --- a/src/publisher/pubSerial.h +++ b/src/publisher/pubSerial.h @@ -21,28 +21,24 @@ class PubSerial { mUtcTimestamp = utcTs; } - void tickerMinute() { - DPRINTLN(DBG_INFO, "tickerMinute"); - if(++mTick >= mCfg->serial.interval) { - mTick = 0; - if (mCfg->serial.showIv) { - char topic[30], val[10]; - for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL != iv) { - record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - if (iv->isAvailable(*mUtcTimestamp, rec)) { - DPRINTLN(DBG_INFO, F("Inverter: ") + String(id)); - for (uint8_t i = 0; i < rec->length; i++) { - if (0.0f != iv->getValue(i, rec)) { - snprintf(topic, 30, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec)); - snprintf(val, 10, "%.3f %s", iv->getValue(i, rec), iv->getUnit(i, rec)); - DPRINTLN(DBG_INFO, String(topic) + ": " + String(val)); - } - yield(); + void tick(void) { + if (mCfg->serial.showIv) { + char topic[32 + MAX_NAME_LENGTH], val[40]; + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + if (iv->isAvailable(*mUtcTimestamp, rec)) { + DPRINTLN(DBG_INFO, F("Inverter: ") + String(id)); + for (uint8_t i = 0; i < rec->length; i++) { + if (0.0f != iv->getValue(i, rec)) { + snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec)); + snprintf(val, 40, "%.3f %s", iv->getValue(i, rec), iv->getUnit(i, rec)); + DPRINTLN(DBG_INFO, String(topic) + ": " + String(val)); } - DPRINTLN(DBG_INFO, ""); + yield(); } + DPRINTLN(DBG_INFO, ""); } } } @@ -52,7 +48,6 @@ class PubSerial { private: settings_t *mCfg; HMSYSTEM *mSys; - uint8_t mTick; uint32_t *mUtcTimestamp; }; diff --git a/src/utils/llist.h b/src/utils/llist.h new file mode 100644 index 00000000..dd139c86 --- /dev/null +++ b/src/utils/llist.h @@ -0,0 +1,108 @@ +//----------------------------------------------------------------------------- +// 2022 Ahoy, https://ahoydtu.de +// Lukas Pusch, lukas@lpusch.de +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- +#ifndef __LIST_H__ +#define __LIST_H__ + +template +struct node_s { + typedef T dT; + node_s *pre; + node_s *nxt; + uint32_t id; + dT d; + node_s() : pre(NULL), nxt(NULL), d() {} + node_s(Args... args) : id(0), pre(NULL), nxt(NULL), d(args...) {} +}; + +template +class llist { + typedef node_s elmType; + typedef T dataType; + public: + llist() : root(mPool) { + root = NULL; + elmType *p = mPool; + for(uint32_t i = 0; i < MAX_NUM; i++) { + p->id = i; + p++; + } + mFill = mMax = 0; + } + + elmType *add(Args... args) { + elmType *p = root, *t; + if(NULL == (t = getFreeNode())) + return NULL; + if(++mFill > mMax) + mMax = mFill; + + if(NULL == root) { + p = root = t; + p->pre = p; + p->nxt = p; + } + else { + p = root->pre; + t->pre = p; + p->nxt->pre = t; + t->nxt = p->nxt; + p->nxt = t; + } + t->d = dataType(args...); + return p; + } + + elmType *getFront() { + return root; + } + + elmType *get(elmType *p) { + p = p->nxt; + return (p == root) ? NULL : p; + } + + elmType *rem(elmType *p) { + if(NULL == p) + return NULL; + elmType *t = p->nxt; + p->nxt->pre = p->pre; + p->pre->nxt = p->nxt; + if(root == p) + root = NULL; + p->nxt = NULL; + p->pre = NULL; + p = NULL; + mFill--; + return (NULL == root) ? NULL : ((t == root) ? NULL : t); + } + + uint16_t getFill(void) { + return mFill; + } + + uint16_t getMaxFill(void) { + return mMax; + } + + protected: + elmType *root; + + private: + elmType *getFreeNode(void) { + elmType *n = mPool; + for(uint32_t i = 0; i < MAX_NUM; i++) { + if(NULL == n->nxt) + return n; + n++; + } + return NULL; + } + + elmType mPool[MAX_NUM]; + uint16_t mFill, mMax; +}; + +#endif /*__LIST_H__*/ diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h index 25702ce3..5e7848b1 100644 --- a/src/utils/scheduler.h +++ b/src/utils/scheduler.h @@ -7,152 +7,132 @@ #ifndef __SCHEDULER_H__ #define __SCHEDULER_H__ -#include #include -#include - -enum {EVERY_SEC = 1, EVERY_MIN, EVERY_HR, EVERY_12H, EVERY_DAY}; -typedef std::function SchedulerCb; - -struct once_t { - uint32_t n; - SchedulerCb f; - once_t(uint32_t a, SchedulerCb b) : n(a), f(b) {} - once_t() : n(0), f(NULL) {} -}; +#include "llist.h" +#include "dbg.h" namespace ah { -class Scheduler { - public: - Scheduler() {} - - void setup() { - mPrevMillis = 0; - mSeconds = 0; - mMinutes = 0; - mHours = 0; - mUptime = 0; - mTimestamp = 0; - } - - void loop() { - if (millis() - mPrevMillis >= 1000) { - mPrevMillis += 1000; - mUptime++; - if(0 != mTimestamp) - mTimestamp++; - notify(&mListSecond); - onceFuncTick(); - if(++mSeconds >= 60) { - mSeconds = 0; - notify(&mListMinute); - onceAtFuncTick(); - if(++mMinutes >= 60) { - mMinutes = 0; - notify(&mListHour); - if(++mHours >= 24) { - mHours = 0; - notify(&mListDay); - notify(&mList12h); - } - else if(mHours == 12) - notify(&mList12h); - } - } + typedef std::function scdCb; + + enum {SCD_SEC = 1, SCD_MIN = 60, SCD_HOUR = 3600, SCD_12H = 43200, SCD_DAY = 86400}; + + struct scdEvry_s { + scdCb c; + uint32_t timeout; + uint32_t reload; + scdEvry_s() : c(NULL), timeout(0), reload(0) {} + scdEvry_s(scdCb a, uint32_t tmt, uint32_t rl) : c(a), timeout(tmt), reload(rl) {} + }; + + struct scdAt_s { + scdCb c; + uint32_t timestamp; + scdAt_s() : c(NULL), timestamp(0) {} + scdAt_s(scdCb a, uint32_t ts) : c(a), timestamp(ts) {} + }; + + + typedef node_s sP; + typedef node_s sPAt; + class Scheduler { + public: + Scheduler() {} + + void setup() { + mUptime = 0; + mTimestamp = 0; + mPrevMillis = millis(); } - } - // checked every second - void once(uint32_t sec, SchedulerCb cb, const char *info = NULL) { - if(NULL != info) { - DPRINT(DBG_INFO, F("once in [s]: ") + String(sec)); - DBGPRINTLN(F(", ") + String(info)); - } - mOnce.push_back(once_t(sec, cb)); - } - - // checked every minute - void onceAt(uint32_t timestamp, SchedulerCb cb, const char *info = NULL) { - if(timestamp > mTimestamp) { - if(NULL != info) { - DPRINT(DBG_INFO, F("onceAt (UTC): ") + getDateTimeStr(timestamp)); - DBGPRINTLN(F(", ") + String(info)); + void loop(void) { + mMillis = millis(); + mDiff = mMillis - mPrevMillis; + if(mDiff >= 1000) { + if(mMillis < mPrevMillis) { // overflow + mPrevMillis = mMillis; + return; + } + mDiffSeconds = mDiff / 1000; + mPrevMillis += (mPrevMillis * 1000); + checkEvery(); + checkAt(); + mUptime += mDiffSeconds; + if(0 != mTimestamp) + mTimestamp += mDiffSeconds; } - mOnceAt.push_back(once_t(timestamp, cb)); } - } - - virtual void setTimestamp(uint32_t ts) { - mTimestamp = ts; - } - - void addListener(uint8_t every, SchedulerCb cb) { - switch(every) { - case EVERY_SEC: mListSecond.push_back(cb); break; - case EVERY_MIN: mListMinute.push_back(cb); break; - case EVERY_HR: mListHour.push_back(cb); break; - case EVERY_12H: mList12h.push_back(cb); break; - case EVERY_DAY: mListDay.push_back(cb); break; - default: break; + + void once(scdCb c, uint32_t timeout) { mStack.add(c, timeout, 0); } + void every(scdCb c, uint32_t interval) { mStack.add(c, interval, interval); } + void onceAt(scdCb c, uint32_t timestamp) { mStackAt.add(c, timestamp); } + + void everySec(scdCb c) { mStack.add(c, SCD_SEC, SCD_SEC); } + void everyMin(scdCb c) { mStack.add(c, SCD_MIN, SCD_MIN); } + void everyHour(scdCb c) { mStack.add(c, SCD_HOUR, SCD_HOUR); } + void every12h(scdCb c) { mStack.add(c, SCD_12H, SCD_12H); } + void everyDay(scdCb c) { mStack.add(c, SCD_DAY, SCD_DAY); } + + virtual void setTimestamp(uint32_t ts) { + mTimestamp = ts; } - } - uint32_t getUptime(void) { - return mUptime; - } + uint32_t getUptime(void) { + return mUptime; + } - uint32_t getTimestamp(void) { - return mTimestamp; - } + uint32_t getTimestamp(void) { + return mTimestamp; + } - protected: - virtual void notify(std::list *lType) { - for(std::list::iterator it = lType->begin(); it != lType->end(); ++it) { - (*it)(); + void stat() { + DPRINTLN(DBG_INFO, "max fill every: " + String(mStack.getMaxFill())); + DPRINTLN(DBG_INFO, "max fill at: " + String(mStackAt.getMaxFill())); } - } - - uint32_t mTimestamp; - - private: - void onceFuncTick(void) { - if(mOnce.empty()) - return; - for(std::list::iterator it = mOnce.begin(); it != mOnce.end();) { - if(((*it).n)-- == 0) { - ((*it).f)(); - it = mOnce.erase(it); + + protected: + uint32_t mTimestamp; + + private: + inline void checkEvery(void) { + bool expired; + sP *p = mStack.getFront(); + while(NULL != p) { + if(mDiffSeconds >= p->d.timeout) expired = true; + else if((p->d.timeout--) == 0) expired = true; + else expired = false; + + if(expired) { + (p->d.c)(); + if(0 == p->d.reload) + p = mStack.rem(p); + else { + p->d.timeout = p->d.reload - 1; + p = mStack.get(p); + } + } + else + p = mStack.get(p); } - else - ++it; } - } - - void onceAtFuncTick(void) { - if(mOnceAt.empty()) - return; - for(std::list::iterator it = mOnceAt.begin(); it != mOnceAt.end();) { - if(((*it).n) < mTimestamp) { - ((*it).f)(); - it = mOnceAt.erase(it); + + inline void checkAt(void) { + sPAt *p = mStackAt.getFront(); + while(NULL != p) { + if((p->d.timestamp) <= mTimestamp) { + (p->d.c)(); + p = mStackAt.rem(p); + } + else + p = mStackAt.get(p); } - else - ++it; } - } - - std::list mListSecond; - std::list mListMinute; - std::list mListHour; - std::list mList12h; - std::list mListDay; - - std::list mOnce; - std::list mOnceAt; - uint32_t mPrevMillis, mUptime; - uint8_t mSeconds, mMinutes, mHours; -}; + llist<25, scdEvry_s, scdCb, uint32_t, uint32_t> mStack; + llist<10, scdAt_s, scdCb, uint32_t> mStackAt; + uint32_t mMillis, mPrevMillis, mDiff; + uint32_t mUptime; + uint8_t mDiffSeconds; + }; } #endif /*__SCHEDULER_H__*/ diff --git a/src/utils/sun.h b/src/utils/sun.h index c6d078d4..c66149c2 100644 --- a/src/utils/sun.h +++ b/src/utils/sun.h @@ -10,7 +10,7 @@ namespace ah { void calculateSunriseSunset(uint32_t utcTs, uint32_t offset, float lat, float lon, uint32_t *sunrise, uint32_t *sunset) { // Source: https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth - // Julian day since 1.1.2000 12:00 + correction 69.12s + // Julian day since 1.1.2000 12:00 double n_JulianDay = (utcTs + offset) / 86400 - 10957.0; // Mean solar time double J = n_JulianDay - lon / 360; diff --git a/src/web/html/index.html b/src/web/html/index.html index 070aee31..b5b55b9b 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -48,9 +48,6 @@
Discuss with us on Discord
-

Documentation

- ahoydtu.de -

Support this project:

  • Report issues
  • @@ -118,10 +115,13 @@ var sec = up % 60; var sunrise = new Date(obj["ts_sunrise"] * 1000); var sunset = new Date(obj["ts_sunset"] * 1000); - document.getElementById("uptime").innerHTML = days + " Days, " - + ("0"+hrs).substr(-2) + ":" - + ("0"+min).substr(-2) + ":" - + ("0"+sec).substr(-2); + var e = document.getElementById("uptime"); + e.innerHTML = days + " Day"; + if(1 != days) + e.innerHTML += "s"; + e.innerHTML += ", " + ("0"+hrs).substr(-2) + ":" + + ("0"+min).substr(-2) + ":" + + ("0"+sec).substr(-2); var dSpan = document.getElementById("date"); if(0 != obj["ts_now"]) dSpan.innerHTML = date.toLocaleString('de-DE'); diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 82370031..c8a10412 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -8,8 +8,6 @@ #define F(sl) (sl) #endif #include "ahoywifi.h" -#include "../utils/ahoyTimer.h" - // NTP CONFIG #define NTP_PACKET_SIZE 48 @@ -25,17 +23,16 @@ ahoywifi::ahoywifi() { //----------------------------------------------------------------------------- void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp) { - char ipSta[16]; mConfig = config; mUtcTimestamp = utcTimestamp; #if !defined(FB_WIFI_OVERRIDDEN) - if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) != 0) + if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) == 0) setupAp(); #endif #if !defined(AP_ONLY) - setupStation(); - ah::ip2Char(mConfig->sys.ip.ip, ipSta); + if(mConfig->valid) + setupStation(); #endif #if defined(ESP8266)