Z tego przewodnika dowiesz się, jak można wykorzystać różne węzły języka DSL automatyzacji do tworzenia automatyzacji.
Cały DSL automatyzacji jest umieszczony w jednym węźle automation. Węzeł automation tworzy granicę między zewnętrznym kontekstem języka Kotlin a wbudowanym kontekstem DSL.
Przepływ sekwencyjny
Przepływ sekwencyjny jest domyślnym typem przepływu automatyzacji.
Oto bardzo prosty szablon DSL automatyzacji, który wykorzystuje przepływ sekwencyjny składający się z elementu inicjującego, 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 go ulepszyć, dodając kolejne węzły.
Starter
Węzły poleceń inicjujących określają początkowe okoliczności, które aktywują automatyzację. Może to być na przykład zmiana stanu lub wartości. Automatyzacja musi mieć co najmniej 1 element inicjujący, inaczej nie przejdzie weryfikacji. Aby dodać do automatyzacji więcej niż 1 element inicjujący, musisz użyć węzła select.
Element inicjujący na podstawie atrybutu cechy
Podczas deklarowania węzła początkowego opartego na atrybucie cechy określ:
- urządzenie
- typ urządzenia, do którego należy cecha;
- cecha
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
Parametr typu urządzenia jest wymagany, ponieważ pozwala określić, którego typu urządzenia dotyczy automatyzacja. Na przykład urządzenie może składać się z FanDevice i HeatingCoolingUnitDevice, które zawierają cechę OnOff. Dzięki określeniu typu urządzenia nie ma wątpliwości, która część urządzenia uruchamia automatyzację.
Element inicjujący na podstawie zdarzenia
Podczas deklarowania węzła początkowego opartego na zdarzeniu podaj:
- urządzenie
- typ urządzenia, do którego należy cecha;
- wydarzenie,
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)
Element inicjujący oparty na strukturze i zdarzeniu, z parametrami
Niektóre zdarzenia mogą mieć parametry, więc te parametry również muszą być uwzględnione w uruchamianiu.
Na przykład to polecenie inicjujące używa ScheduledTimeEvent cechy Time, aby aktywować automatyzację o 7:00:
val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
parameter(Time.ScheduledTimeEvent.clockTime(
LocalTime.of(7, 0, 0, 0)))
}
Starter na podstawie pogody
Możesz określić bieżące lub prognozowane warunki pogodowe w uruchamianiu, używając cechy Pogoda:
val weatherState = starter<_>(structure, trait = Weather)
Zobacz Zamykanie rolet, gdy prawdopodobnie będzie padać na stronie Przykładowe automatyzacje.
Uruchamianie ręczne
Warunek inicjujący ręcznie to specjalny typ warunku inicjującego, który umożliwia użytkownikowi ręczne uruchomienie automatyzacji.
Podczas deklarowania ręcznego elementu inicjującego:
- Nie podawaj cechy ani typu urządzenia.
- Udostępnij element interfejsu, który wywołuje metodę
Automation.execute().
Jeśli umieścisz ręczny element inicjujący w przepływie select wraz z innym elementem inicjującym, ręczny element inicjujący zastąpi ten drugi:
select {
manualStarter()
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}
Pamiętaj, że wszystkie węzły condition po elemencie inicjującym ręcznie zostaną ocenione i mogą zablokować wykonanie automatyzacji, w zależności od wyrażenia condition.
Jednym ze sposobów na skonfigurowanie automatyzacji tak, aby węzły condition nie blokowały automatyzacji aktywowanej za pomocą ręcznego aktywatora, jest umieszczenie drugiego aktywatora w osobnym przepływie sekwencyjnym 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 warunku
Węzeł warunku reprezentuje punkt decyzyjny, który określa, czy automatyzacja ma być kontynuowana. Automatyzacja może mieć wiele węzłów condition.
Jeśli wyrażenie dowolnego węzła condition zostanie ocenione jako false, wykonywanie całej automatyzacji zostanie zakończone.
W węźle condition możesz łączyć wiele kryteriów warunków za pomocą różnych operatorów, o ile wyrażenie daje 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 podstawowe, takie jak liczby, znaki, ciągi znaków i wartości logiczne, a także wartości typu wyliczeniowego. Grupowanie podwyrażeń za pomocą nawiasów pozwala kontrolować kolejność ich oceny.
Oto przykład condition, który łączy kilka 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łać się do wartości cechy, do której dostęp uzyskano za pomocą elementu inicjującego:
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 operatorów logicznych można używać wielu stateReaders w węźle condition:
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 stanu
Oprócz wyrażenia logicznego w warunku możesz określić przedział czasu, w którym wyrażenie musi być prawdziwe, aby automatyzacja została uruchomiona. Możesz na przykład zdefiniować warunek, który będzie aktywowany tylko wtedy, gdy światło będzie włączone przez 10 minut.
condition {
expression(lightStateReader.onOff == true)
forDuration(Duration.ofMinutes(10))
}
Czas trwania może wynosić od 5 sekund do 24 godzin.
Węzły działań
Węzeł działania to miejsce, w którym odbywa się praca automatyzacji.
W tym przykładzie działanie wywołuje polecenie broadcast() cechy AssistantBroadcast:
action(device, SpeakerDevice) {
command(AssistantBroadcast.broadcast("Intruder detected!"))
}
Instrukcje importu
Podczas tworzenia automatyzacji nie zawsze jest oczywiste, jak zaimportować różne elementy interfejsów API Google Home do kodu.
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ę na „-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