请参阅以下指南,了解如何使用各种自动化 DSL 节点来构建自动化。
所有自动化 DSL 都放置在单个 automation
节点内。automation
节点构成外部 Kotlin 语言上下文与嵌入式 DSL 上下文之间的边界。
顺序流程
顺序流程是默认的自动化流程类型。
下面是一个非常基本的自动化 DSL 模板,它使用由启动器、条件和操作组成的顺序流程:
import com.google.home.automation.action
import com.google.home.automation.automation
import com.google.home.automation.condition
import com.google.home.automation.sequential
import com.google.home.automation.starter
...
automation {
sequential {
starter<_>(...)
condition {...}
action {...}
}
}
您可以通过添加其他节点来优化此图表。
入门版
启动方式节点用于定义触发自动化操作的初始情况。例如,状态或值的变化。自动化必须至少有一个启动器,否则将无法通过验证。如需向自动化操作添加多个启动器,您必须使用 select
节点。
基于特征属性的初始值
声明基于特征属性的起始节点时,请指定:
- 设备
- 特征所属的设备类型
- 相应特征
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
设备类型参数是必需的,因为它可以让您指定自动化所针对的设备中的哪个设备类型。例如,某个设备可能由 FanDevice
和 HeatingCoolingUnitDevice
组成,这两者都包含 OnOff
特征。通过指定设备类型,可以明确设备中的哪个部分触发自动化操作。
基于事件的启动器
声明基于事件的起始节点时,请指定:
- 设备
- 特征所属的设备类型
- 活动
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)
基于结构和事件的初始代码,包含参数
某些事件可以包含参数,因此这些参数也需要包含在初始代码中。
例如,此启动器使用 Time
特征的 ScheduledTimeEvent
在上午 7:00 激活自动化操作:
val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
parameter(Time.ScheduledTimeEvent.clockTime(
LocalTime.of(7, 0, 0, 0)))
}
手动启动器
手动启动器是一种特殊的启动器,可让用户手动运行自动化操作。
声明手动启动器时:
- 未指定特征或设备类型。
- 提供一个调用
Automation.execute()
的界面元素。
如果将手动启动器与另一个启动器一起放置在 select
流中,手动启动器会替换另一个启动器:
select {
manualStarter()
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}
请注意,手动启动器之后的任何 condition
节点都会被评估,并且可能会阻止自动化执行,具体取决于 condition
表达式。
一种结构化自动化操作的方式是,将其他启动器及其 condition
放在单独的顺序流中,这样 condition
节点就不会阻塞通过手动启动器激活的自动化操作:
automation_graph {
sequential {
select {
sequential {
starter<_>(...)
condition {...}
}
sequential {
manualStarter()
}
}
action {...}
}
}
引用属性的值
如需在表达式中使用属性的值,请使用以下语法。
使用 stateReader
:
val time = stateReader<_>(structure, Structure, Time)
val currTime = time.currentTime
使用 starter
:
val starterNode = starter<_>(device1, LaundryWasherDevice, OnOff)
condition() {
expression = starterNode.onOff equals true
}
条件节点和表达式
条件节点表示一个决策点,用于确定自动化流程是否继续。一个自动化流程可以包含多个 condition
节点。
如果任何 condition
节点的表达式的计算结果为 false
,则整个自动化流程的执行结束。
在 condition
节点中,您可以使用各种运算符组合多个条件,只要表达式的计算结果为单个布尔值即可。如果结果值为 true
,则表示满足条件,自动化流程会继续执行下一个节点。如果值为 false
,自动化流程会在该点停止执行。
表达式的构成方式与 Kotlin 中的表达式类似,可以包含数字、字符、字符串和布尔值等基本值,以及枚举值。使用圆括号对子表达式进行分组,可控制它们的求值顺序。
以下是一个 condition
的示例,它将多个子表达式合并为一个表达式:
condition() {
val expr1 = starterNode.lockState equals DlLockState.Unlocked
val expr2 = stateReaderNode.lockState equals true
val expr3 = occupancySensingDevice.occupied notEquals 0
val expr4 = timeStateReaderNode
.currentTime
.between(
timeStateReaderNode.sunsetTime,
timeStateReaderNode.sunriseTime)
expression = (expr1 and expr2) or (expr3 and expr4)
}
您可以通过启动器引用所访问特征的值:
val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }
stateReader
在 condition
节点中引用特征属性值的另一种方法是使用 stateReader
节点。
为此,请先在 stateReader
节点中捕获特征属性值。stateReader
将 structure
和特征作为实参:
import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)
然后在 condition
节点中引用 stateReader
:
condition() {
expression =
filterMonitoringState.changeIndication
.equals(ChangeIndicationEnum.Warning)
}
使用比较和逻辑运算符,可在 condition
节点中使用多个 stateReaders
:
val armState = stateReader<_>(doorLock, DoorLockDevice, ArmDisarm )
val doorLockState = stateReader<_>(doorLock, DoorLockDevice, DoorLock)
condition() {
expression =
(armState.armState equals true)
and
(doorLockState.lockState equals true)
}
条件持续时间
除了在条件中使用布尔表达式外,您还可以指定一个时间范围,只有在该时间范围内表达式为 true 时,系统才会运行自动化操作。例如,您可以定义一个仅在灯亮了 10 分钟后触发的条件。
condition {
expression(lightStateReader.onOff == true)
forDuration(Duration.ofMinutes(10))
}
时长可以介于 1 分钟到 30 分钟之间。
操作节点
操作节点是自动化操作执行工作的位置。在此示例中,操作会调用 AssistantBroadcast
特征的 broadcast()
命令:
action(device, SpeakerDevice) {
command(AssistantBroadcast.broadcast("Intruder detected!"))
}
import 语句
在开发自动化操作时,如何将 Home API 的各种元素导入到代码中并不总是显而易见。
特征属性是从特征的 Companion
对象导入的:
import com.google.home.matter.standard.OnOff.Companion.onOff
由特征定义的数据结构从名称以“-Trait”结尾的特征类导入:
import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum
从特征的 Companion
对象导入特征命令:
import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold