È possibile accedere alle API Structure tramite le API Home per Android. Importa questi pacchetti nella tua app:
import com.google.home.Home
import com.google.home.Id
import com.google.home.Structure
Gestione degli errori
Qualsiasi metodo nelle API Home può generare un'eccezione
HomeException, pertanto ti consigliamo di utilizzare un blocco try-catch per rilevare HomeException su tutte le chiamate.
Quando gestisci HomeException, controlla i campi
error.code e
error.message per scoprire cosa non ha funzionato. Potrebbero esserci anche codici di errore secondari, quindi chiama il metodo
getSubErrorCodes() e controlla il risultato.
Eventuali eccezioni non gestite causeranno l'arresto anomalo dell'app.
Per saperne di più, consulta Gestione degli errori.
Chiamate di esempio
Recupera un elenco di strutture
Una volta inizializzata, una chiamata structures() restituisce un flusso di strutture accessibili:
// Get a flow of all structures accessible to the user val allStructuresFlow: HomeObjectsFlow<Structure> = home.structures() // Calling list() on a HomeObjectsFlow returns the first Set of elements. val allStructures: Set<Structure> = allStructuresFlow.list()
L'API structures() è un flusso che potrebbe non restituire immediatamente un elenco valido di strutture. Se la tua app è reattiva e si iscrive a quel flusso per gestire la 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.
In alternativa, se la programmazione imperativa è fortemente richiesta al posto della programmazione reattiva, è possibile utilizzare un operatore di flusso terminale:
val everyStructure = withTimeout(5000) { home.structures().first { it.isNotEmpty() } }
Questa chiamata attende che un elenco valido di strutture passi attraverso il flusso e scade se l'elenco non viene ricevuto entro un timeout designato dall'app.
Recupera le proprietà della struttura
Con l'elenco delle strutture a portata di mano, puoi accedere alle relative proprietà:
// Get a flow on a structure. Flow emits new values on structure metadata changes: name. val structureFlow: Flow<Structure> = home.structures().itemFlow(myStructureId) // Get a snapshot of the structure. val structure: Structure = structureFlow.first() // Get structure properties println("id ${structure.id}") println("name ${structure.name}")
Trova una struttura per nome
Se conosci il nome di una struttura, puoi accedervi anche utilizzando la proprietà name:
val myHome = home.structures().list().first { it.name == "My home" }
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? = null var structure2: Structure? = null try { structure1 = home.structures().list().firstOrNull { it.name == "Main House" } } catch (e: HomeException) { // Code for handling the exception } try { structure2 = home.structures().list().firstOrNull { it.name == "Guest Cottage" } } catch (e: HomeException) { // Code for handling the exception }
Visualizza un elenco di stanze
Una volta ottenuta una struttura, puoi recuperare un elenco di stanze e accedere alle relative proprietà:
val allRoomsFlow: HomeObjectsFlow<Room> = structure.rooms() val allRooms: Set<Room> = allRoomsFlow.list() val room: Room = allRooms.first() println("id ${room.id}") println("name ${room.name}")
Crea una stanza virtuale
Per creare una nuova stanza:
val testName = "Test Room Name" val newRoom: Room = structure.createRoom(testName)
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 con un solo ID:
val roomToDelete1 = allRooms.filter { it.id == testRoomId }.firstOrNull() structure.deleteRoom(roomToDelete1!!)
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
Una volta creata una struttura, puoi spostare i dispositivi in un'altra stanza all'interno di quella struttura:
val room2 = structure.rooms().get(Id("room_id_other_structure")) val device1 = structure.devices().get(Id("device_id1")) structure.moveDevicesToRoom(room2!!, listOf(device1!!))
Se hai solo gli ID dispositivo e stanza, puoi anche spostare i dispositivi:
structure.moveDevicesToRoom(Id("room_id_other_structure"), listOf(Id("device_id1")))
Modifica il nome di una stanza
Chiama il metodo setName() per modificare il nome di una stanza:
livingRoom.setName("Living Room")
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.
Visualizza i tipi di dispositivi per cui un utente ha concesso le autorizzazioni
Nell'ecosistema Google Home, per la maggior parte dei tipi di dispositivi, gli utenti possono concedere le autorizzazioni per tutti i dispositivi di quel tipo contemporaneamente. Per i tipi di dispositivi sensibili o con limitazioni, come serrature, videocamere o campanelli, gli utenti devono concedere l'autorizzazione singolarmente.
Per determinare se un utente ha concesso l'autorizzazione ad accedere a un tipo di dispositivo sensibile o con limitazioni, utilizza la funzione consentedDeviceTypes() a livello di struttura:
import com.google.home.Structure
import com.google.home.DeviceType
import com.google.home.DeviceTypeFactory
import com.google.home.consentedDeviceTypes // Extension function from the SDK
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
/**
* Example of how an app may monitor which device types have been granted access by a user.
*/
fun monitorDeviceConsent(structure: Structure, myScope: CoroutineScope) {
// Obtain the flow of consented device type factories
val consentedTypesFlow: Flow<Set<DeviceTypeFactory<out DeviceType>>> =
structure.consentedDeviceTypes()
myScope.launch {
consentedTypesFlow.collect { consentedSet ->
// Check if the user has consented to share a specific restricted
// type, such as a Doorbell or Camera.
val hasCameraAccess = consentedSet.any {
it.toString() == "matter.google.type.GoogleDoorbellDevice"
}
if (hasCameraAccess) {
// Enable features that require camera access
} else {
// Inform the user or disable camera-specific features
}
}
}
}
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 eseguire query e interagire con i gruppi di dispositivi, includi DeviceGroup nell'elenco entityTypes durante l'inizializzazione di FactoryRegistry, insieme ai tratti Group, GroupManagement e GroupMembership.
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 osservare tutti i gruppi di dispositivi in una struttura, chiama home.entities(DeviceGroup)
e filtra in base all'ID della struttura:
home.entities(DeviceGroup).collect { allGroups ->
val structureGroups = allGroups.filter { it.structureId == structure.id }
for (group in structureGroups) {
val groupName = group.trait(Group)?.Name
println("Found group: $groupName with ID: ${group.id.id}")
}
}
Interagisci con i dispositivi dei membri del gruppo
L'iterazione sui dispositivi membri di un gruppo con group.devices() 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.
Ad esempio, per inviare una singola richiesta batch con i comandi per un tratto a tutti i membri compatibili di un gruppo:
val members = group.devices(enableMultipartDevices = true).first()
val onOffTraits = members.mapNotNull { device ->
device.partOrNull(OnOffLightDevice).first()?.standardTraits?.onOff
}
val responses = home.sendBatchedCommands {
onOffTraits.map { onOff ->
add(onOff.onBatchable())
}
}
for (response in responses) {
response.getOrThrow()
}
Puoi anche aggiornare un attributo su tutti i dispositivi membri corrispondenti di un gruppo
(ad esempio, impostando onTransitionTime su 1u su tutti i membri
DimmableLightDevice) e attendere il completamento entro una scadenza:
val members = group.devices(enableMultipartDevices = true).first()
withTimeout(5.seconds) {
members.map { device ->
async {
val light = device.partOrNull(DimmableLightDevice).first()
val levelControl = light?.standardTraits?.levelControl
if (
levelControl?.supports(
LevelControl.Attribute.onTransitionTime
) == true
) {
levelControl.update { setOnTransitionTime(1u) }
}
}
}.awaitAll()
}
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:
val members = group.devices(enableMultipartDevices = true).first()
val minMaxMireds: UShort? = members.mapNotNull { device ->
val light = device.partOrNull(ColorTemperatureLightDevice).first()
light?.standardTraits?.colorControl?.colorTempPhysicalMaxMireds
}.minOrNull()
Crea un gruppo di dispositivi
Utilizza
GroupManagement
sulla struttura per creare un gruppo di dispositivi:
val groupManagement = structure.trait(GroupManagementTrait)
val response = groupManagement?.createUserDefinedGroup(
name = "Living room lights",
memberDeviceObjectIds = listOf(light1.id.id, light2.id.id)
)
Gestione dell'appartenenza ai gruppi
Per aggiungere membri a un gruppo esistente:
structure.trait(GroupManagementTrait)?.addGroupMembers(
groupObjectId = group.id.id,
memberDeviceObjectIds = listOf(light3.id.id)
)
Per rimuovere membri da un gruppo:
structure.trait(GroupManagementTrait)?.removeGroupMembers(
groupObjectId = group.id.id,
memberDeviceObjectIds = listOf(light1.id.id)
)
Modifica il nome di un gruppo di dispositivi
Per rinominare un gruppo di dispositivi, aggiorna l'attributo name nel GroupTrait del gruppo:
group.trait(GroupTrait)?.update {
name = "Movie corner"
}
Elimina un gruppo di dispositivi
Per eliminare un gruppo di dispositivi da una struttura:
structure.trait(GroupManagementTrait)?.deleteGroup(
groupObjectId = group.id.id
)
Automazioni
Il punto di accesso all'API Automation è tramite una struttura. Per scoprire di più sulle automazioni nelle API Home, consulta la panoramica dell'API Automation su Android.