家に新しい Matter デバイスを追加する

iOS 用 Home API は、Matter ハブを使用してデバイスをファブリックにコミッショニングします。コミッショニング中、アプリはコマンドを SDK に送信し、次にハブに送信します。

Xcode プロジェクトの構成

Commissioning API を実装する前に、必要な機能、利用資格、Info.plist プロパティを Xcode ターゲットに追加してください。

利用資格

メインアプリのターゲットと拡張機能の .entitlements ファイルに次のエントリを含めます。

  • Thread ネットワーク認証情報の管理:

    <key>com.apple.developer.networking.manage-thread-network-credentials</key>
    <true/>
    

    配布ビルドでこの利用資格を使用するには、利用資格リクエスト フォームを Apple に送信する必要があります。Apple では、Thread Group のメンバーシップを証明し、Thread Border Router が Thread Group によって認定されていることを確認する必要があります。

  • Wi-Fi 情報:

    <key>com.apple.developer.networking.wifi-info</key>
    <true/>
    
  • アプリグループ: メインアプリと Matter Add Device Extension が通信できるように、共有アプリグループを追加します (例: group.com.yourdomain.appgroupname)。 この識別子は、デベロッパーが Apple Developer Console で作成して登録します。Xcode のターゲット機能で構成されているアプリグループと一致する必要があります。Google Home SDK は、両方のターゲットでこの識別子を使用して、共有 UserDefaults コンテナを使用してコミッショニング状態、ファブリック認証情報、部屋リストを自動的に同期します。

キーチェーンの共有(省略可)

アプリ拡張機能で、UserInfo.authorizationToken() を使用してメインアプリに保存されている認証情報またはアクセス トークンを取得する必要がある場合は、メインアプリとアプリ拡張機能の両方のターゲットで、利用資格 plist に共有キーチェーン アクセス グループを構成する必要があります。

<key>keychain-access-groups</key>
<array>
    <string>$(AppIdentifierPrefix)your.shared.keychain.group</string>
</array>

Info.plist プロパティ

メインアプリのターゲットの Info.plist に次の説明キーを含めます。

  • 位置情報の使用状況の説明:

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Your custom message explaining why location access is needed to read the current Wi-Fi SSID</string>
    
  • Bonjour サービス: NSBonjourServices で、ローカルの Matter と Thread の検出に必要なサービスを含めます。

    <key>NSBonjourServices</key>
    <array>
        <string>_matter._tcp</string>
        <string>_matterc._udp</string>
        <string>_matterd._udp</string>
        <string>_meshcop._udp</string>
    </array>
    
  • ローカル ネットワークの使用状況の説明: ローカル ネットワーク検出権限について説明するメッセージを含む NSLocalNetworkUsageDescription キーを含めます。

デバイスをコミッショニングする

Matter デバイスをコミッショニングするには:

  1. Home APIs iOS SDKMatter コミッショニング リクエストの準備を行うよう structure.prepareForMatterCommissioning() で通知します。 このコマンドは次の処理を行います。

    • 権限が付与されていることを確認します。
    • ハブがオンラインで到達可能であることを確認します。
    • 他にアクティブなコミッショニング セッションがないことを確認します。
    do {
      try await structure.prepareForMatterCommissioning()
    } catch {
      // Failed to prepare for Matter Commissioning
      return
    }
    
  2. MatterAddDeviceRequest() でリクエストを作成して、Apple の Matter サポートフローを開始します。

    let topology = MatterAddDeviceRequest.Topology(
      ecosystemName: "Google Home",
      homes: [MatterAddDeviceRequest.Home(displayName: structure.name)]
    )
    
    let request = MatterAddDeviceRequest(topology: topology)
    
  3. perform() でリクエストを実行します。エラーが発生した場合は、 コミッショニング リクエストをstructure.cancelMatterCommissioning()でキャンセルします。

    do {
      // Starting MatterAddDeviceRequest.
      try await request.perform()
      // Successfully completed MatterAddDeviceRequest.
      let commissionedDeviceIDs = try structure.completeMatterCommissioning()
      // Commissioned device IDs.
    } catch let error {
      structure.cancelMatterCommissioning()
      // Failed to complete MatterAddDeviceRequest.
    }
    
  4. デバイスのコミッショニング時にアプリが MatterAddDevice 拡張機能と通信できるように、Apple Developer ConsoleApp Group ID を作成します。

    このグループ ID を使用するには、アプリケーション バンドル ID とプロビジョニング プロファイルも更新する必要があります。

  5. 初期化時に、グループ識別子を使用するように Home インスタンスを構成します。

    func application(_ application: UIApplication, didFinishLaunchingWithOptions
    launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
      Home.configure {
        $0.sharedAppGroup = "group.com.sample.app.commissioning"
      }
    
      return true
    }
    
  6. Apple の iOS Matter App Extension を実装します。

    サンプルコードは、Apple の MatterAddDeviceExtensionRequestHandler API のサブクラスを実装する例を示しています。

    少なくとも、GoogleHomeMatterCommissionerSDK フレームワーク を拡張機能ターゲットに追加し、3 つのメソッドをオーバーライドして Google Home platformHomeMatterCommissioner API を呼び出します。

    • commissionDevice
    • rooms
    • configureDevice
    import MatterSupport
    import GoogleHomeSDK
    import OSLog
    
    final class RequestHandler: MatterAddDeviceExtensionRequestHandler {
      // The App Group ID defined by the application to share information between the extension and main app.
      private static var appGroup = "group.com.sample.app.commissioning"
    
      ...
    
      // MARK: - Home API commissioning handlers
    
      /// Commissions a device to the Google Home ecosystem.
      /// - Parameters:
      ///   - home: The home that the device will be added to
      ///   - onboardingPayload: The payload to be sent to the Matter Commissioning SDK to commission the device.
      ///   - commissioningID: An identifier not used by the Home API SDK.
      override func commissionDevice(in home: MatterAddDeviceRequest.Home?, onboardingPayload: String, commissioningID: UUID) async throws {
        // Commission Matter device with payload.
    
        var onboardingPayloadForHub = onboardingPayload
        let homeMatterCommissioner = try HomeMatterCommissioner(appGroup: RequestHandler.appGroup)
        try await homeMatterCommissioner.commissionMatterDevice(
        onboardingPayload: onboardingPayloadForHub)
      }
    
      /// Obtains rooms from the Home Ecosystem to present to the user during the commissioning flow.
      /// - Parameter home: The home that the device will be added to.
      /// - Returns: A list of rooms if obtained from the Google Home ecosystem or an empty list if there was an error in getting them.
      override func rooms(in home: MatterAddDeviceRequest.Home?) async -> [MatterAddDeviceRequest.Room] {
        do {
          let homeMatterCommissioner = try HomeMatterCommissioner(appGroup: RequestHandler.appGroup)
          let fetchedRooms = try homeMatterCommissioner.fetchRooms()
          // Returning fetched rooms.
          return fetchedRooms
        } catch {
          // Failed to fetch rooms with error
          return []
        }
      }
    
      /// Pushes the device's configurations to the Google Home Ecosystem.
      /// - Parameters:
      ///   - name: The friendly name the user chose to set on the device.
      ///   - room: The room identifier that the user chose to put the device in.
      override func configureDevice(named name: String, in room: MatterAddDeviceRequest.Room?) async {
        // Configure Device name: room
        do {
          let homeMatterCommissioner = try HomeMatterCommissioner(appGroup: RequestHandler.appGroup)
          await homeMatterCommissioner.configureMatterDevice(
            deviceName: name, roomName: room?.displayName)
        } catch {
          // Configure Device failed with error
        }
      }
    }