Guide DSL iOS

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 Swift 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 DSL d'automatisation très simple qui utilise un flux séquentiel composé d'un déclencheur, d'une condition et d'une action :

import GoogleHomeSDK
import GoogleHomeTypes

automation (
...
) {
  starter(...)
  condition {...}
  action {...}
}

Vous pouvez affiner cette sélection en ajoutant des nœuds.

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.

Starter basé sur l'attribut de trait

Lorsque vous déclarez un nœud de démarrage basé sur un attribut de caractéristique, spécifiez :

  • l'appareil
  • le type d'appareil auquel appartient le trait.
  • le trait
starter(
  thermostat,
  Matter.TemperatureSensorDeviceType.self,
  Matter.TemperatureMeasurementTrait.self
)

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. Par exemple, un appareil peut être composé d'un FanDeviceType et d'un HeatingCoolingUnitDeviceType, qui contiennent tous deux le trait OnOffTrait. En spécifiant le type d'appareil, vous évitez toute ambiguïté quant à la partie de l'appareil qui déclenche l'automatisation.

Starter basé sur un événement

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

  • l'appareil
  • le type d'appareil auquel appartient le trait.
  • l'événement
starter(
  doorbell,
  Google.GoogleDoorbellDeviceType.self,
  Google.DoorbellPressTrait.DoorbellPressedEvent
)

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

Certains événements peuvent comporter des paramètres. Ces paramètres doivent donc également être inclus dans le starter.

Par exemple, ce déclencheur utilise ScheduledEvent de TimeTrait pour activer l'automatisation à 7h00 :

typealias TimeTrait = Google.TimeTrait

let earlyMorning = starter(
  structure,
  TimeTrait.ScheduledEvent.self
) {
  TimeTrait.ScheduledEvent.clockTime(TimeOfDay(hours: 7, minutes: 0))
}

Démarreur 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émarreur 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,
    Matter.TemperatureSensorDeviceType.self,
    Matter.TemperatureMeasurementTrait.self
  )
}

Notez que tous les nœuds condition qui suivent un nœud de démarrage 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'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, vous pouvez placer l'autre déclencheur dans un flux séquentiel distinct avec son condition :

import GoogleHomeSDK
import GoogleHomeTypes

automation (
...
) {

  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 :

typealias TimeTrait = Google.TimeTrait

let time = stateReader(structure, TimeTrait.self)
time
let currTime = time.currentTime

Avec un starter :

typealias LaundryWasherDeviceType = Matter.LaundryWasherDeviceType
typealias OnOffTrait = Google.OnOffTrait

let starterNode = starter(device1, LaundryWasherDeviceType.self, OnOffTrait.self)
starterNode
condition {
  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 soit évaluée à 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 cesse de s'exécuter à ce moment-là.

Les expressions sont formées de la même manière que les expressions en Swift 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 avec des 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 {
  let exp1 = starterNode.lockState.equals(.unlocked)
  let exp2 = stateReaderNode.lockState.equals(true)
  let exp3 = occupancySensingDevice.occupied.notEquals(0)
  (exp1.and(exp2)).or(exp3)
}

Vous pouvez faire référence à la valeur d'un trait accessible via un starter :

typealias OnOffTrait = Matter.OnOffTrait

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

stateReader

L'autre façon de référencer les valeurs d'attribut de caractéristique dans un nœud condition consiste à 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 prend le structure et le trait comme arguments :

typealias ActivatedCarbonFilterMonitoringTrait = Matter.ActivatedCarbonFilterMonitoringTrait

let filterMonitoringState = stateReader(structure, ActivatedCarbonFilterMonitoringTrait.self)

Référencez ensuite stateReader dans le nœud condition :

condition {
filterMonitoringState.changeIndication.equals(.warning)
}

En utilisant des opérateurs de comparaison et logiques, plusieurs stateReaders peuvent être utilisés dans un nœud condition :

typealias ArmDisarm = Google.ArmDisarmTrait
typealias DoorLockDevice = Matter.DoorLockDeviceType
typealias DoorLock = Matter.DoorLockTrait

let armState = stateReader(doorLock, DoorLockDevice.self, ArmDisarm )
let doorLockState = stateReader(doorLock, DoorLockDevice.self, DoorLock)
armState
doorLockState
condition {
  let exp1 = armState.armState
  let exp2 = doorLockState.lockState
  exp1.and(exp2)
}

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 que l'automatisation s'exécute. Par exemple, vous pouvez définir une condition qui se déclenche uniquement si une lumière est allumée depuis dix minutes.

condition(for: .seconds(600)) {
lightStateReader.onOff.equals(true)
}

La durée peut varier de 1 à 30 minutes.

Nœuds d'action

Le nœud d'action est l'endroit où le travail d'automatisation a lieu. Dans cet exemple, l'action appelle la commande broadcast() de AssistantBroadcastTrait :

action(speaker, SpeakerDeviceType.self) {
  Google.AssistantBroadcastTrait.broadcast(msg: "Oven Cycle Complete")
}