In der folgenden Anleitung erfahren Sie, wie verschiedene Automation DSL-Knoten zum Erstellen einer Automatisierung verwendet werden können.
Die gesamte Automatisierungs-DSL befindet sich in einem einzelnen automation
-Knoten. Der Knoten automation
bildet die Grenze zwischen dem äußeren Kotlin-Sprachkontext und dem eingebetteten DSL-Kontext.
Sequenzieller Ablauf
Der sequenzielle Ablauf ist der Standardtyp für Automatisierungsabläufe.
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 {...}
}
}
Durch das Hinzufügen weiterer Knoten kann das Ergebnis noch weiter verfeinert werden.
Starter
Auslöserknoten definieren die anfänglichen Umstände, die eine Automatisierung aktivieren. Das kann beispielsweise eine Änderung des Status oder des Werts sein. Eine Automatisierung muss mindestens einen Starter haben, da sie sonst die Validierung nicht besteht. Wenn Sie einer Automatisierung mehr als einen Starter hinzufügen möchten, müssen Sie einen select
-Knoten verwenden.
Starter basierend auf dem Attribut „Merkmal“
Wenn Sie einen Startknoten deklarieren, der auf einem Trait-Attribut basiert, geben Sie Folgendes an:
- das Gerät
- Der Gerätetyp, zu dem das Merkmal gehört
- die Eigenschaft
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
Der Parameter „deviceType“ 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 FanDevice
und einem HeatingCoolingUnitDevice
bestehen, die beide das Merkmal OnOff
enthalten. Durch die Angabe des Gerätetyps wird eindeutig festgelegt, welcher Teil des Geräts die Automatisierung auslöst.
Starter basierend auf Ereignis
Wenn Sie einen Startknoten deklarieren, der auf einem Ereignis basiert, geben Sie Folgendes an:
- das Gerät
- Der Gerätetyp, zu dem das Merkmal gehört
- das Ereignis
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)
Starter auf Grundlage einer Struktur und eines Ereignisses mit Parametern
Einige Ereignisse können Parameter haben. Diese Parameter müssen daher auch im Starter enthalten sein.
Dieser Auslöser verwendet beispielsweise das ScheduledTimeEvent
-Attribut des Time
-Traits, um den automatisierten Ablauf um 7:00 Uhr zu aktivieren:
val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
parameter(Time.ScheduledTimeEvent.clockTime(
LocalTime.of(7, 0, 0, 0)))
}
Manueller Starter
Ein manueller Auslöser ist ein spezieller Auslösertyp, mit dem der Nutzer die Automatisierung manuell ausführen kann.
Beim Deklarieren eines manuellen Starters:
- Geben Sie keine Eigenschaft oder keinen Gerätetyp an.
- Stellen Sie ein UI-Element bereit, das
Automation.execute()
aufruft.
Wenn Sie einen manuellen Auslöser in einem select
-Ablauf zusammen mit einem anderen Auslöser platzieren, wird der andere Auslöser durch den manuellen Auslöser überschrieben:
select {
manualStarter()
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}
Alle condition
-Knoten, die auf einen manuellen Starter folgen, werden ausgewertet und können die Ausführung der Automatisierung blockieren, je nach condition
-Ausdruck.
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 stellen:
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. 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 wird mit dem nächsten Knoten fortgesetzt. Wenn der Wert false
ist, wird die Automatisierung an dieser Stelle beendet.
Ausdrücke werden ähnlich wie 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 ein Beispiel für einen condition
, der mehrere Unterausdrücke in 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
Eine weitere Möglichkeit, auf Attributwerte von Eigenschaften in einem condition
-Knoten zu verweisen, ist ein stateReader
-Knoten.
Erfassen Sie dazu zuerst den Attributwert des Merkmals in einem stateReader
-Knoten. Für stateReader
werden die structure
und das Attribut als Argumente verwendet:
import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)
Verweisen Sie dann im Knoten condition
auf stateReader
:
condition() {
expression =
filterMonitoringState.changeIndication
.equals(ChangeIndicationEnum.Warning)
}
Mithilfe von 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 „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 {
expression(lightStateReader.onOff == true)
forDuration(Duration.ofMinutes(10))
}
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 Traits AssistantBroadcast
auf:
action(device, SpeakerDevice) {
command(AssistantBroadcast.broadcast("Intruder detected!"))
}
Importanweisungen
Beim Entwickeln von Automatisierungen ist es nicht immer offensichtlich, wie verschiedene Elemente der Home-APIs in Ihren Code importiert werden.
Die Attributwerte werden aus dem Companion
-Objekt des Traits importiert:
import com.google.home.matter.standard.OnOff.Companion.onOff
Datenstrukturen, die durch ein Attribut definiert werden, werden aus der Attributklasse importiert, deren Name mit „-Trait“ endet:
import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum
Trait-Befehle werden aus dem Companion
-Objekt des Traits importiert:
import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold