From 59e2a5eeb82ef278407978e8be2c3e93ab99c81f Mon Sep 17 00:00:00 2001 From: Nic Limper Date: Mon, 18 Mar 2024 16:39:44 +0100 Subject: [PATCH] Various fixes - bugfix not recognizing identical image https://github.com/jjwbruijn/OpenEPaperLink/issues/255 - Count number of updates https://github.com/jjwbruijn/OpenEPaperLink/issues/247 - Optionally align interval of RSS/calendar/etc https://github.com/jjwbruijn/OpenEPaperLink/issues/106 --- ESP32_AP-Flasher/data/tag_md5_db.json | 9 +++++ ESP32_AP-Flasher/include/settings.h | 1 + ESP32_AP-Flasher/include/tag_db.h | 3 +- ESP32_AP-Flasher/src/contentmanager.cpp | 43 ++++++++++++--------- ESP32_AP-Flasher/src/newproto.cpp | 13 ++++--- ESP32_AP-Flasher/src/tag_db.cpp | 2 + ESP32_AP-Flasher/wwwroot/content_cards.json | 8 ++-- 7 files changed, 50 insertions(+), 29 deletions(-) diff --git a/ESP32_AP-Flasher/data/tag_md5_db.json b/ESP32_AP-Flasher/data/tag_md5_db.json index 4851340f..909cbe3b 100644 --- a/ESP32_AP-Flasher/data/tag_md5_db.json +++ b/ESP32_AP-Flasher/data/tag_md5_db.json @@ -71,6 +71,15 @@ "type":1, "note":"2.9 v032 FW" }, + { + "name": "2.9 White - 4rd", + "mac_offset": 64518, + "mac_format": 1, + "mac_suffix": "3B10", + "MD5": "52B8F6316BC2EB45231B23B2CD563B80", + "type": 1, + "note": "2.9 v031 FW" + }, { "name":"2.9 White + NFC UC8151", "mac_offset":64518, diff --git a/ESP32_AP-Flasher/include/settings.h b/ESP32_AP-Flasher/include/settings.h index b24c367d..12d542c8 100644 --- a/ESP32_AP-Flasher/include/settings.h +++ b/ESP32_AP-Flasher/include/settings.h @@ -13,4 +13,5 @@ // flasher options #define CUSTOM_MAC_HDR 0x0000 +#define MAX_XFER_ATTEMPTS 20 #define MAX_WRITE_ATTEMPTS 5 \ 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 b58fef74..540304f7 100644 --- a/ESP32_AP-Flasher/include/tag_db.h +++ b/ESP32_AP-Flasher/include/tag_db.h @@ -15,7 +15,7 @@ #define NO_SUBGHZ_CHANNEL 255 class tagRecord { public: - tagRecord() : mac{0}, version(0), alias(""), lastseen(0), nextupdate(0), contentMode(0), pendingCount(0), md5{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), apIp(IPAddress(0, 0, 0, 0)), pendingIdle(0), hasCustomLUT(false), rotate(0), lut(0), tagSoftwareVersion(0), currentChannel(0), dataType(0), filename(""), data(nullptr), len(0), invert(0) {} + tagRecord() : mac{0}, version(0), alias(""), lastseen(0), nextupdate(0), contentMode(0), pendingCount(0), md5{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), apIp(IPAddress(0, 0, 0, 0)), pendingIdle(0), hasCustomLUT(false), rotate(0), lut(0), tagSoftwareVersion(0), currentChannel(0), dataType(0), filename(""), data(nullptr), len(0), invert(0), updateCount(0) {} uint8_t mac[8]; uint8_t version; @@ -44,6 +44,7 @@ class tagRecord { uint16_t tagSoftwareVersion; uint8_t currentChannel; uint8_t invert; + uint32_t updateCount; uint8_t dataType; String filename; diff --git a/ESP32_AP-Flasher/src/contentmanager.cpp b/ESP32_AP-Flasher/src/contentmanager.cpp index e717d7f8..b206be5d 100644 --- a/ESP32_AP-Flasher/src/contentmanager.cpp +++ b/ESP32_AP-Flasher/src/contentmanager.cpp @@ -235,6 +235,17 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { imageParams.lut = EPD_LUT_OTA; } + int32_t interval = 60 * 60; + interval = cfgobj["interval"].as() * 60; + Serial.println("interval: " + String(interval)); + if (interval < 0) { + interval = -interval; + unsigned int secondsUntilNext = (interval - (now % interval)) % interval; + interval = secondsUntilNext; + Serial.println("seconds until next: " + String(interval)); + } else if (interval < 180) + interval = 60 * 60; + switch (taginfo->contentMode) { case 0: // Not configured case 22: // Static image @@ -363,13 +374,12 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { { const int httpcode = getImgURL(filename, cfgobj["url"], (time_t)cfgobj["#fetched"], imageParams, String(hexmac)); - const int interval = cfgobj["interval"].as(); if (httpcode == 200) { - taginfo->nextupdate = now + 60 * (interval < 3 ? 15 : interval); - updateTagImage(filename, mac, interval, taginfo, imageParams); + taginfo->nextupdate = now + interval; + updateTagImage(filename, mac, interval / 60, taginfo, imageParams); cfgobj["#fetched"] = now; } else if (httpcode == 304) { - taginfo->nextupdate = now + 60 * (interval < 3 ? 15 : interval); + taginfo->nextupdate = now + interval; } else { taginfo->nextupdate = now + 300; } @@ -380,9 +390,8 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { case 9: // RSSFeed if (getRssFeed(filename, cfgobj["url"], cfgobj["title"], taginfo, imageParams)) { - const int interval = cfgobj["interval"].as(); - taginfo->nextupdate = now + 60 * (interval < 3 ? 60 : interval); - updateTagImage(filename, mac, interval, taginfo, imageParams); + taginfo->nextupdate = now + interval; + updateTagImage(filename, mac, interval / 60, taginfo, imageParams); } else { taginfo->nextupdate = now + 300; } @@ -402,9 +411,8 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { case 11: // Calendar: if (getCalFeed(filename, cfgobj, taginfo, imageParams)) { - const int interval = cfgobj["interval"].as(); - taginfo->nextupdate = now + 60 * (interval < 3 ? 15 : interval); - updateTagImage(filename, mac, interval, taginfo, imageParams); + taginfo->nextupdate = now + interval; + updateTagImage(filename, mac, interval / 60, taginfo, imageParams); } else { taginfo->nextupdate = now + 300; } @@ -474,13 +482,12 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { DynamicJsonDocument json(1000); Serial.println("Get json url + file"); if (util::httpGetJson(configUrl, json, 1000)) { + taginfo->nextupdate = now + interval; if (getJsonTemplateFileExtractVariables(filename, configFilename, json, taginfo, imageParams)) { - updateTagImage(filename, mac, cfgobj["interval"].as(), taginfo, imageParams); + updateTagImage(filename, mac, interval / 60, taginfo, imageParams); } else { wsErr("error opening file " + configFilename); } - const int interval = cfgobj["interval"].as(); - taginfo->nextupdate = now + 60 * (interval < 3 ? 15 : interval); } else { taginfo->nextupdate = now + 600; } @@ -488,7 +495,7 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { } else { const bool result = getJsonTemplateFile(filename, configFilename, taginfo, imageParams); if (result) { - updateTagImage(filename, mac, cfgobj["interval"].as(), taginfo, imageParams); + updateTagImage(filename, mac, interval, taginfo, imageParams); } else { wsErr("error opening file " + configFilename); } @@ -496,13 +503,12 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { } } else { const int httpcode = getJsonTemplateUrl(filename, cfgobj["url"], (time_t)cfgobj["#fetched"], String(hexmac), taginfo, imageParams); - const int interval = cfgobj["interval"].as(); if (httpcode == 200) { - taginfo->nextupdate = now + 60 * (interval < 3 ? 15 : interval); - updateTagImage(filename, mac, interval, taginfo, imageParams); + taginfo->nextupdate = now + interval; + updateTagImage(filename, mac, interval / 60, taginfo, imageParams); cfgobj["#fetched"] = now; } else if (httpcode == 304) { - taginfo->nextupdate = now + 60 * (interval < 3 ? 15 : interval); + taginfo->nextupdate = now + interval; } else { taginfo->nextupdate = now + 600; } @@ -558,6 +564,7 @@ bool updateTagImage(String &filename, const uint8_t *dst, uint16_t nextCheckin, imageParams.dataType = DATATYPE_IMG_RAW_2BPP; Serial.println("datatype: DATATYPE_IMG_RAW_2BPP"); } + if (nextCheckin > 0x7fff) nextCheckin = 0; prepareDataAvail(filename, imageParams.dataType, imageParams.lut, dst, nextCheckin); } return true; diff --git a/ESP32_AP-Flasher/src/newproto.cpp b/ESP32_AP-Flasher/src/newproto.cpp index 79295597..c672f968 100644 --- a/ESP32_AP-Flasher/src/newproto.cpp +++ b/ESP32_AP-Flasher/src/newproto.cpp @@ -207,9 +207,8 @@ bool prepareDataAvail(String& filename, uint8_t dataType, uint8_t dataTypeArgume } file.close(); - uint16_t attempts = 60 * 24; - if (memcmp(md5bytes, taginfo->md5, 16) == 0) { + if (memcmp(md5bytes, taginfo->md5, 8) == 0) { wsLog("new image is the same as current image. not updating tag."); wsSendTaginfo(dst, SYNC_TAGSTATUS); if (contentFS->exists(filename) && resend == false) { @@ -251,7 +250,7 @@ bool prepareDataAvail(String& filename, uint8_t dataType, uint8_t dataTypeArgume pending.availdatainfo.dataSize = filesize; pending.availdatainfo.dataTypeArgument = dataTypeArgument; pending.availdatainfo.nextCheckIn = nextCheckin; - pending.attemptsLeft = attempts; + pending.attemptsLeft = MAX_XFER_ATTEMPTS; checkMirror(taginfo, &pending); queueDataAvail(&pending, !taginfo->isExternal); if (taginfo->isExternal == false) { @@ -453,6 +452,7 @@ void processXferComplete(struct espXferComplete* xfc, bool local) { } } memcpy(md5bytes, &queueItem->pendingdata.availdatainfo.dataVer, sizeof(uint64_t)); + memset(md5bytes + sizeof(uint64_t), 0, 16 - sizeof(uint64_t)); dequeueItem(xfc->src); } @@ -460,6 +460,7 @@ void processXferComplete(struct espXferComplete* xfc, bool local) { if (taginfo != nullptr) { clearPending(taginfo); memcpy(taginfo->md5, md5bytes, sizeof(md5bytes)); + taginfo->updateCount++; taginfo->pendingCount = countQueueItem(xfc->src); taginfo->wakeupReason = 0; if (taginfo->contentMode == 12 && local == false) { @@ -684,7 +685,7 @@ bool sendAPSegmentedData(const uint8_t* dst, String data, uint16_t icons, bool i memcpy((void*)&(pending.availdatainfo.dataVer), data.c_str(), 10); pending.availdatainfo.dataTypeArgument = inverted; pending.availdatainfo.nextCheckIn = 0; - pending.attemptsLeft = 120; + pending.attemptsLeft = MAX_XFER_ATTEMPTS; Serial.printf(">AP Segmented Data %02X%02X%02X%02X%02X%02X%02X%02X\n\0", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]); if (local) { return queueDataAvail(&pending, true); @@ -703,7 +704,7 @@ bool showAPSegmentedInfo(const uint8_t* dst, bool local) { pending.availdatainfo.dataVer = 0x00; pending.availdatainfo.dataTypeArgument = 0; pending.availdatainfo.nextCheckIn = 0; - pending.attemptsLeft = 120; + pending.attemptsLeft = MAX_XFER_ATTEMPTS; Serial.printf(">SDA %02X%02X%02X%02X%02X%02X%02X%02X\n\0", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]); if (local) { return queueDataAvail(&pending, true); @@ -724,7 +725,7 @@ bool sendTagCommand(const uint8_t* dst, uint8_t cmd, bool local, const uint8_t* memcpy(&pending.availdatainfo.dataVer, payload, sizeof(uint64_t)); memcpy(&pending.availdatainfo.dataSize, payload + sizeof(uint64_t), sizeof(uint32_t)); } - pending.attemptsLeft = 120; + pending.attemptsLeft = MAX_XFER_ATTEMPTS; Serial.printf(">Tag CMD %02X%02X%02X%02X%02X%02X%02X%02X\n\0", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]); tagRecord* taginfo = tagRecord::findByMAC(dst); diff --git a/ESP32_AP-Flasher/src/tag_db.cpp b/ESP32_AP-Flasher/src/tag_db.cpp index c394679c..fc785106 100644 --- a/ESP32_AP-Flasher/src/tag_db.cpp +++ b/ESP32_AP-Flasher/src/tag_db.cpp @@ -119,6 +119,7 @@ void fillNode(JsonObject& tag, const tagRecord* taginfo) { tag["rotate"] = taginfo->rotate; tag["lut"] = taginfo->lut; tag["invert"] = taginfo->invert; + tag["updatecount"] = taginfo->updateCount; tag["ch"] = taginfo->currentChannel; tag["ver"] = taginfo->tagSoftwareVersion; } @@ -226,6 +227,7 @@ bool loadDB(const String& filename) { taginfo->rotate = tag["rotate"] | 0; taginfo->lut = tag["lut"] | 0; taginfo->invert = tag["invert"] | 0; + taginfo->updateCount = tag["updatecount"] | 0; taginfo->currentChannel = tag["ch"] | 0; taginfo->tagSoftwareVersion = tag["ver"] | 0; } diff --git a/ESP32_AP-Flasher/wwwroot/content_cards.json b/ESP32_AP-Flasher/wwwroot/content_cards.json index d2938666..2fd95154 100644 --- a/ESP32_AP-Flasher/wwwroot/content_cards.json +++ b/ESP32_AP-Flasher/wwwroot/content_cards.json @@ -212,7 +212,7 @@ { "key": "interval", "name": "Interval", - "desc": "How often (in minutes) the feed is being refreshed", + "desc": "How often (in minutes) the feed is being refreshed. Negative value to align the interval (-60 is 'on the whole hour')", "type": "int" } ] @@ -231,7 +231,7 @@ { "key": "interval", "name": "Interval", - "desc": "How often (in minutes) the image is being fetched. Minimum is 3 minutes.", + "desc": "How often (in minutes) the image is being fetched. Minimum is 3 minutes. Negative value to align the interval (-60 is 'on the whole hour')", "type": "int" } ] @@ -276,7 +276,7 @@ { "key": "interval", "name": "Interval", - "desc": "How often (in minutes) the calendar is being refreshed", + "desc": "How often (in minutes) the calendar is being refreshed. Negative value to align the interval (-60 is 'on the whole hour')", "type": "int" } ] @@ -411,7 +411,7 @@ { "key": "interval", "name": "Interval", - "desc": "In case of an url, how often (in minutes) the template is being fetched. Minimum is 3 minutes.", + "desc": "In case of an url, how often (in minutes) the template is being fetched. Minimum is 3 minutes. Negative value to align the interval (-60 is 'on the whole hour')", "type": "int" } ]