Z tego przewodnika dowiesz się, jak za pomocą różnych węzłów Automation DSL tworzyć automatyzacje.
Cały język DSL automatyzacji znajduje się w jednym węźle automation
. Węzeł
automation
stanowi granicę między zewnętrznym kontekstem języka Kotlin
a osadzonym kontekstem DSL.
Przepływ sekwencyjny
Przepływ sekwencyjny to domyślny typ przepływu automatyzacji.
Oto bardzo prosty szablon DSL automatyzacji, który wykorzystuje sekwencyjny przepływ składający się z elementu początkowego, warunku i działania:
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 {...}
}
}
Możesz to poprawić, dodając kolejne węzły.
Początkujący
Węzły początkowe określają początkowe okoliczności, które aktywują automatyzację. Na przykład zmiana stanu lub wartości. Automatyzacja musi mieć co najmniej 1 element początkowy, w przeciwnym razie nie przejdzie weryfikacji. Aby dodać do automatyzacji więcej niż jeden element początkowy, musisz użyć węzła select
.
Starter na podstawie atrybutu cechy
Podczas deklarowania węzła początkowego opartego na atrybucie cechy podaj:
- urządzenie
- typ urządzenia, do którego należy cecha;
- cecha
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
Parametr typu urządzenia jest wymagany, ponieważ umożliwia określenie, do którego typu urządzenia w ramach urządzenia odnosi się automatyzacja. Urządzenie może się np. składać z FanDevice
i HeatingCoolingUnitDevice
, z których oba zawierają cechę OnOff
. Określenie typu urządzenia eliminuje niejasności co do tego, która część urządzenia wywołuje automatyzację.
Lista startowa na podstawie zdarzenia
Podczas deklarowania węzła początkowego opartego na zdarzeniu określ:
- urządzenie
- typ urządzenia, do którego należy cecha;
- wydarzenie,
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)
Wstępna wersja oparta na strukturze i zdarzeniu z parametrami
Niektóre zdarzenia mogą mieć parametry, więc te parametry też muszą być uwzględnione w wersji początkowej.
Na przykład ten starter używa cechy
Time
ScheduledTimeEvent
, aby aktywować automatyzację o 7:00:
val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
parameter(Time.ScheduledTimeEvent.clockTime(
LocalTime.of(7, 0, 0, 0)))
}
Rozrusznik ręczny
Ręczny wyzwalacz to specjalny typ wyzwalacza, który umożliwia użytkownikowi ręczne uruchamianie automatyzacji.
Podczas deklarowania ręcznego startera:
- Nie określaj cechy ani typu urządzenia.
- Podaj element interfejsu, który wywołuje funkcję
Automation.execute()
.
Jeśli umieścisz ręczny początek w select
przepływie razem z innym początkiem, ręczny początek zastąpi ten drugi:
select {
manualStarter()
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}
Pamiętaj, że wszystkie condition
węzły następujące po ręcznym węźle początkowym zostaną sprawdzone i mogą zablokować wykonanie automatyzacji w zależności od condition
wyrażenia.
Jednym ze sposobów skonstruowania automatyzacji tak, aby węzły condition
nie blokowały automatyzacji aktywowanej za pomocą ręcznego startera, jest umieszczenie innego startera w osobnym przepływie sekwencyjnym wraz z węzłem condition
:
automation_graph {
sequential {
select {
sequential {
starter<_>(...)
condition {...}
}
sequential {
manualStarter()
}
}
action {...}
}
}
Odwoływanie się do wartości atrybutu
Aby użyć w wyrażeniu wartości atrybutu, zastosuj tę składnię:
W przypadku stateReader
:
val time = stateReader<_>(structure, Structure, Time)
val currTime = time.currentTime
W przypadku starter
:
val starterNode = starter<_>(device1, LaundryWasherDevice, OnOff)
condition() {
expression = starterNode.onOff equals true
}
Węzły warunków i wyrażenia
Węzeł warunku reprezentuje punkt decyzyjny, który określa, czy automatyzacja będzie kontynuowana. Automatyzacja może mieć wiele węzłów condition
.
Jeśli wyrażenie dowolnego węzła condition
przyjmie wartość false
, wykonanie całej automatyzacji zostanie zakończone.
W węźle condition
możesz łączyć wiele kryteriów warunku za pomocą różnych operatorów, o ile wyrażenie daje w wyniku pojedynczą wartość logiczną. Jeśli wynikowa wartość to true
, warunek jest spełniony, a automatyzacja kontynuuje wykonywanie następnego węzła. Jeśli jest to false
, automatyzacja przestaje działać w tym momencie.
Wyrażenia są tworzone podobnie jak wyrażenia w języku Kotlin i mogą zawierać wartości pierwotne, takie jak liczby, znaki, ciągi tekstowe i wartości logiczne, a także wartości wyliczeniowe. Grupowanie podwyrażeń za pomocą nawiasów pozwala kontrolować kolejność ich obliczania.
Oto przykład condition
, który łączy wiele podwyrażeń w jedno wyrażenie:
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)
}
Możesz odwoływać się do wartości cechy, do której dostęp uzyskano za pomocą elementu początkowego:
val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }
stateReader
Innym sposobem odwoływania się do wartości atrybutów cech w węźle condition
jest użycie węzła stateReader
.
Aby to zrobić, najpierw przechwyć wartość atrybutu cechy w węźle stateReader
. Funkcja stateReader
przyjmuje jako argumenty structure
i cechę:
import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)
Następnie odwołaj się do stateReader
w węźle condition
:
condition() {
expression =
filterMonitoringState.changeIndication
.equals(ChangeIndicationEnum.Warning)
}
Za pomocą operatorów porównania i logicznych w węźle condition
można użyć wielu stateReaders
:
val armState = stateReader<_>(doorLock, DoorLockDevice, ArmDisarm )
val doorLockState = stateReader<_>(doorLock, DoorLockDevice, DoorLock)
condition() {
expression =
(armState.armState equals true)
and
(doorLockState.lockState equals true)
}
Czas trwania warunku
Oprócz wyrażenia logicznego w warunku możesz określić przedział czasu, w którym wyrażenie musi być prawdziwe, aby uruchomić automatyzację. Możesz na przykład zdefiniować warunek, który będzie aktywowany tylko wtedy, gdy światło jest włączone od 10 minut.
condition {
expression(lightStateReader.onOff == true)
forDuration(Duration.ofMinutes(10))
}
Może to być od 1 do 30 minut.
Węzły działań
W węźle działania odbywa się praca automatyzacji.
W tym przykładzie działanie wywołuje polecenie AssistantBroadcast
cechy broadcast()
:
action(device, SpeakerDevice) {
command(AssistantBroadcast.broadcast("Intruder detected!"))
}
Importowanie wyciągów
Podczas tworzenia automatyzacji nie zawsze jest oczywiste, jak zaimportować do kodu różne elementy interfejsów Home API.
Atrybuty cechy są importowane z obiektu Companion
cechy:
import com.google.home.matter.standard.OnOff.Companion.onOff
Struktury danych zdefiniowane przez cechę są importowane z klasy cechy, której nazwa kończy się ciągiem „-Trait”:
import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum
Polecenia cechy są importowane z obiektu Companion
cechy:
import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold