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 code = document.getElementById('bambuCode').value; | ||||||
|             const autoSend = document.getElementById('autoSend').checked; |             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(response => response.json()) | ||||||
|                 .then(data => { |                 .then(data => { | ||||||
|                     if (data.healthy) { |                     if (data.healthy) { | ||||||
| @@ -122,13 +122,18 @@ | |||||||
|                         <label for="bambuCode">Access Code:</label> |                         <label for="bambuCode">Access Code:</label> | ||||||
|                         <input type="text" id="bambuCode" placeholder="Access Code vom Drucker" value="{{bambuCode}}"> |                         <input type="text" id="bambuCode" placeholder="Access Code vom Drucker" value="{{bambuCode}}"> | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class="input-group"> |                     <hr> | ||||||
|                         If activated, FilaMan will automatically update the next filled tray with the last scanned and weighed spool. |                     <p>If activated, FilaMan will automatically update the next filled tray with the last scanned and weighed spool.</p> | ||||||
|                         <label for="autoSend">Auto Send to Bambu:</label> |                     <div class="input-group" style="display: flex; margin-bottom: 0;"> | ||||||
|                         <input type="checkbox" id="autoSend" {{autoSendToBambu}}> |                         <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> |                     </div> | ||||||
|  |  | ||||||
|                     <button onclick="saveBambuCredentials()">Save Bambu Credentials</button> |                     <button style="margin: 0;" onclick="saveBambuCredentials()">Save Bambu Credentials</button> | ||||||
|                     <p id="bambuStatusMessage"></p> |                     <p id="bambuStatusMessage"></p> | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ int ams_count = 0; | |||||||
| String amsJsonData;  // Speichert das fertige JSON für WebSocket-Clients | String amsJsonData;  // Speichert das fertige JSON für WebSocket-Clients | ||||||
| AMSData ams_data[MAX_AMS];  // Definition des Arrays; | 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) { |     if (BambuMqttTask) { | ||||||
|         vTaskDelete(BambuMqttTask); |         vTaskDelete(BambuMqttTask); | ||||||
|     } |     } | ||||||
| @@ -42,6 +42,7 @@ bool saveBambuCredentials(const String& ip, const String& serialnr, const String | |||||||
|     doc["bambu_accesscode"] = accesscode; |     doc["bambu_accesscode"] = accesscode; | ||||||
|     doc["bambu_serialnr"] = serialnr; |     doc["bambu_serialnr"] = serialnr; | ||||||
|     doc["autoSendToBambu"] = autoSend; |     doc["autoSendToBambu"] = autoSend; | ||||||
|  |     doc["autoSendTime"] = (autoSendTime != "") ? autoSendTime.toInt() : autoSetBambuAmsCounter; | ||||||
|  |  | ||||||
|     if (!saveJsonValue("/bambu_credentials.json", doc)) { |     if (!saveJsonValue("/bambu_credentials.json", doc)) { | ||||||
|         Serial.println("Fehler beim Speichern der Bambu-Credentials."); |         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_accesscode = accesscode.c_str(); | ||||||
|     bambu_serialnr = serialnr.c_str(); |     bambu_serialnr = serialnr.c_str(); | ||||||
|     autoSendToBambu = autoSend; |     autoSendToBambu = autoSend; | ||||||
|  |     autoSetBambuAmsCounter = autoSendTime.toInt(); | ||||||
|  |  | ||||||
|     vTaskDelay(100 / portTICK_PERIOD_MS); |     vTaskDelay(100 / portTICK_PERIOD_MS); | ||||||
|     if (!setupMqtt()) return false; |     if (!setupMqtt()) return false; | ||||||
| @@ -67,7 +69,8 @@ bool loadBambuCredentials() { | |||||||
|         String ip = doc["bambu_ip"].as<String>(); |         String ip = doc["bambu_ip"].as<String>(); | ||||||
|         String code = doc["bambu_accesscode"].as<String>(); |         String code = doc["bambu_accesscode"].as<String>(); | ||||||
|         String serial = doc["bambu_serialnr"].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(); |         ip.trim(); | ||||||
|         code.trim(); |         code.trim(); | ||||||
| @@ -95,12 +98,37 @@ FilamentResult findFilamentIdx(String brand, String type) { | |||||||
|     // JSON-Dokument für die Filament-Daten erstellen |     // JSON-Dokument für die Filament-Daten erstellen | ||||||
|     JsonDocument doc; |     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 |     // 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"); |         Serial.println("Fehler beim Laden der Filament-Daten"); | ||||||
|         return {"GFL99", "PLA"}; // Fallback auf Generic PLA |         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 |     // 1. Erst versuchen wir die exakte Brand + Type Kombination zu finden | ||||||
|     String searchKey; |     String searchKey; | ||||||
|     if (brand == "Bambu" || brand == "Bambulab") { |     if (brand == "Bambu" || brand == "Bambulab") { | ||||||
|   | |||||||
| @@ -114,6 +114,8 @@ void loop() { | |||||||
|  |  | ||||||
|   // Wenn Bambu auto set Spool aktiv |   // Wenn Bambu auto set Spool aktiv | ||||||
|   if (autoSendToBambu && autoSetToBambuSpoolId > 0 && currentMillis - lastAutoSetBambuAmsTime >= autoSetBambuAmsInterval)  |   if (autoSendToBambu && autoSetToBambuSpoolId > 0 && currentMillis - lastAutoSetBambuAmsTime >= autoSetBambuAmsInterval)  | ||||||
|  |   { | ||||||
|  |     if (hasReadRfidTag == 0) | ||||||
|     { |     { | ||||||
|       lastAutoSetBambuAmsTime = currentMillis; |       lastAutoSetBambuAmsTime = currentMillis; | ||||||
|       oledShowMessage("Auto Set         " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s"); |       oledShowMessage("Auto Set         " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s"); | ||||||
| @@ -126,6 +128,11 @@ void loop() { | |||||||
|         oledShowWeight(weight); |         oledShowWeight(weight); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |       autoAmsCounter = 0; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|    |    | ||||||
|  |  | ||||||
|   // Wenn Waage nicht Kalibriert |   // 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 "esp_task_wdt.h" | ||||||
| #include <Update.h> | #include <Update.h> | ||||||
| #include "display.h" | #include "display.h" | ||||||
|  | #include "ota.h" | ||||||
|  |  | ||||||
| #ifndef VERSION | #ifndef VERSION | ||||||
|   #define VERSION "1.1.0" |   #define VERSION "1.1.0" | ||||||
| @@ -23,48 +24,6 @@ AsyncWebSocket ws("/ws"); | |||||||
| uint8_t lastSuccess = 0; | uint8_t lastSuccess = 0; | ||||||
| uint8_t lastHasReadRfidTag = 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) { | void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { | ||||||
|     if (type == WS_EVT_CONNECT) { |     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) { | void setupWebserver(AsyncWebServer &server) { | ||||||
|     // Deaktiviere alle Debug-Ausgaben |     // Deaktiviere alle Debug-Ausgaben | ||||||
|     Serial.setDebugOutput(false); |     Serial.setDebugOutput(false); | ||||||
| @@ -426,17 +286,19 @@ void setupWebserver(AsyncWebServer &server) { | |||||||
|         String bambu_serialnr = request->getParam("bambu_serialnr")->value(); |         String bambu_serialnr = request->getParam("bambu_serialnr")->value(); | ||||||
|         String bambu_accesscode = request->getParam("bambu_accesscode")->value(); |         String bambu_accesscode = request->getParam("bambu_accesscode")->value(); | ||||||
|         bool autoSend = (request->getParam("autoSend")->value() == "true") ? true : false; |         bool autoSend = (request->getParam("autoSend")->value() == "true") ? true : false; | ||||||
|  |         String autoSendTime = request->getParam("autoSendTime")->value(); | ||||||
|         Serial.println(autoSend); |         Serial.println(autoSend); | ||||||
|         bambu_ip.trim(); |         bambu_ip.trim(); | ||||||
|         bambu_serialnr.trim(); |         bambu_serialnr.trim(); | ||||||
|         bambu_accesscode.trim(); |         bambu_accesscode.trim(); | ||||||
|  |         autoSendTime.trim(); | ||||||
|  |  | ||||||
|         if (bambu_ip.length() == 0 || bambu_serialnr.length() == 0 || bambu_accesscode.length() == 0) { |         if (bambu_ip.length() == 0 || bambu_serialnr.length() == 0 || bambu_accesscode.length() == 0) { | ||||||
|             request->send(400, "application/json", "{\"success\": false, \"error\": \"Empty parameter\"}"); |             request->send(400, "application/json", "{\"success\": false, \"error\": \"Empty parameter\"}"); | ||||||
|             return; |             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") + "}"); |         request->send(200, "application/json", "{\"healthy\": " + String(success ? "true" : "false") + "}"); | ||||||
|     }); |     }); | ||||||
| @@ -534,50 +396,3 @@ void setupWebserver(AsyncWebServer &server) { | |||||||
|     server.begin(); |     server.begin(); | ||||||
|     Serial.println("Webserver gestartet"); |     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 | // Server-Initialisierung und Handler | ||||||
| void initWebServer(); | 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 handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total); | ||||||
| void setupWebserver(AsyncWebServer &server); | void setupWebserver(AsyncWebServer &server); | ||||||
|  |  | ||||||
| @@ -29,8 +28,4 @@ void sendNfcData(AsyncWebSocketClient *client); | |||||||
| void foundNfcTag(AsyncWebSocketClient *client, uint8_t success); | void foundNfcTag(AsyncWebSocketClient *client, uint8_t success); | ||||||
| void sendWriteResult(AsyncWebSocketClient *client, uint8_t success); | void sendWriteResult(AsyncWebSocketClient *client, uint8_t success); | ||||||
|  |  | ||||||
| // Upgrade-Funktionen |  | ||||||
| void backupJsonConfigs(); |  | ||||||
| void restoreJsonConfigs(); |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user