Estruturar APIs no iOS

As APIs Structure podem ser acessadas pelas APIs Home para iOS.

Para trabalhar com as APIs Structure, primeiro importe o pacote GoogleHomeSDK para seu app:

import GoogleHomeSDK

Tratamento de erros

Alguns métodos nas APIs Home geram um HomeError. Por isso, recomendamos que você use um bloco do-catch para capturar HomeError nessas chamadas.

Ao processar HomeError, verifique os campos code e message para saber o que deu errado.

Qualquer erro não tratado vai causar uma falha no app.

Para mais informações, consulte Tratamento de erros.

API Structure

Home representa o gráfico da casa e é o ponto de entrada da API Structure. Ele fornece referências a estruturas, salas e dispositivos.

Structure representa uma estrutura no seu gráfico da casa. Ele dá acesso a metadados de estrutura, como id e name.

Use structures() para receber todas as estruturas na sua conta. As estruturas são retornadas na forma de um Query, que oferece várias maneiras de consumir os dados:

API Descrição
stream() Retorna um Publisher que emite cada objeto individualmente à medida que as mudanças ocorrem.
batched() Retorna um Publisher que emite o resultado atual como um Set de objetos. Cada Set emitido representa o estado atual do gráfico de objetos.
list() Retorna o resultado atual como um Set de objetos.

A chamada structures().list() pode não retornar imediatamente um conjunto válido de estruturas. Se o app for reativo e chamar stream() para se inscrever em todas as mudanças de estrutura para acionar a interface, uma lista válida de estruturas será retornada eventualmente. Há outras situações em que uma lista de estruturas vazia pode ser retornada, por exemplo, se o smartphone do usuário perder a conectividade ou se ele tiver revogado as permissões do seu app. Não se esqueça de processar esses casos no seu app.

@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)

Exemplos de chamadas de estrutura

Receber um conjunto de estruturas

Chamar list() em um Query<Structure> retorna o conjunto mais recente de elementos:

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

Ao projetar um app reativo, use chamadas batched() e stream() em vez de list(), porque elas produzem dados automaticamente quando o gráfico inicial muda.

Receber propriedades de estrutura

Com a lista de estruturas em mãos, você pode acessar as propriedades delas:

// 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 = try await structureChanges.first!

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

Encontrar uma estrutura pelo nome

Se você souber o nome de uma estrutura, também poderá acessá-la usando a propriedade name:

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

A partir daí, é possível acessar propriedades, cômodos e dispositivos de cada estrutura.

Trabalhar com várias estruturas

Para usar mais de uma estrutura, receba uma referência separada para cada uma delas:

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

Salas

Um ambiente contém um grupo de dispositivos. Uma sala sempre faz parte de uma estrutura, e uma estrutura pode ter várias salas. Remover um ambiente de uma estrutura não remove os dispositivos desse ambiente da estrutura. No entanto, se o ambiente for excluído, os dispositivos nele vão ficar sem atribuição.

Use Home.rooms() para recuperar todos os ambientes da conta e roomID = device.roomID para mostrar os dispositivos correspondentes em cada ambiente.

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)

Exemplos de chamadas da Room

Receber uma lista de salas

Usando a classe Home, você pode acessar uma lista de salas e as propriedades delas:

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) ")

Criar uma sala

Para criar um novo ambiente em um Structure:

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

Excluir um ambiente

Ou, se preferir, exclua uma sala:

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

Também é possível excluir uma sala usando o ID dela:

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

Se um ambiente com dispositivos for excluído, os dispositivos ainda estarão na estrutura, mas não atribuídos a um ambiente.

Mover dispositivos para outro ambiente

Com o Structure, também é possível mover um dispositivo para outro ambiente:

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

Mudar o nome de um ambiente

Chame o método setName(_:) para mudar o nome de um ambiente:

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

Ao mudar o nome de uma sala, a struct Room original permanece a mesma, e a mudança é refletida no objeto Room atualizado retornado.

Os nomes serão truncados se excederem o limite de 60 pontos de código Unicode (caracteres), e nenhum erro será gerado. Os desenvolvedores são responsáveis por processar nomes longos e, por exemplo, podem decidir se querem informar aos usuários que os nomes serão truncados.

Lista de APIs

Depois que uma instância de Home é criada, as seguintes APIs de estrutura ficam acessíveis por ela:

API Descrição
devices() Recebe todos os dispositivos visíveis para esta conta.
device(id:) Receba um Publisher para um dispositivo específico que emite o estado atual e novamente em qualquer atualização de estado futura.
structures() Recebe todas as estruturas na Conta do Google. Retorna um Query<Structure> que oferece mais opções de recuperação e filtragem.
structure(id:) Receba a estrutura com o ID correspondente.
rooms() Recebe todas as salas na Conta do Google. Retorna um Query<strRoom> que oferece mais opções de recuperação e filtragem.
room(id:) Receba um Publisher para uma sala especificada que emite o estado atual e novamente em qualquer atualização de estado futura.

O Structure tem as seguintes APIs:

API Descrição
deleteRoom(id:) Exclua uma sala com o ID dela.
id O ID exclusivo do sistema da estrutura.
move(device:, to:) Mover um dispositivo para outro ambiente na estrutura.
move(device:, to:) Mova o dispositivo com o ID especificado para o ambiente com o ID especificado.
move(devices:, to:) Move os dispositivos especificados para o ambiente indicado.
move(devices:, to:) Move os dispositivos com os IDs especificados para o ambiente com o ID especificado.
name O nome da estrutura fornecido pelo usuário.

O Room tem as seguintes APIs:

API Descrição
id O ID exclusivo do sistema do quarto.
name O nome da sala fornecido pelo usuário.
structureID O ID exclusivo do sistema da estrutura a que o quarto pertence.