API Structure sur Android

Les API Structure sont accessibles via les API Home pour Android. Importez les packages suivants dans votre application :

import com.google.home.Home
import com.google.home.Id
import com.google.home.Structure

Gestion des exceptions

N'importe quelle méthode des API Home peut générer une HomeException. Nous vous recommandons donc d'utiliser un bloc try-catch pour intercepter HomeException dans tous les appels.

Lorsque vous gérez HomeException, vérifiez les champs error.code et error.message pour savoir ce qui s'est passé. Il peut également y avoir des codes de sous-erreur . Appelez donc la getSubErrorCodes() méthode et vérifiez le résultat.

Toutes les exceptions non gérées entraîneront le plantage de votre application.

Pour en savoir plus, consultez la section Gestion des erreurs.

Exemples d'appels

Obtenir une liste de structures

Une fois initialisé, un appel structures() renvoie un flux de structures auxquelles vous avez accès :

// 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() est un flux qui peut ne pas renvoyer immédiatement une liste de structures valide. Si votre application est réactive et s'abonne à ce flux pour gérer l'UI, une liste de structures valide doit être renvoyée à terme. Une liste de structures vide peut également être renvoyée dans d'autres cas, par exemple si le téléphone de l'utilisateur perd la connectivité ou si l'utilisateur a révoqué les autorisations de votre application. Vous devez vous assurer de gérer ces cas dans votre application.

Si la programmation impérative est fortement requise au lieu de la programmation réactive, vous pouvez utiliser un opérateur de flux terminal :

val everyStructure = withTimeout(5000) { home.structures().first { it.isNotEmpty() } }

Cet appel attend qu'une liste de structures valide soit transmise dans le flux et expire si la liste n'est pas reçue dans le délai d'expiration désigné par l'application.

Obtenir les propriétés d'une structure

Une fois la liste des structures obtenue, vous pouvez accéder à leurs propriétés :

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

Rechercher une structure par son nom

Si vous connaissez le nom d'une structure, vous pouvez également y accéder à l'aide de la propriété name :

val myHome = home.structures().list().first { it.name == "My home" }

Vous pouvez ensuite accéder aux propriétés, aux pièces et aux appareils de chaque structure.

Travailler avec plusieurs structures

Pour utiliser plusieurs structures, obtenez une référence distincte pour chacune d'elles :

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
}

Obtenir une liste de pièces

Une fois une structure obtenue, vous pouvez obtenir une liste de pièces et accéder à leurs propriétés :

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

Créer une pièce

Pour créer une pièce :

val testName = "Test Room Name"
val newRoom: Room = structure.createRoom(testName)

Supprimer une pièce

Vous pouvez également supprimer une pièce :

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

Vous pouvez également supprimer une pièce avec un simple ID :

val roomToDelete1 = allRooms.filter { it.id == testRoomId }.firstOrNull()
structure.deleteRoom(roomToDelete1!!)

Si une pièce contenant des appareils est supprimée, les appareils restent dans la structure, mais ne sont plus associés à une pièce.

Déplacer des appareils dans une autre pièce

Une fois une structure obtenue, vous pouvez déplacer des appareils dans une autre pièce de cette structure :

val room2 = structure.rooms().get(Id("room_id_other_structure"))
    val device1 = structure.devices().get(Id("device_id1"))
    structure.moveDevicesToRoom(room2!!, listOf(device1!!))

Si vous ne disposez que des ID d'appareil et de pièce, vous pouvez également déplacer des appareils :

structure.moveDevicesToRoom(Id("room_id_other_structure"), listOf(Id("device_id1")))

Modifier le nom d'une pièce

Appelez la setName() méthode pour modifier le nom d'une pièce :

livingRoom.setName("Living Room")

Les noms seront tronqués s'ils dépassent la limite de 60 points de code Unicode (caractères), et aucune erreur ne sera générée. Les développeurs sont responsables de la gestion des noms longs. Ils peuvent, par exemple, décider d'informer les utilisateurs que les noms seront tronqués.

Dans l'écosystème Google Home, pour la plupart des types d'appareils, les utilisateurs peuvent accorder des autorisations pour tous les appareils de ce type à la fois. Pour les types d'appareils sensibles ou soumis à des restrictions, tels que les serrures, les caméras ou les sonnettes, les utilisateurs doivent accorder des autorisations individuellement.

Pour déterminer si un utilisateur a accordé l'autorisation d'accéder à un type d'appareil sensible ou soumis à des restrictions, utilisez la fonction consentedDeviceTypes() au niveau de la structure :

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

Automatisations

Le point d'entrée de l'API Automation se fait via une structure. Pour en savoir plus sur les automatisations dans les API Home, consultez la présentation de l'API Automation sur Android.