Gerätestatus unter iOS überwachen

In den Home APIs für iOS können Änderungen am Status im Zuhause mithilfe des Combine-Frameworks in Swift beobachtet werden. Änderungen an Strukturen, Räumen, Gerätemetadaten und Gerätestatus in den Home APIs können mit jeder API über HomeDevice beobachtet werden. Dazu abonniert man Publisher, die Werte aus asynchronen Ereignissen bereitstellen.

Wenn ein Element in einer Sammlung hinzugefügt, gelöscht oder geändert wird, wird der letzte Snapshot der Sammlung zurückgegeben.

Es liegt am Entwickler, die spezifischen Änderungen abzuleiten, indem er diesen Snapshot mit einer älteren Kopie vergleicht. Dazu kann das Feld id verwendet werden, das für jeden übergeordneten Objekttyp in den Home APIs bereitgestellt wird.

Optionale Objekte entpacken

Wenn ein Objekt optional ist, verwenden Sie if let oder guard, um das Objekt sicher zu entpacken. Verwenden Sie ! nicht, da ! nur verwendet werden sollte, wenn der Entwickler sicher ist, dass das Objekt nicht „nil“ sein kann.

Der Eingabeparameter structureID im Beispiel ist als String? definiert. Das bedeutet, dass es sich um einen optionalen String handelt, der auch „nil“ sein kann. Mit dieser Funktion wird das Structure-Objekt anhand der Eingabe in structureID gesucht.

So empfehlen wir, mit optionalen Objekten umzugehen:

func structure(structureID: String?) -> Structure? {
    guard let structureID else { return nil }
    return structures.first { $0.id == structureID }
  }

Verlage verwenden

Im Folgenden finden Sie einige grundlegende Beispiele für die Zusammenarbeit mit Verlagen und Webpublishern in den Home-APIs. Für die folgenden Beispiele muss eine Instanz von Home erstellt werden.

var home: Home?

Bevor Sie auf Sammlungen zugreifen, müssen Sie sie entpacken, da sie optional sind:

guard let home else { return nil }

Änderungen an einer Struktur verfolgen

Die folgenden Änderungen an einer Struktur lösen diese Erfassung aus:

home.structures().batched()
  .compactMap { $0.first(where: { $0.id = myStructureID} }
  .removeDuplicates()
  .sink { structure in
    if let structure = structure {
      print("Structure \(structure.id) updated to \(structure.name)")
    }
  }

Änderungen an einem bestimmten Gerät verfolgen

Die folgenden Änderungen an einem Gerät lösen diese Sammlung aus:

home.devices().batched()
  .compactMap { deviceList -> HomeDevice? in
    deviceList.filter { $0.name == "Bedroom Lamp"}.first
  }
  .removeDuplicates()
  .sink { lampDevice in
    if lampDevice != nil {
      print("The bedroom lamp has changed!")
    }
  }

Änderungen an einem bestimmten Merkmal auf einem Gerät verfolgen

Verwenden Sie ein beliebiges Merkmal, das vom Gerät und den Home-APIs unterstützt wird. Eine vollständige Liste finden Sie unter Trait.

device.types.subscribe(OnOffLightDeviceType.self)
  .compactMap { $0.matterTraits.onOffTrait }
  .removeDuplicates()
  .sink { onOffState in
    if let onOffState = onOffState {
      print("Got new state update: \(onOffState.onOff)")
    }
  }

Änderungen an einem bestimmten Typ auf einem Gerät verfolgen

Die folgenden Änderungen an einem Gerätetyp lösen diese Erfassung aus:

Verwenden Sie einen beliebigen Matter-Gerätetyp, der von den Home APIs unterstützt wird. Eine vollständige Liste finden Sie unter DeviceType.

device.types.subscribe(DimmableLightDeviceType.self)
  .compactMap { $0.matterTraits.levelControlTrait }
  .removeDuplicates()
  .sink { dimmableLightDevice in
    if let dimmableLightDevice = dimmableLightDevice
      print("Got new state update! \(levelControlTrait.currentLevel)")
    }
  }

Änderungen an einem Raum in einem Gebäude verfolgen

Die folgenden Änderungen an einem Chatroom lösen diese Sammlung aus:

Wenn Sie nachverfolgen möchten, wann Geräte einem Raum hinzugefügt oder daraus entfernt werden, verwenden Sie die devices()-Abfrage.

home.rooms().batched()
  .sink { rooms in
    print("Got a new updated set of rooms!")
    for room in rooms {
      print("Got room #\(room.name)")
    }
  }

Ereignisse abonnieren

In den Home APIs werden Ereignisse verwendet, um Änderungen am Status eines Geräts zu erkennen.

self.cancellable = self.device.types.subscribe(FanDeviceType.self)
  .receive(on: DispatchQueue.main)
  .catch { error in
    Logger.error("Error getting FanDeviceType: \(error)")
    return Empty<FanDeviceType, Never>().eraseToAnyPublisher()
  }
  .sink { [weak self] fanDeviceType in
    self?.fanDeviceType = fanDeviceType
    self?.updateTileInfo()
  }
}