Accéder aux appareils et aux métadonnées des appareils pour Android

Les API d'appareil sont accessibles via les API Home pour Android. Importez ces packages dans votre application :

import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id

Pour utiliser des types ou des caractéristiques d'appareil spécifiques avec les API d'appareil, vous devez les importer individuellement.

Par exemple, pour utiliser la caractéristique Matter On/Off et le type d'appareil On/Off Plug-in Unit, importez les packages suivants dans votre application :

import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice

Pour en savoir plus, consultez la section Modèle de données sur Android.

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 sur 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.

Toute exception non gérée entraînera le plantage de votre application.

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

Pour obtenir un exemple, consultez la section Envoyer une commande à un appareil.

Exemples d'appels

Obtenir la liste des appareils

Une fois que vous disposez d'une référence à l'instance Structure, un appel devices() renvoie un Flow d'appareils auxquels vous pouvez accéder à partir de cette structure :

// Get a flow of all devices accessible to the user
val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices()

// Calling list() on a HomeObjectsFlow returns the first Set of elements.
val allDevices: Set<HomeDevice> = allDevicesFlow.list()

Vous pouvez ensuite accéder aux états de chaque appareil et envoyer des commandes aux appareils.

Avec la version 1.8 des API Home, vous pouvez demander à l'API de représenter chaque appareil multipartite comme un seul appareil en définissant le paramètre enableMultipartDevices de la méthode devices() sur true. Pour en savoir plus, consultez la section Appareils multipartites sur Android.

Lire l'état d'un appareil

Consultez un exemple de vérification de l'attribut OnOff à partir de la caractéristique On/Off de l'appareil. À l'aide du modèle de données de caractéristique des API Home, où cette caractéristique est identifiée comme OnOff, vous pouvez récupérer les données de la caractéristique via la classe standardTraits du type d'appareil :

// Assuming we have a device.
val deviceFlow = home.devices().itemFlow(myDeviceId)

val device = deviceFlow.first()

// Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger
// on the specific trait changes and not the whole type.
val onOffTraitFlow: Flow<OnOff?> =
  device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged()

val onOffTrait: OnOff = onOffTraitFlow.first()!!

Pour en savoir plus sur la fonction de flux Kotlin, consultez la section distinctUntilChanged.

Invalider l'état dans un abonnement de caractéristique

L'interface TraitStateInvalidation permet d'invalider un état récupéré via des abonnements à l'appareil cible dans les cas où l'état n'est pas signalé correctement. Par exemple, l'état peut ne pas être signalé correctement si vous utilisez des attributs dans des caractéristiques Matter avec la qualité "C" ou en raison d'une implémentation d'appareil qui provoque de manière inattendue le problème.

Cette API émet une lecture forcée de l'état actuel de la caractéristique et renvoie le résultat via les flux de caractéristiques existants.

Obtenez la caractéristique, puis exécutez une forceRead sur celle-ci :

val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()

Obtenir la liste des caractéristiques d'un type d'appareil

Les types d'appareils doivent être utilisés comme point d'entrée pour la lecture des caractéristiques, car ils décomposent un appareil en ses éléments fonctionnels (comme les points de terminaison dans Matter).

Ils tiennent également compte des conflits de caractéristiques dans le cas où un appareil comporte deux types d'appareils, qui peuvent tous deux avoir la même caractéristique. Par exemple, si un appareil est à la fois un haut-parleur et une lumière à intensité variable, il aura deux caractéristiques On/Off et deux caractéristiques de contrôle du niveau.

Pour obtenir la liste des caractéristiques disponibles pour le type d'appareil Dimmable Light :

// Get all types available on this device. Requires the types to be part of the registry during
// SDK initialization.
val typesFlow: Flow<Set<DeviceType>> = device.types()

// Get a snapshot of all types.
val types: Set<DeviceType> = typesFlow.first()

// Get the DimmableLightDevice instance from the set of types.
val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull()

// Get all traits in the type + traits registered
val allTraits: Set<Trait> = dimmableLightDevice!!.traits()

Un autre type de conflit de caractéristiques peut se produire lorsqu'un appareil comporte deux caractéristiques portant le même nom. Par exemple, onOff peut faire référence à une instance de la caractéristique OnOff standard ou à une instance d'une caractéristique OnOff définie par le fabricant. Pour éliminer toute ambiguïté potentielle quant à la caractéristique visée, une instance Trait référencée via un appareil doit être précédée d'un espace de noms qualifiant. Pour les caractéristiques standards, c'est-à-dire celles qui sont analogues aux Matter clusters standards, utilisez standardTraits. Pour les caractéristiques Google, utilisez googleTraits :

// Accessing standard traits on the type.
val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff
val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl

Pour accéder à une caractéristique spécifique au fabricant, référencez-la directement :

// Accessing a custom trait on the type.
val customTrait = dimmableLightDevice.trait(MyCustomTrait)

Obtenir la liste des appareils avec une caractéristique spécifique

La filter fonction en Kotlin peut être utilisée pour affiner davantage les appels d'API. Par exemple, pour obtenir la liste des appareils de la maison qui ont tous la caractéristique On/Off :

// Get all devices that support OnOff
val onOffDevices: Flow<List<HomeDevice>> =
  home.devices().map { devices -> devices.filter { it.has(OnOff) } }

Consultez l'interface Trait pour obtenir la liste complète des caractéristiques disponibles dans les API Home.

Obtenir la liste des appareils avec des types d'appareils similaires

Pour obtenir la liste des appareils qui représentent toutes les lumières d'une maison :

// Get a list of devices with similar device types (lights)
val lightDevices =
  home.devices().map { devices ->
    devices.filter {
      it.has(DimmableLightDevice) ||
        it.has(OnOffLightDevice) ||
        it.has(ColorTemperatureLightDevice) ||
        it.has(ExtendedColorLightDevice)
    }
  }

Il existe plusieurs types d'appareils dans les API Home qui peuvent représenter un type d'appareil de base. Par exemple, il n'existe pas de type d'appareil "Light". Au lieu de cela, il existe quatre types d'appareils différents qui peuvent représenter une lumière, comme illustré dans l'exemple précédent. Par conséquent, pour obtenir une vue complète du type d'appareil de niveau supérieur dans une maison, plusieurs types d'appareils doivent être inclus dans les flux filtrés.

Consultez l'interface DeviceType pour obtenir la liste complète des types d'appareils disponibles dans les API Home.

Obtenir l'ID de fournisseur ou l'ID de produit d'un appareil

La caractéristique BasicInformation inclut des informations telles que l'ID de fournisseur, l'ID de produit, le nom du produit et le numéro de série d'un appareil :

// Get device basic information. All general information traits are on the RootNodeDevice type.
val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!!
println("vendorName ${basicInformation.vendorName}")
println("vendorId ${basicInformation.vendorId}")
println("productId ${basicInformation.productId}")

Identification des appareils cloud-to-cloud pour les fabricants d'appareils

Si vous êtes fabricant d'appareils et que vous créez des Cloud-to-cloud appareils, pour identifier vos Cloud-to-cloud appareils via la BasicInformation caractéristique, vous pouvez inclure ces champs de chaîne dans leur SYNC réponse :

  • ID de fournisseur émis par Connectivity Standards Alliance (Alliance) : "matterOriginalVendorId": "0xfff1",

  • Identifiant de produit qui identifie de manière unique un produit d'un fournisseur : "matterOriginalProductId": "0x1234",

  • Identifiant unique de l'appareil, construit d'une manière spécifique au fabricant : "matterUniqueId": "matter-device-id",

Lorsque vous saisissez ces champs de chaîne, utilisez vos Matter ID de fournisseur et de produit si vous en avez. Si vous n'êtes pas membre et que ces ID ne vous ont pas été attribués, vous pouvez laisser les champs matterOriginalVendorId et matterOriginalProductId vides et fournir matterUniqueId comme identifiant.Alliance

L'exemple de réponse SYNC montre l'utilisation de ces champs :

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "456",
        "type": "action.devices.types.LIGHT",
        "traits": [
          "action.devices.traits.OnOff",
          "action.devices.traits.Brightness",
          "action.devices.traits.ColorSetting",
        ],
        "willReportState": true,
        "deviceInfo": { ... },
        "matterOriginalVendorId": "0xfff1",
        "matterOriginalProductId": "0x1234",
        "matterUniqueId": "matter-device-id",
        "otherDeviceIds": [
          {
            "deviceId": "local-device-id",
          }
        ]
      }
    ]
  }
}

Pour en savoir plus, consultez la documentation Cloud-to-cloud SYNC.

Métadonnées d'appareil et de caractéristique

Les appareils et les caractéristiques des API Home sont associés à des métadonnées, ce qui peut vous aider à gérer l'expérience utilisateur dans une application.

Chaque caractéristique des API Home contient une sourceConnectivity propriété, qui fournit des informations sur l'état en ligne et la localité (routage local ou distant).

Obtenir le type principal d'un appareil

Certains appareils peuvent présenter plusieurs types d'appareils via les API Home. Pour s'assurer que les utilisateurs disposent des options appropriées dans une application (telles que le contrôle des appareils et les automatisations suggérées) pour leurs appareils, il est utile de vérifier le type d'appareil principal d'un appareil.

Tout d'abord, obtenez le ou les types d'appareil à l'aide de type(), puis déterminez le ou les types principaux :

val types = device.types().first()
val primaryTypes = types.filter { it.metadata.isPrimaryType }

Vérifier si une caractéristique est en ligne

Utilisez la méthode connectivityState() pour vérifier la connectivité d'une caractéristique :

val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState

Certaines caractéristiques, généralement les caractéristiques smart home Google, peuvent s'afficher hors connexion si l'appareil n'est pas connecté à Internet. En effet, ces caractéristiques sont basées sur le cloud et ne disposent pas de routage local.

Vérifier la connectivité d'un appareil

La connectivité d'un appareil est en fait vérifiée au niveau du type d'appareil, car certains appareils sont compatibles avec plusieurs types d'appareils. L'état renvoyé est une combinaison des états de connectivité de toutes les caractéristiques de cet appareil.

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

Un état PARTIALLY_ONLINE peut être observé dans le cas de types d'appareils mixtes lorsqu'il n'y a pas de connectivité Internet. Matter caractéristiques standards peuvent toujours être en ligne en raison du routage local, mais les caractéristiques basées sur le cloud seront hors connexion.

Vérifier le routage réseau d'une caractéristique

La localité d'une caractéristique est également disponible dans les API Home. dataSourceLocality indique si la caractéristique est routée à distance (via le cloud), localement (via un hub local) ou en peer-to-peer (directement d'appareil à appareil, sans hub).

La valeur de localité inconnue UNSPECIFIED est possible, par exemple, lorsqu'une application démarre et n'a pas encore atteint un hub ou un serveur pour la connectivité de l'appareil. Ces appareils ne sont pas accessibles et les requêtes d'interaction provenant de commandes ou d'événements échoueront. Il appartient au client de déterminer comment gérer ces appareils.

val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality

Vérifier le routage réseau d'un appareil

Comme la connectivité, la localité est vérifiée au niveau du type d'appareil. L'état renvoyé est une combinaison de la localité de toutes les caractéristiques de cet appareil.

val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality

Un état MIXED peut être observé dans un scénario similaire à celui de la connectivité PARTIALLY_ONLINE : certaines caractéristiques sont basées sur le cloud, tandis que d'autres sont locales.

Modifier le nom d'un appareil

Appelez la setName() méthode pour modifier le nom d'un appareil :

mixerDevice.setName("Grendel")

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 et peuvent, par exemple, décider s'ils souhaitent informer les utilisateurs que les noms seront tronqués.