È possibile accedere alle API Structure tramite le API Home per iOS.
Per utilizzare le API Structure, importa innanzitutto il pacchetto GoogleHomeSDK nella tua app:
import GoogleHomeSDK
Gestione degli errori
Alcuni metodi nelle API Home generano un'eccezione HomeError, pertanto ti consigliamo di utilizzare un blocco do-catch per rilevare l'eccezione HomeError su queste chiamate.
Quando gestisci HomeError, controlla i campi code e message per scoprire cosa non ha funzionato.
Eventuali errori non gestiti causeranno l'arresto anomalo dell'app.
Per saperne di più, consulta Gestione degli errori.
API Structure
Home rappresenta il grafico della casa ed è il punto di accesso all'API Structure.
Fornisce riferimenti a strutture, stanze e dispositivi.
Structure rappresenta una struttura nel tuo Home Graph. Fornisce l'accesso ai metadati della struttura, come id e name.
Utilizza structures() per
recuperare tutte le strutture nel tuo account. Le strutture vengono restituite sotto forma di Query, che offre una scelta di modi per utilizzare i suoi dati:
| API | Descrizione |
|---|---|
stream() |
Restituisce un Publisher che emette ogni oggetto singolarmente man mano che vengono apportate modifiche. |
batched() |
Restituisce un Publisher che emette il risultato corrente come Set di oggetti. Ogni Set emesso rappresenta lo stato attuale del grafo degli oggetti. |
list() |
Restituisce il risultato corrente come Set di oggetti. |
La chiamata structures().list() potrebbe non restituire immediatamente un insieme valido di strutture. Se la tua app è reattiva e chiama stream() per iscriversi a tutte le modifiche della struttura per gestire l'UI, alla fine dovrebbe essere restituito un elenco valido di strutture. Esistono altre situazioni in cui potrebbe essere restituito un elenco di strutture vuoto, ad esempio se lo smartphone dell'utente perde la connettività o se l'utente ha revocato le autorizzazioni alla tua app. Assicurati di gestire questi casi nella tua 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 {
// Failed to load structures
return Just([Structure]())
}
.assign(to: \.structures, on: self)
Chiamate alla struttura di esempio
Recupera un insieme di strutture
La chiamata di list() su un Query<Structure> restituisce l'insieme di elementi più recente:
// Get a stream of all structures accessible to the user let allStructuresChanges = self.home.structures() let allStructures = try? await allStructuresChanges.list()
Quando progetti un'app reattiva, ti consigliamo di utilizzare le chiamate batched() e stream() anziché list(), perché producono automaticamente dati quando il grafico della casa cambia.
Recupera le proprietà della struttura
Con l'elenco delle strutture a portata di mano, puoi accedere alle relative proprietà:
// 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) ")
Trova una struttura per nome
Se conosci il nome di una struttura, puoi accedervi anche utilizzando la proprietà name:
do { structure1 = try await home.structures().list().first(where: { $0.name == "Main House" }) } catch let _ as HomeError { // Code for handling the exception }
Da qui è possibile accedere alle proprietà, alle stanze e ai dispositivi di ogni struttura.
Utilizza più strutture
Per utilizzare più di una struttura, ottieni un riferimento separato per ogni struttura:
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 }
Camere
Una stanza contiene un gruppo di dispositivi. Una stanza fa sempre parte di una struttura e una struttura può avere più stanze. La rimozione di una stanza da una struttura non comporta la rimozione dei dispositivi presenti in quella stanza dalla struttura. Tuttavia, se la stanza viene eliminata, i dispositivi al suo interno non vengono assegnati.
Utilizza Home.rooms() per recuperare tutte le stanze nell'account, quindi utilizza roomID = device.roomID per visualizzare i dispositivi corrispondenti in ogni stanza.
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)
Chiamate alla stanza di esempio
Visualizza un elenco di stanze
Utilizzando la classe Home, puoi ottenere un elenco di stanze e accedere alle relative proprietà:
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) ")
Crea una stanza virtuale
Per creare una nuova stanza in un 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 }
Eliminare una stanza
In alternativa, puoi eliminare una stanza:
val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull() structure.deleteRoom(roomToDelete!!)
Puoi anche eliminare una stanza utilizzando il suo ID:
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 } }
Se una stanza con dispositivi viene eliminata, i dispositivi rimarranno nella struttura, ma non saranno più assegnati a una stanza.
Sposta i dispositivi in un'altra stanza
Structure ti consente anche di spostare un dispositivo in un'altra stanza:
do { try await structure.move(device: light, to: room) } catch let _ as HomeError { // Code for handling the exception }
Modifica il nome di una stanza
Chiama il metodo
setName(_:)
per modificare il nome di una stanza:
let updatedRoom = try await theRoom.setName("new room name")
Quando cambi il nome di una stanza, la struttura Room originale rimane invariata e la modifica viene applicata all'oggetto Room aggiornato restituito.
I nomi verranno troncati se superano il limite di 60 punti di codice Unicode (caratteri) e non verranno generati errori. Gli sviluppatori sono responsabili della gestione dei nomi lunghi e, ad esempio, possono decidere se informare gli utenti che i nomi verranno troncati.
Gruppi di dispositivi
Un gruppo di dispositivi rappresenta una raccolta di dispositivi definita dall'utente all'interno di una singola struttura. L'iscrizione al gruppo viene conservata nei servizi Google ed è visibile agli altri membri della struttura e alle altre app con accesso alla struttura.
Come le stanze fisiche, i gruppi di dispositivi appartengono a una singola struttura. A differenza delle stanze, i gruppi di dispositivi sono raggruppamenti logici. Un dispositivo può appartenere a più gruppi di dispositivi contemporaneamente. I gruppi di dispositivi possono contenere fino a 100 dispositivi.
I gruppi di dispositivi sono rappresentati dall'entitàDeviceGroup, che è distinta da HomeDevice. Per interagire con i gruppi di dispositivi, includi i tipi e i tratti dei dispositivi pertinenti durante la configurazione di ReferencedAutomationTypes in Home.configure, insieme ai tratti GroupTrait, GroupManagementTrait e GroupMembershipTrait.
Puoi interagire con i dispositivi di un gruppo eseguendo l'iterazione direttamente sui dispositivi membri (consulta Interagisci con i dispositivi membri del gruppo) o scegliendo come target una parte del tipo di dispositivo su DeviceGroup (consulta Controlla un gruppo di dispositivi).
Visualizza un elenco dei gruppi di dispositivi
Per eseguire una query su tutti i gruppi di dispositivi della casa:
let groups = try await home.entities(DeviceGroup.self).list()
for group in groups {
let groupTrait = await group.traits.get(Google.GroupTrait.self)
let name = groupTrait?.attributes.name ?? "Device Group"
print("Found group: \(name) with ID: \(group.id)")
}
Interagisci con i dispositivi dei membri del gruppo
L'iterazione sui dispositivi membri di un gruppo ti offre un controllo granulare sui singoli membri, ti consente di raggruppare i comandi in un'unica richiesta e di aggregare o scrivere attributi tra i membri.
Innanzitutto, filtra i dispositivi della casa controllando il campo GroupMembershipTrait di ogni dispositivo per l'ID gruppo target:
let allDevices = try await home.devices().list()
var members: [HomeDevice] = []
for device in allDevices {
if let membership = await device.traits.get(
Google.GroupMembershipTrait.self
),
membership.attributes.groupObjectIdsArray.contains(group.id) {
members.append(device)
}
}
Per inviare una singola richiesta batch con i comandi per un tratto a tutti i membri compatibili di un gruppo:
var onOffTraits: [Matter.OnOffTrait] = []
for device in members {
if let light = await device.types.get(OnOffLightDeviceType.self),
let onOff = light.matterTraits.onOffTrait {
onOffTraits.append(onOff)
}
}
let traitsToUse = onOffTraits
let responses = try await home.sendBatchedCommands { batcher in
return try traitsToUse.map { batcher.add(try $0.onBatchable()) }
}
for response in responses {
try response.getOrThrow()
}
Puoi anche aggiornare un attributo su tutti i dispositivi membri corrispondenti di un gruppo
(ad esempio, impostando onTransitionTime su 1 su tutti i
membri DimmableLightDeviceType) contemporaneamente e attendere il completamento entro una
scadenza:
try await withThrowingTaskGroup(of: Void.self) { taskGroup in
taskGroup.addTask {
try await Task.sleep(for: .seconds(5))
throw CancellationError()
}
for device in members {
taskGroup.addTask {
guard let light = await device.types.get(DimmableLightDeviceType.self),
let levelControl = light.matterTraits.levelControlTrait,
levelControl.attributes.$onTransitionTime.isSupported
else { return }
_ = try await levelControl.update {
$0.setOnTransitionTime(1)
}
}
}
for _ in 0..<members.count {
try await taskGroup.next()
}
taskGroup.cancelAll()
}
Per aggregare un attributo tra i membri di un gruppo, ad esempio per trovare il valore minimo di colorTempPhysicalMaxMireds per tutte le luci con temperatura di colore nel gruppo:
var maxMiredsValues: [UInt16] = []
for device in members {
if let light = await device.types.get(ColorTemperatureLightDeviceType.self),
let mireds = light.matterTraits.colorControlTrait?.attributes
.colorTempPhysicalMaxMireds {
maxMiredsValues.append(mireds)
}
}
let minMaxMireds = maxMiredsValues.min()
Crea un gruppo di dispositivi
Utilizza
GroupManagementTrait
sulla struttura per creare un gruppo di dispositivi:
let groupsManagementTrait =
try await structure.traits(Google.GroupManagementTrait)
let _ = try await groupsManagementTrait.createUserDefinedGroup(
withName: "Kitchen Lights",
withDevices: [light1, light2]
)
Gestione dell'appartenenza ai gruppi
Per aggiungere membri a un gruppo esistente:
let groupManagementTrait =
try await structure.traits(Google.GroupManagementTrait.self)
groupManagementTrait.addGroupMembers(
groupObjectId: group.id,
memberDeviceObjectIds = [light3.id],
)
Per rimuovere membri da un gruppo:
let groupManagementTrait =
try await structure.traits(Google.GroupManagementTrait.self)
_ = try await groupManagementTrait.removeGroupMembers(
groupObjectId: group.id,
memberDeviceObjectIdsArray: Array(removedIDs)
)
Modifica il nome di un gruppo di dispositivi
Per rinominare un gruppo di dispositivi, aggiorna il campo name di GroupTrait:
let groupTrait = group.traits.get(Google.GroupTrait.self)
_ = try await groupTrait.update { $0.name = "Movie Corner" }
Elimina un gruppo di dispositivi
Per eliminare un gruppo di dispositivi da una struttura:
let groupManagementTrait =
try await structure.traits.get(Google.GroupManagementTrait.self)
_ = try await groupManagementTrait.deleteGroup(groupObjectId: group.id)