Используйте следующее руководство, чтобы понять, как различные узлы Automation DSL могут быть использованы для построения автоматизации.
Все DSL-документы автоматизации размещаются в одном узле automation
. Узел automation
образует границу между внешним языковым контекстом Swift и встроенным контекстом DSL.
Последовательный поток
Последовательный поток является типом потока автоматизации по умолчанию.
Вот очень простой шаблон Automation DSL, который использует последовательный поток, состоящий из стартера, условия и действия:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
action {...}
}
Его можно усовершенствовать, добавив дополнительные узлы.
Стартер
Узлы-стартеры определяют начальные условия активации автоматизации. Например, изменение состояния или значения. У автоматизации должен быть хотя бы один стартер, иначе она не пройдет валидацию. Чтобы добавить в автоматизацию более одного стартера, необходимо использовать узел select
.
Стартер на основе атрибута черты характера
При объявлении начального узла, основанного на атрибуте черты, укажите:
- устройство
- тип устройства, к которому принадлежит признак
- черта
starter(
thermostat,
Matter.TemperatureSensorDeviceType.self,
Matter.TemperatureMeasurementTrait.self
)
Параметр типа устройства является обязательным, поскольку он позволяет указать, к какому типу устройств внутри устройства относится автоматизация. Например, устройство может состоять из двух типов: FanDeviceType
и HeatingCoolingUnitDeviceType
, оба из которых содержат свойство OnOffTrait
. Указание типа устройства исключает неоднозначность в отношении того, какая часть устройства запускает автоматизацию.
Стартер на основе события
При объявлении стартового узла, основанного на событии, укажите:
- устройство
- тип устройства, к которому принадлежит признак
- событие
starter(
doorbell,
Google.GoogleDoorbellDeviceType.self,
Google.DoorbellPressTrait.DoorbellPressedEvent
)
Стартер на основе структуры и события с параметрами
Некоторые события могут иметь параметры, поэтому эти параметры также необходимо включить в стартер.
Например, этот стартер использует ScheduledEvent
TimeTrait
для активации автоматизации в 7:00 утра:
typealias TimeTrait = Google.TimeTrait
let earlyMorning = starter(
structure,
TimeTrait.ScheduledEvent.self
) {
TimeTrait.ScheduledEvent.clockTime(TimeOfDay(hours: 7, minutes: 0))
}
Ручной стартер
Ручной пускатель — это особый тип пускателя, который позволяет пользователю вручную запускать автоматику.
При объявлении ручного стартера:
- Не указывайте характеристику или тип устройства.
- Предоставьте элемент пользовательского интерфейса, который вызывает
Automation.execute()
.
При размещении ручного пускателя в select
потоке вместе с другим пускателем ручной пускатель имеет приоритет над другим пускателем:
select {
manualStarter()
starter(
thermostat,
Matter.TemperatureSensorDeviceType.self,
Matter.TemperatureMeasurementTrait.self
)
}
Обратите внимание, что любые узлы condition
, следующие за ручным пускателем, будут оценены и могут заблокировать выполнение автоматизации в зависимости от выражения condition
.
Один из способов структурировать автоматизацию таким образом, чтобы узлы condition
не блокировали автоматизацию, активированную с помощью ручного пускателя, — поместить другой пускатель в отдельный последовательный поток вместе с его condition
:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
select {
sequential {
starter(...)
condition {...}
}
sequential {
manualStarter()
}
}
action {...}
}
Ссылка на значение атрибута
Чтобы использовать значение атрибута в выражении, используйте следующий синтаксис.
С stateReader
:
typealias TimeTrait = Google.TimeTrait
let time = stateReader(structure, TimeTrait.self)
time
let currTime = time.currentTime
Со starter
:
typealias LaundryWasherDeviceType = Matter.LaundryWasherDeviceType
typealias OnOffTrait = Google.OnOffTrait
let starterNode = starter(device1, LaundryWasherDeviceType.self, OnOffTrait.self)
starterNode
condition {
starterNode.onOff.equals(true)
}
Условные узлы и выражения
Узел условия представляет собой точку принятия решения, которая определяет, будет ли продолжена автоматизация. Автоматизация может иметь несколько узлов condition
. Если выражение любого узла condition
принимает значение false
, выполнение всей автоматизации завершается.
В узле condition
можно комбинировать несколько условий с помощью различных операторов , при условии, что выражение возвращает одно логическое значение. Если результирующее значение равно true
, условие выполняется, и автоматизация продолжает выполнение следующего узла. Если оно равно false
, автоматизация останавливает выполнение в этой точке.
Выражения формируются аналогично выражениям в Swift и могут содержать примитивные значения, такие как числа, символы, строки и логические значения, а также значения Enum. Группировка подвыражений с помощью скобок позволяет контролировать порядок их вычисления.
Вот пример condition
, которое объединяет несколько подвыражений в одно выражение:
condition {
let exp1 = starterNode.lockState.equals(.unlocked)
let exp2 = stateReaderNode.lockState.equals(true)
let exp3 = occupancySensingDevice.occupied.notEquals(0)
(exp1.and(exp2)).or(exp3)
}
Вы можете ссылаться на значение признака, доступ к которому осуществляется через стартер:
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
Другой способ ссылки на значения атрибутов признаков в узле condition
— использование узла stateReader
.
Для этого сначала необходимо получить значение атрибута типажа в узле stateReader
. stateReader
принимает structure
и тип в качестве аргументов:
typealias ActivatedCarbonFilterMonitoringTrait = Matter.ActivatedCarbonFilterMonitoringTrait
let filterMonitoringState = stateReader(structure, ActivatedCarbonFilterMonitoringTrait.self)
Затем обратитесь к stateReader
в узле condition
:
condition {
filterMonitoringState.changeIndication.equals(.warning)
}
Используя операторы сравнения и логические операторы , в узле condition
можно использовать несколько 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)
}
Длительность состояния
Помимо логического выражения в условии, вы можете указать временной интервал, в течение которого выражение должно быть истинным для запуска автоматизации. Например, можно определить условие, которое сработает только если свет горит в течение десяти минут.
condition(for: .seconds(600)) {
lightStateReader.onOff.equals(true)
}
Продолжительность может варьироваться от одной до 30 минут.
Узлы действий
Узел действия — это место, где происходит автоматизация. В этом примере действие вызывает команду broadcast()
класса AssistantBroadcastTrait
:
action(speaker, SpeakerDeviceType.self) {
Google.AssistantBroadcastTrait.broadcast(msg: "Oven Cycle Complete")
}