feat: improve update progress reporting and enhance WebSocket notifications
This commit is contained in:
parent
d2da501b94
commit
5c59016f94
@ -157,13 +157,43 @@
|
|||||||
|
|
||||||
// WebSocket für Update-Progress
|
// WebSocket für Update-Progress
|
||||||
const ws = new WebSocket('ws://' + window.location.host + '/ws');
|
const ws = new WebSocket('ws://' + window.location.host + '/ws');
|
||||||
|
let updateInProgress = false;
|
||||||
|
|
||||||
ws.onmessage = function(event) {
|
ws.onmessage = function(event) {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(event.data);
|
const data = JSON.parse(event.data);
|
||||||
if (data.type === "updateProgress") {
|
if (data.type === "updateProgress" && updateInProgress) {
|
||||||
progressContainer.style.display = 'block';
|
progressContainer.style.display = 'block';
|
||||||
progress.style.width = data.progress + '%';
|
|
||||||
progress.textContent = data.progress + '%';
|
// Setze den Fortschritt nur wenn er größer ist als der aktuelle
|
||||||
|
const currentProgress = parseInt(progress.textContent);
|
||||||
|
const newProgress = parseInt(data.progress);
|
||||||
|
if (isNaN(currentProgress) || newProgress > currentProgress) {
|
||||||
|
progress.style.width = data.progress + '%';
|
||||||
|
progress.textContent = data.progress + '%';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zeige verschiedene Status-Nachrichten
|
||||||
|
if (data.status === "finalizing") {
|
||||||
|
status.textContent = "Finalizing update...";
|
||||||
|
status.classList.add('success');
|
||||||
|
status.style.display = 'block';
|
||||||
|
} else if (data.status === "complete" || data.status === "success") {
|
||||||
|
status.textContent = "Update successful! Device is restarting... Page will reload in 30 seconds.";
|
||||||
|
status.classList.add('success');
|
||||||
|
status.style.display = 'block';
|
||||||
|
|
||||||
|
// Versuche die WebSocket-Verbindung sauber zu schließen
|
||||||
|
try {
|
||||||
|
ws.close();
|
||||||
|
} catch (e) {
|
||||||
|
console.log('WebSocket already closed');
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/';
|
||||||
|
}, 30000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('WebSocket message error:', e);
|
console.error('WebSocket message error:', e);
|
||||||
@ -171,11 +201,26 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ws.onclose = function() {
|
ws.onclose = function() {
|
||||||
// Wenn der WebSocket geschlossen wird während eines Updates, zeige eine Nachricht
|
// Wenn das Update läuft und der Fortschritt hoch ist, zeige Success
|
||||||
if (progressContainer.style.display !== 'none' && progress.style.width !== '100%') {
|
if (updateInProgress) {
|
||||||
status.textContent = "Connection lost. Update may still be in progress...";
|
const currentProgress = parseInt(progress.textContent);
|
||||||
status.classList.add('warning');
|
if (!isNaN(currentProgress) && currentProgress >= 90) {
|
||||||
status.style.display = 'block';
|
status.textContent = "Update appears successful! Device is restarting... Page will reload in 30 seconds.";
|
||||||
|
status.classList.add('success');
|
||||||
|
status.style.display = 'block';
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/';
|
||||||
|
}, 30000);
|
||||||
|
} else {
|
||||||
|
status.textContent = "Connection lost. Please wait 30 seconds and check if the update was successful...";
|
||||||
|
status.classList.add('warning');
|
||||||
|
status.style.display = 'block';
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/';
|
||||||
|
}, 30000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -188,6 +233,7 @@
|
|||||||
alert('Please select a file.');
|
alert('Please select a file.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate file name pattern
|
// Validate file name pattern
|
||||||
if (updateType === 'firmware' && !file.name.startsWith('upgrade_filaman_firmware_')) {
|
if (updateType === 'firmware' && !file.name.startsWith('upgrade_filaman_firmware_')) {
|
||||||
alert('Please select a valid firmware file (upgrade_filaman_firmware_*.bin)');
|
alert('Please select a valid firmware file (upgrade_filaman_firmware_*.bin)');
|
||||||
@ -198,13 +244,13 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateInProgress = true;
|
||||||
progressContainer.style.display = 'block';
|
progressContainer.style.display = 'block';
|
||||||
status.style.display = 'none';
|
status.style.display = 'none';
|
||||||
status.className = 'status';
|
status.className = 'status';
|
||||||
// Reset progress bar
|
|
||||||
progress.style.width = '0%';
|
progress.style.width = '0%';
|
||||||
progress.textContent = '0%';
|
progress.textContent = '0%';
|
||||||
// Disable both forms during update
|
|
||||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = true);
|
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = true);
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
@ -215,44 +261,72 @@
|
|||||||
try {
|
try {
|
||||||
const response = JSON.parse(xhr.responseText);
|
const response = JSON.parse(xhr.responseText);
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
status.textContent = "Update successful! Restarting device... The page will reload in 30 seconds.";
|
if (progress.textContent !== '100%') {
|
||||||
|
progress.style.width = '100%';
|
||||||
|
progress.textContent = '100%';
|
||||||
|
}
|
||||||
|
status.textContent = "Update successful! Device is restarting... Page will reload in 30 seconds.";
|
||||||
status.classList.add('success');
|
status.classList.add('success');
|
||||||
status.style.display = 'block';
|
status.style.display = 'block';
|
||||||
|
|
||||||
// Setze Progress auf 100%
|
|
||||||
progress.style.width = '100%';
|
|
||||||
progress.textContent = '100%';
|
|
||||||
|
|
||||||
// Automatischer Redirect nach 30 Sekunden
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = '/';
|
window.location.href = '/';
|
||||||
}, 30000);
|
}, 30000);
|
||||||
} else {
|
} else {
|
||||||
|
updateInProgress = false;
|
||||||
status.textContent = response.message || "Update failed";
|
status.textContent = response.message || "Update failed";
|
||||||
status.classList.add('error');
|
status.classList.add('error');
|
||||||
status.style.display = 'block';
|
status.style.display = 'block';
|
||||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
status.textContent = "Error: Invalid server response";
|
if (progress.textContent === '100%') {
|
||||||
status.classList.add('error');
|
// Wenn 100% erreicht wurden, nehmen wir an, dass das Update erfolgreich war
|
||||||
status.style.display = 'block';
|
status.textContent = "Update appears successful! Device is restarting... Page will reload in 30 seconds.";
|
||||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
status.classList.add('success');
|
||||||
|
status.style.display = 'block';
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/';
|
||||||
|
}, 30000);
|
||||||
|
} else {
|
||||||
|
handleUpdateError("Invalid server response");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
status.textContent = "Update failed with status: " + xhr.status;
|
if (progress.textContent === '100%') {
|
||||||
status.classList.add('error');
|
// Bei 100% Fortschritt gehen wir von einem erfolgreichen Update aus
|
||||||
status.style.display = 'block';
|
status.textContent = "Update appears successful! Device is restarting... Page will reload in 30 seconds.";
|
||||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
status.classList.add('success');
|
||||||
|
status.style.display = 'block';
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/';
|
||||||
|
}, 30000);
|
||||||
|
} else {
|
||||||
|
handleUpdateError("Server error: " + xhr.status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.onerror = function() {
|
xhr.onerror = function() {
|
||||||
status.textContent = "Network error during update";
|
if (progress.textContent === '100%') {
|
||||||
|
// Bei 100% Fortschritt gehen wir von einem erfolgreichen Update aus
|
||||||
|
status.textContent = "Update appears successful! Device is restarting... Page will reload in 30 seconds.";
|
||||||
|
status.classList.add('success');
|
||||||
|
status.style.display = 'block';
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/';
|
||||||
|
}, 30000);
|
||||||
|
} else {
|
||||||
|
handleUpdateError("Network error during update");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleUpdateError(message) {
|
||||||
|
updateInProgress = false;
|
||||||
|
status.textContent = message;
|
||||||
status.classList.add('error');
|
status.classList.add('error');
|
||||||
status.style.display = 'block';
|
status.style.display = 'block';
|
||||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
||||||
};
|
}
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('update', file);
|
formData.append('update', file);
|
||||||
|
@ -376,15 +376,19 @@ void setupWebserver(AsyncWebServer &server) {
|
|||||||
// Update-Handler mit verbesserter Fehlerbehandlung
|
// Update-Handler mit verbesserter Fehlerbehandlung
|
||||||
server.on("/update", HTTP_POST,
|
server.on("/update", HTTP_POST,
|
||||||
[](AsyncWebServerRequest *request) {
|
[](AsyncWebServerRequest *request) {
|
||||||
// Nach Update-Abschluss
|
|
||||||
bool success = !Update.hasError();
|
bool success = !Update.hasError();
|
||||||
|
|
||||||
// Bei SPIFFS Update und Erfolg: Restore Configs vor dem Neustart
|
|
||||||
if (success && currentUpdateCommand == U_SPIFFS) {
|
if (success && currentUpdateCommand == U_SPIFFS) {
|
||||||
restoreJsonConfigs();
|
restoreJsonConfigs();
|
||||||
|
delay(200); // Warte auf Restore-Abschluss
|
||||||
}
|
}
|
||||||
|
|
||||||
String message = success ? "Update successful" : String("Update failed: ") + Update.errorString();
|
String message = success ? "Update successful" : String("Update failed: ") + Update.errorString();
|
||||||
|
|
||||||
|
// Sende finale Bestätigung über WebSocket mit eindeutigem Status
|
||||||
|
ws.textAll("{\"type\":\"updateProgress\",\"progress\":100,\"status\":\"complete\",\"success\":true}");
|
||||||
|
delay(1000); // Längerer Delay für WebSocket
|
||||||
|
|
||||||
AsyncWebServerResponse *response = request->beginResponse(
|
AsyncWebServerResponse *response = request->beginResponse(
|
||||||
success ? 200 : 400,
|
success ? 200 : 400,
|
||||||
"application/json",
|
"application/json",
|
||||||
@ -394,26 +398,26 @@ void setupWebserver(AsyncWebServer &server) {
|
|||||||
request->send(response);
|
request->send(response);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
oledShowMessage("Upgrade successful Rebooting");
|
oledShowMessage("Update successful");
|
||||||
delay(500);
|
delay(2000); // Noch längerer Delay vor Neustart
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
} else {
|
||||||
else {
|
oledShowMessage("Update failed");
|
||||||
oledShowMessage("Upgrade failed");
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
|
[](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||||
static size_t updateSize = 0;
|
static size_t updateSize = 0;
|
||||||
|
static size_t totalWritten = 0;
|
||||||
|
|
||||||
if (!index) {
|
if (!index) {
|
||||||
updateSize = request->contentLength();
|
updateSize = request->contentLength();
|
||||||
|
totalWritten = 0;
|
||||||
currentUpdateCommand = (filename.indexOf("website") > -1) ? U_SPIFFS : U_FLASH;
|
currentUpdateCommand = (filename.indexOf("website") > -1) ? U_SPIFFS : U_FLASH;
|
||||||
|
|
||||||
if (currentUpdateCommand == U_SPIFFS) {
|
if (currentUpdateCommand == U_SPIFFS) {
|
||||||
oledShowMessage("SPIFFS Update...");
|
oledShowMessage("SPIFFS Update...");
|
||||||
backupJsonConfigs();
|
backupJsonConfigs();
|
||||||
|
|
||||||
// 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);
|
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL);
|
||||||
if (!partition) {
|
if (!partition) {
|
||||||
String errorMsg = "SPIFFS partition not found";
|
String errorMsg = "SPIFFS partition not found";
|
||||||
@ -443,15 +447,25 @@ void setupWebserver(AsyncWebServer &server) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update OLED Display alle 5% und Webseite bei jeder Änderung
|
totalWritten += len;
|
||||||
|
int currentProgress;
|
||||||
|
|
||||||
|
// Unterschiedliche Fortschrittsberechnung für SPIFFS und Firmware
|
||||||
|
if (currentUpdateCommand == U_SPIFFS) {
|
||||||
|
// SPIFFS Update: Fortschritt basierend auf Upload-Größe
|
||||||
|
currentProgress = (totalWritten * 100) / updateSize;
|
||||||
|
// Skaliere den Fortschritt auf 0-90%, da das Schreiben ins SPIFFS länger dauert
|
||||||
|
currentProgress = (currentProgress * 90) / 100;
|
||||||
|
} else {
|
||||||
|
// Firmware Update: Normaler Fortschritt
|
||||||
|
currentProgress = (totalWritten * 100) / updateSize;
|
||||||
|
}
|
||||||
|
|
||||||
static int lastProgress = -1;
|
static int lastProgress = -1;
|
||||||
int currentProgress = (index + len) * 100 / updateSize;
|
|
||||||
if (currentProgress != lastProgress) {
|
if (currentProgress != lastProgress) {
|
||||||
// OLED nur alle 5% aktualisieren
|
|
||||||
if (currentProgress % 5 == 0) {
|
if (currentProgress % 5 == 0) {
|
||||||
oledShowMessage(String(currentProgress) + "% complete");
|
oledShowMessage(String(currentProgress) + "% complete");
|
||||||
}
|
}
|
||||||
// Webseite bei jeder Änderung aktualisieren
|
|
||||||
lastProgress = currentProgress;
|
lastProgress = currentProgress;
|
||||||
ws.textAll("{\"type\":\"updateProgress\",\"progress\":" + String(currentProgress) + "}");
|
ws.textAll("{\"type\":\"updateProgress\",\"progress\":" + String(currentProgress) + "}");
|
||||||
}
|
}
|
||||||
@ -463,8 +477,14 @@ void setupWebserver(AsyncWebServer &server) {
|
|||||||
request->send(400, "application/json", "{\"success\":false,\"message\":\"" + errorMsg + "\"}");
|
request->send(400, "application/json", "{\"success\":false,\"message\":\"" + errorMsg + "\"}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Sende finale Progress-Nachricht
|
|
||||||
ws.textAll("{\"type\":\"updateProgress\",\"progress\":100}");
|
// Bei SPIFFS Update zeige 95% an, da noch das Restore kommt
|
||||||
|
if (currentUpdateCommand == U_SPIFFS) {
|
||||||
|
ws.textAll("{\"type\":\"updateProgress\",\"progress\":95,\"status\":\"finalizing\"}");
|
||||||
|
} else {
|
||||||
|
ws.textAll("{\"type\":\"updateProgress\",\"progress\":100,\"status\":\"finalizing\"}");
|
||||||
|
}
|
||||||
|
delay(200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user