iOS DSL guide

Im folgenden Leitfaden erfahren Sie, wie Sie verschiedene Automation DSL-Knoten zum Erstellen einer Automatisierung verwenden können.

Das gesamte Automatisierungs-DSL wird in einem einzigen automation-Knoten platziert. 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 den Ablauf der Automatisierung.

Beispiel für eine sequenzielle DSL

Hier ist eine sehr einfache Automation DSL-Vorlage mit einem sequenziellen Ablauf, der aus einem Auslöser, einer Bedingung und einer Aktion besteht:

import GoogleHomeSDK
import GoogleHomeTypes

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

Dies kann durch Hinzufügen weiterer Knoten optimiert werden.

Starter

Mit Auslöserknoten werden die anfänglichen Umstände definiert, die eine Automatisierung aktivieren. Zum Beispiel eine Status- oder Wertänderung. Eine Automatisierung muss mindestens einen Auslöser haben, da sie sonst nicht validiert werden kann. Wenn Sie einer Automatisierung mehrere Auslöser hinzufügen möchten, müssen Sie einen select-Knoten verwenden.

Auslöser basierend auf dem Merkmalattribut

Geben Sie beim Deklarieren eines Auslöserknotens, der auf einem Merkmalattribut basiert, Folgendes an:

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

Der Parameter „device_type“ ist erforderlich, da Sie damit angeben können, welcher Gerätetyp innerhalb eines Geräts von der Automatisierung angesprochen werden soll. Ein Gerät kann beispielsweise aus einem FanDeviceType und einem HeatingCoolingUnitDeviceType bestehen, die beide das Merkmal OnOffTrait enthalten. Wenn Sie den Gerätetyp angeben, ist klar, welcher Teil des Geräts die Automatisierung auslöst.

Auslöser basierend auf Ereignis

Geben Sie bei der Deklarierung eines Auslöserknotens, der auf einem Ereignis basiert, Folgendes an:

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

Auslöser auf Grundlage einer Struktur und eines Ereignisses mit Parametern

Einige Ereignisse können Parameter haben. Diese Parameter müssen daher auch in den Auslöser aufgenommen werden.

In diesem Auslöser wird beispielsweise ScheduledEvent von TimeTrait verwendet, um die Automatisierung 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 Auslöser

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

Wenn Sie einen manuellen Auslöser deklarieren:

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

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

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

Hinweis: Alle condition-Knoten nach einem manuellen Auslöser werden ausgewertet und können je nach condition-Ausdruck die Ausführung der Automatisierung blockieren.

Manuellen Auslöser 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 setzen:

import GoogleHomeSDK
import GoogleHomeTypes

automation (
...
) {

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

}

Verweis auf den Wert eines Attributs

Verwenden Sie die folgende Syntax, um den Wert eines Attributs in einem Ausdruck zu verwenden.

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 festlegt, ob die Automatisierung fortgesetzt wird oder nicht. Eine Automatisierung kann mehrere condition-Knoten haben. Wenn der Ausdruck eines condition-Knotens false ergibt, wird die Ausführung der gesamten Automatisierung beendet.

Innerhalb eines condition-Knotens können Sie mehrere Bedingungskriterien mit verschiedenen Operatoren kombinieren, solange der Ausdruck zu einem einzelnen booleschen Wert führt. Wenn der resultierende Wert true ist, ist die Bedingung erfüllt und die Automatisierung führt die Ausführung des nächsten Knotens fort. Wenn das false ist, wird die Automatisierung an diesem Punkt 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. Wenn Sie untergeordnete Ausdrücke in Klammern gruppieren, können Sie die Reihenfolge festlegen, in der sie ausgewertet werden.

Hier 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 Attributs verweisen, auf das über einen Auslöser 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 Werte von Merkmalattributen in einem condition-Knoten zu verweisen, ist ein stateReader-Knoten.

Dazu müssen Sie zuerst den Wert des Merkmalattributs in einem stateReader-Knoten erfassen. Eine stateReader nimmt den structure und das Merkmal als Argumente an:

typealias ActivatedCarbonFilterMonitoringTrait = Matter.ActivatedCarbonFilterMonitoringTrait

let filterMonitoringState = stateReader(structure, ActivatedCarbonFilterMonitoringTrait.self)

Verweisen Sie dann auf stateReader im Knoten condition:

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

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

Bedingungsdauer

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