diff --git a/ESP32_AP-Flasher/data/languages.json b/ESP32_AP-Flasher/data/languages.json index 2234a892..3998ced2 100644 --- a/ESP32_AP-Flasher/data/languages.json +++ b/ESP32_AP-Flasher/data/languages.json @@ -3,54 +3,63 @@ "language": "en", "daysShort": ["SU", "MO", "TU", "WE", "TH", "FR", "SA"], "days": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], - "months": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] + "months": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + "date_format": "%d-%m-%Y" }, "1": { "language": "nl", "daysShort": ["ZO", "MA", "DI", "WO", "DO", "VR", "ZA"], "days": ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"], - "months": ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"] + "months": ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"], + "date_format": "%d-%m-%Y" }, "2": { "language": "de", "daysShort": ["SO", "MO", "DI", "MI", "DO", "FR", "SA"], "days": ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], - "months": ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"] + "months": ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], + "date_format": "%d.%m.%Y" }, "3": { "language": "no", "daysShort": ["SØ", "MA", "TI", "ON", "TO", "FR", "LØ"], "days": ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"], - "months": ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"] + "months": ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"], + "date_format": "%d-%m-%Y" }, "5": { "language": "cz", "daysShort": ["NE", "PO", "ÚT", "ST", "ČT", "PÁ", "SO"], "days": ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota"], - "months": ["Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"] + "months": ["Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"], + "date_format": "%d-%m-%Y" }, "6": { "language": "sk", "daysShort": ["NE", "PO", "UT", "ST", "ŠT", "PI", "SO"], "days": ["Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota"], - "months": ["Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Oktober", "November", "December"] + "months": ["Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Oktober", "November", "December"], + "date_format": "%d-%m-%Y" }, "7": { "language": "pl", "daysShort": ["Ni", "Po", "Wt", "Śr", "Cz", "Pt", "So"], "days": ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"], - "months": ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"] + "months": ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"], + "date_format": "%d-%m-%Y" }, "8": { "language": "es", "daysShort": ["D", "L", "MA", "MI", "J", "V", "S"], "days": ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"], - "months": ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"] + "months": ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"], + "date_format": "%d-%m-%Y" }, "4": { "language": "fr", "daysShort": ["DI", "LU", "MA", "ME", "JE", "VE", "SA"], "days": ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"], - "months": ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Aout", "Septembre", "Octobre", "Novembre", "Decembre"] + "months": ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Aout", "Septembre", "Octobre", "Novembre", "Decembre"], + "date_format": "%d-%m-%Y" } } diff --git a/ESP32_AP-Flasher/include/language.h b/ESP32_AP-Flasher/include/language.h index edb2991d..abdaa247 100644 --- a/ESP32_AP-Flasher/include/language.h +++ b/ESP32_AP-Flasher/include/language.h @@ -5,5 +5,7 @@ extern String languageDaysShort[7]; extern String languageDays[7]; extern String languageMonth[12]; +extern String languageDateFormat; extern void updateLanguageFromConfig(); + diff --git a/ESP32_AP-Flasher/include/tag_db.h b/ESP32_AP-Flasher/include/tag_db.h index 526ded36..4dbf78b6 100644 --- a/ESP32_AP-Flasher/include/tag_db.h +++ b/ESP32_AP-Flasher/include/tag_db.h @@ -14,9 +14,10 @@ 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), 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), 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), 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) {} uint8_t mac[8]; + uint8_t version; String alias; uint32_t lastseen; uint32_t nextupdate; @@ -89,7 +90,7 @@ extern std::vector tagDB; extern std::unordered_map hwtype; extern std::unordered_map varDB; extern String tagDBtoJson(const uint8_t mac[8] = nullptr, uint8_t startPos = 0); -extern bool deleteRecord(const uint8_t mac[8]); +extern bool deleteRecord(const uint8_t mac[8], bool allVersions = true); extern void fillNode(JsonObject& tag, const tagRecord* taginfo); extern void saveDB(const String& filename); extern bool loadDB(const String& filename); @@ -111,5 +112,7 @@ extern HwType getHwType(const uint8_t id); /// @return false If not extern bool setVarDB(const std::string& key, const String& value, const bool notify = true); extern void cleanupCurrent(); +extern void pushTagInfo(tagRecord* taginfo); +extern void popTagInfo(const uint8_t mac[8] = nullptr); #pragma pack(pop) diff --git a/ESP32_AP-Flasher/include/util.h b/ESP32_AP-Flasher/include/util.h index 388de15e..e1ca76f7 100644 --- a/ESP32_AP-Flasher/include/util.h +++ b/ESP32_AP-Flasher/include/util.h @@ -92,6 +92,7 @@ static bool httpGetJson(String &url, JsonDocument &json, const uint16_t timeout, http.end(); if (error) { Serial.printf("[httpGetJson] JSON: %s\n", error.c_str()); + wsErr("[httpGetJson] JSON: " + String(error.c_str())); return false; } return true; diff --git a/ESP32_AP-Flasher/src/contentmanager.cpp b/ESP32_AP-Flasher/src/contentmanager.cpp index db12b4db..cf5fcb95 100644 --- a/ESP32_AP-Flasher/src/contentmanager.cpp +++ b/ESP32_AP-Flasher/src/contentmanager.cpp @@ -332,9 +332,7 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { } } } - cfgobj["filename"] = ""; taginfo->nextupdate = 3216153600; - taginfo->contentMode = 0; } else { taginfo->nextupdate = now + 300; } @@ -421,18 +419,18 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { } case 17: // tag command + { sendTagCommand(mac, cfgobj["cmd"].as(), (taginfo->isExternal == false)); - cfgobj["filename"] = ""; taginfo->nextupdate = 3216153600; - taginfo->contentMode = 0; break; + } case 18: // tag config + { prepareConfigFile(mac, cfgobj); - cfgobj["filename"] = ""; taginfo->nextupdate = 3216153600; - taginfo->contentMode = 0; break; + } case 19: // json template { @@ -1115,7 +1113,7 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa struct tm timeinfo; localtime_r(&now, &timeinfo); char dateString[40]; - strftime(dateString, sizeof(dateString), "%d-%m-%Y", &timeinfo); + strftime(dateString, sizeof(dateString), languageDateFormat.c_str(), &timeinfo); HTTPClient http; // logLine("http getCalFeed " + URL); diff --git a/ESP32_AP-Flasher/src/ips_display.cpp b/ESP32_AP-Flasher/src/ips_display.cpp index 92fb1f6f..a9f987ee 100644 --- a/ESP32_AP-Flasher/src/ips_display.cpp +++ b/ESP32_AP-Flasher/src/ips_display.cpp @@ -50,7 +50,7 @@ void TFTLog(String text) { int32_t findId(uint8_t mac[8]) { for (uint32_t c = 0; c < tagDB.size(); c++) { tagRecord* tag = tagDB.at(c); - if (memcmp(tag->mac, mac, 8) == 0) { + if (memcmp(tag->mac, mac, 8) == 0 && tag->version == 0) { return c; } } diff --git a/ESP32_AP-Flasher/src/language.cpp b/ESP32_AP-Flasher/src/language.cpp index 4f710916..fa405e4f 100644 --- a/ESP32_AP-Flasher/src/language.cpp +++ b/ESP32_AP-Flasher/src/language.cpp @@ -11,6 +11,7 @@ String languageDaysShort[7]; String languageDays[7]; String languageMonth[12]; +String languageDateFormat; int currentLanguage = 0; @@ -46,5 +47,6 @@ void updateLanguageFromConfig() { for (int i = 0; i < 12; ++i) { languageMonth[i] = languageObject["months"][i].as(); } + languageDateFormat = languageObject["date_format"].as(); } diff --git a/ESP32_AP-Flasher/src/newproto.cpp b/ESP32_AP-Flasher/src/newproto.cpp index 44973660..1f6d2e0e 100644 --- a/ESP32_AP-Flasher/src/newproto.cpp +++ b/ESP32_AP-Flasher/src/newproto.cpp @@ -423,6 +423,11 @@ void processXferComplete(struct espXferComplete* xfc, bool local) { contentFS->remove(dst_path); } } + if (taginfo->contentMode == 5 || taginfo->contentMode == 17 || taginfo->contentMode == 18) { + popTagInfo(xfc->src); + taginfo = tagRecord::findByMAC(xfc->src); + taginfo->nextupdate = now; + } } wsSendTaginfo(xfc->src, SYNC_TAGSTATUS); if (local) udpsync.netProcessXferComplete(xfc); @@ -573,7 +578,7 @@ void processTagReturnData(struct espTagReturnData* trd, uint8_t len, bool local) void refreshAllPending() { for (int16_t c = 0; c < tagDB.size(); c++) { tagRecord* taginfo = tagDB.at(c); - if (taginfo->pending) { + if (taginfo->pending && taginfo->version == 0) { clearPending(taginfo); taginfo->nextupdate = 0; memset(taginfo->md5, 0, 16 * sizeof(uint8_t)); @@ -714,7 +719,7 @@ void updateTaginfoitem(struct TagInfo* taginfoitem, IPAddress remoteIP) { bool checkMirror(struct tagRecord* taginfo, struct pendingData* pending) { for (int16_t c = 0; c < tagDB.size(); c++) { tagRecord* taginfo2 = tagDB.at(c); - if (taginfo2->contentMode == 20) { + if (taginfo2->contentMode == 20 && taginfo2->version == 0) { DynamicJsonDocument doc(500); deserializeJson(doc, taginfo2->modeConfigJson); JsonObject cfgobj = doc.as(); diff --git a/ESP32_AP-Flasher/src/tag_db.cpp b/ESP32_AP-Flasher/src/tag_db.cpp index 98f72700..f3b0201d 100644 --- a/ESP32_AP-Flasher/src/tag_db.cpp +++ b/ESP32_AP-Flasher/src/tag_db.cpp @@ -22,17 +22,17 @@ Config config; tagRecord* tagRecord::findByMAC(const uint8_t mac[8]) { for (tagRecord* tag : tagDB) { - if (memcmp(tag->mac, mac, 8) == 0) { + if (memcmp(tag->mac, mac, 8) == 0 && tag->version == 0) { return tag; } } return nullptr; } -bool deleteRecord(const uint8_t mac[8]) { +bool deleteRecord(const uint8_t mac[8], bool allVersions) { for (uint32_t c = 0; c < tagDB.size(); c++) { tagRecord* tag = tagDB.at(c); - if (memcmp(tag->mac, mac, 8) == 0) { + if (memcmp(tag->mac, mac, 8) == 0 && (allVersions || tag->version == 0)) { if (tag->data != nullptr) { free(tag->data); } @@ -74,7 +74,7 @@ String tagDBtoJson(const uint8_t mac[8], uint8_t startPos) { const tagRecord* taginfo = tagDB.at(c); const bool select = !mac || memcmp(taginfo->mac, mac, 8) == 0; - if (select) { + if (select && taginfo->version == 0) { JsonObject tag = tags.createNestedObject(); fillNode(tag, taginfo); if (mac) { @@ -154,12 +154,14 @@ void saveDB(const String& filename) { const tagRecord* taginfo = tagDB.at(c); doc.clear(); - JsonObject tag = doc.createNestedObject(); - fillNode(tag, taginfo); - if (c > 0) { - file.write(','); + if (taginfo->version == 0) { + JsonObject tag = doc.createNestedObject(); + fillNode(tag, taginfo); + if (c > 0) { + file.write(','); + } + serializeJsonPretty(doc, file); } - serializeJsonPretty(doc, file); } file.write(']'); @@ -448,4 +450,19 @@ void cleanupCurrent() { file = dir.openNextFile(); } dir.close(); -} \ No newline at end of file +} + +void pushTagInfo(tagRecord* taginfo) { + tagRecord* taginfo2 = new tagRecord(*taginfo); + taginfo2->version = 1; + tagDB.push_back(taginfo2); +} + +void popTagInfo(const uint8_t mac[8]) { + for (tagRecord* tag : tagDB) { + if (memcmp(tag->mac, mac, 8) == 0 && tag->version == 1) { + deleteRecord(mac, false); + tag->version = 0; + } + } +} diff --git a/ESP32_AP-Flasher/src/web.cpp b/ESP32_AP-Flasher/src/web.cpp index 786b57e7..1aab0829 100644 --- a/ESP32_AP-Flasher/src/web.cpp +++ b/ESP32_AP-Flasher/src/web.cpp @@ -100,7 +100,7 @@ void wsSendSysteminfo() { if (day != timeinfo.tm_mday) { day = timeinfo.tm_mday; char timeBuffer[80]; - strftime(timeBuffer, sizeof(timeBuffer), "%d-%m-%Y", &timeinfo); + strftime(timeBuffer, sizeof(timeBuffer), languageDateFormat.c_str(), &timeinfo); setVarDB("ap_date", timeBuffer); } setVarDB("ap_ip", WiFi.localIP().toString()); @@ -293,9 +293,14 @@ void init_web() { if (hex2mac(dst, mac)) { tagRecord *taginfo = tagRecord::findByMAC(mac); if (taginfo != nullptr) { + uint16_t newContentMode = atoi(request->getParam("contentmode", true)->value().c_str()); + if (newContentMode != taginfo->contentMode && (newContentMode == 5 || newContentMode == 17 || newContentMode == 18)) { + // temporary content, restore after sending + pushTagInfo(taginfo); + } taginfo->alias = request->getParam("alias", true)->value(); taginfo->modeConfigJson = request->getParam("modecfgjson", true)->value(); - taginfo->contentMode = atoi(request->getParam("contentmode", true)->value().c_str()); + taginfo->contentMode = newContentMode; taginfo->nextupdate = 0; if (request->hasParam("rotate", true)) { taginfo->rotate = atoi(request->getParam("rotate", true)->value().c_str());