С помощью Automation DSL можно создавать более сложные сценарии автоматизации, чем те, которые описаны в руководстве по DSL для базовой автоматизации на устройствах Android.
Последовательность с несколькими действиями
Программа может выполнять несколько действий. Например, вместо одного узла action можно использовать несколько узлов action, которые выполняются последовательно:
automation {
sequential {
starter<_>(...)
condition {...}
action {...}
action {...}
action {...}
}
}
Последовательное выполнение с несколькими параллельными действиями
Если в узле parallel разместить несколько узлов action, действия будут выполняться одновременно.
automation {
sequential {
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.
automation {
sequential {
val contactState = starter<_>(
contactSensor,
ContactSensorDevice,
BooleanState,
)
val lightState = stateReader<_>(
light,
DimmableLightDevice,
OnOff,
)
condition {
// Door opened (contact sensor open)
expression = contactState.stateValue equals false
}
// Conditionally turn on the light if it's off
ifThen(lightState.onOff equals false) {
action(light, DimmableLightDevice) { command(OnOff.on()) }
}
// Continue executing subsequent actions in the sequential flow
action(structure) {
command(AssistantBroadcast.broadcast("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.
automation {
sequential {
val doorLockEvent = starter<_>(
doorLock,
DoorLockDevice,
LockOperationEvent,
)
val lightState = stateReader<_>(
light,
DimmableLightDevice,
OnOff,
)
condition {
expression =
doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock
}
ifThen(lightState.onOff equals false) {
action(light, DimmableLightDevice) { command(OnOff.on()) }
}.orElse {
action(structure) {
command(AssistantBroadcast.broadcast("Welcome home!"))
}
}
}
}
Как объединять несколько условий в цепочку
Вы можете объединить несколько необязательных блоков .elseIf(...) { ... }, чтобы последовательно оценить несколько условий. Выполняется первая ветвь, условие которой оценивается как true, а все остальные ветви пропускаются. Если ни одно из условий не возвращает значение true, выполняется необязательный блок .orElse { ... } (если он указан):
// Adjust climate controls based on room temperature changes.
automation {
sequential {
val tempStarter = starter<_>(
tempSensor,
TemperatureSensorDevice,
TemperatureMeasurement,
)
// If temperature is high (>= 28°C / 2800 mC), switch thermostat to Cool mode
ifThen(tempStarter.measuredValue greaterThanOrEquals 2800) {
action(thermostat, ThermostatDevice) {
command(
SimplifiedThermostat.setSystemMode(
SimplifiedThermostatSystemModeEnum.Cool
)
)
}
}.elseIf(tempStarter.measuredValue lessThan 1800) {
// If temperature is low (< 18°C / 1800 mC), switch to Heat mode
action(thermostat, ThermostatDevice) {
command(
SimplifiedThermostat.setSystemMode(
SimplifiedThermostatSystemModeEnum.Heat
)
)
}
}.orElse {
// Otherwise, turn on the fan
action(fan, FanDevice) {
command(OnOff.on())
}
}
}
}
Вложенные процессы с условиями
Условные блоки можно вкладывать в другие блоки ifThen, elseIf или orElse, а также комбинировать с узлами parallel, delayFor и stateReader.
Блоки ifThen, elseIf и orElse выполняют свое содержимое как последовательные потоки. В каждую ветвь можно поместить любые последовательные узлы, в том числе action, stateReader, parallel, delayFor и вложенные блоки ifThen.
Задержка обработки платежа
Вы можете добавить паузу в автоматизацию, используя ключевое слово delayFor, которое принимает аргумент java.time.Duration, представляющий собой время паузы перед продолжением выполнения. Приостановка может длиться от пяти секунд до 24 часов.
Например, чтобы четыре раза включить и выключить свет с пятисекундной паузой между каждым переключением, выполните следующие действия:
sequential {
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
Подавление триггеров
Подавление триггеров позволяет автоматизации игнорировать starter в течение определенного периода времени после исходного события-триггера. Например, если программа имеет starter, которое запускается при обнаружении движения, и вы задали продолжительность подавления триггера пять минут, то после запуска starter не будет запускаться снова в течение следующих пяти минут. Это предотвращает многократное быстрое срабатывание автоматизации.
Чтобы применить подавление триггеров к автоматизации, используйте ключевое слово suppressFor с аргументом java.time.Duration, который определяет, сколько времени должно пройти, прежде чем реагировать на последующие триггеры.
Продолжительность подавления может составлять от пяти секунд до 24 часов.
automation {
sequential {
val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
suppressFor(Duration.ofMinutes(30))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
Обратите внимание, что подавление триггера влияет на все starters в автоматизации, которые предшествуют suppressFor.
Ограничение количества выполнений
Вы можете ограничить количество запусков автоматизации.
Например, вы можете настроить однократную программу, чтобы робот-пылесос запустился, пока вас нет дома.
Для этого задайте значение поля метаданных maxExecutionCount.
Ниже приведен пример автоматизации, которую можно выполнить только один раз:
automation { // The automation can only be executed once. maxExecutionCount = 1 // When the door lock state changes sequential { val doorLockEvent = starter<_>(doorLock, DoorLockDevice, LockOperationEvent) // if the door is unlocked condition() { expression = (doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock) } // turn the light on action(light, DimmableLightDevice) { command(OnOff.on()) } } }
Автоматизация будет удалена сразу после того, как будет выполнена в последний раз и достигнет значения maxExecutionCount. Запись об автоматизации останется на вкладке Google Home app (GHA) Действия, включая automation_id.
Как задавать атрибуты признаков в действии
Чтобы задать значение атрибута характеристики:
- Создайте узел
updateв узлеaction, добавив нужный признак в качестве аргумента узлаupdate:action(deviceReference, deviceType) { update(trait) { } } - В узле
updateдля каждого атрибута, который нужно изменить, используйте функцию-мутатор и передайте ей новое значение. Чтобы сформировать название функции-мутатора:- Название атрибута должно начинаться с заглавной буквы.
- Добавьте перед ним слово
set.
defaultMoveRate, нужно использовать функцию-мутаторsetDefaultMoveRate.
Обратите внимание, что узел update может иметь несколько функций мутатора. Ниже приведен пример, в котором обновляются два атрибута:
action(device, Fan) {
update(FanControl) {
setPercentSetting(50u)
setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
}
}