As APIs de dispositivo podem ser acessadas pelas APIs do Google 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 atributos de dispositivo específicos com as APIs Device, eles precisam ser importados individualmente.
Por exemplo, para usar a característica de Ativar/Desativar Matter e o tipo de dispositivo Unidade de Plug-in de Ativar/Desativar, 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 um
HomeException. Por isso, recomendamos que você use um bloco try-catch para
capturar 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 suberro.
Por isso, chame o método
getSubErrorCodes() e verifique o resultado.
Qualquer exceção não processada vai resultar na falha do app.
Para mais informações, consulte Tratamento de erros.
Consulte Enviar um comando para 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 para você nessa 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()
Nela, é possível acessar os estados de cada dispositivo e enviar comandos para eles.
Com a versão 1.8 das APIs do Google Home, é possível fazer com que a API represente cada dispositivo de várias partes como um único dispositivo, definindo o parâmetro enableMultipartDevices do método devices() como true. Consulte
Dispositivos de várias partes no Android para mais
informações.
Ler o estado de um dispositivo
Confira um exemplo de verificação do atributo OnOff do atributo On/Off do dispositivo. Usando o modelo de dados de atributo das APIs do Google Home, em que esse atributo é
identificado como OnOff, é possível recuperar dados de atributo 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 atributo
A interface TraitStateInvalidation
permite invalidar um estado recuperado por meio de assinaturas
no 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 traços Matter com a qualidade "C"
ou devido a uma implementação de dispositivo que causa o problema de forma inesperada.
Essa API emite uma leitura forçada do estado atual do atributo e retorna o resultado pelos fluxos de atributos atuais.
Acesse o atributo e execute um forceRead nele:
val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()
Acessar uma lista de atributos de tipo de dispositivo
Os tipos de dispositivo precisam ser usados como um ponto de entrada para ler atributos, já que eles decompoem um dispositivo em partes funcionais (como endpoints em Matter).
Eles também consideram colisões de atributos caso um dispositivo tenha dois tipos, ambos com o mesmo atributo. Por exemplo, se um dispositivo for um alto-falante e uma luz regulável, ele terá dois atributos de ativação/desativação e dois de controle de nível.
Para ver a lista de atributos disponíveis para o tipo de dispositivo Luz com regulagem de intensidade:
// 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 atributo pode ocorrer quando um dispositivo tem dois atributos com o
mesmo nome. Por exemplo, onOff pode se referir a uma instância do atributo padrão
OnOff ou a uma instância de um atributo OnOff
definido pelo fabricante. Para eliminar qualquer ambiguidade em relação ao atributo pretendido, uma instância de Trait referenciada por um dispositivo precisa ser precedida por um namespace qualificado. Para características padrão, ou seja, aquelas que são análogas aos clusters padrão do Matter, use standardTraits. Para atributos do Google, use googleTraits:
// Accessing standard traits on the type. val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl
Para acessar um atributo específico do fabricante, faça referência direta a ele:
// Accessing a custom trait on the type. val customTrait = dimmableLightDevice.trait(MyCustomTrait)
Receber uma lista de dispositivos com um atributo específico
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 têm o atributo On/Off:
// Get all devices that support OnOff val onOffDevices: Flow<List<HomeDevice>> = home.devices().map { devices -> devices.filter { it.has(OnOff) } }
Consulte a interface Trait para uma lista completa de atributos disponíveis nas APIs Home.
Receber uma lista de dispositivos com tipos semelhantes
Para ver 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 do Google 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, como mostrado no exemplo anterior. Portanto, 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 nos fluxos filtrados.
Consulte a interface DeviceType
para ver uma lista completa dos tipos de dispositivos disponíveis nas APIs do Google Home.
Encontrar o ID do fornecedor ou do produto de um dispositivo
O atributo BasicInformation
inclui informações como ID do fornecedor, ID do produto, nome do produto e
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 dispositivos Cloud-to-cloud,
para identificar seus
dispositivos Cloud-to-cloud pelo
atributo BasicInformation, inclua estes campos de string na
resposta SYNC:
O ID do fornecedor emitido pelo Connectivity Standards Alliance (Alliance):
"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 preencher esses campos de string, use os IDs de fornecedor e ID do produto do Matter, se tiver. Se você não for membro da
Alliance e não tiver esses IDs, deixe os campos matterOriginalVendorId e matterOriginalProductId em branco
e forneça o matterUniqueId como identificador.
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 do Cloud-to-cloud SYNC.
Metadados de dispositivos e atributos
Os dispositivos e atributos nas APIs do Google Home têm metadados associados a eles, o que pode ajudar a gerenciar a experiência do usuário em um app.
Cada atributo nas APIs do Google Home contém uma propriedade
sourceConnectivity, que tem informações sobre o status on-line e a localidade de um atributo
(roteamento local ou remoto).
Receber o tipo principal de um dispositivo
Alguns dispositivos podem apresentar vários tipos de dispositivos pelas APIs do Google Home. Para garantir que os usuários vejam as opções adequadas em um app (como controle de dispositivos e automações sugeridas) para os dispositivos deles, é útil verificar qual é o tipo principal de um dispositivo.
Primeiro, use type() para descobrir os tipos do dispositivo e, em seguida, determine os tipos principais:
val types = device.types().first() val primaryTypes = types.filter { it.metadata.isPrimaryType }
Verificar se um atributo está on-line
Use o método connectivityState() para verificar a conectividade de um atributo:
val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState
Alguns atributos, normalmente do Google smart home, podem aparecer off-line se o dispositivo não tiver conexão de internet. Isso ocorre porque esses atributos são baseados 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. O estado retornado é uma combinação dos estados de conectividade de todos os atributos 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.
Encontrar o endereço IP do dispositivo
Para encontrar o endereço IP do dispositivo, use o atributo networkInterfaces do
trait
GeneralDiagnostics. Os endereços são retornados como matrizes de bytes, que podem ser formatadas como strings IPv4 ou IPv6 padrão:
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()
Verificar o roteamento de rede de uma característica
A localidade de um atributo também está disponível nas APIs Home. O
dataSourceLocality indica se o atributo é roteado remotamente (pela
nuvem), localmente (por um hub local) ou ponto a ponto (diretamente de um dispositivo
para outro, sem hub).
O valor de localidade desconhecido UNSPECIFIED é possível, por exemplo, enquanto um app
está sendo inicializado e ainda não alcançou um hub ou servidor para conectividade do dispositivo. Esses
dispositivos não estão acessíveis 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 todos os atributos nesse dispositivo.
val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality
Um estado de MIXED pode ser observado em um cenário semelhante
ao da conectividade PARTIALLY_ONLINE: alguns atributos são baseados na nuvem, enquanto
outros são locais.
Mudar o nome de um dispositivo
Chame o método setName()
para mudar o nome de um dispositivo:
mixerDevice.setName("Grendel")
Os nomes serão truncados se ultrapassarem o limite de 60 pontos de código Unicode (caracteres), e nenhum erro será gerado. Os desenvolvedores são responsáveis por lidar com nomes longos e, por exemplo, podem decidir se querem informar aos usuários que os nomes serão truncados.
Verificar a associação de um dispositivo a um grupo
Um dispositivo físico pode pertencer a um ou mais grupos de dispositivos. Para ver a quais
grupos um dispositivo pertence, verifique o
atributo
GroupMembership
no dispositivo:
val groupIds = device.trait(GroupMembershipTrait)?.groupObjectIds.orEmpty()
for (groupId in groupIds) {
println("HomeAPI", "Device belongs to group: $groupId")
}
Por outro lado, é possível observar todos os dispositivos membros que pertencem a um
DeviceGroup chamando o
fluxo devices() em um DeviceGroup:
group.devices(enableMultipartDevices = true).collect { members ->
println("HomeAPI", "Group contains ${members.size} devices")
}
Para inspecionar os tipos de dispositivo compatíveis com um DeviceGroup e enviar comandos para
o grupo como uma única entidade, consulte
Controlar um grupo de dispositivos.