Z tego przewodnika dowiesz się, jak używać różnych węzłów Automation DSL do tworzenia automatyzacji.
Cały kod Automation DSL 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 podstawowy szablon Automation DSL, który korzysta z przepływu sekwencyjnego składającego się z polecenia inicjującego, warunku i działania:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
action {...}
}
Możesz go udoskonalić, dodając dodatkowe węzły.
Polecenie inicjujące
Węzły polecenia inicjującego określają początkowe okoliczności, które aktywują automatyzację. Może to być np. zmiana stanu lub wartości. Automatyzacja musi mieć co najmniej 1 polecenie inicjujące, w przeciwnym razie nie przejdzie weryfikacji. Aby dodać do automatyzacji więcej niż 1 polecenie inicjujące, musisz użyć węzła select.
Polecenie inicjujące na podstawie atrybutu cechy
Deklarując węzeł polecenia inicjującego, który jest oparty na atrybucie cechy, określ:
- urządzenie,
- typ urządzenia, do którego należy cecha,
- cechę.
starter(
thermostat,
Matter.TemperatureSensorDeviceType.self,
Matter.TemperatureMeasurementTrait.self
)
Parametr typu urządzenia jest wymagany, ponieważ pozwala określić, do którego typu urządzenia w urządzeniu odnosi się automatyzacja. Urządzenie może się np. składać z
FanDeviceType
i
HeatingCoolingUnitDeviceType,
z których oba zawierają cechę
OnOffTrait
. Określenie typu urządzenia eliminuje niejednoznaczność co do tego, która część urządzenia wywołuje automatyzację.
Polecenie inicjujące na podstawie zdarzenia
Deklarując węzeł polecenia inicjującego, który jest oparty na zdarzeniu, określ:
- urządzenie,
- typ urządzenia, do którego należy cecha,
- zdarzenie.
starter(
doorbell,
Google.GoogleDoorbellDeviceType.self,
Google.DoorbellPressTrait.DoorbellPressedEvent
)
Polecenie inicjujące na podstawie struktury i zdarzenia z parametrami
Niektóre zdarzenia mogą mieć parametry, dlatego należy je uwzględnić w poleceniu inicjującym.
Na przykład to polecenie inicjujące używa
TimeTrait's ScheduledEvent
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))
}
Polecenie inicjujące na podstawie pogody
W poleceniu inicjującym możesz określić aktualne lub prognozowane warunki pogodowe za pomocą cechy Weather:
let weatherState = starter<_>(structure, trait = Weather)
Na stronie Przykłady automatyzacji znajdziesz przykład Close the blinds if it is likely to rain (Zamknij rolety, jeśli prawdopodobnie będzie padać).
Ręczne polecenie inicjujące
Ręczne polecenie inicjujące to specjalny typ polecenia inicjującego, który umożliwia użytkownikowi ręczne uruchomienie automatyzacji.
Deklarując ręczne polecenie inicjujące:
- Nie określaj cechy ani typu urządzenia.
- Podaj element interfejsu, który wywołuje
Automation.execute().
Jeśli umieścisz ręczne polecenie inicjujące w przepływie select wraz z innym poleceniem inicjującym, ręczne polecenie inicjujące zastąpi inne polecenie inicjujące:
select {
manualStarter()
starter(
thermostat,
Matter.TemperatureSensorDeviceType.self,
Matter.TemperatureMeasurementTrait.self
)
}
Pamiętaj, że wszystkie węzły condition znajdujące się za ręcznym poleceniem 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 ręcznym poleceniem inicjującym, jest umieszczenie innego polecenia inicjującego w osobnym przepływie sekwencyjnym wraz z jego condition:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
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.
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 i wyrażenia warunków
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 przyjmuje pojedynczą wartość logiczną. Jeśli wartość wynikowa to true, warunek jest spełniony, a automatyzacja kontynuuje wykonywanie następnego węzła. Jeśli wartość to false, automatyzacja zatrzymuje się 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 znaków i wartości logiczne, a także wartości wyliczeniowe. Grupowanie wyrażeń podrzędnych za pomocą nawiasów pozwala kontrolować kolejność ich oceniania.
Oto przykład condition, który łączy wiele wyrażeń podrzędnych 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ą 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 na odwoływanie 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. 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)
}
W węźle condition można używać wielu stateReaders za pomocą operatorów porównania
i
logicznych:
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 można było uruchomić automatyzację. Możesz np. zdefiniować warunek, który uruchamia się tylko wtedy, gdy światło jest włączone przez 10 minut.
condition(for: .seconds(600)) {
lightStateReader.onOff.equals(true)
}
Czas trwania może wynosić od 1 do 30 minut.
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
AssistantBroadcastTrait's
broadcast() polecenie:
action(speaker, SpeakerDeviceType.self) {
Google.AssistantBroadcastTrait.broadcast(msg: "Oven Cycle Complete")
}