- Package HA : 8 scripts d'effets (calmes et « boum ») et une automatisation webhook local_only avec liste blanche stricte - Page web autonome (HTML/CSS/JS ES5) tenant sur un écran de lecteur MP3 - Mini APK Android (WebView verrouillée) compilé sans Gradle - Modèles + config.local.env non versionné : aucune valeur réelle (IP, ID du webhook, entité, prénom) dans le dépôt ; deploy.sh génère et déploie, android/build.sh injecte la configuration Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ma lumière — télécommande LED pour une chambre d'enfant
Une appli Android sur le lecteur MP3 d'un enfant pilote le ruban LED de sa chambre via Home Assistant. L'enfant n'a accès à rien d'autre dans HA.
[Lecteur MP3 Android] [Home Assistant sur le LAN]
appli « Ma lumière »
(WebView plein écran) --GET--> /local/led/index.html (page servie par HA)
--POST--> /api/webhook/<id> (local_only, POST)
│
▼
automatisation (liste blanche)
│
▼
light.<ruban> / script.led_* (8 effets)
Ce document décrit l'installation et récapitule les interventions réalisées le 10 octobre 2026.
1. Installation
Ce dépôt est public : il ne contient aucune valeur réelle. Les fichiers versionnés sont des modèles avec des marqueurs, remplacés au déploiement par les valeurs de config.local.env.
| Marqueur | Variable | Exemple |
|---|---|---|
__HA_IP__ / __HA_PORT__ |
adresse de HA sur le LAN | 192.168.1.10 / 8123 |
__WEBHOOK_ID__ |
ID du webhook, long et aléatoire | led-chambre-$(openssl rand -hex 16) |
__ENTITE__ |
entité du ruban | light.ruban_led |
__PRENOM__ |
prénom affiché dans la page | Camille |
| — | SSH_HOST : alias SSH vers HA |
homeassistant |
| — | APP_ID : identifiant Android de l'appli |
fr.exemple.lumiere |
Étapes :
- Copier
config.example.envenconfig.local.envet le remplir. - Une seule fois, dans
configuration.yamlde HA, ajouterpackages: !include_dir_named packagessoushomeassistant:, puis redémarrer HA. - Lancer
./deploy.sh. Il génèredist/, copie le package et la page sur HA via SSH, lanceha core check, puis recharge les scripts et les automatisations. Le rechargement utilise un jeton HA placé dans.env(HA_TOKEN=…), optionnel. - Compiler l'appli avec
android/build.sh(il faut un SDK Android avec build-tools 30.0.2 et la plateforme 25), puis l'installer avecadb install -r android/build/ma-lumiere.apk.
Fichiers jamais versionnés (voir .gitignore) : config.local.env, .env, dist/, android/build/.
2. Contexte technique
| Élément | Valeur |
|---|---|
| Home Assistant | HAOS 2026.6 sur Odroid N2, en HTTP sur le LAN, accès distant uniquement via VPN WireGuard |
| Ruban | RGB non adressable, driver Zigbee Iderwel via Zigbee2MQTT, mode couleur xy |
| Lecteur MP3 | Fanvace M36, Android 13, écran 640×1136 à 300 dpi (≈ 341 × 530 px utiles), WebView 108, navigateur bloqué par l'app lock |
Constats faits pendant les tests sur le ruban :
- Couleurs fixes, luminosité et
transition(fondus) fonctionnent bien. - Les effets natifs du driver (
colorloop,breathe…) ne sont pas fiables : ils ont été abandonnés au profit de scripts HA. - Le driver ne remonte pas l'effet en cours : l'attribut
effectvaut toujoursNonedans HA.
3. Interventions sur Home Assistant
3.1 Fichiers modifiés ou créés
| Fichier sur HA | Action |
|---|---|
/config/configuration.yaml |
1 ligne ajoutée sous homeassistant: : packages: !include_dir_named packages |
/config/packages/led_chambre.yaml |
créé : 8 scripts d'effets et l'automatisation webhook |
/config/www/led/ |
créé : index.html, manifest.json, icon.svg, icon-180/192/512.png |
Aucun autre fichier existant n'a été modifié. En particulier, scripts.yaml et automations.yaml n'ont pas été touchés.
3.2 Sauvegardes laissées sur HA
| Sauvegarde | Contenu |
|---|---|
/config/configuration.yaml.bak-led-20261010 |
configuration.yaml d'origine, avant l'ajout de packages: |
/config/led_chambre.yaml.bak-20261010-boum |
package avant l'ajout des effets disco/boum/tourbillon |
/config/led_chambre.yaml.bak-20261010-disco |
package avant la correction du bug disco |
Ces sauvegardes sont volontairement placées hors de packages/, pour que HA ne les charge pas.
3.3 Opérations effectuées
- Vérification de la configuration avec
ha core checkavant chaque mise en service. - Un redémarrage de HA, pour activer
packages:. - Ensuite, uniquement des rechargements à chaud (
script.reload,automation.reload), sans redémarrage.
3.4 Contenu du package led_chambre.yaml
Scripts d'effets, tous en mode: restart :
| Script | Comportement | Rythme Zigbee |
|---|---|---|
led_arc_en_ciel |
tour des teintes par pas de 30° | 1 commande / 3 s |
led_respiration |
garde la couleur, luminosité 10 % ↔ 100 % | 1 / 3 s |
led_coucher_de_soleil |
orange → rose → rouge → violet | 1 / 5 s |
led_ocean |
bleu → turquoise → cyan → bleu profond | 1 / 4 s |
led_veilleuse |
orange à 5 %, puis extinction en fondu au bout de 30 min | — |
led_disco |
saut de couleur vive chaque seconde | 1 / s |
led_boum |
flash d'une couleur à 100 %, puis fondu à 25 % | 1 / s |
led_tourbillon |
arc-en-ciel rapide, pas de 45° | 1 / s |
Il n'y a pas de stroboscope : le réseau Zigbee ne le permet pas, et il présente un risque photosensible.
Automatisation led_chambre_webhook :
-
Webhook avec
local_only: true,allowed_methods: [POST]et un ID aléatoire long. -
mode: restart: si plusieurs commandes arrivent très vite, seule la dernière compte. -
Contrat du corps JSON :
actionchamp effet off— arrête tous les effets et éteint le ruban (fondu 1 s) couleurteinte0–359arrête les effets et applique une couleur fixe luminositevaleur5–100change la luminosité sans couper l'effet en cours effetnomarrête l'effet en cours et lance script.led_<nom>s'il est dans la liste blanche -
Liste blanche stricte : le JSON ne sert jamais à construire un entity_id. Les valeurs sont bornées et ont des valeurs par défaut, et toute autre requête est ignorée.
-
La luminosité revient automatiquement à 100 % quand le ruban était éteint, ou quand on sort de la veilleuse, de la respiration ou de Boum.
4. Interventions sur le lecteur MP3
- Installation via ADB de l'appli « Ma lumière », aujourd'hui en version 1.1.
- Aucun autre réglage n'a été modifié sur l'appareil.
- Le débogage USB a été activé pour l'installation.
Ce que fait l'appli : c'est un wrapper WebView de 37 Ko qui affiche en plein écran la page servie par HA.
- Elle n'autorise la navigation que vers
http://<HA>/local/led/, et bloque toute requête vers une autre adresse. - Le HTTP non chiffré n'est autorisé que vers l'IP de HA.
- Si HA ne répond pas, elle affiche « La lumière ne répond pas » avec un bouton Réessayer.
- Le cache est désactivé, et la page est rechargée à chaque retour dans l'appli (ajouté en v1.1). Une modification de la page sur HA apparaît donc sans réinstaller l'appli.
5. Fichiers du dépôt
├── CLAUDE.md consignes du projet
├── README.md ce document
├── config.example.env modèle de configuration (à copier en config.local.env)
├── deploy.sh génère dist/ depuis les modèles et déploie sur HA
├── packages/led_chambre.yaml modèle → /config/packages/led_chambre.yaml
├── www/led/ modèles → /config/www/led/
│ ├── index.html la page (HTML/CSS/JS ES5 en un seul fichier)
│ ├── manifest.json
│ └── icon.svg, icon-*.png
└── android/ sources de l'APK
├── build.sh compilation sans Gradle → build/ma-lumiere.apk
├── AndroidManifest.xml
├── res/ icônes, thème, network_security_config (modèle)
└── src/app/lumiere/MainActivity.java
La page est pensée pour tenir sur un seul écran du lecteur :
- en haut, Veilleuse et Éteindre ;
- 9 pastilles de couleur ;
- 4 niveaux de luminosité ;
- 4 animations calmes ;
- 3 animations « boum » au style néon.
Elle n'affiche aucun état du ruban, puisque le webhook ne renvoie rien. Un appui réussi fait apparaître un halo blanc ; une erreur fait trembler le bouton et affiche un message rouge.
6. Tests réalisés
- Ruban, en direct : couleurs, fondus, luminosité, puis effets natifs, qui se sont révélés peu fiables.
- Webhook avec curl :
- toutes les actions et les 8 effets fonctionnent, et un seul script tourne à la fois ;
- les entrées non valides sont ignorées sans erreur : nom hors liste blanche (
../light.autre), action inconnue, corps non JSON ; - les valeurs sont bornées (teinte 999 → 359, luminosité 1 → 5 %) ;
- une requête GET est refusée (405) ;
- les logs HA sont propres.
- De bout en bout sur le lecteur : des taps simulés via ADB (couleur, arc-en-ciel, veilleuse, éteindre) ont été vérifiés dans l'état HA.
- Modèles : les fichiers générés par
deploy.sh --render-onlysont identiques aux fichiers en service, hors commentaires. L'APK généré contient la bonne adresse et le bon identifiant.
Bug corrigé : led_disco plantait au bout d'environ 10 s, parce qu'une teinte 0 tirée d'une palette en variables arrivait vide dans hs_color. Le rouge vaut maintenant 360 dans les palettes de Disco et de Boum.
7. Maintenance
Tester le webhook (avec les valeurs de config.local.env) :
curl -X POST -H "Content-Type: application/json" \
-d '{"action":"effet","nom":"arc_en_ciel"}' \
http://<HA_IP>:<HA_PORT>/api/webhook/<WEBHOOK_ID>
Modifier la page ou un effet :
- Modifier le modèle (
www/led/index.htmloupackages/led_chambre.yaml). - Lancer
./deploy.sh. - Rouvrir l'appli sur le lecteur. Pas de réinstallation.
Ajouter un effet :
- Ajouter le script
led_<nom>dans le package. - Ajouter
<nom>danseffetset danstous_les_effetsde l'automatisation. - Ajouter une tuile dans la page.
- Lancer
./deploy.sh.
Recompiler l'appli, par exemple si l'IP de HA change :
- Mettre à jour
config.local.env. - Lancer
android/build.sh, puisadb install -r android/build/ma-lumiere.apk.
Il faut garder la même clé de signature, ~/.android/debug.keystore. Sinon Android refusera la mise à jour et il faudra désinstaller l'appli d'abord.
Tout retirer :
- Supprimer
/config/packages/led_chambre.yamlet/config/www/led/. - Retirer la ligne
packages:deconfiguration.yaml, ou restaurer la sauvegarde. - Lancer
ha core check, puis redémarrer HA. - Désinstaller l'appli :
adb uninstall <APP_ID>.
8. Reste à faire
- Autoriser « Ma lumière » dans l'app lock du lecteur.
- Réserver l'IP de HA sur la box, puisqu'elle est compilée dans l'appli.
- Supprimer le jeton HA de développement (profil HA → Sécurité) et le fichier
.envquand ils ne sont plus utiles. L'appli n'en a pas besoin. - Éventuellement, désactiver le débogage USB sur le lecteur.
- Éventuellement, supprimer les sauvegardes
*.bak*dans/configune fois que tout est validé.
ℹ️ Le dossier /local/ de HA est accessible sans authentification depuis le LAN. C'est voulu : la page ne contient aucun secret, et le webhook n'accepte que des commandes en liste blanche, uniquement depuis le réseau local.