From ed16cff06e2d327b6c31cb33ae9e7495d6fead22 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 27 Dec 2022 23:15:36 +0100 Subject: [PATCH] fix Update button protection (prevent double click #527) optimized scheduler #515 (thx @beegee3) --- src/CHANGES.md | 4 ++ src/app.h | 4 +- src/appInterface.h | 2 +- src/defines.h | 2 +- src/utils/scheduler.h | 119 ++++++++++++++++++--------------------- src/web/RestApi.h | 7 +-- src/web/html/update.html | 12 +++- 7 files changed, 76 insertions(+), 74 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index a6c29c7ee..ef486e39f 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Changelog +## 0.5.63 +* fix Update button protection (prevent double click #527) +* optimized scheduler #515 (thx @beegee3) + ## 0.5.62 * fix MQTT `status` update * removed MQTT `available_text` (can be deducted from `available`) diff --git a/src/app.h b/src/app.h index 09542e320..ca5b29e23 100644 --- a/src/app.h +++ b/src/app.h @@ -155,8 +155,8 @@ class app : public IApp, public ah::Scheduler { return mApi.getTimezoneOffset(); } - void getSchedulerInfo(uint16_t *everyMax, uint16_t *atMax) { - return getStat(everyMax, atMax); + void getSchedulerInfo(uint8_t *max) { + return getStat(max); } void setTimestamp(uint32_t newTime) { diff --git a/src/appInterface.h b/src/appInterface.h index 1a71ad610..94f753992 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -28,7 +28,7 @@ class IApp { virtual void setTimestamp(uint32_t newTime) = 0; virtual String getTimeStr(uint32_t offset) = 0; virtual uint32_t getTimezoneOffset() = 0; - virtual void getSchedulerInfo(uint16_t *everyMax, uint16_t *atMax); + virtual void getSchedulerInfo(uint8_t *max) = 0; virtual bool getRebootRequestState() = 0; virtual bool getSettingsValid() = 0; diff --git a/src/defines.h b/src/defines.h index 2778da464..473d67244 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 62 +#define VERSION_PATCH 63 //------------------------------------- typedef struct { diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h index fb80d1417..36dcdaaef 100644 --- a/src/utils/scheduler.h +++ b/src/utils/scheduler.h @@ -8,7 +8,6 @@ #define __SCHEDULER_H__ #include -#include "llist.h" #include "dbg.h" namespace ah { @@ -16,24 +15,17 @@ namespace ah { enum {SCD_SEC = 1, SCD_MIN = 60, SCD_HOUR = 3600, SCD_12H = 43200, SCD_DAY = 86400}; - struct scdEvry_s { + struct sP { 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) {} + bool isTimestamp; + sP() : c(NULL), timeout(0), reload(0), isTimestamp(false) {} + sP(scdCb a, uint32_t tmt, uint32_t rl, bool its) : c(a), timeout(tmt), reload(rl), isTimestamp(its) {} }; - 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) {} - }; + #define MAX_NUM_TICKER 30 - - typedef node_s sP; - typedef node_s sPAt; class Scheduler { public: Scheduler() {} @@ -41,7 +33,10 @@ namespace ah { void setup() { mUptime = 0; mTimestamp = 0; + mMax = 0; mPrevMillis = millis(); + for (uint8_t i = 0; i < MAX_NUM_TICKER; i++) + mTickerInUse[i] = false; } void loop(void) { @@ -66,37 +61,29 @@ namespace ah { mUptime += mDiffSeconds; if(0 != mTimestamp) mTimestamp += mDiffSeconds; - checkEvery(); - checkAt(); + checkTicker(); } - void once(scdCb c, uint32_t timeout) { mStack.add(c, timeout, 0); } - void onceAt(scdCb c, uint32_t timestamp) { mStackAt.add(c, timestamp); } - uint8_t every(scdCb c, uint32_t interval){ return mStack.add(c, interval, interval)->id; } + void once(scdCb c, uint32_t timeout) { addTicker(c, timeout, 0, false); } + void onceAt(scdCb c, uint32_t timestamp) { addTicker(c, timestamp, 0, true); } + uint8_t every(scdCb c, uint32_t interval){ return addTicker(c, interval, interval, false); } - 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); } + void everySec(scdCb c) { every(c, SCD_SEC); } + void everyMin(scdCb c) { every(c, SCD_MIN); } + void everyHour(scdCb c) { every(c, SCD_HOUR); } + void every12h(scdCb c) { every(c, SCD_12H); } + void everyDay(scdCb c) { every(c, SCD_DAY); } virtual void setTimestamp(uint32_t ts) { mTimestamp = ts; } bool resetEveryById(uint8_t id) { - sP *p = mStack.getFront(); - while(NULL != p) { - if(p->id == id) - break; - p = mStack.get(p); - } - if(NULL != p) { - p->d.timeout = p->d.reload; - return true; - } - return false; + if (mTickerInUse[id] == false) + return false; + mTicker[id].timeout = mTicker[id].reload; + return true; } uint32_t getUptime(void) { @@ -107,53 +94,57 @@ namespace ah { return mTimestamp; } - void getStat(uint16_t *everyMax, uint16_t *atMax) { - *everyMax = mStack.getMaxFill(); - *atMax = mStackAt.getMaxFill(); + void getStat(uint8_t *max) { + *max = mMax; } protected: uint32_t mTimestamp; private: - inline void checkEvery(void) { - sP *p = mStack.getFront(); - while(NULL != p) { - if(mDiffSeconds >= p->d.timeout) { // expired - (p->d.c)(); - yield(); - if(0 == p->d.reload) - p = mStack.rem(p); - else { - p->d.timeout = p->d.reload; - p = mStack.get(p); - } - } - else { // not expired - p->d.timeout -= mDiffSeconds; - p = mStack.get(p); + inline uint8_t addTicker(scdCb c, uint32_t timeout, uint32_t reload, bool isTimestamp) { + for (uint8_t i = 0; i < MAX_NUM_TICKER; i++) { + if (!mTickerInUse[i]) { + mTickerInUse[i] = true; + mTicker[i].c = c; + mTicker[i].timeout = timeout; + mTicker[i].reload = reload; + mTicker[i].isTimestamp = isTimestamp; + if(mMax == i) + mMax = i + 1; + return i; } } + return 0xff; } - inline void checkAt(void) { - sPAt *p = mStackAt.getFront(); - while(NULL != p) { - if((p->d.timestamp) <= mTimestamp) { - (p->d.c)(); - yield(); - p = mStackAt.rem(p); + inline void checkTicker(void) { + bool inUse[MAX_NUM_TICKER]; + for (uint8_t i = 0; i < MAX_NUM_TICKER; i++) + inUse[i] = mTickerInUse[i]; + for (uint8_t i = 0; i < MAX_NUM_TICKER; i++) { + if (inUse[i]) { + if (mTicker[i].timeout <= ((mTicker[i].isTimestamp) ? mTimestamp : mDiffSeconds)) { // expired + if(0 == mTicker[i].reload) + mTickerInUse[i] = false; + else + mTicker[i].timeout = mTicker[i].reload; + (mTicker[i].c)(); + yield(); + } + else // not expired + if (!mTicker[i].isTimestamp) + mTicker[i].timeout -= mDiffSeconds; } - else - p = mStackAt.get(p); } } - llist<20, scdEvry_s, scdCb, uint32_t, uint32_t> mStack; - llist<10, scdAt_s, scdCb, uint32_t> mStackAt; + sP mTicker[MAX_NUM_TICKER]; + bool mTickerInUse[MAX_NUM_TICKER]; uint32_t mMillis, mPrevMillis, mDiff; uint32_t mUptime; uint8_t mDiffSeconds; + uint8_t mMax; }; } diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 19cb2603a..b9483dc1b 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -201,10 +201,9 @@ class RestApi { //obj[F("littlefs_total")] = LittleFS.totalBytes(); //obj[F("littlefs_used")] = LittleFS.usedBytes(); - uint16_t evry, at; - mApp->getSchedulerInfo(&evry, &at); - obj[F("schEvryMax")] = evry; - obj[F("schAtMax")] = at; + uint8_t max; + mApp->getSchedulerInfo(&max); + obj[F("schMax")] = max; } void getHtmlSystem(JsonObject obj) { diff --git a/src/web/html/update.html b/src/web/html/update.html index 1040efb7e..215188db2 100644 --- a/src/web/html/update.html +++ b/src/web/html/update.html @@ -19,9 +19,11 @@
-
- + + +
+