Руководство по устройству Chime для Android

Основной тип устройства Chime можно реализовать с помощью стандартного признака на основе Matter com.google.home.matter.standard.Chime или собственной версии признака от Google com.google.home.google.Chime, которая, помимо возможностей, указанных в стандарте Matter, поддерживает внешние звонки. Устройство с сигналом также может реализовывать черту Identify, которая позволяет идентифицировать его по внешнему виду или звуку.

Перед использованием функций или попыткой обновить атрибуты всегда проверяйте, поддерживаются ли они устройством. Подробнее о том, как управлять устройствами на сайтеAndroid…

Тип устройства для Home API Функции Пример приложения на Kotlin История успеха

Звонок

ChimeDevice

home.matter.0000.types.0146

Устройство, которое может воспроизводить различные предустановленные звуки и обычно используется с дверным звонком, аудиодомофоном или видеодомофоном.

Обязательные черты
     matter Chime

Необязательные черты
     matter Identify
Дверной звонок

Как получить основную информацию об устройстве

   Реализовано в тестовом приложении для Android   

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

// Get device basic information. All general information traits are on the RootNodeDevice type.
    device.type(RootNodeDevice).first().standardTraits.basicInformation?.let { basicInformation ->
        println("vendorName ${basicInformation.vendorName}")
        println("vendorId ${basicInformation.vendorId}")
        println("productId ${basicInformation.productId}")
        println("productName ${basicInformation.productName}")
        println("softwareVersion ${basicInformation.softwareVersion}")
    }

Поддержка многочастных сообщений

Звонок может состоять из нескольких типов устройств, включая звонок и, при необходимости, колонку. Кроме того, некоторые колокольчики оснащены Thread Border Router (TBR). Чтобы обеспечить максимально широкую поддержку, приложения, использующие API Home и управляющие звонками, должны быть написаны с учетом многокомпонентных устройств. Подробнее об устройствах, состоящих из нескольких частей…

Каждое устройство с многочастным звонком должно быть представлено в приложении одной карточкой. Устройство Chime должно быть основным, а колонка Child Speaker – частью Chime.

Громкость динамика должна быть основной настройкой устройства Chime.

Сопоставление OnOff

Для звонка с типами устройств "Звонок" и "Колонка" кнопка "Вкл./Выкл." в управляющем приложении должна быть сопоставлена с атрибутом Enabled звонка.

Согласно Matter спецификации библиотеки устройств, если задать для атрибута Enabled признака Chime значение False, то, помимо отключения звукового сигнала, будет подавлен звук и визуальные индикаторы.

Поддержка автоматизации

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

Звуки могут использоваться в качестве триггеров и действий для автоматизации.

Любое устройство, входящее в состав родительского устройства Chime и используемое в автоматизации, должно быть указано с помощью AutomationPartPath.

В примере ниже показано, как создать автоматизацию с многочастным звуковым сигналом, который реализует черту Chime, а также Speaker. Автоматизация запускается, когда открывается входная дверь:

import com.google.home.automation.automation
import com.google.home.automation.greaterThan
import com.google.home.google.GoogleDoorDevice
import com.google.home.google.OpenClose
import com.google.home.matter.standard.ChimeDevice
import com.google.home.matter.standard.Chime
// ...

// Fetch devices
val devices = homeManager.devices()

// Fetch devices using the multipart device model.
val multipartDevices = homeManager.devices(enableMultipartDevices = true)

val doorDevice = devices.first() {
  it.has(GoogleDoorDevice) &&
  it.has(OpenClose)
}

// Obtain a reference to the chime device.
val chime = multipartDevices.first() {
  it.has(ChimeDevice) &&
  it.has(Chime)
}

// Extract the AutomationPartPath for the specific Chime part
val chimePartPath = chime.automationPart(chime.part(ChimeDevice).first())!!

// Build the automation
val chimeAutomation = automation {
  sequential {
    val doorOpenClose = stateReader<_>(doorDevice, GoogleDoorDevice, OpenClose)
    // Starter: When the door state changes
    val starterNode = starter<_>(doorDevice, GoogleDoorDevice, OpenClose)
    condition {
     expression = doorOpenClose.openPercent greaterThan(0)
    }
    // Action: Play a chime sound
    action(chimePartPath) {
      command(Chime.playChimeSound())
    }
  }
}

Дополнительную информацию об автоматизации с использованием многокомпонентных устройств можно найти в разделе Автоматизация с использованием многокомпонентных устройств.

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

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

   Реализовано в тестовом приложении для Android   
val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

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

Как узнать IP-адрес устройства

Чтобы найти IP-адрес устройства, используйте атрибут networkInterfaces признака GeneralDiagnostics. Адреса возвращаются в виде массивов байтов, которые можно отформатировать в стандартные строки IPv4 или IPv6:

val ipAddresses =
  trait.networkInterfaces?.flatMap { networkInterface ->
    (networkInterface.ipv4Addresses + networkInterface.ipv6Addresses).mapNotNull { bytes ->
      try {
        java.net.InetAddress.getByAddress(bytes).hostAddress
      } catch (e: java.net.UnknownHostException) {
        null
      }
    }
  } ?: emptyList()