mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 06:06:23 +01:00
Allow for SDCard based OTA update
Signed-off-by: Mimoja <git@mimoja.de>
This commit is contained in:
@@ -8,6 +8,7 @@ void handleGetExtUrl(AsyncWebServerRequest* request);
|
|||||||
void handleLittleFSUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final);
|
void handleLittleFSUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final);
|
||||||
void handleUpdateOTA(AsyncWebServerRequest* request);
|
void handleUpdateOTA(AsyncWebServerRequest* request);
|
||||||
void firmwareUpdateTask(void* parameter);
|
void firmwareUpdateTask(void* parameter);
|
||||||
void updateFirmware(const char* url, const char* expectedMd5, size_t size);
|
void updateFirmwareFromURL(const char* url, const char* expectedMd5, size_t size);
|
||||||
|
bool executeUpdate(const char* expectedMd5, size_t size, Stream &stream, size_t stream_size);
|
||||||
void handleRollback(AsyncWebServerRequest* request);
|
void handleRollback(AsyncWebServerRequest* request);
|
||||||
void handleUpdateActions(AsyncWebServerRequest* request);
|
void handleUpdateActions(AsyncWebServerRequest* request);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class DynStorage {
|
|||||||
void end();
|
void end();
|
||||||
void listFiles();
|
void listFiles();
|
||||||
size_t freeSpace();
|
size_t freeSpace();
|
||||||
|
void checkForUpdate();
|
||||||
#ifdef HAS_SDCARD
|
#ifdef HAS_SDCARD
|
||||||
uint8_t cardType();
|
uint8_t cardType();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ void timeTask(void* parameter) {
|
|||||||
|
|
||||||
if (now % 5 == 0 || apInfo.state != AP_STATE_ONLINE || config.runStatus != RUNSTATUS_RUN) wsSendSysteminfo();
|
if (now % 5 == 0 || apInfo.state != AP_STATE_ONLINE || config.runStatus != RUNSTATUS_RUN) wsSendSysteminfo();
|
||||||
if (now % 5 == 0) Serial.printf("Free heap: %.2f KB\n", ESP.getFreeHeap() / 1024.0f);
|
if (now % 5 == 0) Serial.printf("Free heap: %.2f KB\n", ESP.getFreeHeap() / 1024.0f);
|
||||||
|
if (now % 5 == 0) Storage.checkForUpdate();
|
||||||
if (now % 300 == 6 && config.runStatus != RUNSTATUS_STOP) saveDB("/current/tagDB.json");
|
if (now % 300 == 6 && config.runStatus != RUNSTATUS_STOP) saveDB("/current/tagDB.json");
|
||||||
|
|
||||||
if (apInfo.state == AP_STATE_ONLINE) contentRunner();
|
if (apInfo.state == AP_STATE_ONLINE) contentRunner();
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ void handleGetExtUrl(AsyncWebServerRequest* request) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
request->send(httpResponseCode, "text/plain", "Failed to fetch URL");
|
request->send(httpResponseCode, "text/plain", "Failed to fetch URL");
|
||||||
wsSerial(http.errorToString(httpResponseCode));
|
wsLog(http.errorToString(httpResponseCode));
|
||||||
}
|
}
|
||||||
http.end();
|
http.end();
|
||||||
} else {
|
} else {
|
||||||
@@ -164,20 +164,74 @@ void firmwareUpdateTask(void* parameter) {
|
|||||||
FirmwareUpdateParams* params = reinterpret_cast<FirmwareUpdateParams*>(parameter);
|
FirmwareUpdateParams* params = reinterpret_cast<FirmwareUpdateParams*>(parameter);
|
||||||
|
|
||||||
if (ESP.getMaxAllocHeap() < 22000) {
|
if (ESP.getMaxAllocHeap() < 22000) {
|
||||||
wsSerial("Error: Not enough memory left. Restart the esp32 and try updating again.");
|
wsLog("Error: Not enough memory left. Restart the esp32 and try updating again.");
|
||||||
wsSerial("[reboot]");
|
wsLog("[reboot]");
|
||||||
} else {
|
} else {
|
||||||
const char* url = params->url.c_str();
|
const char* url = params->url.c_str();
|
||||||
const char* md5 = params->md5.c_str();
|
const char* md5 = params->md5.c_str();
|
||||||
size_t size = params->size;
|
size_t size = params->size;
|
||||||
updateFirmware(url, md5, size);
|
updateFirmwareFromURL(url, md5, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete params;
|
delete params;
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateFirmware(const char* url, const char* expectedMd5, size_t size) {
|
bool executeUpdate(const char* expectedMd5, size_t size, Stream &stream, size_t stream_size) {
|
||||||
|
if (!Update.begin(size)) {
|
||||||
|
wsLog("Failed to begin firmware update");
|
||||||
|
wsLog(Update.errorString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expectedMd5) {
|
||||||
|
Serial.println("Setting update md5: " + String(expectedMd5));
|
||||||
|
if (!Update.setMD5(expectedMd5)) {
|
||||||
|
Serial.println("Failed to set firmware md5");
|
||||||
|
wsErr("Failed to set firmware md5");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long progressTimer = millis();
|
||||||
|
Update.onProgress([&progressTimer](size_t progress, size_t total) {
|
||||||
|
if (millis() - progressTimer > 500 || progress == total) {
|
||||||
|
char buffer[50];
|
||||||
|
sprintf(buffer, "Progress: %u%% %d %d", progress * 100 / total, progress, total);
|
||||||
|
wsLog(String(buffer));
|
||||||
|
Serial.println(String(buffer));
|
||||||
|
progressTimer = millis();
|
||||||
|
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
size_t written = Update.writeStream(stream);
|
||||||
|
if (written != stream_size) {
|
||||||
|
Serial.println("Error writing firmware:");
|
||||||
|
wsLog("Error writing firmware:");
|
||||||
|
Serial.println(Update.errorString());
|
||||||
|
wsLog(Update.errorString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Update.end(true)) {
|
||||||
|
Serial.println("Error updating firmware:");
|
||||||
|
wsLog("Error updating firmware:");
|
||||||
|
Serial.println(Update.errorString());
|
||||||
|
wsLog(Update.errorString());
|
||||||
|
Update.abort();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsLog("Firmware update successful");
|
||||||
|
wsLog("Reboot system now");
|
||||||
|
wsLog("[reboot]");
|
||||||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void updateFirmwareFromURL(const char* url, const char* expectedMd5, size_t size) {
|
||||||
uint32_t freeStack = uxTaskGetStackHighWaterMark(NULL);
|
uint32_t freeStack = uxTaskGetStackHighWaterMark(NULL);
|
||||||
Serial.printf("Free heap: %d allocatable: %d stack: %d\n", ESP.getFreeHeap(), ESP.getMaxAllocHeap(), freeStack);
|
Serial.printf("Free heap: %d allocatable: %d stack: %d\n", ESP.getFreeHeap(), ESP.getMaxAllocHeap(), freeStack);
|
||||||
|
|
||||||
@@ -189,8 +243,8 @@ void updateFirmware(const char* url, const char* expectedMd5, size_t size) {
|
|||||||
|
|
||||||
HTTPClient httpClient;
|
HTTPClient httpClient;
|
||||||
|
|
||||||
wsSerial("start downloading");
|
wsLog("start downloading");
|
||||||
wsSerial(url);
|
wsLog(url);
|
||||||
|
|
||||||
httpClient.begin(url);
|
httpClient.begin(url);
|
||||||
httpClient.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
|
httpClient.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
|
||||||
@@ -201,43 +255,10 @@ void updateFirmware(const char* url, const char* expectedMd5, size_t size) {
|
|||||||
Serial.printf("Free heap: %d allocatable: %d stack: %d\n", ESP.getFreeHeap(), ESP.getMaxAllocHeap(), freeStack);
|
Serial.printf("Free heap: %d allocatable: %d stack: %d\n", ESP.getFreeHeap(), ESP.getMaxAllocHeap(), freeStack);
|
||||||
|
|
||||||
if (httpCode == HTTP_CODE_OK) {
|
if (httpCode == HTTP_CODE_OK) {
|
||||||
if (Update.begin(size)) {
|
executeUpdate(expectedMd5, size, httpClient.getStream(), httpClient.getSize());
|
||||||
Update.setMD5(expectedMd5);
|
|
||||||
|
|
||||||
unsigned long progressTimer = millis();
|
|
||||||
Update.onProgress([&progressTimer](size_t progress, size_t total) {
|
|
||||||
if (millis() - progressTimer > 500 || progress == total) {
|
|
||||||
char buffer[50];
|
|
||||||
sprintf(buffer, "Progress: %u%% %d %d", progress * 100 / total, progress, total);
|
|
||||||
wsSerial(String(buffer));
|
|
||||||
progressTimer = millis();
|
|
||||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
size_t written = Update.writeStream(httpClient.getStream());
|
|
||||||
if (written == httpClient.getSize()) {
|
|
||||||
if (Update.end(true)) {
|
|
||||||
wsSerial("Firmware update successful");
|
|
||||||
wsSerial("Reboot system now");
|
|
||||||
wsSerial("[reboot]");
|
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
||||||
// ESP.restart();
|
|
||||||
} else {
|
|
||||||
wsSerial("Error updating firmware:");
|
|
||||||
wsSerial(Update.errorString());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wsSerial("Error writing firmware data:");
|
|
||||||
wsSerial(Update.errorString());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wsSerial("Failed to begin firmware update");
|
|
||||||
wsSerial(Update.errorString());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
wsSerial("Failed to download firmware file (HTTP code " + String(httpCode) + ")");
|
wsLog("Failed to download firmware file (HTTP code " + String(httpCode) + ")");
|
||||||
wsSerial(httpClient.errorToString(httpCode));
|
wsLog(httpClient.errorToString(httpCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
httpClient.end();
|
httpClient.end();
|
||||||
@@ -251,26 +272,26 @@ void handleRollback(AsyncWebServerRequest* request) {
|
|||||||
bool rollbackSuccess = Update.rollBack();
|
bool rollbackSuccess = Update.rollBack();
|
||||||
if (rollbackSuccess) {
|
if (rollbackSuccess) {
|
||||||
request->send(200, "Rollback successful");
|
request->send(200, "Rollback successful");
|
||||||
wsSerial("Rollback successful");
|
wsLog("Rollback successful");
|
||||||
wsSerial("Reboot system now");
|
wsLog("Reboot system now");
|
||||||
wsSerial("[reboot]");
|
wsLog("[reboot]");
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
// ESP.restart();
|
// ESP.restart();
|
||||||
} else {
|
} else {
|
||||||
wsSerial("Rollback failed");
|
wsLog("Rollback failed");
|
||||||
request->send(400, "Rollback failed");
|
request->send(400, "Rollback failed");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wsSerial("Rollback not allowed");
|
wsLog("Rollback not allowed");
|
||||||
request->send(400, "Rollback not allowed");
|
request->send(400, "Rollback not allowed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleUpdateActions(AsyncWebServerRequest* request) {
|
void handleUpdateActions(AsyncWebServerRequest* request) {
|
||||||
wsSerial("Performing cleanup");
|
wsLog("Performing cleanup");
|
||||||
File file = contentFS->open("/update_actions.json", "r");
|
File file = contentFS->open("/update_actions.json", "r");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
wsSerial("No update_actions.json present");
|
wsLog("No update_actions.json present");
|
||||||
request->send(200, "No update actions needed");
|
request->send(200, "No update actions needed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -279,11 +300,11 @@ void handleUpdateActions(AsyncWebServerRequest* request) {
|
|||||||
JsonArray deleteFiles = doc["deletefile"].as<JsonArray>();
|
JsonArray deleteFiles = doc["deletefile"].as<JsonArray>();
|
||||||
for (const auto& filePath : deleteFiles) {
|
for (const auto& filePath : deleteFiles) {
|
||||||
if (contentFS->remove(filePath.as<const char*>())) {
|
if (contentFS->remove(filePath.as<const char*>())) {
|
||||||
wsSerial("deleted file: " + filePath.as<String>());
|
wsLog("deleted file: " + filePath.as<String>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
wsSerial("Cleanup finished");
|
wsLog("Cleanup finished");
|
||||||
request->send(200, "Clean up finished");
|
request->send(200, "Clean up finished");
|
||||||
contentFS->remove("/update_actions.json");
|
contentFS->remove("/update_actions.json");
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,8 @@ static SPIClass* spi;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "LittleFS.h"
|
#include "LittleFS.h"
|
||||||
|
#include "web.h"
|
||||||
|
#include "ota.h"
|
||||||
|
|
||||||
DynStorage::DynStorage() : isInited(0) {}
|
DynStorage::DynStorage() : isInited(0) {}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user