- 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>
6.7 KiB
6.7 KiB
Télécommande LED chambre — Home Assistant
Objectif
Permettre à ma fille de piloter le ruban LED de sa chambre depuis son lecteur MP3 Android, via une page web ultra simple, sans lui donner accès au reste de Home Assistant.
Matériel
- Ruban LED RGB non adressable : toute la longueur affiche la même couleur. Aucun effet de « vague » spatiale n'est possible, seulement des effets globaux (cycles, fondus, respiration).
- Driver Zigbee Iderwel (PWM), intégré à Home Assistant.
- Dépôt public : aucune valeur réelle (IP, ID du webhook, entité, prénom, identifiant Android) dans les fichiers versionnés. Elles sont dans
config.local.env(non versionné, modèle :config.example.env). Les fichiers versionnés sont des modèles avec des marqueurs__HA_IP__,__HA_PORT__,__WEBHOOK_ID__,__ENTITE__,__PRENOM__;deploy.shgénèredist/et déploie,android/build.shgénèreConfig.javaet la config réseau. Ne jamais réintroduire de valeur réelle dans un fichier versionné. - entity_id du ruban :
ENTITEdansconfig.local.env(mode couleurxy;hs_coloraccepté, converti par HA) - intégration Zigbee : Zigbee2MQTT
- HA : HAOS sur Odroid N2, adresse
HA_IP:HA_PORT; accès SSH via l'aliasSSH_HOST(root : lecture seule par défaut). Jeton HA de dev dans.env(non versionné). - Effets natifs du driver (
colorloop,breathe…) peu fiables : testés, ne pas les utiliser. Les effets passent par des scripts HA. Couleurs fixes, luminosité ettransitionfonctionnent bien. - Le driver ne remonte pas l'attribut
effect(toujoursNonedans HA). - MP3 : Fanvace M36, Android 13, écran 640×1136 à 300 dpi (≈ 341 px CSS de large), WebView 108. Branché en ADB.
- Pas de navigateur accessible (app lock) : la page est affichée par un mini APK WebView (
android/, code dans le paquetapp.lumiere, identifiant installé =APP_IDappliqué via--rename-manifest-package), qui n'autorise quehttp://HA_IP:HA_PORT/local/led/. Recompiler avecandroid/build.sh(clé de debug~/.android/debug.keystore: garder la même pour les mises à jour), installer avecadb install -r android/build/ma-lumiere.apk. Si l'IP de HA change : modifierconfig.local.env, recompiler et réinstaller.
Architecture
[Page HTML statique] --POST JSON--> [Webhook HA (local_only)] --> [Automatisation] --> light.* / scripts d'effets
/config/www/led/ /api/webhook/<id>
servie sur /local/led/
- Scripts d'effets (
script.led_<nom>) : boucles infinies (repeat: while true) delight.turn_onavectransition, enmode: restart. - Automatisation webhook : point d'entrée unique, qui ne peut agir que sur le ruban et sur une liste fermée de scripts.
- Page web : gros boutons, aucune authentification, à ajouter sur l'écran d'accueil du MP3.
Contrat du webhook (corps JSON)
| action | champs | effet |
|---|---|---|
off |
— | arrête tous les effets et éteint le ruban (transition 1 s) |
couleur |
teinte (0–359) |
arrête les effets, couleur fixe hs_color: [teinte, 100] |
luminosite |
valeur (5–100) |
brightness_pct, valeur bornée côté HA |
effet |
nom (ex. arc_en_ciel) |
arrête l'effet en cours et lance script.led_<nom> s'il figure dans la liste blanche |
Contraintes et règles
- Sécurité
- Webhook en
local_only: trueetallowed_methods: [POST], avec un ID aléatoire long. - Liste blanche stricte des scripts dans l'automatisation ; ne jamais construire un entity_id arbitraire à partir du JSON.
- Toutes les valeurs numériques sont bornées et ont un
defaultcôté HA. - Aucun jeton HA dans la page.
- Webhook en
- Zigbee : ne pas inonder le réseau. Garder au moins 1 s entre deux commandes dans les scripts (idéalement 2–3 s avec
transitionégale au delay). Les fondus sont lissés par le driver. - Effets : lancer un nouvel effet ou une couleur fixe arrête toujours l'effet en cours.
- Pas de retour d'état : le webhook ne renvoie rien. La page ne connaît pas l'état du ruban et l'UI ne doit pas faire semblant de le connaître (pas de toggle on/off avec un état affiché).
- Page web
- Un seul fichier HTML autonome (CSS et JS inline), sans dépendance externe ni CDN.
- JS compatible avec un vieux navigateur Android : ES5 de préférence, ou au minimum sans syntaxe récente (
?.,??, etc.). Utiliserfetchs'il est disponible, sinonXMLHttpRequest. - Pensée pour un petit écran tactile en portrait : grandes cibles tactiles, peu de texte, très visuelle (pastilles de couleur, icônes d'effets), retour visuel immédiat au tap.
- Balises
<meta name="viewport">etapple-mobile-web-app/manifestminimal pour que le raccourci sur l'écran d'accueil ressemble à une appli. - Interface en français, pour une enfant.
Effets (en place dans packages/led_chambre.yaml)
- Calmes (≥ 2 s entre commandes) :
arc_en_ciel(pas de 30°, 3 s),respiration(10 ↔ 100 %, 3 s),coucher_de_soleil(5 s),ocean(4 s),veilleuse(orange 5 %, extinction en fondu après 30 min). - Boum (1 commande/s, le minimum) :
disco(sauts de couleur),boum(flash 100 % puis fondu à 25 %),tourbillon(arc-en-ciel rapide). Pas de stroboscope. - Le webhook remet 100 % quand on sort d'un effet qui baisse la luminosité (veilleuse, respiration, boum) ou quand le ruban est éteint.
- Piège : dans une palette en
variables, une teinte0arrive vide danshs_coloret fait planter le script → utiliser360pour le rouge. - Ajouter un effet = script
led_<nom>+ entrée danseffetsettous_les_effetsde l'automatisation + tuile dans la page ; déployer avec./deploy.sh(copie,ha core check,script.reload/automation.reload, pas de redémarrage).
Livrables attendus
scripts.yaml: les scripts d'effetsautomations.yaml: l'automatisation webhook (ou un packagepackages/led_chambre.yamlregroupant les deux)www/led/index.html: la page- Procédure de test :
curl -X POST -H "Content-Type: application/json" -d '{"action":"effet","nom":"arc_en_ciel"}' http://<ha>:8123/api/webhook/<id>- tester chaque action avec curl avant de toucher à la page
- APK « Ma lumière » (
android/) installé via ADB, à autoriser dans l'app lock
Ordre de travail
- Scripts d'effets, testés depuis Outils de développement → Actions
- Automatisation webhook, testée avec curl
- Page web, testée d'abord sur desktop en vue mobile, puis sur le MP3