Interfejsy Structure API na iOS

Dostęp do interfejsów Structure API można uzyskać za pomocą interfejsów Home API na iOS.

Aby korzystać z interfejsów Structure API, najpierw zaimportuj pakiet GoogleHomeSDK do swojej aplikacji:

import GoogleHomeSDK

Obsługa błędów

Niektóre metody w interfejsach Home API zgłaszają błąd HomeError, dlatego zalecamy używanie bloku do-catch, aby przechwytywać błędy HomeError w tych wywołaniach.

Podczas obsługi błędu HomeError sprawdź pola code i message , aby dowiedzieć się, co poszło nie tak.

Wszelkie nieobsłużone błędy spowodują awarię aplikacji.

Więcej informacji znajdziesz w sekcji Obsługa błędów.

Interfejs Structure API

Home reprezentuje wykres Home i jest punktem wejścia do interfejsu Structure API. Zawiera odniesienia do struktur, pomieszczeń i urządzeń.

Structure reprezentuje strukturę na wykresie Home. Umożliwia dostęp do metadanych struktury, takich jak id i name.

Aby uzyskać wszystkie struktury na koncie, użyj structures() to. Struktury są zwracane w postaci Query, która oferuje różne sposoby wykorzystania danych:

Interfejs API Opis
stream() Zwraca Publisher, który emituje każdy obiekt osobno w miarę wprowadzania zmian.
batched() Zwraca Publisher, który emituje bieżący wynik jako Set obiektów. Każdy emitowany Set reprezentuje bieżący stan wykresu obiektów.
list() Zwraca bieżący wynik jako Set obiektów.

Wywołanie structures().list() może nie zwrócić od razu prawidłowego zestawu struktur. Jeśli Twoja aplikacja jest reaktywna i wywołuje stream(), aby subskrybować wszystkie zmiany struktury w celu sterowania interfejsem, w końcu powinna zostać zwrócona prawidłowa lista struktur. Istnieją też inne sytuacje, w których może zostać zwrócona pusta lista struktur, np. gdy telefon użytkownika utraci połączenie lub gdy użytkownik cofnie uprawnienia Twojej aplikacji. Musisz zadbać o obsługę tych przypadków w swojej aplikacji.

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

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

Przykładowe wywołania struktury

Pobieranie zestawu struktur

Wywołanie list() w przypadku Query<Structure> zwraca najnowszy zestaw elementów:

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

Podczas projektowania aplikacji reaktywnej warto używać wywołań batched() i stream() zamiast list(), ponieważ automatycznie generują one dane, gdy zmienia się wykres Home.

Pobieranie właściwości struktury

Mając listę struktur, możesz uzyskać dostęp do ich właściwości:

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

Znajdowanie struktury według nazwy

Jeśli znasz nazwę struktury, możesz też uzyskać do niej dostęp za pomocą właściwości name:

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

Stamtąd można uzyskać dostęp do właściwości, pomieszczeń i urządzeń każdej struktury.

Praca z wieloma strukturami

Aby używać więcej niż 1 struktury, uzyskaj osobne odniesienie do każdej z nich:

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
}

Pokoje

Pokój zawiera grupę urządzeń. Pokój jest zawsze częścią struktury, a struktura może mieć wiele pomieszczeń. Usunięcie pokoju ze struktury nie powoduje usunięcia urządzeń w tym pokoju ze struktury. Jeśli jednak pokój zostanie usunięty, urządzenia w tym pokoju zostaną odłączone.

Aby pobrać wszystkie pokoje na koncie, użyj Home.rooms(), a następnie użyj roomID = device.roomID, aby wyświetlić odpowiednie urządzenia w każdym pokoju.

self.home.rooms().batched()
  .combineLatest(self.home.devices().batched())
  .receive(on: DispatchQueue.main)
  .catch { error in
    // Failed to load rooms and devices
    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)

Przykładowe wywołania pokoju

Pobieranie listy pokoi

Za pomocą klasy Home możesz pobrać listę pokoi i uzyskać dostęp do ich właściwości:

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

Tworzenie pokoju

Aby utworzyć nowy pokój w 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
}

Usuwanie pokoju

Możesz też usunąć pokój:

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

Możesz też usunąć pokój za pomocą jego identyfikatora:

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

Jeśli usuniesz pokój z urządzeniami, urządzenia nadal będą w strukturze, ale nie będą już przypisane do pokoju.

Przenoszenie urządzeń do innego pokoju

Structure umożliwia też przenoszenie urządzeń do innego pokoju:

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

Zmienianie nazwy pokoju

Aby zmienić nazwę pokoju, wywołaj setName(_:) metodę:

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

Podczas zmiany nazwy pokoju oryginalna struktura Room pozostaje taka sama, a zmiana jest odzwierciedlana w zwracanym zaktualizowanym obiekcie Room.

Nazwy dłuższe niż 60 punktów kodowych Unicode (znaków) zostaną obcięte i nie zostaną zgłoszone żadne błędy. Deweloperzy są odpowiedzialni za obsługę długich nazw i mogą na przykład zdecydować, czy chcą informować użytkowników o tym, że nazwy zostaną obcięte.