Android 上的 Automation API 概览

自动化功能可用于自动执行住宅中的任务和设备设置。自动化操作已在 Google Home 生态系统中以日常安排的形式提供,可通过 Google Home app (GHA)Google Home for web 上的 automation script editor 使用。

现在,Google Home 生态系统中的自动化操作可通过适用于 Android 的 Home API 实现。它们使用与 GHA 日常安排和 script editor 中使用的基本概念相同的概念,但具有只能通过 Home API 实现的增强功能,包括:

  • 访问设备的所有 Matter 标准和 smart home 特征(如 Home API 中所示)。
  • 支持顺序、并行和选择执行流程。

自动化操作使用自动化 DSL 编写,这是一种专门用于在 Kotlin 中构建自动化操作的领域特定语言。

您打算在应用中通过设备和结构或自动化 API 使用的任何特征和类型都必须在初始化时注册。请参阅在 Android 上初始化住宅

用户撤消完整权限时的指导

如果用户撤消完整权限,所有现有自动化操作都将停止运行。此外,如果用户撤消对特定设备的访问权限,则与这些设备关联的启动方式、条件和操作将停止工作。

每次应用启动时,请务必检查权限是否仍然有效。如果已撤消,请务必移除所有之前的数据,包括应用中缓存的所有数据。

当结构访问权限被撤消时,系统会向您的云后端传送 StructureAccessRevokedEvent。如需了解端到端的合作伙伴云和移动应用撤消工作流,请参阅结构化授权

开发者历程

Automation API 只是整个开发过程中的一部分。它是在集成 Structure API 和 Device API 之后实现的,以确保用户在想要使用自动化操作时能够顺利使用。

  1. 开发者规划自动化流程,并使用自动化 DSL 定义该流程。
  2. 开发者将自动化定义嵌入到 Kotlin Android 应用中。
  3. 应用会根据用户设备的相关信息(包括使用 Discovery API 或 Device API 收集的特征、属性、命令和事件)向用户显示自动化操作。
    1. 借助 Discovery API,应用可以生成根据用户结构中存在的设备类型和特征量身定制的自动化操作草稿,无论用户是否提供输入内容。
    2. Device API 可以提供与 Discovery API 大致相同的信息,但它并未针对自动化使用情形进行优化。如需了解详情,请参阅比较设备 API 和 Discovery API
  4. 应用会创建与所选结构对应的实际自动化操作。
  5. 自动化操作现在已在用户的结构中提供,可以使用 Structure API 方法执行或删除。

用户可以随时创建新的自动化操作实例,选择不同的结构,或者根据应用逻辑,选择不同的设备组。每次执行此操作时,应用都会生成一个新的自动化实例。

在最基本的情况下,您可以向用户建议执行相对基本任务的预定义自动化操作。或者,您也可以提供一个自动化操作框架,让用户根据自己的需求进行自定义。或者,您也可以编写一个开放式自动化编辑器,让用户能够使用 Automation API 中提供的所有构建块来构建复杂的自动化。

自动化操作建议

Home API 可以根据空间中存在的设备类型等因素,为 Structure 建议自动化操作。

自动化操作建议由 AutomationSuggestion 类表示。

Structure 接口包含 HasSuggestions 接口,后者提供 suggestions() 函数,该函数会返回自动化建议集合。

likeSuggestion()dislikeSuggestion() 方法旨在连接到 界面控件,用户可以通过点按这些控件来提供反馈。

第三种方法 clearSuggestionFeedback() 可让用户移除针对建议的自动化操作提供的反馈。

用户反馈会影响未来的建议。

此示例演示了如何检索 Structure 的可用自动化建议、提取建议 ID,以及使用 likeSuggestion()clearSuggestionFeedback()dislikeSuggestion() 记录用户反馈。

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.home.Structure
import kotlinx.coroutines.launch

class AutomationSuggestionsViewModel(private val structure: Structure) : ViewModel() {

  fun loadAndGiveFeedback() {
    viewModelScope.launch {
      // 1. Fetch suggestions from structure
      val suggestions = structure.suggestions()
      val firstSuggestion = suggestions.firstOrNull() ?: return@launch

      // Extract string suggestion ID
      val suggestionId: String = firstSuggestion.id.id

      // 2. Like the suggestion (thumbs up)
      val liked = structure.likeSuggestion(suggestionId)

      // 3. Clear previous feedback if the user toggled it off
      if (liked) {
        structure.clearSuggestionFeedback(suggestionId)
      }

      // 4. Dislike the suggestion (thumbs down)
      structure.dislikeSuggestion(suggestionId)
    }
  }
}

动态命令参数

动态命令参数允许开发者构建在运行时动态解析而非严格依赖于静态常量值的作用参数。这可实现以下两个主要功能:

  • 传递属性值的引用,这些属性来自启动器(例如事件载荷)或状态读取器节点,或者来自自动化流程中声明的局部变量。
  • 用于捕获运行时动态值(例如事件属性或状态值)并将动态值直接传递到命令参数中的表达式。

使用场景

将发送多次按压事件的实体旋转开关绑定到可调光灯。点击次数是在运行时传递到 LevelControl 步命令中的动态值。

动态参数的运作方式

在 Android 上的自动化 DSL 中,命令参数直接接受 ExpressionReference 实例,而不是静态常量值。在构建自动化时,DSL 会将这些封装到 Parameter 定义中。

验证规则

动态命令参数遵循以下验证限制:

  • 在发现期间,动态参数会被假定为在结构上有效,因为发现 API 仅评估静态实参的具体值限制。
  • 引用或表达式节点必须出现在自动化图中的上游,然后才能在下游命令操作中被引用。

在 Android 上使用动态命令参数

直接将动态表达式传递给命令参数:

import com.google.home.automation.action
import com.google.home.automation.automation
import com.google.home.automation.fieldSelect
import com.google.home.automation.sequential
import com.google.home.automation.starter
import com.google.home.matter.standard.DimmableLightDevice
import com.google.home.matter.standard.DimmerSwitchDevice
import com.google.home.matter.standard.LevelControl
import com.google.home.matter.standard.LevelControlTrait.StepModeEnum
import com.google.home.matter.standard.Switch

val keypressAutomation = automation {
  name = "Dynamic command parameters example"
  description = "Pass starter event field directly to command"
  sequential {
    val dimmerStarter = starter(
      dimmerSwitch,
      DimmerSwitchDevice,
      Switch.MultiPressOngoingEvent,
    )

    val clickCountExpr = fieldSelect<Switch.MultiPressOngoingEvent, UInt>(
      dimmerStarter,
      Switch.MultiPressOngoingEvent.EventFields.currentNumberOfPressesCounted,
    )

    action(dimmableLight, DimmableLightDevice) {
      command(
        LevelControl.step(
          stepMode = StepModeEnum.Up,
          stepSize = clickCountExpr,
        )
      )
    }
  }
}

或者,将表达式分配给局部变量声明,然后在流程中稍后引用该变量:

import com.google.home.automation.action
import com.google.home.automation.automation
import com.google.home.automation.fieldSelect
import com.google.home.automation.sequential
import com.google.home.automation.starter
import com.google.home.automation.variable
import com.google.home.matter.standard.DimmableLightDevice
import com.google.home.matter.standard.DimmerSwitchDevice
import com.google.home.matter.standard.LevelControl
import com.google.home.matter.standard.LevelControlTrait.StepModeEnum
import com.google.home.matter.standard.Switch

val myAutomationWithVariable = automation {
  name = "Dynamic command parameters with variables"
  description = "Declare a variable, assign value, and pass reference"
  sequential {
    val dimmerStarter = starter(
      dimmerSwitch,
      DimmerSwitchDevice,
      Switch.MultiPressOngoingEvent,
    )

    val clickCountExpr = fieldSelect<Switch.MultiPressOngoingEvent, UInt>(
      dimmerStarter,
      Switch.MultiPressOngoingEvent.EventFields.currentNumberOfPressesCounted,
    )

    val clickCountVar = variable<UInt>()
    clickCountVar.assign(clickCountExpr)

    action(dimmableLight, DimmableLightDevice) {
      command(
        LevelControl.step(
          stepMode = StepModeEnum.Up,
          stepSize = clickCountVar,
        )
      )
    }
  }
}

类型限制

确保变量和表达式的类型与接收命令参数所需的 Matter 架构类型定义(例如 UShortUByteUInt8)一致。

资源限制

以下限制适用于 Home API 中的自动化操作:

表:自动化 API 资源限制
指标 限制
每个结构的自动化操作数量上限 64
每个自动化任务的节点数上限 128
每个自动化任务的表达式节点数上限 64
每个结构的自动化实例数上限 1024
每个开发者每个结构的自动化实例数上限 64
每个结构每天的执行次数上限 1024
每个开发者每天每个结构的执行次数上限 128