С помощью DSL можно создавать более сложные автоматизации, чем те, которые описаны в руководстве по DSL для iOS.
Последовательные с несколькими действиями
Автоматизация может выполнять несколько действий. Например, вместо одного узла action можно использовать несколько узлов action, которые будут выполняться последовательно:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
action {...}
action {...}
action {...}
}
Последовательные действия с несколькими параллельными действиями
Если вы поместите несколько узлов action в узел parallel, действия будут выполняться одновременно.
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
parallel {
action {...}
action {...}
action {...}
}
}
Если в узле sequential есть узлы action, которые идут после узла parallel, они не будут выполняться, пока не завершится выполнение всех узлов в узле parallel.
Условное выполнение
По умолчанию автоматизация выполняет узлы последовательно или параллельно. Если вам нужна логика условного ветвления, то есть выполнение разных действий или путей в зависимости от условий выполнения, используйте операторы if-then-else, которые создаются с помощью блоков DSL условного управления: ifThen, elseIf и orElse.
Стандартный узел condition блокирует всю автоматизацию (если условие оценивается как false, автоматизация немедленно прекращает выполнение), а блоки ifThen позволяют управлять ветвлением.
- Узел
conditionостанавливает выполнение всей автоматизации (или текущего пути выполнения), если выражение равноfalse. ifThen/elseIf/orElse– оценивает условия по порядку. Если условиеfalse, выполнение переходит к следующей ветвиelseIf, резервной ветвиorElseили к последующим узлам автоматизации, если ни одно условие не выполняется.
Выполнение действия на основе условия
Блок ifThen оценивает условное выражение. Если выражение оценивается как true, выполняются действия или узлы DSL, вложенные в блок. Если условие не выполняется (false), действия пропускаются и автоматизация переходит к следующим узлам в последовательности.
Вы можете использовать отдельный блок ifThen, если хотите выполнить действие при условии, не блокируя и не завершая последующие узлы в автоматизации:
// 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.")
}
}
Как выполнять разные действия в зависимости от условия
Чтобы выполнить один набор действий, если условие истинно, и другой, если оно ложно, добавьте блок .orElse { ... } после 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!")
}
}
}
Объединение нескольких условий в последовательность
Вы можете объединить один или несколько необязательных блоков .elseIf(...) { ... }, чтобы последовательно оценить несколько условий. Выполняется первая ветвь, условие которой оценивается как true, а все остальные ветви пропускаются. Если ни одно из условий не равно true, выполняется необязательный блок .orElse { ... } (если он указан):
// 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()
}
}
}
Вложенные условные процессы
Условные блоки можно вкладывать в другие блоки ifThen, elseIf или orElse, а также комбинировать с узлами parallel, delay(for:) и stateReader.
Блоки ifThen, elseIf и orElse выполняют свое содержимое как последовательные потоки. Внутри каждой ветви можно разместить любые последовательные узлы, включая action, stateReader, parallel, delay(for:) и вложенные блоки ifThen.
Задержка обработки платежа
Вы можете добавлять паузы в автоматизации с помощью метода delay(for:), который принимает аргумент Duration, указывающий, как долго нужно ждать перед продолжением выполнения. Продолжительность паузы может составлять от пяти секунд до 24 часов.
Например, чтобы включить и выключить свет четыре раза с паузой в пять секунд между каждым переключением:
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() }
}
Исключение триггеров
Подавление триггера – это функция, которая позволяет автоматизации игнорировать starter в течение определенного периода времени после первоначального события-триггера. Например, если автоматизация содержит starter, который срабатывает при обнаружении движения, и вы задали длительность подавления триггера в пять минут, то после срабатывания starter он не сработает снова в течение следующих пяти минут. Это предотвращает быстрое повторное срабатывание автоматизации.
Чтобы применить подавление триггеров к автоматизации, используйте ключевое слово suppress(for:) с аргументом Duration, который указывает, сколько времени должно пройти, прежде чем автоматизация сможет реагировать на последующие триггеры.
Продолжительность блокировки может составлять от пяти секунд до 24 часов.
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() }
}
Обратите внимание, что подавление триггеров влияет на все starters в автоматизации, которые предшествуют Suppression.
Ограничьте количество выполнений
Вы можете ограничить количество запусков автоматизации.
Например, вы можете настроить однократную автоматизацию, которая запустит пылесос, пока вас не будет дома.
Для этого задайте поле метаданных maxExecutionCount автоматизации.
Ниже приведен пример автоматизации, которая может выполняться только один раз.
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)
}
}
Автоматизация будет удалена сразу после последнего выполнения, когда будет достигнуто значение maxExecutionCount. Запись об автоматизации останется на вкладке Google Home app (GHA) Действия, в том числе в разделе automation_id.
Как задать атрибуты признака в действии
Чтобы задать значение атрибута, выполните следующие действия:
- Создайте узел
updateвнутри узлаaction, указав нужный признак в качестве аргумента узлаupdate:action(deviceReference, deviceType) { update(trait) { } } - В узле
updateдля каждого атрибута, который нужно изменить, используйте функцию-мутатор и передайте ей новое значение. Чтобы сформировать название функции-мутатора:- Название атрибута должно начинаться с заглавной буквы.
- Добавьте к нему префикс
set.
defaultMoveRate, нужно использовать функцию-мутаторsetDefaultMoveRate.
Обратите внимание, что у узла update может быть несколько функций-мутаторов. Ниже приведен пример, в котором обновляются два атрибута:
typealias FanDeviceType = Matter.FanDeviceType
typealias FanControlTrait = Matter.FanControlTrait
action(fan, FanDeviceType.self) {
update(FanControlTrait.self) {
$0.setFanMode(.on)
}
}