Monitorowanie stanu urządzenia w iOS

W interfejsach Home API na iOS śledzenie zmian stanu w domu jest możliwe dzięki użyciu frameworka Combine w języku Swift. Śledzenie zmian w strukturach, pokojach, metadanych urządzeń i stanie urządzeń w interfejsach Home API można przeprowadzić za pomocą dowolnego interfejsu API, używając HomeDevice. Odbywa się to przez subskrybowanie wydawców udostępniających wartości z asynchronicznych zdarzeń.

Gdy element w kolekcji zostanie dodany, usunięty lub zmodyfikowany, zwracana jest najnowsza migawka kolekcji.

Deweloper musi samodzielnie określić konkretne zmiany, porównując tę migawkę ze starszą kopią. W tym celu można użyć pola id udostępnianego w przypadku każdego typu obiektu nadrzędnego w interfejsach Home API.

Jak rozpakować obiekty opcjonalne

Gdy obiekt jest opcjonalny, użyj if let lub guard, aby bezpiecznie go rozpakować. Nie używaj !, ponieważ nie należy go używać, chyba że deweloper ma pewność, że obiekt nie może mieć wartości null.!

Parametr wejściowy structureID w przykładzie jest zdefiniowany jako String?, co oznacza, że jest to ciąg znaków, który jest opcjonalny i może mieć wartość null. Ta funkcja znajduje obiekt Structure na podstawie danych wejściowych w structureID.

Oto jak zalecamy obsługiwać obiekty opcjonalne:

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

Jak korzystać z wydawców

Poniżej znajdziesz kilka podstawowych przykładów pracy z wydawcami w interfejsach Home API. W przypadku tych przykładów należy utworzyć instancję Home.

var home: Home?

Zanim uzyskasz dostęp do kolekcji, rozpakuj je, ponieważ są opcjonalne:

guard let home else { return nil }

Śledzenie zmian w strukturze

Ta kolekcja jest wywoływana przez te zmiany w strukturze:

  • Nazwa struktury
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)")
    }
  }

Śledzenie zmian w konkretnym urządzeniu

Ta kolekcja jest wywoływana przez te zmiany w urządzeniu:

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

Śledzenie zmian w konkretnej cesze urządzenia

Użyj dowolnej cechy obsługiwanej przez urządzenie i interfejsy Home API. Pełną listę znajdziesz w sekcji 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)")
    }
  }

Śledzenie zmian w konkretnym typie urządzenia

Ta kolekcja jest wywoływana przez te zmiany w typie urządzenia:

Użyj dowolnego typu urządzenia Matter obsługiwanego przez interfejsy Home API. Pełną listę znajdziesz w sekcji 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)")
    }
  }

Śledzenie zmian w pokoju w strukturze

Ta kolekcja jest wywoływana przez te zmiany w pokoju:

Aby śledzić, kiedy urządzenia są dodawane do pokoju lub z niego usuwane, użyj devices() zapytania.

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

Subskrybowanie zdarzeń

W interfejsach Home API zdarzenia służą do wykrywania zmian stanu urządzenia.

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