Files
bachirandClaude Opus 5.5 e4bd58afa7 Télécommande LED pour chambre d'enfant via Home Assistant
- 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>
2026-10-10 21:29:51 +02:00

6.7 KiB
Raw Permalink Blame History

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.sh génère dist/ et déploie, android/build.sh génère Config.java et la config réseau. Ne jamais réintroduire de valeur réelle dans un fichier versionné.
  • entity_id du ruban : ENTITE dans config.local.env (mode couleur xy ; hs_color accepté, converti par HA)
  • intégration Zigbee : Zigbee2MQTT
  • HA : HAOS sur Odroid N2, adresse HA_IP:HA_PORT ; accès SSH via l'alias SSH_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é et transition fonctionnent bien.
  • Le driver ne remonte pas l'attribut effect (toujours None dans 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 paquet app.lumiere, identifiant installé = APP_ID appliqué via --rename-manifest-package), qui n'autorise que http://HA_IP:HA_PORT/local/led/. Recompiler avec android/build.sh (clé de debug ~/.android/debug.keystore : garder la même pour les mises à jour), installer avec adb install -r android/build/ma-lumiere.apk. Si l'IP de HA change : modifier config.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/
  1. Scripts d'effets (script.led_<nom>) : boucles infinies (repeat: while true) de light.turn_on avec transition, en mode: restart.
  2. Automatisation webhook : point d'entrée unique, qui ne peut agir que sur le ruban et sur une liste fermée de scripts.
  3. 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: true et allowed_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 default côté HA.
    • Aucun jeton HA dans la page.
  • 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.). Utiliser fetch s'il est disponible, sinon XMLHttpRequest.
    • 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"> et apple-mobile-web-app / manifest minimal 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 teinte 0 arrive vide dans hs_color et fait planter le script → utiliser 360 pour le rouge.
  • Ajouter un effet = script led_<nom> + entrée dans effets et tous_les_effets de 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

  1. scripts.yaml : les scripts d'effets
  2. automations.yaml : l'automatisation webhook (ou un package packages/led_chambre.yaml regroupant les deux)
  3. www/led/index.html : la page
  4. 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
  5. APK « Ma lumière » (android/) installé via ADB, à autoriser dans l'app lock

Ordre de travail

  1. Scripts d'effets, testés depuis Outils de développement → Actions
  2. Automatisation webhook, testée avec curl
  3. Page web, testée d'abord sur desktop en vue mobile, puis sur le MP3