Cómo agregar dispositivos Matter nuevos a una casa

Las APIs de Home para iOS usan un concentrador Matter para asignar un dispositivo a un tejido. Durante la puesta en marcha, la app envía un comando al SDK y, luego, al concentrador.

Configuración del proyecto de Xcode

   Implementado en la app de ejemplo para iOS   

Antes de implementar la API de Commissioning, asegúrate de agregar las capacidades, los derechos y las propiedades de Info.plist requeridos a tus destinos de Xcode:

Autorizaciones

Incluye las siguientes entradas en los archivos .entitlements de destino y extensión de tu app principal:

  • Administración de credenciales de red de Thread:

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

    Para usar este derecho en una compilación distribuida, debes enviar un formulario de solicitud de derecho a Apple. Apple requiere que demuestres tu membresía en el Thread Group y verifiques que tu Thread Border Router (TBR) esté certificado por el Thread Group.

  • Información de Wi-Fi:

    <key>com.apple.developer.networking.wifi-info</key>
    <true/>
    
  • Grupos de apps: Agrega un grupo de apps compartido para permitir que tu app principal y la extensión para agregar dispositivos de Matter se comuniquen (por ejemplo, group.com.yourdomain.appgroupname). El desarrollador crea y registra este identificador en su consola de desarrollador de Apple, y debe coincidir con el grupo de apps configurado en las capacidades de destino en Xcode. El SDK de Google Home usa este identificador en ambos destinos para sincronizar automáticamente el estado de la comisión, las credenciales de la estructura y las listas de habitaciones con un contenedor UserDefaults compartido.

Uso compartido de llaveros (opcional)

Si la extensión de tu app necesita recuperar credenciales o tokens de acceso almacenados por la app principal con UserInfo.authorizationToken(), debes configurar un grupo de acceso de llavero compartido para los destinos de la app principal y de la extensión de la app en sus plist de derechos:

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

Propiedades de Info.plist

Incluye las siguientes claves de descripción en el archivo Info.plist del destino principal de tu app:

  • Descripción del uso de la ubicación:

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Your custom message explaining why location access is needed to read the current Wi-Fi SSID</string>
    
  • Servicios de Bonjour: En NSBonjourServices, incluye los servicios necesarios para el descubrimiento local de Matter y Thread:

    <key>NSBonjourServices</key>
    <array>
        <string>_matter._tcp</string>
        <string>_matterc._udp</string>
        <string>_matterd._udp</string>
        <string>_meshcop._udp</string>
    </array>
    
  • Descripción del uso de la red local: Incluye la clave NSLocalNetworkUsageDescription con un mensaje que explique los permisos de descubrimiento de la red local.

Cómo acondicionar un dispositivo

Para poner en marcha un dispositivo Matter, haz lo siguiente:

  1. Notifica al Home APIs iOS SDK que se prepare para las solicitudes de puesta en marcha de Matter con structure.prepareForMatterCommissioning(). Este comando hará lo siguiente:

    • Verifica que se haya otorgado el permiso.
    • Asegúrate de que el concentrador esté en línea y sea accesible.
    • Asegúrate de que no haya otra sesión de puesta en marcha activa en curso.
    do {
      try await structure.prepareForMatterCommissioning()
    } catch {
      // Failed to prepare for Matter Commissioning
      return
    }
    
  2. Crea una solicitud con MatterAddDeviceRequest() para iniciar el flujo de asistencia de Matter de Apple.

    let topology = MatterAddDeviceRequest.Topology(
      ecosystemName: "Google Home",
      homes: [MatterAddDeviceRequest.Home(displayName: structure.name)]
    )
    
    let request = MatterAddDeviceRequest(topology: topology)
    
  3. Realiza la solicitud con perform(). Si se produce un error, cancela la solicitud de puesta en marcha con 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. Crea un App Group ID en la consola para desarrolladores de Apple para permitir que la app se comunique con la extensión MatterAddDevice cuando se ponga en marcha el dispositivo.

    También deberás actualizar el identificador de paquete de la aplicación y los perfiles de aprovisionamiento para usar este ID de grupo.

  5. Cuando inicialices, configura la instancia de Home para que use el identificador de grupo.

    func application(_ application: UIApplication, didFinishLaunchingWithOptions
    launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
      Home.configure {
        $0.sharedAppGroup = "group.com.sample.app.commissioning"
      }
    
      return true
    }
    
  6. Implementa la extensión de la app de Matter para iOS de Apple.

    En el código de muestra, se incluye un ejemplo de implementación de una subclase de la API MatterAddDeviceExtensionRequestHandler de Apple.

    Como mínimo, agrega el framework de GoogleHomeMatterCommissionerSDK al destino de la extensión y anula tres métodos para llamar a las APIs de Google Home platformHomeMatterCommissioner.

    • 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
        }
      }
    }