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."))
}
}
}
根据条件执行不同的操作
如需在条件为 true 时执行一组操作,并在条件为 false 时执行另一组操作,请在 ifThen(...) { ... } 后链接可选的 .orElse { ... } 块:
// 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
实参,表示在继续执行之前暂停的时间。暂停时长可能短至 5 秒,也可能长达 24 小时。
例如,如需切换灯泡四次,每次切换之间暂停 5 秒,请执行以下操作:
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,并且您指定了 5 分钟的触发抑制时长,那么当 starter 触发时,它在接下来的 5 分钟内不会再次触发。这样可以防止自动化快速重复触发。
如需对自动化应用触发抑制,请使用
suppressFor
关键字,并使用
java.time.Duration
实参表示在响应后续触发之前等待的时间。
抑制时长可能短至 5 秒,也可能长达 24 小时。
automation {
sequential {
val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
suppressFor(Duration.ofMinutes(30))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
请注意,触发抑制会影响自动化中位于 suppressFor 之前的所有 starters。
限制执行次数
您可以限制自动化运行的次数。
例如,您可能想要设置一个一次性自动化,让它在您白天不在家时运行吸尘器。
为此,请设置自动化的
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。
在操作中设置特征属性
如需设置特征属性的值,请执行以下操作:
- 在
action节点内创建一个update节点,并将相关特征作为update节点的实参:action(deviceReference, deviceType) { update(trait) { } } - 在
update节点内,对于要修改的每个属性, 使用 mutator 函数,并向其传递新值。 如需构成 mutator 函数的名称,请执行以下操作:- 将属性的名称大写
- 在前面加上单词
set。
defaultMoveRate的属性, 您可以使用名为setDefaultMoveRate的 mutator 函数。
请注意,一个 update 节点可以有多个 mutator 函数。以下示例展示了如何更新两个属性:
action(device, Fan) {
update(FanControl) {
setPercentSetting(50u)
setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
}
}