mirror of
https://github.com/lumapu/ahoy.git
synced 2025-06-06 04:31:37 +02:00
fix Update button protection (prevent double click #527)
optimized scheduler #515 (thx @beegee3)
This commit is contained in:
parent
e5de2517e2
commit
ed16cff06e
7 changed files with 79 additions and 77 deletions
|
@ -1,5 +1,9 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.5.63
|
||||||
|
* fix Update button protection (prevent double click #527)
|
||||||
|
* optimized scheduler #515 (thx @beegee3)
|
||||||
|
|
||||||
## 0.5.62
|
## 0.5.62
|
||||||
* fix MQTT `status` update
|
* fix MQTT `status` update
|
||||||
* removed MQTT `available_text` (can be deducted from `available`)
|
* removed MQTT `available_text` (can be deducted from `available`)
|
||||||
|
|
|
@ -155,8 +155,8 @@ class app : public IApp, public ah::Scheduler {
|
||||||
return mApi.getTimezoneOffset();
|
return mApi.getTimezoneOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void getSchedulerInfo(uint16_t *everyMax, uint16_t *atMax) {
|
void getSchedulerInfo(uint8_t *max) {
|
||||||
return getStat(everyMax, atMax);
|
return getStat(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTimestamp(uint32_t newTime) {
|
void setTimestamp(uint32_t newTime) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ class IApp {
|
||||||
virtual void setTimestamp(uint32_t newTime) = 0;
|
virtual void setTimestamp(uint32_t newTime) = 0;
|
||||||
virtual String getTimeStr(uint32_t offset) = 0;
|
virtual String getTimeStr(uint32_t offset) = 0;
|
||||||
virtual uint32_t getTimezoneOffset() = 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 getRebootRequestState() = 0;
|
||||||
virtual bool getSettingsValid() = 0;
|
virtual bool getSettingsValid() = 0;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 5
|
#define VERSION_MINOR 5
|
||||||
#define VERSION_PATCH 62
|
#define VERSION_PATCH 63
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#define __SCHEDULER_H__
|
#define __SCHEDULER_H__
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "llist.h"
|
|
||||||
#include "dbg.h"
|
#include "dbg.h"
|
||||||
|
|
||||||
namespace ah {
|
namespace ah {
|
||||||
|
@ -16,24 +15,17 @@ namespace ah {
|
||||||
|
|
||||||
enum {SCD_SEC = 1, SCD_MIN = 60, SCD_HOUR = 3600, SCD_12H = 43200, SCD_DAY = 86400};
|
enum {SCD_SEC = 1, SCD_MIN = 60, SCD_HOUR = 3600, SCD_12H = 43200, SCD_DAY = 86400};
|
||||||
|
|
||||||
struct scdEvry_s {
|
struct sP {
|
||||||
scdCb c;
|
scdCb c;
|
||||||
uint32_t timeout;
|
uint32_t timeout;
|
||||||
uint32_t reload;
|
uint32_t reload;
|
||||||
scdEvry_s() : c(NULL), timeout(0), reload(0) {}
|
bool isTimestamp;
|
||||||
scdEvry_s(scdCb a, uint32_t tmt, uint32_t rl) : c(a), timeout(tmt), reload(rl) {}
|
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 {
|
#define MAX_NUM_TICKER 30
|
||||||
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<scdEvry_s, scdCb, uint32_t, uint32_t> sP;
|
|
||||||
typedef node_s<scdAt_s, scdCb, uint32_t> sPAt;
|
|
||||||
class Scheduler {
|
class Scheduler {
|
||||||
public:
|
public:
|
||||||
Scheduler() {}
|
Scheduler() {}
|
||||||
|
@ -41,7 +33,10 @@ namespace ah {
|
||||||
void setup() {
|
void setup() {
|
||||||
mUptime = 0;
|
mUptime = 0;
|
||||||
mTimestamp = 0;
|
mTimestamp = 0;
|
||||||
|
mMax = 0;
|
||||||
mPrevMillis = millis();
|
mPrevMillis = millis();
|
||||||
|
for (uint8_t i = 0; i < MAX_NUM_TICKER; i++)
|
||||||
|
mTickerInUse[i] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop(void) {
|
void loop(void) {
|
||||||
|
@ -66,37 +61,29 @@ namespace ah {
|
||||||
mUptime += mDiffSeconds;
|
mUptime += mDiffSeconds;
|
||||||
if(0 != mTimestamp)
|
if(0 != mTimestamp)
|
||||||
mTimestamp += mDiffSeconds;
|
mTimestamp += mDiffSeconds;
|
||||||
checkEvery();
|
checkTicker();
|
||||||
checkAt();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void once(scdCb c, uint32_t timeout) { mStack.add(c, timeout, 0); }
|
void once(scdCb c, uint32_t timeout) { addTicker(c, timeout, 0, false); }
|
||||||
void onceAt(scdCb c, uint32_t timestamp) { mStackAt.add(c, timestamp); }
|
void onceAt(scdCb c, uint32_t timestamp) { addTicker(c, timestamp, 0, true); }
|
||||||
uint8_t every(scdCb c, uint32_t interval){ return mStack.add(c, interval, interval)->id; }
|
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 everySec(scdCb c) { every(c, SCD_SEC); }
|
||||||
void everyMin(scdCb c) { mStack.add(c, SCD_MIN, SCD_MIN); }
|
void everyMin(scdCb c) { every(c, SCD_MIN); }
|
||||||
void everyHour(scdCb c) { mStack.add(c, SCD_HOUR, SCD_HOUR); }
|
void everyHour(scdCb c) { every(c, SCD_HOUR); }
|
||||||
void every12h(scdCb c) { mStack.add(c, SCD_12H, SCD_12H); }
|
void every12h(scdCb c) { every(c, SCD_12H); }
|
||||||
void everyDay(scdCb c) { mStack.add(c, SCD_DAY, SCD_DAY); }
|
void everyDay(scdCb c) { every(c, SCD_DAY); }
|
||||||
|
|
||||||
virtual void setTimestamp(uint32_t ts) {
|
virtual void setTimestamp(uint32_t ts) {
|
||||||
mTimestamp = ts;
|
mTimestamp = ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool resetEveryById(uint8_t id) {
|
bool resetEveryById(uint8_t id) {
|
||||||
sP *p = mStack.getFront();
|
if (mTickerInUse[id] == false)
|
||||||
while(NULL != p) {
|
return false;
|
||||||
if(p->id == id)
|
mTicker[id].timeout = mTicker[id].reload;
|
||||||
break;
|
return true;
|
||||||
p = mStack.get(p);
|
|
||||||
}
|
|
||||||
if(NULL != p) {
|
|
||||||
p->d.timeout = p->d.reload;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getUptime(void) {
|
uint32_t getUptime(void) {
|
||||||
|
@ -107,53 +94,57 @@ namespace ah {
|
||||||
return mTimestamp;
|
return mTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getStat(uint16_t *everyMax, uint16_t *atMax) {
|
void getStat(uint8_t *max) {
|
||||||
*everyMax = mStack.getMaxFill();
|
*max = mMax;
|
||||||
*atMax = mStackAt.getMaxFill();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t mTimestamp;
|
uint32_t mTimestamp;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void checkEvery(void) {
|
inline uint8_t addTicker(scdCb c, uint32_t timeout, uint32_t reload, bool isTimestamp) {
|
||||||
sP *p = mStack.getFront();
|
for (uint8_t i = 0; i < MAX_NUM_TICKER; i++) {
|
||||||
while(NULL != p) {
|
if (!mTickerInUse[i]) {
|
||||||
if(mDiffSeconds >= p->d.timeout) { // expired
|
mTickerInUse[i] = true;
|
||||||
(p->d.c)();
|
mTicker[i].c = c;
|
||||||
yield();
|
mTicker[i].timeout = timeout;
|
||||||
if(0 == p->d.reload)
|
mTicker[i].reload = reload;
|
||||||
p = mStack.rem(p);
|
mTicker[i].isTimestamp = isTimestamp;
|
||||||
else {
|
if(mMax == i)
|
||||||
p->d.timeout = p->d.reload;
|
mMax = i + 1;
|
||||||
p = mStack.get(p);
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
else { // not expired
|
if (!mTicker[i].isTimestamp)
|
||||||
p->d.timeout -= mDiffSeconds;
|
mTicker[i].timeout -= mDiffSeconds;
|
||||||
p = mStack.get(p);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void checkAt(void) {
|
sP mTicker[MAX_NUM_TICKER];
|
||||||
sPAt *p = mStackAt.getFront();
|
bool mTickerInUse[MAX_NUM_TICKER];
|
||||||
while(NULL != p) {
|
|
||||||
if((p->d.timestamp) <= mTimestamp) {
|
|
||||||
(p->d.c)();
|
|
||||||
yield();
|
|
||||||
p = mStackAt.rem(p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
p = mStackAt.get(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
llist<20, scdEvry_s, scdCb, uint32_t, uint32_t> mStack;
|
|
||||||
llist<10, scdAt_s, scdCb, uint32_t> mStackAt;
|
|
||||||
uint32_t mMillis, mPrevMillis, mDiff;
|
uint32_t mMillis, mPrevMillis, mDiff;
|
||||||
uint32_t mUptime;
|
uint32_t mUptime;
|
||||||
uint8_t mDiffSeconds;
|
uint8_t mDiffSeconds;
|
||||||
|
uint8_t mMax;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,10 +201,9 @@ class RestApi {
|
||||||
//obj[F("littlefs_total")] = LittleFS.totalBytes();
|
//obj[F("littlefs_total")] = LittleFS.totalBytes();
|
||||||
//obj[F("littlefs_used")] = LittleFS.usedBytes();
|
//obj[F("littlefs_used")] = LittleFS.usedBytes();
|
||||||
|
|
||||||
uint16_t evry, at;
|
uint8_t max;
|
||||||
mApp->getSchedulerInfo(&evry, &at);
|
mApp->getSchedulerInfo(&max);
|
||||||
obj[F("schEvryMax")] = evry;
|
obj[F("schMax")] = max;
|
||||||
obj[F("schAtMax")] = at;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void getHtmlSystem(JsonObject obj) {
|
void getHtmlSystem(JsonObject obj) {
|
||||||
|
|
|
@ -19,9 +19,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<form method="POST" action="/update" enctype="multipart/form-data" accept-charset="utf-8">
|
<form id="form" method="POST" action="/update" enctype="multipart/form-data" accept-charset="utf-8">
|
||||||
<input type="file" name="update"><input type="submit" value="Update">
|
<input type="file" name="update">
|
||||||
|
<input type="button" class="btn" value="Update" onclick="hide()">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
|
@ -54,6 +56,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hide() {
|
||||||
|
document.getElementById("form").submit();
|
||||||
|
var e = document.getElementById("content");
|
||||||
|
e.replaceChildren(span("update started"));
|
||||||
|
}
|
||||||
|
|
||||||
getAjax("/api/index", parse);
|
getAjax("/api/index", parse);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue