mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 01:04:30 +01:00
@@ -163,6 +163,7 @@ Latency will be around 40 seconds.">
|
||||
<div><span id="runstate"></div>
|
||||
<div><span id="apstatecolor">⬤</span> <span id="apstate">loading</span></div>
|
||||
<div><span id="apconfigbutton">AP config</span></div>
|
||||
<div><span id="sdstatecolor" style="display:none">⬤</span> <span style="display:none" id="sdstate"></span></div>
|
||||
<div><a href="/edit" target="littlefs" class="filebutton">edit contentFS</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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")) {
|
||||
|
||||
@@ -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<String>());
|
||||
xSemaphoreGive(wsMutex);
|
||||
|
||||
Reference in New Issue
Block a user