diff --git a/esp32_fw/data/www/index.html b/esp32_fw/data/www/index.html
index 0cfbbcfa..637013b6 100644
--- a/esp32_fw/data/www/index.html
+++ b/esp32_fw/data/www/index.html
@@ -52,8 +52,9 @@
+
Currently active tags:
+
reboot AP
- Currently active tags:
diff --git a/esp32_fw/data/www/main.css b/esp32_fw/data/www/main.css
index fbc054f5..61c312b9 100644
--- a/esp32_fw/data/www/main.css
+++ b/esp32_fw/data/www/main.css
@@ -52,28 +52,32 @@ label {
.actionbox>div:first-child {
padding: 10px;
- background-color: white;
- margin: 5px;
+ background-color: white;
+ margin: 5px;
}
-.actionbox p {
- padding: 5px;
+.actionbox>div:first-child>div:first-child {
+ flex-grow: 2;
}
-.actionbox .columns {
+.actionbox>div {
display:flex;
- flex-wrap: wrap;
+ gap: 20px;
}
-.filebutton {
- padding:2px 5px;
+#rebootbutton {
+ padding: 2px 5px;
background-color: #cccccc;
text-decoration: none;
color: black;
+ cursor: pointer;
}
-.editbtn {
- float:right;
+.filebutton {
+ padding: 2px 5px;
+ background-color: #cccccc;
+ text-decoration: none;
+ color: black;
}
.columns div {
diff --git a/esp32_fw/data/www/main.js b/esp32_fw/data/www/main.js
index c0ea7d21..d9fc8d66 100644
--- a/esp32_fw/data/www/main.js
+++ b/esp32_fw/data/www/main.js
@@ -259,7 +259,28 @@ $('#cfgsave').onclick = function () {
}
$('#cfgdelete').onclick = function () {
- let mac = $('#cfgmac').dataset.mac;
+ let formData = new FormData();
+ formData.append("mac", $('#cfgmac').dataset.mac);
+ fetch("/delete_cfg", {
+ method: "POST",
+ body: formData
+ })
+ .then(response => response.text())
+ .then(data => {
+ var div = $('#tag' + $('#cfgmac').dataset.mac);
+ div.remove();
+ showMessage(data);
+ })
+ .catch(error => showMessage('Error: ' + error));
+ $('#configbox').style.display = 'none';
+}
+
+$('#rebootbutton').onclick = function () {
+ showMessage("rebooting AP....",true);
+ fetch("/reboot", {
+ method: "POST"
+ });
+ socket.close();
}
function contentselected() {
diff --git a/esp32_fw/include/newproto.h b/esp32_fw/include/newproto.h
index 5d98df56..306c050b 100644
--- a/esp32_fw/include/newproto.h
+++ b/esp32_fw/include/newproto.h
@@ -9,4 +9,5 @@ extern bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, u
extern void processJoinNetwork(struct espJoinNetwork* xjn);
extern void processXferComplete(struct espXferComplete* xfc);
extern void processXferTimeout(struct espXferComplete* xfc);
-extern void processDataReq(struct espAvailDataReq* adr);
\ No newline at end of file
+extern void processDataReq(struct espAvailDataReq* adr);
+void refreshAllPending();
\ No newline at end of file
diff --git a/esp32_fw/include/pendingdata.h b/esp32_fw/include/pendingdata.h
index 88b09054..eced4e64 100644
--- a/esp32_fw/include/pendingdata.h
+++ b/esp32_fw/include/pendingdata.h
@@ -8,9 +8,7 @@
class pendingdata {
public:
String filename;
- //uint8_t dst[8];
uint64_t ver;
- String md5;
uint32_t timeout;
uint8_t datatimeout;
uint8_t* data = nullptr;
diff --git a/esp32_fw/include/tag_db.h b/esp32_fw/include/tag_db.h
index 3e7e713e..50606a72 100644
--- a/esp32_fw/include/tag_db.h
+++ b/esp32_fw/include/tag_db.h
@@ -43,6 +43,7 @@ class tagRecord {
extern std::vector tagDB;
String tagDBtoJson(uint8_t mac[6] = nullptr, uint8_t startPos = 0);
+bool deleteRecord(uint8_t mac[6]);
void fillNode(JsonObject &tag, tagRecord* &taginfo);
void saveDB(String filename);
void loadDB(String filename);
diff --git a/esp32_fw/src/contentmanager.cpp b/esp32_fw/src/contentmanager.cpp
index b4559cc8..c8ac6acc 100644
--- a/esp32_fw/src/contentmanager.cpp
+++ b/esp32_fw/src/contentmanager.cpp
@@ -200,7 +200,7 @@ void initSprite(TFT_eSprite &spr, int w, int h) {
spr.setColorDepth(8);
spr.createSprite(w, h);
if (spr.getPointer() == nullptr) {
- wsErr("Failed to create sprite in drawNumber");
+ wsErr("Failed to create sprite");
}
spr.fillSprite(TFT_WHITE);
}
diff --git a/esp32_fw/src/main.cpp b/esp32_fw/src/main.cpp
index 9dc18d5d..9a4efe08 100644
--- a/esp32_fw/src/main.cpp
+++ b/esp32_fw/src/main.cpp
@@ -44,10 +44,10 @@ void setup() {
init_web();
loadDB("/current/tagDB.json");
- xTaskCreate(timeTask, "timed tasks", 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(timeTask, "timed tasks", 10000, NULL, 2, NULL);
}
void loop() {
diff --git a/esp32_fw/src/newproto.cpp b/esp32_fw/src/newproto.cpp
index a39ac298..88c0ed34 100644
--- a/esp32_fw/src/newproto.cpp
+++ b/esp32_fw/src/newproto.cpp
@@ -63,7 +63,6 @@ void prepareIdleReq(uint8_t* dst, uint16_t nextCheckin) {
char buffer[64];
uint8_t src[8];
*((uint64_t*)src) = swap64(*((uint64_t*)dst));
- sprintf(buffer, "idle request %02X%02X%02X%02X%02X%02X %d minutes\n\0", src[2], src[3], src[4], src[5], src[6], src[7], nextCheckin);
Serial.print(buffer);
sendDataAvail(&pending);
@@ -135,7 +134,7 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
if (taginfo != nullptr) {
if (memcmp(md5bytes, taginfo->md5pending, 16) == 0) {
- wsLog("new image is the same as current image. not updating tag.");
+ wsLog("new image is the same as current or already pending image. not updating tag.");
wsSendTaginfo(mac);
return true;
}
@@ -147,7 +146,6 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
lut = EPD_LUT_DEFAULT; // full update once a day
taginfo->lastfullupdate = now;
}
- Serial.println("last midnight: "+String(last_midnight)+" last full: "+String(taginfo->lastfullupdate) + " -> lut: " + String(lut));
} else {
wsErr("Tag not found, this shouldn't happen.");
}
@@ -266,10 +264,14 @@ void processXferComplete(struct espXferComplete* xfc) {
sprintf(src_path, "/current/%02X%02X%02X%02X%02X%02X.pending\0", src[2], src[3], src[4], src[5], src[6], src[7]);
sprintf(dst_path, "/current/%02X%02X%02X%02X%02X%02X.bmp\0", src[2], src[3], src[4], src[5], src[6], src[7]);
sprintf(tmp_path, "/temp/%02X%02X%02X%02X%02X%02X.bmp\0", src[2], src[3], src[4], src[5], src[6], src[7]);
- if (LittleFS.exists(dst_path)) {
+ if (LittleFS.exists(dst_path) && LittleFS.exists(src_path)) {
LittleFS.remove(dst_path);
}
- LittleFS.rename(src_path, dst_path);
+ if (LittleFS.exists(src_path)) {
+ LittleFS.rename(src_path, dst_path);
+ } else {
+ wsErr("hm, weird, no pending image found after xfercomplete.");
+ }
if (LittleFS.exists(tmp_path)) {
LittleFS.remove(tmp_path);
}
@@ -362,11 +364,23 @@ void processDataReq(struct espAvailDataReq* eadr) {
taginfo->capabilities = eadr->adr.capabilities;
}
- Serial.printf("t=%d, lqi=%d, rssi=%d, ", eadr->adr.temperature, eadr->adr.lastPacketLQI, eadr->adr.lastPacketRSSI);
- Serial.printf("hwtype=%d, reason=%d, volt=%d", eadr->adr.hwType,eadr->adr.wakeupReason,eadr->adr.batteryMv);
sprintf(buffer, "pending) {
+ taginfo->pending = false;
+ taginfo->nextupdate = 0;
+ memset(taginfo->md5, 0, 16 * sizeof(uint8_t));
+ memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
+ wsSendTaginfo(taginfo->mac);
+ }
+ }
+};
\ No newline at end of file
diff --git a/esp32_fw/src/serial.cpp b/esp32_fw/src/serial.cpp
index 2331151a..9698faf3 100644
--- a/esp32_fw/src/serial.cpp
+++ b/esp32_fw/src/serial.cpp
@@ -251,6 +251,8 @@ void zbsRxTask(void* parameter) {
Serial.println("I wasn't able to connect to a ZBS tag, trying to reboot the tag.");
Serial.println("If this problem persists, please check wiring and definitions in the settings.h file, and presence of the right firmware");
simplePowerOn();
+ wsErr("The AP tag crashed. Restarting tag, regenerating all pending info.");
+ refreshAllPending();
}
}
diff --git a/esp32_fw/src/tag_db.cpp b/esp32_fw/src/tag_db.cpp
index e6b6224f..2f585d24 100644
--- a/esp32_fw/src/tag_db.cpp
+++ b/esp32_fw/src/tag_db.cpp
@@ -20,6 +20,19 @@ tagRecord* tagRecord::findByMAC(uint8_t mac[6]) {
return nullptr;
}
+bool deleteRecord(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) {
+ delete tagDB[c];
+ tagDB.erase(tagDB.begin() + c);
+ return true;
+ }
+ }
+ return false;
+}
+
String tagDBtoJson(uint8_t mac[6], uint8_t startPos) {
DynamicJsonDocument doc(2500);
JsonArray tags = doc.createNestedArray("tags");
@@ -55,9 +68,12 @@ void fillNode(JsonObject &tag, tagRecord* &taginfo) {
char buffer[16];
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;
- char hex[7];
- sprintf(hex, "%02x%02x%02x\0", taginfo->md5[0], taginfo->md5[1], taginfo->md5[2]);
- tag["hash"] = hex;
+
+ char hex[33];
+ for (uint8_t i = 0; i < 16; i++) {
+ sprintf(hex + (i * 2), "%02x", taginfo->md5[i]);
+ }
+ tag["hash"] = (String)hex;
tag["lastseen"] = taginfo->lastseen;
tag["nextupdate"] = taginfo->nextupdate;
tag["nextcheckin"] = taginfo->expectedNextCheckin;
@@ -140,8 +156,14 @@ void loadDB(String filename) {
memcpy(taginfo->mac, mac, sizeof(taginfo->mac));
tagDB.push_back(taginfo);
}
+ String md5 = tag["hash"].as();
+ if (md5.length() >= 32) {
+ for (int i = 0; i < 16; i++) {
+ taginfo->md5[i] = strtoul(md5.substring(i * 2, i * 2 + 2).c_str(), NULL, 16);
+ }
+ }
+ memcpy(taginfo->md5pending, taginfo->md5, sizeof(taginfo->md5));
taginfo->lastseen = (uint32_t)tag["lastseen"];
- //taginfo->lastseen = 0;
taginfo->nextupdate = (uint32_t)tag["nextupdate"];
taginfo->expectedNextCheckin = (uint16_t)tag["nextcheckin"];
if (taginfo->expectedNextCheckin < now - 1800) {
diff --git a/esp32_fw/src/web.cpp b/esp32_fw/src/web.cpp
index 0bdcf4be..4da1b13f 100644
--- a/esp32_fw/src/web.cpp
+++ b/esp32_fw/src/web.cpp
@@ -42,30 +42,11 @@ uint64_t swap64(uint64_t x) {
}
void webSocketSendProcess(void *parameter) {
- uint32_t ulNotificationValue;
- Serial.print("websocket thread started\n");
websocketUpdater = xTaskGetCurrentTaskHandle();
wsMutex = xSemaphoreCreateMutex();
while (true) {
- ulNotificationValue = ulTaskNotifyTake(pdTRUE, 1000 / portTICK_RATE_MS);
- if (ulNotificationValue == 0) { // timeout, so every 1s
- ws.cleanupClients();
- } else {
- // if (ws.count())
- // sendStatus(STATUS_WIFI_ACTIVITY);
- DynamicJsonDocument doc(1500);
- if (ulNotificationValue & 2) { // WS_SEND_MODE_STATUS) {
- }
- /*
- JsonArray statusframes = doc.createNestedArray("frames");
- }*/
- size_t len = measureJson(doc);
- xSemaphoreTake(wsMutex, portMAX_DELAY);
- auto buffer = std::make_shared>(len);
- serializeJson(doc, buffer->data(), len);
- // ws.textAll((char*)buffer->data());
- xSemaphoreGive(wsMutex);
- }
+ ws.cleanupClients();
+ vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
@@ -146,17 +127,17 @@ void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType
void wsLog(String text) {
StaticJsonDocument<500> doc;
doc["logMsg"] = text;
- xSemaphoreTake(wsMutex, portMAX_DELAY);
+ if (wsMutex) xSemaphoreTake(wsMutex, portMAX_DELAY);
ws.textAll(doc.as());
- xSemaphoreGive(wsMutex);
+ if (wsMutex) xSemaphoreGive(wsMutex);
}
void wsErr(String text) {
StaticJsonDocument<500> doc;
doc["errMsg"] = text;
- xSemaphoreTake(wsMutex, portMAX_DELAY);
+ if (wsMutex) xSemaphoreTake(wsMutex, portMAX_DELAY);
ws.textAll(doc.as());
- xSemaphoreGive(wsMutex);
+ if (wsMutex) xSemaphoreGive(wsMutex);
}
void wsSendSysteminfo() {
@@ -214,6 +195,12 @@ void init_web() {
server.on("/reboot", HTTP_POST, [](AsyncWebServerRequest *request) {
request->send(200, "text/plain", "OK Reboot");
+ wsErr("REBOOTING");
+ ws.enable(false);
+ refreshAllPending();
+ saveDB("/current/tagDB.json");
+ ws.closeAll();
+ delay(100);
ESP.restart();
});
@@ -226,34 +213,6 @@ void init_web() {
},
doImageUpload);
- server.on("/req_checkin", HTTP_POST, [](AsyncWebServerRequest *request) {
- String filename;
- String dst;
- if (request->hasParam("dst", true)) {
- dst = request->getParam("dst", true)->value();
- uint8_t mac_addr[12]; // I expected this to return like 8 values, but if I make the array 8 bytes long, things die.
- mac_addr[0] = 0x00;
- mac_addr[1] = 0x00;
- if (sscanf(dst.c_str(), "%02X%02X%02X%02X%02X%02X",
- &mac_addr[2],
- &mac_addr[3],
- &mac_addr[4],
- &mac_addr[5],
- &mac_addr[6],
- &mac_addr[7]) != 6) {
- request->send(200, "text/plain", "Something went wrong trying to parse the mac address");
- } else {
- *((uint64_t *)mac_addr) = swap64(*((uint64_t *)mac_addr));
- if (prepareDataAvail(&filename, DATATYPE_NOUPDATE, mac_addr,0)) {
- request->send(200, "text/plain", "Sending check-in request to " + dst);
- }
- }
- return;
- }
- request->send(200, "text/plain", "Didn't get the required params");
- return;
- });
-
server.on("/get_db", HTTP_GET, [](AsyncWebServerRequest *request) {
String json = "";
if (request->hasParam("mac")) {
@@ -284,8 +243,8 @@ void init_web() {
taginfo->modeConfigJson = request->getParam("modecfgjson", true)->value();
taginfo->contentMode = atoi(request->getParam("contentmode", true)->value().c_str());
taginfo->nextupdate = 0;
- memset(taginfo->md5, 0, 16 * sizeof(uint8_t));
- memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
+ //memset(taginfo->md5, 0, 16 * sizeof(uint8_t));
+ //memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
wsSendTaginfo(mac);
saveDB("/current/tagDB.json");
request->send(200, "text/plain", "Ok, saved");
@@ -297,6 +256,22 @@ void init_web() {
request->send(200, "text/plain", "Ok, saved");
});
+ server.on("/delete_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) {
+ if (deleteRecord(mac)) {
+ request->send(200, "text/plain", "Ok, deleted");
+ } else {
+ request->send(200, "text/plain", "Error while saving: mac not found");
+ }
+ }
+ } else {
+ request->send(500, "text/plain", "no mac");
+ }
+ });
+
server.onNotFound([](AsyncWebServerRequest *request) {
if (request->url() == "/" || request->url() == "index.htm") {
request->send(200, "text/html", "-");