L'upload offline avait deux defauts vs l'update online:
- pas de self-heal des services (pas de Step 3c equivalent)
- ancienne UX synchrone (spinner sans feedback pendant 60-90s)
Maintenant:
- update_firmware_from_file.sh: nouveau Step 4c qui appelle
setup_services.sh (alignement avec online)
- launcher.php upload_firmware: lance le script en background et
reutilise le mecanisme log/done de l'update online
- admin.html uploadFirmware: apres l'upload du ZIP, bascule sur
le meme systeme de polling/progress que l'online (avec mapping
d'etapes specifique au script offline)
- Detection de fin par substring 'completed successfully!' (matche
les 2 markers finaux differents)
Fix au passage: le bouton 'Upload & Install' restait bloque sur
'Installing...' apres succes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
L'ancien flow etait un AJAX bloquant qui attendait ~90s sans aucun
retour visuel autre qu'un spinner.
Nouveau flow:
- Backend: launcher.php lance update_firmware.sh en background
(route update_firmware_start) et expose une route de polling
incremental (update_firmware_progress) avec offset.
- Frontend: progress bar Bootstrap animee + label de l'etape en
cours + timer mm:ss / estimation, plus streaming des logs
toutes les 700ms.
- Sous-etape Step 3c (la plus longue): interpolation fine de la
progression en comptant les 'Started X' (services demarres).
- Logs techniques masques par defaut dans <details>, ouverts
automatiquement en cas d'echec pour faciliter le debug.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Les requetes MIN/MAX(timestamp) sur les tables capteur etaient
faussees par les lignes accumulees pendant le bug RTC (v1.7.4):
la chaine 'not connected' > toute date ISO en tri ASCII, donc
MAX() retournait 'not connected' au lieu de la vraie date la
plus recente.
Fix: WHERE timestamp != 'not connected' dans les requetes MIN/MAX.
Les lignes 'not connected' restent en base, elles sont juste
ignorees pour le calcul des bornes temporelles affichees.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ajout dans le tableau admin et dans les listes allowed restart/toggle:
- rtc_save_to_db.service
- nebuleair-wifi-powersave.timer
- nebuleair-cpu-power.service
Aussi: nebuleair-noise-data.timer etait dans get_systemd_services
mais absent des listes restart/toggle (les boutons n'auraient pas
fonctionne). Corrige.
Nouveau: support d'un display_name explicite par service (override
optionnel) pour les noms qui ne suivent pas la convention
'nebuleair-*-data.timer'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Le check -x echouait car git config core.fileMode=false (defini dans
installation_part1.sh) strippe le bit executable. Resultat: Step 3c
logguait 'not found or not executable, skipping' au lieu de
reellement appeler setup_services.sh.
Fix: chmod +x avant l'execution, comme le fait deja
installation_part2.sh sur le meme script.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
setup_services.sh devient la source unique pour les services systemd
(le service rtc_save_to_db etait auparavant cree inline dans
installation_part2.sh, en doublon avec un commentaire dans save_to_db.py).
update_firmware.sh appelle maintenant setup_services.sh apres le git
pull. Resultat: les capteurs deja deployes peuvent se reparer tout
seuls au prochain update firmware (services manquants, masques, ou
nouveaux services ajoutes au repo apres l'installation initiale).
Defensif: systemctl unmask sur rtc_save_to_db avant creation du
fichier .service, pour eviter d'ecrire dans /dev/null si le service
avait ete masque (cas observe sur un capteur en production).
Pas de risque sur les capteurs sains: reecriture des .service avec
le meme contenu, comportement inchange.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Le check SIM sur CSQ=99 ajoutait 2 commandes AT a chaque coupure
signal temporaire (frequent en zone marginale) pour un gain
marginal: le check sur la branche USOCR/PDP attrape le cas avec
un delai de 1-2 cycles max (le modem sans SIM alterne CSQ=99
et CSQ>0).
On garde uniquement le check v1.7.1 dans la branche USOCR.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sans SIM, le modem retourne CSQ=99 systematique et le script
sortait avant d'atteindre le check SIM ajoute en v1.7.1.
- Branche CSQ=99: appelle aussi check_sim_status()
- Si SIM absente: alerte rouge + notification WiFi
- Si SIM OK: message vert (coupure reseau temporaire)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Meme modele que NPM: ecriture en base avec valeurs a 0 et noise_status=0xFF
si capteur deconnecte, flag ERR_NOISE (bit 5) dans byte 66 UDP, messages
explicites sur page capteurs et self-test.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Lecture npm_status depuis derniere mesure en base (rowid DESC, pas de moyenne)
- Independant du RTC (pas de dependance au timestamp)
- Byte 67 du payload UDP = registre status NextPM
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- NPM: mode --dry-run (print JSON sans ecriture en base)
- launcher.php: endpoint npm appelle get_data_modbus_v3.py --dry-run
- sensors.html: affichage PM + temp + humidite + status NPM decode
- Suppression unite ug/m3 sur le champ status
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Lecture fichier VERSION et pack major.minor.patch dans bytes 69-71
- README: documentation complete structure 100 bytes + conso data
- Changelog mis a jour
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Bytes 66-68 (error_flags, npm_status, device_status) initialises a 0x00
au lieu de 0xFF pour eviter faux positifs cote serveur
- Implementation flag RTC (byte 66) + methodes SensorPayload
- Escalade PDP reset: si echec → notification + hardware reboot + exit
- Changelog et VERSION mis a jour
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extraction du code self-test dans des fichiers partagés (selftest.js +
selftest-modal.html) pour éviter la duplication. Ajout du bouton Run
Self Test sur les pages index, sensors et admin. Nouveau test RTC qui
vérifie la connexion du module DS3231 et la synchronisation horloge.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Corrige une desynchronisation serie qui causait l'envoi de la commande
AT+USOWR comme donnees UDP au lieu du payload capteurs. Ajout de flush
buffer serie, verification du prompt @, et abort propre a chaque etape.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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 <noreply@anthropic.com>