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

Vous pouvez accéder aux API de l'appareil via les API Home pour iOS. Importez les packages suivants dans votre application:

import GoogleHomeSDK
import GoogleHomeTypes

Pour en savoir plus, consultez Modèle de données sur iOS.

Gestion des exceptions

Certaines méthodes des API Home génèrent une exception HomeError. Nous vous recommandons donc d'utiliser un bloc do-catch pour intercepter les exceptions HomeError sur ces appels.

Lorsque vous gérez HomeError, vérifiez ses champs code et message pour savoir ce qui s'est mal passé.

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

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

Pour en savoir plus, consultez Envoyer une commande à un appareil.

Exemples d'appels

Obtenir la liste des appareils

Avec une référence à l'objet Home, appelez devices() pour obtenir une Query d'appareils accessibles. Appelez la méthode batched() de Query, qui émet un ensemble reflétant l'état actuel de la maison à chaque modification des métadonnées de l'appareil. Vous pouvez également appeler Query.list() pour obtenir un instantané des appareils disponibles. Il s'agit d'une méthode pratique qui s'abonne au flux batched() et renvoie la première valeur émise. Query.stream() produit un flux qui émet de nouvelles valeurs en cas de modification des métadonnées de l'appareil, telles que son nom, sa pièce ou sa structure. En interne, cela utilise batched() et n'émet que les propriétés modifiées.

// Get a list of all devices accessible to the user
let homeDevices = try await self.home.devices().list()

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

Obtenir les types d'appareils

Pour obtenir les types d'appareils associés à un appareil, lisez la propriété types de l'appareil, qui renvoie un DeviceTypeController.

Appelez DeviceTypeController.subscribe(_:) pour vous abonner aux mises à jour d'un type d'appareil spécifique:

let devices = try await self.home.devices().list()
if let device = devices.first(where: { $0.id == myDeviceId }) {
  var receivedUpdate1 = false
  var receivedUpdate2 = false
  device.types.subscribe(OnOffLightDeviceType.self)
    .assertNoFailure()
    .sink { device in
      if !receivedUpdate1 {
        receivedUpdate1 = true
        Task {
          try await device.matterTraits.onOffTrait?.on()
        }
        return
      }
      if !receivedUpdate2 {
        receivedUpdate2 = true
        return
      }
      fatalError("Received unexpected update")
    }
}

Si l'appareil n'est pas compatible avec le type d'appareil spécifié, il renvoie un Empty Publisher qui se termine immédiatement.

Si l'appareil est compatible avec un type d'appareil spécifique, vous pouvez obtenir un gestionnaire de ce type en appelant get():

if let device = devices.first(where: { $0.id == myDeviceId }) {
  let deviceType = await device.types.get(OnOffLightDeviceType.self)
}

Si l'appareil n'est pas compatible avec le type spécifié, il renvoie nil.

Appelez DeviceTypeController.subscribeAll() pour obtenir un Publisher de DeviceTypeCollection. Cette classe vous permet de vérifier si l'appareil dispose d'un type d'appareil particulier:

if let device = devices.first(where: { $0.id == myDeviceId }) {
  device.types.subscribeAll()
    .assertNoFailure()
    .sink { types in
      let lightDeviceType = types[OnOffLightDeviceType.self]
      let fanDeviceType = types[FanDeviceType.self]
    }
}

Obtenir une caractéristique de type d'appareil

Les types d'appareils sont le 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 prennent également en compte les 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 ampoule à intensité variable, il comporte deux attributs "Marche/Arrêt" et deux attributs "Contrôle du niveau".

Un autre type de collision de traits peut se produire lorsqu'un appareil comporte deux traits 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 concernant la caractéristique souhaitée, référencez une caractéristique via l'une des deux collections de caractéristiques pour chaque type d'appareil.

Pour les traits standards, c'est-à-dire ceux qui sont analogues aux clusters standards Matter, utilisez matterTraits. Par exemple, pour obtenir une caractéristique spécifique pour le type d'appareil "Lumière à intensité variable" :

if let dimmableLightDeviceType =
  await device.types.get(DimmableLightDeviceType.self)
{
  // Accessing standard trait on the type.
  let levelControlTrait =
    dimmableLightDeviceType.matterTraits.levelControlTrait.self
}

Pour les traits Google, utilisez googleTraits:

if let doorbellDeviceType = await device.types.get(GoogleDoorbellDeviceType.self) {
  // Accessing Google trait on the type.
  let doorbellPressTrait =
    doorbellDeviceType.googleTraits.doorbellPressTrait.self
}

Pour accéder à un trait spécifique au fabricant, faites-y référence via la propriété traits, mais préfixez-la par le nom du package du fabricant:

let deviceType = await device1?.types.get(OnOffLightDeviceType.self)
// Accessing custom trait on the type.
if let spinnerTrait = deviceType?.traits[ExampleOrganization.SpinnerTrait.self] {
  let rpmVal = spinnerTrait.attributes.rpm
}

Lire l'état d'un appareil

Examinez cet exemple de vérification de l'attribut OnOff à partir du trait "Marche/Arrêt" de l'appareil:

let lightDevices = devices.filter {
  $0.types.contains(OnOffLightDeviceType.self)
}
let light1 = lightDevices.first
let lightDeviceTypeOptional = await light1?.types.get(OnOffLightDeviceType.self)
if let onOffTrait = lightDeviceTypeOptional?.matterTraits.onOffTrait {
  let onOffVal = onOffTrait.attributes.onOff
}

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

Pour obtenir la liste des appareils présentant une caractéristique spécifique, vous devez itérer sur les appareils, les types d'appareils de chaque appareil et les caractéristiques de chaque type d'appareil. Par exemple, pour obtenir la liste des appareils de la maison qui ont tous la caractéristique Marche/Arrêt:

// Get all light devices that support levelControl
var levelControlDevices: [HomeDevice] = []
var allDevices = try await home.devices().list()
for device in allDevices {
  if let deviceType = await device.types.get(OnOffLightDeviceType.self) {
    if deviceType.traits.contains(Matter.LevelControlTrait.self) {
      levelControlDevices.append(device)
    }
  }
}

Consultez l'index des traits sur iOS pour obtenir la liste complète des traits disponibles dans les API Home.

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

Pour obtenir la liste des appareils représentant toutes les ampoules d'une maison:

// Get a list of devices with similar device types (lights)
let lightDevices =
  try await self.home.devices().list().compactMap {
    $0.types.contains(DimmableLightDeviceType.self)
      || $0.types.contains(OnOffLightDeviceType.self)
      || $0.types.contains(ColorTemperatureLightDeviceType.self)
      || $0.types.contains(ExtendedColorLightDeviceType.self)
  }

Dans les API Home, plusieurs types d'appareils peuvent représenter un type d'appareil de base. Par exemple, il n'existe pas de type d'appareil "Ampoule". Au lieu de cela, quatre types d'appareils différents peuvent représenter une lumière, comme indiqué dans 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.

Consultez la section Types d'appareils compatibles sur iOS pour obtenir la liste complète des types d'appareils et de leurs caractéristiques disponibles dans les API Home.

Obtenir le nom, l'ID ou l'identifiant produit du fournisseur d'un appareil

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

guard
  let vendorName =
    basicInfoTrait.attributes.vendorName
else {
  fatalError("Failed to get vendorName")
}
guard
  let vendorID =
    basicInfoTrait.attributes.vendorID
else {
  fatalError("Failed to get vendorID")
}
guard
  let productID =
    basicInfoTrait.attributes.productID
else {
  fatalError("Failed to get productID")
}

Identifier les appareils cloud-to-cloud

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

  • L'ID du fournisseur délivré 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, qui est construit de 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, le cas échéant. Si vous n'êtes pas membre de la CSA et que vous n'avez pas reçu ces ID, vous pouvez laisser les champs matterOriginalVendorId et matterOriginalProductId vides et indiquer 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 SYNC Cloud-to-cloud.

Métadonnées de l'appareil et des traits

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

Chaque caractéristique des API Home contient une propriété sourceConnectivity, qui contient des informations sur l'état en ligne et la localité d'une caractéristique (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 vous assurer que les utilisateurs voient les options appropriées dans une application (telles que le contrôle de l'appareil et les suggestions d'automatisation) pour leurs appareils, il est utile de vérifier si un type d'appareil est le type principal de l'appareil.

if let deviceType =
  await device?.types.get(HumiditySensorDeviceType.self)
{
  if deviceType.metadata.isPrimaryType {
    print("Humidity Sensor is the primary type on this device.")
  } else {
    print("Humidity Sensor isn't the primary type on this device.")
  }
}

Vérifier si un trait est en ligne

Lisez la propriété connectivityState pour vérifier la connectivité d'un trait:

let levelControlConnectivity =
  levelControlTrait.metadata.sourceConnectivity
  .connectivityState

Certains traits, en particulier les traits Google smart home, peuvent s'afficher hors connexion si l'appareil n'est pas connecté à Internet. En effet, ces traits sont basés dans 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.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

Un état partiallyOnline peut être observé en cas de types d'appareils mixtes en l'absence de connexion Internet. Les traits standards Matter peuvent toujours être en ligne en raison du routage local, mais les traits basés dans 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 la caractéristique est acheminée à distance (via le cloud), localement (via un hub local) ou en pair à pair (directement d'un appareil à un autre, sans hub).

La valeur de localité inconnue unspecified est possible, par exemple, lorsqu'une application démarre et qu'elle n'a pas encore atteint de hub ou de 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. C'est au client de déterminer comment gérer ces appareils.

let levelControlLocality =
  levelControlTrait.metadata.sourceConnectivity
  .dataSourceLocality

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

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

let lightLocality =
  dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality

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

Liste des API

Une fois une instance de Home créée, les API Device suivantes sont accessibles via celle-ci:

API Description
device(id:) Renvoie un Publisher pour l'appareil spécifié qui émet l'état de l'appareil chaque fois qu'il change.
devices() Récupérez tous les appareils de toutes les structures du compte Google. Affiche un objet Query<HomeDevice> qui fournit d'autres options de récupération et de filtrage.

Une fois que vous disposez d'un HomeDevice, les API suivantes y sont accessibles:

API Description
id ID système unique de l'appareil.
name Nom de l'appareil fourni par l'utilisateur.
structureID ID de la structure à laquelle l'appareil est attribué. Renvoie un objet String?.
roomID ID de la chambre à laquelle l'appareil est attribué. Renvoie un objet String?.
types Obtenez un type spécifique ou tous les types disponibles sur l'appareil.
isMatterDevice Si l'appareil est sauvegardé par Matter.
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.