From 49d86620bd2ddd1aa9a764fe924ddc0a2ce48a19 Mon Sep 17 00:00:00 2001 From: Nic Limper Date: Thu, 25 May 2023 14:28:54 +0200 Subject: [PATCH] preparations for custom LUT --- ESP32_AP-Flasher/data/gradient.jpg | Bin 0 -> 17002 bytes ESP32_AP-Flasher/data/www/content_cards.json | 17 +++++ ESP32_AP-Flasher/data/www/main.js | 6 +- ESP32_AP-Flasher/include/commstructs.h | 1 + ESP32_AP-Flasher/include/contentmanager.h | 3 +- ESP32_AP-Flasher/include/makeimage.h | 2 + ESP32_AP-Flasher/include/newproto.h | 2 +- ESP32_AP-Flasher/include/tag_db.h | 4 +- ESP32_AP-Flasher/src/contentmanager.cpp | 71 +++++++++++++++++-- ESP32_AP-Flasher/src/makeimage.cpp | 34 ++++++++- ESP32_AP-Flasher/src/newproto.cpp | 36 ++++------ 11 files changed, 142 insertions(+), 34 deletions(-) create mode 100644 ESP32_AP-Flasher/data/gradient.jpg diff --git a/ESP32_AP-Flasher/data/gradient.jpg b/ESP32_AP-Flasher/data/gradient.jpg new file mode 100644 index 0000000000000000000000000000000000000000..34300c0a9e2e6ff966ea3488fc63b84a8064f811 GIT binary patch literal 17002 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 { - //console.log(event.data) + console.log(event.data) const msg = JSON.parse(event.data); if (msg.logMsg) { showMessage(msg.logMsg, false); @@ -213,7 +213,7 @@ function updatecards() { if (item.dataset.lastseen && item.dataset.lastseen > 1672531200) { let idletime = (Date.now() / 1000) - servertimediff - item.dataset.lastseen; $('#tag' + tagmac + ' .lastseen').innerHTML = "last seen" + displayTime(Math.floor(idletime)) + " ago"; - if ((Date.now() / 1000) - servertimediff - 300 > item.dataset.nextcheckin) { + if ((Date.now() / 1000) - servertimediff - 600 > item.dataset.nextcheckin) { $('#tag' + tagmac + ' .warningicon').style.display = 'inline-block'; $('#tag' + tagmac).classList.remove("tagpending") $('#tag' + tagmac).style.background = '#e0e0a0'; diff --git a/ESP32_AP-Flasher/include/commstructs.h b/ESP32_AP-Flasher/include/commstructs.h index 3d02ec51..73732d25 100644 --- a/ESP32_AP-Flasher/include/commstructs.h +++ b/ESP32_AP-Flasher/include/commstructs.h @@ -48,6 +48,7 @@ struct espAvailDataReq { #define EPD_LUT_NO_REPEATS 1 #define EPD_LUT_FAST_NO_REDS 2 #define EPD_LUT_FAST 3 +#define EPD_LUT_OTA 0x10 struct AvailDataInfo { uint8_t checksum; diff --git a/ESP32_AP-Flasher/include/contentmanager.h b/ESP32_AP-Flasher/include/contentmanager.h index 3cbc0f2c..2af05e3e 100644 --- a/ESP32_AP-Flasher/include/contentmanager.h +++ b/ESP32_AP-Flasher/include/contentmanager.h @@ -33,5 +33,6 @@ char *formatHttpDate(time_t t); String urlEncode(const char *msg); int windSpeedToBeaufort(float windSpeed); String windDirectionIcon(int degrees); -String mac62hex(uint8_t *mac); void getLocation(JsonObject &cfgobj); +void prepareNFCReq(uint8_t* dst, const char* url); +void prepareLUTreq(uint8_t *dst, String input); \ No newline at end of file diff --git a/ESP32_AP-Flasher/include/makeimage.h b/ESP32_AP-Flasher/include/makeimage.h index b9369d18..165a2f2e 100644 --- a/ESP32_AP-Flasher/include/makeimage.h +++ b/ESP32_AP-Flasher/include/makeimage.h @@ -7,6 +7,8 @@ struct imgParam { bool hasRed; uint8_t dataType; bool dither; + bool grayLut = false; + char segments[12]; uint16_t symbols; bool invert; diff --git a/ESP32_AP-Flasher/include/newproto.h b/ESP32_AP-Flasher/include/newproto.h index e8758464..a0348c8f 100644 --- a/ESP32_AP-Flasher/include/newproto.h +++ b/ESP32_AP-Flasher/include/newproto.h @@ -5,7 +5,7 @@ extern bool checkCRC(void* p, uint8_t len); extern void processBlockRequest(struct espBlockRequest* br); extern void prepareIdleReq(uint8_t* dst, uint16_t nextCheckin); -extern void prepareNFCReq(uint8_t* dst, const char* url); +extern void prepareDataAvail(uint8_t* data, uint16_t len, uint8_t dataType, uint8_t* dst); extern bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t nextCheckin); extern void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP); extern void processXferComplete(struct espXferComplete* xfc, bool local); diff --git a/ESP32_AP-Flasher/include/tag_db.h b/ESP32_AP-Flasher/include/tag_db.h index 3ce6c409..b49ae093 100644 --- a/ESP32_AP-Flasher/include/tag_db.h +++ b/ESP32_AP-Flasher/include/tag_db.h @@ -13,7 +13,7 @@ class tagRecord { public: - tagRecord() : mac{0}, alias(""), lastseen(0), nextupdate(0), contentMode(0), pending(false), md5{0}, md5pending{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), pendingIdle(0), + tagRecord() : mac{0}, alias(""), lastseen(0), nextupdate(0), contentMode(0), pending(false), md5{0}, md5pending{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), pendingIdle(0), hasCustomLUT(false), filename(""), data(nullptr), len(0) {} uint8_t mac[8]; @@ -36,7 +36,7 @@ class tagRecord { uint32_t lastfullupdate; bool isExternal; uint16_t pendingIdle; - + bool hasCustomLUT; String filename; uint8_t* data; uint32_t len; diff --git a/ESP32_AP-Flasher/src/contentmanager.cpp b/ESP32_AP-Flasher/src/contentmanager.cpp index 452f7e89..4db48a59 100644 --- a/ESP32_AP-Flasher/src/contentmanager.cpp +++ b/ESP32_AP-Flasher/src/contentmanager.cpp @@ -1,19 +1,30 @@ #include "contentmanager.h" +// possibility to turn off, to save space if needed +#define CONTENT_QR +#define CONTENT_RSS +#define CONTENT_CAL + #include #include #include #include #include +#ifdef CONTENT_RSS #include +#endif #include #include +#if defined CONTENT_RSS || defined CONTENT_CAL #include "U8g2_for_TFT_eSPI.h" +#endif #include "commstructs.h" #include "makeimage.h" #include "newproto.h" +#ifdef CONTENT_QR #include "qrcode.h" +#endif #include "tag_db.h" #include "settings.h" #include "web.h" @@ -95,6 +106,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) { imageParams.hasRed = false; imageParams.dataType = DATATYPE_IMG_RAW_1BPP; imageParams.dither = true; + if (taginfo->hasCustomLUT) imageParams.grayLut = true; imageParams.invert = false; imageParams.symbols = 0; @@ -108,7 +120,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) { if (imageParams.hasRed) imageParams.dataType = DATATYPE_IMG_RAW_2BPP; if (prepareDataAvail(&filename, imageParams.dataType, mac, cfgobj["timetolive"].as())) { cfgobj["#fetched"] = true; - if (cfgobj["delete"].as()) LittleFS.remove("/"+cfgobj["filename"].as()); + if (cfgobj["delete"].as()=="1") LittleFS.remove("/"+cfgobj["filename"].as()); } else { wsErr("Error accessing " + filename); } @@ -237,10 +249,15 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) { case 14: // NFC URL taginfo->nextupdate = 3216153600; - memset(taginfo->md5, 0, 16 * sizeof(uint8_t)); - memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t)); prepareNFCReq(mac, cfgobj["url"].as()); break; + + case 15: // send gray LUT + + taginfo->nextupdate = 3216153600; + prepareLUTreq(mac, cfgobj["bytes"]); + taginfo->hasCustomLUT = true; + break; } taginfo->modeConfigJson = doc.as(); @@ -783,9 +800,12 @@ bool getImgURL(String &filename, String URL, time_t fetched, imgParam &imagePara return (httpCode == 200 || httpCode == 304); } +#ifdef CONTENT_RSS rssClass reader; +#endif bool getRssFeed(String &filename, String URL, String title, tagRecord *&taginfo, imgParam &imageParams) { +#ifdef CONTENT_RSS // https://github.com/garretlab/shoddyxml2 // http://feeds.feedburner.com/tweakers/nieuws @@ -854,6 +874,7 @@ bool getRssFeed(String &filename, String URL, String title, tagRecord *&taginfo, spr2buffer(spr, filename, imageParams); spr.deleteSprite(); +#endif return true; } @@ -878,6 +899,7 @@ char *epoch_to_display(time_t utc) { } bool getCalFeed(String &filename, String URL, String title, tagRecord *&taginfo, imgParam &imageParams) { +#ifdef CONTENT_CAL // google apps scripts method to retrieve calendar // see /data/calendar.txt for description @@ -988,11 +1010,12 @@ bool getCalFeed(String &filename, String URL, String title, tagRecord *&taginfo, spr2buffer(spr, filename, imageParams); spr.deleteSprite(); - +#endif return true; } void drawQR(String &filename, String qrcontent, String title, tagRecord *&taginfo, imgParam &imageParams) { +#ifdef CONTENT_QR TFT_eSPI tft = TFT_eSPI(); TFT_eSprite spr = TFT_eSprite(&tft); LittleFS.begin(); @@ -1037,6 +1060,7 @@ void drawQR(String &filename, String qrcontent, String title, tagRecord *&taginf spr2buffer(spr, filename, imageParams); spr.deleteSprite(); +#endif } char *formatHttpDate(time_t t) { @@ -1111,4 +1135,41 @@ void getLocation(JsonObject &cfgobj) { cfgobj["#tz"] = tz; } } -} \ No newline at end of file +} + +void prepareNFCReq(uint8_t *dst, const char *url) { + uint8_t *data; + size_t len = strlen(url); + data = new uint8_t[len + 8]; + + // TLV + data[0] = 0x03; // NDEF message (TLV type) + data[1] = 4 + len + 1; + // ndef record + data[2] = 0xD1; + data[3] = 0x01; // well known record type + data[4] = len + 1; // payload length + data[5] = 0x55; // payload type (URI record) + data[6] = 0x00; // URI identifier code (no prepending) + + memcpy(data + 7, reinterpret_cast(url), len); + len = 7 + len; + data[len] = 0xFE; + len = 1 + len; + prepareDataAvail(data, len, DATATYPE_NFC_RAW_CONTENT, dst); +} + +void prepareLUTreq(uint8_t *dst, String input) { + const char *delimiters = ", \t"; + const int maxValues = 70; + uint8_t waveform[maxValues]; + char *ptr = strtok(const_cast(input.c_str()), delimiters); + int i = 0; + while (ptr != nullptr && i < maxValues) { + waveform[i++] = static_cast(strtol(ptr, nullptr, 16)); + ptr = strtok(nullptr, delimiters); + } + Serial.println(String(i) + " bytes found"); + size_t waveformLen = sizeof(waveform); + prepareDataAvail(waveform, waveformLen, DATATYPE_CUSTOM_LUT_OTA, dst); +} diff --git a/ESP32_AP-Flasher/src/makeimage.cpp b/ESP32_AP-Flasher/src/makeimage.cpp index 3408b6b6..168af98f 100644 --- a/ESP32_AP-Flasher/src/makeimage.cpp +++ b/ESP32_AP-Flasher/src/makeimage.cpp @@ -116,6 +116,11 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) { {0, 0, 0}, // Black {255, 0, 0} // Red }; + if (imageParams.grayLut) { + Color newColor = {150, 150, 150}; + palette.push_back(newColor); + Serial.println("rendering with gray"); + } int num_colors = palette.size(); Color color; Error *error_bufferold = new Error[bufw]; @@ -143,13 +148,40 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) { uint16_t bitIndex = 7 - (x % 8); uint16_t byteIndex = (y * bufw + x) / 8; + + // this looks a bit ugly, but it's performing better than shorter notations + switch (best_color_index) { + case 1: + blackBuffer[byteIndex] |= (1 << bitIndex); + break; + case 2: + imageParams.hasRed = true; + redBuffer[byteIndex] |= (1 << bitIndex); + break; + case 3: + blackBuffer[byteIndex] |= (1 << bitIndex); + redBuffer[byteIndex] |= (1 << bitIndex); + imageParams.hasRed = true; + break; + } + /* + alt 1: + if (best_color_index & 1) { blackBuffer[byteIndex] |= (1 << bitIndex); - } else if (best_color_index & 2) { + } + if (best_color_index & 2) { imageParams.hasRed = true; redBuffer[byteIndex] |= (1 << bitIndex); } + alt 2: + + blackBuffer[byteIndex] |= ((best_color_index & 1) << bitIndex); + redBuffer[byteIndex] |= ((best_color_index & 2) << bitIndex); + imageParams.hasRed |= (best_color_index & 2); + */ + if (imageParams.dither) { Error error = { ((float)color.r + error_bufferold[x].r - palette[best_color_index].r) / 16.0f, diff --git a/ESP32_AP-Flasher/src/newproto.cpp b/ESP32_AP-Flasher/src/newproto.cpp index 4bbfd12d..ea9ecb76 100644 --- a/ESP32_AP-Flasher/src/newproto.cpp +++ b/ESP32_AP-Flasher/src/newproto.cpp @@ -79,7 +79,7 @@ void prepareIdleReq(uint8_t* dst, uint16_t nextCheckin) { } } -void prepareNFCReq(uint8_t* dst, const char* url) { +void prepareDataAvail(uint8_t* data, uint16_t len, uint8_t dataType, uint8_t* dst) { tagRecord* taginfo = nullptr; taginfo = tagRecord::findByMAC(dst); if (taginfo == nullptr) { @@ -88,32 +88,22 @@ void prepareNFCReq(uint8_t* dst, const char* url) { } clearPending(taginfo); - size_t len = strlen(url); - taginfo->data = new uint8_t[len + 8]; - - // TLV - taginfo->data[0] = 0x03; // NDEF message (TLV type) - taginfo->data[1] = 4 + len + 1; - - // ndef record - taginfo->data[2] = 0xD1; - taginfo->data[3] = 0x01; // well known record type - taginfo->data[4] = len + 1; // payload length - taginfo->data[5] = 0x55; // payload type (URI record) - taginfo->data[6] = 0x00; // URI identifier code (no prepending) - - memcpy(taginfo->data + 7, reinterpret_cast(url), len); - len = 7 + len; - taginfo->data[len] = 0xFE; - len = 1 + len; - + taginfo->data = (uint8_t*)malloc(len); + if (taginfo->data == nullptr) { + wsErr("no memory allocation for data"); + return; + } + memcpy(taginfo->data, data, len); taginfo->pending = true; taginfo->len = len; + taginfo->expectedNextCheckin = 0; + taginfo->filename = String(); + memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t)); struct pendingData pending = {0}; memcpy(pending.targetMac, dst, 8); pending.availdatainfo.dataSize = len; - pending.availdatainfo.dataType = DATATYPE_NFC_RAW_CONTENT; + pending.availdatainfo.dataType = dataType; pending.availdatainfo.nextCheckIn = 0; pending.availdatainfo.dataVer = millis(); pending.attemptsLeft = 10; @@ -182,6 +172,10 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t lut = EPD_LUT_DEFAULT; // full update once a day taginfo->lastfullupdate = now; } + if (taginfo->hasCustomLUT && taginfo->capabilities & CAPABILITY_SUPPORTS_CUSTOM_LUTS) { + Serial.println("using custom LUT"); + lut = EPD_LUT_OTA; + } if (dataType != DATATYPE_FW_UPDATE) { char dst_path[64];