Guide du DSL Android

Consultez le guide suivant pour comprendre comment utiliser différents nœuds Automation DSL afin de créer une automatisation.

L'ensemble d'Automation DSL est placé dans un seul nœud automation. Le nœud automation forme la limite entre le contexte de langage Kotlin externe et le contexte DSL intégré.

Flux séquentiel

Le flux séquentiel est le type de flux d'automatisation par défaut.

Exemple de DSL séquentielle

Voici un modèle Automation DSL très basique qui utilise un flux séquentiel composé d'un déclencheur, d'une condition et d'une action :


import com.google.home.automation.action
import com.google.home.automation.automation
import com.google.home.automation.condition
import com.google.home.automation.sequential
import com.google.home.automation.starter

...

automation {
  sequential {
    starter<_>(...)
    condition {...}
    action {...}
  }
}

Vous pouvez l'affiner en ajoutant des nœuds supplémentaires.

Starter

Les nœuds de déclencheur définissent les circonstances initiales qui activent une automatisation. Par exemple, un changement d'état ou de valeur. Une automatisation doit comporter au moins un déclencheur, sinon la validation échouera. Pour ajouter plusieurs déclencheurs à une automatisation, vous devez utiliser un nœud select.

Déclencheur basé sur un attribut de caractéristique

Lorsque vous déclarez un nœud de déclencheur basé sur un attribut de caractéristique, spécifiez les éléments suivants :

  • l'appareil
  • le type d'appareil auquel appartient la caractéristique
  • la caractéristique
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)

Le paramètre de type d'appareil est obligatoire, car il vous permet de spécifier le type d'appareil auquel l'automatisation s'adresse dans un appareil. Par exemple, un appareil peut être composé d'un FanDevice et d'un HeatingCoolingUnitDevice, qui contiennent tous deux la OnOff caractéristique. En spécifiant le type d'appareil, il n'y a aucune ambiguïté quant à la partie de l'appareil qui déclenche l'automatisation.

Déclencheur basé sur un événement

Lorsque vous déclarez un nœud de déclencheur basé sur un événement, spécifiez les éléments suivants :

  • l'appareil
  • le type d'appareil auquel appartient la caractéristique
  • l'événement
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)

Déclencheur basé sur une structure et un événement, avec des paramètres

Certains événements peuvent avoir des paramètres. Vous devez donc les inclure dans le déclencheur.

Par exemple, ce déclencheur utilise le Time de la caractéristique ScheduledTimeEvent pour activer l'automatisation à 7h00 :

val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
  parameter(Time.ScheduledTimeEvent.clockTime(
    LocalTime.of(7, 0, 0, 0)))
}

Déclencheur basé sur la météo

Vous pouvez spécifier les conditions météorologiques actuelles ou prévues dans un déclencheur à l'aide de la caractéristique Weather :

val weatherState = starter<_>(structure, trait = Weather)

Consultez Fermer les stores s'il risque de pleuvoir sur la page Exemples d'automatisation.

Déclencheur manuel

Un déclencheur manuel est un type spécial de déclencheur qui permet à l'utilisateur d'exécuter manuellement l'automatisation.

Lorsque vous déclarez un déclencheur manuel :

  • Ne spécifiez pas de caractéristique ni de type d'appareil.
  • Fournissez un élément d'interface utilisateur qui appelle Automation.execute().

Lorsque vous placez un déclencheur manuel dans un flux select avec un autre déclencheur, le déclencheur manuel remplace l'autre déclencheur :

select {
  manualStarter()
  starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}

Notez que tous les nœuds condition qui suivent un déclencheur manuel seront évalués et pourront bloquer l'exécution de l'automatisation, en fonction de l'expression condition.

Séparer un déclencheur manuel d&#39;un déclencheur conditionnel

Pour structurer votre automatisation de sorte que les nœuds condition ne bloquent pas une automatisation activée avec un déclencheur manuel, placez l'autre déclencheur dans un flux séquentiel distinct avec sa condition :

automation_graph {
  sequential {
    select {
      sequential {
        starter<_>(...)
        condition {...}
      }
      sequential {
        manualStarter()
      }
    }
    action {...}
  }
}

Faire référence à la valeur d'un attribut

Pour utiliser la valeur d'un attribut dans une expression, utilisez la syntaxe suivante.

Avec un stateReader :

val time = stateReader<_>(structure, Structure, Time)
val currTime = time.currentTime

Avec un starter :

val starterNode = starter<_>(device1, LaundryWasherDevice, OnOff)
condition() {
  expression = starterNode.onOff equals true
}

Nœuds et expressions de condition

Un nœud de condition représente un point de décision qui détermine si l'automatisation se poursuit ou non. Une automatisation peut comporter plusieurs nœuds condition. Si l'expression d'un nœud condition renvoie la valeur false, l'exécution de l'ensemble de l'automatisation s'arrête.

Dans un nœud condition, vous pouvez combiner plusieurs critères de condition à l'aide de différents opérateurs, à condition que l'expression renvoie une seule valeur booléenne. Si la valeur résultante est true, la condition est remplie et l'automatisation poursuit l'exécution du nœud suivant. Si la valeur est false, l'automatisation s'arrête à ce stade.

Les expressions sont formées de la même manière que les expressions en Kotlin et peuvent contenir des valeurs primitives telles que des nombres, des caractères, des chaînes et des valeurs booléennes, ainsi que des valeurs d'énumération. Le regroupement des sous-expressions entre parenthèses vous permet de contrôler l'ordre dans lequel elles sont évaluées.

Voici un exemple de condition qui combine plusieurs sous-expressions en une seule expression :

condition() {
  val expr1 = starterNode.lockState equals DlLockState.Unlocked
  val expr2 = stateReaderNode.lockState equals true

  val expr3 = occupancySensingDevice.occupied notEquals 0
  val expr4 = timeStateReaderNode
    .currentTime
    .between(
      timeStateReaderNode.sunsetTime,
      timeStateReaderNode.sunriseTime)
  expression = (expr1 and expr2) or (expr3 and expr4)
}

Vous pouvez faire référence à la valeur d'une caractéristique à laquelle vous accédez via un déclencheur :

val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }

stateReader

L'autre façon de faire référence aux valeurs d'attribut de caractéristique dans un nœud condition consiste à utiliser un nœud stateReader.

Pour ce faire, capturez d'abord la valeur de l'attribut de caractéristique dans un nœud stateReader. Un stateReader prend la structure et la caractéristique comme arguments :

import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)

Faites ensuite référence au stateReader dans le nœud condition :

condition() {
  expression =
    filterMonitoringState.changeIndication
      .equals(ChangeIndicationEnum.Warning)
}

À l'aide d'opérateurs de comparaison et logiques, plusieurs stateReaders peuvent être utilisés dans un nœud condition :

val armState = stateReader<_>(doorLock, DoorLockDevice, ArmDisarm )
val doorLockState = stateReader<_>(doorLock, DoorLockDevice, DoorLock)
condition() {
  expression =
    (armState.armState equals true)
    and
    (doorLockState.lockState equals true)
}

Durée de la condition

En plus d'une expression booléenne dans une condition, vous pouvez spécifier une période pendant laquelle l'expression doit être vraie pour exécuter l'automatisation. Par exemple, vous pouvez définir une condition qui ne se déclenche que si une lumière est allumée depuis dix minutes.

  condition {
    expression(lightStateReader.onOff == true)
    forDuration(Duration.ofMinutes(10))
  }

La durée peut aller de 5 secondes à 24 heures.

Nœuds d'action

Le nœud d'action est l'endroit où l'automatisation a lieu. Dans cet exemple, l'action appelle la AssistantBroadcast caractéristique's broadcast() commande :

action(device, SpeakerDevice) {
  command(AssistantBroadcast.broadcast("Intruder detected!"))
}

Instructions d'importation

Lorsque vous développez des automatisations, il n'est pas toujours évident d'importer différents éléments des API Home dans votre code.

Les attributs de caractéristique sont importés à partir de l'objet Companion de la caractéristique :

import com.google.home.matter.standard.OnOff.Companion.onOff

Les structures de données définies par une caractéristique sont importées à partir de la classe de caractéristique dont le nom se termine par "-Trait" :

import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum

Les commandes de caractéristique sont importées à partir de l'objet Companion de la caractéristique :

import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold