iOS DSL guide

In der folgenden Anleitung erfahren Sie, wie verschiedene Automation DSL-Knoten zum Erstellen einer Automatisierung verwendet werden können.

Die gesamte Automatisierungs-DSL befindet sich in einem einzelnen automation-Knoten. Der Knoten automation bildet die Grenze zwischen dem äußeren Swift-Sprachkontext und dem eingebetteten DSL-Kontext.

Sequenzieller Ablauf

Der sequenzielle Ablauf ist der Standardtyp für Automatisierungsabläufe.

Beispiel für sequenzielle DSL

Hier ist eine sehr einfache Automation DSL-Vorlage, die einen sequenziellen Ablauf mit einem Starter, einer Bedingung und einer Aktion verwendet:

import GoogleHomeSDK
import GoogleHomeTypes

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

Durch das Hinzufügen weiterer Knoten kann das Ergebnis noch weiter verfeinert werden.

Starter

Auslöserknoten definieren die anfänglichen Umstände, die eine Automatisierung aktivieren. Das kann beispielsweise eine Änderung des Status oder des Werts sein. Eine Automatisierung muss mindestens einen Starter haben, da sie sonst die Validierung nicht besteht. Wenn Sie einer Automatisierung mehr als einen Starter hinzufügen möchten, müssen Sie einen select-Knoten verwenden.

Starter basierend auf dem Attribut „Merkmal“

Wenn Sie einen Startknoten deklarieren, der auf einem Trait-Attribut basiert, geben Sie Folgendes an:

  • das Gerät
  • Der Gerätetyp, zu dem das Merkmal gehört
  • die Eigenschaft
starter(
  thermostat,
  Matter.TemperatureSensorDeviceType.self,
  Matter.TemperatureMeasurementTrait.self
)

Der Parameter „deviceType“ ist erforderlich, da Sie damit angeben können, auf welchen Gerätetyp innerhalb eines Geräts sich die Automatisierung bezieht. Ein Gerät kann beispielsweise aus einem FanDeviceType und einem HeatingCoolingUnitDeviceType bestehen, die beide das Merkmal OnOffTrait enthalten. Durch die Angabe des Gerätetyps wird eindeutig festgelegt, welcher Teil des Geräts die Automatisierung auslöst.

Starter basierend auf Ereignis

Wenn Sie einen Startknoten deklarieren, der auf einem Ereignis basiert, geben Sie Folgendes an:

  • das Gerät
  • Der Gerätetyp, zu dem das Merkmal gehört
  • die Veranstaltung
starter(
  doorbell,
  Google.GoogleDoorbellDeviceType.self,
  Google.DoorbellPressTrait.DoorbellPressedEvent
)

Starter auf Grundlage einer Struktur und eines Ereignisses mit Parametern

Einige Ereignisse können Parameter haben. Diese Parameter müssen daher auch im Starter enthalten sein.

In diesem Auslöser wird beispielsweise die ScheduledEvent von TimeTrait verwendet, um den automatisierten Ablauf um 7:00 Uhr zu aktivieren:

typealias TimeTrait = Google.TimeTrait

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

Manueller Starter

Ein manueller Auslöser ist ein spezieller Auslösertyp, mit dem der Nutzer die Automatisierung manuell ausführen kann.

Beim Deklarieren eines manuellen Starters:

  • Geben Sie keine Eigenschaft oder keinen Gerätetyp an.
  • Stellen Sie ein UI-Element bereit, das Automation.execute() aufruft.

Wenn Sie einen manuellen Auslöser in einem select-Ablauf zusammen mit einem anderen Auslöser platzieren, wird der andere Auslöser durch den manuellen Auslöser überschrieben:

select {
  manualStarter()
  starter(
    thermostat,
    Matter.TemperatureSensorDeviceType.self,
    Matter.TemperatureMeasurementTrait.self
  )
}

Alle condition-Knoten, die auf einen manuellen Starter folgen, werden ausgewertet und können die Ausführung der Automatisierung blockieren, je nach condition-Ausdruck.

Manuellen Starter von einer Bedingung trennen

Eine Möglichkeit, Ihre Automatisierung so zu strukturieren, dass condition-Knoten eine Automatisierung, die mit einem manuellen Auslöser aktiviert wurde, nicht blockieren, besteht darin, den anderen Auslöser zusammen mit seinem condition in einen separaten sequenziellen Ablauf zu stellen:

import GoogleHomeSDK
import GoogleHomeTypes

automation (
...
) {

  select {
    sequential {
      starter(...)
      condition {...}
    }
    sequential {
      manualStarter()
    }
  }
  action {...}

}

Auf den Wert eines Attributs verweisen

Wenn Sie den Wert eines Attributs in einem Ausdruck verwenden möchten, verwenden Sie die folgende Syntax.

Mit einem stateReader:

typealias TimeTrait = Google.TimeTrait

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

Mit einem starter:

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

let starterNode = starter(device1, LaundryWasherDeviceType.self, OnOffTrait.self)
starterNode
condition {
  starterNode.onOff.equals(true)
}

Bedingungsknoten und ‑ausdrücke

Ein Bedingungsknoten stellt einen Entscheidungspunkt dar, der bestimmt, ob die Automatisierung fortgesetzt wird. Eine Automatisierung kann mehrere condition-Knoten haben. Wenn der Ausdruck eines condition-Knotens als false ausgewertet wird, wird die Ausführung der gesamten Automatisierung beendet.

In einem condition-Knoten können Sie mehrere Bedingungskriterien mit verschiedenen Operatoren kombinieren, sofern der Ausdruck zu einem einzelnen booleschen Wert ausgewertet wird. Wenn der resultierende Wert true ist, ist die Bedingung erfüllt und die Automatisierung wird mit dem nächsten Knoten fortgesetzt. Wenn der Wert false ist, wird die Automatisierung an dieser Stelle beendet.

Ausdrücke werden ähnlich wie in Swift gebildet und können primitive Werte wie Zahlen, Zeichen, Strings und boolesche Werte sowie Enum-Werte enthalten. Durch Gruppieren von Unterausdrücken mit Klammern können Sie die Reihenfolge steuern, in der sie ausgewertet werden.

Hier ist ein Beispiel für einen condition, der mehrere Unterausdrücke in einem einzigen Ausdruck kombiniert:

condition {
  let exp1 = starterNode.lockState.equals(.unlocked)
  let exp2 = stateReaderNode.lockState.equals(true)
  let exp3 = occupancySensingDevice.occupied.notEquals(0)
  (exp1.and(exp2)).or(exp3)
}

Sie können auf den Wert eines Merkmals verweisen, auf das über einen Starter zugegriffen wird:

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

Eine weitere Möglichkeit, auf Attributwerte von Eigenschaften in einem condition-Knoten zu verweisen, ist ein stateReader-Knoten.

Erfassen Sie dazu zuerst den Attributwert des Merkmals in einem stateReader-Knoten. Für stateReader werden die structure und das Attribut als Argumente verwendet:

typealias ActivatedCarbonFilterMonitoringTrait = Matter.ActivatedCarbonFilterMonitoringTrait

let filterMonitoringState = stateReader(structure, ActivatedCarbonFilterMonitoringTrait.self)

Verweisen Sie dann im Knoten condition auf stateReader:

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

Mit Vergleichs- und logischen Operatoren> können mehrere stateReaders in einem condition-Knoten verwendet werden:

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)
}

Dauer der Bedingung

Zusätzlich zu einem booleschen Ausdruck in einer Bedingung können Sie einen Zeitraum angeben, in dem der Ausdruck „wahr“ sein muss, damit die Automatisierung ausgeführt wird. Sie können beispielsweise eine Bedingung definieren, die nur ausgelöst wird, wenn eine Lampe zehn Minuten lang eingeschaltet war.

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

Die Dauer kann zwischen einer und 30 Minuten liegen.

Aktionsknoten

Im Aktionsknoten wird die Arbeit der Automatisierung ausgeführt. In diesem Beispiel ruft die Aktion den Befehl broadcast() von AssistantBroadcastTrait auf:

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