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

Vous pouvez accéder aux API de l'appareil 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'appareils spécifiques avec les API Device, ils doivent être importés individuellement.

Par exemple, pour utiliser le trait Matter et le type d'appareil "Module enfichable marche/arrêt", 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 Modèle de données sur Android.

Gestion des exceptions

Toute 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 ses champs code et message pour savoir ce qui s'est mal passé.

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

Pour en savoir plus, consultez Gestion des erreurs.

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

Exemples d'appels

Obtenir la liste des appareils

Avec la structure disponible, un appel devices() renvoie un flux d'appareils auxquels vous avez accès à 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()

Les états de chaque appareil sont alors accessibles et les commandes compatibles peuvent être envoyées à l'appareil.

Lire l'état d'un appareil

Examinons un exemple de vérification de l'attribut OnOff à partir du trait On/Off de l'appareil. En utilisant le modèle de données de caractéristiques des API Home, où cette caractéristique est identifiée comme OnOff, vous pouvez récupérer les données de caractéristiques 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 distinctUntilChanged.

Invalider l'état dans un abonnement à un trait

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. Voici quelques exemples de cas où l'état peut ne pas être signalé correctement : utilisation d'attributs dans des caractéristiques Matter avec la qualité "C" ou en raison d'une implémentation d'appareil qui provoque le problème de manière inattendue.

Cette API effectue une lecture forcée de l'état actuel du trait et renvoie le résultat via les flux de traits existants.

Obtenez le trait, puis exécutez un forceRead sur le trait :

val generalDiagnosticsTrait = device.trait(GeneralDiagnostics).first()
generalDiagnosticsTrait.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 traits, car ils décomposent un appareil en ses éléments fonctionnels (comme les points de terminaison dans Matter).

Ils tiennent également compte des collisions 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 une enceinte et une lumière à intensité variable, il aura deux traits "Marche/Arrêt" et deux traits "Contrôle du niveau".

Pour obtenir la liste des caractéristiques disponibles pour le type d'appareil "Lumière à intensité variable" :

// 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 possède deux caractéristiques portant le même nom. Par exemple, onOff peut faire référence à une instance du trait OnOff standard ou à une instance d'un trait OnOff défini par le fabricant. Pour éliminer toute ambiguïté potentielle quant au trait visé, une instance Trait référencée par le biais d'un appareil doit être précédée d'un espace de noms qualifiant. Pour les traits standards, c'est-à-dire ceux qui sont analogues aux clusters standards Matter, utilisez standardTraits. Pour les traits Google, utilisez googleTraits :

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

Pour accéder à un trait spécifique à un fabricant, faites-y directement référence :

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

Obtenir la liste des appareils dotés d'un trait spécifique

La fonction filter 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 possèdent tous le trait 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 ayant 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)
    }
  }

Les API Home comportent plusieurs types d'appareils qui peuvent représenter un type d'appareil principal. Par exemple, il n'existe pas de type d'appareil "Lumière". Au lieu de cela, il existe quatre types d'appareils différents qui peuvent représenter une lumière, comme le montre l'exemple précédent. Par conséquent, pour obtenir une vue complète des types d'appareils 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 du fournisseur ou du produit pour un appareil

Le trait BasicInformation inclut des informations telles que l'ID du fournisseur, l'ID du 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 à cloud pour les fabricants d'appareils

Si vous êtes fabricant d'appareils Cloud-to-cloud et que vous souhaitez identifier vos appareils Cloud-to-cloud à l'aide du trait BasicInformation, vous pouvez inclure ces champs de chaîne dans leur réponse SYNC :

  • L'ID fournisseur émis par la Connectivity Standards Alliance (CSA) : "matterOriginalVendorId": "0xfff1",

  • Code 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 ID de fournisseur et de produit Matter si vous en avez. Si vous n'êtes pas membre de la CSA 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.

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 de l'appareil et du trait

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

Chaque trait des API Home contient une propriété sourceConnectivity qui fournit des informations sur l'état en ligne et la localité (routage local ou à distance) d'un trait.

Obtenir le type principal d'un appareil

Certains appareils peuvent présenter plusieurs types d'appareils via les API Home. Pour vous assurer que les utilisateurs disposent des options appropriées dans une application (comme 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.

Commencez par obtenir 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 un trait est en ligne

Utilisez la méthode connectivityState() pour vérifier la connectivité d'un trait :

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

Certains traits, généralement les traits Google smart home, 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 tous les traits de cet appareil.

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

Un état PARTIALLY_ONLINE peut être observé dans le cas de types d'appareils mixtes en l'absence de connectivité Internet. Les traits standards Matter peuvent toujours être en ligne en raison du routage local, mais les traits basés sur le cloud seront hors connexion.

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

La localité d'un trait est également disponible dans les API Home. dataSourceLocality indique si le trait est acheminé à 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 demandes 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é pour tous les traits de cet appareil.

val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality

Dans un scénario semblable à celui de la connectivité PARTIALLY_ONLINE, un état MIXED peut être observé : certains traits sont basés dans le cloud, tandis que d'autres sont locaux.

Modifier le nom d'un appareil

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

mixerDevice.setName("Grendel")

Liste des API

Une fois qu'une instance de Home est créée, les API d'appareil suivantes sont accessibles via celle-ci :

API Description
devices() Récupérez tous les appareils de toutes les structures sur le compte Google. Renvoie un HomeObjectsFlow qui fournit d'autres options de récupération et de filtrage.

Une fois que vous disposez d'un HomeDevice, vous pouvez accéder aux API suivantes :

API Description
allCandidates() Renvoie tous les candidats à l'automatisation pour l'appareil et ses enfants.
candidates() Renvoie tous les candidats à l'automatisation pour l'appareil.
connectivityStateChanged Dernière heure à laquelle l'état de l'appareil a changé.
events(event) Obtient un flux d'un événement spécifique.
events(trait) Obtient un flux de tous les événements de ce trait.
events(traits) Obtient un flux de tous les événements par ces caractéristiques.
getSourceConnectivity(trait) Obtenez les métadonnées d'un trait spécifique. Renvoie un objet SourceConnectivity.
has(trait) Vérifiez si le trait demandé est pris en charge par l'appareil.
has(type) Si l'appareil est compatible avec le type fourni.
id ID système unique de l'appareil.
isInRoom Si l'appareil se trouve dans une pièce.
isInStructure Si l'appareil se trouve dans une structure.
isMatterDevice Si l'appareil est couvert par Matter.
name Nom de l'appareil fourni par l'utilisateur.
room() Pièce à laquelle l'appareil est attribué. Renvoie un objet Room.
roomId ID de la pièce à laquelle l'appareil est attribué. Renvoie un Id.
sourceConnectivity Connectivité source de l'appareil, représentant les états de connectivité agrégés et la localité réseau des caractéristiques de l'appareil.
structure() Structure à laquelle l'appareil est attribué. Renvoie un objet Structure.
structureId ID de la structure à laquelle l'appareil est attribué. Renvoie un Id.
type(type) Obtenez la définition du type avec les caractéristiques renseignées (le cas échéant) pour un accès direct. Renvoie toujours un instantané à jour des caractéristiques.
types() Obtenez la liste de tous les types disponibles sur l'appareil.