使用 iOS 版 Home API 建構行動應用程式

1. 簡介

f154e30306882c74.png

什麼是 Home API?

Google Home API 提供一組程式庫,可供開發人員運用 Google Home 生態系統。開發人員可使用 Home API 建構應用程式,順暢地委派及控制智慧住宅裝置。

3e11583c779a2cec.png

這部影片會簡要介紹您要建構的行動應用程式,因此請在完成程式碼研究室時觀看影片。

Home API 的元件

Home API 包含:

  • 裝置結構 API:與使用者的住家互動。應用程式可使用這些 API 讀取裝置、房間和住家資訊 (例如查看目前的溫度控制器溫度),以及控制裝置 (例如變更溫度控制器設定點)。
  • 調試 API:輕鬆將新 Matter 裝置調試 (設定) 到 Fabric 中。
  • 自動化動作 API:建立、刪除及查詢使用者住家執行的自動化動作。

必要條件

課程內容

  • 瞭解如何使用 Home API 按照最佳做法建構 iOS 應用程式。
  • 如何使用裝置和結構體 API 代表及控制智慧住宅。
  • 如何使用 Commissioning API 將裝置新增至 Google Home 生態系統。
  • 如何使用 Automation API 建立基本自動化動作。

2. 設定「你的住家」

準備裝置

Google Home Playground 提供各種預先建構的模擬智慧住宅裝置,建議您使用這個平台充分發揮 Home API 的潛力,特別是家中裝置數量有限時。

按照操作說明登入 Google Home Playground,並在 Google Home 應用程式完成帳戶連結。完成後,您應該就能在 Google Home 應用程式的「裝置」分頁中看到裝置。

c892afce113abe8f.png

3. 開始設定

取得範例應用程式的程式碼

首先,從 GitHub 複製原始碼:

git clone https://github.com/google-home/google-home-api-sample-app-ios.git

範例目錄包含本程式碼研究室的兩個分支版本:startfinished

  • start:本專案的範例程式碼。您需要加以修改,才能完成這個程式碼研究室。
  • finished:本程式碼研究室完成後的程式碼,可用來檢查您的成果。

探索「範例」程式碼

首先,請切換至複製存放區的 start 分支版本,開始進行這個程式碼研究室:

git checkout start

這個分支版本包含專案的範例程式碼。您會在整個程式碼研究室中修改這段程式碼,實作完整功能。程式碼研究室範例應用程式提供以 Swift 建構的基本結構,可與 Home APIs iOS SDK 互動。讓我們快速瞭解 start 專案中的主要元件:

  • Main Entry (GoogleHomeAPISampleIOSApp):位於 GoogleHomeAPISampleIOS/Main/GoogleHomeAPISampleIOS.swift 中,是應用程式的主要進入點。這個類別會設定並初始化 SDK,以及設定主要使用者介面。
  • Core Views (View/)
    • MainView.swift:啟動後的根檢視區塊,內含主要 NavigationView。這個函式負責選取有效的 Google Home 結構,並顯示對應的 StructureView
    • StructureView.swift:顯示目前所選結構的內容,並使用分頁在「裝置」格線和「自動化動作」清單之間切換。此外,你也可以透過選單新增房間或裝置。
    • DeviceView.swift:代表 StructureView 格線中單一裝置的互動式資訊方塊。
    • AutomationsView.swift:顯示結構的現有自動化動作清單,並提供導覽功能,方便您建立或查看自動化動作詳細資料。
  • ViewModels (ViewModel/):這些類別會管理檢視區塊的狀態和邏輯。
    • AccountViewModel.swift:處理與 Home 物件的連線,並管理驗證狀態。
    • MainViewModel.swift:管理可用 Structure 物件的清單,並追蹤所選結構。
    • StructureViewModel.swift:管理所選結構中的房間和 DeviceControl 物件顯示方式。
    • AutomationList.swiftAutomationViewModel.swift 等等:處理擷取、顯示、建立及管理自動化動作。
  • Device Controls (ViewModel/Device/)
    • DeviceControl.swift:代表 UI 中可控制裝置的基本類別。
    • 特定子類別 (LightControl.swiftFanControl.swiftOnOffPlugInUnitControl.swift 等):根據特徵實作不同裝置類型的 UI 邏輯、裝置控制和狀態對應。
    • DeviceControlFactory.swift:負責為指定 HomeDevice 建立適當的 DeviceControl 子類別。
  • Commissioning (Commissioning/)
    • CommissioningManager.swift:包含管理 Matter 裝置委派流程的邏輯。
  • Utilities & UX (Utils/, UX/, Storage/):包含 UI 元素 (顏色、尺寸)、錯誤處理、資料儲存 (SelectedStructureStorage.swift) 和其他公用程式的輔助程式碼。

在本程式碼研究室中,您會在 start 專案中看到 TODO 等註解,或是註解掉的程式碼區塊和快訊。這些標記代表您將新增或取消註解程式碼的部分,以便按照提供的步驟實作必要功能。

建立 Apple 部署設定檔

如要設定 App Attest,請按照操作說明建立 Apple 部署設定檔。請注意,設定完成後,應用程式只能部署在實體裝置上,無法部署在模擬器中。

設定驗證方法

如要取得 OAuth 用戶端 ID 並啟用 Home API,請先登入 Google Cloud,然後建立新專案或選取現有專案。然後按照提供的步驟產生 OAuth 用戶端 ID、啟用 Home API,並將帳戶加入許可清單。

設定 SDK

取得 Home APIs iOS SDK,並參閱「設定 SDK」一文中的設定操作說明進行設定。請記得將 HOME_API_TODO_ADD_APP_GROUP 替換為您自己的應用程式群組。

建構並執行專案

使用 start 分支版本建構及執行專案後,應該會出現 TODO 對話方塊和顯示「需要登入」的畫面。我們將在下列各節中實作 Home API 互動。

bd56b7080037e38a.png 9c0f08a3f4197a77.png

注意:在專案中搜尋對話方塊中顯示的文字,找出需要修改的程式碼。例如搜尋「TODO: initialize Home」。

4. 初始化

初始化 Home

使用任何 iOS 版 Home API 前,您必須先在應用程式中初始化 HomeHome 是 SDK 的頂層項目,可存取使用者結構中的所有實體。要求特定類型的所有實體時,API 會傳回 Query 物件,讓您選擇接收結果的方式。在 GoogleHomeAPISampleIOS/Accounts/AccountViewModel.swift 中移除註解和警示,以實作住家初始化作業。connect()

  /// TODO: initialize Home
  /// Remove comments to initialize Home and handling permission.
  private func connect() {
    Task {
      do {
        self.home = try await Home.connect()
      } catch {
        Logger().error("Auth error: \(error).")
      }
    }
  }

使用 Home API 的權限

執行應用程式時,系統會顯示同意畫面。請選擇 Google Home 結構,然後選取 Google Cloud 專案允許清單中的帳戶。

47310f458c0094d9.png 4a571dbd9979a88c.png e29c75891a3a67af.png

5. 裝置和結構

取得會議室和裝置

GoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift 中,移除 getRoomsAndDevices() 中的註解和快訊,即可分別透過 home.rooms()home.devices() 取得所選結構中的房間和裝置。

  /// TODO: get rooms and devices
  /// Remove comments to get the rooms and devices from home entry
  private func getRoomsAndDevices(){
    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 { [weak self] rooms, devices in
        guard let self = self else { return [] }
        self.hasLoaded = true
        return self.process(rooms: rooms, devices: devices)
      }
      /// receive from .map and .assign() to publisher entries
      .assign(to: &self.$entries)
  }

process() 函式會先確保裝置位於同一個房間,再使用 DeviceControlDeviceControlFactory 讓裝置以 HomeDevices 形式互動。

4c677c4c294e67ca.png

注意:如果裝置未列在 DeviceControlFactory 中,系統會顯示「不支援」。如要進一步瞭解支援的裝置,請參閱「iOS 支援的裝置類型」頁面。

與裝置互動

在裝置上輕觸或滑動時,插頭 outlet1 最初會處於非使用中狀態。如要啟用互動功能,請找出 GoogleHomeAPISampleIOS/ViewModel/Device/OnOffPlugInUnitControl.swift,然後移除 primaryAction() 函式中的註解和警示。

  /// TODO: primary action of OnOffPlug
  /// Toggles the plug; usually provided as the `action` callback on a Button.
  public override func primaryAction() {
    self.updateTileInfo(isBusy: true)
    Task { @MainActor [weak self] in
      guard
        let self = self,
        let onOffPluginUnitDeviceType = self.onOffPluginUnitDeviceType,
        let onOffTrait = onOffPluginUnitDeviceType.matterTraits.onOffTrait
      else { return }

      do {
        try await onOffTrait.toggle()
      } catch {
        Logger().error("Failed to to toggle OnOffPluginUnit on/off trait: \(error)")
        self.updateTileInfo(isBusy: false)
      }
    }
  }

primaryAction() 函式位於 OnOffPlugInUnitControl 類別中,可切換智慧插座或 OnOffPluginUnitDeviceType 代表的任何裝置的開/關狀態。

如需其他裝置控制範例,請參閱 GoogleHomeAPISampleIOS/ViewModel/Device

建立新房間

結構體 API 可用於建立及刪除房間,以及在房間之間轉移裝置。

GoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift 中,移除 addRoom() 中的註解和警示。

  /// TODO: add room
  /// Add a new room in a given structure.
  func addRoom(name: String, structure: Structure) {
    Task {
      do {
        // The view will be updated with the values from the devices publisher.
        _ = try await structure.createRoom(name: name)
      } catch {
        Logger().error("Failed to create room: \(error)")
      }
    }
  }

如要使用 structure.createRoom() 建立新會議室,請前往左上角,依序選取「+」圖示 >「新增會議室」。輸入新的聊天室名稱,然後按一下「建立聊天室」。新房間會在幾秒後顯示。

b122ae6642b7da1c.png a45f785e1d51938e.png 7753b56cbdcff8d6.png

將裝置移到其他房間

GoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift 中,移除 moveDevice() 中的註解和警示。

  /// TODO: move device
  /// Move a device into a different room.
  func moveDevice(device deviceID: String, to roomID: String, structure: Structure) {
    Task {
      do {
        _ = try await structure.move(device: deviceID, to: roomID)
      } catch {
        Logger().error("Failed to move to room: \(error)")
      }
    }
  }

如要移動裝置,請長按 structure.move(),選取「移至其他房間」,然後選擇新房間。

f9627592af44163d.png fd126fabb454f2bf.png 813e1e23e50cd9f6.png

刪除空白聊天室

GoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift 中,移除 removeRoom() 中的註解和警示。

  /// TODO: delete room
  /// Delete an empty room in a given structure.
  func removeRoom(id: String, structure: Structure) {
    Task {
      do {
        // The view will be updated with the values from the devices publisher.
        _ = try await structure.deleteRoom(id: id)
      } catch {
        Logger().error("Failed to remove room: \(error)")
      }
    }
  }

如要刪除空白聊天室 structure.deleteRoom(),請按一下聊天室名稱右側的垃圾桶圖示,然後確認刪除。請注意,只有空白的房間才能刪除。

4f129262ad67f564.png

注意:將裝置移回原先的房間,即可建立空房間。

6. 委任

注意:本節需要 Google Hub 和支援 Matter 的裝置。確認結構中的 Google Hub 已連上網路且可連線。如果沒有 Matter 裝置,請改用 Matter 虛擬裝置應用程式。

新增 Matter 裝置

應用程式可透過 Commissioning API,將新的 Matter 裝置新增至使用者的住家和 Google 帳戶。這能讓使用者直接在應用程式中順暢完成設定。

GoogleHomeAPISampleIOS/Commissioning/CommissioningManager.swift 中,移除 addMatterDevice() 中的註解和警示。

  /// TODO: add Matter Device
  /// Starts the Matter device commissioning flow to add the device to the user's home.
  /// - Parameters:
  ///   - structure: The structure to add the device to.
  ///   - add3PFabricFirst: Whether to add the device to a third party fabric first.
  public func addMatterDevice(to structure: Structure, add3PFabricFirst: Bool) {
    self.isCommissioning = true

    /// pass if it's 1p or 3p commissioning
    let userDefaults = UserDefaults(
      suiteName: CommissioningManager.appGroup)
    userDefaults?.set(
    add3PFabricFirst, forKey: CommissioningUserDefaultsKeys.shouldPerform3PFabricCommissioning)

    Task {
      do {
        try await structure.prepareForMatterCommissioning()
      } catch {
        Logger().error("Failed to prepare for Matter Commissioning: \(error).")
        self.isCommissioning = false
        return
      }

      // Prepare the Matter request by providing the ecosystem name and home to be added to.
      let topology = MatterAddDeviceRequest.Topology(
        ecosystemName: "Google Home",
        homes: [MatterAddDeviceRequest.Home(displayName: structure.name)]
      )
      let request = MatterAddDeviceRequest(topology: topology)

      do {
        Logger().info("Starting MatterAddDeviceRequest.")
        try await request.perform()
        Logger().info("Completed MatterAddDeviceRequest.")
        let commissionedDeviceIDs = try structure.completeMatterCommissioning()
        Logger().info("Commissioned device IDs: \(commissionedDeviceIDs).")
      } catch let error {
        structure.cancelMatterCommissioning()
        Logger().error("Failed to complete MatterAddDeviceRequest: \(error).")
      }

      self.isCommissioning = false
    }
  }

如要使用 structure.prepareForMatterCommissioning() 建立新房間,請前往左上角,依序選取「+」圖示 >「Add Device to Google Fabric」。並使用 MatterAddDeviceRequest 將 Matter 裝置新增至房間。選取房間和裝置名稱後,裝置會顯示在「裝置」畫面中。

adf6cbb531787aaf.png f002bd6320bc480d.png

7. 自動化

查看住家結構體中的所有自動化動作

輕觸底部導覽列中的「自動化動作」。系統會列出結構中的所有自動化動作,並顯示 structure.listAutomations()

cc6d50f72f812c24.png

注意:如果尚未設定任何住家自動化動作,系統會顯示「新增自動化動作即可開始使用」。

建立自動化作業

您已熟悉裝置和結構體 API,也知道如何新增裝置,現在可以使用 Automation API 建立新的自動化動作。

GoogleHomeAPISampleIOS/ViewModel/Automation/AutomationsRepository.swift 中,移除 lightAutomation() 中的註解、快訊和空白自動化動作。

  /// TODO: create automation
  /// - Parameter devices: devices in current selected structure
  /// - Returns: the automation object to be created
  /// This automation will turn off the light after 5 seconds.
  public func lightAutomation(devices: Set<HomeDevice>) async throws -> any DraftAutomation {
    let light = devices.first { $0.name == "light2" }
    
    guard let light else {
      Logger().error("Unable to find light device with name light2")
      throw HomeError.notFound("No devices support OnOffLightDeviceType")
    }
    
    return automation(
      name: "Turn off light after 5 seconds",
      description:
        """
        Turns off light2 after it has been on for 5 seconds.
        """
    ) {
      let onOffStarter = starter(light, OnOffLightDeviceType.self, OnOffTrait.self)
      onOffStarter
      condition {
        onOffStarter.onOff.equals(true)
      }
      delay(for: Duration.seconds(5))
      action(light, OnOffLightDeviceType.self) {
        OnOffTrait.off()
      }
    }
  }

如要建立自動化動作,在燈光開啟五秒後關閉,請前往自動化動作檢視畫面,然後按一下「+ 新增」按鈕。然後選取「5 秒後關燈」。系統會顯示自動化詳細資料,包括 starterconditionaction。按一下「儲存」,即可透過 structure.createAutomation() 建立自動化動作。

21c1f8ea2a29134b.png 4bd36f6ed9c5f6e9.png

注意:可用的自動化動作取決於住家中的裝置。如果沒有看到任何可用的自動化動作,請嘗試將燈具裝置重新命名為「light2」。

返回「裝置」分頁,然後開啟名為「light2」的燈。五秒後就會自動關閉。

自動化動作的元件包括:

  • 啟動條件:這是啟動自動化動作的事件。在本例中,只要 OnOffTrait 發生變更,自動化動作就會啟動。
  • 條件:檢查啟動裝置是否符合特定需求。在這種情況下,如果燈亮著,就會執行自動化動作。
  • 動作:這是您要執行的自動化動作,但前提是啟動條件符合規定。如果符合條件,燈具就會關閉。

如需更多範例,請參閱「自動化動作範例」頁面。

刪除自動化動作

當您在現有自動化動作上向左滑動,然後輕觸垃圾桶圖示,從結構中移除自動化動作時,系統會叫用 structure.deleteAutomation() 方法。

dc678cd9e16f89a5.png

8. 恭喜

恭喜!您已成功使用 iOS 適用的 Home API 建構基本的智慧住宅應用程式。

成就

  • 初始化:使用 Home.connect() 將應用程式連結至 Google Home 生態系統。
  • 權限:處理使用者驗證和授權,以存取住家資料。
  • 裝置和結構:使用 home.rooms()home.devices() 擷取及顯示房間和裝置。
  • 裝置控制:實作裝置互動,例如透過呼叫特徵的指令切換 OnOffPluginUnitDeviceType 的狀態。
  • 結構管理:新增建立新房間 (structure.createRoom())、在房間之間移動裝置 (structure.move()) 和刪除空房間 (structure.deleteRoom()) 的功能。
  • 委派:整合 SDK 的委派流程,新增 Matter 裝置 (MatterAddDeviceRequest)。
  • 自動化:瞭解如何在結構中列出、建立 (structure.createAutomation()) 及刪除 (structure.deleteAutomation()) 自動化動作。

您現在已初步瞭解如何運用 Home API,在 iOS 裝置上打造豐富的智慧住宅控制體驗。

後續步驟

  • 探索如何控制範例應用程式提供的其他裝置類型 (燈具、風扇、百葉窗等)。
  • 深入瞭解各種裝置適用的不同特徵和指令。
  • 你可以嘗試使用不同的啟動條件、限制條件和動作,建立更複雜的自動化動作。
  • 如要瞭解更多進階功能和詳細資料,請參閱 Home API 說明文件

非常好!