Acessar dispositivos e metadados de dispositivos para Android

As APIs de dispositivo podem ser acessadas pelas APIs Home para Android. Importe estes pacotes para o app:

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

Para usar tipos ou características de dispositivos específicos com as APIs de dispositivo, eles precisam ser importados individualmente.

Por exemplo, para usar a característica de ativação/desativação do Matter Matter e o tipo de dispositivo de unidade de plug-in de ativação/desativação, importe os seguintes pacotes para o aplicativo:

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

Para mais informações, consulte Modelo de dados no Android.

Tratamento de erros

Qualquer método nas APIs Home pode gerar uma HomeException. Por isso, recomendamos que você use um try-catch para detectar HomeException em todas as chamadas.

Ao processar HomeException, verifique os campos error.code e error.message para saber o que deu errado. Também pode haver códigos de sub-erro também. Portanto, chame o getSubErrorCodes() método e verifique o resultado.

Qualquer exceção não tratada vai resultar em falha do app.

Para mais informações, consulte Tratamento de erros.

Consulte Enviar um comando a um dispositivo para ver um exemplo.

Exemplos de chamadas

Receber uma lista de dispositivos

Depois de ter uma referência à instância Structure, uma chamada devices() retorna um Flow de dispositivos acessíveis a você dessa estrutura:

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

A partir daí, você pode acessar os estados de cada dispositivo e enviar comandos a eles.

Com a versão 1.8 das APIs Home, você tem a opção de fazer com que a API represente cada dispositivo multipartes como um único dispositivo definindo o parâmetro enableMultipartDevices do método devices() como true. Consulte Dispositivos multipartes no Android para mais informações.

Ler o estado de um dispositivo

Confira um exemplo de como verificar o atributo OnOff da característica de ativação/desativação do dispositivo. Usando o modelo de dados de característica das APIs Home, em que essa característica é identificada como OnOff, você pode recuperar dados de características pela classe standardTraits do tipo de dispositivo:

// 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()!!

Consulte distinctUntilChanged para saber mais sobre a função de fluxo do Kotlin.

Invalidar o estado em uma assinatura de característica

A interface TraitStateInvalidation oferece a capacidade de invalidar um estado recuperado por assinaturas do dispositivo de destino nos casos em que o estado não está sendo informado corretamente. Exemplos de quando o estado pode não ser informado corretamente incluem o uso de atributos em características do Matter com a qualidade "C" ou devido a uma implementação de dispositivo que causa o problema inesperadamente.

Essa API emite uma leitura forçada do estado atual da característica e retorna o resultado por fluxos de características atuais.

Receba a característica e execute um forceRead nela:

val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()

Receber uma lista de características de tipo de dispositivo

Os tipos de dispositivos precisam ser usados como um ponto de entrada para a leitura de características, já que eles decompõem um dispositivo em partes funcionais (como endpoints no Matter).

Eles também consideram colisões de características no caso de um dispositivo apresentar dois tipos de dispositivos, ambos com a mesma característica. Por exemplo, se um dispositivo for um alto-falante e uma luz regulável, ele terá duas características de ativação/desativação e duas de controle de nível.

Para receber a lista de traits disponíveis para o tipo de dispositivo de luz regulável:

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

Outro tipo de colisão de características pode ocorrer quando um dispositivo tem duas características com o mesmo nome. Por exemplo, onOff pode se referir a uma instância da característica OnOff padrão ou a uma instância de uma característica OnOff definida pelo fabricante. Para eliminar qualquer ambiguidade potencial quanto à característica pretendida, uma instância Trait referenciada por um dispositivo precisa ser precedida por um namespace qualificado. Para características padrão, ou seja, aquelas análogas aos Matter clusters padrão, use standardTraits. Para características do Google, use googleTraits:

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

Para acessar uma característica específica do fabricante, faça referência a ela diretamente:

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

Receber uma lista de dispositivos com uma característica específica

A função filter no Kotlin pode ser usada para refinar ainda mais as chamadas de API. Por exemplo, para receber uma lista de dispositivos na casa que tenham a característica de ativação/desativação:

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

Consulte a Trait interface para conferir uma lista completa de características disponíveis nas APIs Home.

Receber uma lista de dispositivos com tipos de dispositivos semelhantes

Para receber uma lista de dispositivos que representam todas as luzes de uma casa:

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

Há vários tipos de dispositivos nas APIs Home que podem representar um tipo de dispositivo principal. Por exemplo, não há um tipo de dispositivo "Luz". Em vez disso, há quatro tipos de dispositivos diferentes que podem representar uma luz, conforme mostrado no exemplo anterior. Assim, para ter uma visão abrangente do tipo de dispositivo de nível superior em uma casa, vários tipos de dispositivos precisam ser incluídos em fluxos filtrados.

Consulte a interface DeviceType para conferir uma lista completa de tipos de dispositivos disponíveis nas APIs Home.

Receber o ID do fornecedor ou do produto de um dispositivo

A BasicInformation característica inclui informações como ID do fornecedor, ID do produto, nome do produto e o número de série de um dispositivo:

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

Identificação de dispositivos de nuvem para nuvem para fabricantes de dispositivos

Se você é um fabricante de dispositivos e cria Cloud-to-cloud dispositivos, para identificar seus Cloud-to-cloud dispositivos pela BasicInformation característica, inclua estes campos de string na resposta SYNC:

  • O ID do fornecedor emitido pela Connectivity Standards Alliance (Alliance) issued vendor ID: "matterOriginalVendorId": "0xfff1",

  • Um identificador de produto que identifica exclusivamente um produto de um fornecedor: "matterOriginalProductId": "0x1234",

  • Um identificador exclusivo do dispositivo, que é construído de maneira específica do fabricante: "matterUniqueId": "matter-device-id",

Ao inserir esses campos de string, use os IDs de Matter fornecedor e produto, se você os tiver. Se você não for membro e não tiver recebido esses IDs, deixe os campos e em branco e forneça o como identificador.AlliancematterOriginalVendorIdmatterOriginalProductIdmatterUniqueId

O exemplo de resposta SYNC mostra o uso desses campos:

{
  "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",
          }
        ]
      }
    ]
  }
}

Para mais informações, consulte a documentação Cloud-to-cloud SYNC.

Metadados de dispositivos e características

Os dispositivos e as características nas APIs Home têm metadados associados a eles, o que pode ajudar a gerenciar a experiência do usuário em um app.

Cada característica nas APIs Home contém uma sourceConnectivity propriedade, que tem informações sobre o status on-line e a localidade de uma característica (roteamento local ou remoto).

Receber o tipo principal de um dispositivo

Alguns dispositivos podem apresentar vários tipos de dispositivos pelas APIs Home. Para garantir que os usuários recebam as opções adequadas em um app (como controle de dispositivos e automações sugeridas) para os dispositivos deles, é útil verificar qual é o tipo de dispositivo principal.

Primeiro, receba os tipos do dispositivo usando type(), e determine os tipos principais:

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

Verificar se uma característica está on-line

Use o método connectivityState() para verificar a conectividade de uma característica:

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

Algumas características, normalmente as do Google smart home, podem aparecer off-line se o dispositivo não tiver conectividade com a Internet. Isso ocorre porque essas características são baseadas na nuvem e não têm roteamento local.

Verificar a conectividade de um dispositivo

A conectividade de um dispositivo é verificada no nível do tipo de dispositivo, porque alguns dispositivos são compatíveis com vários tipos de dispositivos. O estado retornado é uma combinação dos estados de conectividade de todas as características desse dispositivo.

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

Um estado de PARTIALLY_ONLINE pode ser observado no caso de tipos de dispositivos mistos quando não há conectividade com a Internet. As características padrão do Matter ainda podem estar on-line devido ao roteamento local, mas as características baseadas na nuvem estarão off-line.

Verificar o roteamento de rede de uma característica

A localidade de uma característica também está disponível nas APIs Home. O dataSourceLocality indica se a característica é roteada remotamente (pela nuvem), localmente (por um hub local) ou ponto a ponto (diretamente de dispositivo para dispositivo, sem hub).

O valor de localidade desconhecido UNSPECIFIED é possível, por exemplo, enquanto um app está sendo inicializado e ainda não atingiu um hub ou servidor para conectividade de dispositivo. Esses dispositivos não podem ser acessados e vão falhar nas solicitações de interação de comandos ou eventos. Cabe ao cliente determinar como lidar com esses dispositivos.

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

Verificar o roteamento de rede de um dispositivo

Assim como a conectividade, a localidade é verificada no nível do tipo de dispositivo. O estado retornado é uma combinação da localidade de todas as características desse dispositivo.

val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality

Um estado de MIXED pode ser observado em um cenário semelhante ao de conectividade PARTIALLY_ONLINE: algumas características são baseadas na nuvem, enquanto outras são locais.

Mudar o nome de um dispositivo

Chame o setName() método para mudar o nome de um dispositivo:

mixerDevice.setName("Grendel")

Os nomes serão truncados se excederem o limite de 60 pontos de código Unicode (caracteres), e nenhum erro será gerado. Os desenvolvedores são responsáveis por processar nomes longos e, por exemplo, podem decidir se querem informar aos usuários que os nomes serão truncados.