From e4a106ee2346ab7e212ea2d2362288377f0d9f11 Mon Sep 17 00:00:00 2001 From: Nic Limper Date: Mon, 30 Jan 2023 23:40:14 +0100 Subject: [PATCH] tag database, web interface. Caution, this crashes. Investigating. --- esp32_fw/.vscode/settings.json | 54 +++++++++++++- esp32_fw/data/index.html | 47 +++++++++++- esp32_fw/data/main.css | 71 +++++++++++++++++-- esp32_fw/data/main.js | 126 ++++++++++++++++++++++++++------- esp32_fw/include/tag_db.h | 36 ++++++++++ esp32_fw/include/web.h | 9 +-- esp32_fw/src/main.cpp | 22 +++--- esp32_fw/src/newproto.cpp | 46 ++++++++++-- esp32_fw/src/tag_db.cpp | 51 +++++++++++++ esp32_fw/src/web.cpp | 78 +++++++++++++++++--- tag_fw/make.bat | 16 ++++- 11 files changed, 493 insertions(+), 63 deletions(-) create mode 100644 esp32_fw/include/tag_db.h create mode 100644 esp32_fw/src/tag_db.cpp diff --git a/esp32_fw/.vscode/settings.json b/esp32_fw/.vscode/settings.json index 5f294ebf..ea185af3 100644 --- a/esp32_fw/.vscode/settings.json +++ b/esp32_fw/.vscode/settings.json @@ -1,3 +1,55 @@ { - "C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0}" + "C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0}", + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "regex": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp" + } } \ No newline at end of file diff --git a/esp32_fw/data/index.html b/esp32_fw/data/index.html index 1bdff43b..ea1ffddd 100644 --- a/esp32_fw/data/index.html +++ b/esp32_fw/data/index.html @@ -14,6 +14,41 @@ +
+
+

00000000

+

+ + +

+

+ + +

+

+ + +

+

+ + +

+
+
@@ -60,19 +95,25 @@
+
- last: + last:
+
-

logging

+

+ logging + + +

diff --git a/esp32_fw/data/main.css b/esp32_fw/data/main.css index ea4e65c6..f7ae66c3 100644 --- a/esp32_fw/data/main.css +++ b/esp32_fw/data/main.css @@ -3,7 +3,6 @@ padding:0; border:0; list-style-type: none; - -webkit-appearance: none; outline: none; font-weight: 400; -webkit-box-sizing: border-box; @@ -76,19 +75,61 @@ label { background-color: white; } -.actionbox input { - border: solid 1px black; +input { + border: solid 1px #666666; padding: 4px; } -.actionbox input[type=button] { +input[type=button] { border: 0px; padding: 4px; cursor:pointer; } -.actionbox input[type=button]:hover { +input[type=button]:hover { background-color:#aaaaaa; } +select { + padding: 4px; +} + +#configbox { + display: none; + position: fixed; + top: 80px; + left: 50px; + width: 500px; + padding: 15px; + background-color: #f0e6d3; + z-index: 999; + box-shadow: 7px 10px 52px -19px rgba(0, 0, 0, 0.63); +} + +#configbox p { + padding: 5px; +} + +#configbox h3 { + font-size: 1.5em; + font-weight: bold; +} + +#cfgdelete { + position: absolute; + bottom: 15px; + right: 15px; + cursor:pointer; +} + +.closebtn { + border: 1px solid black; + float: right; + width: 19px; + height: 20px; + font-size: 1.1em; + text-align: center; + margin: 5px; + cursor: pointer; +} .logbox { margin: 5px; @@ -104,13 +145,21 @@ label { cursor:pointer; } +.logbox #sysinfo { + float: right; +} + .taglist { display: flex; flex-wrap: wrap; } +#tagtemplate { + display:none; +} + .tagcard { - width: 220px; + width: 225px; position: relative; height: 170px; margin: 5px; @@ -151,6 +200,16 @@ label { background-image: url("data: image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAQAAAAngNWGAAABXklEQVQoz43SP2tUQRQF8N99ecFKFEVh0Y1ZbFQ2xEoIQkoLW0t7C/OVLGzyHay1EAQjRFGrLMkjKSwWsRGV3WvxZvc9XQtnivl35sydc048nfuvVkW0k8XYtT936pVja5jJv/Z7wPZo0wNzLzQSHWnVwTZtqY1su2to3bZhj7dewEYeu+iDawi7bhn7Yl9TWGsikrzksnNxr9zfsIErcaEAMysyZXrvE5mp6w7zc8rMzFJjGNlxFWHmWKMVd2DHsHuadQ+NkcKxZ2pPXC8FHHhu1v91X6ZcUZHYy8xwwyju5wAzJypDFdHka5OiaN1yHDl100BaMyq84cwrs1JjtTBu7E5xIpeebLndOZOlnK859d1bZ0JoHPiRU986ZxYZmdjP8/HRrkfSS2+MTTXlycyawhlHJBOH5k789A6x/H/sZQuMKKNatjGLvkoreUy/lsnsq1mXJOe/Ut6tM38DZpmDFxwTi8EAAAAASUVORK5CYII="); } +.warningicon { + display:none; + font-size: 1.3em; + background-color: yellow; + color: black; + height: 20px; + width: 20px; + vertical-align: top; + text-align: center; +} ul.messages { padding: 5px; diff --git a/esp32_fw/data/main.js b/esp32_fw/data/main.js index a7f90d92..64410a45 100644 --- a/esp32_fw/data/main.js +++ b/esp32_fw/data/main.js @@ -1,6 +1,21 @@ const $ = document.querySelector.bind(document); +const contentModes = ["static image", "current date", "count days", "count hours","current weather","public transport","memo text"]; +const models = ["unknown", "1.54\" 152x152px", "2.9\" 296x128px", "4.2\" 400x300px"]; + + let socket; +connect(); +setInterval(updatecards, 1000); +window.addEventListener("load", function () { + fetch("/get_db") + .then(response => response.json()) + .then(data => { + processTags(data.tags); + }) + .catch(error => showMessage('Error: ' + error)); +}); + function connect() { socket = new WebSocket("ws://" + location.host + "/ws"); @@ -10,7 +25,7 @@ function connect() { }); socket.addEventListener("message", (event) => { - console.log(event.data) + console.log(event.data); const msg = JSON.parse(event.data); if (msg.logMsg) { showMessage(msg.logMsg); @@ -18,6 +33,9 @@ function connect() { if (msg.tags) { processTags(msg.tags); } + if (msg.sys) { + $('#sysinfo').innerHTML = 'free heap: ' + msg.sys.heap + ' bytes ┇ db size: ' + msg.sys.dbsize + ' bytes ┇ db record count: ' + msg.sys.recordcount + ' ┇ littlefs free: ' + msg.sys.littlefsfree + ' bytes'; + } }); socket.addEventListener("close", (event) => { @@ -26,40 +44,65 @@ function connect() { }); } -connect(); - function processTags(tagArray) { - var date = new Date(), - dateString = date.toLocaleDateString('nl-NL', { day: '2-digit', month: '2-digit', year: 'numeric' }), - time = date.toLocaleTimeString('nl-NL', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' }); for (const element of tagArray) { tagmac = element.mac; - if ($('#tag' + tagmac) == null) { - const div = $('#tagtemplate').cloneNode(true); + + var div = $('#tag' + tagmac); + if (div == null) { + + div = $('#tagtemplate').cloneNode(true); div.setAttribute('id', 'tag'+tagmac); div.dataset.mac = tagmac; $('#taglist').appendChild(div); + $('#tag' + tagmac + ' .mac').innerHTML = tagmac; - $('#tag' + tagmac + ' .alias').innerHTML = tagmac; - $('#tag' + tagmac + ' .lastseen').innerHTML = dateString+' '+time; - var img = $('#tag' + tagmac + ' .tagimg') + var img = $('#tag' + tagmac + ' .tagimg'); img.addEventListener('error', function handleError() { img.style.display = 'none'; }); - img.style.display = 'block'; - img.src = '/edit?edit=current/' + tagmac +'.bmp'; - //+'
button: '+element.buttonstate - $('#taglist').appendChild(div); - } else { - $('#tag' + tagmac + ' .lastseen').innerHTML = dateString + ' ' + time; - var img = $('#tag' + tagmac + ' .tagimg') - img.style.display = 'block'; - img.src = '/edit?edit=current/' + tagmac + '.bmp&' + date; - } - console.log(element.buttonstate); + } + + div.style.display = 'block'; + + let alias = element.alias; + if (!alias) alias = tagmac; + $('#tag' + tagmac + ' .alias').innerHTML = alias; + + var img = $('#tag' + tagmac + ' .tagimg'); + img.style.display = 'block'; + img.src = '/edit?edit=current/' + tagmac + '.bmp&' + (new Date()).getTime(); + + $('#tag' + tagmac + ' .contentmode').innerHTML = contentModes[element.contentmode]; + $('#tag' + tagmac + ' .model').innerHTML = models[element.model]; + + var date = new Date(element.nextupdate * 1000); + var options = { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + $('#tag' + tagmac + ' .nextupdate').innerHTML = date.toLocaleString('nl-NL', options).replace(',', ''); + + date = new Date(element.lastseen * 1000); + var options = { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false}; + $('#tag' + tagmac + ' .lastseen').innerHTML = date.toLocaleString('nl-NL', options).replace(',', ''); + + div.dataset.lastseen = element.lastseen; + div.dataset.lastseenlocaltime = Date.now(); + $('#tag' + tagmac + ' .warningicon').style.display = 'none'; + + if (element.pending) $('#tag' + tagmac + ' .pending').innerHTML = "pending..."; else $('#tag' + tagmac + ' .pending').innerHTML = ""; + } } +function updatecards() { + document.querySelectorAll('[data-mac]').forEach(item => { + var tagmac = item.dataset.mac; + var idletime = Date.now() - item.dataset.lastseenlocaltime; + $('#tag' + tagmac + ' .idletime').innerHTML = int(idletime); + if (idletime > 300000) $('#tag' + tagmac + ' .warningicon').style.display='inline-block'; + if (idletime > 1800000) $('#tag' + tagmac).style.display = 'none'; + }) +} + $('#send_image').onclick = function() { let formData = new FormData(); formData.append("dst", $("#dstmac").value); @@ -103,6 +146,10 @@ $('#clearlog').onclick = function () { $('#messages').innerHTML=''; } +$('.closebtn').onclick = function (event) { + event.target.parentNode.style.display='none'; +} + $('#taglist').addEventListener("click", (event) => { let currentElement = event.target; while (currentElement !== $('#taglist')) { @@ -119,10 +166,41 @@ $('#taglist').addEventListener("click", (event) => { $('#dstmac').value=mac; } if (event.target.classList.contains("configicon")) { - console.log('config') + $('#cfgmac').innerHTML = mac; + $('#cfgmac').dataset.mac = mac; + fetch("/get_db?mac=" + mac) + .then(response => response.json()) + .then(data => { + console.log(data); + var tagdata = data.tags[0]; + $('#cfgalias').value = tagdata.alias; + $('#cfgcontent').value = tagdata.contentmode; + $('#cfgmodel').value = tagdata.model; + $('#configbox').style.display = 'block'; + }) + .catch(error => showMessage('Error: ' + error)); } +}) -}); +$('#cfgsave').onclick = function () { + let formData = new FormData(); + formData.append("mac", $('#cfgmac').dataset.mac); + formData.append("alias", $('#cfgalias').value); + formData.append("contentmode", $('#cfgcontent').value); + formData.append("model", $('#cfgmodel').value); + fetch("/save_cfg", { + method: "POST", + body: formData + }) + .then(response => response.text()) + .then(data => showMessage(data)) + .catch(error => showMessage('Error: ' + error)); + $('#configbox').style.display = 'none'; +} + +$('#cfgdelete').onclick = function () { + let mac = $('#cfgmac').dataset.mac; +} function showMessage(message) { const messages = $('#messages'); diff --git a/esp32_fw/include/tag_db.h b/esp32_fw/include/tag_db.h new file mode 100644 index 00000000..2d44313a --- /dev/null +++ b/esp32_fw/include/tag_db.h @@ -0,0 +1,36 @@ +#include + +#include + +#pragma pack(push, 1) +#pragma once + +enum contentModes { + Image, + Today, + CountDays, + CountHours, + Weather, + PubTrans, + Memo, +}; + +class tagRecord { + public: + tagRecord() : mac{0}, model(0), alias(""), lastseen(0), nextupdate(0), contentMode(Image), pending(false), button(false), currFilename(""), pendingFilename("") {} + + uint8_t mac[6]; + u_int8_t model; + String alias; + uint32_t lastseen; + uint32_t nextupdate; + contentModes contentMode; + bool pending; + bool button; + String currFilename; + String pendingFilename; + static tagRecord* findByMAC(uint8_t mac[6]); +}; + +extern std::vector tagDB; +String tagDBtoJson(uint8_t mac[6] = nullptr); \ No newline at end of file diff --git a/esp32_fw/include/web.h b/esp32_fw/include/web.h index a4f32135..71c40f5c 100644 --- a/esp32_fw/include/web.h +++ b/esp32_fw/include/web.h @@ -5,12 +5,13 @@ void init_web(); void doImageUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); -extern void webSocketSendProcess(void *parameter); -extern void wsString(String text); -extern void wsSendTaginfo(uint8_t src[8]); +//extern void webSocketSendProcess(void *parameter); +void wsString(String text); +void wsSendTaginfo(uint8_t mac[6]); +void wsSendSysteminfo(); extern uint64_t swap64(uint64_t x); -extern AsyncWebSocket ws;//("/ws"); +extern AsyncWebSocket ws; //("/ws"); extern SemaphoreHandle_t wsMutex; extern TaskHandle_t websocketUpdater; \ No newline at end of file diff --git a/esp32_fw/src/main.cpp b/esp32_fw/src/main.cpp index 80fc377b..71f04968 100644 --- a/esp32_fw/src/main.cpp +++ b/esp32_fw/src/main.cpp @@ -4,15 +4,22 @@ #include #include "flasher.h" +#include "makeimage.h" #include "pendingdata.h" #include "serial.h" #include "soc/rtc_wdt.h" +#include "tag_db.h" #include "web.h" -#include "makeimage.h" void freeHeapTask(void* parameter) { while (1) { //Serial.printf("Free heap=%d\n", ESP.getFreeHeap()); + //time_t now; + tm tm; + if (!getLocalTime(&tm)) { + Serial.println("Failed to obtain time"); + } + wsSendSysteminfo(); vTaskDelay(30000 / portTICK_PERIOD_MS); } } @@ -22,20 +29,13 @@ void setup() { Serial.print(">\n"); init_web(); - long timezone = 2; - byte daysavetime = 1; - configTime(0, 3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org"); - struct tm tmstruct; - delay(2000); - tmstruct.tm_year = 0; - getLocalTime(&tmstruct, 5000); - Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct.tm_year) + 1900, (tmstruct.tm_mon) + 1, tmstruct.tm_mday, tmstruct.tm_hour, tmstruct.tm_min, tmstruct.tm_sec); - Serial.println(""); + configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", "europe.pool.ntp.org", "time.nist.gov"); + // https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv xTaskCreate(freeHeapTask, "print free heap", 10000, NULL, 2, NULL); xTaskCreate(zbsRxTask, "zbsRX Process", 10000, NULL, 2, NULL); xTaskCreate(garbageCollection, "pending-data cleanup", 5000, NULL, 1, NULL); - xTaskCreate(webSocketSendProcess, "ws", 5000, NULL,configMAX_PRIORITIES-10, NULL); + //xTaskCreate(webSocketSendProcess, "ws", 5000, NULL,configMAX_PRIORITIES-10, NULL); } void loop() { diff --git a/esp32_fw/src/newproto.cpp b/esp32_fw/src/newproto.cpp index d476e1d0..64f48fd7 100644 --- a/esp32_fw/src/newproto.cpp +++ b/esp32_fw/src/newproto.cpp @@ -4,12 +4,14 @@ #include #include #include +#include #include "LittleFS.h" #include "commstructs.h" #include "pendingdata.h" #include "serial.h" #include "settings.h" +#include "tag_db.h" #include "web.h" extern void sendBlock(const void* data, const uint16_t len); @@ -128,6 +130,17 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t int bytes_written = file.write(pendinginfo->data, pendinginfo->len); file.close(); + uint8_t src[8]; + *((uint64_t*)src) = swap64(*((uint64_t*)dst)); + uint8_t mac[6]; + memcpy(mac, src + 2, sizeof(mac)); + tagRecord* taginfo = nullptr; + taginfo = tagRecord::findByMAC(mac); + if (taginfo != nullptr) { + taginfo->pending = true; + } + wsSendTaginfo(mac); + return true; } @@ -180,7 +193,15 @@ void processXferComplete(struct espXferComplete* xfc) { sprintf(buffer, "< %02X%02X%02X%02X%02X%02X reports xfer complete\n\0", src[2], src[3], src[4], src[5], src[6], src[7]); wsString((String)buffer); Serial.print(buffer); - wsSendTaginfo(src); + uint8_t mac[6]; + memcpy(mac, src + 2, sizeof(mac)); + + tagRecord* taginfo = nullptr; + taginfo = tagRecord::findByMAC(mac); + if (taginfo != nullptr) { + taginfo->pending = false; + } + wsSendTaginfo(mac); char src_path[64]; char dst_path[64]; @@ -198,8 +219,25 @@ void processDataReq(struct espAvailDataReq* eadr) { char buffer[64]; uint8_t src[8]; *((uint64_t*)src) = swap64(*((uint64_t*)eadr->src)); - sprintf(buffer, "adr.buttonState); - wsString((String)buffer); + + tagRecord* taginfo = nullptr; + uint8_t mac[6]; + memcpy(mac, src + 2, sizeof(mac)); + + taginfo = tagRecord::findByMAC(mac); + time_t now; + time(&now); + if (taginfo == nullptr) { + taginfo = new tagRecord; + memcpy(taginfo->mac, src + 2, sizeof(taginfo->mac)); + taginfo->pending = false; + tagDB.push_back(taginfo); + } + taginfo->lastseen = now; + taginfo->button = (eadr->adr.buttonState == 1); + + sprintf(buffer, " + +#include "tag_db.h" +#include +#include + +std::vector tagDB; + +tagRecord* tagRecord::findByMAC(uint8_t mac[6]) { + for (int16_t c = 0; c < tagDB.size(); c++) { + tagRecord* tag = nullptr; + tag = tagDB.at(c); + if (memcmp(tag->mac, mac, 6) == 0) { + return tag; + } + } + return nullptr; +} + +String tagDBtoJson(uint8_t mac[6]) { + DynamicJsonDocument doc(1000); + JsonArray tags = doc.createNestedArray("tags"); + + for (int16_t c = 0; c < tagDB.size(); c++) { + tagRecord* taginfo = nullptr; + taginfo = tagDB.at(c); + + bool select = false; + if (mac) { + if (memcmp(taginfo->mac, mac, 6) == 0) { + select = true; + } + } else { + select = true; + } + if (select) { + JsonObject tag = tags.createNestedObject(); + char buffer[64]; + sprintf(buffer, "%02X%02X%02X%02X%02X%02X\0", taginfo->mac[0], taginfo->mac[1], taginfo->mac[2], taginfo->mac[3], taginfo->mac[4], taginfo->mac[5]); + tag["mac"] = (String)buffer; + tag["lastseen"] = taginfo->lastseen; + tag["nextupdate"] = taginfo->nextupdate; + tag["model"] = taginfo->model; + tag["pending"] = taginfo->pending; + tag["button"] = taginfo->button; + tag["alias"] = taginfo->alias; + tag["contentmode"] = taginfo->contentMode; + } + } + return doc.as(); +} \ No newline at end of file diff --git a/esp32_fw/src/web.cpp b/esp32_fw/src/web.cpp index 33ed3e2e..3eb35563 100644 --- a/esp32_fw/src/web.cpp +++ b/esp32_fw/src/web.cpp @@ -14,6 +14,7 @@ #include "commstructs.h" #include "newproto.h" #include "settings.h" +#include "tag_db.h" extern uint8_t data_to_send[]; @@ -189,21 +190,49 @@ void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType } void wsString(String text) { - DynamicJsonDocument doc(1500); + DynamicJsonDocument doc(100); doc["logMsg"] = text; xSemaphoreTake(wsMutex, portMAX_DELAY); ws.textAll(doc.as()); xSemaphoreGive(wsMutex); } -void wsSendTaginfo(uint8_t src[8]) { - DynamicJsonDocument doc(1500); +void wsSendSysteminfo() { + DynamicJsonDocument doc(250); + JsonObject sys = doc.createNestedObject("sys"); + time_t now; + time(&now); + sys["currtime"] = now; + sys["heap"] = ESP.getFreeHeap(); + sys["recordcount"] = tagDB.size(); + sys["dbsize"] = tagDB.size() * sizeof(tagRecord); + sys["littlefsfree"] = LittleFS.totalBytes() - LittleFS.usedBytes(); + + xSemaphoreTake(wsMutex, portMAX_DELAY); + ws.textAll(doc.as()); + xSemaphoreGive(wsMutex); +} + +void wsSendTaginfo(uint8_t mac[6]) { + DynamicJsonDocument doc(1000); JsonArray tags = doc.createNestedArray("tags"); JsonObject tag = tags.createNestedObject(); char buffer[64]; - sprintf(buffer, "%02X%02X%02X%02X%02X%02X\0", src[2], src[3], src[4], src[5], src[6], src[7]); + sprintf(buffer, "%02X%02X%02X%02X%02X%02X\0", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); tag["mac"] = (String)buffer; - //tag["buttonstate"] = eadr->adr.buttonState; + + tagRecord *taginfo = nullptr; + taginfo = tagRecord::findByMAC(mac); + if (taginfo != nullptr) { + tag["lastseen"] = taginfo->lastseen; + tag["nextupdate"] = taginfo->nextupdate; + tag["model"] = taginfo->model; + tag["pending"] = taginfo->pending; + tag["button"] = taginfo->button; + tag["alias"] = taginfo->alias; + tag["contentmode"] = taginfo->contentMode; + } + xSemaphoreTake(wsMutex, portMAX_DELAY); ws.textAll(doc.as()); xSemaphoreGive(wsMutex); @@ -240,10 +269,6 @@ void init_web() { ws.onEvent(onEvent); server.addHandler(&ws); - server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(200, "text/plain", String(ESP.getFreeHeap())); - }); - server.on("/reboot", HTTP_POST, [](AsyncWebServerRequest *request) { request->send(200, "text/plain", "OK Reboot"); ESP.restart(); @@ -349,6 +374,41 @@ void init_web() { return; }); + server.on("/get_db", HTTP_GET, [](AsyncWebServerRequest *request) { + String json = ""; + if (request->hasParam("mac")) { + String dst = request->getParam("mac")->value(); + uint8_t mac[6]; + if (sscanf(dst.c_str(), "%02X%02X%02X%02X%02X%02X", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5])==6) { + json = tagDBtoJson(mac); + } + } else { + json = tagDBtoJson(); + } + request->send(200, "application/json", json); + }); + + server.on("/save_cfg", HTTP_POST, [](AsyncWebServerRequest *request) { + if (request->hasParam("mac", true)) { + String dst = request->getParam("mac", true)->value(); + uint8_t mac[6]; + if (sscanf(dst.c_str(), "%02X%02X%02X%02X%02X%02X", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6) { + tagRecord *taginfo = nullptr; + taginfo = tagRecord::findByMAC(mac); + if (taginfo != nullptr) { + taginfo->alias = request->getParam("alias", true)->value(); + taginfo->contentMode = (contentModes)atoi(request->getParam("contentmode", true)->value().c_str()); + taginfo->model = atoi(request->getParam("model", true)->value().c_str()); + wsSendTaginfo(mac); + request->send(200, "text/plain", "Ok, saved"); + } else { + request->send(200, "text/plain", "Error while saving: mac not found"); + } + } + } + request->send(200, "text/plain", "Ok, saved"); + }); + server.onNotFound([](AsyncWebServerRequest *request) { if (request->url() == "/" || request->url() == "index.htm") { request->send(200, "text/html", "-"); diff --git a/tag_fw/make.bat b/tag_fw/make.bat index 8f656d19..500df1a7 100644 --- a/tag_fw/make.bat +++ b/tag_fw/make.bat @@ -1,6 +1,20 @@ @echo off +del fs154.bin +del fw29.bin +del fw42.bin makeit clean -makeit +makeit BUILD=zbs154v033 CPU=8051 SOC=zbs243 +pause +ren main.bin fw154.bin +makeit clean +makeit BUILD=zbs29v033 CPU=8051 SOC=zbs243 +pause +ren main.bin fw29.bin +makeit clean +makeit BUILD=zbs42v033 CPU=8051 SOC=zbs243 +pause +ren main.bin fw42.bin + del /s *.asm del /s *.lst del /s *.rst