feat: update version to 1.2.3; modify HTML files to reflect new version; enhance firmware update process and UI improvements
This commit is contained in:
235
src/ota.cpp
235
src/ota.cpp
@ -3,219 +3,44 @@
|
||||
#include <Update.h>
|
||||
#include <SPIFFS.h>
|
||||
#include "commonFS.h"
|
||||
#include <esp_task_wdt.h>
|
||||
#include <esp_int_wdt.h>
|
||||
#include <esp_pthread.h>
|
||||
#include <esp_ota_ops.h>
|
||||
|
||||
// Reduzierter Puffer für Dateioperationen
|
||||
const size_t BUFFER_SIZE = 128;
|
||||
const size_t MIN_FREE_HEAP = 32768; // 32KB minimum free heap
|
||||
|
||||
// Files to backup before update
|
||||
const char* CONFIG_FILES[] = {
|
||||
"/bambu_credentials.json",
|
||||
"/spoolman_url.json"
|
||||
};
|
||||
const int CONFIG_FILES_COUNT = sizeof(CONFIG_FILES) / sizeof(CONFIG_FILES[0]);
|
||||
|
||||
bool backupConfigs() {
|
||||
if (!SPIFFS.begin(true)) {
|
||||
Serial.println("Failed to mount SPIFFS");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < CONFIG_FILES_COUNT; i++) {
|
||||
if (SPIFFS.exists(CONFIG_FILES[i])) {
|
||||
String backupFile = String(CONFIG_FILES[i]) + ".bak";
|
||||
|
||||
if (SPIFFS.exists(backupFile)) {
|
||||
SPIFFS.remove(backupFile);
|
||||
}
|
||||
|
||||
File sourceFile = SPIFFS.open(CONFIG_FILES[i], "r");
|
||||
File destFile = SPIFFS.open(backupFile, "w");
|
||||
|
||||
if (!sourceFile || !destFile) {
|
||||
Serial.printf("Failed to open files for backup: %s\n", CONFIG_FILES[i]);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verwenden Sie einen kleineren Puffer
|
||||
uint8_t* buf = (uint8_t*)malloc(BUFFER_SIZE);
|
||||
if (!buf) {
|
||||
Serial.println("Failed to allocate buffer");
|
||||
sourceFile.close();
|
||||
destFile.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
bool success = true;
|
||||
while ((len = sourceFile.read(buf, BUFFER_SIZE)) > 0) {
|
||||
if (destFile.write(buf, len) != len) {
|
||||
Serial.println("Write failed");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
sourceFile.close();
|
||||
destFile.close();
|
||||
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool restoreConfigs() {
|
||||
if (!SPIFFS.begin(true)) {
|
||||
Serial.println("Failed to mount SPIFFS");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
for (int i = 0; i < CONFIG_FILES_COUNT; i++) {
|
||||
String backupFile = String(CONFIG_FILES[i]) + ".bak";
|
||||
if (SPIFFS.exists(backupFile)) {
|
||||
if (SPIFFS.exists(CONFIG_FILES[i])) {
|
||||
SPIFFS.remove(CONFIG_FILES[i]);
|
||||
}
|
||||
|
||||
File sourceFile = SPIFFS.open(backupFile, "r");
|
||||
File destFile = SPIFFS.open(CONFIG_FILES[i], "w");
|
||||
|
||||
if (!sourceFile || !destFile) {
|
||||
Serial.printf("Failed to open files for restore: %s\n", CONFIG_FILES[i]);
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Verwenden Sie einen kleineren Puffer
|
||||
uint8_t* buf = (uint8_t*)malloc(BUFFER_SIZE);
|
||||
if (!buf) {
|
||||
Serial.println("Failed to allocate buffer");
|
||||
sourceFile.close();
|
||||
destFile.close();
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
while ((len = sourceFile.read(buf, BUFFER_SIZE)) > 0) {
|
||||
if (destFile.write(buf, len) != len) {
|
||||
Serial.println("Write failed");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
sourceFile.close();
|
||||
destFile.close();
|
||||
|
||||
SPIFFS.remove(backupFile);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void handleOTAUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||
static bool updateStarted = false;
|
||||
static size_t totalBytes = 0;
|
||||
static size_t totalSize = 0;
|
||||
|
||||
if (!index) {
|
||||
updateStarted = false;
|
||||
totalBytes = 0;
|
||||
totalSize = request->contentLength();
|
||||
|
||||
// Check minimum heap size
|
||||
if (ESP.getFreeHeap() < MIN_FREE_HEAP) {
|
||||
request->send(500, "text/plain", "Not enough memory available");
|
||||
return;
|
||||
}
|
||||
|
||||
if (totalSize == 0) {
|
||||
request->send(400, "text/plain", "Invalid file size");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("Update size: %u bytes\n", totalSize);
|
||||
Serial.printf("Free space: %u bytes\n", ESP.getFreeSketchSpace());
|
||||
Serial.printf("Free heap: %u bytes\n", ESP.getFreeHeap());
|
||||
|
||||
// Backup configs first
|
||||
if (!backupConfigs()) {
|
||||
request->send(500, "text/plain", "Failed to backup configuration");
|
||||
return;
|
||||
}
|
||||
|
||||
// Close all files and unmount SPIFFS
|
||||
SPIFFS.end();
|
||||
|
||||
// Begin update with minimal configuration
|
||||
if (!Update.begin(totalSize)) {
|
||||
Serial.printf("Update.begin failed: %s\n", Update.errorString());
|
||||
request->send(500, "text/plain", "Failed to start update");
|
||||
return;
|
||||
}
|
||||
|
||||
updateStarted = true;
|
||||
Serial.println("Update process started");
|
||||
|
||||
// Send initial progress
|
||||
request->send(200, "text/plain", "0");
|
||||
}
|
||||
|
||||
if (!updateStarted) {
|
||||
request->send(500, "text/plain", "Update not properly started");
|
||||
return;
|
||||
}
|
||||
|
||||
// Write update data
|
||||
if (Update.write(data, len) != len) {
|
||||
Serial.printf("Update.write failed: %s\n", Update.errorString());
|
||||
Update.abort();
|
||||
request->send(500, "text/plain", "Error during update");
|
||||
return;
|
||||
}
|
||||
|
||||
totalBytes += len;
|
||||
static size_t contentLength = 0;
|
||||
|
||||
// Send progress update
|
||||
if (!final) {
|
||||
int progress = (totalBytes * 100) / totalSize;
|
||||
request->send(200, "text/plain", String(progress));
|
||||
if (!index) {
|
||||
contentLength = request->contentLength();
|
||||
Serial.printf("Update size: %u bytes\n", contentLength);
|
||||
|
||||
if (contentLength == 0) {
|
||||
request->send(400, "application/json", "{\"status\":\"error\",\"message\":\"Invalid file size\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Update.begin(contentLength)) {
|
||||
Serial.printf("Not enough space: %u required\n", contentLength);
|
||||
request->send(400, "application/json", "{\"status\":\"error\",\"message\":\"Not enough space available\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("Update started");
|
||||
}
|
||||
|
||||
if (Update.write(data, len) != len) {
|
||||
Update.printError(Serial);
|
||||
request->send(400, "application/json", "{\"status\":\"error\",\"message\":\"Error writing update\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (final) {
|
||||
if (!Update.end(true)) {
|
||||
Serial.printf("Update.end failed: %s\n", Update.errorString());
|
||||
request->send(500, "text/plain", "Update failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to restore configs
|
||||
if (!SPIFFS.begin(true)) {
|
||||
Serial.println("Failed to mount SPIFFS for restore");
|
||||
request->send(200, "application/json", "{\"status\": \"success\", \"message\": \"Update successful but config restore failed. Device will restart...\", \"restart\": true}");
|
||||
delay(2000);
|
||||
if (Update.end(true)) {
|
||||
Serial.println("Update complete");
|
||||
request->send(200, "application/json", "{\"status\":\"success\",\"message\":\"Update successful! Device will restart...\",\"restart\":true}");
|
||||
delay(1000);
|
||||
ESP.restart();
|
||||
return;
|
||||
} else {
|
||||
Update.printError(Serial);
|
||||
request->send(400, "application/json", "{\"status\":\"error\",\"message\":\"Update failed\"}");
|
||||
}
|
||||
|
||||
if (!restoreConfigs()) {
|
||||
Serial.println("Failed to restore configs");
|
||||
}
|
||||
|
||||
request->send(200, "application/json", "{\"status\": \"success\", \"message\": \"Update successful! Device will restart...\", \"restart\": true}");
|
||||
delay(2000);
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ void setupWebserver(AsyncWebServer &server) {
|
||||
// Route für about
|
||||
server.on("/about", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
Serial.println("Anfrage für /about erhalten");
|
||||
AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/about.html.gz", "text/html");
|
||||
AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/index.html.gz", "text/html");
|
||||
response->addHeader("Content-Encoding", "gzip");
|
||||
response->addHeader("Cache-Control", CACHE_CONTROL);
|
||||
request->send(response);
|
||||
@ -338,8 +338,13 @@ void setupWebserver(AsyncWebServer &server) {
|
||||
Serial.println("RFID.js gesendet");
|
||||
});
|
||||
|
||||
// Route für Firmware Update
|
||||
// Route for Firmware Update
|
||||
server.on("/upgrade", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
// During OTA, reduce memory usage
|
||||
ws.enable(false); // Temporarily disable WebSocket
|
||||
ws.cleanupClients();
|
||||
|
||||
Serial.println("Request for /upgrade received");
|
||||
AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/upgrade.html.gz", "text/html");
|
||||
response->addHeader("Content-Encoding", "gzip");
|
||||
response->addHeader("Cache-Control", CACHE_CONTROL);
|
||||
@ -350,7 +355,12 @@ void setupWebserver(AsyncWebServer &server) {
|
||||
[](AsyncWebServerRequest *request) {
|
||||
// The response will be sent from handleOTAUpload when the upload is complete
|
||||
},
|
||||
handleOTAUpload
|
||||
[](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||
// Free memory before handling update
|
||||
ws.enable(false);
|
||||
ws.cleanupClients();
|
||||
handleOTAUpload(request, filename, index, data, len, final);
|
||||
}
|
||||
);
|
||||
|
||||
// Fehlerbehandlung für nicht gefundene Seiten
|
||||
|
Reference in New Issue
Block a user