Développeurs
Cartes d’extension
API v1 des cartes d’extension des tableaux de bord.
Pour les besoins qui dépassent les cartes natives et la carte composée, un administrateur peut installer des cartes d'extension écrites en JavaScript.
Isolation
- Chaque carte s'exécute dans un iframe isolé (
sandbox="allow-scripts", origine opaque). Elle n'a ni cookie, ni session, ni accès à l'API de My Habita ou à la page parente. - Elle ne voit et ne commande que les entités qui lui ont été confiées dans la configuration de la carte (« Entités confiées à l'extension »).
- Ses commandes passent par My Habita, avec les mêmes contrôles qu'une commande depuis l'interface (validation, droits, PIN pour les actions sensibles, traces).
- Une extension qui plante affiche son erreur dans sa carte, sans affecter le tableau de bord.
- Les extensions restent du code exécuté dans le navigateur de vos utilisateurs : n'installez que des extensions dont vous avez lu le code.
Installation
sudo cp -r /opt/myhabita/examples/extensions/jauge /var/lib/myhabita-www/extensions/
Dans un tableau de bord : Modifier → + Carte → Extension. Choisissez ensuite l'extension, la carte, les entités confiées et la configuration JSON.
Structure d'une extension
/var/lib/myhabita-www/extensions/<identifiant>/
├── manifest.json
└── <carte>.js (un fichier par carte déclarée)
manifest.json :
{
"name": "Jauge circulaire",
"version": "1.0.0",
"apiVersion": 1,
"cards": [{ "id": "jauge", "name": "Jauge circulaire" }]
}
Règles :
- L'identifiant du dossier et celui de chaque carte s'écrivent en
a-z,0-9,-ou_, sur 40 caractères au plus. - Une extension dont
apiVersiondiffère de la version prise en charge est signalée comme incompatible.
API exposée dans la carte
MyHabita.defineCard('jauge', {
mount(root, api) { /* construire le contenu dans root */ },
update(api) { /* facultatif : appelé à chaque changement d'état d'une entité confiée */ },
});
| Élément | Description |
|---|---|
api.apiVersion |
1 |
api.config |
Configuration JSON de la carte (inclut entities) |
api.theme |
Variables CSS du thème (--accent, --text, --surface… aussi appliquées au document) |
api.entities() |
Identifiants des entités confiées |
api.state(id) |
État : { values, availability, pending, lastReported, … } (voir EntityState) |
api.entity(id) |
Description : { domain, primary, capabilities[], … } |
api.name(id) |
Nom affiché |
api.onState(cb) |
cb(entityId, state) à chaque changement |
api.command(id, set) |
Promesse résolue avec [{ id, status }] ; rejetée si la commande est refusée. La confirmation arrive ensuite par onState, quand l'équipement la rapporte. |
Protocole (pour information)
Échanges postMessage entre la page et l'iframe, préfixés mh: 1 :
- de la page vers l'iframe :
init,state,result; - de l'iframe vers la page :
ready,command,error.
L'environnement d'exécution est dans packages/web/public/extension-frame.html ; l'hôte, dans packages/web/src/cards/extension.tsx.
Exemple
examples/extensions/jauge/ affiche la première entité confiée sous forme de jauge ; un appui bascule une lumière ou une prise. Il est vérifié par le test de bout en bout « carte d'extension isolée ».
Évolution
Toute modification incompatible de cette API créera une version 2. La version 1 restera prise en charge au moins pendant une version majeure de My Habita.