In dieser Anleitung erfahren Sie, wie Sie verschiedene Automation DSL-Knoten verwenden können, um eine Automatisierung zu erstellen.
Die gesamte Automation DSL befindet sich in einem einzelnen automation-Knoten. Der automation-Knoten bildet die Grenze zwischen dem äußeren Kotlin-Sprachkontext und dem eingebetteten DSL-Kontext.
Sequenzieller Ablauf
Der sequenzielle Ablauf ist der Standardtyp des Automatisierungsablaufs.
Hier ist eine sehr einfache Automation DSL-Vorlage, die einen sequenziellen Ablauf mit einem Starter, einer Bedingung und einer Aktion verwendet:
import com.google.home.automation.action
import com.google.home.automation.automation
import com.google.home.automation.condition
import com.google.home.automation.sequential
import com.google.home.automation.starter
...
automation {
sequential {
starter<_>(...)
condition {...}
action {...}
}
}
Sie kann durch Hinzufügen weiterer Knoten verfeinert werden.
Starter
Starterknoten definieren die anfänglichen Umstände, die eine Automatisierung aktivieren. Beispielsweise eine Änderung des Status oder Werts. Eine Automatisierung muss mindestens einen Starter haben, andernfalls schlägt die Validierung fehl. Wenn Sie einer Automatisierung mehr als einen Starter hinzufügen möchten, müssen Sie einen select-Knoten verwenden.
Starter basierend auf einem Attribut eines Merkmals
Wenn Sie einen Starterknoten deklarieren, der auf einem Attribut eines Merkmals basiert, geben Sie Folgendes an:
- das Gerät
- den Gerätetyp, zu dem das Merkmal gehört
- das Merkmal
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
Der Parameter für den Gerätetyp 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
bestehen, das
FanDevice
und einem
HeatingCoolingUnitDeviceenthält,
die beide das
OnOff
Merkmal enthalten. Durch Angabe des Gerätetyps gibt es keine Unklarheiten darüber, welcher Teil des Geräts die Automatisierung auslöst.
Starter basierend auf einem Ereignis
Wenn Sie einen Starterknoten deklarieren, der auf einem Ereignis basiert, geben Sie Folgendes an:
- das Gerät
- den Gerätetyp, zu dem das Merkmal gehört
- das Ereignis
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)
Starter basierend auf einer Struktur und einem Ereignis mit Parametern
Einige Ereignisse können Parameter haben. Diese Parameter müssen daher auch im Starter enthalten sein.
Dieser Starter verwendet beispielsweise das
Time MerkmalScheduledTimeEvent, um die Automatisierung um 7:00 Uhr zu aktivieren:
val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
parameter(Time.ScheduledTimeEvent.clockTime(
LocalTime.of(7, 0, 0, 0)))
}
Starter basierend auf dem Wetter
Sie können aktuelle oder prognostizierte Wetterbedingungen in einem Auslöser angeben, indem Sie das Merkmal „Weather“ verwenden:
val weatherState = starter<_>(structure, trait = Weather)
Weitere Informationen finden Sie auf der Seite mit Beispielautomatisierungen unter „Close the blinds if it is likely to rain“ (Schließe die Jalousien, wenn es wahrscheinlich regnet).
Manueller Starter
Ein manueller Starter ist ein spezieller Startertyp, mit dem der Nutzer die Automatisierung manuell ausführen kann.
Wenn Sie einen manuellen Starter deklarieren:
- Geben Sie kein Merkmal oder keinen Gerätetyp an.
- Geben Sie ein UI-Element an, das
Automation.execute()aufruft.
Wenn Sie einen manuellen Starter zusammen mit einem anderen Starter in einem select-Ablauf platzieren, überschreibt der manuelle Starter den anderen Starter:
select {
manualStarter()
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}
Beachten Sie, dass alle condition-Knoten nach einem manuellen Auslöser ausgewertet werden und die Ausführung der Automatisierung je nach condition-Ausdruck blockieren können.
Eine Möglichkeit, Ihre Automatisierung so zu strukturieren, dass condition-Knoten keine Automatisierung blockieren, die mit einem manuellen Auslöser aktiviert wurde, besteht darin, den anderen Auslöser zusammen mit seiner condition in einen separaten sequenziellen Ablauf zu setzen:
automation_graph {
sequential {
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:
val time = stateReader<_>(structure, Structure, Time)
val currTime = time.currentTime
Mit einem starter:
val starterNode = starter<_>(device1, LaundryWasherDevice, OnOff)
condition() {
expression = 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
als einzelner
boolescher Wert ausgewertet wird. Wenn der resultierende Wert true ist, ist die Bedingung erfüllt und die Automatisierung setzt die Ausführung des nächsten Knotens fort. Wenn der Wert false ist, wird die Ausführung der Automatisierung an dieser Stelle beendet.
Ausdrücke werden ähnlich wie Ausdrücke in Kotlin 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 eine condition, die mehrere Unterausdrücke zu einem einzigen Ausdruck kombiniert:
condition() {
val expr1 = starterNode.lockState equals DlLockState.Unlocked
val expr2 = stateReaderNode.lockState equals true
val expr3 = occupancySensingDevice.occupied notEquals 0
val expr4 = timeStateReaderNode
.currentTime
.between(
timeStateReaderNode.sunsetTime,
timeStateReaderNode.sunriseTime)
expression = (expr1 and expr2) or (expr3 and expr4)
}
Sie können auf den Wert eines Merkmals verweisen, auf das über einen Starter zugegriffen wird:
val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }
stateReader
Die andere Möglichkeit, in einem condition-Knoten auf Attributwerte von Merkmalen zu verweisen, ist ein stateReader-Knoten.
Dazu müssen Sie zuerst den Attributwert des Merkmals in einem stateReader-Knoten erfassen. Ein stateReader verwendet die structure und das Merkmal als Argumente:
import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)
Verweisen Sie dann im condition-Knoten auf den stateReader:
condition() {
expression =
filterMonitoringState.changeIndication
.equals(ChangeIndicationEnum.Warning)
}
Mit Vergleichs- und
logischen Operatoren können mehrere
stateReaders in einem condition Knoten verwendet werden:
val armState = stateReader<_>(doorLock, DoorLockDevice, ArmDisarm )
val doorLockState = stateReader<_>(doorLock, DoorLockDevice, DoorLock)
condition() {
expression =
(armState.armState equals true)
and
(doorLockState.lockState equals true)
}
Dauer der Bedingung
Zusätzlich zu einem booleschen Ausdruck in einer Bedingung können Sie einen Zeitraum angeben, in dem der Ausdruck „true“ 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 {
expression(lightStateReader.onOff == true)
forDuration(Duration.ofMinutes(10))
}
Die Dauer kann zwischen 5 Sekunden und 24 Stunden liegen.
Aktionsknoten
Im Aktionsknoten findet die Arbeit der Automatisierung statt.
In diesem Beispiel ruft die Aktion den
AssistantBroadcast
Befehl
broadcast() auf:
action(device, SpeakerDevice) {
command(AssistantBroadcast.broadcast("Intruder detected!"))
}
Importanweisungen
Bei der Entwicklung von Automatisierungen ist nicht immer klar, wie verschiedene Elemente der Home APIs in Ihren Code importiert werden.
Attributwerte von Merkmalen werden aus dem Companion-Objekt des Merkmals importiert:
import com.google.home.matter.standard.OnOff.Companion.onOff
Datenstrukturen, die durch ein Merkmal definiert werden, werden aus der Merkmalsklasse importiert, deren Name auf „-Trait“ endet:
import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum
Befehle von Merkmalen werden aus dem Companion-Objekt des Merkmals importiert:
import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold