DSL-скрипты позволяют создавать более сложные автоматизации, чем те, которые описаны в руководстве по DSL-скриптам для базовых автоматизаций на Android.
Последовательные с несколькими действиями
Автоматизация может выполнять несколько действий. Например, вместо одного узла action можно использовать несколько узлов action, которые будут выполняться последовательно:
automation {
sequential {
starter<_>(...)
condition {...}
action {...}
action {...}
action {...}
}
}
Последовательные действия с несколькими параллельными действиями
Если вы поместите несколько узлов action в узел parallel, действия будут выполняться одновременно.
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)
}
}