Concepts du DSL Android

Voici une présentation des concepts fondamentaux du DSL d'automatisation sur Android.

Composants d'automatisation

Une automatisation se compose des éléments de base suivants, généralement évalués dans cet ordre :

  1. Déclencheur : définit les conditions initiales qui activent l'automatisation, comme une modification d'un trait. Une automatisation doit avoir un déclencheur.
  2. Condition : toute contrainte supplémentaire à évaluer après l'activation d'une automatisation. L'expression d'une condition doit renvoyer la valeur true pour que les actions d'une automatisation puissent se poursuivre.
  3. Action : commandes ou mises à jour d'état effectuées lorsque toutes les conditions sont remplies.

Par exemple, vous avez peut-être une automatisation qui baisse la luminosité des lumières d'une pièce lorsque le téléviseur de cette pièce est allumé entre le coucher et le lever du soleil. Dans cet exemple :

  1. Démarrage : le téléviseur a été allumé, ce qui correspond à un changement d'état d'un trait TV.
  2. Condition : l'heure actuelle de la maison où se trouve le téléviseur est évaluée.
  3. Action : les lumières de la pièce où se trouve le téléviseur sont tamisées.

L'automatisation est activée lorsque le téléviseur de la pièce est allumé, mais elle ne s'exécute que si la condition "l'heure est comprise entre le coucher et le lever du soleil" est remplie.

En plus de la structure de base, les automatisations des API Home contiennent également des métadonnées, telles que name et description, qui peuvent être utilisées pour les identifier pour les développeurs et les utilisateurs.

Nœuds

Dans les API Home, la structure logique d'une automatisation se compose de nœuds. Les nœuds sont des unités abstraites et réutilisables qui représentent des comportements d'entité ou des flux d'exécution. Chaque nœud peut avoir des variables d'entrée et des variables de sortie qui peuvent être utilisées par d'autres nœuds.

Table : Types de nœuds d'automatisation
Nœud Type de nœud Implémentation Kotlin Description
Starter Comportement StarterNodeDsl Démarre une automatisation lorsque l'état d'un trait (n'importe quel attribut) change.
StateReader Comportement StateReaderNodeDsl Lit un attribut de caractéristique et vous permet de capturer sa valeur pour l'utiliser dans des nœuds de condition.
Action Comportement ActionNodeDsl Appelle des commandes de traits.
Séquentielle Flux d'exécution SequentialFlow Exécute les nœuds d'action imbriqués de manière séquentielle. Il s'agit du comportement d'exécution par défaut.
Parallèle Flux d'exécution ParallelFlow Exécute les nœuds d'action imbriqués en parallèle.
Condition Flux d'exécution ConditionNodeDsl Modifiez conditionnellement le flux d'exécution en fonction des évaluations d'expressions logiques. Les conditions peuvent être associées à un déclencheur (conditions spécifiques au déclencheur) ou être globales (s'appliquer à tous les déclencheurs).
Sélectionner Flux d'exécution SelectFlow Permet à plusieurs déclencheurs d'activer une automatisation.
Expression Valeur Expression Il peut s'agir de la valeur d'un attribut de caractéristique, d'une constante ou d'une valeur littérale, et doit correspondre à une liste, un nombre, une valeur booléenne ou une chaîne.

Nœuds de comportement

Les nœuds tels que les déclencheurs et les actions sont des nœuds comportementaux. Les déclencheurs activent une automatisation en fonction des changements d'attributs de l'appareil. Les actions permettent d'envoyer des commandes aux appareils ou de mettre à jour leurs attributs.

Les nœuds de comportement sont généralement liés aux caractéristiques de l'appareil et à l'état des caractéristiques de sortie à utiliser comme entrée dans d'autres nœuds.

Nœuds de flux d'exécution

Certains nœuds représentent des flux d'exécution, tels que séquentiels et parallèles. Chacun de ces nœuds contient les nœuds de comportement qui définissent l'automatisation.

Par exemple, un flux séquentiel peut contenir des nœuds qui s'exécutent dans l'ordre séquentiel. Il s'agit généralement d'un déclencheur, d'une condition et d'une action.

Flux d'exécution séquentiels
Figure 1 : Flux d'automatisation séquentiel

Un flux parallèle peut comporter plusieurs nœuds d'action s'exécutant en même temps, par exemple pour allumer plusieurs lumières simultanément. Les nœuds suivant un flux parallèle ne s'exécutent que lorsque toutes les branches du flux parallèle sont terminées.

Flux d'exécution parallèle
Figure 2 : Flux d'automatisation parallèle

Un autre type de flux d'exécution est le flux conditionnel, qui peut modifier le flux d'exécution en fonction de l'évaluation d'une expression.

Par exemple, vous avez peut-être une automatisation qui effectue une action en fonction de l'heure de la journée. Un nœud de condition vérifie l'heure de la journée, puis suit le chemin d'exécution approprié en fonction de cette évaluation.

Flux de condition
Figure 3 : Flux de conditions

Un flux de sélection est utile lorsque vous souhaitez disposer de plusieurs déclencheurs pour activer votre automatisation. Lorsque vous incluez deux déclencheurs ou plus dans un flux select, n'importe lequel d'entre eux peut activer l'automatisation.

Par exemple, vous pouvez écrire une automatisation qui baisse les stores au coucher du soleil, si la température dépasse un certain seuil ou si la luminosité dépasse un seuil. Trois starters distincts gèrent chacun de ces scénarios, et les trois seraient enveloppés dans un flux select.

Sélectionner un flux
Figure 4 : Flux de sélection

Flux imbriqués

Dans les automatisations complexes, les nœuds de flux d'exécution peuvent également être imbriqués. Par exemple, vous pouvez avoir un flux séquentiel qui exécute un flux parallèle.

Flux d'exécution imbriqués
Figure 5 : Flux d'exécution imbriqués

Les nœuds DSL peuvent être imbriqués et combinés de différentes manières pour répondre à vos besoins spécifiques, en fonction des contraintes décrites dans le tableau suivant. La colonne "Builder" contient des liens vers la documentation du compilateur Kotlin avec sûreté de typage, qui détaille ce qui est autorisé pour chaque type de nœud.

Tableau : Combinaisons possibles de nœuds
Nœud Peut contenir le type de nœud et les données suivants Doit appartenir à l'un des types de nœuds suivants
Starter Expression Sélectionner, Séquentielle
ManualStarter Sélectionner, Séquentielle
StateReader Expression (généralement constituée d'une valeur d'attribut de trait) Action, Condition
Action Commande, Entité, Expression Parallèle, Sélection, Séquentiel
Séquentielle Parallèle, Sélection, Séquentiel
Parallèle Action Séquentielle
Condition Expression Parallèle, Séquentiel
Sélectionner Condition, Sequential, Starter, ManualStarter Séquentiel et doit être le premier nœud du flux

DSL d'automatisation

Dans les API Home, les automatisations sont définies à l'aide du DSL (langage spécifique au domaine) Automation. Le DSL d'automatisation est implémenté en tant que DSL Kotlin (langage spécifique au domaine), à l'aide de compilateurs Kotlin avec sûreté de typage. Il est spécifiquement conçu pour définir des modèles d'automatisation.

Lorsqu'une automatisation est compilée, les builders Kotlin à sécurité typée génèrent des classes de données Kotlin qui sont ensuite sérialisées en JSON de tampon de protocole, lequel est utilisé pour effectuer des appels aux services d'automatisation de Google.

Le DSL d'automatisation simplifie et rationalise le processus de création d'automatisations. Il utilise nativement le même modèle de données de caractéristiques standards Matter et de caractéristiques smart home figurant dans l'API Device.

Le DSL d'automatisation définit également la logique d'une automatisation en termes de types d'appareils abstraits, par opposition aux instances d'appareils spécifiques situées dans la maison d'un utilisateur. Il permet au développeur de fournir des paramètres d'entrée qui peuvent être utilisés au moment de l'exécution pour spécifier des instances d'appareil réelles, ainsi que d'autres valeurs de paramètres importantes.

La syntaxe DSL est semblable à celle de Kotlin et est tout aussi sûre en termes de typage. Toutefois, une automatisation écrite dans le DSL d'automatisation est plus simple et plus concise que la même automatisation écrite en Kotlin pur.

Exemple

Voici un exemple d'automatisation qui allume un appareil, écrit à l'aide du DSL d'automatisation :

val automation = automation {
  name = "MyFirstAutomation"
  description = "If light1 is on, turn on light2."
  isActive = true
  sequential {
    val onOffTrait = starter<_>(device1, OnOffLightDevice, OnOff)
    condition() { expression = onOffTrait.onOff equals true }
    action(device2, OnOffLightDevice) { command(OnOff.on()) }
  }
}

Cette automatisation est très basique : lorsque device1, une lumière, s'allume (l'attribut onOff passe à true), la commande on() est envoyée pour allumer device2.

L'automatisation utilise un nœud sequential, ce qui indique que ses nœuds s'exécuteront dans l'ordre séquentiel.

Le nœud sequential contient des nœuds de comportement tels que starter, condition et action. La sortie du nœud starter est attribuée à une variable à utiliser dans le nœud condition.