Monitorowanie stanu urządzenia w iOS

W interfejsach API Home na iOS można obserwować zmiany stanu w domu za pomocą ramy Combine w Swift. Obserwowanie zmian w strukturach, pomieszczeniach, metadanych urządzeń i stanie urządzeń w interfejsach API Home jest możliwe za pomocą dowolnego interfejsu API, który używa HomeDevice. Aby to zrobić, zasubskrybuj wydawców, którzy udostępniają wartości z zdarzeń asynchronicznych.

Gdy dodasz, usuniesz lub zmodyfikujesz dowolny element kolekcji, zwrócony zostanie jej najnowszy snapshot.

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

Jak rozpakować opcjonalne obiekty

Jeśli obiekt jest opcjonalny, użyj wartości if let lub guard, aby bezpiecznie go rozpakować. Nie używaj !, ponieważ ! nigdy nie powinno być używane, chyba że deweloper wie na pewno, że obiekt nie może być równy nil.

W tym przykładzie parametr wejściowy structureID jest zdefiniowany jako String?, co oznacza, że jest to opcjonalny ciąg znaków, który może być równy 0. Ta funkcja znajduje obiekt Structure na podstawie danych wejściowych w parametrye structureID.

Oto jak zalecamy obsługiwać opcjonalne obiekty:

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 interakcji z wydawcami w ramach interfejsu Home API. W przypadku poniższych przykładów musisz utworzyć wystąpienie elementu Home.

var home: Home?

Zanim uzyskasz dostęp do kolekcji, musisz je rozpakować, ponieważ są opcjonalne:

guard let home else { return nil }

Śledzenie zmian w strukturze

Ta kolekcja jest wywoływana 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 danych dotyczących konkretnej cechy na urządzeniu

Użyj dowolnej cechy obsługiwanej przez urządzenie i interfejsy API Home. 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 tworzona, gdy nastąpią te zmiany typu urządzenia:

Użyj dowolnego typu urządzenia Matter obsługiwanego przez interfejsy API Home. 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

Te zmiany w pokoju powodują utworzenie kolekcji:

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

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 API Home 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()
  }
}