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 jest domyślnym typem przepływu automatyzacji.
Oto bardzo prosty szablon DSL automatyzacji, który korzysta z sekwencyjnego przepływu składającego się z elementu początkowego, warunku i działania:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
action {...}
}
Możesz to poprawić, dodając kolejne węzły.
Początkujący
Węzły początkowe 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ż jeden element początkowy, musisz użyć węzła select.
Starter na podstawie atrybutu cechy
Podczas deklarowania węzła początkowego opartego na atrybucie cechy podaj:
- 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. Urządzenie może się np. składać z FanDeviceType i HeatingCoolingUnitDeviceType, które zawierają cechę OnOffTrait. Określenie typu urządzenia eliminuje niejasności co do tego, która część urządzenia wywołuje automatyzację.
Lista startowa na podstawie wydarzenia
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
)
Wstępna konfiguracja na podstawie struktury i zdarzenia z parametrami
Niektóre zdarzenia mogą mieć parametry, więc te parametry też muszą być uwzględnione w wersji początkowej.
Na przykład ten starter używa polecenia 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))
}
Rozrusznik ręczny
Ręczny wyzwalacz to specjalny typ wyzwalacza, 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 wraz z innym poleceniem, ręczne polecenie zastąpi to drugie:
select {
manualStarter()
starter(
thermostat,
Matter.TemperatureSensorDeviceType.self,
Matter.TemperatureMeasurementTrait.self
)
}
Pamiętaj, że wszystkie conditionwęzły następujące po ręcznym węźle początkowym zostaną sprawdzone i mogą zablokować wykonanie automatyzacji w zależności od conditionwyrażenia.
Jednym ze sposobów na skonstruowanie automatyzacji tak, aby węzły condition nie blokowały automatyzacji aktywowanej za pomocą ręcznego polecenia, jest umieszczenie innego polecenia 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ę:
Za pomocą stateReader:
typealias TimeTrait = Google.TimeTrait
let time = stateReader(structure, TimeTrait.self)
time
let currTime = time.currentTime
Za pomocą 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 warunków i wyrażenia
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ływać się do wartości cechy, do której dostęp uzyskano za pomocą elementu początkowego:
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 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")
}