Commit Graph

54 Commits

Author SHA1 Message Date
PaulVua
aa71766748 v1.12.2: flag CO2_ERROR (bit 7) quand la sonde S88 est deconnectee
A la demande: en plus du sentinel 0xFFFF dans le champ CO2, on remonte le
defaut via error_flags byte 66 bit 7.

- ERR_CO2 = 0x80 (bit 7, double sens vent/CO2 selon device_type cote serveur)
- s88_disconnected -> error_flags |= ERR_CO2 dans SARA_send_data_v2.py
- error_flags.md: bit 7 documente comme WIND_ERROR / CO2_ERROR

Confirme par le user: le serveur lit le bit 7 comme CO2_ERROR sur ces unites.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 17:30:21 +02:00
PaulVua
d554f03195 v1.12.1: S88 ecrit toujours + code d'etat, plus de CO2 perime transmis
Probleme vu sur pro100: sonde S88 muette (panne cablage) mais write_data.py
n'ecrivait rien -> la base gardait la derniere valeur (487 ppm d'hier) et la
loop d'envoi la transmettait en boucle.

- data_S88: nouvelle colonne s88_status (0=OK, 0xFF=sonde muette), comme
  npm_status/noise_status. Migration via create_db.py + set_config.py + self-heal.
- S88/write_data.py: ecrit DESORMAIS une ligne a chaque cycle (CO2=0 + 0xFF si
  pas de reponse). Connexion SQLite timeout=10 (anti database-is-locked).
- SARA_send_data_v2.py: lit s88_status; si 0xFF -> bytes 81-82 restent 0xFFFF
  (CO2 absent) au lieu d'envoyer une valeur perimee. Compatible bases non migrees.
- database.html + launcher.php: badge statut + colonne dans les exports CSV.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 17:10:32 +02:00
PaulVua
dad953acdc v1.12.0: transmission CO2 S88 dans le payload UDP Miotiq (byte 81)
Débloque le WIP S88->Miotiq. Spec serveur reçue: byte 81-82 = CO2 (ISO_17,
uint16 ppm). Source = Senseair S88 (vrai CO2 NDIR).

- SensorPayload.set_co2() -> bytes 81-82 (uint16, clamp 0..65535)
- lecture data_S88 (derniere ligne) si config S88 active, puis set_co2
- defaut 0xFFFF = capteur absent
- canal UDP Miotiq uniquement (CSV/JSON non touches)
- error_flags.md: byte-map a jour (81-82 = CO2)

CCS811 (TVOC/eCO2) NON transmis: pas encore de champ dans la spec Miotiq.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 16:55:54 +02:00
PaulVua
13c266d694 v1.11.0: CCS811 en daemon + fix filtrage + I2C 10kHz requis
Vérif terrain sur pro100 : à 100 kHz le CCS811 renvoie des valeurs corrompues
0x8000 (32768) par clock-stretching, et le modèle oneshot-reset-toutes-les-10s
ne donne que le 1er échantillon post-init (garbage). Refonte :

- CCS811/daemon.py: service long-running (Type=simple, Restart=always). Init 1x,
  boucle lecture/écriture 10s, filtre eCO2 dans [400,8192], re-init auto sur
  erreurs I2C répétées. Remplace write_data.py (supprimé).
- CCS811/get_data.py: lit la dernière ligne data_CCS811 au lieu du capteur
  (évite la collision I2C avec le daemon -> corruption observée).
- setup_services.sh: service daemon + self-heal suppression de l'ancien .timer;
  activation hors boucle timers.
- launcher.php: .timer -> .service (map statut + allowedServices x2).
- update_firmware.sh: redémarre le daemon à l'OTA.
- doc: README (archi daemon + I2C 10kHz confirmé requis), CLAUDE.md, changelog.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 16:08:03 +02:00
PaulVua
46c73acb7e v1.10.1: OTA installe les deps pip + filtre lectures parasites CCS811
Découvert en vérif SSH sur nebuleair-pro100 : le timer CCS811 échouait en
ModuleNotFoundError car l'OTA fait git pull mais ne réinstallait jamais les
dépendances pip (installation_part1.sh ne tourne qu'à l'install neuve).

- requirements.txt: source unique de vérité des deps Python
- installation_part1.sh: install via requirements.txt (chemin relatif au script,
  le repo n'est pas encore cloné dans /var/www à cette étape)
- update_firmware.sh: nouvelle étape 2a, pip install -r requirements.txt
  (idempotent) -> les capteurs déjà déployés récupèrent les libs manquantes à l'OTA
- CCS811/write_data.py + get_data.py: skip des lectures eCO2 < 400 ppm
  (échantillon 0/0 parasite juste après init du driver, plancher physique = 400)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 15:51:58 +02:00
PaulVua
4f3d273981 v1.10.0: intégration capteur CCS811 (TVOC/eCO2, I2C)
Nouveau capteur de qualité d'air CCS811 sur le bus I2C, calqué sur le
pattern S88 (local-only, pas encore dans le payload de transmission).

- CCS811/get_data.py (lecture live) + write_data.py (timer 10s, self-heal table)
- table data_CCS811 (timestamp, eCO2, TVOC) dans create_db.py
- config CCS811 (bool) + CCS811_address (0x5A/0x5B, défaut 0x5A) dans set_config.py
- service+timer systemd nebuleair-ccs811-data (10s) + ajout boucle d'activation
- admin.html: case d'activation + dropdown adresse I2C
- sensors.html: carte Get Data (TVOC + eCO2)
- database.html + launcher.php: consultation/export/stats data_CCS811
- lib adafruit-circuitpython-ccs811 dans installation_part1.sh
- CCS811/README.md: câblage, adresses, warning clock-stretching I2C sur Pi
- CLAUDE.md + changelog mis à jour

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 14:27:11 +02:00
PaulVua
4767b145b2 v1.9.19: S88/write_data.py - self-heal CREATE TABLE IF NOT EXISTS
Protège contre le cas où l'OTA n'appelle pas create_db.py (problème
bash classique: le script d'OTA est chargé en mémoire au lancement,
le git pull du step 1 met à jour le fichier sur disque mais bash
continue d'exécuter l'ancienne version).

Le script crée la table data_S88 lui-même au démarrage. Schéma dupliqué
de create_db.py — à garder synchro. Pattern à appliquer aux futurs
capteurs pour éviter cette classe de bug.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 17:12:53 +02:00
PaulVua
4e5e1a8144 v1.9.18: fix OTA - create_db.py manquant dans update scripts
Les MAJ OTA ne lancent pas create_db.py, donc toute nouvelle table
ajoutée par une release (ex: data_S88) reste inexistante en base.
Les timers tournent, le script s'exécute, mais l'INSERT échoue
silencieusement avec 'no such table' — capturé par le try/except,
exit 0, systemd voit success.

Symptôme observé sur les capteurs avec S88 activé: 'Get Data' marche
(live read), mais 'Mesures CO2 (Senseair S88)' montre 'Aucune donnée
disponible dans cette table'.

Fix: create_db.py est appelé en step 2 juste avant set_config.py
dans les deux scripts d'update (git pull et upload fichier).
Idempotent (CREATE IF NOT EXISTS + ALTER ADD COLUMN in try/except).

Self-bootstrap: après cette OTA, tous les capteurs auront toutes
les tables, y compris celles introduites dans des releases passées.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 17:03:07 +02:00
PaulVua
0f94fda0ba v1.9.17: database.html - modal + pagination, boutons S88
Refonte des boutons 'Consulter la base de donnée': ils ouvrent
désormais un grand modal Bootstrap (modal-xl scrollable) avec
pagination 20 lignes/page (Précédent/Suivant + indicateur de plage).
Le dropdown 'Nombre de mesures' est supprimé.

Ajout des boutons Senseair S88 dans les 3 cartes pointant sur
data_S88, et renommage du bouton MH-Z19 pour le distinguer.

Backend: sqlite/read.py accepte un OFFSET optionnel (3e argument,
défaut 0) et launcher.php endpoint table_mesure transmet ?offset=N.
Rétrocompatible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 16:51:49 +02:00
PaulVua
6d157cd099 v1.9.16: S88 - dropdown port avec labels PCB (NPM1/2/3)
Le sélecteur affiche 'port NPM1 (/dev/ttyAMA5)' au lieu de juste
'/dev/ttyAMA5', pour matcher le silkscreen de la PCB et éviter
les erreurs de branchement. ttyAMA0 et ttyAMA2 (SARA) sont retirés.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 16:39:28 +02:00
PaulVua
54d0387c1d v1.9.15: S88 - sélecteur de port UART dans admin.html
Ajoute un dropdown ttyAMA0/2/3/4/5 sous la checkbox 'Send CO2
sensor data (Senseair S88)' qui modifie S88_port en base.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 16:31:23 +02:00
PaulVua
7681578f22 v1.9.14: Senseair S88 - implémentation lecture Modbus RTU
read_co2() lit IR1..IR4 en une trame (status + CO2) à 9600 8N1,
adresse 0xFE 'any address', avec vérification CRC16-Modbus et rejet
de la mesure si status non-nul (warm-up ou erreur).

CRC requête/réponse validés contre les exemples du datasheet TDE14367.
Doc protocole consolidée dans S88/README.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 16:24:44 +02:00
PaulVua
239bdfea69 v1.9.13: Capteur CO2 Senseair S88 - scaffolding
Table data_S88, flag config S88 + port configurable S88_port
(default /dev/ttyAMA5), service/timer systemd 10s, carte
sensors.html, endpoint launcher.php, toggle admin.html.

read_co2() est un stub NotImplementedError en attente du datasheet.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 16:15:37 +02:00
PaulVua
4a74f949a0 v1.9.12: SARA loop - 2e test de comm avant hardware reboot
Quand AT+CSQ ne repond pas (hoquet serie temporaire), retente le
AT+CSQ jusqu'a 3x (0.5s d'intervalle) avant d'escalader. Si le modem
repond, le flux normal reprend sans reboot -> evite les coupures
d'alim GPIO et l'usure du modem pour une absence de reponse ponctuelle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 10:27:35 +02:00
PaulVua
3c8ce03449 v1.9.11: Bouton 'Test Power Supply' (check sous-tension rapide)
Ajoute un bouton à côté de 'Run Self Test' (4 pages) qui lance
uniquement le check sous-tension dans un petit modal dédié, sans
dérouler tout le Self Test. Réutilise l'endpoint type=throttled.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 09:40:32 +02:00
PaulVua
6c0318ba6e v1.9.10: Self Test - check sous-tension (vcgencmd get_throttled)
Ajoute un test 'Power Supply' au Self Test pour détecter une
sous-tension du Pi (cause fréquente de capteurs USB instables,
corruptions SD, reboots). Endpoint launcher.php?type=throttled
+ script power/get_throttled.py (lancé via sudo python3, déjà
whitelisté — pas de modif sudoers). Affiché en tête des résultats
et dans le rapport copiable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 09:25:18 +02:00
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
PaulVua
ff1225d483 v1.9.8: Self Test - vrai check Envea + firmware version + renommage
- Fix Envea Gas Sensors: scan physique via detect_envea_device (read_ref.py)
  sur ttyAMA3/4/5 au lieu de juste vérifier envea_sondes_table.connected=1.
  L'ancien check disait Passed même sans sonde branchée car read_value_v2.py -d
  imprime un en-tête de debug non vide et utilise "Failed" pas "error".
- Ajout Firmware Version dans les logs et le rapport (via firmware_version
  déjà retourné par get_config_sqlite, pas d'AJAX supplémentaire).
- Renommage titre modal "Modem Self Test" -> "Self Test" (couvre aussi
  capteurs et RTC, pas uniquement le modem).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 12:04:28 +02:00
PaulVua
bf38fdf811 v1.9.5: Modal wifi_connect.log - message clair si fichier absent
Au lieu d'afficher l'erreur Apache "404 Not Found" qui faisait croire
à un bug, le modal indique maintenant que le log n'existe que lorsqu'une
tentative de connexion WiFi a déjà eu lieu. Inclut aussi un échappement
HTML basique du contenu et limite l'affichage aux 1000 dernières lignes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:44:26 +02:00
PaulVua
3aae307842 v1.9.4: UI - Modal pour consulter wifi_connect.log depuis l'admin
Ajoute un bouton 'WiFi connect logs' dans logs.html qui ouvre un modal
avec le contenu de logs/wifi_connect.log (créé en v1.9.3). Permet de
diagnostiquer une tentative de connexion WiFi sans passer en SSH.

Le contenu est chargé à l'ouverture du modal (pas au chargement de la
page) pour éviter de saturer la limite de 6 connexions du navigateur
sur la page Journal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:36:42 +02:00
PaulVua
3109455ea0 v1.9.3: Fix wifi_connect (escaping shell + URL) + log dédié
Bugs corrigés:
- launcher.php passait SSID/PASS au shell sans escapeshellarg(): un
  mot de passe avec $/&/;/espace cassait silencieusement la commande
  avant que nmcli ne soit appelé. Cause probable des retours clients
  "ça bloque au cliquer sur Se connecter".
- wifi.html n'encodait pas SSID/PASS dans l'URL: caractères &/+/=
  corrompaient la requête.

Observabilité:
- Nouveau fichier logs/wifi_connect.log avec timestamps stricts
- launcher.php log la requête entrante (IP, longueurs SSID/PASS)
- connexion.sh: fonction log_wc(), snapshots NM avant/après,
  capture stdout+stderr nmcli, code retour explicite, fallback SSID
  dérivé du serial si deviceName indisponible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:23:10 +02:00
PaulVua
69fa928d56 v1.9.2: Fix hotspot non démarré si SQLite lockée au boot
- boot_hotspot.sh: busy timeout 5s sur les requêtes SQLite
- boot_hotspot.sh: SSID fallback nebuleair-pro-<serial> si deviceName vide
- Corrige le cas où le hotspot ne démarrait pas quand la DB était
  lockée par les timers systemd au boot (SSID vide → nmcli refuse)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:15:08 +02:00
PaulVua
654c05f548 v1.9.1: Admin UI - Section Reseau Tailscale (statut, IP, hostname, logs)
- admin.html: nouveau card 'Reseau Tailscale' avec statut connecte/deconnecte,
  IP tailnet, hostname, serveur Headscale et bouton Actualiser
- admin.html: bloc deroulant pour consulter les 50 dernieres lignes du log
  bootstrap (logs/tailscale_bootstrap.log)
- launcher.php: nouvelles actions get_tailscale_info (status + IP + hostname
  via sudo tailscale ip/status) et get_tailscale_log (tail -n 50)

Complete la v1.9.0 avec la visibilite UI necessaire pour valider/diagnostiquer
la connexion Tailscale sur chaque capteur sans avoir a passer en SSH.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 12:11:03 +02:00
PaulVua
b008b486ae v1.9.0: Enrolement automatique des capteurs sur le tailnet AirCarto (Tailscale/Headscale)
- installation_part1.sh: install paquet Tailscale + sudoers /usr/bin/tailscale
- services/tailscale_bootstrap.sh (nouveau): script idempotent d'enrolement au boot
- services/setup_services.sh: service systemd nebuleair-tailscale-bootstrap (one-shot)
- update_firmware.sh: nouvelle etape 3d 'Bootstrap Tailscale' (self-heal install + fetch
  authkey depuis data.nebuleair.fr/pro_4G/get_tailscale_key.php + enrolement). Fallback
  HTTPS->HTTP en attendant le cert TLS cote serveur.

Permet l'acces SSH distant aux 200 capteurs deployes via le tailnet une fois que leur
client a clique sur 'Update' dans l'admin web. Necessite l'endpoint serveur
get_tailscale_key.php en place sur data.nebuleair.fr (a deployer en parallele cote
AirCarto, auth par deviceID + rate limit + audit log).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:58:19 +02:00
PaulVua
c593b152e8 v1.8.3: Affichage version firmware dans la sidebar
Ajoute la version firmware sous le nom du capteur dans la sidebar, visible
sur toutes les pages. Permet d'identifier d'un coup d'oeil le chemin de
mise a jour disponible (online git pull vs offline ZIP upload >= v1.4.0).

- launcher.php: get_config_sqlite injecte firmware_version (lu depuis VERSION)
- sidebar.html: ajout d'un <small> sous sideBar_sensorName (statique)
- topbar-logo.js: peuple .sideBar_firmwareVersion via le fetch existant +
  MutationObserver (aucun nouveau fetch -> respecte la limite 6 connexions)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 12:39:40 +02:00
PaulVua
54283b8e3a v1.8.2: Pre-flight check sudoers avec instructions de fix dans l'UI
Sur les anciens capteurs sans regle sudoers NOPASSWD pour
/var/www/nebuleair_pro_4g/*, l'update echouait avec un message
sudo cryptique.

Nouveau:
- preflight_sudo_check() en PHP teste 'sudo -n -l <script>' avant
  de lancer l'update (online ou offline)
- Si KO: la route retourne error_type=sudoers_missing avec un
  message clair et la sortie technique de sudo
- L'UI affiche une alerte warning structuree avec etapes numerotees,
  contenu du fichier /etc/sudoers.d/nebuleair pret a coller, et un
  bouton 'Copier le contenu' (presse-papier)
- Echec immediat (<1s) au lieu d'attendre le timeout du script

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:19:17 +02:00
PaulVua
11ac2b184a v1.8.1: Alignement upload offline sur le flow online (UX + self-heal)
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>
2026-05-12 18:00:10 +02:00
PaulVua
7338381c98 v1.8.0: Refonte UX update firmware (progress bar live + streaming logs)
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>
2026-05-12 17:53:44 +02:00
PaulVua
5d7aac38e1 v1.7.7: Fix 'Plus recente' = 'not connected' sur page database
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>
2026-05-12 17:47:27 +02:00
PaulVua
d34b029d48 v1.7.6: Tableau SystemD Services - ajout des 3 services manquants
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>
2026-05-12 17:42:58 +02:00
PaulVua
b87b054e2b v1.7.5: Fix update_firmware Step 3c (chmod +x setup_services.sh)
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>
2026-05-12 17:38:40 +02:00
PaulVua
7ad133f446 v1.7.4: Source de verite unique pour les services + update self-healing
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>
2026-05-12 17:33:54 +02:00
PaulVua
094926e30d v1.7.3: Revert du check SIM sur branche CSQ=99
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>
2026-05-12 11:36:50 +02:00
PaulVua
71211e281a v1.7.2: Detection SIM aussi dans la branche CSQ=99
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>
2026-05-12 11:32:43 +02:00
PaulVua
c004d32f0b v1.7.1: Detection SIM injoignable avant escalade hardware reboot
- Nouvelle fonction check_sim_status() (AT+CPIN? + AT+CCID)
- Branche d'echec PDP: diagnostic SIM avant reboot hardware
- Logs HTML tres visibles si SIM absente (bordure rouge, action claire)
- Notification WiFi dediee: 'SIM NOT DETECTED -> physical check required'
- Zero impact happy path: check uniquement quand PDP reset echoue

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 11:27:28 +02:00
PaulVua
2e5be6f542 v1.7.0: Tests Miotiq UDP — PDP, socket, ping aller-retour bidirectionnel
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 17:25:56 +02:00
PaulVua
8785f8cff4 v1.6.5: Page modem — tests Miotiq UDP (PDP, socket, ping aller-retour)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 16:21:02 +02:00
PaulVua
7045adc7a6 v1.6.4: Page modem — progression reset hardware + boutons LED status PCB
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 11:29:02 +02:00
PaulVua
c062263b24 v1.6.3: Logs SARA en temps reel — auto-refresh + python3 -u unbuffered
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 18:36:54 +02:00
PaulVua
9f76e3b2de v1.6.2: Simplification script boot SARA — config modem deleguee au script principal
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:15:24 +01:00
PaulVua
47d76be5df v1.6.1: NSRT MK4 deconnexion — noise_status en base + ERR_NOISE dans error_flags
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>
2026-03-19 11:42:10 +01:00
PaulVua
bd2e1f1eda v1.6.0: envoi npm_status dans payload UDP (byte 67)
- 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>
2026-03-18 13:24:26 +01:00
PaulVua
b3c019c27b v1.5.2: page capteurs NPM via get_data_modbus_v3.py --dry-run
- 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>
2026-03-18 13:10:56 +01:00
PaulVua
a9db7750b2 v1.5.1: envoi firmware version dans payload UDP (bytes 69-71)
- 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>
2026-03-18 11:44:24 +01:00
PaulVua
eb93ba49bd v1.5.0: error flags payload UDP + init bytes status a 0x00
- 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>
2026-03-18 10:17:37 +01:00
PaulVua
7b324f8ab8 v1.4.6 — Admin: RTC vs navigateur, blocage update hotspot, liens Gitea
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 19:34:25 +01:00
PaulVua
6e17f39a2c v1.4.5 — Page WiFi: oublier réseau + badge hotspot sidebar + refonte UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:28:46 +01:00
PaulVua
5bffec10a1 v1.4.3 — Payload UDP bruit cur_leq + cur_level, améliorations page database
- UDP bytes 22-23: noise_cur_leq, 24-25: noise_cur_level, 26-27: max_noise (réservé)
- Page database: validation dates obligatoire + bouton télécharger toute la table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 10:03:08 +01:00
paul_vua
d5b2e9c6c3 v1.4.2 — Fix bug AT+USOWR leak dans payload UDP Miotiq
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>
2026-03-14 22:53:59 +01:00
PaulVua
7ab06f3413 v1.4.1 — Migration capteur bruit I2C vers NSRT MK4 USB
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 16:04:17 +01:00