From b8e4af4e4db31c6bb3b1798d15c8b652934953ac Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 21 Feb 2025 10:35:52 +0100 Subject: [PATCH] refactor: update SPIFFS initialization and partition sizes; enhance WiFi setup --- .github/workflows/providers/gitea-release.yml | 6 +- .../workflows/providers/github-release.yml | 6 +- html/upgrade.html | 238 ++++++------------ partitions.csv | 6 +- platformio.ini | 42 +--- scripts/pre_spiffs.py | 18 ++ src/commonFS.cpp | 26 +- src/commonFS.h | 2 +- src/ota.cpp | 2 +- src/website.cpp | 94 ++++++- src/website.h | 10 +- src/wlan.cpp | 1 + 12 files changed, 220 insertions(+), 231 deletions(-) diff --git a/.github/workflows/providers/gitea-release.yml b/.github/workflows/providers/gitea-release.yml index c7ca805..29cc691 100644 --- a/.github/workflows/providers/gitea-release.yml +++ b/.github/workflows/providers/gitea-release.yml @@ -63,7 +63,7 @@ jobs: # Create release files cp spiffs.bin filaman_spiffs.bin - # Create full binary + # Create full binary with correct partition offsets echo "Creating full binary..." esptool.py --chip esp32 merge_bin \ --fill-flash-size 4MB \ @@ -71,10 +71,10 @@ jobs: --flash_freq 40m \ --flash_size 4MB \ -o filaman_full.bin \ - 0x0000 bootloader.bin \ + 0x1000 bootloader.bin \ 0x8000 partitions.bin \ 0x10000 firmware.bin \ - 0x390000 spiffs.bin + 0x310000 spiffs.bin # Verify file sizes echo "File sizes:" diff --git a/.github/workflows/providers/github-release.yml b/.github/workflows/providers/github-release.yml index 5d899d2..31e7f7d 100644 --- a/.github/workflows/providers/github-release.yml +++ b/.github/workflows/providers/github-release.yml @@ -52,7 +52,7 @@ jobs: # Create release files cp spiffs.bin filaman_spiffs.bin - # Create full binary + # Create full binary with correct partition offsets echo "Creating full binary..." esptool.py --chip esp32 merge_bin \ --fill-flash-size 4MB \ @@ -60,10 +60,10 @@ jobs: --flash_freq 40m \ --flash_size 4MB \ -o filaman_full.bin \ - 0x0000 bootloader.bin \ + 0x1000 bootloader.bin \ 0x8000 partitions.bin \ 0x10000 firmware.bin \ - 0x390000 spiffs.bin + 0x310000 spiffs.bin # Verify file sizes echo "File sizes:" diff --git a/html/upgrade.html b/html/upgrade.html index 9370308..f883c9c 100644 --- a/html/upgrade.html +++ b/html/upgrade.html @@ -1,190 +1,116 @@ - + - FilaMan - Filament Management Tool - + FilaMan - Firmware Update + - - - -
-

Firmware Upgrade

- +

Firmware Update

+
- Warning: Please do not turn off or restart the device during the update. - The device will restart automatically after the update. + Warning: Do not power off the device during update.
-
-
- - -
+
+ + +
+ + -
-
0%
-
-
+
diff --git a/partitions.csv b/partitions.csv index f8b271b..a494bd7 100644 --- a/partitions.csv +++ b/partitions.csv @@ -1,6 +1,6 @@ # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x5000, otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x1C0000, -app1, app, ota_1, 0x1D0000, 0x1C0000, -spiffs, data, spiffs, 0x390000, 0x60000, \ No newline at end of file +app0, app, ota_0, 0x10000, 0x180000, +app1, app, ota_1, 0x190000, 0x180000, +spiffs, data, spiffs, 0x310000, 0xE0000, \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index f0948ad..9ee1e72 100644 --- a/platformio.ini +++ b/platformio.ini @@ -19,8 +19,10 @@ monitor_speed = 115200 lib_deps = tzapu/WiFiManager @ ^2.0.17 - https://github.com/me-no-dev/ESPAsyncWebServer.git#master - me-no-dev/AsyncTCP @ ^1.1.1 + #https://github.com/me-no-dev/ESPAsyncWebServer.git#master + #me-no-dev/AsyncTCP @ ^1.1.1 + mathieucarbou/ESPAsyncWebServer @ ^3.6.0 + esp32async/AsyncTCP @ ^3.3.5 bogde/HX711 @ ^0.7.5 adafruit/Adafruit SSD1306 @ ^2.5.13 adafruit/Adafruit GFX Library @ ^1.11.11 @@ -48,38 +50,14 @@ build_flags = -DCORE_DEBUG_LEVEL=3 -DCONFIG_ARDUHAL_LOG_COLORS=1 -DOTA_DEBUG=1 - -DARDUINO_RUNNING_CORE=1 - -DARDUINO_EVENT_RUNNING_CORE=1 -DCONFIG_ESP32_PANIC_PRINT_REBOOT -DCONFIG_ARDUINO_OTA_READSIZE=8192 - -DCONFIG_ASYNC_TCP_RUNNING_CORE=1 - -DCONFIG_ASYNC_TCP_USE_WDT=0 - -DASYNC_TCP_USE_WDT=0 - -DCONFIG_LWIP_TCP_TMR_INTERVAL=25 - -DCONFIG_LWIP_TCP_MSS=1436 - -DCONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 - -DCONFIG_LWIP_TCP_WND_DEFAULT=5744 - -DCONFIG_LWIP_TCP_RCV_BUF_DEFAULT=11488 - -DCONFIG_LWIP_TCP_RECVMBOX_SIZE=64 - -DCONFIG_LWIP_MAX_SOCKETS=10 - -DCONFIG_LWIP_MAX_ACTIVE_TCP=16 - -DCONFIG_LWIP_MAX_LISTENING_TCP=16 - -DCONFIG_LWIP_TCP_MAXRTX=6 - -DCONFIG_LWIP_TCP_SYNMAXRTX=3 - -DCONFIG_LWIP_TCP_QUEUE_OOSEQ=0 - -DCONFIG_LWIP_TCP_OVERSIZE_MSS=0 - -DCONFIG_LWIP_TCP_RTO_TIME=1500 - -DCONFIG_LWIP_IPV6=0 - -DCONFIG_LWIP_STATS=0 - -DCONFIG_LWIP_USE_ONLY_LWIP_SELECT=1 - -DCONFIG_LWIP_NETIF_LOOPBACK=0 - -DCONFIG_LWIP_IRAM_OPTIMIZATION=1 - -DCONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 - -DCONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 - -DCONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 - -DCONFIG_ESP32_WIFI_TX_BA_WIN=6 - -DCONFIG_ESP32_WIFI_RX_BA_WIN=6 - -DCONFIG_ESP32_WIFI_CSI_ENABLED=0 + -DCONFIG_PARTITION_TABLE_OFFSET=0x8000 + -DCONFIG_PARTITION_TABLE_MD5=y + -DCONFIG_APP_ROLLBACK_ENABLE=1 + -DSPIFFS_MAX_PARTITIONS=3 + -DCONFIG_SPIFFS_LOG_BLOCK_SIZE=4096 + -DCONFIG_SPIFFS_CACHE=y extra_scripts = scripts/extra_script.py diff --git a/scripts/pre_spiffs.py b/scripts/pre_spiffs.py index 5c6da82..1f4a1e2 100644 --- a/scripts/pre_spiffs.py +++ b/scripts/pre_spiffs.py @@ -1,5 +1,23 @@ Import("env") +board_config = env.BoardConfig() + +# Calculate SPIFFS size based on partition table +SPIFFS_START = 0x310000 # From partitions.csv +SPIFFS_SIZE = 0xE0000 # From partitions.csv +SPIFFS_PAGE = 256 +SPIFFS_BLOCK = 4096 + +env.Replace( + MKSPIFFSTOOL="mkspiffs", + SPIFFSBLOCKSZ=SPIFFS_BLOCK, + SPIFFSBLOCKSIZE=SPIFFS_BLOCK, + SPIFFSSTART=SPIFFS_START, + SPIFFSEND=SPIFFS_START + SPIFFS_SIZE, + SPIFFSPAGESZ=SPIFFS_PAGE, + SPIFFSSIZE=SPIFFS_SIZE +) + # Wiederverwendung der replace_version Funktion exec(open("./scripts/pre_build.py").read()) diff --git a/src/commonFS.cpp b/src/commonFS.cpp index 1e5fcdd..05487ee 100644 --- a/src/commonFS.cpp +++ b/src/commonFS.cpp @@ -1,4 +1,5 @@ #include "commonFS.h" +#include bool saveJsonValue(const char* filename, const JsonDocument& doc) { File file = SPIFFS.open(filename, "w"); @@ -35,23 +36,12 @@ bool loadJsonValue(const char* filename, JsonDocument& doc) { return true; } -bool initializeSPIFFS() { - // Erster Versuch - if (SPIFFS.begin(true)) { - Serial.println("SPIFFS mounted successfully."); - return true; +void initializeSPIFFS() { + if (!SPIFFS.begin(true, "/spiffs", 10, "spiffs")) { + Serial.println("SPIFFS Mount Failed"); + return; } - - // Formatierung versuchen - Serial.println("Failed to mount SPIFFS. Formatting..."); - SPIFFS.format(); - - // Zweiter Versuch nach Formatierung - if (SPIFFS.begin(true)) { - Serial.println("SPIFFS formatted and mounted successfully."); - return true; - } - - Serial.println("SPIFFS initialization failed completely."); - return false; + Serial.printf("SPIFFS Total: %u bytes\n", SPIFFS.totalBytes()); + Serial.printf("SPIFFS Used: %u bytes\n", SPIFFS.usedBytes()); + Serial.printf("SPIFFS Free: %u bytes\n", SPIFFS.totalBytes() - SPIFFS.usedBytes()); } \ No newline at end of file diff --git a/src/commonFS.h b/src/commonFS.h index b94dadd..273bf72 100644 --- a/src/commonFS.h +++ b/src/commonFS.h @@ -7,6 +7,6 @@ bool saveJsonValue(const char* filename, const JsonDocument& doc); bool loadJsonValue(const char* filename, JsonDocument& doc); -bool initializeSPIFFS(); +void initializeSPIFFS(); #endif diff --git a/src/ota.cpp b/src/ota.cpp index be8f3f0..de30e9f 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -10,7 +10,7 @@ #define UPLOAD_TIMEOUT_MS 60000 // 60 Sekunden Timeout für den gesamten Upload #define CHUNK_RESPONSE_TIMEOUT_MS 10000 // 10 Sekunden Timeout pro Chunk #define MAX_FAILED_CHUNKS 3 // Maximale Anzahl fehlgeschlagener Chunks bevor Abbruch -#define MAX_FILE_SIZE 4000000 // 4MB Limit +#define MAX_FILE_SIZE 4194304 // 4MB Limit static bool tasksAreStopped = false; static uint32_t lastChunkTime = 0; diff --git a/src/website.cpp b/src/website.cpp index dd2636d..9f4f61c 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -8,9 +8,11 @@ #include "scale.h" #include "esp_task_wdt.h" #include "ota.h" +#include // Cache-Control Header definieren #define CACHE_CONTROL "max-age=31536000" // Cache für 1 Jahr +#define MAX_UPLOAD_SIZE 4194304 // 4MB maximale Upload-Größe AsyncWebServer server(webserverPort); AsyncWebSocket ws("/ws"); @@ -156,6 +158,10 @@ void sendAmsData(AsyncWebSocketClient *client) { } void setupWebserver(AsyncWebServer &server) { + // Konfiguriere Server für große Uploads + server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){}); + server.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){}); + // Lade die Spoolman-URL beim Booten spoolmanUrl = loadSpoolmanUrl(); Serial.print("Geladene Spoolman-URL: "); @@ -338,28 +344,72 @@ void setupWebserver(AsyncWebServer &server) { Serial.println("RFID.js gesendet"); }); - // Route for Firmware Update + // Vereinfachter Update-Handler 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); + response->addHeader("Cache-Control", "no-store"); request->send(response); }); + // Update-Handler mit verbesserter Fehlerbehandlung server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request) { - // The response will be sent from handleOTAUpload when the upload is complete + // Nach Update-Abschluss + bool success = !Update.hasError(); + AsyncWebServerResponse *response = request->beginResponse( + success ? 200 : 400, + "application/json", + success ? "{\"success\":true,\"message\":\"Update successful\"}" + : "{\"success\":false,\"message\":\"Update failed\"}" + ); + response->addHeader("Connection", "close"); + request->send(response); + + if (success) { + delay(500); + ESP.restart(); + } }, [](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); + static size_t updateSize = 0; + static int command = 0; + + if (!index) { + updateSize = request->contentLength(); + command = (filename.indexOf("spiffs") > -1) ? U_SPIFFS : U_FLASH; + Serial.printf("Update Start: %s\nSize: %u\nCommand: %d\n", filename.c_str(), updateSize, command); + + if (!Update.begin(updateSize, command)) { + Serial.printf("Update Begin Error: "); + Update.printError(Serial); + String errorMsg = String("Update begin failed: ") + Update.errorString(); + request->send(400, "application/json", "{\"success\":false,\"message\":\"" + errorMsg + "\"}"); + return; + } + } + + if (len) { + if (Update.write(data, len) != len) { + Serial.printf("Update Write Error: "); + Update.printError(Serial); + String errorMsg = String("Write failed: ") + Update.errorString(); + request->send(400, "application/json", "{\"success\":false,\"message\":\"" + errorMsg + "\"}"); + return; + } + Serial.printf("Progress: %u/%u\r", index + len, updateSize); + } + + if (final) { + if (!Update.end(true)) { + Serial.printf("Update End Error: "); + Update.printError(Serial); + String errorMsg = String("Update end failed: ") + Update.errorString(); + request->send(400, "application/json", "{\"success\":false,\"message\":\"" + errorMsg + "\"}"); + return; + } + Serial.printf("\nUpdate Success: %uB\n", index+len); + } } ); @@ -379,3 +429,23 @@ void setupWebserver(AsyncWebServer &server) { server.begin(); Serial.println("Webserver gestartet"); } + +// Upload-Handler für alle Datei-Uploads +void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { + if (!filename.endsWith(".bin")) { + request->send(400, "application/json", "{\"success\":false,\"message\":\"Invalid file type\"}"); + return; + } + + if (request->url() == "/update") { + handleOTAUpload(request, filename, index, data, len, final); + } +} + +// Body-Handler für große Anfragen +void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) { + // Handler für große POST-Anfragen + if (total > MAX_UPLOAD_SIZE) { + request->send(413, "application/json", "{\"success\":false,\"message\":\"File too large\"}"); + } +} \ No newline at end of file diff --git a/src/website.h b/src/website.h index e35a25e..06627b1 100644 --- a/src/website.h +++ b/src/website.h @@ -6,8 +6,8 @@ #include "commonFS.h" #include "api.h" #include -#include -#include +#include +#include #include "bambu.h" #include "nfc.h" #include "scale.h" @@ -17,7 +17,13 @@ extern String spoolmanUrl; extern AsyncWebServer server; extern AsyncWebSocket ws; +// Server-Initialisierung und Handler +void initWebServer(); +void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); +void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total); void setupWebserver(AsyncWebServer &server); + +// WebSocket-Funktionen void sendAmsData(AsyncWebSocketClient *client); void sendNfcData(AsyncWebSocketClient *client); void foundNfcTag(AsyncWebSocketClient *client, uint8_t success); diff --git a/src/wlan.cpp b/src/wlan.cpp index bb94583..c4f844d 100644 --- a/src/wlan.cpp +++ b/src/wlan.cpp @@ -12,6 +12,7 @@ bool wm_nonblocking = false; void initWiFi() { WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP WiFi.setSleep(false); // disable sleep mode + esp_wifi_set_ps(WIFI_PS_NONE); //esp_wifi_set_max_tx_power(72); // Setze maximale Sendeleistung auf 20dBm