Создайте мобильное приложение с использованием Home API на iOS

1. Введение

f154e30306882c74.png

Что такое Home API?

API Google Home предоставляют разработчикам набор библиотек для подключения к экосистеме Google Home. С помощью API Home разработчики могут создавать приложения, которые легко вводят в эксплуатацию и контролируют устройства умного дома.

3e11583c779a2cec.png

Компоненты API Home

API Home состоят из:

  • API устройств и структур : взаимодействуют с домом пользователя. Приложения могут использовать эти API для считывания информации об устройствах, комнатах и ​​структурах (например, для просмотра текущей температуры термостата) и управления устройствами (например, для изменения заданного значения термостата).
  • Ввод в эксплуатацию API : ввод в эксплуатацию (настройка) новых устройств Matter в инфраструктуру с минимальными усилиями.
  • API автоматизации : создание, удаление и запрос автоматизаций, работающих в доме пользователя.

Предпосылки

Чему вы научитесь

  • Как создать приложение iOS с использованием API Home с использованием лучших практик.
  • Как использовать API устройств и структур для представления и управления умным домом.
  • Как использовать Commissioning API для добавления устройств в экосистему Google Home.
  • Как использовать API автоматизации для создания базовой автоматизации.

2. Обустройте свой дом

Подготовьте устройства

Google Home Playground предлагает множество готовых эмулируемых устройств для умного дома и рекомендуется для изучения всего потенциала API Home, особенно если у вас дома ограниченное количество устройств.

Следуйте инструкциям, чтобы войти в 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

Каталог примеров содержит две ветки: start и finished для этой кодовой лаборатории.

  • 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.swift , AutomationViewModel.swift и т. д.: обрабатывает выборку, отображение, создание и управление автоматизациями.
  • Device Controls (ViewModel/Device/) :
    • DeviceControl.swift : базовый класс для представления управляемых устройств в пользовательском интерфейсе.
    • Конкретные подклассы ( LightControl.swift , FanControl.swift , OnOffPlugInUnitControl.swift и т. д.): реализуют логику пользовательского интерфейса, управление устройствами и отображение состояний для различных типов устройств на основе их характеристик.
    • DeviceControlFactory.swift : отвечает за создание соответствующего подкласса DeviceControl для данного HomeDevice .
  • Commissioning (Commissioning/) :
    • CommissioningManager.swift : Содержит логику управления процессом ввода в эксплуатацию устройства Matter.
  • Utilities & UX (Utils/, UX/, Storage/) : содержит вспомогательный код для элементов пользовательского интерфейса (цвета, размеры), обработки ошибок, хранения данных ( SelectedStructureStorage.swift ) и других утилит.

В этой кодовой лаборатории вы найдете комментарии, такие как TODO или закомментированные блоки кода и оповещения в start проекте. Они отмечают разделы, в которых вы добавите или раскомментируете код для реализации требуемой функциональности, следуя предоставленным шагам.

Создание файлов конфигурации развертывания Apple

Чтобы настроить App Attest, следуйте инструкциям по созданию файлов конфигурации развертывания Apple . Обратите внимание, что после настройки приложение можно развернуть только на реальном устройстве, а не в симуляторе.

Настроить аутентификацию

Чтобы получить идентификатор клиента OAuth и включить Home API, сначала войдите в Google Cloud и либо создайте новый проект, либо выберите существующий. Затем следуйте предоставленным шагам для генерации идентификатора клиента OAuth и включения Home API , а также добавьте свою учетную запись в список разрешенных.

Настройте SDK

Получите Home APIs iOS SDK и настройте его, следуя инструкциям по настройке, приведенным в разделе Настройка SDK . Не забудьте заменить HOME_API_TODO_ADD_APP_GROUP на свою собственную группу приложений.

Постройте и запустите проект

После сборки и запуска проекта с start веткой должен появиться диалог TODO и экран с надписью «Требуется вход». Взаимодействие с API Home будет реализовано в следующих разделах.

bd56b7080037e38a.png9c0f08a3f4197a77.png

Примечание : Найдите код, который необходимо изменить, выполнив поиск по проекту для текста, отображаемого в диалоговом окне. Например, выполните поиск по запросу "TODO: initialize Home".

4. Инициализация

Инициализировать дом

Перед использованием любого из API Home для iOS необходимо инициализировать Home в своем приложении. Home — это запись верхнего уровня в SDK, которая обеспечивает доступ ко всем сущностям в структуре пользователя. При запросе всех сущностей определенного типа API возвращает объект Query , который позволяет выбрать способ получения результатов. В GoogleHomeAPISampleIOS/Accounts/AccountViewModel.swift удалите комментарий и оповещение в connect() для реализации инициализации home.

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

Разрешение на использование API Home

При запуске приложения появится экран согласия. Выберите структуру Google Home и выберите учетную запись, которая находится в списке разрешенных вашего проекта Google Cloud.

47310f458c0094d9.png4a571dbd9979a88c.pnge29c75891a3a67af.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() сначала проверяет, находятся ли устройства в одной комнате, а затем заставляет их взаимодействовать как HomeDevices с помощью DeviceControl и DeviceControlFactory .

4c677c4c294e67ca.png

Примечание : Если ваше устройство не указано в DeviceControlFactory , оно будет отображаться как «Не поддерживается». Чтобы узнать больше о поддерживаемых устройствах, см. страницу Поддерживаемые типы устройств на iOS .

Взаимодействие с устройством

Plug 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.pnga45f785e1d51938e.png7753b56cbdcff8d6.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.pngfd126fabb454f2bf.png813e1e23e50cd9f6.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 Virtual Device .

Добавить устройство 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() , перейдите в верхний левый угол и выберите значок "+" > Добавить устройство в Google Fabric . Он использует MatterAddDeviceRequest для добавления устройства Matter в вашу комнату. После выбора комнаты и имени устройства устройство отобразится на экране "Устройства".

adf6cbb531787aaf.pngf002bd6320bc480d.png

7. Автоматизация

Просмотреть все автоматики в структуре

Нажмите на Automations в нижней панели навигации. Это выведет список всех автоматизаций в вашей структуре с помощью structure.listAutomations() .

cc6d50f72f812c24.png

Примечание : Если у вас не настроена никакая домашняя автоматизация, вы увидите сообщение «Добавьте автоматизацию, чтобы начать».

Создать автоматизацию

Теперь, когда вы знакомы с API устройств и структур и добавлением нового устройства, пришло время создать новую автоматизацию с помощью 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 секунд ». Появятся сведения об автоматизации, включая starter , condition и action . Нажмите « Сохранить », чтобы создать автоматизацию с помощью structure.createAutomation() .

21c1f8ea2a29134b.png4bd36f6ed9c5f6e9.png

Примечание : Доступные автоматизации зависят от устройств в вашем доме. Если вы не видите доступных автоматизаций, попробуйте переименовать свое световое устройство в «light2».

Вернитесь на вкладку «Устройства» и включите свет с именем «light2». Он автоматически выключится через пять секунд.

Компонентами автоматизации являются:

  • Starter: Это событие, которое инициирует автоматизацию. В этом примере автоматизация начнется после изменения OnOffTrait .
  • Условие: Проверяет, соответствует ли пусковое устройство определенным требованиям. В этом случае автоматизация будет выполнена, если свет горит.
  • Действие: Это автоматизация, которую вы хотите выполнить, но только если стартер соответствует требованиям. Если условия выполнены, свет будет выключен.

Дополнительные примеры можно найти на странице «Примеры автоматизации» .

Удалить автоматизацию

Метод structure.deleteAutomation() вызывается, когда вы проводите пальцем влево по существующей автоматизации и нажимаете значок корзины, чтобы удалить ее из структуры.

dc678cd9e16f89a5.png

8. Поздравления

Поздравляем! Вы успешно создали базовое приложение для умного дома с использованием Home API для iOS.

Чего вы достигли :

  • Инициализация : подключите свое приложение к экосистеме Google Home с помощью Home.connect() .
  • Разрешения : Осуществляет аутентификацию пользователей и авторизацию для доступа к домашним данным.
  • Устройства и структуры : Извлечение и отображение комнат и устройств с помощью home.rooms() и home.devices() .
  • Управление устройством : реализовано взаимодействие с устройством, например, переключение состояния OnOffPluginUnitDeviceType путем вызова команд для его свойств.
  • Управление структурой : добавлены функции создания новых комнат ( structure.createRoom() ), перемещения устройств между комнатами ( structure.move() ) и удаления пустых комнат ( structure.deleteRoom() ).
  • Ввод в эксплуатацию : Интегрирован процесс ввода в эксплуатацию SDK для добавления новых устройств Matter ( MatterAddDeviceRequest ).
  • Автоматизация : изучено, как перечислять, создавать ( structure.createAutomation() ) и удалять ( structure.deleteAutomation() ) автоматизации внутри структуры.

Теперь у вас есть базовые знания о том, как использовать API Home для создания полнофункциональных систем управления умным домом на базе iOS.

Следующие шаги :

  • Изучите управление другими типами устройств, представленными в примере приложения (освещение, вентиляторы, жалюзи и т. д.).
  • Изучите подробнее различные характеристики и команды, доступные для разных устройств.
  • Поэкспериментируйте с созданием более сложных автоматизаций, используя различные пускатели, условия и действия.
  • Более подробную информацию и дополнительные функции можно найти в документации по API Home .

Отличная работа!