From df783c6f8f7f86bd6310e291f5d3af4f5ca6a62d Mon Sep 17 00:00:00 2001 From: Nic Limper Date: Thu, 3 Aug 2023 12:37:29 +0200 Subject: [PATCH] ability to mirror tags mirrored tags don't take file system space (f they are local to the AP), and don't take time to generate. They share their buffer with the source tag. --- ESP32_AP-Flasher/include/newproto.h | 1 + ESP32_AP-Flasher/src/newproto.cpp | 65 ++++++++++++++++++++- ESP32_AP-Flasher/src/tag_db.cpp | 9 ++- ESP32_AP-Flasher/src/web.cpp | 1 - ESP32_AP-Flasher/wwwroot/content_cards.json | 19 ++++++ ESP32_AP-Flasher/wwwroot/main.js | 4 +- 6 files changed, 93 insertions(+), 6 deletions(-) diff --git a/ESP32_AP-Flasher/include/newproto.h b/ESP32_AP-Flasher/include/newproto.h index f003a41b..a52b30bd 100644 --- a/ESP32_AP-Flasher/include/newproto.h +++ b/ESP32_AP-Flasher/include/newproto.h @@ -16,6 +16,7 @@ extern bool sendTagCommand(uint8_t* dst, uint8_t cmd, bool local); extern bool sendAPSegmentedData(uint8_t* dst, String data, uint16_t icons, bool inverted, bool local); extern bool showAPSegmentedInfo(uint8_t* dst, bool local); extern void updateTaginfoitem(struct TagInfo* taginfoitem); +bool checkMirror(struct tagRecord* taginfo, struct pendingData* pending); void refreshAllPending(); void updateContent(uint8_t* dst); diff --git a/ESP32_AP-Flasher/src/newproto.cpp b/ESP32_AP-Flasher/src/newproto.cpp index d587c62b..92d8080c 100644 --- a/ESP32_AP-Flasher/src/newproto.cpp +++ b/ESP32_AP-Flasher/src/newproto.cpp @@ -215,6 +215,7 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t pending.availdatainfo.dataTypeArgument = lut; pending.availdatainfo.nextCheckIn = nextCheckin; pending.attemptsLeft = attempts; + checkMirror(taginfo, &pending); if (taginfo->isExternal == false) { char buffer[64]; sprintf(buffer, ">SDA %02X%02X%02X%02X%02X%02X%02X%02X TYPE 0x%02X\n\0", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0], pending.availdatainfo.dataType); @@ -315,6 +316,7 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) { } taginfo->contentMode = 12; taginfo->nextupdate = 3216153600; + checkMirror(taginfo, pending); sendDataAvail(pending); wsSendTaginfo(pending->targetMac, SYNC_NOSYNC); @@ -613,8 +615,6 @@ bool sendTagCommand(uint8_t* dst, uint8_t cmd, bool local) { } } - - void updateTaginfoitem(struct TagInfo* taginfoitem) { tagRecord* taginfo = nullptr; taginfo = tagRecord::findByMAC(taginfoitem->mac); @@ -661,4 +661,63 @@ void updateTaginfoitem(struct TagInfo* taginfoitem) { wsSendTaginfo(taginfo->mac, SYNC_NOSYNC); } } -} \ No newline at end of file +} + +bool checkMirror(struct tagRecord* taginfo, struct pendingData* pending) { + for (int16_t c = 0; c < tagDB.size(); c++) { + tagRecord* taginfo2 = nullptr; + taginfo2 = tagDB.at(c); + if (taginfo2->contentMode == 20) { + DynamicJsonDocument doc(500); + deserializeJson(doc, taginfo2->modeConfigJson); + JsonObject cfgobj = doc.as(); + uint8_t mac[8] = {0}; + if (hex2mac(cfgobj["mac"], mac) && memcmp(mac, taginfo->mac, sizeof(mac)) == 0) { + + if (taginfo->data == nullptr) { + fs::File file = contentFS->open(taginfo->filename); + if (!file) { + return false; + } + taginfo->data = getDataForFile(&file); + file.close(); + } + + clearPending(taginfo2); + taginfo2->expectedNextCheckin = taginfo->expectedNextCheckin; + taginfo2->filename = taginfo->filename; + taginfo2->len = taginfo->len; + taginfo2->data = taginfo->data; // copy buffer pointer + taginfo2->dataType = taginfo->dataType; + taginfo2->pending = true; + taginfo2->nextupdate = 3216153600; + memcpy(taginfo2->md5pending, taginfo->md5pending, sizeof(taginfo->md5pending)); + + struct pendingData pending2 = {0}; + memcpy(pending2.targetMac, taginfo2->mac, 8); + pending2.availdatainfo.dataType = taginfo2->dataType; + pending2.availdatainfo.dataVer = *((uint64_t*)taginfo2->md5pending); + pending2.availdatainfo.dataSize = taginfo2->len; + pending2.availdatainfo.dataTypeArgument = pending->availdatainfo.dataTypeArgument; + pending2.availdatainfo.nextCheckIn = pending->availdatainfo.nextCheckIn; + pending2.attemptsLeft = pending->attemptsLeft; + + if (taginfo2->isExternal == false) { + sendDataAvail(&pending2); + } else { + char dst_path[64]; + sprintf(dst_path, "/current/%02X%02X%02X%02X%02X%02X%02X%02X.pending\0", taginfo2->mac[7], taginfo2->mac[6], taginfo2->mac[5], taginfo2->mac[4], taginfo2->mac[3], taginfo2->mac[2], taginfo2->mac[1], taginfo2->mac[0]); + File file = contentFS->open(dst_path, "w"); + if (file) { + file.write(taginfo2->data, taginfo2->len); + file.close(); + udpsync.netSendDataAvail(&pending2); + } + } + + wsSendTaginfo(taginfo2->mac, SYNC_TAGSTATUS); + } + } + } + return false; +} diff --git a/ESP32_AP-Flasher/src/tag_db.cpp b/ESP32_AP-Flasher/src/tag_db.cpp index ac985e6a..da3b5788 100644 --- a/ESP32_AP-Flasher/src/tag_db.cpp +++ b/ESP32_AP-Flasher/src/tag_db.cpp @@ -261,8 +261,15 @@ uint8_t getTagCount() { void clearPending(tagRecord* taginfo) { taginfo->filename = String(); if (taginfo->data != nullptr) { - free(taginfo->data); + + //check if this is the last copy of the buffer + int datacount = 0; + for (int16_t c = 0; c < tagDB.size(); c++) { + if (tagDB.at(c)->data == taginfo->data) datacount++; + } + if (datacount == 1) free(taginfo->data); taginfo->data = nullptr; + } taginfo->pending = false; } diff --git a/ESP32_AP-Flasher/src/web.cpp b/ESP32_AP-Flasher/src/web.cpp index 744bed06..ea9ba69a 100644 --- a/ESP32_AP-Flasher/src/web.cpp +++ b/ESP32_AP-Flasher/src/web.cpp @@ -9,7 +9,6 @@ #include #include -#include "ArduinoJson.h" #include "AsyncJson.h" #include "LittleFS.h" #include "SPIFFSEditor.h" diff --git a/ESP32_AP-Flasher/wwwroot/content_cards.json b/ESP32_AP-Flasher/wwwroot/content_cards.json index eb8a9ed1..2e199656 100644 --- a/ESP32_AP-Flasher/wwwroot/content_cards.json +++ b/ESP32_AP-Flasher/wwwroot/content_cards.json @@ -554,5 +554,24 @@ } } ] + }, + { + "id": 20, + "name": "Display a copy", + "desc": "Mirror the contents of a source tag to this destination tag, regardless of the content. The two tags should be of the same type. Ideally, the destination tag is local to the AP.", + "hwtype": [ + 0, + 1, + 2, + 17 + ], + "param": [ + { + "key": "mac", + "name": "Mac-address", + "desc": "Mac-address of the tag you want to use as content source. The source tag should either be associated with this access point, or this access point should be the content source.", + "type": "text" + } + ] } ] \ No newline at end of file diff --git a/ESP32_AP-Flasher/wwwroot/main.js b/ESP32_AP-Flasher/wwwroot/main.js index 2e2e1e27..b4758926 100644 --- a/ESP32_AP-Flasher/wwwroot/main.js +++ b/ESP32_AP-Flasher/wwwroot/main.js @@ -237,7 +237,9 @@ function processTags(tagArray) { $('#tag' + tagmac + ' .received').style.opacity = "0"; } - if (div.dataset.hash != element.hash && div.dataset.hwtype > -1 && (element.isexternal == false || element.contentMode != 12)) { + if (element.contentMode == 20) { + $('#tag' + tagmac + ' .tagimg').style.display = 'none'; + } else if (div.dataset.hash != element.hash && div.dataset.hwtype > -1 && (element.isexternal == false || element.contentMode != 12)) { loadImage(tagmac, '/current/' + tagmac + '.raw?' + element.hash); div.dataset.hash = element.hash; }