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 Swift 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 polecenia inicjującego, warunku i działania:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
action {...}
}
Możesz to poprawić, dodając kolejne węzły.
Starter
Węzły poleceń inicjujących 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ż jedno polecenie inicjujące, musisz użyć węzła select.
Starter 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,
Matter.TemperatureSensorDeviceType.self,
Matter.TemperatureMeasurementTrait.self
)
Parametr typu urządzenia jest wymagany, ponieważ umożliwia określenie, do którego typu urządzenia w ramach urządzenia odnosi się automatyzacja. Na przykład urządzenie może składać się z FanDeviceType i HeatingCoolingUnitDeviceType, z których oba zawierają cechę OnOffTrait. Określenie typu urządzenia eliminuje niejasności co do tego, która część urządzenia wywołuje automatyzację.
Polecenie inicjujące 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,
Google.GoogleDoorbellDeviceType.self,
Google.DoorbellPressTrait.DoorbellPressedEvent
)
Polecenie inicjujące na podstawie struktury i zdarzenia z parametrami
Niektóre zdarzenia mogą mieć parametry, więc te parametry też muszą być uwzględnione w poleceniu inicjującym.
Na przykład to polecenie inicjujące używa TimeTraitScheduledEvent, aby aktywować automatyzację o 7:00:
typealias TimeTrait = Google.TimeTrait
let earlyMorning = starter(
structure,
TimeTrait.ScheduledEvent.self
) {
TimeTrait.ScheduledEvent.clockTime(TimeOfDay(hours: 7, minutes: 0))
}
Starter na podstawie pogody
W poleceniach inicjujących możesz określać aktualne lub prognozowane warunki pogodowe, używając cechy Weather:
let weatherState = starter<_>(structure, trait = Weather)
Zobacz Zasłoń rolety, jeśli prawdopodobnie będzie padać deszcz na stronie Przykłady automatyzacji.
Rozrusznik ręczny
Ręczne polecenie inicjujące to specjalny typ polecenia inicjującego, 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 w przepływie select umieścisz ręczne polecenie inicjujące wraz z innym poleceniem inicjującym, ręczne polecenie inicjujące zastąpi to drugie:
select {
manualStarter()
starter(
thermostat,
Matter.TemperatureSensorDeviceType.self,
Matter.TemperatureMeasurementTrait.self
)
}
Pamiętaj, że wszystkie węzły condition następujące po ręcznym poleceniu inicjującym zostaną ocenione i mogą zablokować wykonanie automatyzacji w zależności od wyrażenia condition.
Jednym ze sposobów na skonstruowanie automatyzacji tak, aby węzły condition nie blokowały automatyzacji aktywowanej za pomocą ręcznego polecenia inicjującego, jest umieszczenie innego polecenia inicjującego w osobnym przepływie sekwencyjnym wraz z węzłem condition:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
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ę:
Z stateReader:
typealias TimeTrait = Google.TimeTrait
let time = stateReader(structure, TimeTrait.self)
time
let currTime = time.currentTime
Z starter:
typealias LaundryWasherDeviceType = Matter.LaundryWasherDeviceType
typealias OnOffTrait = Google.OnOffTrait
let starterNode = starter(device1, LaundryWasherDeviceType.self, OnOffTrait.self)
starterNode
condition {
starterNode.onOff.equals(true)
}
Węzły i wyrażenia warunku
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 jedną 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 Swift 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 {
let exp1 = starterNode.lockState.equals(.unlocked)
let exp2 = stateReaderNode.lockState.equals(true)
let exp3 = occupancySensingDevice.occupied.notEquals(0)
(exp1.and(exp2)).or(exp3)
}
Możesz odwołać się do wartości cechy, do której dostęp uzyskano za pomocą polecenia inicjującego:
typealias OnOffTrait = Matter.OnOffTrait
let starterNode = starter(device, OnOffTrait.self)
starterNode
condition {
starterNode.onOff.equals(true)
}
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 A
stateReader przyjmuje jako argumenty structure i cechę:
typealias ActivatedCarbonFilterMonitoringTrait = Matter.ActivatedCarbonFilterMonitoringTrait
let filterMonitoringState = stateReader(structure, ActivatedCarbonFilterMonitoringTrait.self)
Następnie odwołaj się do stateReader w węźle condition:
condition {
filterMonitoringState.changeIndication.equals(.warning)
}
Za pomocą operatorów porównania i logicznych w węźle condition można użyć wielu operatorów stateReaders:
typealias ArmDisarm = Google.ArmDisarmTrait
typealias DoorLockDevice = Matter.DoorLockDeviceType
typealias DoorLock = Matter.DoorLockTrait
let armState = stateReader(doorLock, DoorLockDevice.self, ArmDisarm )
let doorLockState = stateReader(doorLock, DoorLockDevice.self, DoorLock)
armState
doorLockState
condition {
let exp1 = armState.armState
let exp2 = doorLockState.lockState
exp1.and(exp2)
}
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 przez 10 minut.
condition(for: .seconds(600)) {
lightStateReader.onOff.equals(true)
}
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 AssistantBroadcastTraitbroadcast():
action(speaker, SpeakerDeviceType.self) {
Google.AssistantBroadcastTrait.broadcast(msg: "Oven Cycle Complete")
}