Utilisez le guide suivant pour comprendre comment différents nœuds DSL d'automatisation peuvent être utilisés pour créer une automatisation.
Tout le DSL d'automatisation 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.
Voici un modèle DSL d'automatisation 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 affiner cette analyse 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 de sélection.
Déclencheur basé sur l'attribut de trait
Lorsque vous déclarez un nœud de déclencheur basé sur un attribut de trait, spécifiez:
- l'appareil
- Type d'appareil auquel la caractéristique appartient
- le trait
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
Le paramètre "device type" (Type d'appareil) est obligatoire, car il vous permet de spécifier le type d'appareil dans lequel l'automatisation s'adresse. Par exemple, un appareil peut être composé d'un FanDevice
et d'un HeatingCoolingUnitDevice
, qui contiennent tous deux le trait OnOff
. En spécifiant le type d'appareil, il n'y a aucune ambiguïté sur 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émarrage basé sur un événement, spécifiez:
- l'appareil
- Type d'appareil auquel le trait appartient
- 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 comporter des paramètres. Par conséquent, ces paramètres doivent également être inclus dans le déclencheur.
Par exemple, ce déclencheur utilise ScheduledTimeEvent
de la caractéristique Time
pour activer l'automatisation à 7h00 :
val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
parameter(Time.ScheduledTimeEvent.clockTime(
LocalTime.of(7, 0, 0, 0)))
}
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 peuvent bloquer l'exécution de l'automatisation, en fonction de l'expression condition
.
Pour structurer votre automatisation afin que les nœuds condition
ne bloquent pas une automatisation activée avec un déclencheur manuel, vous pouvez placer l'autre déclencheur dans un flux séquentiel distinct avec son condition
:
automation_graph {
sequential {
select {
sequential {
starter<_>(...)
condition {...}
}
sequential {
manualStarter()
}
}
action {...}
}
}
Référencer la valeur d'un attribut
Pour utiliser la valeur d'un attribut dans une expression, utilisez la syntaxe suivante.
Avec une stateReader
:
val time = stateReader<_>(structure, Structure, Time)
val currTime = time.currentTime
Avec une 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 se termine.
Dans un nœud condition
, vous pouvez combiner plusieurs critères de condition à l'aide de divers opérateurs, à condition que l'expression renvoie une seule valeur booléenne. Si la valeur obtenue 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 celles de 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 Enum. Le regroupement de sous-expressions à l'aide de 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'un trait auquel 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 trait dans un nœud condition
est d'utiliser un nœud stateReader
.
Pour ce faire, commencez par capturer la valeur de l'attribut de trait dans un nœud stateReader
. Un stateReader
utilise le structure
et le trait comme arguments:
import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)
Ensuite, référencez stateReader
dans le nœud condition
:
condition() {
expression =
filterMonitoringState.changeIndication
.equals(ChangeIndicationEnum.Warning)
}
À l'aide d'opérateurs de comparaison et de logiques, vous pouvez utiliser plusieurs stateReaders
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 pendant dix minutes.
condition {
expression(lightStateReader.onOff == true)
forDuration(Duration.ofMinutes(10))
}
La durée peut varier d'une à 30 minutes.
Nœuds d'action
C'est dans le nœud d'action que l'automatisation se produit.
Dans cet exemple, l'action appelle la commande broadcast()
du trait AssistantBroadcast
:
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 les différents éléments des API Home dans votre code.
Les attributs de trait sont importés à partir de l'objet Companion
du trait:
import com.google.home.matter.standard.OnOff.Companion.onOff
Les structures de données définies par un trait sont importées à partir de la classe de trait dont le nom se termine par "-Trait":
import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum
Les commandes de trait sont importées à partir de l'objet Companion
du trait:
import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold