From 88c5ee76be9b13b769cd33db1ee731b3bceb4a35 Mon Sep 17 00:00:00 2001 From: Mimoja Date: Wed, 5 Jul 2023 17:13:28 +0200 Subject: [PATCH] Report SDCard status to frontend Signed-off-by: Mimoja --- ESP32_AP-Flasher/data/www/index.html | 1 + ESP32_AP-Flasher/data/www/main.js | 12 +++ ESP32_AP-Flasher/include/storage.h | 5 +- ESP32_AP-Flasher/src/storage.cpp | 140 +++++++++++++++++++++++++-- ESP32_AP-Flasher/src/web.cpp | 4 + 5 files changed, 153 insertions(+), 9 deletions(-) diff --git a/ESP32_AP-Flasher/data/www/index.html b/ESP32_AP-Flasher/data/www/index.html index 28f5f025..f7dab1d2 100644 --- a/ESP32_AP-Flasher/data/www/index.html +++ b/ESP32_AP-Flasher/data/www/index.html @@ -163,6 +163,7 @@ Latency will be around 40 seconds.">
loading
AP config
+
edit contentFS
diff --git a/ESP32_AP-Flasher/data/www/main.js b/ESP32_AP-Flasher/data/www/main.js index c68c7ecf..a225922e 100644 --- a/ESP32_AP-Flasher/data/www/main.js +++ b/ESP32_AP-Flasher/data/www/main.js @@ -101,6 +101,18 @@ function connect() { $("#runstate").innerHTML = runstate[msg.sys.runstate].state; $("#temp").innerHTML = msg.sys.temp.toFixed(1) + '°C'; } + if (typeof msg.sys.sdcard != "undefined") { + $("#sdstatecolor").style.display = ''; + $("#sdstate").style.display = ''; + const sdName = ["", "MMC", "SD", "SDHC", "Unknown"]; + if (msg.sys.sdcard == 0) { + $("#sdstatecolor").style.color = "red"; + $("#sdstate").innerHTML = "SD failed" + } else { + $("#sdstatecolor").style.color = "green"; + $("#sdstate").innerHTML = sdName[msg.sys.sdcard]; + } + } servertimediff = (Date.now() / 1000) - msg.sys.currtime; } if (msg.apitem) { diff --git a/ESP32_AP-Flasher/include/storage.h b/ESP32_AP-Flasher/include/storage.h index a1732e25..8bd7cd6c 100644 --- a/ESP32_AP-Flasher/include/storage.h +++ b/ESP32_AP-Flasher/include/storage.h @@ -28,9 +28,12 @@ class DynStorage { void end(); void listFiles(); size_t freeSpace(); + #ifdef HAS_SDCARD + uint8_t cardType(); + #endif private: - bool isInited; + bool isInited = false; }; extern DynStorage Storage; diff --git a/ESP32_AP-Flasher/src/storage.cpp b/ESP32_AP-Flasher/src/storage.cpp index 2cb5849f..4a8f5a9d 100644 --- a/ESP32_AP-Flasher/src/storage.cpp +++ b/ESP32_AP-Flasher/src/storage.cpp @@ -42,6 +42,11 @@ static void initSDCard() { contentFS = &SD; } + +uint8_t DynStorage::cardType() { + return SD.cardType(); +} + #endif size_t DynStorage::freeSpace(){ @@ -116,21 +121,140 @@ void copyIfNeeded(const char* path) { copyBetweenFS(LittleFS, path, *contentFS); } } + #endif +String md5Filepath = "/ota_md5.txt"; +String otaFilepath = "/ota.bin"; + +SemaphoreHandle_t otaMutex; + +static void fileSystemFirmwareUpdateTask(void* parameter) { + const char* md5 = nullptr; + String md5Str = ""; + + xSemaphoreTake(otaMutex, portMAX_DELAY); + + File updateBin = contentFS->open(otaFilepath); + if (!updateBin) { + Serial.println("Failed to load " + otaFilepath); + wsErr("Failed to load " + otaFilepath); + xSemaphoreGive(otaMutex); + return; + } + + if(updateBin.isDirectory()){ + Serial.println("Error " + otaFilepath + " is not a file"); + wsErr("Error " + otaFilepath + " is not a file"); + updateBin.close(); + xSemaphoreGive(otaMutex); + return; + } + + // MD5 check + if (contentFS->exists(md5Filepath)) { + Serial.println("Reading MD5 file"); + File md5File = contentFS->open(md5Filepath); + if (!md5File ) { + Serial.println("Failed to load ota md5 even tho an md5 file exists"); + wsErr("Failed to load ota md5 even tho an md5 file exists"); + contentFS->rename(md5Filepath, md5Filepath + "_failure.txt"); + xSemaphoreGive(otaMutex); + return; + } + + if(md5File.size() < 32){ + Serial.println("md5 sum too short"); + wsErr("md5 sum too short"); + md5File.close(); + contentFS->rename(md5Filepath, md5Filepath + "_failure.txt"); + xSemaphoreGive(otaMutex); + return; + } + + // Only take the md5 from the output of md5sum + // "471a53ab5e35fa9d3e642a82fa95f3ce .pio/build/Esp32-POE-ISO/firmware.bin" + md5Str = md5File.readStringUntil(' '); + md5Str.trim(); + md5Str.toLowerCase(); + Serial.println(String("ota.bin md5:") + md5Str); + wsLog(String("ota.bin md5:") + md5Str); + md5 = md5Str.c_str(); + md5File.close(); + } + + bool success = executeUpdate(md5, updateBin.size(), updateBin, updateBin.size()); + if (!success) { + Serial.println("Update failed."); + } + updateBin.close(); + contentFS->remove(otaFilepath); + + if (contentFS->exists(md5Filepath)) + contentFS->remove(md5Filepath); + + if (success) { + Serial.println("Rebooting now"); + wsLog("Rebooting now!"); + ESP.restart(); + } + + xSemaphoreGive(otaMutex); +} + +void DynStorage::checkForUpdate() { + Storage.begin(); + + if (!contentFS->exists(otaFilepath)) { + return; + } + + if(!otaMutex) + otaMutex = xSemaphoreCreateMutex(); + + // An update process is already running + if (xQueuePeek((xQueueHandle)otaMutex, (void*)NULL, (portTickType)NULL) != pdTRUE) + return; + + File updateBin = contentFS->open(otaFilepath); + if (!updateBin) { + Serial.println("Failed to load " + otaFilepath); + wsErr("Failed to load " + otaFilepath); + } + + size_t updateSize = updateBin.size(); + if (updateSize <= 0) { + return; + } + updateBin.close(); + Serial.println("Found OTA file on contentFS, updating async"); + wsLog("Found OTA file on contentFS, updating async"); + + xTaskCreate(fileSystemFirmwareUpdateTask, "FSUpdateTask", 6144, NULL, 10, NULL); +} + void DynStorage::begin() { initLittleFS(); #ifdef HAS_SDCARD - initSDCard(); + bool inited = initSDCard(); - copyIfNeeded("/index.html"); - copyIfNeeded("/fonts"); - copyIfNeeded("/www"); - copyIfNeeded("/AP_FW_Pack.bin"); - copyIfNeeded("/tag_md5_db.json"); - copyIfNeeded("/update_actions.json"); - copyIfNeeded("/content_template.json"); + if(inited && inited != this->isInited) { + Serial.println("SDCard mounted"); + wsLog("SDcard mounted"); + copyIfNeeded("/index.html"); + copyIfNeeded("/fonts"); + copyIfNeeded("/www"); + copyIfNeeded("/AP_FW_Pack.bin"); + copyIfNeeded("/tag_md5_db.json"); + copyIfNeeded("/update_actions.json"); + copyIfNeeded("/content_template.json"); + } + if (this->isInited && !inited) { + Serial.println("Lost connection to the SDCard"); + wsErr("Lost connection to the SDCard"); + } + this->isInited = inited; #endif if (!contentFS->exists("/current")) { diff --git a/ESP32_AP-Flasher/src/web.cpp b/ESP32_AP-Flasher/src/web.cpp index 5c0336fb..13ea66bd 100644 --- a/ESP32_AP-Flasher/src/web.cpp +++ b/ESP32_AP-Flasher/src/web.cpp @@ -144,6 +144,10 @@ void wsSendSysteminfo() { sys["wifistatus"] = WiFi.status(); sys["wifissid"] = WiFi.SSID(); +#ifdef HAS_SDCARD + sys["sdcard"] = Storage.cardType(); +#endif + xSemaphoreTake(wsMutex, portMAX_DELAY); ws.textAll(doc.as()); xSemaphoreGive(wsMutex);