Android DSL 概念

以下是 Android 自动化 DSL 的基本概念概览。

自动化组件

自动化操作由以下基本组件组成,通常按以下顺序进行评估:

  1. 启动方式 - 定义激活自动化操作的初始条件,例如特征发生变化。自动化操作必须有启动方式。
  2. 条件 - 自动化操作启动后要评估的所有其他限制。条件中的表达式必须求值为 true,自动化操作才能继续执行。
  3. 操作 - 满足所有条件时执行的命令或状态更新。

例如,您可能设置了这样一项自动化操作:在日落到日出之间,当某个房间的电视打开时,该房间的灯光会变暗。在此示例中:

  1. 启动器 - 电视已开启,这是电视特性状态的变化。
  2. 条件 - 评估电视所在住宅的当前时间。
  3. 操作 - 与电视位于同一房间内的灯光变暗。

当房间内的电视打开时,自动化操作会被激活,但只有在满足“时间在日落和日出之间”这一条件时,自动化操作才会执行。

除了基本结构之外,Home API 中的自动化操作还包含元数据,例如 name 和 description,可用于向开发者和用户标识这些自动化操作。

节点

在 Home API 中,自动化操作的逻辑结构由节点组成。节点是抽象的可重用单元,表示实体行为或执行流程。每个节点都可以有输入变量,以及可能被其他节点使用的输出变量。

表:自动化节点类型
节点 节点类型 Kotlin 实现 说明
Starter 行为 StarterNodeDsl 当特性的状态(任何属性)发生变化时启动自动化操作。
StateReader 行为 StateReaderNodeDsl 读取特征属性,并让您捕获其值以在条件节点中使用。
操作 行为 ActionNodeDsl 调用 trait 命令。
依序 执行流程 SequentialFlow 按顺序执行嵌套的操作节点。这是默认执行行为。
Parallel 执行流程 ParallelFlow 并行执行嵌套的操作节点。
条件 执行流程 ConditionNodeDsl 根据逻辑表达式的评估结果,有条件地更改执行流程。条件可以与启动器相关联(启动器特定条件),也可以是全局条件(适用于所有启动器)。
选择 执行流程 SelectFlow 允许通过多个启动方式来启动自动化操作。
IfFlow 执行流程 IfFlowDsl 根据哪个条件(如果有)的求值结果为 true,最多运行一个操作(或分支)(类似于 if-then-else 语句)。
表达式 值 Expression 可以是特征属性的值、常量或字面量值,并且求值结果必须为列表、数字、布尔值或字符串。

行为节点

启动方式和操作等节点属于行为节点。启动方式会根据设备属性变化来激活自动化操作。操作会发出设备命令或更新属性。

行为节点通常与设备特征相关联,并输出特征状态,以用作其他节点的输入。

执行流程节点

有些节点表示执行流程,例如依序和并行。 其中每个节点都包含定义自动化操作的行为节点。

例如,依序流程可能包含按顺序执行的节点。通常,这些是启动方式、条件和操作。

顺序执行流程
图 1:顺序自动化流程

并行流程可能有多个操作节点同时执行,例如同时打开多盏灯。在并行流的所有分支完成之前,并行流之后的节点不会执行。

并行执行流程
图 2:并行自动化流程

另一种类型的执行流是条件流,它可以根据表达式的求值结果更改执行流。

例如,您可能有一个自动化操作,会根据是否是夜间来执行操作。条件节点会检查一天中的时间,然后根据该评估结果遵循适当的执行路径。

条件流
图 3:条件流

如果您希望有多个启动方式可以激活自动化操作,选择流程会很有用。如果您在 select 流程中添加了两个或更多启动方式,则其中任何一个启动方式都可以激活自动化操作。

例如,您可以编写一项自动化操作,在日落时、温度升至特定阈值以上时或亮度超过阈值时放下百叶窗。三个单独的启动器分别处理这些场景,并且这三个启动器都将封装在 select 流程中。

选择流程
图 4:选择流程

if-then-else 流程 (IfFlow) 允许在自动化操作中执行分支条件。condition 节点会在条件为 false 时停止整个自动化操作,而 if-then-else 流程则不同,它会在条件为 true 时有条件地执行特定操作,并且可以回退到替代条件或回退操作,或者继续执行自动化操作中的后续节点。如需了解详情,请参阅条件执行。

嵌套流

在复杂的自动化操作中,执行流程节点也可以嵌套。例如,您可能有一个执行并行流的顺序流。

嵌套执行流程
图 5:嵌套执行流程

DSL 节点可以根据下表中列出的限制,以各种方式嵌套和组合,以满足您的特定需求。“构建器”列链接到 Kotlin 类型安全构建器文档,其中详细介绍了每种类型的节点中允许使用的内容。

表:节点组合方式
节点 可能包含以下节点类型和数据 必须位于以下节点类型之一中
Starter 表达式 选择,依序
ManualStarter 选择,依序
StateReader 表达式(通常由特征属性值组成) IfFlow、Parallel、Sequential
操作 命令、实体、表达式 IfFlow、Parallel、Select、Sequential
依序 IfFlow、Parallel、Select、Sequential
Parallel 操作 IfFlow、Sequential
条件 表达式 IfFlow、Parallel、Sequential
选择 Condition, Sequential, Starter, ManualStarter 依序,且必须是流程中的第一个节点
IfFlow Action、Condition、Delay、IfFlow、Parallel、Sequential、StateReader、Suppression 依序

自动化 DSL

在 Home API 中,自动化操作是使用自动化 DSL(领域特定语言)定义的。自动化 DSL 是作为 Kotlin DSL(领域特定语言)实现的,它使用 Kotlin 类型安全构建器,专为定义自动化模板而设计。

编译自动化操作时,Kotlin 类型安全构建器会生成 Kotlin 数据类,然后这些类会被序列化为协议缓冲区 JSON,用于调用 Google 的自动化服务。

自动化 DSL 可简化和简化构建自动化的过程。它原生使用 Device API 中提供的 Matter 标准特征和 smart home 特征的相同数据模型。

自动化 DSL 还根据抽象设备类型(而非位于用户家中的特定设备实例)定义自动化逻辑。它允许开发者提供可在运行时使用的输入参数,以指定实际设备实例以及其他重要参数值。

DSL 语法与 Kotlin 类似,并且同样具有类型安全性,但使用自动化 DSL 编写的自动化操作比使用纯 Kotlin 编写的相同自动化操作更简单、更简洁。

示例

以下是使用自动化 DSL 编写的用于开启设备的自动化操作示例:

val automation = automation {
  name = "MyFirstAutomation"
  description = "If light1 is on, turn on light2."
  isActive = true
  sequential {
    val onOffTrait = starter<_>(device1, OnOffLightDevice, OnOff)
    condition() { expression = onOffTrait.onOff equals true }
    action(device2, OnOffLightDevice) { command(OnOff.on()) }
  }
}

此自动化操作非常基本:当 device1(一盏灯)开启(onOff 属性更改为 true)时,发送 on() 命令以开启 device2。

该自动化操作使用 sequential 节点,这表示其节点将按顺序运行。

sequential 节点内包含行为节点,例如 starter、condition 和 action。starter 节点的输出会分配给一个变量,以便在 condition 节点中使用。