Z tego przewodnika dowiesz się, jak tworzyć automatyzacje za pomocą różnych węzłów automatyzacji DSL.
Cały kod DSL automatyzacji jest umieszczony w pojedynczym węźle automation
. automation
stanowi granicę między zewnętrznym kontekstem języka Kotlin a osadzonym kontekstem DSL.
Sekwencyjny przepływ
Sekwencyjny to domyślny typ procedury automatyzacji.
Oto bardzo prosty szablon automatyzacji DSL, który używa sekwencyjnego przepływu, składającego się z elementu startowego, 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żna to doprecyzować, dodając dodatkowe węzły.
Początkujący
Początkowe węzły definiują początkowe okoliczności, które aktywują automatyzację. na przykład zmiana stanu lub wartości. Automatyzacja musi mieć co najmniej 1 element inicjujący, w przeciwnym razie nie przejdzie walidacji. Aby dodać do automatyzacji więcej niż 1 element inicjujący, musisz użyć węzła wyboru.
Starter na podstawie atrybutu cech
Podczas deklarowania węzła startowego opartego na atrybucie cechy podaj:
- urządzenie
- typ urządzenia, do którego należy cecha;
- cecha
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
Parametr device type jest wymagany, ponieważ pozwala określić, który typ urządzenia ma być obsługiwany przez automatyzację. Na przykład urządzenie może składać się z FanDevice
i HeatingCoolingUnitDevice
, z których oba zawierają cechę OnOff
. Określając typ urządzenia, usuwasz niejasności dotyczące tego, która część urządzenia uruchamia automatyzację.
Starter na podstawie zdarzenia
Podczas deklarowania węzła startowego opartego na zdarzeniu podaj:
- urządzenie
- typ urządzenia, do którego należy cecha;
- wydarzenie
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)
Szablon oparty na strukturze i zdarzeniu z parametrami
Niektóre zdarzenia mogą mieć parametry, więc te parametry muszą też zostać uwzględnione w starterze.
Na przykład ten starter używa atrybutu Time
ScheduledTimeEvent
, aby aktywować automatyzację o godzinie 7:00 rano:
val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
parameter(Time.ScheduledTimeEvent.clockTime(
LocalTime.of(7, 0, 0, 0)))
}
Ręczne uruchamianie
Rozpoczęcie ręczne to specjalny typ inicjatora, który umożliwia użytkownikowi ręczne uruchamianie automatyzacji.
Podczas deklarowania ręcznego uruchamiania:
- Nie określaj cech ani typu urządzenia.
- Podaj element interfejsu, który wywołuje
Automation.execute()
.
Gdy w sekwencji select
umieścisz element inicjujący ręczny razem z innym elementem inicjującym, element inicjujący ręczny zastąpi inny element inicjujący:
select {
manualStarter()
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}
Pamiętaj, że wszystkie węzły condition
po ręcznym starterze zostaną ocenione i mogą zablokować wykonanie automatyzacji w zależności od wyrażenia condition
.
Jednym ze sposobów ustrukturyzowania automatyzacji tak, aby węzły condition
nie blokowały automatyzacji aktywowanej za pomocą ręcznego startera, jest umieszczenie drugiego startera w osobnym sekwencyjnym przepływie wraz z jego condition
:
automation_graph {
sequential {
select {
sequential {
starter<_>(...)
condition {...}
}
sequential {
manualStarter()
}
}
action {...}
}
}
Odwoływanie się do wartości atrybutu
Aby użyć wartości atrybutu w wyrażeniu, użyj tej 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 i wyrażenia warunków
Węzeł warunku reprezentuje punkt podejmowania decyzji, który decyduje, czy automatyzacja będzie kontynuowana. Automatyzacja może mieć wiele węzłów condition
.
Jeśli wyrażenie dowolnego węzła condition
ma wartość false
, kończy się wykonywanie całej automatyzacji.
W węźle condition
możesz łączyć wiele warunków za pomocą różnych operatorów, o ile wyrażenie zwraca jedną wartość logiczną. Jeśli wynikowa wartość to true
, warunek jest spełniony i 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 w Kotlinie i mogą zawierać wartości proste, takie jak liczby, znaki, ciągi tekstowe i wartości logiczne, a także wartości typu Enum. Grupowanie podwyrażeń za pomocą nawiasów pozwala kontrolować kolejność ich obliczania.
Oto przykład condition
, który łączy wiele podwyrażeń w jeden 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)
}
Wartość atrybutu możesz pobrać za pomocą startera:
val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }
stateReader
Innym sposobem na odniesienie wartości atrybutów cech w węźle condition
jest użycie węzła stateReader
.
Aby to zrobić, najpierw uchwyć wartość atrybutu cechy w kodzie stateReader
. Funkcja stateReader
przyjmuje jako argumenty structure
i cechę:
import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)
Następnie odwołuj się do elementu stateReader
w węźle condition
:
condition() {
expression =
filterMonitoringState.changeIndication
.equals(ChangeIndicationEnum.Warning)
}
Za pomocą operatorów porównawczych i operatorów logicznych możesz używać w węźle condition
wielu funkcji 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 automatyzacja mogła się wykonać. Możesz na przykład zdefiniować warunek, który będzie działać tylko wtedy, gdy światło było włączone przez 10 minut.
condition {
expression(lightStateReader.onOff == true)
forDuration(Duration.ofMinutes(10))
}
Czas trwania może wynosić od 1 do 30 minut.
Węzły akcji
W węźle działania odbywa się automatyzacja.
W tym przykładzie działanie wywołuje polecenie AssistantBroadcast
elementu broadcast()
:
action(device, SpeakerDevice) {
command(AssistantBroadcast.broadcast("Intruder detected!"))
}
Importowanie wyciągów
Podczas tworzenia automatyzacji nie zawsze wiadomo, jak zaimportować do kodu różne elementy interfejsów API Home.
Atrybuty cech są importowane z obiektu Companion
danej cechy:
import com.google.home.matter.standard.OnOff.Companion.onOff
Struktury danych zdefiniowane przez cechę są importowane z klasy cech, której nazwa kończy się na „-Trait”:
import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum
Polecenia cech są importowane z obiektu Companion
danej cechy:
import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold