Compare commits
	
		
			5 Commits
		
	
	
		
			v1.3.95
			...
			e4825d2905
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e4825d2905 | |||
| c1733848d3 | |||
| 484c95523d | |||
| 8499613215 | |||
| 08f37186b4 | 
							
								
								
									
										31
									
								
								html/own_filaments.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								html/own_filaments.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| { | ||||
|     "TPU": "GFU99", | ||||
|     "PA": "GFN99", | ||||
|     "PA-CF": "GFN98", | ||||
|     "PLA": "GFL99", | ||||
|     "PLA Silk": "GFL96", | ||||
|     "PLA-CF": "GFL98", | ||||
|     "PLA High Speed": "GFL95", | ||||
|     "PETG": "GFG99", | ||||
|     "PETG-CF": "GFG98", | ||||
|     "PCTG": "GFG97", | ||||
|     "ABS": "GFB99", | ||||
|     "ABS+HS": "GFB99", | ||||
|     "PC": "GFC99", | ||||
|     "PC/ABS": "GFC99", | ||||
|     "ASA": "GFB98", | ||||
|     "PVA": "GFS99", | ||||
|     "HIPS": "GFS98", | ||||
|     "PPS-CF": "GFT98", | ||||
|     "PPS": "GFT97", | ||||
|     "PPA-CF": "GFN97", | ||||
|     "PPA-GF": "GFN96", | ||||
|     "PE": "GFP99", | ||||
|     "PE-CF": "GFP98", | ||||
|     "PP": "GFP97", | ||||
|     "PP-CF": "GFP96", | ||||
|     "PP-GF": "GFP95", | ||||
|     "EVA": "GFR99", | ||||
|     "PHA": "GFR98", | ||||
|     "BVOH": "GFS97" | ||||
| } | ||||
| @@ -76,7 +76,7 @@ | ||||
|             const code = document.getElementById('bambuCode').value; | ||||
|             const autoSend = document.getElementById('autoSend').checked; | ||||
|  | ||||
|             fetch(`/api/bambu?bambu_ip=${encodeURIComponent(ip)}&bambu_serialnr=${encodeURIComponent(serial)}&bambu_accesscode=${encodeURIComponent(code)}&autoSend=${autoSend}`) | ||||
|             fetch(`/api/bambu?bambu_ip=${encodeURIComponent(ip)}&bambu_serialnr=${encodeURIComponent(serial)}&bambu_accesscode=${encodeURIComponent(code)}&autoSend=${autoSend}$autoSendTime=${autoSendTime}`) | ||||
|                 .then(response => response.json()) | ||||
|                 .then(data => { | ||||
|                     if (data.healthy) { | ||||
| @@ -122,13 +122,18 @@ | ||||
|                         <label for="bambuCode">Access Code:</label> | ||||
|                         <input type="text" id="bambuCode" placeholder="Access Code vom Drucker" value="{{bambuCode}}"> | ||||
|                     </div> | ||||
|                     <div class="input-group"> | ||||
|                         If activated, FilaMan will automatically update the next filled tray with the last scanned and weighed spool. | ||||
|                         <label for="autoSend">Auto Send to Bambu:</label> | ||||
|                         <input type="checkbox" id="autoSend" {{autoSendToBambu}}> | ||||
|                     <hr> | ||||
|                     <p>If activated, FilaMan will automatically update the next filled tray with the last scanned and weighed spool.</p> | ||||
|                     <div class="input-group" style="display: flex; margin-bottom: 0;"> | ||||
|                         <label for="autoSend" style="width: 250px; margin-right: 5px;">Auto Send to Bambu:</label> | ||||
|                         <label for="autoSendTime" style="width: 250px; margin-right: 5px;">Wait time in Seconds:</label> | ||||
|                     </div> | ||||
|                     <div class="input-group" style="display: flex;"> | ||||
|                         <input type="checkbox" id="autoSend" {{autoSendToBambu}} style="width: 190px; margin-right: 10px;"> | ||||
|                         <input type="text" id="autoSendTime" placeholder="Time to wait for new Spool" value="{{autoSendTime}}" style="width: 100px;"> | ||||
|                     </div> | ||||
|  | ||||
|                     <button onclick="saveBambuCredentials()">Save Bambu Credentials</button> | ||||
|                     <button style="margin: 0;" onclick="saveBambuCredentials()">Save Bambu Credentials</button> | ||||
|                     <p id="bambuStatusMessage"></p> | ||||
|                 </div> | ||||
|             </div> | ||||
|   | ||||
| @@ -32,7 +32,7 @@ int ams_count = 0; | ||||
| String amsJsonData;  // Speichert das fertige JSON für WebSocket-Clients | ||||
| AMSData ams_data[MAX_AMS];  // Definition des Arrays; | ||||
|  | ||||
| bool saveBambuCredentials(const String& ip, const String& serialnr, const String& accesscode, bool autoSend) { | ||||
| bool saveBambuCredentials(const String& ip, const String& serialnr, const String& accesscode, bool autoSend, const String& autoSendTime) { | ||||
|     if (BambuMqttTask) { | ||||
|         vTaskDelete(BambuMqttTask); | ||||
|     } | ||||
| @@ -42,6 +42,7 @@ bool saveBambuCredentials(const String& ip, const String& serialnr, const String | ||||
|     doc["bambu_accesscode"] = accesscode; | ||||
|     doc["bambu_serialnr"] = serialnr; | ||||
|     doc["autoSendToBambu"] = autoSend; | ||||
|     doc["autoSendTime"] = (autoSendTime != "") ? autoSendTime.toInt() : autoSetBambuAmsCounter; | ||||
|  | ||||
|     if (!saveJsonValue("/bambu_credentials.json", doc)) { | ||||
|         Serial.println("Fehler beim Speichern der Bambu-Credentials."); | ||||
| @@ -53,6 +54,7 @@ bool saveBambuCredentials(const String& ip, const String& serialnr, const String | ||||
|     bambu_accesscode = accesscode.c_str(); | ||||
|     bambu_serialnr = serialnr.c_str(); | ||||
|     autoSendToBambu = autoSend; | ||||
|     autoSetBambuAmsCounter = autoSendTime.toInt(); | ||||
|  | ||||
|     vTaskDelay(100 / portTICK_PERIOD_MS); | ||||
|     if (!setupMqtt()) return false; | ||||
| @@ -67,7 +69,8 @@ bool loadBambuCredentials() { | ||||
|         String ip = doc["bambu_ip"].as<String>(); | ||||
|         String code = doc["bambu_accesscode"].as<String>(); | ||||
|         String serial = doc["bambu_serialnr"].as<String>(); | ||||
|         autoSendToBambu = doc["autoSendToBambu"].as<bool>(); | ||||
|         if (doc["autoSendToBambu"].is<bool>()) autoSendToBambu = doc["autoSendToBambu"].as<bool>(); | ||||
|         if (doc["autoSendTime"].is<int>()) autoSetBambuAmsCounter = doc["autoSendTime"].as<int>(); | ||||
|  | ||||
|         ip.trim(); | ||||
|         code.trim(); | ||||
| @@ -95,12 +98,37 @@ FilamentResult findFilamentIdx(String brand, String type) { | ||||
|     // JSON-Dokument für die Filament-Daten erstellen | ||||
|     JsonDocument doc; | ||||
|      | ||||
|     // Laden der own_filaments.json | ||||
|     String ownFilament = ""; | ||||
|     if (!loadJsonValue("/own_filaments.json", doc))  | ||||
|     { | ||||
|         Serial.println("Fehler beim Laden der eigenen Filament-Daten"); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // Durchsuche direkt nach dem Type als Schlüssel | ||||
|         if (doc[type].is<String>()) { | ||||
|             ownFilament = doc[type].as<String>(); | ||||
|         } | ||||
|         doc.clear(); | ||||
|     } | ||||
|  | ||||
|     // Laden der bambu_filaments.json | ||||
|     if (!loadJsonValue("/bambu_filaments.json", doc)) { | ||||
|     if (!loadJsonValue("/bambu_filaments.json", doc))  | ||||
|     { | ||||
|         Serial.println("Fehler beim Laden der Filament-Daten"); | ||||
|         return {"GFL99", "PLA"}; // Fallback auf Generic PLA | ||||
|     } | ||||
|  | ||||
|     // Wenn eigener Typ | ||||
|     if (ownFilament != "") | ||||
|     { | ||||
|         if (doc[ownFilament].is<String>())  | ||||
|         { | ||||
|             return {ownFilament, doc[ownFilament].as<String>()}; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // 1. Erst versuchen wir die exakte Brand + Type Kombination zu finden | ||||
|     String searchKey; | ||||
|     if (brand == "Bambu" || brand == "Bambulab") { | ||||
|   | ||||
| @@ -114,6 +114,8 @@ void loop() { | ||||
|  | ||||
|   // Wenn Bambu auto set Spool aktiv | ||||
|   if (autoSendToBambu && autoSetToBambuSpoolId > 0 && currentMillis - lastAutoSetBambuAmsTime >= autoSetBambuAmsInterval)  | ||||
|   { | ||||
|     if (hasReadRfidTag == 0) | ||||
|     { | ||||
|       lastAutoSetBambuAmsTime = currentMillis; | ||||
|       oledShowMessage("Auto Set         " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s"); | ||||
| @@ -126,6 +128,11 @@ void loop() { | ||||
|         oledShowWeight(weight); | ||||
|       } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       autoAmsCounter = 0; | ||||
|     } | ||||
|   } | ||||
|    | ||||
|  | ||||
|   // Wenn Waage nicht Kalibriert | ||||
|   | ||||
							
								
								
									
										199
									
								
								src/ota.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								src/ota.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,199 @@ | ||||
| #include <Arduino.h> | ||||
| #include <website.h> | ||||
| #include <commonFS.h> | ||||
|  | ||||
| // Globale Variablen für Config Backups hinzufügen | ||||
| String bambuCredentialsBackup; | ||||
| String spoolmanUrlBackup; | ||||
|  | ||||
| // Globale Variable für den Update-Typ | ||||
| static int currentUpdateCommand = 0; | ||||
|  | ||||
| // Globale Update-Variablen | ||||
| static size_t updateTotalSize = 0; | ||||
| static size_t updateWritten = 0; | ||||
| static bool isSpiffsUpdate = false; | ||||
|  | ||||
|  | ||||
| void backupJsonConfigs() { | ||||
|     // Bambu Credentials backup | ||||
|     if (SPIFFS.exists("/bambu_credentials.json")) { | ||||
|         File file = SPIFFS.open("/bambu_credentials.json", "r"); | ||||
|         if (file) { | ||||
|             bambuCredentialsBackup = file.readString(); | ||||
|             file.close(); | ||||
|             Serial.println("Bambu credentials backed up"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Spoolman URL backup | ||||
|     if (SPIFFS.exists("/spoolman_url.json")) { | ||||
|         File file = SPIFFS.open("/spoolman_url.json", "r"); | ||||
|         if (file) { | ||||
|             spoolmanUrlBackup = file.readString(); | ||||
|             file.close(); | ||||
|             Serial.println("Spoolman URL backed up"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void restoreJsonConfigs() { | ||||
|     // Restore Bambu credentials | ||||
|     if (bambuCredentialsBackup.length() > 0) { | ||||
|         File file = SPIFFS.open("/bambu_credentials.json", "w"); | ||||
|         if (file) { | ||||
|             file.print(bambuCredentialsBackup); | ||||
|             file.close(); | ||||
|             Serial.println("Bambu credentials restored"); | ||||
|         } | ||||
|         bambuCredentialsBackup = ""; // Clear backup | ||||
|     } | ||||
|  | ||||
|     // Restore Spoolman URL | ||||
|     if (spoolmanUrlBackup.length() > 0) { | ||||
|         File file = SPIFFS.open("/spoolman_url.json", "w"); | ||||
|         if (file) { | ||||
|             file.print(spoolmanUrlBackup); | ||||
|             file.close(); | ||||
|             Serial.println("Spoolman URL restored"); | ||||
|         } | ||||
|         spoolmanUrlBackup = ""; // Clear backup | ||||
|     } | ||||
| } | ||||
|  | ||||
| void espRestart() { | ||||
|     yield(); | ||||
|     vTaskDelay(5000 / portTICK_PERIOD_MS); | ||||
|  | ||||
|     ESP.restart(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void sendUpdateProgress(int progress, const char* status = nullptr, const char* message = nullptr) { | ||||
|     static int lastSentProgress = -1; | ||||
|      | ||||
|     // Verhindere zu häufige Updates | ||||
|     if (progress == lastSentProgress && !status && !message) { | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     String progressMsg = "{\"type\":\"updateProgress\",\"progress\":" + String(progress); | ||||
|     if (status) { | ||||
|         progressMsg += ",\"status\":\"" + String(status) + "\""; | ||||
|     } | ||||
|     if (message) { | ||||
|         progressMsg += ",\"message\":\"" + String(message) + "\""; | ||||
|     } | ||||
|     progressMsg += "}"; | ||||
|      | ||||
|     // Sende die Nachricht mehrmals mit Verzögerung für wichtige Updates | ||||
|     if (status || abs(progress - lastSentProgress) >= 10 || progress == 100) { | ||||
|         for (int i = 0; i < 2; i++) { | ||||
|             ws.textAll(progressMsg); | ||||
|             delay(100);  // Längerer Delay zwischen Nachrichten | ||||
|         } | ||||
|     } else { | ||||
|         ws.textAll(progressMsg); | ||||
|         delay(50); | ||||
|     } | ||||
|      | ||||
|     lastSentProgress = progress; | ||||
| } | ||||
|  | ||||
| void handleUpdate(AsyncWebServer &server) { | ||||
|     AsyncCallbackWebHandler* updateHandler = new AsyncCallbackWebHandler(); | ||||
|     updateHandler->setUri("/update"); | ||||
|     updateHandler->setMethod(HTTP_POST); | ||||
|      | ||||
|     updateHandler->onUpload([](AsyncWebServerRequest *request, String filename, | ||||
|                              size_t index, uint8_t *data, size_t len, bool final) { | ||||
|         if (!index) { | ||||
|             updateTotalSize = request->contentLength(); | ||||
|             updateWritten = 0; | ||||
|             isSpiffsUpdate = (filename.indexOf("website") > -1); | ||||
|              | ||||
|             if (isSpiffsUpdate) { | ||||
|                 // Backup vor dem Update | ||||
|                 sendUpdateProgress(0, "backup", "Backing up configurations..."); | ||||
|                 delay(200); | ||||
|                 backupJsonConfigs(); | ||||
|                 delay(200); | ||||
|                  | ||||
|                 const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); | ||||
|                 if (!partition || !Update.begin(partition->size, U_SPIFFS)) { | ||||
|                     request->send(400, "application/json", "{\"success\":false,\"message\":\"Update initialization failed\"}"); | ||||
|                     return; | ||||
|                 } | ||||
|                 sendUpdateProgress(5, "starting", "Starting SPIFFS update..."); | ||||
|                 delay(200); | ||||
|             } else { | ||||
|                 if (!Update.begin(updateTotalSize)) { | ||||
|                     request->send(400, "application/json", "{\"success\":false,\"message\":\"Update initialization failed\"}"); | ||||
|                     return; | ||||
|                 } | ||||
|                 sendUpdateProgress(0, "starting", "Starting firmware update..."); | ||||
|                 delay(200); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (len) { | ||||
|             if (Update.write(data, len) != len) { | ||||
|                 request->send(400, "application/json", "{\"success\":false,\"message\":\"Write failed\"}"); | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             updateWritten += len; | ||||
|             int currentProgress; | ||||
|              | ||||
|             // Berechne den Fortschritt basierend auf dem Update-Typ | ||||
|             if (isSpiffsUpdate) { | ||||
|                 // SPIFFS: 5-75% für Upload | ||||
|                 currentProgress = 5 + (updateWritten * 100) / updateTotalSize; | ||||
|             } else { | ||||
|                 // Firmware: 0-100% für Upload | ||||
|                 currentProgress = 1 + (updateWritten * 100) / updateTotalSize; | ||||
|             } | ||||
|              | ||||
|             static int lastProgress = -1; | ||||
|             if (currentProgress != lastProgress && (currentProgress % 10 == 0 || final)) { | ||||
|                 sendUpdateProgress(currentProgress, "uploading"); | ||||
|                 oledShowMessage("Update: " + String(currentProgress) + "%"); | ||||
|                 delay(50); | ||||
|                 lastProgress = currentProgress; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (final) { | ||||
|             if (Update.end(true)) { | ||||
|                 if (isSpiffsUpdate) { | ||||
|                     restoreJsonConfigs(); | ||||
|                 } | ||||
|             } else { | ||||
|                 request->send(400, "application/json", "{\"success\":false,\"message\":\"Update finalization failed\"}"); | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     updateHandler->onRequest([](AsyncWebServerRequest *request) { | ||||
|         if (Update.hasError()) { | ||||
|             request->send(400, "application/json", "{\"success\":false,\"message\":\"Update failed\"}"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Erste 100% Nachricht | ||||
|         ws.textAll("{\"type\":\"updateProgress\",\"progress\":100,\"status\":\"success\",\"message\":\"Update successful! Restarting device...\"}"); | ||||
|         vTaskDelay(2000 / portTICK_PERIOD_MS); | ||||
|          | ||||
|         AsyncWebServerResponse *response = request->beginResponse(200, "application/json",  | ||||
|             "{\"success\":true,\"message\":\"Update successful! Restarting device...\"}"); | ||||
|         response->addHeader("Connection", "close"); | ||||
|         request->send(response); | ||||
|          | ||||
|         // Zweite 100% Nachricht zur Sicherheit | ||||
|         ws.textAll("{\"type\":\"updateProgress\",\"progress\":100,\"status\":\"success\",\"message\":\"Update successful! Restarting device...\"}"); | ||||
|          | ||||
|         espRestart(); | ||||
|     }); | ||||
|  | ||||
|     server.addHandler(updateHandler); | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/ota.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/ota.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| #ifndef OTA_H | ||||
| #define OTA_H | ||||
|  | ||||
| #include <ArduinoOTA.h> | ||||
| #include <ESPAsyncWebServer.h> | ||||
|  | ||||
| void handleUpdate(AsyncWebServer &server); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										193
									
								
								src/website.cpp
									
									
									
									
									
								
							
							
						
						
									
										193
									
								
								src/website.cpp
									
									
									
									
									
								
							| @@ -9,6 +9,7 @@ | ||||
| #include "esp_task_wdt.h" | ||||
| #include <Update.h> | ||||
| #include "display.h" | ||||
| #include "ota.h" | ||||
|  | ||||
| #ifndef VERSION | ||||
|   #define VERSION "1.1.0" | ||||
| @@ -23,48 +24,6 @@ AsyncWebSocket ws("/ws"); | ||||
| uint8_t lastSuccess = 0; | ||||
| uint8_t lastHasReadRfidTag = 0; | ||||
|  | ||||
| // Globale Variablen für Config Backups hinzufügen | ||||
| String bambuCredentialsBackup; | ||||
| String spoolmanUrlBackup; | ||||
|  | ||||
| // Globale Variable für den Update-Typ | ||||
| static int currentUpdateCommand = 0; | ||||
|  | ||||
| // Globale Update-Variablen | ||||
| static size_t updateTotalSize = 0; | ||||
| static size_t updateWritten = 0; | ||||
| static bool isSpiffsUpdate = false; | ||||
|  | ||||
| void sendUpdateProgress(int progress, const char* status = nullptr, const char* message = nullptr) { | ||||
|     static int lastSentProgress = -1; | ||||
|      | ||||
|     // Verhindere zu häufige Updates | ||||
|     if (progress == lastSentProgress && !status && !message) { | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     String progressMsg = "{\"type\":\"updateProgress\",\"progress\":" + String(progress); | ||||
|     if (status) { | ||||
|         progressMsg += ",\"status\":\"" + String(status) + "\""; | ||||
|     } | ||||
|     if (message) { | ||||
|         progressMsg += ",\"message\":\"" + String(message) + "\""; | ||||
|     } | ||||
|     progressMsg += "}"; | ||||
|      | ||||
|     // Sende die Nachricht mehrmals mit Verzögerung für wichtige Updates | ||||
|     if (status || abs(progress - lastSentProgress) >= 10 || progress == 100) { | ||||
|         for (int i = 0; i < 2; i++) { | ||||
|             ws.textAll(progressMsg); | ||||
|             delay(100);  // Längerer Delay zwischen Nachrichten | ||||
|         } | ||||
|     } else { | ||||
|         ws.textAll(progressMsg); | ||||
|         delay(50); | ||||
|     } | ||||
|      | ||||
|     lastSentProgress = progress; | ||||
| } | ||||
|  | ||||
| void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { | ||||
|     if (type == WS_EVT_CONNECT) { | ||||
| @@ -207,105 +166,6 @@ void sendAmsData(AsyncWebSocketClient *client) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| void handleUpdate(AsyncWebServer &server) { | ||||
|     AsyncCallbackWebHandler* updateHandler = new AsyncCallbackWebHandler(); | ||||
|     updateHandler->setUri("/update"); | ||||
|     updateHandler->setMethod(HTTP_POST); | ||||
|      | ||||
|     updateHandler->onUpload([](AsyncWebServerRequest *request, String filename, | ||||
|                              size_t index, uint8_t *data, size_t len, bool final) { | ||||
|         if (!index) { | ||||
|             updateTotalSize = request->contentLength(); | ||||
|             updateWritten = 0; | ||||
|             isSpiffsUpdate = (filename.indexOf("website") > -1); | ||||
|              | ||||
|             if (isSpiffsUpdate) { | ||||
|                 // Backup vor dem Update | ||||
|                 sendUpdateProgress(0, "backup", "Backing up configurations..."); | ||||
|                 delay(200); | ||||
|                 backupJsonConfigs(); | ||||
|                 delay(200); | ||||
|                  | ||||
|                 const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); | ||||
|                 if (!partition || !Update.begin(partition->size, U_SPIFFS)) { | ||||
|                     request->send(400, "application/json", "{\"success\":false,\"message\":\"Update initialization failed\"}"); | ||||
|                     return; | ||||
|                 } | ||||
|                 sendUpdateProgress(5, "starting", "Starting SPIFFS update..."); | ||||
|                 delay(200); | ||||
|             } else { | ||||
|                 if (!Update.begin(updateTotalSize)) { | ||||
|                     request->send(400, "application/json", "{\"success\":false,\"message\":\"Update initialization failed\"}"); | ||||
|                     return; | ||||
|                 } | ||||
|                 sendUpdateProgress(0, "starting", "Starting firmware update..."); | ||||
|                 delay(200); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (len) { | ||||
|             if (Update.write(data, len) != len) { | ||||
|                 request->send(400, "application/json", "{\"success\":false,\"message\":\"Write failed\"}"); | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             updateWritten += len; | ||||
|             int currentProgress; | ||||
|              | ||||
|             // Berechne den Fortschritt basierend auf dem Update-Typ | ||||
|             if (isSpiffsUpdate) { | ||||
|                 // SPIFFS: 5-75% für Upload | ||||
|                 currentProgress = 5 + (updateWritten * 100) / updateTotalSize; | ||||
|             } else { | ||||
|                 // Firmware: 0-100% für Upload | ||||
|                 currentProgress = 1 + (updateWritten * 100) / updateTotalSize; | ||||
|             } | ||||
|              | ||||
|             static int lastProgress = -1; | ||||
|             if (currentProgress != lastProgress && (currentProgress % 10 == 0 || final)) { | ||||
|                 sendUpdateProgress(currentProgress, "uploading"); | ||||
|                 oledShowMessage("Update: " + String(currentProgress) + "%"); | ||||
|                 delay(50); | ||||
|                 lastProgress = currentProgress; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (final) { | ||||
|             if (Update.end(true)) { | ||||
|                 if (isSpiffsUpdate) { | ||||
|                     restoreJsonConfigs(); | ||||
|                 } | ||||
|             } else { | ||||
|                 request->send(400, "application/json", "{\"success\":false,\"message\":\"Update finalization failed\"}"); | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     updateHandler->onRequest([](AsyncWebServerRequest *request) { | ||||
|         if (Update.hasError()) { | ||||
|             request->send(400, "application/json", "{\"success\":false,\"message\":\"Update failed\"}"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Erste 100% Nachricht | ||||
|         ws.textAll("{\"type\":\"updateProgress\",\"progress\":100,\"status\":\"success\",\"message\":\"Update successful! Restarting device...\"}"); | ||||
|         delay(2000);  // Längerer Delay für die erste Nachricht | ||||
|          | ||||
|         AsyncWebServerResponse *response = request->beginResponse(200, "application/json",  | ||||
|             "{\"success\":true,\"message\":\"Update successful! Restarting device...\"}"); | ||||
|         response->addHeader("Connection", "close"); | ||||
|         request->send(response); | ||||
|          | ||||
|         // Zweite 100% Nachricht zur Sicherheit | ||||
|         ws.textAll("{\"type\":\"updateProgress\",\"progress\":100,\"status\":\"success\",\"message\":\"Update successful! Restarting device...\"}"); | ||||
|         delay(3000);  // Noch längerer Delay vor dem Neustart | ||||
|          | ||||
|         ESP.restart(); | ||||
|     }); | ||||
|  | ||||
|     server.addHandler(updateHandler); | ||||
| } | ||||
|  | ||||
| void setupWebserver(AsyncWebServer &server) { | ||||
|     // Deaktiviere alle Debug-Ausgaben | ||||
|     Serial.setDebugOutput(false); | ||||
| @@ -426,17 +286,19 @@ void setupWebserver(AsyncWebServer &server) { | ||||
|         String bambu_serialnr = request->getParam("bambu_serialnr")->value(); | ||||
|         String bambu_accesscode = request->getParam("bambu_accesscode")->value(); | ||||
|         bool autoSend = (request->getParam("autoSend")->value() == "true") ? true : false; | ||||
|         String autoSendTime = request->getParam("autoSendTime")->value(); | ||||
|         Serial.println(autoSend); | ||||
|         bambu_ip.trim(); | ||||
|         bambu_serialnr.trim(); | ||||
|         bambu_accesscode.trim(); | ||||
|         autoSendTime.trim(); | ||||
|  | ||||
|         if (bambu_ip.length() == 0 || bambu_serialnr.length() == 0 || bambu_accesscode.length() == 0) { | ||||
|             request->send(400, "application/json", "{\"success\": false, \"error\": \"Empty parameter\"}"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         bool success = saveBambuCredentials(bambu_ip, bambu_serialnr, bambu_accesscode, autoSend); | ||||
|         bool success = saveBambuCredentials(bambu_ip, bambu_serialnr, bambu_accesscode, autoSend, autoSendTime); | ||||
|  | ||||
|         request->send(200, "application/json", "{\"healthy\": " + String(success ? "true" : "false") + "}"); | ||||
|     }); | ||||
| @@ -534,50 +396,3 @@ void setupWebserver(AsyncWebServer &server) { | ||||
|     server.begin(); | ||||
|     Serial.println("Webserver gestartet"); | ||||
| } | ||||
|  | ||||
|  | ||||
| void backupJsonConfigs() { | ||||
|     // Bambu Credentials backup | ||||
|     if (SPIFFS.exists("/bambu_credentials.json")) { | ||||
|         File file = SPIFFS.open("/bambu_credentials.json", "r"); | ||||
|         if (file) { | ||||
|             bambuCredentialsBackup = file.readString(); | ||||
|             file.close(); | ||||
|             Serial.println("Bambu credentials backed up"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Spoolman URL backup | ||||
|     if (SPIFFS.exists("/spoolman_url.json")) { | ||||
|         File file = SPIFFS.open("/spoolman_url.json", "r"); | ||||
|         if (file) { | ||||
|             spoolmanUrlBackup = file.readString(); | ||||
|             file.close(); | ||||
|             Serial.println("Spoolman URL backed up"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void restoreJsonConfigs() { | ||||
|     // Restore Bambu credentials | ||||
|     if (bambuCredentialsBackup.length() > 0) { | ||||
|         File file = SPIFFS.open("/bambu_credentials.json", "w"); | ||||
|         if (file) { | ||||
|             file.print(bambuCredentialsBackup); | ||||
|             file.close(); | ||||
|             Serial.println("Bambu credentials restored"); | ||||
|         } | ||||
|         bambuCredentialsBackup = ""; // Clear backup | ||||
|     } | ||||
|  | ||||
|     // Restore Spoolman URL | ||||
|     if (spoolmanUrlBackup.length() > 0) { | ||||
|         File file = SPIFFS.open("/spoolman_url.json", "w"); | ||||
|         if (file) { | ||||
|             file.print(spoolmanUrlBackup); | ||||
|             file.close(); | ||||
|             Serial.println("Spoolman URL restored"); | ||||
|         } | ||||
|         spoolmanUrlBackup = ""; // Clear backup | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -19,7 +19,6 @@ 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); | ||||
|  | ||||
| @@ -29,8 +28,4 @@ void sendNfcData(AsyncWebSocketClient *client); | ||||
| void foundNfcTag(AsyncWebSocketClient *client, uint8_t success); | ||||
| void sendWriteResult(AsyncWebSocketClient *client, uint8_t success); | ||||
|  | ||||
| // Upgrade-Funktionen | ||||
| void backupJsonConfigs(); | ||||
| void restoreJsonConfigs(); | ||||
|  | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user