可以通过适用于 iOS 的 Home API 访问结构 API。
如需使用 Structure API,请先将 GoogleHomeSDK
软件包导入到您的应用中:
import GoogleHomeSDK
错误处理
Home API 中的某些方法会抛出 HomeError
,因此我们建议您使用 do-catch
块来捕获这些调用中的 HomeError
。
处理 HomeError
时,请检查其 code
和 message
字段,了解问题所在。
任何未处理的错误都会导致应用崩溃。
如需了解详情,请参阅错误处理。
Structure API
Home
表示 Home Graph,是 Structure API 的入口点。
它提供对结构、房间和设备的引用。
Structure
表示 Home Graph 中的结构。它提供对结构元数据(例如 id
和 name
)的访问权限。
使用 structures()
获取您账号中的所有结构。这些结构以 Query
的形式返回,其中提供了多种使用其数据的方式:
API | 说明 |
---|---|
stream() |
返回一个 Publisher ,该对象会在发生更改时单独发出每个对象。 |
batched() |
返回一个 Publisher ,该 Publisher 会将当前结果作为对象 Set 发出。每次发出的 Set 都表示对象图的当前状态。 |
list() |
以对象 Set 的形式返回当前结果。 |
structures().list()
调用可能不会立即返回一组有效的结构。如果您的应用是响应式的,并且调用 stream()
来订阅所有结构更改以驱动界面,则最终应返回有效的结构列表。在其他情况下也可能会返回空结构列表,例如,如果用户的手机断开连接,或者用户已撤消向您的应用授予的权限。您应确保在应用中处理这些情况。
@Published public private(set) var structures: [Structure] = []
private var structuresCancellable: AnyCancellable?
self.structuresCancellable = home
.structures()
.batched()
.receive(on: DispatchQueue.main)
.map { Array($0) }
.catch {
Logger.error("Failed to load structures: \($0)")
return Just([Structure]())
}
.assign(to: \.structures, on: self)
结构化通话示例
获取一组结构
对 Query<Structure>
调用 list()
会返回最新的元素集:
// Get a stream of all structures accessible to the user let allStructuresChanges = try await self.home.structures() let allStructures = try? await allStructuresChanges.list()
设计响应式应用时,您需要使用 batched()
和 stream()
调用,而不是 list()
,因为这些调用会在主图发生变化时自动生成数据。
获取结构属性
有了结构列表后,您就可以访问这些结构的属性:
// Get a stream of changes taking place on a structure. let structureChanges = try await home.structures().list().filter { $0.id == structureID } // Get a snapshot of the structure. let structure = try await structureChanges.first! // Get structure properties print("id \(structure.id) ") print("name \(structure.name) ")
按名称查找结构
如果您知道结构的名称,也可以使用 name
属性访问该结构:
do { structure1 = try await home.structures().list().first(where: { $0.name == "Main House" }) } catch let error as HomeError { // Code for handling the exception }
您可以在此处访问每个结构的房源、房间和设备。
处理多种结构
如需使用多个结构,请分别获取每个结构的引用:
var structure1: Structure! var structure2: Structure! do { structure1 = try await home.structures().list().first(where: { $0.name == "Main House" }) } catch let error as HomeError { // Code for handling the exception } do { structure2 = try await home.structures().list().first(where: { $0.name == "Guest Cottage" }) } catch let error as HomeError { // Code for handling the exception }
Rooms
房间包含一组设备。房间始终是结构的一部分,一个结构可以包含多个房间。从结构中移除房间并不会从结构中移除该房间内的设备。不过,如果房间被删除,该房间中的设备将变为未分配状态。
使用 Home.rooms()
检索账号中的所有房间,然后使用 roomID = device.roomID
显示每个房间中的相应设备。
self.home.rooms().batched()
.combineLatest(self.home.devices().batched())
.receive(on: DispatchQueue.main)
.catch { error in
Logger.error("Failed to load rooms and devices: \(error)")
return Just((Set<Room>(), Set<HomeDevice>()))
}
.map { rooms, devices in
var devicesByRoom = [Room: [HomeDevice]]()
for room in rooms where room.structureID == currentStructureID {
devicesByRoom[room] = devices.filter { $0.roomID == room.id }
}
return devicesByRoom
}.assign(to: &self.$devicesByRoom)
会议室通话示例
获取会议室列表
使用 Home
类,您可以获取会议室列表并访问这些会议室的属性:
let allRoomsChanges = self.home.rooms() let allRooms = try await allRoomsChanges.list() let room = allRooms.first! XCTAssertTrue(allRooms.contains(room)) print("id \(room.id) ") print("name \(room.name) ")
创建聊天室
如需在 Structure
中创建新房间,请执行以下操作:
let testName = "Test Room Name" var newRoom: Room! do { newRoom = try await structure.createRoom(name: testName) XCTAssertNotNil(newRoom) } catch let error as HomeError { // Code for handling the exception }
删除房间
或者,您也可以删除聊天室:
val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull() structure.deleteRoom(roomToDelete!!)
您还可以使用会议室 ID 删除会议室:
let roomToDelete = allRooms.first(where: { $0.id == room.id }) if let roomToDelete1 = roomToDelete { do { try await structure.deleteRoom(roomToDelete1) } catch let error as HomeError { // Code for handling the exception } }
如果删除包含设备的房间,这些设备仍会保留在住宅结构中,但不再分配到任何房间。
将设备移至其他房间
借助 Structure
,您还可以将设备移至其他房间:
do { try await structure.move(device: light, to: room) } catch let error as HomeError { // Code for handling the exception }
更改会议室名称
调用 setName(_:)
方法可更改房间的名称:
let updatedRoom = try await theRoom.setName("new room name")
更改房间名称时,原始 Room
结构体保持不变,更改会反映在返回的更新后的 Room
对象中。
如果名称超过 60 个 Unicode 码位(字符)的限制,系统会截断名称,但不会抛出任何错误。开发者负责处理过长的名称,例如,可以决定是否要告知用户名称将被截断。
API 列表
创建 Home
的实例后,可以通过该实例访问以下 Structure API:
API | 说明 |
---|---|
devices() |
获取此账号可看到的所有设备。 |
device(id:) |
获取指定设备的 Publisher ,该 Publisher 会在当前状态发生变化时发出信号,并在任何未来的状态更新时再次发出信号。 |
structures() |
获取 Google 账号中的所有结构。返回一个 Query<Structure> ,其中包含更多检索和过滤选项。 |
structure(id:) |
获取具有匹配 ID 的结构。 |
rooms() |
获取 Google 账号中的所有房间。返回一个 Query<strRoom> ,其中包含更多检索和过滤选项。 |
room(id:) |
获取指定房间的 Publisher ,该 Publisher 会发出当前状态,并在任何未来的状态更新时再次发出。 |
Structure
具有以下 API:
API | 说明 |
---|---|
deleteRoom(id:) |
删除具有指定聊天室 ID 的聊天室。 |
id |
结构的唯一系统 ID。 |
move(device:, to:) |
将设备移至结构中的其他房间。 |
move(device:, to:) |
将具有指定 ID 的设备移至具有指定 ID 的房间。 |
move(devices:, to:) |
将指定设备移至指定房间。 |
move(devices:, to:) |
将具有指定 ID 的设备移至具有指定 ID 的房间。 |
name |
用户提供的结构的名称。 |
Room
具有以下 API:
API | 说明 |
---|---|
id |
客房的唯一系统 ID。 |
name |
用户提供的聊天室名称。 |
structureID |
相应客房所属结构的唯一系统 ID。 |