您可以通过适用于 iOS 的 Home API 访问设备 API。将以下软件包导入您的应用:
import GoogleHomeSDK
import GoogleHomeTypes
如需了解详情,请参阅 iOS 上的数据模型。
错误处理
Home API 中的某些方法会抛出 HomeError
,因此我们建议您使用 do-catch
块捕获这些调用的 HomeError
。
处理 HomeError
时,请检查其 code
和 message
字段,了解问题所在。
任何未处理的错误都会导致应用崩溃。
如需了解详情,请参阅错误处理。
如需查看示例,请参阅向设备发送命令。
调用示例
获取设备列表
使用对 Home
对象的引用,调用 devices()
以获取可访问设备的 Query
。调用 Query
的 batched()
方法,该方法会在每次设备元数据发生变化时发出反映住宅当前状态的 Set。或者,调用 Query.list()
以获取可用设备的快照。这是一个便捷方法,用于订阅 batched()
流并返回第一个发射的值。Query.stream()
会生成一个数据流,用于在设备元数据(例如名称、房间或结构)发生变化时发出新值。在内部,此方法使用 batched()
,并且仅发出更改的属性。
// Get a list of all devices accessible to the user let homeDevices = try await self.home.devices().list()
从中,您可以访问每台设备的状态,并可以向设备发送支持的命令。
获取设备的类型
如需获取与设备关联的设备类型,请读取设备的 types
属性,该属性会返回 DeviceTypeController
。
调用 DeviceTypeController.subscribe(_:)
以订阅特定设备类型的更新:
let devices = try await self.home.devices().list() if let device = devices.first(where: { $0.id == myDeviceId }) { var receivedUpdate1 = false var receivedUpdate2 = false device.types.subscribe(OnOffLightDeviceType.self) .assertNoFailure() .sink { device in if !receivedUpdate1 { receivedUpdate1 = true Task { try await device.matterTraits.onOffTrait?.on() } return } if !receivedUpdate2 { receivedUpdate2 = true return } fatalError("Received unexpected update") } }
如果设备不支持指定的设备类型,则会返回一个立即完成的 Empty
Publisher
。
如果设备支持特定设备类型,您可以通过调用 get()
获取该类型的句柄:
if let device = devices.first(where: { $0.id == myDeviceId }) { let deviceType = await device.types.get(OnOffLightDeviceType.self) }
如果设备不支持指定的类型,则会返回 nil
。
调用 DeviceTypeController.subscribeAll()
以获取 DeviceTypeCollection
的 Publisher
。借助此类,您可以检查设备是否具有特定的设备类型:
if let device = devices.first(where: { $0.id == myDeviceId }) { device.types.subscribeAll() .assertNoFailure() .sink { types in let lightDeviceType = types[OnOffLightDeviceType.self] let fanDeviceType = types[FanDeviceType.self] } }
获取设备类型特征
设备类型是读取 trait 的入口点,因为它们会将设备分解为其功能组件(如 Matter 中的端点)。
它们还会考虑设备具有两种设备类型的情况,这两种设备类型都可能具有相同的特征。例如,如果某个设备既是音箱又是可调光灯,则它将具有两个开/关 trait 和两个亮度控制 trait。
如果设备具有两个名称相同的特征,则可能会发生另一种特征冲突。例如,onOff
可以是指标准 OnOff
trait 的实例,也可以是指制造商定义的 OnOff
trait 的实例。为消除关于要使用的 trait 的任何潜在歧义,请通过每种设备类型的两个 trait 集合之一引用 trait。
对于标准 trait(即类似于 Matter 标准集群的 trait),请使用 matterTraits
。例如,如需获取可调光灯设备类型的特定 trait,请执行以下操作:
if let dimmableLightDeviceType = await device.types.get(DimmableLightDeviceType.self) { // Accessing standard trait on the type. let levelControlTrait = dimmableLightDeviceType.matterTraits.levelControlTrait.self }
对于 Google trait,请使用 googleTraits
:
if let doorbellDeviceType = await device.types.get(GoogleDoorbellDeviceType.self) { // Accessing Google trait on the type. let doorbellPressTrait = doorbellDeviceType.googleTraits.doorbellPressTrait.self }
如需访问特定于制造商的特征,请通过 traits
属性引用该特征,但在前面加上制造商的软件包名称:
let deviceType = await device1?.types.get(OnOffLightDeviceType.self) // Accessing custom trait on the type. if let spinnerTrait = deviceType?.traits[ExampleOrganization.SpinnerTrait.self] { let rpmVal = spinnerTrait.attributes.rpm }
读取设备状态
请查看以下示例,了解如何从设备的开/关 trait 检查 OnOff
属性:
let lightDevices = devices.filter { $0.types.contains(OnOffLightDeviceType.self) } let light1 = lightDevices.first let lightDeviceTypeOptional = await light1?.types.get(OnOffLightDeviceType.self) if let onOffTrait = lightDeviceTypeOptional?.matterTraits.onOffTrait { let onOffVal = onOffTrait.attributes.onOff }
获取具有特定 trait 的设备列表
如需获取具有特定特征的设备列表,您需要迭代设备、每部设备的设备类型以及每种设备类型的特征。例如,如需获取住宅中所有具有开/关 trait 的设备的列表,请执行以下操作:
// Get all light devices that support levelControl var levelControlDevices: [HomeDevice] = [] var allDevices = try await home.devices().list() for device in allDevices { if let deviceType = await device.types.get(OnOffLightDeviceType.self) { if deviceType.traits.contains(Matter.LevelControlTrait.self) { levelControlDevices.append(device) } } }
如需查看 Home API 中提供的特征的完整列表,请参阅 iOS 上的 trait 索引。
获取具有类似设备类型的设备列表
如需获取代表住宅中所有灯具的设备列表,请执行以下操作:
// Get a list of devices with similar device types (lights) let lightDevices = try await self.home.devices().list().compactMap { $0.types.contains(DimmableLightDeviceType.self) || $0.types.contains(OnOffLightDeviceType.self) || $0.types.contains(ColorTemperatureLightDeviceType.self) || $0.types.contains(ExtendedColorLightDeviceType.self) }
Home API 中有多种设备类型可以代表核心设备类型。例如,没有“灯”设备类型。相反,有四种不同的设备类型可以表示灯具,如前面的示例所示。因此,若要全面了解住宅中更高级别的设备类型,必须包含多个设备类型。
如需查看 Home API 中提供的设备类型及其特征的完整列表,请参阅 iOS 上受支持的设备类型。
获取设备的供应商名称、供应商 ID 或产品 ID
BasicInformationTrait
trait 包含设备的供应商 ID、产品 ID、产品名称和序列号等信息:
guard let vendorName = basicInfoTrait.attributes.vendorName else { fatalError("Failed to get vendorName") } guard let vendorID = basicInfoTrait.attributes.vendorID else { fatalError("Failed to get vendorID") } guard let productID = basicInfoTrait.attributes.productID else { fatalError("Failed to get productID") }
识别云到云设备
如果您是设备制造商并构建 Cloud-to-cloud 设备,为了通过 BasicInformationTrait
识别您的 Cloud-to-cloud 设备,您可以在其 SYNC
响应中添加以下字符串字段:
连接标准联盟 (CSA) 签发的供应商 ID:
"matterOriginalVendorId": "0xfff1",
用于唯一标识供应商商品的商品标识码:
"matterOriginalProductId": "0x1234",
设备的唯一标识符,采用制造商专有的构建方式:
"matterUniqueId": "matter-device-id",
输入这些字符串字段时,请使用您的 Matter 供应商 ID 和商品 ID(如果有)。如果您不是 CSA 会员,并且未获得这些 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 中的设备和特征具有关联的元数据,这有助于管理应用中的用户体验。
Home API 中的每个 trait 都包含一个 sourceConnectivity
属性,其中包含与 trait 的在线状态和本地性(本地或远程路由)相关的信息。
获取设备的主要类型
某些设备可能会通过 Home API 呈现多种设备类型。为确保在应用中向用户显示适用于其设备的选项(例如设备控制和建议的自动化操作),请务必检查设备类型是否为设备的主要类型。
if let deviceType = await device?.types.get(HumiditySensorDeviceType.self) { if deviceType.metadata.isPrimaryType { print("Humidity Sensor is the primary type on this device.") } else { print("Humidity Sensor isn't the primary type on this device.") } }
检查 trait 是否在线
读取 connectivityState
属性以检查 trait 的连接性:
let levelControlConnectivity = levelControlTrait.metadata.sourceConnectivity .connectivityState
如果设备无法连接到互联网,某些 trait(通常是 Google smart home trait)可能会显示为离线。这是因为这些 trait 是基于云的,没有本地路由。
检查设备的连接情况
实际上,系统会在设备类型级别检查设备的连接性,因为某些设备支持多种设备类型。返回的状态是该设备上所有 trait 的连接状态的组合。
let lightConnectivity = dimmableLightDeviceType.metadata.sourceConnectivity .connectivityState
如果混合设备类型且未连接到互联网,则可能会观察到 partiallyOnline
状态。由于本地路由,Matter 标准 trait 可能仍处于在线状态,但基于云的 trait 将处于离线状态。
检查 trait 的网络路由
Home API 中也提供 trait 的地区性。dataSourceLocality
表示 trait 是远程路由(通过云)、本地路由(通过本地集线器)还是点对点路由(直接从设备到设备,无集线器)。
例如,当应用正在启动且尚未到达用于设备连接的集线器或服务器时,可能会出现未知本地性值 unspecified
。这些设备无法访问,并且会拒绝来自命令或事件的互动请求。客户可以自行决定如何处理此类设备。
let levelControlLocality = levelControlTrait.metadata.sourceConnectivity .dataSourceLocality
检查设备的网络路由
与连接性一样,系统会在设备类型级别检查本地性。返回的状态是该设备上所有 trait 的本地性的组合。
let lightLocality = dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality
在与 partiallyOnline
连接类似的场景中,可能会观察到 mixed
状态:某些 trait 基于云,而其他 trait 则是本地的。
API 列表
创建 Home
的实例后,您可以通过该实例访问以下设备 API:
API | 说明 |
---|---|
device(id:) |
为指定设备返回 Publisher ,该 Publisher 会在设备状态发生变化时发出设备状态。 |
devices() |
获取 Google 账号中所有结构中的所有设备。返回一个 Query<HomeDevice> ,用于提供进一步的检索和过滤选项。 |
获得 HomeDevice
后,您可以通过它访问以下 API:
API | 说明 |
---|---|
id |
设备的唯一系统 ID。 |
name |
用户提供的设备名称。 |
structureID |
分配给设备的结构的 ID。返回 String? 。 |
roomID |
设备所属房间的 ID。返回 String? 。 |
types |
获取设备上的特定类型或所有可用类型。 |
isMatterDevice |
如果设备由 Matter 支持。 |
sourceConnectivity |
设备的来源连接性,表示设备特征的汇总连接状态和网络位置信息。 |