diff --git a/html/admin.html b/html/admin.html
index f4899de..7b61ccd 100755
--- a/html/admin.html
+++ b/html/admin.html
@@ -155,7 +155,34 @@
Updates
-
+
+
+
+
@@ -285,11 +312,13 @@ window.onload = function() {
const checkbox_bme = document.getElementById("check_bme280");
const checkbox_CO2 = document.getElementById("check_CO2");
const checkbox_SFA30 = document.getElementById("check_sensirionSFA30");
+ const checkbox_uSpot = document.getElementById("check_uSpot");
checkbox_nmp5channels.checked = response.npm_5channel;
checkbox_bme.checked = response["BME280"];
checkbox_SFA30.checked = response["SFA30"];
checkbox_CO2.checked = response["MHZ19"];
+ checkbox_uSpot.checked = response["send_uSpot"];
//si sonde envea is true
if (response["envea"]) {
@@ -439,6 +468,108 @@ function updateGitPull(){
});
}
+function updateFirmware() {
+ console.log("Starting comprehensive firmware update...");
+
+ // Show loading state
+ const updateBtn = document.getElementById('updateBtn');
+ const updateBtnText = document.getElementById('updateBtnText');
+ const updateSpinner = document.getElementById('updateSpinner');
+ const updateOutput = document.getElementById('updateOutput');
+ const updateOutputContent = document.getElementById('updateOutputContent');
+
+ // Disable button and show spinner
+ updateBtn.disabled = true;
+ updateBtnText.textContent = 'Updating...';
+ updateSpinner.style.display = 'inline-block';
+
+ // Show output console
+ updateOutput.style.display = 'block';
+ updateOutputContent.textContent = 'Starting update process...\n';
+
+ $.ajax({
+ url: 'launcher.php?type=update_firmware',
+ method: 'GET',
+ dataType: 'json',
+ timeout: 120000, // 2 minutes timeout
+
+ success: function(response) {
+ console.log('Update completed:', response);
+
+ // Display formatted output
+ if (response.success && response.output) {
+ // Format the output for better readability
+ const formattedOutput = response.output
+ .replace(/\[\d{2}:\d{2}:\d{2}\]/g, function(match) {
+ return `${match}`;
+ })
+ .replace(/✓/g, '✓')
+ .replace(/✗/g, '✗')
+ .replace(/⚠/g, '⚠')
+ .replace(/ℹ/g, 'ℹ');
+
+ updateOutputContent.innerHTML = formattedOutput;
+
+ // Show success toast and reload button
+ showToast('Update completed successfully!', 'success');
+ document.getElementById('reloadBtn').style.display = 'inline-block';
+ } else {
+ updateOutputContent.textContent = 'Update completed but no output received.';
+ showToast('Update may have completed with issues', 'warning');
+ }
+ },
+
+ error: function(xhr, status, error) {
+ console.error('Update failed:', status, error);
+ updateOutputContent.textContent = `Update failed: ${error}\n\nStatus: ${status}\nResponse: ${xhr.responseText || 'No response'}`;
+ showToast('Update failed! Check the output for details.', 'error');
+ },
+
+ complete: function() {
+ // Reset button state
+ updateBtn.disabled = false;
+ updateBtnText.textContent = 'Update firmware';
+ updateSpinner.style.display = 'none';
+ }
+ });
+}
+
+function clearUpdateOutput() {
+ const updateOutput = document.getElementById('updateOutput');
+ const updateOutputContent = document.getElementById('updateOutputContent');
+ const reloadBtn = document.getElementById('reloadBtn');
+
+ updateOutputContent.textContent = '';
+ updateOutput.style.display = 'none';
+ reloadBtn.style.display = 'none';
+}
+
+function showToast(message, type) {
+ const toastLiveExample = document.getElementById('liveToast');
+ const toastBody = toastLiveExample.querySelector('.toast-body');
+
+ // Set toast color based on type
+ toastLiveExample.classList.remove('text-bg-primary', 'text-bg-success', 'text-bg-danger', 'text-bg-warning');
+ switch(type) {
+ case 'success':
+ toastLiveExample.classList.add('text-bg-success');
+ break;
+ case 'error':
+ toastLiveExample.classList.add('text-bg-danger');
+ break;
+ case 'warning':
+ toastLiveExample.classList.add('text-bg-warning');
+ break;
+ default:
+ toastLiveExample.classList.add('text-bg-primary');
+ }
+
+ toastBody.textContent = message;
+ const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);
+ toastBootstrap.show();
+}
+
+
function set_RTC_withNTP(){
console.log("Set RTC module with WIFI (NTP server)");
diff --git a/html/launcher.php b/html/launcher.php
index 3ebcb9d..638d17f 100755
--- a/html/launcher.php
+++ b/html/launcher.php
@@ -255,6 +255,20 @@ if ($type == "git_pull") {
echo $output;
}
+if ($type == "update_firmware") {
+ // Execute the comprehensive update script
+ $command = 'sudo /var/www/moduleair_pro_4g/update_firmware.sh 2>&1';
+ $output = shell_exec($command);
+
+ // Return the output as JSON for better web display
+ header('Content-Type: application/json');
+ echo json_encode([
+ 'success' => true,
+ 'output' => $output,
+ 'timestamp' => date('Y-m-d H:i:s')
+ ]);
+}
+
if ($type == "set_RTC_withNTP") {
$command = 'sudo /usr/bin/python3 /var/www/moduleair_pro_4g/RTC/set_with_NTP.py';
$output = shell_exec($command);