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>
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>
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>
- 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>
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>
Les capteurs deja deployes auront automatiquement la bonne config
Apache/PHP lors de la prochaine mise a jour (git pull ou upload zip).
Verifie si AllowOverride All est actif et si upload_max < 50M avant
de modifier. Pas de conflit avec installation_part1.sh (idempotent).
Co-Authored-By: Claude Opus 4.6 (1M context) <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>
Implements power saving optimizations to extend battery life on solar-powered remote air quality sensors:
- WiFi Power Saving: Disable WiFi 10 minutes after boot to save ~100-200mA
- Configurable via web UI checkbox in admin panel
- WiFi automatically re-enables after reboot for 10-minute configuration window
- Systemd timer (nebuleair-wifi-powersave.timer) manages automatic disable
- New wifi/power_save.py script checks database config and disables WiFi via nmcli
- HDMI Disable: Added hdmi_blanking=2 to boot config to save ~20-30mA
- Automatically configured during installation
- Database: Added wifi_power_saving boolean config (default: disabled)
- Uses INSERT OR IGNORE for safe updates to existing installations
- UI: Added checkbox control in admin.html for WiFi power saving
- Includes helpful description of power savings and behavior
- Services: Updated setup_services.sh and update_firmware.sh to manage new timer
Total power savings: ~120-230mA when WiFi power saving enabled
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>