您可以通过 Home API for Android 访问设备 API。 将以下软件包导入您的应用:
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id
如需将特定设备类型或特征与 Device API 搭配使用,必须单独导入它们。
例如,如需使用 Matter 开关特性和开关插接单元设备类型,请将以下软件包导入到您的应用中:
import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice
如需了解详情,请参阅 Android 上的数据模型。
错误处理
Home API 中的任何方法都可能抛出
HomeException,因此我们建议您使用 try-catch 块在所有调用中捕获 HomeException。
处理 HomeException 时,请检查其
error.code 和
error.message 字段,了解具体出错情况。可能还存在子错误代码,因此请调用
getSubErrorCodes() 方法并检查结果。
任何未处理的异常都会导致应用崩溃。
如需了解详情,请参阅错误处理。
如需查看示例,请参阅向设备发送命令。
示例通话
获取设备列表
获得对 Structure 实例的引用后,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()
在该页面中,您可以访问每个设备的状态并向设备发送命令。
在 Home API 1.8 版中,您可以选择通过将 devices() 方法的 enableMultipartDevices 参数设置为 true,让 API 将每个多部分设备表示为单个设备。如需了解详情,请参阅 Android 上的多部分设备。
读取设备状态
请查看一个示例,了解如何检查设备的 On/Off 特性的 OnOff 属性。使用 Home API 特性数据模型(其中此特性标识为 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 会强制读取当前特性状态,并通过现有特性流返回结果。
获取 trait,然后对 trait 运行 forceRead:
val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()
获取设备类型特征列表
设备类型应用作读取特征的入口点,因为它们会将设备分解为其功能部分(例如 Matter 中的端点)。
如果设备具有两种设备类型,并且这两种类型可能具有相同的特征,则它们还会考虑特征冲突。例如,如果设备既是音箱又是可调光灯,则它将具有两个开关和两个亮度调节特性。
如需获取可调光灯设备类型的可用特征列表,请执行以下操作:
// 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()
当设备具有两个同名 trait 时,可能会发生另一种 trait 冲突。例如,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 的完整列表,请参阅 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 响应中添加以下字符串字段:
Connectivity Standards Alliance (Alliance) 颁发的供应商 ID:
"matterOriginalVendorId": "0xfff1",用于唯一标识供应商商品的商品标识码:
"matterOriginalProductId": "0x1234",设备的唯一标识符,以制造商特有的方式构建:
"matterUniqueId": "matter-device-id",
输入这些字符串字段时,请使用您的 Matter 供应商和产品 ID(如有)。如果您不是 Alliance 成员,并且未被分配这些 ID,则可以将 matterOriginalVendorId 和 matterOriginalProductId 字段留空,并提供 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 中的设备和 trait 具有关联的元数据,这些元数据有助于管理应用中的用户体验。
Home API 中的每个 trait 都包含一个 sourceConnectivity 属性,其中包含有关 trait 的在线状态和位置(本地或远程路由)的信息。
获取设备的主要类型
某些设备可能会通过 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 标准特性可能仍处于在线状态,但基于云的特性将处于离线状态。
获取设备的 IP 地址
如需查找设备的 IP 地址,请使用 GeneralDiagnostics 特性的 networkInterfaces 属性。这些地址会以字节数组的形式返回,您可以将其格式化为标准的 IPv4 或 IPv6 字符串:
val ipAddresses =
trait.networkInterfaces?.flatMap { networkInterface ->
(networkInterface.ipv4Addresses + networkInterface.ipv6Addresses).mapNotNull { bytes ->
try {
java.net.InetAddress.getByAddress(bytes).hostAddress
} catch (e: java.net.UnknownHostException) {
null
}
}
} ?: emptyList()
检查特征的网络路由
Home API 中也提供了特性的位置。dataSourceLocality 指示特性是通过远程(通过云)、本地(通过本地集线器)还是点对点(直接从设备到设备,无集线器)路由。
例如,当应用正在启动且尚未连接到集线器或服务器以实现设备连接时,可能会出现未知位置值 UNSPECIFIED。这些设备无法访问,并且会使来自命令或事件的互动请求失败。客户端需要自行确定如何处理此类设备。
val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality
检查设备的网络路由
与连接性一样,本地性也是在设备类型级别进行检查。返回的状态是该设备上所有特性的本地性组合。
val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality
在与 PARTIALLY_ONLINE 连接性 类似的情况下,可能会观察到 MIXED 状态:某些 trait 基于云,而其他 trait 则是本地的。
更改设备名称
调用 setName() 方法来更改设备名称:
mixerDevice.setName("Grendel")
如果名称超过 60 个 Unicode 码位(字符)限制,则会被截断,并且不会抛出任何错误。开发者负责处理长名称,例如,可以决定是否要告知用户名称将被截断。
查看设备的群组成员资格
一部实体设备可以属于一个或多个设备组。如需查看设备所属的群组,请检查设备上的 GroupMembership 特征:
val groupIds = device.trait(GroupMembershipTrait)?.groupObjectIds.orEmpty()
for (groupId in groupIds) {
println("HomeAPI", "Device belongs to group: $groupId")
}
相反,您可以通过在 DeviceGroup 上调用 devices() flow 来观察属于 DeviceGroup 的所有成员设备:
group.devices(enableMultipartDevices = true).collect { members ->
println("HomeAPI", "Group contains ${members.size} devices")
}
如需检查 DeviceGroup 支持的设备类型,并以单个实体形式向该组发送命令,请参阅控制设备组。