feat: enhance update process with separate forms for firmware and webpage uploads, including validation and improved UI
This commit is contained in:
parent
8199b283c0
commit
60553255b8
@ -50,26 +50,64 @@
|
||||
<!-- head -->
|
||||
|
||||
<div class="content">
|
||||
<h1>Firmware Upgrade</h1>
|
||||
|
||||
<h1>System Update</h1>
|
||||
<div class="warning">
|
||||
<strong>Warning:</strong> Please do not turn off or restart the device during the update.
|
||||
The device will restart automatically after the update.
|
||||
</div>
|
||||
|
||||
<div class="update-form">
|
||||
<form id="updateForm" enctype='multipart/form-data'>
|
||||
<input type='file' name='update' accept='.bin' required>
|
||||
<input type='submit' value='Start Firmware Update'>
|
||||
</form>
|
||||
<div class="update-options">
|
||||
<div class="update-section">
|
||||
<h2>Firmware Update</h2>
|
||||
<p>Upload a new firmware file (filaman_*.bin)</p>
|
||||
<div class="update-form">
|
||||
<form id="firmwareForm" enctype='multipart/form-data' data-type="firmware">
|
||||
<input type='file' name='update' accept='.bin' required>
|
||||
<input type='submit' value='Start Firmware Update'>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="update-section">
|
||||
<h2>Webpage Update</h2>
|
||||
<p>Upload a new webpage file (webpage_*.bin)</p>
|
||||
<div class="update-form">
|
||||
<form id="webpageForm" enctype='multipart/form-data' data-type="webpage">
|
||||
<input type='file' name='update' accept='.bin' required>
|
||||
<input type='submit' value='Start Webpage Update'>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="progress-container">
|
||||
<div class="progress-bar">0%</div>
|
||||
<div class="progress-container" style="display: none;">
|
||||
<div class="progress-bar">0%</</div>
|
||||
</div>
|
||||
<div class="status"></div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.update-options {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
.update-section {
|
||||
flex: 1;
|
||||
background: #f5f5f5;
|
||||
padding: 1.5rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.update-section h2 {
|
||||
margin-top: 0;
|
||||
color: #333;
|
||||
}
|
||||
.update-section p {
|
||||
color: #666;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Hide status indicators during update
|
||||
const statusContainer = document.querySelector('.status-container');
|
||||
@ -77,12 +115,24 @@
|
||||
statusContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
document.getElementById('updateForm').addEventListener('submit', async (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 firmware file.');
|
||||
alert('Please select a file.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate file name pattern
|
||||
if (updateType === 'firmware' && !file.name.startsWith('filaman_')) {
|
||||
alert('Please select a valid firmware file (filaman_*.bin)');
|
||||
return;
|
||||
}
|
||||
if (updateType === 'webpage' && !file.name.startsWith('webpage_')) {
|
||||
alert('Please select a valid webpage file (webpage_*.bin)');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -96,11 +146,12 @@
|
||||
progressContainer.style.display = 'block';
|
||||
status.style.display = 'none';
|
||||
status.className = 'status';
|
||||
form.querySelector('input[type=submit]').disabled = true;
|
||||
|
||||
// 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.upload.onprogress = (e) => {
|
||||
if (e.lengthComputable) {
|
||||
const percentComplete = (e.loaded / e.total) * 100;
|
||||
@ -143,13 +194,13 @@
|
||||
status.style.display = 'block';
|
||||
|
||||
if (xhr.status !== 200) {
|
||||
form.querySelector('input[type=submit]').disabled = false;
|
||||
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';
|
||||
form.querySelector('input[type=submit]').disabled = false;
|
||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
||||
}
|
||||
};
|
||||
|
||||
@ -157,11 +208,14 @@
|
||||
status.textContent = 'Update failed: Network error';
|
||||
status.classList.add('error');
|
||||
status.style.display = 'block';
|
||||
form.querySelector('input[type=submit]').disabled = false;
|
||||
document.querySelectorAll('form input[type=submit]').forEach(btn => btn.disabled = false);
|
||||
};
|
||||
|
||||
xhr.send(formData);
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('firmwareForm').addEventListener('submit', handleUpdate);
|
||||
document.getElementById('webpageForm').addEventListener('submit', handleUpdate);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -385,3 +385,51 @@ void setupWebserver(AsyncWebServer &server) {
|
||||
server.begin();
|
||||
Serial.println("Webserver gestartet");
|
||||
}
|
||||
|
||||
void handleOTAUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||
if (!index) {
|
||||
// Start eines neuen Uploads
|
||||
Serial.println("Update Start: " + filename);
|
||||
|
||||
// Überprüfe den Dateityp basierend auf dem Dateinamen
|
||||
bool isFirmware = filename.startsWith("filaman_");
|
||||
bool isWebpage = filename.startsWith("webpage_");
|
||||
|
||||
if (!isFirmware && !isWebpage) {
|
||||
request->send(400, "application/json", "{\"message\":\"Invalid file type. File must start with 'filaman_' or 'webpage_'\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Wähle den Update-Typ basierend auf dem Dateinamen
|
||||
if (isWebpage) {
|
||||
if (!Update.begin(SPIFFS.totalBytes(), U_SPIFFS)) {
|
||||
Update.printError(Serial);
|
||||
request->send(400, "application/json", "{\"message\":\"SPIFFS Update failed: " + String(Update.errorString()) + "\"}");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH)) {
|
||||
Update.printError(Serial);
|
||||
request->send(400, "application/json", "{\"message\":\"Firmware Update failed: " + String(Update.errorString()) + "\"}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Update.write(data, len) != len) {
|
||||
Update.printError(Serial);
|
||||
request->send(400, "application/json", "{\"message\":\"Write failed: " + String(Update.errorString()) + "\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (final) {
|
||||
if (!Update.end(true)) {
|
||||
Update.printError(Serial);
|
||||
request->send(400, "application/json", "{\"message\":\"Update failed: " + String(Update.errorString()) + "\"}");
|
||||
return;
|
||||
}
|
||||
request->send(200, "application/json", "{\"message\":\"Update successful!\", \"restart\": true}");
|
||||
delay(500);
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user