feat: update version to 1.2.2; change OTA upgrade link in HTML files; enhance OTA upload handling with progress updates and JSON responses
This commit is contained in:
23
src/ota.cpp
23
src/ota.cpp
@ -127,10 +127,12 @@ bool restoreConfigs() {
|
||||
void handleOTAUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||
static bool updateStarted = false;
|
||||
static size_t totalBytes = 0;
|
||||
static size_t totalSize = 0;
|
||||
|
||||
if (!index) {
|
||||
updateStarted = false;
|
||||
totalBytes = 0;
|
||||
totalSize = request->contentLength();
|
||||
|
||||
// Check minimum heap size
|
||||
if (ESP.getFreeHeap() < MIN_FREE_HEAP) {
|
||||
@ -138,13 +140,12 @@ void handleOTAUpload(AsyncWebServerRequest *request, String filename, size_t ind
|
||||
return;
|
||||
}
|
||||
|
||||
size_t updateSize = request->contentLength();
|
||||
if (updateSize == 0) {
|
||||
if (totalSize == 0) {
|
||||
request->send(400, "text/plain", "Invalid file size");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("Update size: %u bytes\n", updateSize);
|
||||
Serial.printf("Update size: %u bytes\n", totalSize);
|
||||
Serial.printf("Free space: %u bytes\n", ESP.getFreeSketchSpace());
|
||||
Serial.printf("Free heap: %u bytes\n", ESP.getFreeHeap());
|
||||
|
||||
@ -158,7 +159,7 @@ void handleOTAUpload(AsyncWebServerRequest *request, String filename, size_t ind
|
||||
SPIFFS.end();
|
||||
|
||||
// Begin update with minimal configuration
|
||||
if (!Update.begin(updateSize)) {
|
||||
if (!Update.begin(totalSize)) {
|
||||
Serial.printf("Update.begin failed: %s\n", Update.errorString());
|
||||
request->send(500, "text/plain", "Failed to start update");
|
||||
return;
|
||||
@ -166,6 +167,9 @@ void handleOTAUpload(AsyncWebServerRequest *request, String filename, size_t ind
|
||||
|
||||
updateStarted = true;
|
||||
Serial.println("Update process started");
|
||||
|
||||
// Send initial progress
|
||||
request->send(200, "text/plain", "0");
|
||||
}
|
||||
|
||||
if (!updateStarted) {
|
||||
@ -182,8 +186,11 @@ void handleOTAUpload(AsyncWebServerRequest *request, String filename, size_t ind
|
||||
}
|
||||
|
||||
totalBytes += len;
|
||||
if (totalBytes % (32 * 1024) == 0) {
|
||||
Serial.printf("Progress: %u bytes\n", totalBytes);
|
||||
|
||||
// Send progress update
|
||||
if (!final) {
|
||||
int progress = (totalBytes * 100) / totalSize;
|
||||
request->send(200, "text/plain", String(progress));
|
||||
}
|
||||
|
||||
if (final) {
|
||||
@ -196,7 +203,7 @@ void handleOTAUpload(AsyncWebServerRequest *request, String filename, size_t ind
|
||||
// Try to restore configs
|
||||
if (!SPIFFS.begin(true)) {
|
||||
Serial.println("Failed to mount SPIFFS for restore");
|
||||
request->send(200, "text/plain", "Update successful but config restore failed. Device will restart...");
|
||||
request->send(200, "application/json", "{\"status\": \"success\", \"message\": \"Update successful but config restore failed. Device will restart...\", \"restart\": true}");
|
||||
delay(2000);
|
||||
ESP.restart();
|
||||
return;
|
||||
@ -206,7 +213,7 @@ void handleOTAUpload(AsyncWebServerRequest *request, String filename, size_t ind
|
||||
Serial.println("Failed to restore configs");
|
||||
}
|
||||
|
||||
request->send(200, "text/plain", "Update successful. Device will restart...");
|
||||
request->send(200, "application/json", "{\"status\": \"success\", \"message\": \"Update successful! Device will restart...\", \"restart\": true}");
|
||||
delay(2000);
|
||||
ESP.restart();
|
||||
}
|
||||
|
101
src/website.cpp
101
src/website.cpp
@ -338,101 +338,12 @@ void setupWebserver(AsyncWebServer &server) {
|
||||
Serial.println("RFID.js gesendet");
|
||||
});
|
||||
|
||||
// Route für OTA Updates
|
||||
server.on("/ota", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
Serial.println("Anfrage für /ota erhalten");
|
||||
|
||||
String html = R"(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Firmware Update</title>
|
||||
<link rel="stylesheet" type="text/css" href="/style.css">
|
||||
<style>
|
||||
.progress-container {
|
||||
width: 100%;
|
||||
margin: 20px 0;
|
||||
display: none;
|
||||
}
|
||||
.progress-bar {
|
||||
width: 0%;
|
||||
height: 20px;
|
||||
background-color: #4CAF50;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
color: white;
|
||||
}
|
||||
.status {
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
display: none;
|
||||
}
|
||||
.error { background-color: #ffebee; color: #c62828; }
|
||||
.success { background-color: #e8f5e9; color: #2e7d32; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Firmware Update</h2>
|
||||
<form id="updateForm" enctype='multipart/form-data'>
|
||||
<input type='file' name='update' accept='.bin' required>
|
||||
<input type='submit' value='Update Firmware'>
|
||||
</form>
|
||||
<div class="progress-container">
|
||||
<div class="progress-bar">0%</div>
|
||||
</div>
|
||||
<div class="status"></div>
|
||||
<script>
|
||||
document.getElementById('updateForm').addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
const file = form.update.files[0];
|
||||
const formData = new FormData();
|
||||
formData.append('update', file);
|
||||
|
||||
const progress = document.querySelector('.progress-bar');
|
||||
const progressContainer = document.querySelector('.progress-container');
|
||||
const status = document.querySelector('.status');
|
||||
|
||||
progressContainer.style.display = 'block';
|
||||
status.style.display = 'none';
|
||||
status.className = 'status';
|
||||
form.querySelector('input[type=submit]').disabled = true;
|
||||
|
||||
try {
|
||||
const response = await fetch('/update', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
onUploadProgress: (e) => {
|
||||
const percent = (e.loaded / e.total) * 100;
|
||||
progress.style.width = percent + '%';
|
||||
progress.textContent = Math.round(percent) + '%';
|
||||
}
|
||||
});
|
||||
|
||||
const result = await response.text();
|
||||
status.textContent = result;
|
||||
status.classList.add(response.ok ? 'success' : 'error');
|
||||
status.style.display = 'block';
|
||||
|
||||
if (response.ok) {
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 5000);
|
||||
} else {
|
||||
form.querySelector('input[type=submit]').disabled = false;
|
||||
}
|
||||
} catch (error) {
|
||||
status.textContent = 'Update failed: ' + error.message;
|
||||
status.classList.add('error');
|
||||
status.style.display = 'block';
|
||||
form.querySelector('input[type=submit]').disabled = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
)";
|
||||
request->send(200, "text/html", html);
|
||||
// Route für Firmware Update
|
||||
server.on("/upgrade", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/upgrade.html.gz", "text/html");
|
||||
response->addHeader("Content-Encoding", "gzip");
|
||||
response->addHeader("Cache-Control", CACHE_CONTROL);
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
server.on("/update", HTTP_POST,
|
||||
|
Reference in New Issue
Block a user