From 6c4f8ef35b5c97ea15d837ab1460f3f3d9f067f2 Mon Sep 17 00:00:00 2001 From: Moritz Wirger Date: Wed, 4 Oct 2023 21:43:28 +0200 Subject: [PATCH] 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 --- ESP32_AP-Flasher/.vscode/settings.json | 4 ++- ESP32_AP-Flasher/include/tag_db.h | 9 ++++- ESP32_AP-Flasher/include/util.h | 46 +++++++++++++++++++----- ESP32_AP-Flasher/src/contentmanager.cpp | 23 ++++++------ ESP32_AP-Flasher/src/main.cpp | 48 ++++++++++++++++--------- ESP32_AP-Flasher/src/newproto.cpp | 16 ++++++--- ESP32_AP-Flasher/src/ota.cpp | 2 +- ESP32_AP-Flasher/src/system.cpp | 4 ++- ESP32_AP-Flasher/src/tag_db.cpp | 8 ++--- ESP32_AP-Flasher/src/udp.cpp | 12 ++++--- 10 files changed, 119 insertions(+), 53 deletions(-) diff --git a/ESP32_AP-Flasher/.vscode/settings.json b/ESP32_AP-Flasher/.vscode/settings.json index ea185af3..6335b759 100644 --- a/ESP32_AP-Flasher/.vscode/settings.json +++ b/ESP32_AP-Flasher/.vscode/settings.json @@ -50,6 +50,8 @@ "stdexcept": "cpp", "streambuf": "cpp", "cinttypes": "cpp", - "typeinfo": "cpp" + "typeinfo": "cpp", + "chrono": "cpp", + "ratio": "cpp" } } \ No newline at end of file diff --git a/ESP32_AP-Flasher/include/tag_db.h b/ESP32_AP-Flasher/include/tag_db.h index 4de04f40..4cbd85e1 100644 --- a/ESP32_AP-Flasher/include/tag_db.h +++ b/ESP32_AP-Flasher/include/tag_db.h @@ -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) diff --git a/ESP32_AP-Flasher/include/util.h b/ESP32_AP-Flasher/include/util.h index 085bfca8..32b33834 100644 --- a/ESP32_AP-Flasher/include/util.h +++ b/ESP32_AP-Flasher/include/util.h @@ -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) diff --git a/ESP32_AP-Flasher/src/contentmanager.cpp b/ESP32_AP-Flasher/src/contentmanager.cpp index 5212f5b7..3ca772bf 100644 --- a/ESP32_AP-Flasher/src/contentmanager.cpp +++ b/ESP32_AP-Flasher/src/contentmanager.cpp @@ -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(); @@ -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); } diff --git a/ESP32_AP-Flasher/src/main.cpp b/ESP32_AP-Flasher/src/main.cpp index bfa3c4fb..11ae17b6 100644 --- a/ESP32_AP-Flasher/src/main.cpp +++ b/ESP32_AP-Flasher/src/main.cpp @@ -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 diff --git a/ESP32_AP-Flasher/src/newproto.cpp b/ESP32_AP-Flasher/src/newproto.cpp index 45bb6b13..b95c8f6f 100644 --- a/ESP32_AP-Flasher/src/newproto.cpp +++ b/ESP32_AP-Flasher/src/newproto.cpp @@ -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); diff --git a/ESP32_AP-Flasher/src/ota.cpp b/ESP32_AP-Flasher/src/ota.cpp index a8e9d1a4..99ec9fd2 100644 --- a/ESP32_AP-Flasher/src/ota.cpp +++ b/ESP32_AP-Flasher/src/ota.cpp @@ -256,7 +256,7 @@ void C6firmwareUpdateTask(void* parameter) { if (result) { setAPstate(false, AP_STATE_OFFLINE); - + wsSerial("Finishing config..."); vTaskDelay(3000 / portTICK_PERIOD_MS); diff --git a/ESP32_AP-Flasher/src/system.cpp b/ESP32_AP-Flasher/src/system.cpp index aa613254..f9cf361e 100644 --- a/ESP32_AP-Flasher/src/system.cpp +++ b/ESP32_AP-Flasher/src/system.cpp @@ -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); } diff --git a/ESP32_AP-Flasher/src/tag_db.cpp b/ESP32_AP-Flasher/src/tag_db.cpp index 28d3b70e..1a636eff 100644 --- a/ESP32_AP-Flasher/src/tag_db.cpp +++ b/ESP32_AP-Flasher/src/tag_db.cpp @@ -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; diff --git a/ESP32_AP-Flasher/src/udp.cpp b/ESP32_AP-Flasher/src/udp.cpp index b0d6b079..739d38ad 100644 --- a/ESP32_AP-Flasher/src/udp.cpp +++ b/ESP32_AP-Flasher/src/udp.cpp @@ -1,13 +1,14 @@ +#include "udp.h" + #include #include #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);