Za pomocą języka DSL automatyzacji można tworzyć automatyzacje bardziej złożone niż te omówione w przewodniku po języku DSL – podstawowe automatyzacje na iOS.
Sekwencyjne z wieloma działaniami
Automatyzacja może wykonywać więcej niż 1 czynność. Na przykład zamiast pojedynczego węzła action możesz mieć wiele węzłów action, które działają w kolejności sekwencyjnej:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
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 jednocześnie.
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
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, dopóki nie zostaną wykonane wszystkie węzły w węźle parallel.
Wykonywanie warunkowe
Domyślnie automatyzacja wykonuje węzły sekwencyjnie lub równolegle. Jeśli potrzebujesz logiki rozgałęziania warunkowego, która wykonuje różne działania lub ścieżki na podstawie warunków środowiska wykonawczego, użyj instrukcji if-then-else, które są tworzone za pomocą bloków DSL warunkowego przepływu sterowania: ifThen, elseIf i orElse.
Standardowy węzeł condition blokuje całą automatyzację (jeśli warunek ma wartość false, automatyzacja natychmiast kończy działanie), natomiast bloki ifThen umożliwiają rozgałęzianie przepływu sterowania:
- Węzeł
condition: zatrzymuje wykonywanie całej automatyzacji (lub bieżącej ścieżki wykonywania), jeśli wyrażenie ma wartośćfalse. ifThen/elseIf/orElse: ocenia warunki w kolejności. Jeśli warunek jestfalse, wykonanie przechodzi do następnej gałęzielseIf, gałęzi zastępczejorElselub 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, działania lub węzły DSL zagnieżdżone w bloku są wykonywane. Jeśli wynik to false, działania są pomijane, a automatyzacja przechodzi do kolejnych węzłów w sekwencji.
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.
typealias ContactSensorDevice = Matter.ContactSensorDeviceType
typealias BooleanStateTrait = Matter.BooleanStateTrait
typealias DimmableLightDevice = Matter.DimmableLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait
automation {
let contactState = starter(
contactSensor,
ContactSensorDevice.self,
BooleanStateTrait.self
)
let lightState = stateReader(
light,
DimmableLightDevice.self,
OnOffTrait.self
)
contactState
lightState
condition {
// Door opened (contact sensor open)
contactState.stateValue.equals(false)
}
// Conditionally turn on the light if it's off
ifThen(lightState.onOff.equals(false)) {
action(light, DimmableLightDevice.self) {
OnOffTrait.on()
}
}
// Continue executing subsequent actions in the sequential flow
action(structure) {
Google.AssistantBroadcastTrait.broadcast(msg: "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 warunek nie jest spełniony, połącz opcjonalny blok .orElse { ... } po ifThen(...) { ... }:
// When the door is unlocked, turn on the entryway light if it is off;
// otherwise, broadcast a welcome message.
typealias DoorLockDevice = Matter.DoorLockDeviceType
typealias DoorLockTrait = Matter.DoorLockTrait
typealias DimmableLightDevice = Matter.DimmableLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait
automation {
let doorLockEvent = starter(
doorLock,
DoorLockDevice.self,
DoorLockTrait.LockOperationEvent.self
)
let lightState = stateReader(
light,
DimmableLightDevice.self,
OnOffTrait.self
)
doorLockEvent
lightState
condition {
doorLockEvent.lockOperationType.equals(.unlock)
}
ifThen(lightState.onOff.equals(false)) {
action(light, DimmableLightDevice.self) {
OnOffTrait.on()
}
}.orElse {
action(structure) {
Google.AssistantBroadcastTrait.broadcast(msg: "Welcome home!")
}
}
}
Łączenie wielu warunków w sekwencję
Możesz połączyć co najmniej 1 opcjonalny blok .elseIf(...) { ... }, aby ocenić kilka warunków po kolei. Wykonywana jest pierwsza gałąź, której warunek ma wartość true, a wszystkie pozostałe gałęzie są pomijane. Jeśli żaden z warunków nie ma wartości true, wykonywany jest opcjonalny blok .orElse { ... } (jeśli został podany):
// Adjust climate controls based on room temperature changes.
typealias TemperatureSensorDeviceType = Matter.TemperatureSensorDeviceType
typealias TemperatureMeasurementTrait = Matter.TemperatureMeasurementTrait
typealias ThermostatDeviceType = Matter.ThermostatDeviceType
typealias SimplifiedThermostatTrait = Google.SimplifiedThermostatTrait
typealias FanDeviceType = Matter.FanDeviceType
typealias OnOffTrait = Matter.OnOffTrait
automation {
let tempStarter = starter(
tempSensor,
TemperatureSensorDeviceType.self,
TemperatureMeasurementTrait.self
)
tempStarter
// If temperature is high (>= 28°C / 2800 mC), switch thermostat to Cool mode
ifThen(tempStarter.measuredValue.greaterThanOrEquals(2800)) {
action(thermostat, ThermostatDeviceType.self) {
SimplifiedThermostatTrait.setSystemMode(systemMode: .cool)
}
}.elseIf(tempStarter.measuredValue.lessThan(1800)) {
// If temperature is low (< 18°C / 1800 mC), switch to Heat mode
action(thermostat, ThermostatDeviceType.self) {
SimplifiedThermostatTrait.setSystemMode(systemMode: .heat)
}
}.orElse {
// Otherwise, turn on the fan
action(fan, FanDeviceType.self) {
OnOffTrait.on()
}
}
}
Zagnieżdżone automatyzacje warunkowe
Bloki warunkowe można zagnieżdżać w innych blokach ifThen, elseIf lub orElse, a także łączyć z węzłami parallel, delay(for:) i stateReader.
Bloki ifThen, elseIf i orElse wykonują swoją zawartość jako sekwencyjne przepływy. W każdej gałęzi możesz umieścić dowolne węzły sekwencyjne, w tym bloki action, stateReader, parallel, delay(for:) i zagnieżdżone bloki ifThen.
Opóźnienia
Możesz wprowadzić przerwy w automatyzacji, używając metody delay(for:), która przyjmuje argument Duration określający, jak długo ma trwać przerwa przed kontynuowaniem wykonywania. 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:
typealias OnOffLightDevice = Matter.OnOffLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait
sequential {
action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
delay(for:.seconds(5))
action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
delay(for:.seconds(5))
action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
delay(for:.seconds(5))
action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
}
Pomijanie aktywatora
Blokowanie aktywacji to funkcja, która pozwala automatyzacji ignorować starter przez określony czas po początkowym zdarzeniu aktywującym. Jeśli na przykład automatyzacja ma starter, który jest aktywowany przez wykrycie ruchu, i określisz czas blokowania aktywacji na 5 minut, to po aktywowaniu starter nie zostanie on ponownie aktywowany przez kolejne 5 minut. Zapobiega to wielokrotnemu uruchamianiu automatyzacji w krótkim czasie.
Aby zastosować blokowanie aktywacji w automatyzacji, użyj słowa kluczowego suppress(for:) z argumentem Duration, który określa, jak długo należy czekać przed reagowaniem na kolejne aktywacje.
Czas wyciszenia może wynosić od 5 sekund do 24 godzin.
typealias OccupancySensorDevice = Matter.OccupancySensorDeviceType
typealias OnOffLightDevice = Matter.OnOffLightDeviceType
typealias MotionDetectionTrait = Google.MotionDetectionTrait
typealias OnOffTrait = Matter.OnOffTrait
automation {
let starterNode = starter(device, OccupancySensorDevice.self, MotionDetectionTrait.self)
starterNode
suppress(for: .seconds(30 * 60)) // 30 minutes
action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
}
Pamiętaj, że pominięcie reguły wpływa na wszystkie starters w automatyzacji, które poprzedzają Suppression.
Ograniczanie liczby uruchomień
Możesz ograniczyć liczbę uruchomień automatyzacji.
Możesz na przykład skonfigurować jednorazową automatyzację, która uruchomi odkurzacz, gdy nie będzie Cię w domu.
Aby to zrobić, ustaw pole metadanych maxExecutionCount automatyzacji.
Poniższy przykład przedstawia automatyzację, która może zostać wykonana tylko raz:
import GoogleHomeSDK
import GoogleHomeTypes
typealias RoboticVacuumCleanerDevice = Matter.RoboticVacuumCleanerDeviceType
typealias RvcRunModeTrait = Matter.RvcRunModeTrait
typealias AreaPresenceStateTrait = Google.AreaPresenceStateTrait
let draftAutomation = automation(
name: "Vacuum home away",
description: "Run the vacuum once when everyone is away.",
maxExecutionCount: 1
) {
let homeAwayState = starter(structure, AreaPresenceStateTrait.self)
homeAwayState
condition {
homeAwayState.presenceState.equals(.presenceStateVacant)
}
action(vacuum, RoboticVacuumCleanerDevice.self) {
RvcRunModeTrait.changeToMode(newMode: 1)
}
}
Automatyzacja zostanie natychmiast usunięta po ostatnim uruchomieniu i osiągnięciu wartości maxExecutionCount. Wpis dotyczący historii automatyzacji pozostanie na karcie Google Home app (GHA) Aktywność, w tym automation_id.
Ustawianie atrybutów cech w działaniu
Aby ustawić wartość atrybutu cechy:
- Utwórz węzeł
updatew węźleaction, podając 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:- Zapisuj nazwę atrybutu wielką literą.
- Dodaj przed nim 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:
typealias FanDeviceType = Matter.FanDeviceType
typealias FanControlTrait = Matter.FanControlTrait
action(fan, FanDeviceType.self) {
update(FanControlTrait.self) {
$0.setFanMode(.on)
}
}