Dostęp do urządzeń i metadanych urządzeń w iOS

Do interfejsów API urządzeń można uzyskać dostęp za pomocą interfejsów API Home na iOS. Zaimportuj do aplikacji te pakiety:

import GoogleHomeSDK
import GoogleHomeTypes

Więcej informacji znajdziesz w artykule Model danych na iOS.

Obsługa błędów

Niektóre metody w interfejsach API Home wywołują błądHomeError, dlatego zalecamy użycie bloku do-catch, aby przechwycić błądHomeError w tych wywołaniach.

Podczas obsługi HomeError sprawdź pola codemessage, aby dowiedzieć się, co poszło nie tak.

Każdy nieobsługiwany błąd spowoduje awarię aplikacji.

Więcej informacji znajdziesz w sekcji Postępowanie z błędami.

Przykład znajdziesz w sekcji Wysyłanie polecenia do urządzenia.

Przykładowe rozmowy

Pobieranie listy urządzeń

W ramach odwołania do obiektu Home wywołaj metodę devices(), aby uzyskać listę Query urządzeń dostępnych w ramach usługi. Wywołaj metodę Query's batched() metody, która emituje zestaw odzwierciedlający bieżący stan Home przy każdej zmianie metadanych urządzenia. Możesz też zadzwonić pod numer Query.list(), aby uzyskać podgląd dostępnych urządzeń. To wygodna metoda, która subskrybuje strumień batched() i zwraca pierwszą wyemitowaną wartość. Query.stream() wygeneruje strumień, który emituje nowe wartości w przypadku zmian metadanych urządzenia, takich jak nazwa, pomieszczenie lub struktura. Wewnętrznie używa ona funkcji batched() i wysyła tylko zmienione właściwości.

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

Tutaj możesz sprawdzić stany poszczególnych urządzeń i wysyłać do nich obsługiwane polecenia.

Pobieranie typów urządzeń

Aby uzyskać typy urządzeń powiązane z danym urządzeniem, odczytaj właściwość types urządzenia, która zwraca wartość DeviceTypeController.

Aby subskrybować aktualizacje dotyczące konkretnego typu urządzenia, zadzwoń pod numer DeviceTypeController.subscribe(_:):

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

Jeśli urządzenie nie obsługuje określonego typu urządzenia, zwraca wartość Empty Publisher, która jest wykonywana natychmiast.

Jeśli urządzenie obsługuje określony typ urządzenia, możesz uzyskać uchwyt tego typu, wywołując funkcję get():

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

Jeśli urządzenie nie obsługuje określonego typu, zwraca wartość nil.

Zadzwoń pod numer DeviceTypeController.subscribeAll(), aby uzyskać PublisherDeviceTypeCollection. Ta klasa umożliwia sprawdzenie, czy urządzenie ma określony typ:

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

Pobieranie cechy typu urządzenia

Typy urządzeń są punktem wejścia do odczytu cech, ponieważ dzielą urządzenie na elementy funkcjonalne (np. punkty końcowe w Matter).

Uwzględniają one też kolizje cech w przypadku urządzeń, które mają 2 typy, z których każdy może mieć tę samą cechę. Jeśli na przykład urządzenie jest jednocześnie głośnikiem i ściemniaczem, ma 2 cechy włączania/wyłączania i 2 cechy regulacji poziomu.

Inny rodzaj kolizji cech może wystąpić, gdy urządzenie ma 2 cechy o tej samej nazwie. Na przykład onOff może odnosić się do instancji standardowej cechy OnOff lub instancji cechy OnOff zdefiniowanej przez producenta. Aby uniknąć niejasności, która cecha ma być używana, odwołuj się do cechy za pomocą jednej z dwóch kolekcji cech na każdym typie urządzenia.

W przypadku standardowych cech, czyli takich, które są analogiczne do standardowych klastrów Matter, użyj matterTraits. Aby na przykład uzyskać konkretną cechę dla typu urządzenia „Światło z możliwością przyciemnienia”:

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

W przypadku cech Google użyj googleTraits:

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

Aby uzyskać dostęp do cechy specyficznej dla producenta, odwołuj się do niej za pomocą właściwości traits, ale poprzedz ją nazwą pakietu producenta:

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
}

Czytanie stanu urządzenia

Oto przykład sprawdzania atrybutu OnOff z właściwości włączenia/wyłączenia urządzenia:

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
}

Pobieranie listy urządzeń z określonymi cechami

Aby uzyskać listę urządzeń z określonymi cechami, musisz przejrzeć urządzenia, ich typy i cechy każdego typu. Aby na przykład uzyskać listę urządzeń w domu, które mają włączoną lub wyłączoną funkcję:

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

Pełną listę cech dostępnych w interfejsach API Home znajdziesz w indeksie cech na iOS.

Pobieranie listy urządzeń o podobnych typach

Aby zobaczyć listę urządzeń odpowiadających wszystkim lampom w domu:

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

Interfejsy API Home obsługują wiele typów urządzeń, które mogą reprezentować podstawowy typ urządzenia. Na przykład nie ma typu urządzenia „Światło”. Zamiast tego w poprzednim przykładzie występują 4 różne typy urządzeń, które mogą reprezentować światło. Aby uzyskać pełny obraz typu urządzenia w domu na wyższym poziomie, musisz uwzględnić kilka typów urządzeń.

Pełną listę typów urządzeń i ich cech dostępnych w interfejsach API Home znajdziesz na stronie Obsługiwane typy urządzeń na iOS.

Pobieranie nazwy, identyfikatora lub identyfikatora produktu producenta urządzenia

Cecha BasicInformationTrait zawiera informacje takie jak identyfikator dostawcy, identyfikator produktu, nazwa produktu i numer seryjny urządzenia:

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

Identyfikacja urządzeń w chmurze dla producentów urządzeń

Jeśli jesteś producentem urządzeń i tworzysz urządzenia Cloud-to-cloud, aby zidentyfikować swoje urządzenia Cloud-to-cloud za pomocą atrybutu BasicInformation, możesz uwzględnić te pola ciągu w odpowiedzi SYNC:

  • Identyfikator dostawcy wydany przez Connectivity Standards Alliance (CSA):"matterOriginalVendorId": "0xfff1",

  • Identyfikator produktu, który jednoznacznie identyfikuje produkt sprzedawcy:"matterOriginalProductId": "0x1234",

  • Unikalny identyfikator urządzenia, który jest tworzony w sposób specyficzny dla producenta:"matterUniqueId": "matter-device-id",

Podczas wypełniania tych pól tekstowych użyj identyfikatorów Matter dostawcy i produktu, jeśli je masz. Jeśli nie jesteś członkiem CSA i nie masz przypisanych tych identyfikatorów, możesz pozostawić pola matterOriginalVendorId i matterOriginalProductId puste i podać matterUniqueId jako identyfikator.

Przykładowa odpowiedź SYNC pokazuje użycie tych pól:

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

Więcej informacji znajdziesz w dokumentacji Cloud-to-cloud SYNC.

Metadane urządzenia i cechy

Urządzenia i cechy w interfejsach API Home są powiązane z metadanymi, które mogą ułatwiać zarządzanie wrażeniami użytkowników w aplikacji.

Każda cecha w interfejsach API Home zawiera właściwość sourceConnectivity, która zawiera informacje o stanie online i lokalizacji cechy (przekierowanie lokalne lub zdalne).

Pobieranie głównego typu urządzenia

Niektóre urządzenia mogą wyświetlać wiele typów urządzeń za pomocą interfejsów API Home. Aby użytkownicy widzieli odpowiednie opcje aplikacji (np. sterowanie urządzeniem i sugerowane automatyzacje) na swoich urządzeniach, warto sprawdzić, czy typ urządzenia jest jego głównym typem.

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

Sprawdzanie, czy cecha jest dostępna online

Aby sprawdzić łączność cechy, odczytaj właściwość connectivityState:

let levelControlConnectivity =
  levelControlTrait.metadata.sourceConnectivity
  .connectivityState

Niektóre cechy, zwykle cechy Google smart home, mogą być wyświetlane offline, jeśli urządzenie nie ma połączenia z internetem. Dzieje się tak, ponieważ te cechy działają w chmurze i nie mają routingu lokalnego.

Sprawdzanie połączenia urządzenia

Możliwość połączenia z urządzeniem jest sprawdzana na poziomie typu urządzenia, ponieważ niektóre urządzenia obsługują wiele typów urządzeń. Zwrócony stan to kombinacja stanów połączeń wszystkich cech na danym urządzeniu.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

Stan partiallyOnline może wystąpić w przypadku mieszanych typów urządzeń, gdy nie ma połączenia z internetem. Matter cechy standardowe mogą nadal być dostępne online ze względu na routing lokalny, ale cechy oparte na chmurze będą offline.

Sprawdzanie kierowania sieciowego cechy

Lokalizacja atrybutu jest też dostępna w interfejsach API Home. dataSourceLocality wskazuje, czy cecha jest kierowana zdalnie (przez chmurę), lokalnie (przez lokalny hub) czy peer-to-peer (bezpośrednio z urządzenia na urządzenie, bez huba).

Nieznana wartość lokalizacji unspecified może wystąpić na przykład podczas uruchamiania aplikacji, która nie połączyła się jeszcze z hubem ani serwerem. Nie można się połączyć z tymi urządzeniami, a ich prośby o interakcję nie będą realizowane. To klient decyduje, jak ma postępować z takimi urządzeniami.

let levelControlLocality =
  levelControlTrait.metadata.sourceConnectivity
  .dataSourceLocality

Sprawdzanie trasowania sieci na urządzeniu

Podobnie jak w przypadku łączności, lokalizacja jest sprawdzana na poziomie typu urządzenia. Zwrócony stan to kombinacja lokalizacji wszystkich cech na danym urządzeniu.

let lightLocality =
  dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality

Stan mixed może być obserwowany w podobnym scenariuszu jak w przypadku połączeń partiallyOnline: niektóre cechy są oparte na chmurze, a inne są lokalne.

Lista interfejsów API

Po utworzeniu instancji interfejsu Home są dostępne te interfejsy API urządzenia:

Interfejs API Opis
device(id:) Zwraca Publisher dla określonego urządzenia, które emituje stan urządzenia, gdy ten się zmienia.
devices() Uzyskaj dostęp do wszystkich urządzeń we wszystkich strukturach na koncie Google. Zwraca Query<HomeDevice>, który zawiera dalsze opcje wyszukiwania i filtrowania.

Gdy masz konto HomeDevice, możesz korzystać z tych interfejsów API:

Interfejs API Opis
id Unikalny identyfikator systemu urządzenia.
name Nazwa urządzenia podana przez użytkownika.
structureID Identyfikator struktury, do której przypisany jest dany sprzęt. Zwraca wartość String?.
roomID Identyfikator pokoju, do którego przypisana jest kamera. Zwraca wartość String?.
types Pobierz określony typ lub wszystkie dostępne typy na urządzeniu.
isMatterDevice Jeśli urządzenie jest obsługiwane przez Matter.
sourceConnectivity Łączność źródłowa urządzenia, która reprezentuje zbiorcze stany łączności i lokalizację sieciową cech urządzenia.