iOS 上的結構體 API

您可透過 iOS 適用的 Home API 存取 Structure API。

如要使用 Structure API,請先將 GoogleHomeSDK 封裝匯入應用程式:

import GoogleHomeSDK

處理錯誤

Home API 中的某些方法會擲回 HomeError,因此建議您使用 do-catch 區塊,在這些呼叫中擷取 HomeError

處理 HomeError 時,請檢查 codemessage 欄位,瞭解發生錯誤的原因。

任何未處理的錯誤都會導致應用程式當機。

詳情請參閱「錯誤處理」一節。

Structure API

Home 代表住家圖表,也是 Structure API 的進入點。並提供結構、房間和裝置的參照。

Structure 代表住家圖表中的結構。可存取 idname 等結構中繼資料。

使用 structures() 取得帳戶中的所有結構。系統會以 Query 的形式傳回結構,並提供多種資料取用方式:

API 說明
stream() 傳回 Publisher,在發生變更時個別發出每個物件。
batched() 傳回 Publisher,該物件會將目前結果做為物件的 Set 發出。發出的每個 Set 都代表物件圖的目前狀態。
list() 以物件 Set 的形式傳回目前結果。

structures().list() 呼叫可能不會立即傳回一組有效的結構。如果應用程式是反應式,且會呼叫 stream() 訂閱所有結構變更來驅動 UI,最終應會傳回有效的結構清單。在其他情況下,系統也可能會傳回空白的結構清單,例如使用者手機失去連線,或是使用者撤銷應用程式的權限。請務必在應用程式中處理這些情況。

@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() 會傳回最新的元素 Set:

// 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)

Room 通話範例

取得會議室清單

您可以使用 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,發出目前狀態,並在日後有任何狀態更新時再次發出。
structures() 取得 Google 帳戶中的所有結構。傳回 Query<Structure>,提供進一步的擷取和篩選選項。
structure(id:) 取得具有相符 ID 的結構。
rooms() 取得 Google 帳戶中的所有房間。傳回 Query<strRoom>,提供進一步的擷取和篩選選項。
room(id:) 取得指定會議室的 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。