Files
nebuleair_pro_4g/changelog.json
PaulVua de8c22092d v1.9.9: Sonde bruit - retry lecture NSRT MK4 (3x) contre ré-énumération USB
Le NSRT MK4 (USB CDC-ACM) se ré-énumère ~1s par cycle sur le pro150
(dmesg: USB disconnect/reconnect en boucle), ce qui faisait échouer
l'ouverture de /dev/ttyACM0 et enregistrait des points isolés 0.0
"Déconnecté". On retente jusqu'à 3 fois (1s d'intervalle) avant de
conclure à une déconnexion. Cause racine matérielle (alim/câble USB)
à traiter en parallèle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 09:10:09 +02:00

742 lines
41 KiB
JSON

{
"versions": [
{
"version": "1.9.9",
"date": "2026-05-28",
"changes": {
"features": [],
"improvements": [
"Sonde bruit (NSRT MK4): le script de collecte retente jusqu'à 3 fois (1s d'intervalle) avant de marquer 'Déconnecté'. Absorbe les ré-énumérations USB ponctuelles de /dev/ttyACM0 (~1s) qui provoquaient des points isolés à 0.0. Si l'ouverture du port échoue on ré-ouvre, si une lecture échoue on garde le handle ouvert et on retente les lectures."
],
"fixes": [],
"compatibility": []
},
"notes": "Le retry est un palliatif: la cause racine observée sur le pro150 (Device 9565AA75) est une vraie ré-énumération USB du NSRT toutes les ~10s (dmesg: 'USB disconnect' / 'new full-speed USB device' en boucle, numéro de device qui monte). À traiter côté matériel: alimentation/sous-tension du Pi (vcgencmd get_throttled), câble et connecteur USB."
},
{
"version": "1.9.8",
"date": "2026-05-21",
"changes": {
"features": [],
"improvements": [
"Self Test: titre du modal renommé 'Modem Self Test' → 'Self Test' (plus juste, le test couvre aussi les capteurs et le RTC)",
"Self Test: ajout de la ligne 'Firmware Version' dans les logs et dans le rapport copiable (récupérée depuis le fichier VERSION via get_config_sqlite, pas d'AJAX supplémentaire)"
],
"fixes": [],
"compatibility": []
},
"notes": "Si le test Envea passe encore en 'Passed' alors qu'aucune sonde n'est branchée: forcer le rafraîchissement du navigateur (Ctrl+F5) — le fichier selftest.js v1.9.7 est probablement en cache. La nouvelle version doit afficher 'Envea ttyAMA3/4/5: detected=...' au lieu de '=== ENVEA Sensor Reader Started ==='."
},
{
"version": "1.9.7",
"date": "2026-05-21",
"changes": {
"features": [],
"improvements": [
"Modem Self Test: le test 'Envea (Gas Sensors)' vérifie maintenant la présence physique du device sur ttyAMA3/4/5 via detect_envea_device (read_ref.py), au lieu de se fier à la config envea_sondes_table.connected=1. Affiche les ports où un device Envea CAIRSENS est réellement détecté"
],
"fixes": [],
"compatibility": []
},
"notes": "Suite de la v1.9.6: le précédent fix parsait read_value_v2.py mais cette sortie reflète la config UI (sonde activée), pas la réponse physique du device. Le self-test utilise désormais la même logique que la page 'Envea Sondes Detection'."
},
{
"version": "1.9.6",
"date": "2026-05-21",
"changes": {
"features": [],
"improvements": [],
"fixes": [
"Modem Self Test: le test 'Envea (Gas Sensors)' passait à tort en 'Passed' même sans sonde physiquement branchée. L'ancien check vérifiait juste que la sortie debug de read_value_v2.py était non vide et ne contenait pas le mot 'error', ce qui était toujours vrai (le script imprime un en-tête '=== ENVEA Sensor Reader Started ===' et utilise 'Failed' pas 'error' pour les échecs). Le test parse maintenant les marqueurs explicites '✓ NAME = ' (trame valide reçue) et '✗ Failed to read NAME' pour décider Passed/Warning/Failed, et liste les sondes qui répondent vs celles qui ne répondent pas"
],
"compatibility": []
},
"notes": "Fix d'un faux positif du self-test Envea. Détecte aussi le cas 'aucune sonde marquée connected=1' dans envea_sondes_table (sortie '! No connected ENVEA sensors found')."
},
{
"version": "1.9.5",
"date": "2026-05-20",
"changes": {
"features": [],
"improvements": [
"logs.html (modal WiFi connect logs): message clair quand le fichier n'existe pas encore (au lieu du 404 d'Apache qui faisait croire à un bug). Échappement HTML du contenu et limitation aux 1000 dernières lignes pour la performance"
],
"fixes": [],
"compatibility": []
},
"notes": "Petit ajustement UX du modal introduit en v1.9.4: si aucune tentative WiFi n'a eu lieu depuis v1.9.3, on indique simplement qu'il faut en déclencher une plutôt que d'afficher une erreur HTTP."
},
{
"version": "1.9.4",
"date": "2026-05-20",
"changes": {
"features": [
"logs.html: bouton 'WiFi connect logs' qui ouvre un modal affichant le contenu de logs/wifi_connect.log (introduit en v1.9.3), avec bouton Refresh. Permet de récupérer la chronologie complète d'une tentative de connexion WiFi directement depuis l'UI admin, sans passer en SSH"
],
"improvements": [],
"fixes": [],
"compatibility": []
},
"notes": "Complète la v1.9.3 en rendant accessible le nouveau log dédié depuis l'interface admin (le fichier était écrit mais pas affiché dans la page Journal)."
},
{
"version": "1.9.3",
"date": "2026-05-20",
"changes": {
"features": [
"Nouveau log dédié logs/wifi_connect.log (timestamps stricts) tracant chaque étape d'une tentative de connexion WiFi depuis le mode hotspot: réception de la requête PHP, état NetworkManager avant/après, code de retour et sortie complète de nmcli, fallback hotspot si échec"
],
"improvements": [
"connexion.sh: réécrit avec fonction log_wc() horodatée, snapshots NM avant/après, capture stdout+stderr de nmcli, validation des arguments d'entrée, busy timeout SQLite, fallback SSID dérivé du serial RPi"
],
"fixes": [
"Correction critique du flow wifi_connect: launcher.php n'échappait pas les arguments SSID/PASS passés en shell (pas d'escapeshellarg). Les SSID avec espaces ou les mots de passe contenant $, &, ;, espaces, etc. étaient corrompus avant d'atteindre nmcli, faisant échouer silencieusement la connexion (retour client: 'ça bloque au moment de cliquer sur se connecter')",
"wifi.html: ajout de encodeURIComponent() sur SSID et PASS dans l'URL de wifi_connect (caractères &, +, =, # cassaient la requête côté serveur)"
],
"compatibility": []
},
"notes": "Corrige le bug le plus probable derrière les retours clients de connexion WiFi qui échoue sans message d'erreur. Le nouveau log wifi_connect.log permet désormais de diagnostiquer précisément un échec (à fournir lors de tout futur retour client). Log tronqué automatiquement chaque nuit comme les autres logs."
},
{
"version": "1.9.2",
"date": "2026-05-20",
"changes": {
"features": [],
"improvements": [
"boot_hotspot.sh: ajout d'un busy timeout de 5s sur toutes les requêtes SQLite pour gérer la contention avec les timers systemd au boot",
"boot_hotspot.sh: SSID de hotspot dérivé du serial RPi (nebuleair-pro-<serial>) en fallback si deviceName est vide dans la DB"
],
"fixes": [
"Correction d'un bug critique: le hotspot ne démarrait pas si la SQLite était lockée au boot (les requêtes échouaient silencieusement, $DEVICE_NAME restait vide, nmcli refusait de créer un hotspot sans SSID). Visible dans les logs par 'Error: in prepare, database is locked (5)' suivi de 'Failed to setup a Wi-Fi hotspot: A wireless setting with a valid SSID is required'"
],
"compatibility": []
},
"notes": "Garantit que le hotspot de configuration démarre dans tous les cas où wlan0 est déconnecté, même en cas de race condition avec les autres services au boot."
},
{
"version": "1.9.1",
"date": "2026-05-19",
"changes": {
"features": [
"Admin: nouvelle section 'Réseau Tailscale' affichant statut de connexion, IP tailnet, hostname et serveur Headscale",
"Admin: bouton 'Actualiser' pour rafraîchir les infos Tailscale, et bloc déroulant pour consulter les 50 dernières lignes du log bootstrap",
"launcher.php: nouvelles actions get_tailscale_info et get_tailscale_log"
],
"improvements": [
"Vérification visuelle immédiate de l'état d'enrôlement Tailscale sans avoir à passer en SSH"
],
"fixes": [],
"compatibility": [
"Aucun impact sur les capteurs sans Tailscale: la section affiche 'Non installé' avec un message d'invite à mettre à jour"
]
},
"notes": "Complète la v1.9.0 (enrôlement automatique) avec la visibilité UI nécessaire pour valider/diagnostiquer la connexion Tailscale sur chaque capteur depuis l'admin web."
},
{
"version": "1.9.0",
"date": "2026-05-19",
"changes": {
"features": [
"Enrôlement automatique des capteurs sur le tailnet AirCarto (Headscale) pour accès SSH distant via Tailscale",
"installation_part1.sh: installation du paquet Tailscale (curl|sh) + règle sudoers /usr/bin/tailscale *",
"services/tailscale_bootstrap.sh: script idempotent d'enrôlement au boot (hostname dérivé du deviceID: nebuleair-pro-<id>)",
"services/setup_services.sh: nouveau service systemd nebuleair-tailscale-bootstrap (one-shot at boot, After=network-online+tailscaled)",
"update_firmware.sh: nouvelle étape 3d 'Bootstrap Tailscale' — self-heal install + fetch authkey depuis data.nebuleair.fr/pro_4G/get_tailscale_key.php + enrôlement"
],
"improvements": [
"update_firmware.sh: chmod 755 désormais appliqué aussi aux services/*.sh (cohérence avec le pattern existant des dossiers Python)",
"Auth de l'endpoint serveur basée sur le deviceID (déjà connu côté AirCarto, pas de nouveau secret à provisionner sur les capteurs)",
"Fallback HTTPS → HTTP pour le fetch authkey tant que data.nebuleair.fr n'a pas de certificat TLS (à retirer une fois le cert en place)"
],
"fixes": [],
"compatibility": [
"Capteurs déployés pré-v1.9.0: le bootstrap Tailscale s'auto-installe au prochain update OTA (self-heal binary + sudoers via /etc/sudoers.d/nebuleair-tailscale)",
"Capteurs sans connectivité au moment de l'update: l'enrôlement échoue silencieusement et sera retenté au prochain boot via le service systemd",
"Aucun secret committé dans le repo: la preauth key est fetchée à la volée depuis le serveur AirCarto"
]
},
"notes": "Permet l'accès SSH distant aux 200 capteurs déployés une fois leur client a cliqué sur 'Update' dans l'admin web — utile pour le support et le debug à distance sans avoir à demander au client d'intervenir. Côté serveur AirCarto, un nouvel endpoint data.nebuleair.fr/pro_4G/get_tailscale_key.php doit être déployé en parallèle (retourne la preauth key Headscale pour les deviceID valides, avec rate-limiting et audit log recommandés)."
},
{
"version": "1.8.3",
"date": "2026-05-13",
"changes": {
"features": [
"Sidebar: affichage de la version firmware juste sous le nom du capteur (visible sur toutes les pages)"
],
"improvements": [
"launcher.php: get_config_sqlite renvoie maintenant firmware_version (lu depuis le fichier VERSION) — pas de nouveau endpoint, pas de nouveau fetch côté UI",
"topbar-logo.js: peuple .sideBar_firmwareVersion via le fetch config existant + MutationObserver (compatible avec le chargement asynchrone de sidebar.html)"
],
"fixes": [],
"compatibility": [
"Aucun risque sur les pages existantes: les handlers AJAX par page restent inchangés, seul launcher.php ajoute un champ dans la réponse JSON"
]
},
"notes": "Permet d'identifier d'un coup d'oeil la version firmware d'un capteur depuis n'importe quelle page de l'UI — utile pour decider du chemin de mise a jour (online git pull >= v0.x, offline ZIP upload >= v1.4.0) sans avoir a fouiller dans admin.html ou en SSH."
},
{
"version": "1.8.2",
"date": "2026-05-12",
"changes": {
"features": [
"Pre-flight check sudoers avant lancement de l'update (online et offline): détecte les capteurs sans règle NOPASSWD et affiche une alerte claire avec la commande de fix",
"Bouton 'Copier le contenu' pour le bloc sudoers à coller (presse-papier)"
],
"improvements": [
"Détection précoce: l'erreur sudo apparaît immédiatement (en < 1s) au lieu d'attendre l'échec du script en background",
"Message d'erreur user-friendly avec étapes numérotées au lieu de l'erreur cryptique de sudo"
],
"fixes": [],
"compatibility": [
"Aucun impact sur les capteurs sains: si sudo NOPASSWD est correctement configuré, le pre-flight passe en <100ms"
]
},
"notes": "Sur les anciens capteurs installés avant l'ajout de la règle sudoers /var/www/nebuleair_pro_4g/* dans installation_part1.sh, l'update via web UI était silencieusement cassé. Désormais l'UI explique exactement quoi faire en SSH pour réparer."
},
{
"version": "1.8.1",
"date": "2026-05-12",
"changes": {
"features": [
"Upload offline (ZIP): même UX live que l'update online (progress bar dynamique, label étape, timer, logs techniques repliables)",
"Upload offline: self-heal via Step 4c qui appelle setup_services.sh (alignement complet avec l'online)"
],
"improvements": [
"Frontend: mapping des étapes spécifique au mode (UPDATE_STEPS_ONLINE / UPDATE_STEPS_OFFLINE) selon le script lancé",
"Frontend: interpolation sub-step gère désormais Step 3c (online) et Step 4c (offline) de la même façon",
"Backend: route upload_firmware lance maintenant le script en background et réutilise le même mécanisme de log/done que l'update online",
"Détection de fin: substring 'completed successfully!' (matche les deux scripts qui ont des markers finaux légèrement différents)"
],
"fixes": [
"Le bouton 'Upload & Install' restait bloqué sur 'Installing...' après succès — resetUpdateButton remet maintenant les deux boutons à zéro"
],
"compatibility": [
"Aucun risque sur les capteurs existants: même logique, juste l'UX qui change côté UI"
]
},
"notes": "Suite v1.8.0: alignement de l'upload offline sur le flow online. Les deux chemins partagent maintenant le même mécanisme de polling, la même progress bar, et le même self-heal Step 3c/4c. Plus de divergence entre les deux modes."
},
{
"version": "1.8.0",
"date": "2026-05-12",
"changes": {
"features": [
"Update firmware: nouvelle UX avec progress bar dynamique, label de l'étape en cours, et timer mm:ss / estimation",
"Update firmware: streaming live des logs (polling 700ms) — plus de fenêtre 'qui bloque' pendant 90s",
"Update firmware: bloc de statut final (succès vert / échec rouge) avec message explicite",
"Update firmware: logs techniques masqués par défaut dans une section repliable, ouverts automatiquement en cas d'échec"
],
"improvements": [
"Backend: 2 nouvelles routes launcher.php — update_firmware_start (lance en background, retour immédiat) et update_firmware_progress (polling incrémental avec offset)",
"Sous-étape Step 3c (setup_services.sh, le plus long): interpolation de la progression via comptage des 'Started X' (npm, envea, sara, etc.)",
"Sous-étape Step 4 (restart services): interpolation via comptage des 'Restarting enabled service:'"
],
"fixes": [],
"compatibility": [
"L'ancienne route update_firmware (synchronous) est conservée pour rétrocompatibilité"
]
},
"notes": "Refonte UX du process de mise à jour: l'utilisateur voit maintenant en temps réel où on en est (étape, %, temps écoulé) au lieu de fixer un spinner pendant 1-2 minutes. Les logs bruts restent accessibles pour debug pro via une section repliable."
},
{
"version": "1.7.7",
"date": "2026-05-12",
"changes": {
"features": [],
"improvements": [],
"fixes": [
"Page database (Informations sur la base): la colonne 'Plus récente' affichait 'not connected' a cause d'un tri lexicographique mixant des chaines 'not connected' et des dates ISO. Les requetes MIN/MAX excluent maintenant 'not connected'."
],
"compatibility": [
"Aucun impact sur les donnees: les lignes 'not connected' restent en base, elles sont juste ignorees pour le calcul des bornes temporelles affichees"
]
},
"notes": "Effet de bord du bug RTC corrige en v1.7.4: les capteurs deployes avec un rtc_save_to_db.service inactif ont accumule des lignes avec timestamp='not connected'. En tri ASCII, 'n' > '2' donc MAX(timestamp) renvoyait 'not connected' au lieu de la vraie date la plus recente."
},
{
"version": "1.7.6",
"date": "2026-05-12",
"changes": {
"features": [],
"improvements": [
"Page admin (tableau SystemD Services): ajout de 3 services manquants — rtc_save_to_db, nebuleair-wifi-powersave.timer, nebuleair-cpu-power.service",
"Page admin: support d'un display_name explicite par service (sinon auto-cleanup) — affichage propre pour les services .service en plus des .timer",
"Page admin: nebuleair-noise-data.timer ajoute aux listes allowed pour restart/toggle (etait dans get_systemd_services mais pas dans les 2 autres)"
],
"fixes": [],
"compatibility": []
},
"notes": "Le tableau SystemD Services affiche maintenant la liste complete des 11 services NebuleAir. Cohérence des 3 listes hardcodees (display, restart, toggle)."
},
{
"version": "1.7.5",
"date": "2026-05-12",
"changes": {
"features": [],
"improvements": [],
"fixes": [
"update_firmware.sh: chmod +x avant d'executer setup_services.sh (le bit executable est strippé par git config core.fileMode=false, donc le check -x echouait systematiquement et Step 3c logguait 'not found or not executable, skipping')"
],
"compatibility": []
},
"notes": "Suite v1.7.4: le self-heal Step 3c n'etait pas reellement actif a cause d'un check -x trop strict. Cette version corrige le probleme en chmod +x avant l'execution, comme le fait deja installation_part2.sh."
},
{
"version": "1.7.4",
"date": "2026-05-12",
"changes": {
"features": [],
"improvements": [
"Services systemd: source de verite unique dans services/setup_services.sh (le service rtc_save_to_db etait auparavant cree inline dans installation_part2.sh)",
"update_firmware.sh: appelle maintenant setup_services.sh apres git pull (self-healing des services manquants/masques sur les capteurs deja deployes)",
"setup_services.sh: systemctl unmask defensif sur rtc_save_to_db avant creation du fichier (evite l'ecriture dans /dev/null si le service avait ete masque)"
],
"fixes": [
"Bug observe sur capteur deployé: rtc_save_to_db.service masque -> timestamp_table reste a 'not connected' -> RTC affiche comme non connecte dans les logs SARA alors que le materiel fonctionne. L'update firmware ne reparait pas cette situation. Avec v1.7.4, un simple update firmware repare automatiquement."
],
"compatibility": [
"Aucun risque sur les capteurs sains: les fichiers .service sont reecrits avec le meme contenu, comportement inchange",
"Capteurs avec services manquants/masques: seront repares automatiquement au prochain update firmware",
"Aucune migration manuelle requise"
]
},
"notes": "Reorganisation interne du provisionnement des services systemd. installation_part2.sh ne contient plus la definition inline du service RTC (deduplique). save_to_db.py ne contient plus les instructions systemd en commentaire (deduplique). update_firmware.sh devient self-healing pour les services."
},
{
"version": "1.7.3",
"date": "2026-05-12",
"changes": {
"features": [],
"improvements": [],
"fixes": [
"Revert v1.7.2: retrait du check SIM sur la branche CSQ=99 (overhead inutile a chaque coupure signal temporaire, le check sur la branche USOCR/PDP suffit avec un delai de 1-2 cycles maximum)"
],
"compatibility": []
},
"notes": "Apres tests: la SIM est detectee tres vite via la branche PDP meme sans le check sur CSQ=99 (le modem alterne CSQ=99 et CSQ>0 sans SIM). Le check sur CSQ=99 ajoutait du cout AT a chaque coupure reseau temporaire pour un gain marginal. On garde uniquement le check v1.7.1 dans la branche USOCR/PDP."
},
{
"version": "1.7.2",
"date": "2026-05-12",
"changes": {
"features": [],
"improvements": [
"Loop SARA: detection SIM injoignable etendue au cas 'signal CSQ=99' (sans SIM, le modem ne peut pas s'enregistrer donc CSQ=99 systematique)",
"Distinction claire entre 'SIM absente' (alerte rouge + notification) et 'coupure reseau temporaire' (message vert, retry au prochain cycle)"
],
"fixes": [
"v1.7.1 ne detectait pas la SIM absente quand CSQ=99 (le script sortait avant d'atteindre le check SIM dans la branche USOCR)"
],
"compatibility": []
},
"notes": "Complement v1.7.1: le check SIM est maintenant appele dans les deux branches d'echec (CSQ=99 et USOCR ERROR). Couvre tous les cas de SIM injoignable."
},
{
"version": "1.7.1",
"date": "2026-05-12",
"changes": {
"features": [],
"improvements": [
"Loop SARA: detection SIM injoignable avant escalade hardware reboot (evite les reboots inutiles en boucle quand la SIM est absente/mal inseree)",
"Logs HTML: bloc rouge tres visible quand la SIM n'est pas detectee (bordure, fond rose, message d'action clair)",
"Notification WiFi dediee: 'SIM NOT DETECTED -> physical check required' au lieu du generique 'UDP socket creation failed'"
],
"fixes": [
"Plus de hardware reboots repetes a chaque cycle de 60s quand la SIM est physiquement injoignable (economie courant + usure transistor GPIO 16)"
],
"compatibility": []
},
"notes": "Quand la sequence PDP echoue, le script verifie maintenant AT+CPIN? et AT+CCID pour diagnostiquer si le probleme vient de la SIM ou du reseau. Si SIM absente: notification claire + arret propre, pas de reboot. Si SIM presente: comportement actuel (reboot hardware). Le check ne s'execute qu'en cas d'erreur, zero impact sur le happy path."
},
{
"version": "1.7.0",
"date": "2026-04-27",
"changes": {
"features": [
"Page modem: section Tests Miotiq (UDP) visible uniquement avec carte SIM Miotiq",
"Test 1 — Verification connexion PDP: detecte si PDP deja actif, active automatiquement si besoin",
"Test 2 — Test socket UDP: cree/connecte/envoie/ferme un socket vers 192.168.0.20:4242",
"Test 3 — Ping aller-retour Miotiq: envoie payload ping (command=0x02), ecoute reponse descendante via API Miotiq sendToDevice"
],
"improvements": [
"Sections Test HTTP et Send message masquees automatiquement en mode Miotiq (pas d'acces internet)",
"Script check PDP user-friendly: affiche IP si deja actif, pas d'erreurs inutiles",
"Logs AT bruts accessibles via bouton collapse sur tous les tests Miotiq",
"Payload UDP: byte 9 recycle de protocol_version (redondant avec bytes 69-71) en champ command",
"Ping Miotiq: socket binde sur port fixe 33333 + mode non-connecte (AT+USOST/USORF) pour recevoir le downlink"
],
"fixes": [],
"compatibility": [
"Necessite mise a jour du parser Miotiq: renommer version en command (byte 9)",
"Byte 9: 0x00=data (nouveaux capteurs), 0x01=data (anciens capteurs, retrocompat), 0x02=ping test",
"Necessite configuration serveur: reponse descendante Miotiq sur dstPort=33333"
]
},
"notes": "La page modem s'adapte au type de carte SIM. En mode Miotiq, les tests HTTP sont remplaces par des tests UDP dedies avec 3 niveaux: connexion PDP, socket UDP, et ping aller-retour bidirectionnel via l'API descendante Miotiq (valide en ~2s)."
},
{
"version": "1.6.4",
"date": "2026-04-02",
"changes": {
"features": [
"Page modem: boutons Activer/Desactiver LED status connexion PCB (AT+UGPIOC=16,2 / AT+UGPIOC=16,255)"
],
"improvements": [
"Page modem: messages de progression en 3 etapes pendant le reset hardware (coupure, redemarrage, test connexion)",
"Page modem: bouton reset hardware desactive pendant l'operation pour eviter les doubles clics"
],
"fixes": [],
"compatibility": []
},
"notes": "Le reset hardware affiche maintenant les etapes en temps reel (~20s). Deux nouveaux boutons permettent de controler la LED bleue du PCB qui indique l'etat de la connexion reseau du modem."
},
{
"version": "1.6.3",
"date": "2026-04-01",
"changes": {
"features": [
"Page logs: bouton Auto-refresh pour suivre les logs SARA en temps reel (polling 3s)"
],
"improvements": [
"Service SARA: ajout flag python3 -u (unbuffered) pour ecriture immediate des logs dans le fichier"
],
"fixes": [],
"compatibility": [
"Necessite re-execution de setup_services.sh pour activer le mode unbuffered (optionnel, pas d'impact si non fait)"
]
},
"notes": "Les logs SARA sont maintenant visibles en temps reel sur la page logs grace au mode unbuffered Python et au rafraichissement automatique. Aucun impact sur les anciennes installations qui ne relancent pas setup_services.sh."
},
{
"version": "1.6.2",
"date": "2026-03-27",
"changes": {
"features": [],
"improvements": [
"Simplification du script de boot SARA (start.py): suppression config AirCarto, uSpot/SSL, PDP et geolocalisation",
"La configuration modem est desormais entierement geree par le script principal (SARA_send_data_v2.py)"
],
"fixes": [],
"compatibility": []
},
"notes": "Le script de boot ne fait plus que 3 choses: reset modem_config_mode, alimentation modem GPIO 16, detection modele R4/R5. Toute la configuration (URLs, certificats, PDP, geolocalisation) est deja geree par le script principal qui tourne chaque minute avec gestion d'erreur et retry."
},
{
"version": "1.6.1",
"date": "2026-03-19",
"changes": {
"features": [
"Sonometre NSRT MK4: detection deconnexion avec message explicite (page capteurs + self-test)",
"Colonne noise_status dans data_NOISE (0x00=OK, 0xFF=deconnecte)",
"ERR_NOISE (bit 5, byte 66) dans error_flags UDP quand sonometre deconnecte"
],
"improvements": [
"Script NSRT_mk4_get_data.py ecrit en base meme si capteur deconnecte (valeurs a 0, noise_status=0xFF)",
"Script read.py: message d'erreur clair au lieu de l'exception Python brute",
"Self-test: affiche 'Capteur deconnecte — verifiez le cablage USB' au lieu de l'erreur technique"
],
"fixes": [],
"compatibility": [
"Migration automatique: colonne noise_status ajoutee via set_config.py lors du firmware update"
]
},
"notes": "Gestion de la deconnexion du sonometre NSRT MK4 alignee sur le modele NPM: ecriture en base avec status d'erreur, flag ERR_NOISE dans la payload UDP, et messages utilisateur explicites sur l'interface web."
},
{
"version": "1.6.0",
"date": "2026-03-18",
"changes": {
"features": [
"Payload UDP Miotiq: envoi npm_status (byte 67) — registre status NextPM en temps reel"
],
"improvements": [
"npm_status lu depuis la derniere mesure en base (rowid DESC, pas de moyenne ni de timestamp)"
],
"fixes": [],
"compatibility": [
"Necessite mise a jour du parser Miotiq pour decoder le byte 67 (npm_status)"
]
},
"notes": "Le capteur envoie maintenant le registre status du NextPM dans chaque trame UDP (byte 67). La valeur est prise de la derniere mesure sans moyenne (un code erreur ne se moyenne pas). Utilise rowid pour eviter toute dependance au RTC."
},
{
"version": "1.5.2",
"date": "2026-03-18",
"changes": {
"features": [
"Page capteurs: lecture NPM via get_data_modbus_v3.py --dry-run (meme script que le timer)",
"Page capteurs: affichage temperature et humidite interne du NPM",
"Page capteurs: decodage npm_status avec flags d'erreur individuels"
],
"improvements": [
"NPM get_data_modbus_v3.py: mode --dry-run (print JSON sans ecriture en base)",
"Page capteurs: status NPM affiche en vert (OK) ou orange/rouge (erreurs decodees)"
],
"fixes": [
"Page capteurs: suppression unite ug/m3 sur le champ message/status"
],
"compatibility": []
},
"notes": "La page capteurs utilise maintenant le meme script Modbus que le timer systemd, en mode dry-run pour eviter les conflits d'ecriture SQLite. Le status NPM est decode bit par bit."
},
{
"version": "1.5.1",
"date": "2026-03-18",
"changes": {
"features": [
"Payload UDP Miotiq: bytes 69-71 firmware version (major.minor.patch)",
"README: documentation complete de la structure des 100 bytes UDP"
],
"improvements": [],
"fixes": [],
"compatibility": [
"Necessite mise a jour du parser Miotiq pour decoder les bytes 69-71 (firmware version)"
]
},
"notes": "Le capteur envoie maintenant sa version firmware dans chaque trame UDP. Cote serveur, bytes 69/70/71 = major/minor/patch. Documentation payload complete ajoutee au README."
},
{
"version": "1.5.0",
"date": "2026-03-18",
"changes": {
"features": [
"Payload UDP Miotiq: byte 66 error_flags (erreurs systeme RTC/capteurs)",
"Payload UDP Miotiq: byte 67 npm_status (registre status NextPM)",
"Payload UDP Miotiq: byte 68 device_status (etat general du boitier, specification)",
"Methodes SensorPayload: set_error_flags(), set_npm_status(), set_device_status()"
],
"improvements": [
"Initialisation bytes 66-68 a 0x00 au lieu de 0xFF pour eviter faux positifs cote serveur",
"Escalade erreur UDP: si PDP reset echoue, notification WiFi + hardware reboot + exit"
],
"fixes": [],
"compatibility": [
"Necessite mise a jour du parser Miotiq pour decoder les bytes 66-68 (error_flags, npm_status, device_status)"
]
},
"notes": "Ajout de registres d'erreur et d'etat dans la payload UDP (bytes 66-68). Les bytes de status sont initialises a 0x00 (aucune erreur) au lieu de 0xFF. Le flag RTC est implemente, les autres flags seront actives progressivement."
},
{
"version": "1.4.6",
"date": "2026-03-17",
"changes": {
"features": [
"Page Admin: comparaison RTC vs heure du navigateur (au lieu de system time)",
"Page Admin: ajout champ Browser time (UTC) dans l'onglet Clock",
"Page Admin: bloquer update firmware en mode hotspot avec message explicatif",
"Page Admin: liens Gitea pour mise a jour hors-ligne (releases + main.zip)"
],
"improvements": [
"Page Admin: RTC time mis en evidence (label bold, input large, bordure bleue)",
"Page Admin: System time replie dans un details/summary (non utilise par le capteur)",
"Page Admin: descriptions ajoutees pour System time, RTC time et Synchroniser le RTC"
],
"fixes": [
"Fix forget_wifi scan: delai 5s + rescan explicite pour remplir wifi_list.csv",
"Fix blocage navigateur: revert optimisations fetch qui saturaient la limite 6 connexions/domaine"
],
"compatibility": []
},
"notes": "L'onglet Clock compare maintenant le RTC a l'heure du navigateur, plus fiable que le system time Linux (non utilise par le capteur). L'update firmware est bloque en mode hotspot avec un message explicatif. La mise a jour hors-ligne via upload .zip reste disponible."
},
{
"version": "1.4.5",
"date": "2026-03-17",
"changes": {
"features": [
"Page WiFi: bouton Oublier le reseau pour passer en mode hotspot sans reboot",
"Page WiFi: badge Mode Hotspot visible dans la sidebar (lien vers page WiFi)",
"Page WiFi: scan des reseaux WiFi en mode hotspot via cache CSV (scan au demarrage)"
],
"improvements": [
"Page WiFi: refonte UI avec cards contextuelles (infos connexion detaillees si connecte, scan si hotspot)",
"Page WiFi: affichage SSID, signal, IP, passerelle, hostname, frequence, securite",
"Page WiFi: scan WiFi masque quand deja connecte, scan avec colonnes signal et securite",
"Page WiFi: migration de config.json vers get_config_sqlite",
"Endpoint internet enrichi: SSID, signal, frequence, securite, passerelle, hostname",
"Scan WiFi en mode hotspot: lecture du fichier wifi_list.csv avec notice explicative",
"forget_wifi.sh: scan WiFi avec rescan explicite et delai avant lancement hotspot"
],
"fixes": [
"Correction VERSION 1.4.3 -> 1.4.4",
"Fix IP hotspot: 192.168.43.1 -> 10.42.0.1 (defaut NetworkManager)",
"Fix forget_wifi.sh: appel bash explicite + disconnect wlan0 avant delete"
],
"compatibility": []
},
"notes": "Le bouton Oublier le reseau supprime la connexion WiFi sauvegardee, scanne les reseaux disponibles, puis demarre le hotspot (pas de reboot necessaire). En mode hotspot, la page WiFi affiche les reseaux scannes au demarrage via un cache CSV. Adresse hotspot: http://10.42.0.1/html/"
},
{
"version": "1.4.4",
"date": "2026-03-16",
"changes": {
"features": [
"Bouton Self Test disponible sur les pages Accueil, Capteurs et Admin (en plus de Modem 4G)",
"Test du module RTC DS3231 integre dans le self-test (connexion + synchronisation horloge)"
],
"improvements": [
"Refactoring self-test : code JS et HTML des modals extraits dans des fichiers partages (selftest.js, selftest-modal.html)",
"Le modal self-test est charge dynamiquement via fetch, plus besoin de dupliquer le HTML"
],
"fixes": [],
"compatibility": []
},
"notes": "Le self-test est maintenant accessible depuis toutes les pages principales. Le test RTC verifie la connexion du module et l'ecart avec l'heure systeme."
},
{
"version": "1.4.3",
"date": "2026-03-16",
"changes": {
"features": [
"Page database: bouton telecharger toute la table (bypass filtre dates)",
"Page database: validation obligatoire des dates avant telechargement par periode"
],
"improvements": [
"Payload UDP bruit: bytes 22-23 = noise_cur_leq, 24-25 = noise_cur_level, 26-27 = max_noise (reserve)",
"Envoi des deux valeurs bruit (cur_LEQ + DB_A_value) en UDP Miotiq au lieu d'une seule"
],
"fixes": [],
"compatibility": [
"Necessite mise a jour du parser Miotiq pour decoder les nouveaux champs noise_cur_leq et noise_cur_level"
]
},
"notes": "Mise a jour structure UDP bruit pour alignement avec parser Miotiq et ameliorations page database."
},
{
"version": "1.4.2",
"date": "2026-03-14",
"changes": {
"features": [],
"improvements": [],
"fixes": [
"Fix envoi UDP Miotiq: desynchronisation serie causant l'envoi de la commande AT+USOWR comme payload au lieu des donnees capteurs",
"Ajout flush buffer serie (reset_input_buffer) avant chaque etape UDP critique",
"Verification du prompt @ du modem avant envoi des donnees binaires",
"Abort propre de l'envoi UDP si creation socket, connexion ou prompt @ echoue",
"Retry creation socket apres reset PDP reussi"
],
"compatibility": []
},
"notes": "Corrige un bug ou le modem SARA envoyait la commande AT+USOWR comme donnees UDP, causant des erreurs UNKNOWN_DEVICE sur le parser Miotiq."
},
{
"version": "1.4.1",
"date": "2026-03-12",
"changes": {
"features": [],
"improvements": [
"Migration capteur bruit de l'ancien systeme I2C vers le sonometre NSRT MK4 en USB",
"Nouveau script sound_meter/read.py pour lecture a la demande (retour JSON)",
"Page capteurs: carte USB avec affichage LEQ et dB(A) au lieu de l'ancien format texte",
"Self-test modem: parsing JSON du NSRT MK4 au lieu de texte brut"
],
"fixes": [
"Correction du self-test bruit qui affichait 'Unexpected value' avec le nouveau capteur"
],
"compatibility": []
},
"notes": "Mise a jour necessaire si le sonometre NSRT MK4 est connecte en USB. L'ancien capteur I2C n'est plus supporte sur la page capteurs."
},
{
"version": "1.4.0",
"date": "2026-03-10",
"changes": {
"features": [
"Mise a jour firmware hors-ligne par upload de fichier ZIP via l'interface web admin",
"Barre de progression pour suivre l'upload du fichier",
"Fichier .update-exclude versionne pour gerer les exclusions rsync de maniere evolutive"
],
"improvements": [
"Vidage du buffer serie avant chaque commande AT dans sara.py (evite les URCs residuelles au demarrage)"
],
"fixes": [],
"compatibility": [
"Necessite l'ajout de update_firmware_from_file.sh dans les permissions sudo de www-data",
"Necessite Apache mod_rewrite pour html/.htaccess (upload 50MB)"
]
},
"notes": "Permet la mise a jour du firmware sans connexion internet : telecharger le .zip depuis Gitea, se connecter au hotspot du capteur, et uploader via admin.html."
},
{
"version": "1.3.0",
"date": "2026-02-17",
"changes": {
"features": [
"Onglet 'Ecran' pour le controle de l'affichage HDMI (ModuleAir Pro uniquement)",
"Demarrage et arret du script d'affichage via l'interface web",
"Verification automatique du type d'appareil pour afficher l'onglet"
],
"improvements": [
"Ajout de logs console pour le debougage des commandes web",
"Traduction de l'element de menu 'Ecran'"
],
"fixes": [
"Correction des permissions d'execution des scripts python via web (sudo)",
"Correction de la visibilite des onglets du menu lateral (doublons ID)"
],
"compatibility": [
"Necessite python3-kivy installe",
"Necessite l'ajout de permissions sudo pour www-data (voir documentation)"
]
},
"notes": "Ajout de la fonctionnalite de controle d'ecran pour les demonstrations."
},
{
"version": "1.2.0",
"date": "2026-02-17",
"changes": {
"features": [
"Integration capteur CO2 MH-Z19 (scripts, base de donnees, service systemd, interface web)",
"Carte test CO2 sur la page capteurs",
"Checkbox activation CO2 sur la page admin",
"Consultation et telechargement des mesures CO2 sur la page base de donnees"
],
"improvements": [],
"fixes": [
"Logo ModuleAir Pro ne s'affichait pas (script dans innerHTML non execute)"
],
"compatibility": [
"Necessite re-execution de create_db.py, set_config.py et setup_services.sh apres mise a jour"
]
},
"notes": "Ajout du support capteur CO2 MH-Z19 pour le ModuleAir Pro. La transmission SARA sera integree dans une version ulterieure."
},
{
"version": "1.1.0",
"date": "2026-02-16",
"changes": {
"features": [
"Card informations base de donnees (taille, nombre d'entrees, dates min/max par table)",
"Telechargement CSV complet par table depuis la page base de donnees",
"Bouton version firmware NextPM sur la page capteurs",
"Tests capteurs integres dans l'auto-test modem",
"Logo dynamique selon le type d'appareil (NebuleAir/ModuleAir)"
],
"improvements": [
"Reordonnancement de l'auto-test : capteurs avant communication"
],
"fixes": [],
"compatibility": []
},
"notes": "Ameliorations de l'interface web : meilleure visibilite sur l'etat de la base de donnees et des capteurs."
},
{
"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."
}
]
}