Мониторинг состояния устройства на iOS

В API Home для iOS отслеживание изменений состояния дома осуществляется с помощью фреймворка Combine в Swift. Отслеживание изменений в структурах, комнатах, метаданных устройства и состоянии устройства в API Home может быть выполнено с помощью любого API, использующего HomeDevice . Это достигается путем подписки на издателей, предоставляющих значения из асинхронных событий.

При добавлении, удалении или изменении любого элемента в коллекции возвращается последний снимок коллекции.

Разработчику предстоит определить конкретные изменения, сравнив этот снимок с более старой копией. Для этой цели можно использовать поле id , предоставляемое для каждого типа родительского объекта в API Home .

Как развернуть необязательные объекты

Если объект является необязательным, используйте if let или guard для безопасного извлечения объекта. Не используйте ! , потому что ! никогда не следует использовать, если разработчик точно не знает, что объект не может быть `nil`.

The input parameter structureID in the example is defined as String? , which means it's a string that is optional and has the possibility of being nil. This function finds the Structure object based on the input in structureID .

Вот как мы рекомендуем обрабатывать необязательные объекты:

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

Как использовать издателей

Ниже приведены несколько базовых примеров работы с издателями в API Home. Для выполнения этих примеров необходимо создать экземпляр Home .

var home: Home?

Перед доступом к коллекциям обязательно распакуйте их, поскольку это необязательный шаг:

guard let home else { return nil }

Отслеживание изменений в структуре

Следующие изменения в структуре запускают этот сбор данных:

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

Отслеживание изменений на конкретном устройстве

Следующие изменения в устройстве запускают этот сбор данных:

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

Отслеживание изменений определенного параметра на устройстве

Используйте любые характеристики, поддерживаемые устройством и API Home. Полный список см. в разделе 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)")
    }
  }

Отслеживание изменений определенного типа на устройстве

Следующие изменения типа устройства запускают этот сбор данных:

Используйте любой тип устройства Matter , поддерживаемый API Home. Полный список см. в 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)")
    }
  }

Отслеживание изменений в помещении здания.

Следующие изменения в помещении запускают эту коллекцию:

Для отслеживания добавления или удаления устройств из комнаты используйте запрос devices() .

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

Подпишитесь на мероприятия

В API Home события используются для обнаружения изменений состояния устройства.

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