Compare commits
No commits in common. "4b25b72b2e30a4c701515916008a7e8622c33c0b" and "fe7b57fe0e51f43410bacd2305b568a9b78dd880" have entirely different histories.
4b25b72b2e
...
fe7b57fe0e
@ -154,108 +154,18 @@
|
||||
const progress = document.querySelector('.progress-bar');
|
||||
const progressContainer = document.querySelector('.progress-container');
|
||||
const status = document.querySelector('.status');
|
||||
let updateInProgress = false;
|
||||
let lastReceivedProgress = 0;
|
||||
|
||||
// WebSocket Handling
|
||||
let ws = null;
|
||||
let wsReconnectTimer = null;
|
||||
|
||||
function connectWebSocket() {
|
||||
ws = new WebSocket('ws://' + window.location.host + '/ws');
|
||||
|
||||
ws.onmessage = function(event) {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.type === "updateProgress" && updateInProgress) {
|
||||
// Zeige Fortschrittsbalken
|
||||
progressContainer.style.display = 'block';
|
||||
|
||||
// Aktualisiere den Fortschritt nur wenn er größer ist
|
||||
const newProgress = parseInt(data.progress);
|
||||
if (!isNaN(newProgress) && newProgress >= lastReceivedProgress) {
|
||||
progress.style.width = newProgress + '%';
|
||||
progress.textContent = newProgress + '%';
|
||||
lastReceivedProgress = newProgress;
|
||||
}
|
||||
|
||||
// Zeige Status-Nachricht
|
||||
if (data.message || data.status) {
|
||||
status.textContent = data.message || getStatusMessage(data.status);
|
||||
status.className = 'status success';
|
||||
status.style.display = 'block';
|
||||
|
||||
// Starte Reload wenn Update erfolgreich
|
||||
if (data.status === 'success' || lastReceivedProgress >= 98) {
|
||||
clearTimeout(wsReconnectTimer);
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 30000);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('WebSocket message error:', e);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onclose = function() {
|
||||
if (updateInProgress) {
|
||||
// Wenn der Fortschritt hoch genug ist, gehen wir von einem erfolgreichen Update aus
|
||||
if (lastReceivedProgress >= 85) {
|
||||
status.textContent = "Update appears successful! Device is restarting... Page will reload in 30 seconds.";
|
||||
status.className = 'status success';
|
||||
status.style.display = 'block';
|
||||
clearTimeout(wsReconnectTimer);
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 30000);
|
||||
} else {
|
||||
// Versuche Reconnect bei niedrigem Fortschritt
|
||||
wsReconnectTimer = setTimeout(connectWebSocket, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = function(err) {
|
||||
console.error('WebSocket error:', err);
|
||||
if (updateInProgress && lastReceivedProgress >= 85) {
|
||||
status.textContent = "Update appears successful! Device is restarting... Page will reload in 30 seconds.";
|
||||
status.className = 'status success';
|
||||
status.style.display = 'block';
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 30000);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Initial WebSocket connection
|
||||
connectWebSocket();
|
||||
|
||||
function getStatusMessage(status) {
|
||||
switch(status) {
|
||||
case 'starting': return 'Starting update...';
|
||||
case 'uploading': return 'Uploading...';
|
||||
case 'finalizing': return 'Finalizing update...';
|
||||
case 'restoring': return 'Restoring configurations...';
|
||||
case 'preparing': return 'Preparing for restart...';
|
||||
case 'success': return 'Update successful! Device is restarting... Page will reload in 30 seconds.';
|
||||
default: return 'Updating...';
|
||||
}
|
||||
}
|
||||
|
||||
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)');
|
||||
@ -266,39 +176,62 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset UI
|
||||
updateInProgress = true;
|
||||
progressContainer.style.display = 'block';
|
||||
status.style.display = 'none';
|
||||
status.className = 'status';
|
||||
|
||||
// Reset progress bar
|
||||
progress.style.width = '0%';
|
||||
progress.textContent = '0%';
|
||||
|
||||
// Disable submit buttons
|
||||
|
||||
// Disable both forms during update
|
||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = true);
|
||||
|
||||
// Send update
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', '/update', true);
|
||||
|
||||
|
||||
xhr.onload = function() {
|
||||
if (xhr.status !== 200 && !progress.textContent.startsWith('100')) {
|
||||
status.textContent = "Update failed: " + (xhr.responseText || "Unknown error");
|
||||
status.className = 'status error';
|
||||
try {
|
||||
let response = this.responseText;
|
||||
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) {
|
||||
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.";
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 30000);
|
||||
} else {
|
||||
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.classList.add('error');
|
||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
||||
}
|
||||
} catch (error) {
|
||||
status.textContent = 'Error: ' + error.message;
|
||||
status.classList.add('error');
|
||||
status.style.display = 'block';
|
||||
updateInProgress = false;
|
||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
xhr.onerror = function() {
|
||||
if (!progress.textContent.startsWith('100')) {
|
||||
status.textContent = "Network error during update";
|
||||
status.className = 'status error';
|
||||
status.style.display = 'block';
|
||||
updateInProgress = false;
|
||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
||||
}
|
||||
status.textContent = 'Update failed: Network error';
|
||||
status.classList.add('error');
|
||||
status.style.display = 'block';
|
||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
||||
};
|
||||
|
||||
const formData = new FormData();
|
||||
|
238
src/website.cpp
238
src/website.cpp
@ -27,45 +27,6 @@ uint8_t lastHasReadRfidTag = 0;
|
||||
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) {
|
||||
Serial.println("Neuer Client verbunden!");
|
||||
@ -207,105 +168,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);
|
||||
@ -508,8 +370,104 @@ void setupWebserver(AsyncWebServer &server) {
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
// Update-Handler registrieren
|
||||
handleUpdate(server);
|
||||
// Update-Handler mit verbesserter Fehlerbehandlung
|
||||
server.on("/update", HTTP_POST,
|
||||
[](AsyncWebServerRequest *request) {
|
||||
// Nach Update-Abschluss
|
||||
bool success = !Update.hasError();
|
||||
String message = success ? "Update successful" : String("Update failed: ") + Update.errorString();
|
||||
AsyncWebServerResponse *response = request->beginResponse(
|
||||
success ? 200 : 400,
|
||||
"application/json",
|
||||
"{\"success\":" + String(success ? "true" : "false") + ",\"message\":\"" + message + "\"}"
|
||||
);
|
||||
response->addHeader("Connection", "close");
|
||||
request->send(response);
|
||||
|
||||
if (success) {
|
||||
oledShowMessage("Upgrade successful Rebooting");
|
||||
delay(500);
|
||||
ESP.restart();
|
||||
}
|
||||
else {
|
||||
oledShowMessage("Upgrade failed");
|
||||
}
|
||||
},
|
||||
[](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||
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;
|
||||
|
||||
if (command == U_SPIFFS) {
|
||||
oledShowMessage("SPIFFS Update...");
|
||||
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);
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
oledShowMessage("Firmware Update...");
|
||||
if (!Update.begin(updateSize, command)) {
|
||||
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) {
|
||||
if (command == U_SPIFFS) {
|
||||
restoreJsonConfigs();
|
||||
}
|
||||
String errorMsg = String("Write failed: ") + Update.errorString();
|
||||
request->send(400, "application/json", "{\"success\":false,\"message\":\"" + errorMsg + "\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update OLED Display alle 5% und Webseite bei jeder Änderung
|
||||
static int lastProgress = -1;
|
||||
int currentProgress = (index + len) * 100 / updateSize;
|
||||
if (currentProgress != lastProgress) {
|
||||
// OLED nur alle 5% aktualisieren
|
||||
if (currentProgress % 5 == 0) {
|
||||
oledShowMessage(String(currentProgress) + "% complete");
|
||||
}
|
||||
// Webseite bei jeder Änderung aktualisieren
|
||||
lastProgress = currentProgress;
|
||||
ws.textAll("{\"type\":\"updateProgress\",\"progress\":" + String(currentProgress) + "}");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
server.on("/api/version", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
String fm_version = VERSION;
|
||||
|
Loading…
x
Reference in New Issue
Block a user