Hier finden Sie eine Übersicht über die grundlegenden Konzepte der Automation DSL.
Automatisierungskomponenten
Eine Automatisierung besteht aus den folgenden grundlegenden Komponenten, die in der Regel in dieser Reihenfolge ausgewertet werden:
- Auslöser: Hiermit werden die Anfangsbedingungen definiert, die die Automatisierung aktivieren, z. B. eine Änderung an einem Attribut. Eine Automatisierung muss einen Auslöser haben.
- Bedingung: Zusätzliche Einschränkungen, die nach der Aktivierung einer Automatisierung ausgewertet werden sollen. Der Ausdruck in einer Bedingung muss
true
ergeben, damit die Aktionen einer Automatisierung fortgesetzt werden. - Aktion: Befehle oder Statusaktualisierungen, die ausgeführt werden, wenn alle Bedingungen erfüllt sind.
Vielleicht haben Sie beispielsweise eine Automatisierung, die das Licht in einem Raum gedimmt, wenn der Fernseher in diesem Raum zwischen Sonnenuntergang und Sonnenaufgang eingeschaltet ist. In diesem Fall gilt Folgendes:
- Starter: Der Fernseher wurde eingeschaltet. Dies ist eine Statusänderung bei einem Fernsehermerkmal.
- Bedingung: Die aktuelle Uhrzeit für das Zuhause, in dem sich der Fernseher befindet, wird ausgewertet.
- Aktion: Die Lampen im selben Raum wie der Fernseher werden gedimmt.
Die Automatisierung wird aktiviert, wenn der Fernseher im Raum eingeschaltet ist, aber nur ausgeführt, wenn die Bedingung „Zeit zwischen Sonnenuntergang und Sonnenaufgang“ erfüllt ist.
Zusätzlich zur grundlegenden Struktur enthalten Automatisierungen in den Home APIs auch Metadaten wie name und description, mit denen sie für Entwickler und Nutzer identifiziert werden können.
Knoten
In den Home APIs besteht die logische Struktur einer Automatisierung aus nodes. Knoten sind abstrakte, wiederverwendbare Einheiten, die das Verhalten von Entitäten oder Ausführungsabläufe darstellen. Jeder Knoten kann Eingabe- und Ausgabevariablen haben, die von anderen Knoten verwendet werden können.
Knoten | Knotentyp | Kotlin-Implementierung | Beschreibung |
---|---|---|---|
Auslöser | Verhaltensbezogen |
StarterNodeDsl
|
Eine Automatisierung wird gestartet, wenn sich der Status eines Attributs ändert. |
StateReader | Verhaltensbezogen |
StateReaderNodeDsl
|
Liest ein Merkmalattribut und ermöglicht es, den Wert für die Verwendung in Bedingungsknoten zu erfassen. |
Aktion | Verhaltensbezogen |
ActionNodeDsl
|
Ruft Befehl(e) für Eigenschaften auf. |
Sequenziell | Ablauf der Ausführung |
SequentialFlow
|
Führt verschachtelte Aktionsknoten nacheinander aus. Das ist das Standardausführungsverhalten. |
Parallel | Ablauf der Ausführung |
ParallelFlow
|
Führt verschachtelte Aktionsknoten parallel aus. |
Bedingung | Ablauf der Ausführung |
ConditionNodeDsl
|
Sie können den Ablauf der Ausführung bedingt anhand der Auswertung logischer Ausdrücke ändern. Bedingungen können mit einem Auslöser verknüpft sein (auslöserspezifische Bedingungen) oder global sein (für alle Auslöser gelten). |
Auswählen | Ablauf der Ausführung |
SelectFlow
|
Ermöglicht es, eine Automatisierung durch mehrere Auslöser zu aktivieren. |
Expression | Wert |
Expression
|
Kann der Wert des Attributs eines Merkmals, eine Konstante oder ein Literalwert sein und muss zu einer Liste, Zahl, einem booleschen Wert oder einem String führen. |
Verhaltensknoten
Knoten wie Auslöser und Aktionen sind Verhaltensknoten. Auslöser aktivieren eine Automatisierung basierend auf Änderungen von Geräteattributen. Mit Aktionen werden Gerätebefehle ausgegeben oder Attribute aktualisiert.
Verhaltensknoten sind in der Regel mit Gerätemerkmalen und dem Ausgabemerkmalenstatus verknüpft, um sie als Eingabe in anderen Knoten zu verwenden.
Knoten des Ablaufs der Ausführung
Einige Knoten stellen Ausführungsabläufe dar, z. B. sequenzielle und parallele. Jeder dieser Knoten enthält die Verhaltensknoten, die die Automatisierung definieren.
Ein sequentieller Ablauf kann beispielsweise Knoten enthalten, die in einer bestimmten Reihenfolge ausgeführt werden. In der Regel sind das Auslöser, Bedingung und Aktion.
In einem parallelen Ablauf können mehrere Aktionsknoten gleichzeitig ausgeführt werden, z. B. wenn mehrere Lampen gleichzeitig eingeschaltet werden sollen. Knoten, die einem parallelen Ablauf folgen, werden erst ausgeführt, wenn alle Verzweigungen des parallelen Ablaufs abgeschlossen sind.
Ein weiterer Ausführungsablauf ist ein Bedingungsablauf, der den Ausführungsablauf basierend auf der Auswertung eines Ausdrucks ändern kann.
Angenommen, Sie haben eine Automatisierung, die eine Aktion ausführt, je nachdem, ob es Nacht ist. Ein Bedingungsknoten prüft die Uhrzeit und folgt dann basierend auf dieser Auswertung dem entsprechenden Ausführungspfad.
Ein ausgewählter Ablauf ist nützlich, wenn Sie mehr als einen Auslöser haben möchten, mit dem Ihre Automatisierung aktiviert werden kann. Wenn Sie zwei oder mehr Auslöser in einen select
-Ablauf einschließen, kann jeder der Auslöser die Automatisierung aktivieren.
Sie können beispielsweise eine Automatisierung erstellen, die die Jalousien bei Sonnenuntergang schließt, wenn die Temperatur über einen bestimmten Wert steigt oder wenn die Helligkeit einen bestimmten Wert überschreitet. Für jedes dieser Szenarien werden drei separate Auslöser verwendet, die alle in einem select
-Ablauf verpackt werden.
Verschachtelte Abläufe
In komplexen Automatisierungen können Ausführungsablaufknoten auch verschachtelt werden. Beispielsweise können Sie einen sequenziellen Ablauf haben, der einen parallelen Ablauf ausführt.
DSL-Knoten können je nach Ihren spezifischen Anforderungen auf verschiedene Arten verschachtelt und kombiniert werden. Beachten Sie dabei die Einschränkungen in der folgenden Tabelle. Die Spalte „Builder“ enthält einen Link zur Dokumentation der typensicheren Builder von Kotlin, in der beschrieben wird, was für jeden Knotentyp zulässig ist.
Knoten | Builder | Kann den folgenden Knotentyp und die folgenden Daten enthalten | Muss zu einem der folgenden Knotentypen gehören |
---|---|---|---|
Auslöser |
AutomationBuilder
|
Ausdruck | Auswählen, Sequenziell |
ManualStarter |
AutomationBuilder
|
Auswählen, Sequenziell | |
StateReader |
AutomationBuilder
|
Ausdruck (normalerweise ein Merkmalattributwert) | Aktion, Bedingung |
Aktion |
ActionBuilder
|
Befehl, Entität, Ausdruck | Parallel, Auswahl, Sequenziell |
Sequenziell |
SequentialFlowBuilder
|
Parallel, Auswahl, Sequenziell | |
Parallel |
ParallelFlowBuilder
|
Aktion | Sequenziell |
Bedingung | ConditionBuilder |
Ausdruck | Parallel, Sequenziell |
Auswählen |
AutomationBuilder
|
Bedingung, Sequenziell, Auslöser, ManualStarter | Sequenziell und muss der erste Knoten im Ablauf sein |
Automation DSL
In den Home APIs werden Automatisierungen mit der Automation DSL (Domain-Specific Language) definiert. Die Automation DSL ist als Kotlin-DSL (domainspezifische Sprache) implementiert und verwendet typsichere Kotlin-Builder. Sie wurde speziell für die Definition von Automatisierungsvorlagen entwickelt.
Beim Kompilieren einer Automatisierung generieren typsichere Kotlin-Builder Kotlin-Datenklassen, die dann in Protocol Buffer JSON serialisiert werden. Diese werden verwendet, um die Automatisierungsdienste von Google aufzurufen.
Die Automation DSL vereinfacht und optimiert den Prozess zum Erstellen von Automatisierungen. Sie verwendet nativ dasselbe Datenmodell mit Matter-Standardmerkmalen und smart home-Merkmalen wie die Device API.
Die Automation DSL definiert auch die Logik einer Automatisierung in Bezug auf abstrakte Gerätetypen, im Gegensatz zu bestimmten Geräteinstanzen im Zuhause eines Nutzers. Der Entwickler kann Eingabeparameter angeben, die zur Laufzeit verwendet werden können, um tatsächliche Geräteinstanzen sowie andere wichtige Parameterwerte anzugeben.
Die DSL-Syntax ähnelt der von Kotlin und ist ebenfalls typsicher. Eine Automatisierung, die in der Automation DSL geschrieben ist, ist jedoch einfacher und prägnanter als dieselbe Automatisierung, die in reiner Kotlin-Syntax geschrieben ist.
Beispiel
Im Folgenden finden Sie ein Beispiel für eine Automatisierung, die ein Gerät einschaltet. Sie wurde mit der Automation DSL geschrieben:
val automation = automation {
name = "MyFirstAutomation"
description = "If light1 is on, turn on light2."
isActive = true
sequential {
val onOffTrait = starter<_>(device1, OnOffLightDevice, OnOff)
condition() { expression = onOffTrait.onOff equals true }
action(device2, OnOffLightDevice) { command(OnOff.on()) }
}
}
Diese Automatisierung ist sehr einfach: Wenn device1
, eine Lampe, eingeschaltet wird (das onOff
-Attribut ändert sich in true
), wird der Befehl on()
gesendet, um device2
einzuschalten.
Die Automatisierung verwendet einen sequential
-Knoten, was bedeutet, dass die Knoten in sequenzieller Reihenfolge ausgeführt werden.
Innerhalb des Knotens sequential
befinden sich Verhaltensknoten wie starter
, condition
und action
. Die Ausgabe des Knotens starter
wird einer Variablen zugewiesen, die im Knoten condition
verwendet wird.