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.

Fehlerbehebung

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

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, die bei jeder Änderung der Gerätemetadaten ein Set ausgibt, 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 wie Name, Raum oder Struktur neue Werte ausgibt. 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 als einzelnes Gerät darzustellen, indem Sie den Parameter enableMultipartDevices der Methode devices() auf true setzen. Weitere Informationen finden Sie unter Mehrteilige Geräte unter iOS.

Gerätetypen abrufen

Um die mit einem Gerät verknüpften Gerätetypen abzurufen, lesen Sie die device's types Property, die einen DeviceTypeController zurückgibt.

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-Attribut abrufen

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

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

Eine andere Art von Attributkollision kann auftreten, wenn ein Gerät zwei Attribute mit demselben Namen hat. Beispielsweise kann sich onOff auf eine Instanz des Standardattributs OnOff oder auf eine Instanz eines vom Hersteller definierten OnOff-Attributs beziehen. Um Unklarheiten darüber zu vermeiden, welches Attribut gemeint ist, verweisen Sie über eine der beiden Attributsammlungen auf jedem Gerätetyp auf ein Attribut.

Verwenden Sie für Standardattribute, die den Matter Standardclustern entsprechen, matterTraits. So rufen Sie beispielsweise ein bestimmtes Attribut für den Gerätetyp „Dimmbare Lampe“ 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-Attribute googleTraits:

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

Um auf ein herstellerspezifisches Attribut zuzugreifen, verweisen Sie über die traits-Property 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 OnOff-Attributs aus dem „Ein/Aus“-Attribut 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 Attribut abrufen

Um eine Liste der Geräte mit einem bestimmten Attribut abzurufen, müssen Sie die Geräte, die Gerätetypen der einzelnen Geräte und die Attribute der einzelnen Gerätetypen durchlaufen. So rufen Sie beispielsweise eine Liste der Geräte im Zuhause ab, die alle das Attribut „Ein/Aus“ 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 Attribute finden Sie unter Attributindex 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. Um eine umfassende Übersicht über den Gerätetyp auf höherer Ebene in einem Zuhause zu erhalten, müssen mehrere Gerätetypen einbezogen werden.

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

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

Das BasicInformationTrait Attribut 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 Attribut zu identifizieren:

  • Vom Connectivity Standards Alliance (Alliance) ausgestellte 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 matterOriginalVendorId und matterOriginalProductId Felder 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 Attributmetadaten

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

Jedes Attribut in den Home APIs enthält eine sourceConnectivity Property mit Informationen zum Onlinestatus und zur Lokalität eines Attributs (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 Attribut online ist

Lesen Sie die connectivityState-Property, um die Verbindung eines Attributs zu prüfen:

let levelControlConnectivity =
  levelControlTrait.metadata.sourceConnectivity
  .connectivityState

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

Verbindung für ein Gerät prüfen

Die Verbindung 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 Verbindungsstatus für alle Attribute auf diesem Gerät.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

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

IP-Adresse des Geräts abrufen

Verwenden Sie das Attribut networkInterfaces, um die IP-Adresse des Geräts zu ermitteln des GeneralDiagnosticsTrait. Die Adressen werden als Data-Objekte zurückgegeben, die Sie mit dem Network-Framework in Standard-IPv4- oder IPv6-Strings formatieren können:

func getIpAddresses(trait: Matter.GeneralDiagnosticsTrait) -> [String] {
  let interfaces = trait.attributes.networkInterfaces ?? []
  var ipAddresses: [String] = []

  for interface in interfaces {
    for data in interface.iPv4Addresses {
      if let ipv4 = IPv4Address(data) {
        ipAddresses.append(String(describing: ipv4))
      }
    }
    for data in interface.iPv6Addresses {
      if let ipv6 = IPv6Address(data) {
        ipAddresses.append(String(describing: ipv6))
      }
    }
  }

  return ipAddresses
}

Netzwerkrouting eines Attributs prüfen

Die Lokalität für ein Attribut ist auch in den Home APIs verfügbar. dataSourceLocality gibt an, ob das Attribut remote (über die Cloud), lokal (über einen lokalen Hub) oder Peer-to-Peer (direkt von Gerät zu Gerät, kein 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äteverbindung 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 Verbindung wird auch die Lokalität auf Gerätetypebene geprüft. Der zurückgegebene Status ist eine Kombination der Lokalität für alle Attribute auf diesem Gerät.

let lightLocality =
  dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality

Ein Status von mixed kann in einem ähnlichen Szenario wie bei der partiallyOnline-Verbindung auftreten: Einige Attribute 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.