Add ap_date and ap_time vars (#142)

* Add ap_date and ap_time vars
* Add convenience creation function for Timer
* Optimize timer
* Document timer
This commit is contained in:
Moritz Wirger
2023-10-04 21:43:28 +02:00
committed by GitHub
parent c403c06b09
commit 6c4f8ef35b
10 changed files with 119 additions and 53 deletions

View File

@@ -50,6 +50,8 @@
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
"typeinfo": "cpp",
"chrono": "cpp",
"ratio": "cpp"
}
}

View File

@@ -108,7 +108,14 @@ extern void clearPending(tagRecord* taginfo);
extern void initAPconfig();
extern void saveAPconfig();
extern HwType getHwType(const uint8_t id);
extern bool setVarDB(const std::string& key, const String& value);
/// @brief Update a variable with the given key and value
///
/// @param key Variable key
/// @param value Variable value
/// @param notify Should the change be notified (true, default) or not (false)
/// @return true If variable was created/updated
/// @return false If not
extern bool setVarDB(const std::string& key, const String& value, const bool notify = true);
extern void cleanupCurrent();
#pragma pack(pop)

View File

@@ -7,6 +7,7 @@
#include "system.h"
#include "web.h"
/// @brief Different utility functions
namespace util {
/// @brief Can be used to wrap a stream and see what's going on
@@ -125,26 +126,46 @@ static bool isSleeping(int sleeptime1, int sleeptime2) {
}
}
/// @brief Get the time_t for midnight
/// @return time_t for midnight
inline time_t getMidnightTime() {
struct tm time_info;
getLocalTime(&time_info);
time_info.tm_hour = time_info.tm_min = time_info.tm_sec = 0;
time_info.tm_mday++;
return mktime(&time_info);
}
/// @brief Timer for kind of scheduling things
class Timer {
public:
Timer(unsigned long interval) : interval_(interval), previousMillis_(0) {}
/// @brief Construct a timer
/// @param interval Interval in ms at which @ref doRun() returns true
/// @param delay Delay in ms until first execution to defer start
Timer(const unsigned long interval, const unsigned long delay = 0) : m_interval(interval), m_nextMillis(millis() + delay) {}
void setInterval(unsigned long interval) {
interval_ = interval;
/// @brief Change the interval
/// @param interval New interval in ms
void setInterval(const unsigned long interval) {
m_interval = interval;
}
bool doRun() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis_ >= interval_) {
previousMillis_ = currentMillis;
/// @brief Check if interval is met
/// @param currentMillis Optionally provide the current time in millis
/// @return True if interval is met, false if not
bool doRun(const unsigned long currentMillis = millis()) {
if (currentMillis >= m_nextMillis) {
m_nextMillis = currentMillis + m_interval;
return true;
}
return false;
}
private:
unsigned long interval_;
unsigned long previousMillis_;
/// @brief Timer interval in ms
unsigned long m_interval;
/// @brief Next timeer interval in ms
unsigned long m_nextMillis;
};
/// @brief Create a String from format
@@ -163,3 +184,10 @@ inline String formatString(char buffer[bufSize], const char *format, ...) {
}
} // namespace util
/// @brief Converts seconds to milliseconds
#define seconds(s) s * 1000
/// @brief Converts minutes to milliseconds
#define minutes(m) seconds(m * 60)
/// @brief Converts hours to milliseconds
#define hours(m) minutes(m * 60)

View File

@@ -178,12 +178,6 @@ void drawNew(const uint8_t mac[8], const bool buttonPressed, tagRecord *&taginfo
}
#endif
struct tm time_info;
getLocalTime(&time_info);
time_info.tm_hour = time_info.tm_min = time_info.tm_sec = 0;
time_info.tm_mday++;
const time_t midnight = mktime(&time_info);
DynamicJsonDocument doc(500);
deserializeJson(doc, taginfo->modeConfigJson);
JsonObject cfgobj = doc.as<JsonObject>();
@@ -193,7 +187,6 @@ void drawNew(const uint8_t mac[8], const bool buttonPressed, tagRecord *&taginfo
taginfo->nextupdate = now + 60;
imgParam imageParams;
imageParams.width = hwdata.width;
imageParams.height = hwdata.height;
imageParams.bpp = hwdata.bpp;
@@ -280,12 +273,12 @@ void drawNew(const uint8_t mac[8], const bool buttonPressed, tagRecord *&taginfo
case 1: // Today
drawDate(filename, taginfo, imageParams);
taginfo->nextupdate = midnight;
updateTagImage(filename, mac, (midnight - now) / 60 - 10, taginfo, imageParams);
taginfo->nextupdate = util::getMidnightTime();
updateTagImage(filename, mac, (taginfo->nextupdate - now) / 60 - 10, taginfo, imageParams);
break;
case 2: // CountDays
drawCounter(mac, buttonPressed, taginfo, cfgobj, filename, imageParams, midnight, 15);
drawCounter(mac, buttonPressed, taginfo, cfgobj, filename, imageParams, util::getMidnightTime(), 15);
break;
case 3: // CountHours
@@ -509,11 +502,19 @@ void replaceVariables(String &format) {
size_t startIndex = 0;
size_t openBraceIndex, closeBraceIndex;
time_t now;
time(&now);
struct tm timedef;
localtime_r(&now, &timedef);
char timeBuffer[80];
strftime(timeBuffer, sizeof(timeBuffer), "%H:%M:%S", &timedef);
setVarDB("ap_time", timeBuffer, false);
while ((openBraceIndex = format.indexOf('{', startIndex)) != -1 &&
(closeBraceIndex = format.indexOf('}', openBraceIndex + 1)) != -1) {
const std::string variableName = format.substring(openBraceIndex + 1, closeBraceIndex).c_str();
const std::string varKey = "{" + variableName + "}";
auto var = varDB.find(variableName);
const auto var = varDB.find(variableName);
if (var != varDB.end()) {
format.replace(varKey.c_str(), var->second.value);
}

View File

@@ -23,10 +23,15 @@
#include "util.h"
#include "web.h"
util::Timer intervalSysinfo(3000);
util::Timer intervalVars(10000);
util::Timer intervalSaveDB(300000);
util::Timer intervalContentRunner(1000);
util::Timer intervalContentRunner(seconds(1));
util::Timer intervalSysinfo(seconds(3));
util::Timer intervalVars(seconds(10));
util::Timer intervalSaveDB(minutes(5));
util::Timer intervalCheckDate(minutes(5));
#ifdef OPENEPAPERLINK_PCB
util::Timer tagConnectTimer(seconds(1));
#endif
SET_LOOP_TASK_STACK_SIZE(16 * 1024);
@@ -158,6 +163,21 @@ void loop() {
if (intervalContentRunner.doRun() && apInfo.state == AP_STATE_ONLINE) {
contentRunner();
}
if (intervalCheckDate.doRun() && config.runStatus == RUNSTATUS_RUN) {
static uint8_t day = 0;
time_t now;
time(&now);
struct tm timedef;
localtime_r(&now, &timedef);
if (day != timedef.tm_mday) {
day = timedef.tm_mday;
char timeBuffer[80];
strftime(timeBuffer, sizeof(timeBuffer), "%d-%m-%Y", &timedef);
setVarDB("ap_date", timeBuffer);
}
}
#ifdef YELLOW_IPS_AP
extern void yellow_ap_display_loop(void);
@@ -165,21 +185,17 @@ void loop() {
#endif
#ifdef OPENEPAPERLINK_PCB
time_t tagConnectTimer = 0;
if (millis() - tagConnectTimer > 1000) {
tagConnectTimer = millis();
if (extTagConnected()) {
flashCountDown(3);
if (tagConnectTimer.doRun() && extTagConnected()) {
flashCountDown(3);
pinMode(FLASHER_EXT_TEST, OUTPUT);
digitalWrite(FLASHER_EXT_TEST, LOW);
pinMode(FLASHER_EXT_TEST, OUTPUT);
digitalWrite(FLASHER_EXT_TEST, LOW);
doTagFlash();
doTagFlash();
vTaskDelay(10000 / portTICK_PERIOD_MS);
pinMode(FLASHER_EXT_TEST, INPUT);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
vTaskDelay(10000 / portTICK_PERIOD_MS);
pinMode(FLASHER_EXT_TEST, INPUT);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
#endif

View File

@@ -330,7 +330,9 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
}
void processBlockRequest(struct espBlockRequest* br) {
if (config.runStatus == RUNSTATUS_STOP) return;
if (config.runStatus == RUNSTATUS_STOP) {
return;
}
if (!checkCRC(br, sizeof(struct espBlockRequest))) {
Serial.print("Failed CRC on a blockrequest received by the AP");
return;
@@ -372,7 +374,9 @@ void processBlockRequest(struct espBlockRequest* br) {
}
void processXferComplete(struct espXferComplete* xfc, bool local) {
if (config.runStatus == RUNSTATUS_STOP) return;
if (config.runStatus == RUNSTATUS_STOP) {
return;
}
char buffer[64];
sprintf(buffer, "< %02X%02X%02X%02X%02X%02X%02X%02X reports xfer complete\n\0", xfc->src[7], xfc->src[6], xfc->src[5], xfc->src[4], xfc->src[3], xfc->src[2], xfc->src[1], xfc->src[0]);
wsLog((String)buffer);
@@ -416,7 +420,9 @@ void processXferComplete(struct espXferComplete* xfc, bool local) {
}
void processXferTimeout(struct espXferComplete* xfc, bool local) {
if (config.runStatus == RUNSTATUS_STOP) return;
if (config.runStatus == RUNSTATUS_STOP) {
return;
}
char buffer[64];
sprintf(buffer, "< %02X%02X%02X%02X%02X%02X%02X%02X xfer timeout\n\0", xfc->src[7], xfc->src[6], xfc->src[5], xfc->src[4], xfc->src[3], xfc->src[2], xfc->src[1], xfc->src[0]);
wsErr((String)buffer);
@@ -440,7 +446,9 @@ void processXferTimeout(struct espXferComplete* xfc, bool local) {
}
void processDataReq(struct espAvailDataReq* eadr, bool local, IPAddress remoteIP) {
if (config.runStatus == RUNSTATUS_STOP) return;
if (config.runStatus == RUNSTATUS_STOP) {
return;
}
char buffer[64];
tagRecord* taginfo = tagRecord::findByMAC(eadr->src);

View File

@@ -256,7 +256,7 @@ void C6firmwareUpdateTask(void* parameter) {
if (result) {
setAPstate(false, AP_STATE_OFFLINE);
wsSerial("Finishing config...");
vTaskDelay(3000 / portTICK_PERIOD_MS);

View File

@@ -26,7 +26,9 @@ void initTime(void* parameter) {
break;
}
}
if (config.runStatus = RUNSTATUS_INIT) config.runStatus = RUNSTATUS_RUN;
if (config.runStatus == RUNSTATUS_INIT) {
config.runStatus = RUNSTATUS_RUN;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
vTaskDelete(NULL);
}

View File

@@ -264,7 +264,7 @@ uint32_t getTagCount(uint32_t& timeoutcount) {
// not initialised, timeout if not seen last 10 minutes
if (timeout > 600) timeoutcount++;
} else if (now - taginfo->expectedNextCheckin > 600) {
//expected checkin is behind, timeout if not seen last 10 minutes
// expected checkin is behind, timeout if not seen last 10 minutes
if (timeout > 600) timeoutcount++;
}
}
@@ -383,19 +383,19 @@ HwType getHwType(const uint8_t id) {
}
}
bool setVarDB(const std::string& key, const String& value) {
bool setVarDB(const std::string& key, const String& value, const bool notify) {
auto it = varDB.find(key);
if (it == varDB.end()) {
varStruct newVar;
newVar.value = value;
newVar.changed = true;
newVar.changed = notify;
varDB[key] = newVar;
return true;
}
if (it->second.value != value) {
it->second.value = value;
it->second.changed = true;
it->second.changed = notify;
return true;
} else {
return false;

View File

@@ -1,13 +1,14 @@
#include "udp.h"
#include <Arduino.h>
#include <WiFi.h>
#include "AsyncUDP.h"
#include "commstructs.h"
#include "newproto.h"
#include "serialap.h"
#include "tag_db.h"
#include "web.h"
#include "serialap.h"
#include "udp.h"
#define UDPIP IPAddress(239, 10, 0, 1)
#define UDPPORT 16033
@@ -41,8 +42,9 @@ void UDPcomm::init() {
}
void UDPcomm::processPacket(AsyncUDPPacket packet) {
if (config.runStatus == RUNSTATUS_STOP) return;
if (config.runStatus == RUNSTATUS_STOP) {
return;
}
IPAddress senderIP = packet.remoteIP();
switch (packet.data()[0]) {
@@ -127,7 +129,7 @@ void autoselect(void* pvParameters) {
}
if (curChannel.channel == 0) {
curChannel.channel = 11;
}
}
config.channel = curChannel.channel;
do {
vTaskDelay(1000 / portTICK_PERIOD_MS);