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 Auslöser, 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.
Auslöser
Auslöserknoten definieren die anfänglichen Umstände, die eine Automatisierung aktivieren. Beispielsweise eine Änderung des Status oder Werts. Eine Automatisierung muss mindestens einen Auslöser haben, andernfalls schlägt die Validierung fehl. Wenn Sie einer Automatisierung mehr als einen Auslöser hinzufügen möchten, müssen Sie einen select-Knoten verwenden.
Auslöser basierend auf einem Attribut
Geben Sie beim Deklarieren eines Auslöserknotens, der auf einem Attribut basiert, Folgendes an:
- das Gerät
- den Gerätetyp, zu dem das Attribut gehört
- das Attribut
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
HeatingCoolingUnitDevice
enthält, die beide das
OnOff
Attribut enthalten. Durch Angabe des Gerätetyps gibt es keine Unklarheiten darüber, welcher Teil des Geräts die Automatisierung auslöst.
Auslöser basierend auf einem Ereignis
Geben Sie beim Deklarieren eines Auslöserknotens, der auf einem Ereignis basiert, Folgendes an:
- das Gerät
- den Gerätetyp, zu dem das Attribut gehört
- das Ereignis
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)
Auslöser basierend auf einer Struktur und einem Ereignis mit Parametern
Einige Ereignisse können Parameter haben. Diese Parameter müssen daher auch im Auslöser enthalten sein.
Dieser Auslöser verwendet beispielsweise das
Time Attributs ScheduledTimeEvent, 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)))
}
Auslöser basierend auf dem Wetter
Sie können im Auslöser aktuelle oder prognostizierte Wetterbedingungen angeben, indem Sie das Attribut „Weather“ verwenden:
val weatherState = starter<_>(structure, trait = Weather)
Weitere Informationen finden Sie auf der Seite mit den Beispielautomatisierungen unter „Close the blinds if it is likely to rain“ (Schließe die Jalousien, wenn es wahrscheinlich regnet).
Manueller Auslöser
Ein manueller Auslöser ist ein spezieller Auslöser, mit dem der Nutzer die Automatisierung manuell ausführen kann.
Beim Deklarieren eines manuellen Auslösers:
- Geben Sie kein Attribut 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 einem select-Ablauf platzieren, überschreibt der manuelle Auslöser den anderen Auslöser:
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 wird mit der Ausführung des nächsten Knotens fortgesetzt. 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 Attributs verweisen, auf das über einen Auslöser zugegriffen wird:
val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }
stateReader
Die andere Möglichkeit, in einem condition-Knoten auf Attributwerte zu verweisen, ist ein stateReader-Knoten.
Erfassen Sie dazu zuerst den Attributwert in einem stateReader-Knoten. Ein stateReader verwendet die structure und das Attribut 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)
}
Bedingungsdauer
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 seit zehn Minuten eingeschaltet ist.
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() des Attributs 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 werden aus dem Companion-Objekt des Attributs importiert:
import com.google.home.matter.standard.OnOff.Companion.onOff
Datenstrukturen, die durch ein Attribut definiert werden, werden aus der Attributklasse importiert, deren Name auf „-Trait“ endet:
import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum
Attributbefehle werden aus dem Companion-Objekt des Attributs importiert:
import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold