Структурные API на iOS

Доступ к API структур можно получить через API Home для iOS.

Для работы со структурированными API сначала импортируйте пакет GoogleHomeSDK в ваше приложение:

import GoogleHomeSDK

Обработка ошибок

Некоторые методы в API Home генерируют HomeError , поэтому мы рекомендуем использовать блок do-catch для обработки таких HomeError .

При обработке HomeError проверьте поля code и message , чтобы выяснить, что пошло не так.

Любые необработанные ошибки приведут к сбою вашего приложения.

Для получения более подробной информации см. раздел «Обработка ошибок» .

Структура API

Home представляет собой граф Home и является точкой входа в Structure API. Он предоставляет ссылки на структуры, комнаты и устройства.

Structure представляет собой структуру в вашем графе Home. Она предоставляет доступ к метаданным структуры, таким как id и name .

Используйте structures() для получения всех структур в вашей учетной записи. Структуры возвращаются в виде Query , который предлагает несколько способов использования данных:

API Описание
stream() Возвращает Publisher , который генерирует каждый объект по отдельности по мере внесения изменений.
batched() Возвращает Publisher , который выдает текущий результат в виде Set объектов (Set). Каждое выданное Set представляет текущее состояние графа объектов.
list() Возвращает текущий результат в виде Set объектов.

Вызов structures().list() может не сразу вернуть корректный набор структур. Если ваше приложение реактивное и вызывает stream() для подписки на все изменения структур, управляющие пользовательским интерфейсом, в конечном итоге должен быть возвращен корректный список структур. Существуют и другие ситуации, когда может быть возвращен пустой список структур, например, если телефон пользователя теряет связь или если пользователь отозвал разрешения для вашего приложения. Вам следует обязательно обрабатывать эти случаи в своем приложении.

@Published public private(set) var structures: [Structure] = []
private var structuresCancellable: AnyCancellable?

  self.structuresCancellable = home
    .structures()
    .batched()
    .receive(on: DispatchQueue.main)
    .map { Array($0) }
    .catch {
      Logger.error("Failed to load structures: \($0)")
      return Just([Structure]())
    }
    .assign(to: \.structures, on: self)

Примеры вызовов структуры

Получите набор структур

Вызов метода list() для Query<Structure> возвращает самый последний набор элементов:

// Get a stream of all structures accessible to the user
let allStructuresChanges = self.home.structures()
let allStructures = try? await allStructuresChanges.list()

При разработке реактивного приложения лучше использовать вызовы batched() и stream() вместо list() , поскольку они автоматически генерируют данные при изменении графа главного экрана.

Получить свойства структуры

Имея на руках список строений, вы можете получить доступ к их свойствам:

// Get a stream of changes taking place on a structure.
let structureChanges = try await home.structures().list().filter { $0.id == structureID }

// Get a snapshot of the structure.
let structure = structureChanges.first!

// Get structure properties
print("id \(structure.id) ")
print("name \(structure.name) ")

Найти сооружение по названию

Если вам известно имя структуры, вы также можете получить к ней доступ, используя свойство name :

do {
  structure1 = try await home.structures().list().first(where: { $0.name == "Main House" })
} catch let _ as HomeError {
  // Code for handling the exception
}

Оттуда становится доступен доступ к объектам недвижимости, помещениям и устройствам каждого здания.

Работа с несколькими структурами

Чтобы использовать несколько структур, получите отдельную ссылку на каждую из них:

var structure1: Structure!
var structure2: Structure!
do {
  structure1 = try await home.structures().list().first(where: { $0.name == "Main House" })
} catch let _ as HomeError {
  // Code for handling the exception
}
do {
  structure2 = try await home.structures().list().first(where: { $0.name == "Guest Cottage" })
} catch let _ as HomeError {
  // Code for handling the exception
}

Комнаты

Комната содержит группу устройств. Комната всегда является частью здания, а здание может содержать несколько комнат. Удаление комнаты из здания не приводит к удалению устройств, находящихся в этой комнате. Однако, если комната удаляется, устройства в этой комнате становятся неназначенными.

Используйте Home.rooms() для получения списка всех комнат в учетной записи, затем используйте roomID = device.roomID для отображения соответствующих устройств в каждой комнате.

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 { rooms, devices in
    var devicesByRoom = [Room: [HomeDevice]]()
    for room in rooms where room.structureID == currentStructureID {
      devicesByRoom[room] = devices.filter { $0.roomID == room.id }
    }
    return devicesByRoom
  }.assign(to: &self.$devicesByRoom)

Примеры звонков в комнату образцов

Получить список комнат

Используя класс Home , вы можете получить список комнат и получить доступ к их свойствам:

let allRoomsChanges = self.home.rooms()
let allRooms = try await allRoomsChanges.list()
let room = allRooms.first!
XCTAssertTrue(allRooms.contains(room))

print("id \(room.id) ")
print("name \(room.name) ")

Создать комнату

Чтобы создать новую комнату в Structure :

let testName = "Test Room Name"
var newRoom: Room!
do {
  newRoom = try await structure.createRoom(name: testName)
  XCTAssertNotNil(newRoom)
} catch let _ as HomeError {
  // Code for handling the exception
}

Удалить комнату

Или же вы можете удалить комнату:

val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull()
    structure.deleteRoom(roomToDelete!!)

Также можно удалить комнату, используя её идентификатор:

let roomToDelete = allRooms.first(where: { $0.id == room.id })
if let roomToDelete1 = roomToDelete {
  do {
    try await structure.deleteRoom(roomToDelete1)
  } catch let _ as HomeError {
    // Code for handling the exception
  }
}

Если помещение с устройствами будет удалено, устройства останутся в структуре, но больше не будут привязаны к помещению.

Перенесите устройства в другую комнату.

Structure также позволяет перемещать устройство в другую комнату:

do {
  try await structure.move(device: light, to: room)
} catch let _ as HomeError {
  // Code for handling the exception
}

Изменить название комнаты

Чтобы изменить название комнаты, вызовите метод setName(_:) :

let updatedRoom = try await theRoom.setName("new room name")

При изменении названия комнаты исходная структура Room остается неизменной, и изменение отражается в возвращаемом обновленном объекте Room .

Имена будут усечены, если их длина превышает 60 символов в кодовой точке Unicode, при этом ошибок возникать не будет. Разработчики несут ответственность за обработку длинных имен и, например, могут решить, сообщать ли пользователям о том, что имена будут усечены.