Język DSL automatyzacji umożliwia tworzenie bardziej złożonych automatyzacji niż te omówione w przewodniku po DSL – podstawowe automatyzacje na Androidzie.
Sekwencyjne z wieloma działaniami
Automatyzacja może wykonywać więcej niż jedną czynność. Na przykład zamiast pojedynczego węzła action możesz mieć kilka węzłów action, które są uruchamiane w kolejności sekwencyjnej:
automation {
sequential {
starter<_>(...)
condition {...}
action {...}
action {...}
action {...}
}
}
Sekwencyjne z wieloma działaniami równoległymi
Jeśli umieścisz kilka węzłów action w węźle parallel, działania będą wykonywane równocześnie.
automation {
sequential {
starter<_>(...)
condition {...}
parallel {
action {...}
action {...}
action {...}
}
}
}
Jeśli w węźle sequential znajdują się węzły action, które występują po węźle parallel, czekają one na wykonanie, aż wszystkie węzły w węźle parallel zostaną wykonane.
Wykonanie warunkowe
Domyślnie automatyzacja wykonuje węzły sekwencyjnie lub równolegle. Jeśli potrzebujesz logiki rozgałęziania warunkowego – wykonywania różnych działań lub ścieżek na podstawie warunków środowiska wykonawczego – użyj instrukcji if-then-else, które są tworzone za pomocą bloków DSL przepływu sterowania warunkowego:ifThen,elseIfiorElse.
Standardowy węzeł condition blokuje całą automatyzację (jeśli warunek ma wartość false, automatyzacja natychmiast się kończy), a bloki ifThen umożliwiają rozgałęzianie przepływu sterowania:
- Węzeł
condition: zatrzymuje wykonanie całej automatyzacji (lub bieżącej ścieżki wykonania), jeśli wyrażenie ma wartośćfalse. ifThen/elseIf/orElse: ocenia warunki w kolejności. Jeśli warunek ma wartośćfalse, wykonanie przechodzi do następnej gałęzielseIf, gałęzi rezerwowejorElselub kontynuuje do kolejnych węzłów w automatyzacji, jeśli żaden warunek nie jest spełniony.
Wykonywanie działania na podstawie warunku
Blok ifThen ocenia wyrażenie warunkowe. Jeśli wyrażenie ma wartość true, wykonywane są działania lub węzły DSL zagnieżdżone w bloku. Jeśli ma wartość false, działania są pomijane, a automatyzacja przechodzi do kolejnych węzłów w przepływie sekwencyjnym.
Możesz użyć samodzielnego bloku ifThen, gdy chcesz wykonać działanie warunkowo bez blokowania lub kończenia kolejnych węzłów w automatyzacji:
// When a door opens, turn on the light only if it is off,
// and always broadcast an announcement.
automation {
sequential {
val contactState = starter<_>(
contactSensor,
ContactSensorDevice,
BooleanState,
)
val lightState = stateReader<_>(
light,
DimmableLightDevice,
OnOff,
)
condition {
// Door opened (contact sensor open)
expression = contactState.stateValue equals false
}
// Conditionally turn on the light if it's off
ifThen(lightState.onOff equals false) {
action(light, DimmableLightDevice) { command(OnOff.on()) }
}
// Continue executing subsequent actions in the sequential flow
action(structure) {
command(AssistantBroadcast.broadcast("The door was opened."))
}
}
}
Wykonywanie różnych działań na podstawie warunku
Aby wykonać jeden zestaw działań, gdy warunek jest spełniony, i alternatywny zestaw działań, gdy nie jest spełniony, połącz opcjonalny blok .orElse { ... } z blokiem ifThen(...) { ... }:
// When the door is unlocked, turn on the entryway light if it is off;
// otherwise, broadcast a welcome message.
automation {
sequential {
val doorLockEvent = starter<_>(
doorLock,
DoorLockDevice,
LockOperationEvent,
)
val lightState = stateReader<_>(
light,
DimmableLightDevice,
OnOff,
)
condition {
expression =
doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock
}
ifThen(lightState.onOff equals false) {
action(light, DimmableLightDevice) { command(OnOff.on()) }
}.orElse {
action(structure) {
command(AssistantBroadcast.broadcast("Welcome home!"))
}
}
}
}
Łączenie wielu warunków w sekwencji
Możesz połączyć jeden lub więcej opcjonalnych bloków .elseIf(...) { ... }, aby ocenić wiele warunków w sekwencji. Wykonana zostanie pierwsza gałąź, której warunek ma wartość true, a wszystkie pozostałe gałęzie zostaną pominięte. Jeśli żaden z warunków nie ma wartości true, wykonywany jest opcjonalny blok .orElse { ... } (jeśli jest dostępny):
// Adjust climate controls based on room temperature changes.
automation {
sequential {
val tempStarter = starter<_>(
tempSensor,
TemperatureSensorDevice,
TemperatureMeasurement,
)
// If temperature is high (>= 28°C / 2800 mC), switch thermostat to Cool mode
ifThen(tempStarter.measuredValue greaterThanOrEquals 2800) {
action(thermostat, ThermostatDevice) {
command(
SimplifiedThermostat.setSystemMode(
SimplifiedThermostatSystemModeEnum.Cool
)
)
}
}.elseIf(tempStarter.measuredValue lessThan 1800) {
// If temperature is low (< 18°C / 1800 mC), switch to Heat mode
action(thermostat, ThermostatDevice) {
command(
SimplifiedThermostat.setSystemMode(
SimplifiedThermostatSystemModeEnum.Heat
)
)
}
}.orElse {
// Otherwise, turn on the fan
action(fan, FanDevice) {
command(OnOff.on())
}
}
}
}
Zagnieżdżone przepływy warunkowe
Bloki warunkowe można zagnieżdżać w innych blokach ifThen, elseIf lub orElse, a także łączyć z węzłami parallel, delayFor i stateReader.
Bloki ifThen, elseIf i orElse wykonują swoją zawartość jako przepływy sekwencyjne. W każdej gałęzi możesz umieścić dowolne węzły sekwencyjne, w tym bloki action, stateReader, parallel, delayFor i zagnieżdżone bloki ifThen.
Opóźnienia
W automatyzacjach możesz wprowadzać przerwy za pomocą słowa kluczowego
delayFor
, które przyjmuje argument
java.time.Duration
określający, jak długo ma trwać wstrzymanie przed kontynuowaniem wykonania. Czas wstrzymania może wynosić od 5 sekund do 24 godzin.
Aby na przykład przełączyć światło 4 razy z 5-sekundową przerwą między każdym przełączeniem:
sequential {
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
Tłumienie reguły
Tłumienie reguły to funkcja, która umożliwia automatyzacji ignorowanie starter przez określony czas po początkowym zdarzeniu wyzwalającym. Jeśli na przykład automatyzacja ma starter, który jest wyzwalany przez wykrycie ruchu, a Ty określisz czas tłumienia reguły na 5 minut, to gdy starter zostanie wyzwolony, nie zostanie wyzwolony ponownie przez następne 5 minut. Zapobiega to szybkiemu i powtarzającemu się wyzwalaniu automatyzacji.
Aby zastosować tłumienie reguły w automatyzacji, użyj słowa kluczowego
suppressFor
z argumentem
java.time.Duration
określającym, jak długo należy czekać przed zareagowaniem na kolejne reguły.
Czas tłumienia może wynosić od 5 sekund do 24 godzin.
automation {
sequential {
val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
suppressFor(Duration.ofMinutes(30))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
Pamiętaj, że tłumienie aktywatora wpływa na wszystkie starters w automatyzacji, które poprzedzają suppressFor.
Ograniczanie liczby uruchomień
Możesz ograniczyć liczbę uruchomień automatyzacji.
Możesz na przykład skonfigurować jednorazową automatyzację, która uruchamia odkurzacz, gdy nie ma Cię w domu.
Aby to zrobić, ustaw pole metadanych automatyzacji
maxExecutionCount.
Poniższy przykład to automatyzacja, która może być wykonana tylko raz:
automation { // The automation can only be executed once. maxExecutionCount = 1 // When the door lock state changes sequential { val doorLockEvent = starter<_>(doorLock, DoorLockDevice, LockOperationEvent) // if the door is unlocked condition() { expression = (doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock) } // turn the light on action(light, DimmableLightDevice) { command(OnOff.on()) } } }
Automatyzacja jest natychmiast usuwana po ostatnim wykonaniu i osiągnięciu wartości maxExecutionCount. Wpis historii automatyzacji pozostaje
na karcie Google Home app (GHA) Aktywność, w tym automation_id.
Ustawianie atrybutów cechy w działaniu
Aby ustawić wartość atrybutu cechy:
- Utwórz węzeł
updatew węźleaction, w tym odpowiednią cechę jako argument węzłaupdate:action(deviceReference, deviceType) { update(trait) { } } - W węźle
updatedla każdego atrybutu, który ma zostać zmodyfikowany, użyj funkcji mutatora i przekaż jej nową wartość. Aby utworzyć nazwę funkcji mutatora:- Zacznij nazwę atrybutu od wielkiej litery.
- Dodaj przed nią słowo
set.
defaultMoveRate, użyj funkcji mutatora o nazwiesetDefaultMoveRate.
Pamiętaj, że węzeł update może mieć wiele funkcji mutatora. Oto przykład, w którym aktualizowane są 2 atrybuty:
action(device, Fan) {
update(FanControl) {
setPercentSetting(50u)
setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
}
}