DSL 概念

本文简要介绍了 Automation DSL 的基本概念。

自动化组件

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

  1. 启动器 - 定义启用自动化操作的初始条件,例如对 trait 的更改。自动化操作必须有启动器。
  2. 条件 - 在自动化操作启用后要评估的任何其他约束条件。条件中的表达式必须求得的值为 true,才能继续执行自动化操作。
  3. 操作 - 在满足所有条件时执行的命令或状态更新。

例如,您可以创建一个自动化操作,在日落到日出期间,当房间内的电视开启时,调暗房间内的灯光。在此示例中:

  1. Starter - 电视已开启,这是电视 trait 的状态变化。
  2. 条件 - 系统会评估电视所在住宅的当前时间。
  3. 操作:电视所在房间的灯光会调暗。

当房间中的电视开启时,系统会启用自动化操作,但只有在满足“时间介于日落和日出之间”这一条件时,自动化操作才会执行。

除了基本结构之外,Home API 中的自动化操作还包含元数据,例如名称说明,可供开发者和用户识别它们。

节点

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

表:自动化节点类型
节点 节点类型 Kotlin 实现 说明
新手 行为 StarterNodeDsl 在 trait 的状态(任何属性)发生变化时启动自动化操作。
StateReader 行为 StateReaderNodeDsl 读取 trait 属性,并让您捕获其值以在条件节点中使用。
操作 行为 ActionNodeDsl 调用 trait 命令。
依序 执行流程 SequentialFlow 按顺序执行嵌套的操作节点。这是默认的执行行为。
并行 执行流程 ParallelFlow 并行执行嵌套的操作节点。
条件 执行流程 ConditionNodeDsl 根据逻辑表达式的求值有条件地更改执行流程。条件可以与启动器相关联(启动器专用条件),也可以是全局条件(适用于所有启动器)。
选择 执行流程 SelectFlow 允许多个启动器启用自动化操作。
表达式 Expression 可以是 trait 的属性的值、常量或字面量值,并且必须求值为列表、数字、布尔值或字符串。

行为节点

启动器和操作等节点属于行为节点。启动器会根据设备属性更改来启用自动化操作。操作用于发出设备命令或更新属性。

行为节点通常与设备 trait 和输出 trait 状态相关联,以便在其他节点中用作输入。

执行流程节点

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

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

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

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

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

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

例如,您可以创建一个自动化操作,根据夜晚与否执行操作。条件节点会检查时间,然后根据该评估结果遵循适当的执行路径。

条件流
图 3:条件流程

如果您希望有多个启动器可以启动自动化操作,则选择流程非常有用。当您在 select 流中封装两个或更多启动器时,其中任一启动器都可以启用自动化操作。

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

选择流程
图 4:选择数据流

嵌套流

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

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

DSL 节点可以通过多种方式嵌套和组合,以满足您的具体需求,具体取决于下表中列出的约束条件。“构建器”列会链接到 Kotlin 类型安全构建器文档,其中详细介绍了允许在每种类型的节点中使用的构建器。

表格:节点的组合方式
节点 构建器 可能包含以下节点类型和数据 必须属于以下某种节点类型
新手 AutomationBuilder 表达式 选择“依序”
ManualStarter AutomationBuilder 选择“依序”
StateReader AutomationBuilder 表达式(通常由 trait 属性值组成) 操作、条件
操作 ActionBuilder 命令、实体、表达式 并行、选择、顺序
依序 SequentialFlowBuilder 并行、选择、顺序
并行 ParallelFlowBuilder 操作 依序
条件 ConditionBuilder 表达式 并行、顺序
选择 AutomationBuilder Condition、Sequential、Starter、ManualStarter 顺序,且必须是流程中的第一个节点

自动化 DSL

在 Home API 中,自动化操作是使用自动化 DSL(特定领域的语言)定义的。自动化 DSL 以 Kotlin DSL(领域特定语言)的形式实现,使用 Kotlin 类型安全构建器,专门用于定义自动化模板。

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

Automation DSL 可简化和简化构建自动化操作的过程。它与 Device API 中使用的 Matter 标准 trait 和 smart home trait 采用相同的原生数据模型

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

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

示例

以下是使用自动化 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 节点包含行为节点,例如 starterconditionactionstarter 节点的输出会分配给一个变量,以便在 condition 节点中使用。