Monitorowanie stanu urządzenia w iOS

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

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

Deweloper musi sam określić konkretne zmiany, porównując ten migawkę ze starszą kopią. Do tego celu można użyć pola id udostępnionego dla 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 rozpakować obiekt. Nie używaj operatora !, ponieważ nie należy go stosować, 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 wyszukuje 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 współpracy z wydawcami w interfejsach Home API. W przypadku poniższych przykładów należy utworzyć instancję elementu Home.

var home: Home?

Przed uzyskaniem dostępu do kolekcji rozpakuj je, ponieważ są opcjonalne:

guard let home else { return nil }

Śledzenie zmian w strukturze

Ta kolekcja jest aktywowana przez te zmiany w strukturze:

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 na określonym urządzeniu

Ta kolekcja jest wywoływana przez te zmiany na 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 przypadku konkretnej cechy na urządzeniu

Używaj dowolnych cech obsługiwanych przez urządzenie i interfejsy Home API. Pełną listę znajdziesz w 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 określonego typu na urządzeniu

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

Używaj dowolnego Mattertypu urządzenia obsługiwanego przez interfejsy Home API. Pełną listę znajdziesz w 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 wydarzeń

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
    Logger.error("Error getting FanDeviceType: \(error)")
    return Empty<FanDeviceType, Never>().eraseToAnyPublisher()
  }
  .sink { [weak self] fanDeviceType in
    self?.fanDeviceType = fanDeviceType
    self?.updateTileInfo()
  }
}