From 413507362367e4e8577cb1357c3b4d0f829c094a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 22 Feb 2025 18:12:27 +0100 Subject: [PATCH] feat: implement WebSocket for update progress and enhance update response handling --- html/upgrade.html | 56 ++++++++++++++++++++++++++++------------------- src/website.cpp | 16 +++++--------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/html/upgrade.html b/html/upgrade.html index e976218..147511c 100644 --- a/html/upgrade.html +++ b/html/upgrade.html @@ -155,17 +155,29 @@ const progressContainer = document.querySelector('.progress-container'); const status = document.querySelector('.status'); + // WebSocket für Update-Progress + const ws = new WebSocket('ws://' + window.location.host + '/ws'); + ws.onmessage = function(event) { + try { + const data = JSON.parse(event.data); + if (data.type === "updateProgress") { + progress.style.width = data.progress + '%'; + progress.textContent = data.progress + '%'; + } + } catch (e) { + console.error('WebSocket message error:', e); + } + }; + function handleUpdate(e) { e.preventDefault(); const form = e.target; const file = form.update.files[0]; const updateType = form.dataset.type; - if (!file) { alert('Please select a file.'); return; } - // Validate file name pattern if (updateType === 'firmware' && !file.name.startsWith('upgrade_filaman_firmware_')) { alert('Please select a valid firmware file (upgrade_filaman_firmware_*.bin)'); @@ -179,56 +191,54 @@ progressContainer.style.display = 'block'; status.style.display = 'none'; status.className = 'status'; - // Reset progress bar progress.style.width = '0%'; progress.textContent = '0%'; - // Disable both forms during update document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = true); const xhr = new XMLHttpRequest(); xhr.open('POST', '/update', true); - + xhr.onload = function() { - try { - let response = this.responseText; + if (xhr.status === 200) { try { - const jsonResponse = JSON.parse(response); - - // Zeige finale Nachricht - status.textContent = jsonResponse.message || "Update complete"; - status.classList.add(jsonResponse.success ? 'success' : 'error'); - status.style.display = 'block'; - - if (jsonResponse.success) { + const response = JSON.parse(xhr.responseText); + if (response.success) { + status.textContent = "Update successful! Restarting device... The page will reload in 30 seconds."; + status.classList.add('success'); + status.style.display = 'block'; + + // Setze Progress auf 100% progress.style.width = '100%'; progress.textContent = '100%'; - // Automatischer Neustart nach erfolgreicher Aktualisierung - status.textContent = "Update successful! Restarting device... The page will reload in 30 seconds."; + // Automatischer Redirect nach 30 Sekunden setTimeout(() => { window.location.href = '/'; }, 30000); } else { + status.textContent = response.message || "Update failed"; + status.classList.add('error'); + status.style.display = 'block'; document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false); } } catch (e) { - console.error('JSON parse error:', e); - status.textContent = 'Update failed: Invalid response from server'; + status.textContent = "Error: Invalid server response"; status.classList.add('error'); + status.style.display = 'block'; document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false); } - } catch (error) { - status.textContent = 'Error: ' + error.message; + } else { + status.textContent = "Update failed with status: " + xhr.status; status.classList.add('error'); status.style.display = 'block'; document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false); } }; - + xhr.onerror = function() { - status.textContent = 'Update failed: Network error'; + status.textContent = "Network error during update"; status.classList.add('error'); status.style.display = 'block'; document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false); diff --git a/src/website.cpp b/src/website.cpp index cac9ba6..abc6b43 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -375,6 +375,12 @@ void setupWebserver(AsyncWebServer &server) { [](AsyncWebServerRequest *request) { // Nach Update-Abschluss bool success = !Update.hasError(); + + // Bei SPIFFS Update und Erfolg: Restore Configs vor dem Neustart + if (success && Update.command() == U_SPIFFS) { + restoreJsonConfigs(); + } + String message = success ? "Update successful" : String("Update failed: ") + Update.errorString(); AsyncWebServerResponse *response = request->beginResponse( success ? 200 : 400, @@ -397,8 +403,6 @@ void setupWebserver(AsyncWebServer &server) { static size_t updateSize = 0; static int command = 0; - //oledShowMessage("Upgrade please wait"); - if (!index) { updateSize = request->contentLength(); command = (filename.indexOf("website") > -1) ? U_SPIFFS : U_FLASH; @@ -410,14 +414,12 @@ void setupWebserver(AsyncWebServer &server) { // Get the actual SPIFFS partition size from ESP32 const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); if (!partition) { - restoreJsonConfigs(); String errorMsg = "SPIFFS partition not found"; request->send(400, "application/json", "{\"success\":false,\"message\":\"" + errorMsg + "\"}"); return; } if (!Update.begin(partition->size, command)) { - restoreJsonConfigs(); String errorMsg = String("Update begin failed: ") + Update.errorString(); request->send(400, "application/json", "{\"success\":false,\"message\":\"" + errorMsg + "\"}"); return; @@ -434,9 +436,6 @@ void setupWebserver(AsyncWebServer &server) { if (len) { if (Update.write(data, len) != len) { - if (command == U_SPIFFS) { - restoreJsonConfigs(); - } String errorMsg = String("Write failed: ") + Update.errorString(); request->send(400, "application/json", "{\"success\":false,\"message\":\"" + errorMsg + "\"}"); return; @@ -458,9 +457,6 @@ void setupWebserver(AsyncWebServer &server) { if (final) { if (!Update.end(true)) { - if (command == U_SPIFFS) { - restoreJsonConfigs(); - } String errorMsg = String("Update end failed: ") + Update.errorString(); request->send(400, "application/json", "{\"success\":false,\"message\":\"" + errorMsg + "\"}"); return;