From 50a8cdd938de3b7d7701c25ad397164ede110484 Mon Sep 17 00:00:00 2001 From: PaulVua Date: Wed, 11 Feb 2026 16:12:18 +0100 Subject: [PATCH] feat: add firmware versioning and device_type support (NebuleAir/ModuleAir) - Add VERSION file (1.0.0) and changelog.json for firmware tracking - Add device_type config param (nebuleair_pro default, backward compatible via INSERT OR IGNORE) - Add device_type select in admin.html Protected Settings - Add version badge and changelog modal in Updates section - Add get_firmware_version and get_changelog PHP endpoints - Display firmware version in update_firmware.sh after git pull Co-Authored-By: Claude Opus 4.6 --- VERSION | 1 + changelog.json | 21 ++++++ html/admin.html | 163 ++++++++++++++++++++++++++++++++++++++++++- html/launcher.php | 41 +++++++++++ sqlite/set_config.py | 1 + update_firmware.sh | 5 ++ 6 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 VERSION create mode 100644 changelog.json diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.0.0 diff --git a/changelog.json b/changelog.json new file mode 100644 index 0000000..8f5efba --- /dev/null +++ b/changelog.json @@ -0,0 +1,21 @@ +{ + "versions": [ + { + "version": "1.0.0", + "date": "2026-02-11", + "changes": { + "features": [ + "Support multi-device : NebuleAir Pro / ModuleAir Pro", + "Systeme de versioning firmware", + "Changelog viewer dans l'interface web" + ], + "improvements": [], + "fixes": [], + "compatibility": [ + "Les capteurs existants sont automatiquement configures en 'nebuleair_pro'" + ] + }, + "notes": "Premiere version tracee. Les capteurs anterieurs recevront device_type=nebuleair_pro par defaut lors de la mise a jour." + } + ] +} diff --git a/html/admin.html b/html/admin.html index 9911885..1351b16 100755 --- a/html/admin.html +++ b/html/admin.html @@ -174,6 +174,13 @@ +
+ + +
@@ -219,7 +226,11 @@
-

Updates

+
+

Updates

+ Version... + +
+ + + @@ -437,6 +470,12 @@ window.onload = function() { checkbox_aircarto.checked = response["send_aircarto"]; checkbox_miotiq.checked = response["send_miotiq"]; + // Set device type + const device_type_select = document.getElementById("device_type"); + if (response["device_type"]) { + device_type_select.value = response["device_type"]; + } + // Set CPU power mode const cpu_power_mode_select = document.getElementById("cpu_power_mode"); if (response["cpu_power_mode"]) { @@ -555,7 +594,10 @@ window.onload = function() { // Load services on page load refreshServices(); - + + // Load firmware version + loadFirmwareVersion(); + } //end window.onload @@ -1644,6 +1686,123 @@ function toggleProtectedSettings() { } } +/* + __ __ _ _ + \ \ / /__ _ __ ___(_) ___ _ __ (_)_ __ __ _ + \ \ / / _ \ '__/ __| |/ _ \| '_ \| | '_ \ / _` | + \ V / __/ | \__ \ | (_) | | | | | | | | (_| | + \_/ \___|_| |___/_|\___/|_| |_|_|_| |_|\__, | + |___/ +*/ + +function loadFirmwareVersion() { + $.ajax({ + url: 'launcher.php?type=get_firmware_version', + dataType: 'json', + method: 'GET', + cache: false, + success: function(response) { + const badge = document.getElementById('firmwareVersionBadge'); + if (response.success) { + badge.textContent = 'v' + response.version; + badge.className = 'badge bg-primary'; + } else { + badge.textContent = 'Version unknown'; + badge.className = 'badge bg-secondary'; + } + }, + error: function() { + const badge = document.getElementById('firmwareVersionBadge'); + badge.textContent = 'Version unknown'; + badge.className = 'badge bg-secondary'; + } + }); +} + +function showChangelogModal() { + const modal = new bootstrap.Modal(document.getElementById('changelogModal')); + modal.show(); + + // Load changelog data + $.ajax({ + url: 'launcher.php?type=get_changelog', + dataType: 'json', + method: 'GET', + cache: false, + success: function(response) { + if (response.success && response.changelog) { + displayChangelog(response.changelog); + } else { + document.getElementById('changelogModalBody').innerHTML = + '
Could not load changelog.
'; + } + }, + error: function() { + document.getElementById('changelogModalBody').innerHTML = + '
Failed to load changelog.
'; + } + }); +} + +function displayChangelog(data) { + const container = document.getElementById('changelogModalBody'); + let html = ''; + + data.versions.forEach(function(version) { + html += `
`; + html += `
`; + html += `
v${version.version}
`; + html += `${version.date}`; + html += `
`; + html += `
`; + + // Features + if (version.changes.features && version.changes.features.length > 0) { + html += `
Features
    `; + version.changes.features.forEach(function(f) { + html += `
  • ${f}
  • `; + }); + html += `
`; + } + + // Improvements + if (version.changes.improvements && version.changes.improvements.length > 0) { + html += `
Improvements
    `; + version.changes.improvements.forEach(function(i) { + html += `
  • ${i}
  • `; + }); + html += `
`; + } + + // Fixes + if (version.changes.fixes && version.changes.fixes.length > 0) { + html += `
Fixes
    `; + version.changes.fixes.forEach(function(f) { + html += `
  • ${f}
  • `; + }); + html += `
`; + } + + // Compatibility + if (version.changes.compatibility && version.changes.compatibility.length > 0) { + html += `
Compatibility:
    `; + version.changes.compatibility.forEach(function(c) { + html += `
  • ${c}
  • `; + }); + html += `
`; + } + + // Notes + if (version.notes) { + html += `

${version.notes}

`; + } + + html += `
`; + }); + + container.innerHTML = html; +} + diff --git a/html/launcher.php b/html/launcher.php index 3c17c4e..c926a2f 100755 --- a/html/launcher.php +++ b/html/launcher.php @@ -1515,6 +1515,47 @@ if ($type == "detect_envea_device") { |___/ */ +// Get firmware version from VERSION file +if ($type == "get_firmware_version") { + $versionFile = '/var/www/nebuleair_pro_4g/VERSION'; + if (file_exists($versionFile)) { + $version = trim(file_get_contents($versionFile)); + echo json_encode([ + 'success' => true, + 'version' => $version + ]); + } else { + echo json_encode([ + 'success' => false, + 'version' => 'unknown' + ]); + } +} + +// Get changelog from changelog.json +if ($type == "get_changelog") { + $changelogFile = '/var/www/nebuleair_pro_4g/changelog.json'; + if (file_exists($changelogFile)) { + $changelog = json_decode(file_get_contents($changelogFile), true); + if ($changelog !== null) { + echo json_encode([ + 'success' => true, + 'changelog' => $changelog + ]); + } else { + echo json_encode([ + 'success' => false, + 'error' => 'Invalid changelog format' + ]); + } + } else { + echo json_encode([ + 'success' => false, + 'error' => 'Changelog file not found' + ]); + } +} + // Get current CPU power mode if ($type == "get_cpu_power_mode") { try { diff --git a/sqlite/set_config.py b/sqlite/set_config.py index da95c4c..863a588 100644 --- a/sqlite/set_config.py +++ b/sqlite/set_config.py @@ -51,6 +51,7 @@ config_entries = [ ("MPPT", "0", "bool"), ("NOISE", "0", "bool"), ("modem_version", "XXX", "str"), + ("device_type", "nebuleair_pro", "str"), ("language", "fr", "str"), ("wifi_power_saving", "0", "bool"), ("cpu_power_mode", "normal", "str") diff --git a/update_firmware.sh b/update_firmware.sh index a5c6db9..d09f96c 100755 --- a/update_firmware.sh +++ b/update_firmware.sh @@ -57,6 +57,11 @@ fi git pull origin $(git branch --show-current) check_status "Git pull" +# Display firmware version +if [ -f "/var/www/nebuleair_pro_4g/VERSION" ]; then + print_status "Firmware version: $(cat /var/www/nebuleair_pro_4g/VERSION)" +fi + # Step 2: Update database configuration print_status "" print_status "Step 2: Updating database configuration..."