Compila una app para dispositivos móviles con las APIs de Home en iOS

1. Introducción

f154e30306882c74.png

¿Qué son las APIs de Home?

Las APIs de Google Home proporcionan un conjunto de bibliotecas para que los desarrolladores aprovechen el ecosistema de Google Home. Con las APIs de Home, los desarrolladores pueden crear apps que permitan poner en funcionamiento y controlar dispositivos inteligentes para la casa sin problemas.

3e11583c779a2cec.png

En este video, se proporciona una breve explicación de la app para dispositivos móviles que compilarás, así que sigue el video mientras realizas el codelab.

Componentes de las APIs de Home

Las APIs de Home se componen de lo siguiente:

  • APIs de Device y Structure: Interactúa con la casa de un usuario. Las apps pueden usar estas APIs para leer información sobre dispositivos, habitaciones y estructuras (por ejemplo, ver la temperatura actual del termostato) y controlar dispositivos (por ejemplo, cambiar el punto de ajuste del termostato).
  • API de Commissioning: Permite comisionar (configurar) nuevos dispositivos Matter en la estructura con el mínimo esfuerzo.
  • API de Automation: Crea, borra y consulta las automatizaciones que se ejecutan en la casa de un usuario.

Requisitos previos

Qué aprenderás

  • Cómo compilar una app para iOS con las APIs de Home y las prácticas recomendadas
  • Cómo usar las APIs de Device y Structure para representar y controlar una casa inteligente
  • Cómo usar la API de Commissioning para agregar dispositivos al ecosistema de Google Home
  • Cómo usar la API de Automation para crear una automatización básica

2. Configura Tu casa

Prepara los dispositivos

El Google Home Playground ofrece una variedad de dispositivos inteligentes para la casa emulados y prediseñados, y se recomienda para explorar todo el potencial de las APIs de Home, en especial si tienes una cantidad limitada de dispositivos en tu casa.

Sigue las instrucciones para acceder a Google Home Playground y completar la vinculación de la cuenta en la app de Google Home. Después de completar este paso, deberías poder ver los dispositivos en la pestaña "Dispositivos" de la app de Google Home.

c892afce113abe8f.png

3. Cómo prepararte

Obtén el código de la app de ejemplo

Comienza por clonar el código fuente de GitHub:

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

El directorio de ejemplo contiene dos ramas, start y finished, para este codelab.

  • start: Es el código de partida para este proyecto, en el que realizarás cambios para completar el codelab.
  • finished: Es el código completo de este codelab, que se usa para verificar tu trabajo.

Explora el código de inicio

Para comenzar este codelab, cambia a la rama start del repositorio clonado:

git checkout start

Esta rama contiene el código de partida del proyecto. Modificarás este código a lo largo del codelab para implementar la funcionalidad completa. La app de ejemplo del codelab proporciona una estructura básica compilada en Swift para interactuar con el SDK de las APIs de Home para iOS. Echemos un vistazo rápido a los componentes clave del proyecto start:

  • Main Entry (GoogleHomeAPISampleIOSApp): Se encuentra en GoogleHomeAPISampleIOS/Main/GoogleHomeAPISampleIOS.swift y es el punto de entrada principal de la app. Configura e inicializa el SDK, y establece la interfaz de usuario principal.
  • Core Views (View/):
    • MainView.swift: Es la vista raíz después del lanzamiento, que contiene el NavigationView principal. Controla la selección de la estructura activa de Google Home y muestra el StructureView correspondiente.
    • StructureView.swift: Muestra el contenido de la estructura seleccionada actualmente, con pestañas para cambiar entre una cuadrícula de Dispositivos y la lista de Automatizaciones. También proporciona menús para agregar habitaciones o dispositivos.
    • DeviceView.swift: Representa la tarjeta interactiva de un solo dispositivo dentro de la cuadrícula StructureView.
    • AutomationsView.swift: Muestra la lista de automatizaciones existentes para la estructura y proporciona navegación para crear o ver detalles de automatización.
  • ViewModels (ViewModel/): Estas clases administran el estado y la lógica de las vistas.
    • AccountViewModel.swift: Controla la conexión al objeto Home y administra el estado de autenticación.
    • MainViewModel.swift: Administra la lista de objetos Structure disponibles y realiza un seguimiento de la estructura seleccionada.
    • StructureViewModel.swift: Administra la visualización de habitaciones y objetos DeviceControl dentro de la estructura seleccionada.
    • AutomationList.swift, AutomationViewModel.swift, etcétera: Controla la recuperación, la visualización, la creación y la administración de automatizaciones.
  • Device Controls (ViewModel/Device/):
    • DeviceControl.swift: Clase base para representar dispositivos controlables en la IU.
    • Subclases específicas (LightControl.swift, FanControl.swift, OnOffPlugInUnitControl.swift, etcétera): Implementan la lógica de la IU, el control del dispositivo y la asignación de estados para diferentes tipos de dispositivos según sus rasgos.
    • DeviceControlFactory.swift: Es responsable de crear la subclase DeviceControl adecuada para un HomeDevice determinado.
  • Commissioning (Commissioning/):
    • CommissioningManager.swift: Contiene la lógica para administrar el flujo de puesta en servicio del dispositivo Matter.
  • Utilities & UX (Utils/, UX/, Storage/): Contiene código auxiliar para elementos de la IU (colores, dimensiones), control de errores, almacenamiento de datos (SelectedStructureStorage.swift) y otras utilidades.

A lo largo de este codelab, encontrarás comentarios como TODO o bloques de código y alertas comentados en el proyecto start. Estas marcas indican las secciones en las que agregarás o quitarás las marcas de comentario del código para implementar la funcionalidad requerida, siguiendo los pasos proporcionados.

Crea archivos de configuración de implementación de Apple

Para configurar App Attest, sigue las instrucciones para crear archivos de configuración de implementación de Apple. Ten en cuenta que, después de la configuración, la app solo se puede implementar en un dispositivo real, no en un simulador.

Configura la autenticación

Para obtener el ID de cliente de OAuth y habilitar las APIs de Home, primero accede a Google Cloud y crea un proyecto nuevo o selecciona uno existente. Luego, sigue los pasos proporcionados para generar el ID de cliente de OAuth, habilitar las APIs de Home y agregar tu cuenta a la lista de entidades permitidas.

Configura el SDK

Obtén el SDK para iOS de las APIs de Home y configúralo según las instrucciones de configuración que se proporcionan en Cómo configurar el SDK. Recuerda reemplazar HOME_API_TODO_ADD_APP_GROUP por tu propio grupo de apps.

Compila y ejecuta el proyecto

Después de compilar y ejecutar el proyecto con la rama start, deberían aparecer un diálogo TODO y una pantalla que muestre el mensaje "Sign in Required". La interacción de las APIs de Home se implementará en las siguientes secciones.

bd56b7080037e38a.png 9c0f08a3f4197a77.png

Nota: Para ubicar el código que se debe modificar, busca en el proyecto el texto que se muestra en el diálogo. Por ejemplo, busca "TODO: initialize Home".

4. Inicialización

Inicializa la casa

Antes de usar cualquiera de las APIs de Home para iOS, debes inicializar Home en tu app. Home es el punto de entrada de nivel superior al SDK y proporciona acceso a todas las entidades de la estructura del usuario. Cuando solicitas todas las entidades de un tipo en particular, la API devuelve un objeto Query que te permite elegir cómo recibir los resultados. En GoogleHomeAPISampleIOS/Accounts/AccountViewModel.swift, quita el comentario y la alerta en connect() para implementar la inicialización de la casa.

  /// 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).")
      }
    }
  }

Permiso para usar las APIs de Home

La pantalla de consentimiento aparecerá cuando ejecutes la app. Elige la estructura de Google Home y selecciona la cuenta que se encuentra en la lista de entidades permitidas de tu proyecto de Google Cloud.

47310f458c0094d9.png 4a571dbd9979a88c.png e29c75891a3a67af.png

5. Dispositivos y estructuras

Obtén habitaciones y dispositivos

En GoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift, quita el comentario y la alerta en getRoomsAndDevices() para obtener las habitaciones y los dispositivos de la estructura seleccionada con home.rooms() y home.devices(), respectivamente.

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

Primero, la función process() garantiza que los dispositivos estén en la misma habitación antes de hacer que interactúen como HomeDevices con DeviceControl y DeviceControlFactory.

4c677c4c294e67ca.png

Nota: Si tu dispositivo no aparece en DeviceControlFactory, se mostrará como "No compatible". Para obtener más información sobre los dispositivos compatibles, consulta la página Tipos de dispositivos compatibles en iOS.

Interactúa con un dispositivo

En un principio, el enchufe outlet1 está inactivo cuando se presiona o desliza el dedo sobre los dispositivos. Para habilitar la interacción con él, busca GoogleHomeAPISampleIOS/ViewModel/Device/OnOffPlugInUnitControl.swift y quita el comentario y la alerta dentro de la función 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)
      }
    }
  }

La función primaryAction(), que se encuentra dentro de la clase OnOffPlugInUnitControl, alterna el estado de encendido o apagado de un enchufe inteligente o de cualquier dispositivo representado por OnOffPluginUnitDeviceType.

En GoogleHomeAPISampleIOS/ViewModel/Device, hay ejemplos adicionales de controles de dispositivos.

Cómo crear una nueva habitación

La API de Structure permite crear y borrar habitaciones, así como transferir dispositivos entre ellas.

En GoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift, quita el comentario y la alerta en 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)")
      }
    }
  }

Para crear una sala nueva con structure.createRoom(), navega a la esquina superior izquierda y selecciona el ícono"+" > Agregar sala. Ingresa el nombre de la sala nueva y haz clic en "Crear sala". La nueva habitación aparecerá después de unos segundos.

b122ae6642b7da1c.png a45f785e1d51938e.png 7753b56cbdcff8d6.png

Mueve el dispositivo a otra habitación

En GoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift, quita el comentario y la alerta en 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)")
      }
    }
  }

Para cambiar la ubicación del dispositivo con structure.move(), manténlo presionado, selecciona "Mover a otra habitación" y elige la nueva habitación.

f9627592af44163d.png fd126fabb454f2bf.png 813e1e23e50cd9f6.png

Cómo borrar una habitación vacía

En GoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift, quita el comentario y la alerta en 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)")
      }
    }
  }

Para borrar una sala vacía con structure.deleteRoom(), haz clic en el ícono de papelera que se encuentra a la derecha del nombre de la sala y confirma la acción. Ten en cuenta que solo se pueden borrar las habitaciones vacías.

4f129262ad67f564.png

Nota: Vuelve a colocar el dispositivo para crear una habitación vacía.

6. Puesta en servicio

Nota: En esta sección, se requiere un centro de Google y un dispositivo Matter. Asegúrate de que el concentrador de Google en tu estructura esté en línea y sea accesible. Si no tienes un dispositivo Matter, prueba usar la app de Matter Virtual Device.

Cómo agregar un dispositivo Matter

La API de Commissioning permite que tu app agregue dispositivos Matter nuevos a la casa y a la Cuenta de Google del usuario. Esto proporciona una experiencia de configuración fluida directamente en tu app.

En GoogleHomeAPISampleIOS/Commissioning/CommissioningManager.swift, quita el comentario y la alerta en 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
    }
  }

Para crear una habitación nueva con structure.prepareForMatterCommissioning(), navega a la esquina superior izquierda y selecciona el ícono “+” > Add Device to Google Fabric. Usa MatterAddDeviceRequest para agregar el dispositivo Matter a tu habitación. Después de seleccionar la habitación y el nombre del dispositivo, este se mostrará en la pantalla "Dispositivos".

adf6cbb531787aaf.png f002bd6320bc480d.png

7. Automatización

Visualiza todas las automatizaciones de la estructura

Presiona Automatizaciones en la barra de navegación inferior. Se enumerarán todas las automatizaciones de tu estructura con structure.listAutomations().

cc6d50f72f812c24.png

Nota: Si no tienes configurada ninguna automatización de la casa, verás el mensaje "Agrega una automatización para comenzar".

Crea una automatización

Ahora que conoces las APIs de Device y Structure, y cómo agregar un dispositivo nuevo, es momento de crear una nueva automatización con la API de Automation.

En GoogleHomeAPISampleIOS/ViewModel/Automation/AutomationsRepository.swift, quita el comentario, la alerta y la automatización vacía en 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()
      }
    }
  }

Para crear una automatización que apague la luz cinco segundos después de que se encienda, ve a la vista de automatización y haz clic en el botón "+ Agregar". Luego, selecciona "Apagar la luz después de 5 segundos". Aparecerán los detalles de la automatización, incluidos starter, condition y action. Haz clic en "Guardar" para crear la automatización con structure.createAutomation().

21c1f8ea2a29134b.png 4bd36f6ed9c5f6e9.png

Nota: Las automatizaciones disponibles dependen de los dispositivos que tengas en tu casa. Si no ves ninguna automatización disponible, intenta cambiar el nombre de tu dispositivo de luz a "luz2".

Vuelve a la pestaña "Dispositivos" y enciende la luz llamada "light2". Se apagará automáticamente después de cinco segundos.

Los componentes de una automatización son los siguientes:

  • Activador: Es un evento que inicia la automatización. En este ejemplo, la automatización se iniciaría una vez que haya un cambio en OnOffTrait.
  • Condición: Verifica si el dispositivo de inicio cumple con requisitos específicos. En este caso, la automatización se ejecutaría si la luz está encendida.
  • Acción: Es la automatización que deseas realizar, pero solo si el activador cumple con los requisitos. Si se cumplen las condiciones, la luz se apagará.

Para ver más ejemplos, consulta la página Ejemplos de automatizaciones.

Cómo borrar una automatización

Se invoca el método structure.deleteAutomation() cuando deslizas el dedo hacia la izquierda en una automatización existente y presionas el ícono de papelera para quitarla de tu estructura.

dc678cd9e16f89a5.png

8. Felicitaciones

¡Felicitaciones! Creaste correctamente una app básica para la casa inteligente con las APIs de Home para iOS.

Tus logros:

  • Inicialización: Conectaste tu app al ecosistema de Google Home con Home.connect().
  • Permisos: Se encargan de la autenticación y autorización del usuario para acceder a los datos de la casa.
  • Dispositivos y estructuras: Se recuperan y muestran las habitaciones y los dispositivos con home.rooms() y home.devices().
  • Control de dispositivos: Se implementó la interacción con el dispositivo, como alternar el estado de un OnOffPluginUnitDeviceType llamando a comandos en sus rasgos.
  • Administración de la estructura: Se agregó la funcionalidad para crear habitaciones nuevas (structure.createRoom()), mover dispositivos entre habitaciones (structure.move()) y borrar habitaciones vacías (structure.deleteRoom()).
  • Puesta en servicio: Se integró el flujo de puesta en servicio del SDK para agregar nuevos dispositivos Matter (MatterAddDeviceRequest).
  • Automatización: Se exploró cómo enumerar, crear (structure.createAutomation()) y borrar (structure.deleteAutomation()) automatizaciones dentro de una estructura.

Ahora tienes una comprensión básica de cómo aprovechar las APIs de Home para crear experiencias de control de la casa inteligente enriquecidas en iOS.

Próximos pasos:

  • Explora el control de otros tipos de dispositivos que se proporcionan en la app de ejemplo (luces, ventiladores, persianas, etcétera).
  • Analiza en detalle los diferentes rasgos y comandos disponibles para varios dispositivos.
  • Experimenta con la creación de automatizaciones más complejas usando diferentes activadores, condiciones y acciones.
  • Consulta la documentación de las APIs de Home para obtener más detalles y funciones avanzadas.

¡Bien hecho!