访问 Android 设备和设备元数据

设备 API 可通过适用于 Android 的 Home API 进行访问。 将以下软件包导入到您的应用中:

import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id

如需将特定设备类型或特征与设备 API 搭配使用,必须单独导入它们。

例如,如需使用 Matter On/Off 特征和 On/Off Plug-in Unit 设备类型,请将以下软件包导入到您的应用中:

import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice

如需了解详情,请参阅 Android 上的数据模型

错误处理

Home API 中的任何方法都可能会抛出 HomeException,因此我们建议您使用 try-catch 块来捕获所有调用中的 HomeException

处理 HomeException 时,请检查其 codemessage 字段,了解问题所在。

任何未处理的异常都会导致应用崩溃。

如需了解详情,请参阅错误处理

如需查看示例,请参阅向设备发送命令

调用示例

获取设备列表

有了结构,devices() 调用会返回一个 Flow,其中包含您可以从该结构访问的设备:

// Get a flow of all devices accessible to the user
val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices()

// Calling list() on a HomeObjectsFlow returns the first Set of elements.
val allDevices: Set<HomeDevice> = allDevicesFlow.list()

这样一来,您便可以访问每台设备的状态,并向设备发送支持的命令。

读取设备状态

我们来看一个示例,该示例展示了如何从设备的 On/Off 特征检查 OnOff 属性。使用 Home APIs 特征数据模型(其中此特征标识为 OnOff),您可以通过设备类型的 standardTraits 类检索特征数据:

// Assuming we have a device.
val deviceFlow = home.devices().itemFlow(myDeviceId)

val device = deviceFlow.first()

// Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger
// on the specific trait changes and not the whole type.
val onOffTraitFlow: Flow<OnOff?> =
  device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged()

val onOffTrait: OnOff = onOffTraitFlow.first()!!

如需详细了解 Kotlin flow 函数,请参阅 distinctUntilChanged

使特征订阅中的状态失效

TraitStateInvalidation 接口提供了一种功能,可在状态未正确报告的情况下,使通过订阅目标设备检索到的状态失效。以下情况可能会导致状态报告不正确:在 Matter 特征中使用质量为“C”的属性,或者由于设备实现意外导致此问题。

此 API 会强制读取当前特征状态,并通过现有特征流返回结果。

获取特征,然后对该特征运行 forceRead

val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()

获取设备类型特征列表

设备类型应作为读取特征的入口点,因为它们会将设备分解为各个功能部件(例如 Matter 中的端点)。

它们还会考虑特性冲突,以防设备具有两种设备类型,而这两种设备类型可能具有相同的特性。例如,如果设备既是音箱又是可调光灯,则会具有两个 On/Off 特征和两个 Level Control 特征。

如需获取“可调光灯”设备类型的可用特征列表,请执行以下操作:

// Get all types available on this device. Requires the types to be part of the registry during
// SDK initialization.
val typesFlow: Flow<Set<DeviceType>> = device.types()

// Get a snapshot of all types.
val types: Set<DeviceType> = typesFlow.first()

// Get the DimmableLightDevice instance from the set of types.
val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull()

// Get all traits in the type + traits registered
val allTraits: Set<Trait> = dimmableLightDevice!!.traits()

当设备具有两个名称相同的特征时,可能会发生另一种特征冲突。例如,onOff 可以指标准 OnOff 特征的实例,也可以指制造商定义的 OnOff 特征的实例。为消除可能存在的关于预期特征的任何歧义,通过设备引用的 Trait 实例应以限定命名空间开头。对于标准特征(即与 Matter 标准集群类似的特征),请使用 standardTraits。对于 Google 特征,请使用 googleTraits

// Accessing standard traits on the type.
val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff
val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl

如需访问制造商专属特征,请直接引用它:

// Accessing a custom trait on the type.
val customTrait = dimmableLightDevice.trait(MyCustomTrait)

获取具有特定特征的设备列表

Kotlin 中的 filter 函数可用于进一步优化 API 调用。例如,如需获取住宅中所有具有“开/关”特征的设备的列表,请执行以下操作:

// Get all devices that support OnOff
val onOffDevices: Flow<List<HomeDevice>> =
  home.devices().map { devices -> devices.filter { it.has(OnOff) } }

如需查看 Home API 中可用的特征的完整列表,请参阅 Trait 接口

获取具有类似设备类型的设备列表

如需获取代表住宅中所有灯具的设备列表,请执行以下操作:

// Get a list of devices with similar device types (lights)
val lightDevices =
  home.devices().map { devices ->
    devices.filter {
      it.has(DimmableLightDevice) ||
        it.has(OnOffLightDevice) ||
        it.has(ColorTemperatureLightDevice) ||
        it.has(ExtendedColorLightDevice)
    }
  }

Home API 中有多种设备类型可以代表核心设备类型。例如,没有“灯”设备类型。相反,有四种不同的设备类型可以表示灯,如上例所示。因此,若要全面了解住宅中更高级别的设备类型,必须在过滤后的流程中包含多种设备类型。

如需查看 Home API 中提供的设备类型的完整列表,请参阅 DeviceType 接口

获取设备的供应商 ID 或产品 ID

BasicInformation 特征包含供应商 ID、产品 ID、产品名称和设备的序列号等信息:

// Get device basic information. All general information traits are on the RootNodeDevice type.
val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!!
println("vendorName ${basicInformation.vendorName}")
println("vendorId ${basicInformation.vendorId}")
println("productId ${basicInformation.productId}")

面向设备制造商的云到云设备识别

如果您是设备制造商并构建 Cloud-to-cloud 设备,为了通过 BasicInformation 特征识别 Cloud-to-cloud 设备,您可以在其 SYNC 响应中添加以下字符串字段:

  • 连接标准联盟 (CSA) 签发的供应商 ID: "matterOriginalVendorId": "0xfff1",

  • 唯一标识供应商产品的商品标识符: "matterOriginalProductId": "0x1234",

  • 设备的唯一标识符,以制造商特定的方式构建: "matterUniqueId": "matter-device-id",

输入这些字符串字段时,请使用您的Matter供应商 ID 和产品 ID(如果有)。如果您不是 CSA 会员,并且未获分配这些 ID,则可以将 matterOriginalVendorIdmatterOriginalProductId 字段留空,并提供 matterUniqueId 作为标识符。

以下示例 SYNC 响应展示了这些字段的用法:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "456",
        "type": "action.devices.types.LIGHT",
        "traits": [
          "action.devices.traits.OnOff",
          "action.devices.traits.Brightness",
          "action.devices.traits.ColorSetting",
        ],
        "willReportState": true,
        "deviceInfo": { ... },
        "matterOriginalVendorId": "0xfff1",
        "matterOriginalProductId": "0x1234",
        "matterUniqueId": "matter-device-id",
        "otherDeviceIds": [
          {
            "deviceId": "local-device-id",
          }
        ]
      }
    ]
  }
}

如需了解详情,请参阅 Cloud-to-cloud SYNC 文档

设备和特征元数据

Home API 中的设备和特征具有相关联的元数据,这些元数据有助于管理应用中的用户体验。

Home API 中的每个特征都包含一个 sourceConnectivity 属性,其中包含有关特征在线状态和位置(本地或远程路由)的信息。

获取设备的主要类型

某些设备可能会通过 Home API 显示多种设备类型。 为了确保用户在应用中看到适合其设备的选项(例如设备控制和建议的自动化操作),最好检查一下设备的主要设备类型。

首先,使用 type() 获取设备的类型,然后确定主要类型:

val types = device.types().first()
val primaryTypes = types.filter { it.metadata.isPrimaryType }

检查特征是否处于在线状态

使用 connectivityState() 方法检查特性的连接性:

val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState

如果设备未连接到互联网,某些特征(通常是 Google smart home 特征)可能会显示为离线。这是因为这些特征基于云,没有本地路由。

检查设备的连接

设备的连接性实际上是在设备类型级别进行检查的,因为某些设备支持多种设备类型。返回的状态是相应设备上所有特征的连接状态的组合。

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

如果设备类型混合,且没有互联网连接,则可能会观察到 PARTIALLY_ONLINE 状态。由于本地路由,Matter 标准特征可能仍处于在线状态,但基于云的特征将处于离线状态。

检查特征的网络路由

特征的语言区域也可在 Home API 中使用。dataSourceLocality 表示该特征是通过远程(通过云端)、本地(通过本地 hub)还是对等(直接从设备到设备,无需 hub)方式进行路由。

例如,当应用正在启动且尚未连接到集线器或服务器以实现设备连接时,可能会出现未知位置值 UNSPECIFIED。这些设备无法访问,并且会因命令或事件而导致互动请求失败。客户端可以自行决定如何处理此类设备。

val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality

检查设备的网络路由

与连接性类似,本地性是在设备类型级别进行检查的。返回的状态是相应设备上所有特征的本地化状态的组合。

val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality

在与 PARTIALLY_ONLINE 连接类似的情况下,可能会出现 MIXED 状态:某些特征基于云,而另一些特征基于本地。

更改设备的名称

调用 setName() 方法可更改设备的名称:

mixerDevice.setName("Grendel")

如果名称超过 60 个 Unicode 码位(字符)的限制,系统会截断名称,但不会抛出任何错误。开发者负责处理过长的名称,例如,可以决定是否要告知用户名称将被截断。

API 列表

创建 Home 的实例后,可以通过该实例访问以下设备 API:

API 说明
devices() 获取 Google 账号中所有结构中的所有设备。返回一个 HomeObjectsFlow,其中包含更多检索和过滤选项。

获得 HomeDevice 后,您可以通过它访问以下 API:

API 说明
allCandidates() 返回设备及其子设备的全部自动化候选对象
candidates() 返回设备的所有自动化候选对象
connectivityStateChanged 设备状态最近一次发生变化的时间。
events(event) 获取特定事件的流程。
events(trait) 获取相应特征的所有事件的流。
events(traits) 获取具有这些特征的所有事件的流。
getSourceConnectivity(trait) 获取特定特征的元数据。返回 SourceConnectivity
has(trait) 检查设备是否支持当前请求的特征。
has(type) 如果设备支持所提供的类型。
id 设备的唯一系统 ID。
isMatterDevice 如果设备由 Matter 提供支持。
name 设备的用户提供名称。
room() 设备分配到的房间。返回 Room
roomId 设备所分配到的房间的 ID。返回 Id
sourceConnectivity 设备的来源连接,表示设备特征的聚合连接状态和网络位置。
structure() 设备所分配到的结构。返回 Structure
structureId 设备所分配到的结构的 ID。返回 Id
type(type) 获取填充了特征(如果可用)的类型定义,以便直接访问。始终返回特征的最新快照。
types() 获取设备上所有可用类型的列表。