iOS DSL guide

In der folgenden Anleitung wird beschrieben, wie du mit verschiedenen DSL-Knoten für die Automatisierung eine Automatisierung erstellen kannst.

Die gesamte Automatisierungs-DSL wird in einem einzelnen 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 Automatisierungsabläufe.

Beispiel für sequenzielle DSL

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

import GoogleHomeSDK
import GoogleHomeTypes

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

Dies kann durch Hinzufügen weiterer Knoten verfeinert werden.

Starter

Auslöserknoten definieren die anfänglichen Umstände, die eine Automatisierung aktivieren. Beispiel: eine Änderung des Status oder Werts. Eine Automatisierung muss mindestens einen Auslöser haben, sonst schlägt die Validierung fehl. Wenn du einer Automatisierung mehr als einen Auslöser hinzufügen möchtest, musst du einen select-Knoten verwenden.

Auslöser basierend auf einem Attribut

Wenn du einen Starterknoten deklarierst, der auf einem Trait-Attribut basiert, gib Folgendes an:

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

Der Parameter „device_type“ ist erforderlich, da du damit angeben kannst, welchen Gerätetyp innerhalb eines Geräts die Automatisierung anspricht. Ein Gerät kann beispielsweise aus einem FanDeviceType und einem HeatingCoolingUnitDeviceType bestehen, die beide das Attribut OnOffTrait enthalten. Wenn du den Gerätetyp angibst, ist eindeutig, welcher Teil des Geräts die Automatisierung auslöst.

Auslöser basierend auf Ereignis

Wenn du einen Starterknoten deklarierst, der auf einem Ereignis basiert, gib Folgendes an:

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

Auslöser basierend auf einem Gebäude und Ereignis, mit Parametern

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

In diesem Beispiel wird der 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))
}

Auslöser basierend auf dem Wetter

Du kannst aktuelle oder vorhergesagte Wetterbedingungen in einem Auslöser angeben, indem du das Attribut „Wetter“ verwendest:

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

Weitere Informationen findest du auf der Seite Beispiele für automatisierte Abläufe unter Jalousien schließen, wenn es wahrscheinlich regnen wird.

Manueller Auslöser

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

Wenn du einen manuellen Auslöser deklarierst:

  • Gib kein Attribut und keinen Gerätetyp an.
  • Stellen Sie ein UI-Element bereit, das Automation.execute() aufruft.

Wenn du einen manuellen Auslöser zusammen mit einem anderen Auslöser in einem select-Ablauf platzierst, überschreibt der manuelle Auslöser den anderen Auslöser:

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

Beachte, dass alle condition-Knoten, die auf einen manuellen Auslöser folgen, ausgewertet werden und die Ausführung der Automatisierung je nach condition-Ausdruck blockieren können.

Manuellen Auslöser von einer Bedingung trennen

Eine Möglichkeit, deine 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 platzieren:

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 oder nicht. 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, solange der Ausdruck zu einem einzelnen booleschen Wert ausgewertet wird. Wenn der resultierende Wert true ist, ist die Bedingung erfüllt und die Automatisierung fährt mit der Ausführung des nächsten Knotens fort. Wenn der Wert false ist, wird die Automatisierung an dieser Stelle beendet.

Ausdrücke werden ähnlich wie Ausdrücke in Swift gebildet und können primitive Werte wie Zahlen, Zeichen, Strings und boolesche Werte sowie Enum-Werte enthalten. Wenn Sie Unterausdrücke mit Klammern gruppieren, 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)
}

Du kannst auf den Wert einer Eigenschaft verweisen, auf die ü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

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

Erfassen Sie dazu zuerst den Attributwert „trait“ in einem stateReader-Knoten. Ein stateReader verwendet die structure und das Attribut als Argumente:

typealias ActivatedCarbonFilterMonitoringTrait = Matter.ActivatedCarbonFilterMonitoringTrait

let filterMonitoringState = stateReader(structure, ActivatedCarbonFilterMonitoringTrait.self)

Verweisen Sie dann im Knoten condition auf die 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 kannst du einen Zeitraum angeben, in dem der Ausdruck wahr sein muss, damit die Automatisierung ausgeführt wird. Du kannst beispielsweise eine Bedingung definieren, die nur ausgelöst wird, wenn ein Licht 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() des AssistantBroadcastTrait auf:

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