Auf Geräte und Gerätemetadaten für iOS zugreifen

Auf Geräte-APIs kann über die Home APIs für iOS zugegriffen werden. Importieren Sie die folgenden Pakete in Ihre App:

import GoogleHomeSDK
import GoogleHomeTypes

Weitere Informationen finden Sie unter Datenmodell unter iOS.

Fehlerbehandlung

Einige Methoden in den Home APIs geben einen HomeError aus. Wir empfehlen daher, einen do-catch Block zu verwenden, um HomeError bei diesen Aufrufen abzufangen.

Prüfen Sie bei der Behandlung von HomeError die Felder code und message , um herauszufinden, was schiefgelaufen ist.

Nicht behandelte Fehler führen zum Absturz Ihrer App.

Weitere Informationen finden Sie unter Fehlerbehandlung.

Ein Beispiel finden Sie unter Befehl an ein Gerät senden.

Beispielaufrufe

Geräteliste abrufen

Rufen Sie mit einem Verweis auf das Home Objekt devices() auf, um eine Query der zugänglichen Geräte abzurufen. Rufen Sie die Methode Query's batched() auf. Diese gibt bei jeder Änderung der Gerätemetadaten ein Set aus, das den aktuellen Status des Zuhauses widerspiegelt. Alternativ können Sie Query.list() aufrufen, um eine Momentaufnahme der verfügbaren Geräte zu erhalten. Dies ist eine Hilfsmethode, die den batched()-Stream abonniert und den ersten ausgegebenen Wert zurückgibt. Query.stream() erzeugt einen Stream, der bei Änderungen der Gerätemetadaten neue Werte ausgibt, z. B. bei Änderungen des Namens, des Raums oder der Struktur. Intern wird batched() verwendet und nur die geänderten Attribute werden ausgegeben.

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

Von dort aus können Sie auf die Status der einzelnen Geräte zugreifen und Befehle an Geräte senden.

Mit Version 1.8 der Home APIs haben Sie die Möglichkeit, jedes mehrteilige Gerät von der API als einzelnes Gerät darstellen zu lassen. Dazu müssen Sie den Parameter enableMultipartDevices der Methode devices() auf true setzen. Weitere Informationen finden Sie unter Mehrteilige Geräte unter iOS.

Gerätetypen abrufen

Wenn Sie die Gerätetypen abrufen möchten, die mit einem Gerät verknüpft sind, lesen Sie die Property types des Geräts. Diese gibt einen DeviceTypeControllerzurück.

Rufen Sie DeviceTypeController.subscribe(_:) auf, um Updates für einen bestimmten Gerätetyp zu abonnieren:

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

Wenn das Gerät den angegebenen Gerätetyp nicht unterstützt, wird ein Empty Publisher zurückgegeben, der sofort abgeschlossen wird.

Wenn das Gerät einen bestimmten Gerätetyp unterstützt, können Sie ein Handle für diesen Typ abrufen, indem Sie get() aufrufen:

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

Wenn das Gerät den angegebenen Typ nicht unterstützt, wird nil zurückgegeben.

Rufen Sie DeviceTypeController.subscribeAll() auf, um ein Publisher von DeviceTypeCollectionzu erhalten. Mit dieser Klasse können Sie prüfen, ob das Gerät einen bestimmten Gerätetyp hat:

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

Gerätetyp-Trait abrufen

Gerätetypen sind der Einstiegspunkt zum Lesen von Traits, da sie ein Gerät in seine funktionalen Teile zerlegen (z. B. Endpunkte in Matter).

Sie berücksichtigen auch Trait-Kollisionen, wenn ein Gerät zwei Gerätetypen hat, die beide dasselbe Trait haben können. Wenn ein Gerät beispielsweise sowohl ein Lautsprecher als auch eine dimmbare Lampe ist, hat es zwei „Ein/Aus“- und zwei „Level Control“-Traits.

Eine andere Art von Trait-Kollision kann auftreten, wenn ein Gerät zwei Traits mit demselben Namen hat. Beispielsweise könnte sich onOff auf eine Instanz des Standard-Traits OnOff oder auf eine Instanz eines vom Hersteller definierten OnOff-Traits beziehen. Um potenzielle Unklarheiten hinsichtlich des beabsichtigten Traits zu vermeiden, verweisen Sie auf ein Trait über eine der beiden Trait-Sammlungen für jeden Gerätetyp.

Verwenden Sie für Standard-Traits, die den Matter Standardclustern entsprechen, matterTraits. So rufen Sie beispielsweise ein bestimmtes Trait für den Gerätetyp „Dimmable Light“ ab:

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

Verwenden Sie für Google-Traits googleTraits:

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

Wenn Sie auf ein herstellerspezifisches Trait zugreifen möchten, verweisen Sie über die Property traits darauf, stellen Sie aber den Paketnamen des Herstellers voran:

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
}

Gerätestatus lesen

Hier ist ein Beispiel für das Prüfen des Attributs OnOff aus dem „Ein/Aus“-Trait des Geräts:

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
}

Liste der Geräte mit einem bestimmten Trait abrufen

Wenn Sie eine Liste der Geräte mit einem bestimmten Trait abrufen möchten, müssen Sie die Geräte, die Gerätetypen der einzelnen Geräte und die Traits der einzelnen Gerätetypen durchlaufen. So rufen Sie beispielsweise eine Liste der Geräte im Zuhause ab, die alle das „Ein/Aus“-Trait haben:

// Get all light devices that support levelControl
var levelControlDevices: [HomeDevice] = []
let 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)
    }
  }
}

Eine vollständige Liste der in den Home APIs verfügbaren Traits finden Sie unter Trait-Index unter iOS.

Liste der Geräte mit ähnlichen Gerätetypen abrufen

So rufen Sie eine Liste der Geräte ab, die alle Lampen in einem Zuhause darstellen:

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

In den Home APIs gibt es mehrere Gerätetypen, die einen Kerngerätetyp darstellen können. Es gibt beispielsweise keinen Gerätetyp „Lampe“. Stattdessen gibt es vier verschiedene Gerätetypen, die eine Lampe darstellen können, wie im vorherigen Beispiel gezeigt. Wenn Sie also eine umfassende Übersicht über den Gerätetyp auf höherer Ebene in einem Zuhause erhalten möchten, müssen mehrere Gerätetypen berücksichtigt werden.

Eine vollständige Liste der Gerätetypen und ihrer Traits, die in den Home APIs verfügbar sind, finden Sie unter Unterstützte Gerätetypen unter iOS.

Anbieternamen, Anbieter-ID oder Produkt-ID für ein Gerät abrufen

Das BasicInformationTrait Trait enthält Informationen wie die Anbieter-ID, die Produkt-ID, den Produktnamen und die Seriennummer eines Geräts:

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

Cloud-zu-Cloud-Geräteidentifikation für Gerätehersteller

Wenn Sie Gerätehersteller sind und Cloud-to-cloud Geräte entwickeln, können Sie diese Stringfelder in die SYNC-Antwort aufnehmen, um Ihre Cloud-to-cloud Geräte über das BasicInformation Trait zu identifizieren:

  • Die von der Connectivity Standards Alliance (Alliance) ausgegebene Anbieter-ID: "matterOriginalVendorId": "0xfff1",

  • Eine Produkt-ID, die ein Produkt eines Anbieters eindeutig identifiziert: "matterOriginalProductId": "0x1234",

  • Eine eindeutige ID für das Gerät, die herstellerspezifisch erstellt wird: "matterUniqueId": "matter-device-id",

Verwenden Sie beim Eingeben dieser Stringfelder Ihre Matter Anbieter- und Produkt-IDs, falls vorhanden. Wenn Sie kein Alliance Mitglied sind und diese IDs nicht zugewiesen wurden, können Sie die Felder matterOriginalVendorId und matterOriginalProductId leer lassen und matterUniqueId als ID angeben.

In der Beispiel-SYNC-Antwort wird die Verwendung dieser Felder gezeigt:

{
  "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",
          }
        ]
      }
    ]
  }
}

Weitere Informationen finden Sie in der Cloud-to-cloud SYNC Dokumentation.

Geräte- und Trait-Metadaten

Geräten und Traits in den Home APIs sind Metadaten zugeordnet, die bei der Verwaltung der Nutzererfahrung in einer App hilfreich sein können.

Jedes Trait in den Home APIs enthält eine sourceConnectivity Property mit Informationen zum Online-Status und zur Lokalität eines Traits (lokales oder Remote-Routing).

Primären Typ eines Geräts abrufen

Einige Geräte können über die Home APIs mehrere Gerätetypen darstellen. Damit Nutzern in einer App die entsprechenden Optionen für ihre Geräte angezeigt werden (z. B. Gerätesteuerung und vorgeschlagene Automatisierungen), ist es hilfreich zu prüfen, ob ein Gerätetyp der primäre Typ des Geräts ist.

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

Prüfen, ob ein Trait online ist

Lesen Sie die Property connectivityState, um die Konnektivität eines Traits zu prüfen:

let levelControlConnectivity =
  levelControlTrait.metadata.sourceConnectivity
  .connectivityState

Einige Traits, in der Regel Google smart home Traits, werden möglicherweise als offline angezeigt, wenn das Gerät keine Internetverbindung hat. Das liegt daran, dass diese Traits cloudbasiert sind und kein lokales Routing haben.

Konnektivität für ein Gerät prüfen

Die Konnektivität für ein Gerät wird auf Gerätetypebene geprüft, da einige Geräte mehrere Gerätetypen unterstützen. Der zurückgegebene Status ist eine Kombination der Konnektivitätsstatus für alle Traits auf diesem Gerät.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

Bei gemischten Gerätetypen kann der Status partiallyOnline auftreten, wenn keine Internetverbindung besteht. Matter Standard Traits sind aufgrund des lokalen Routings möglicherweise weiterhin online, cloudbasierte Traits jedoch offline.

Netzwerkrouting eines Traits prüfen

Die Lokalität für ein Trait ist auch in den Home APIs verfügbar. Die dataSourceLocality gibt an, ob das Trait remote (über die Cloud), lokal (über einen lokalen Hub) oder Peer-to-Peer (direkt von Gerät zu Gerät, ohne Hub) geroutet wird.

Der unbekannte Lokalitätswert unspecified ist beispielsweise möglich, wenn eine App gestartet wird und noch keinen Hub oder Server für die Gerätekonnektivität erreicht hat. Diese Geräte sind nicht erreichbar und Interaktionsanfragen von Befehlen oder Ereignissen schlagen fehl. Es liegt am Client, wie mit solchen Geräten umgegangen wird.

let levelControlLocality =
  levelControlTrait.metadata.sourceConnectivity
  .dataSourceLocality

Netzwerkrouting für ein Gerät prüfen

Wie die Konnektivität wird auch die Lokalität auf Gerätetypebene geprüft. Der zurückgegebene Status ist eine Kombination der Lokalität für alle Traits auf diesem Gerät.

let lightLocality =
  dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality

Ein Status von mixed kann in einem ähnlichen Szenario wie bei der partiallyOnline-Konnektivität auftreten: Einige Traits sind cloudbasiert, andere lokal.

Namen eines Geräts ändern

Rufen Sie die setName(_:) Methode auf, um den Namen eines Geräts zu ändern:

let updatedDevice = try await theDevice.setName("new device name")

Wenn Sie den Namen eines Geräts ändern, bleibt die ursprüngliche HomeDevice-Struktur unverändert und die Änderung wird im zurückgegebenen aktualisierten HomeDevice-Objekt widergespiegelt.

Namen werden abgeschnitten, wenn sie das Limit von 60 Unicode-Codepunkten (Zeichen) überschreiten. Es werden keine Fehler ausgegeben. Entwickler sind für die Verarbeitung langer Namen verantwortlich und können beispielsweise entscheiden, ob sie Nutzer darüber informieren möchten, dass Namen abgeschnitten werden.