Доступ к устройствам и метаданным устройств для Android

Доступ к API устройства можно получить через Home API для Android. Импортируйте эти пакеты в своё приложение:

import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id

Чтобы использовать определенные типы устройств или характеристики с API устройств, их необходимо импортировать по отдельности.

Например, чтобы использовать свойство Matter On/Off и тип устройства On/Off Plug-in Unit, импортируйте в свое приложение следующие пакеты:

import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice

Более подробную информацию см. в разделе Модель данных на Android .

Обработка ошибок

Любой метод в Home API может выдать исключение HomeException , поэтому мы рекомендуем использовать блок try-catch для перехвата HomeException во всех вызовах.

При обработке HomeException проверьте его code и поля message , чтобы узнать, что пошло не так.

Любые необработанные исключения приведут к сбою вашего приложения.

Более подробную информацию см. в разделе Обработка ошибок .

См. пример в разделе Отправка команды на устройство .

Примеры звонков

Получить список устройств

При наличии структуры вызов devices() возвращает поток устройств, доступных вам из этой структуры:

// Get a flow of all devices accessible to the user
val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices()

// Calling list() on a HomeObjectsFlow returns the first Set of elements.
val allDevices: Set<HomeDevice> = allDevicesFlow.list()

Отсюда становятся доступны состояния каждого устройства, и на устройство можно отправлять поддерживаемые команды.

Чтение состояния устройства

Рассмотрим пример проверки атрибута OnOff из свойства On/Off устройства. Используя модель данных свойств Home API, где это свойство идентифицировано как OnOff , вы можете получить данные свойства через класс standardTraits типа устройства:

// Assuming we have a device.
val deviceFlow = home.devices().itemFlow(myDeviceId)

val device = deviceFlow.first()

// Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger
// on the specific trait changes and not the whole type.
val onOffTraitFlow: Flow<OnOff?> =
  device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged()

val onOffTrait: OnOff = onOffTraitFlow.first()!!

Подробнее о функции потока Kotlin см. в разделе distinctUntilChanged

Отменить состояние в подписке на признак

Интерфейс TraitStateInvalidation позволяет аннулировать состояние, полученное через подписки на целевое устройство, в случаях, когда состояние отображается некорректно. Примерами случаев, когда состояние может отображаться некорректно, являются использование атрибутов в трейтах Matter с качеством «C» или реализация устройства, которая неожиданно вызывает проблему.

Этот API принудительно считывает текущее состояние признака и возвращает результат через существующие потоки признаков.

Получите признак, затем запустите forceRead для этого признака:

val generalDiagnosticsTrait = device.trait(GeneralDiagnostics).first()
generalDiagnosticsTrait.forceRead()

Получить список характеристик типа устройства

Типы устройств следует использовать в качестве точки входа для считывания характеристик, поскольку они разлагают устройство на его функциональные части (как конечные точки в Matter ).

Они также учитывают коллизии характеристик в случае, если устройство относится к двум типам устройств, у обоих из которых может быть одна и та же характеристика. Например, если устройство одновременно является динамиком и диммируемым светильником, у него будут две характеристики «Вкл./Выкл.» и две характеристики «Регулировка уровня».

Чтобы получить список доступных характеристик для типа устройства Dimmable Light:

// Get all types available on this device. Requires the types to be part of the registry during
// SDK initialization.
val typesFlow: Flow<Set<DeviceType>> = device.types()

// Get a snapshot of all types.
val types: Set<DeviceType> = typesFlow.first()

// Get the DimmableLightDevice instance from the set of types.
val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull()

// Get all traits in the type + traits registered
val allTraits: Set<Trait> = dimmableLightDevice!!.traits()

Другой тип конфликта трейтов может возникнуть, когда устройство имеет два трейта с одинаковым именем. Например, onOff может ссылаться на экземпляр стандартного трейта OnOff или на экземпляр трейта OnOff , определённого производителем. Чтобы исключить любую потенциальную неоднозначность относительно того, какой трейт подразумевается, экземпляру Trait , на который ссылается устройство, должно предшествовать соответствующее пространство имён. Для стандартных трейтов, то есть тех, которые аналогичны стандартным кластерам Matter , используйте standardTraits . Для трейтов Google используйте googleTraits :

// Accessing standard traits on the type.
val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff
val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl

Чтобы получить доступ к характеристике, специфичной для производителя, сошлитесь на нее напрямую:

// Accessing a custom trait on the type.
val customTrait = dimmableLightDevice.trait(MyCustomTrait)

Получить список устройств с определенной характеристикой

Функция filter в Kotlin может использоваться для дальнейшего уточнения вызовов API. Например, чтобы получить список устройств в доме, все из которых имеют свойство «Вкл/Выкл»:

// Get all devices that support OnOff
val onOffDevices: Flow<List<HomeDevice>> =
  home.devices().map { devices -> devices.filter { it.has(OnOff) } }

Полный список характеристик, доступных в API Home, смотрите в разделе Интерфейс Trait .

Получить список устройств с похожими типами устройств

Чтобы получить список устройств, представляющих все источники света в доме:

// Get a list of devices with similar device types (lights)
val lightDevices =
  home.devices().map { devices ->
    devices.filter {
      it.has(DimmableLightDevice) ||
        it.has(OnOffLightDevice) ||
        it.has(ColorTemperatureLightDevice) ||
        it.has(ExtendedColorLightDevice)
    }
  }

В API Home есть несколько типов устройств, которые могут представлять основной тип устройств. Например, отсутствует тип устройства «Светильник». Вместо него существует четыре различных типа устройств, которые могут представлять светильник, как показано в предыдущем примере. Таким образом, для получения комплексного представления о типах устройств более высокого уровня в доме необходимо включить несколько типов устройств в отфильтрованные потоки.

Полный список типов устройств, доступных в Home API, см. в интерфейсе DeviceType

Получите идентификатор поставщика или идентификатор продукта для устройства

Признак BasicInformation включает в себя такую информацию, как идентификатор поставщика, идентификатор продукта, название продукта и серийный номер устройства:

// Get device basic information. All general information traits are on the RootNodeDevice type.
val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!!
println("vendorName ${basicInformation.vendorName}")
println("vendorId ${basicInformation.vendorId}")
println("productId ${basicInformation.productId}")

Идентификация устройств в облаке для производителей устройств

Если вы являетесь производителем устройств и создаете устройства Cloud-to-cloud , то для идентификации ваших устройств Cloud-to-cloud с помощью признака BasicInformation вы можете включить следующие строковые поля в их ответ SYNC :

  • Альянс по стандартам связи (CSA) выдал идентификатор поставщика: "matterOriginalVendorId": "0xfff1",

  • Идентификатор продукта, который однозначно идентифицирует продукт поставщика: "matterOriginalProductId": "0x1234",

  • Уникальный идентификатор устройства, создаваемый производителем: "matterUniqueId": "matter-device-id",

При заполнении этих строковых полей используйте идентификаторы поставщика и продукта Matter , если они у вас есть. Если вы не являетесь участником CSA и вам не присвоены эти идентификаторы, вы можете оставить поля matterOriginalVendorId и matterOriginalProductId пустыми и указать идентификатор matterUniqueId .

Пример ответа SYNC показывает использование этих полей:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "456",
        "type": "action.devices.types.LIGHT",
        "traits": [
          "action.devices.traits.OnOff",
          "action.devices.traits.Brightness",
          "action.devices.traits.ColorSetting",
        ],
        "willReportState": true,
        "deviceInfo": { ... },
        "matterOriginalVendorId": "0xfff1",
        "matterOriginalProductId": "0x1234",
        "matterUniqueId": "matter-device-id",
        "otherDeviceIds": [
          {
            "deviceId": "local-device-id",
          }
        ]
      }
    ]
  }
}

Более подробную информацию см. в документации Cloud-to-cloud SYNC .

Метаданные устройств и характеристик

С устройствами и характеристиками в API Home связаны метаданные, которые могут помочь в управлении пользовательским интерфейсом в приложении.

Каждый признак в API Home содержит свойство sourceConnectivity , которое содержит информацию о сетевом статусе признака и его местоположении (локальная или удаленная маршрутизация).

Получить основной тип устройства

Некоторые устройства могут поддерживать несколько типов устройств через API Home. Чтобы пользователи получали в приложении необходимые функции (например, управление устройствами и предлагаемые варианты автоматизации) для своих устройств, полезно проверить основной тип устройства.

Сначала получите тип(ы) устройства с помощью type() , затем определите основной(ые) тип(ы):

val types = device.types().first()
val primaryTypes = types.filter { it.metadata.isPrimaryType }

Проверьте, доступен ли признак в сети

Используйте метод connectivityState() для проверки связности признака:

val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState

Некоторые характеристики, как правило, характеристики smart home Google, могут отображаться в режиме офлайн, если устройство не подключено к интернету. Это связано с тем, что эти характеристики работают в облаке и не имеют локальной маршрутизации.

Проверьте подключение к устройству

Подключённость устройства фактически проверяется на уровне типа устройства, поскольку некоторые устройства поддерживают несколько типов устройств. Возвращаемое состояние представляет собой комбинацию состояний подключения для всех характеристик этого устройства.

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

Состояние PARTIALLY_ONLINE может наблюдаться в случае смешанных типов устройств при отсутствии подключения к Интернету. Стандартные трейты Matter могут оставаться онлайн благодаря локальной маршрутизации, но облачные трейты будут недоступны.

Проверьте сетевую маршрутизацию признака

Местоположение признака также доступно в API Home. Параметр dataSourceLocality указывает, маршрутизируется ли признак удалённо (через облако), локально (через локальный концентратор) или одноранговым способом (напрямую с устройства на устройство, без концентратора).

Значение неизвестной локальности UNSPECIFIED возможно, например, когда приложение загружается и ещё не достигло концентратора или сервера для подключения устройств. Эти устройства недоступны и не будут отвечать на запросы взаимодействия от команд или событий. Клиент должен самостоятельно определить, как обращаться с такими устройствами.

val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality

Проверьте сетевую маршрутизацию для устройства

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

val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality

Состояние MIXED может наблюдаться в аналогичном сценарии, что и PARTIALLY_ONLINE подключение: некоторые характеристики являются облачными, а другие — локальными.

Изменить имя устройства

Вызовите метод setName() , чтобы изменить имя устройства:

mixerDevice.setName("Grendel")

Имена будут усечены, если их длина превышает лимит в 60 кодовых точек (символов) Unicode, без каких-либо ошибок. Разработчики несут ответственность за обработку длинных имён и, например, могут решить, следует ли уведомлять пользователей о том, что имена будут усечены.

список API

После создания экземпляра Home через него становятся доступны следующие API-интерфейсы устройств:

API Описание
devices() Получить все устройства во всех структурах учётной записи Google. Возвращает HomeObjectsFlow , предоставляющий дополнительные возможности поиска и фильтрации.

Если у вас есть HomeDevice , через него доступны следующие API:

API Описание
allCandidates() Возвращает всех кандидатов на автоматизацию для устройства и его дочерних элементов.
candidates() Возвращает всех кандидатов на автоматизацию для устройства.
connectivityStateChanged Последний раз, когда изменилось состояние устройства.
events(event) Получает поток определенного события.
events(trait) Получает поток всех событий по этой черте.
events(traits) Получает поток всех событий по этим чертам.
getSourceConnectivity(trait) Получить метаданные для определенного признака. Возвращает SourceConnectivity .
has(trait) Проверьте, поддерживается ли текущая запрошенная характеристика устройством.
has(type) Если устройство поддерживает предоставленный тип.
id Уникальный системный идентификатор устройства.
isInRoom Если устройство находится в помещении.
isInStructure Если устройство находится в конструкции.
isMatterDevice Если устройство поддерживается Matter .
name Имя устройства, указанное пользователем.
room() Комната, к которой относится устройство. Возвращает Room .
roomId Идентификатор комнаты, к которой назначено устройство. Возвращает Id .
sourceConnectivity Исходная связность устройства, представляющая агрегированные состояния связности и сетевую локальность характеристик устройства.
structure() Структура, к которой относится устройство. Возвращает Structure .
structureId Идентификатор структуры, к которой назначено устройство. Возвращает Id .
type(type) Получает определение типа с заполненными признаками (при наличии) для прямого доступа. Всегда возвращает актуальный снимок признаков.
types() Получите список всех типов, доступных на устройстве.