Android DSL 概念

本文简要介绍了 Android 上自动化 DSL 的基本概念。

自动化组件

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

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

例如,您可能设置了自动化操作,在日落到日出之间,当房间内的电视打开时,调暗房间内的灯光。在此示例中:

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

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

除了基本结构之外,Home API 中的自动化操作还包含元数据,例如 namedescription,开发者和用户可以使用这些元数据来识别自动化操作。

节点

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

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

行为节点

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

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

执行流程节点

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

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

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

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

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

另一种执行流程是条件流程,它可以根据表达式的评估结果更改执行流程。

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

条件流
图 3:条件流程

如果您希望有多个可触发自动化操作的启动器,选择流程会很有用。如果您将两个或更多启动方式包含在 select 流中,那么任何一个启动方式都可以触发自动化操作。

例如,您可以编写一个自动化操作,在日落时、温度升至某个阈值以上时或亮度超过某个阈值时,降低百叶窗。这三种场景分别由三个单独的启动器处理,所有这三个启动器都将封装在一个 select 流中。

选择流程
图 4:选择流程

嵌套 flow

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

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

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

表:节点可能组合的方式
节点 可能包含以下节点类型和数据 必须位于以下节点类型之一中
Starter 表达式 选择“依序”
ManualStarter 选择“依序”
StateReader 表达式(通常由特征属性值组成) 操作、条件
操作 命令、实体、表达式 并行、选择、顺序
依序 并行、选择、顺序
并行 操作 依序
条件 表达式 并行、顺序
选择 条件、顺序、启动器、手动启动器 顺序执行,且必须是流程中的第一个节点

自动化 DSL

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

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

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

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

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

示例

以下是使用 Automation 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 节点中使用。