As APIs de dispositivo podem ser acessadas pelas APIs do Google Home para iOS. Importe os seguintes pacotes para o app:
import GoogleHomeSDK
import GoogleHomeTypes
Para mais informações, consulte Modelo de dados no iOS.
Tratamento de erros
Alguns métodos nas APIs do Google Home geram uma
HomeError. Por isso, recomendamos que você use um bloco do-catch para capturar
HomeError nessas chamadas.
Ao processar HomeError, verifique os campos code e message
para saber o que deu errado.
Qualquer erro não processado vai causar uma falha no 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
Com uma referência ao objeto Home, invocar
devices() para receber um
Query de dispositivos
acessíveis.
Chame o método
batched()
do Query, que emite um Set que reflete o estado atual da casa com cada
mudança de metadados do dispositivo. Ou chame
Query.list() para ver um
snapshot dos dispositivos disponíveis. Esse é um método de conveniência que se inscreve no
stream batched() e retorna o primeiro valor emitido.
Query.stream()
produz um stream que emite novos valores em mudanças de metadados do dispositivo, como
nome, ambiente ou estrutura. Internamente, isso usa batched() e emite apenas
as propriedades modificadas.
// Get a list of all devices accessible to the user let homeDevices = try await self.home.devices().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 iOS para mais
informações.
Acessar os tipos do dispositivo
Para conferir os tipos de dispositivo associados a um dispositivo, leia a
propriedade types
dele, que retorna um
DeviceTypeController.
Chame DeviceTypeController.subscribe(_:) para se inscrever em atualizações de um
tipo de dispositivo específico:
let devices = try await self.home.devices().list() if let device = devices.first(where: { $0.id == myDeviceId }) { var receivedUpdate1 = false var receivedUpdate2 = false device.types.subscribe(OnOffLightDeviceType.self) .assertNoFailure() .sink { device in if !receivedUpdate1 { receivedUpdate1 = true Task { try await device.matterTraits.onOffTrait?.on() } return } if !receivedUpdate2 { receivedUpdate2 = true return } fatalError("Received unexpected update") } }
Se o dispositivo não for compatível com o tipo especificado, ele vai retornar um Empty
Publisher que é concluído imediatamente.
Se o dispositivo for compatível com um tipo específico, você poderá receber um identificador para esse
tipo chamando get():
if let device = devices.first(where: { $0.id == myDeviceId }) { let _ = await device.types.get(OnOffLightDeviceType.self) }
Se o dispositivo não for compatível com o tipo especificado, ele vai retornar nil.
Chame
DeviceTypeController.subscribeAll()
para receber um Publisher de
DeviceTypeCollection.
Essa classe permite verificar se o dispositivo tem um tipo específico:
if let device = devices.first(where: { $0.id == myDeviceId }) { device.types.subscribeAll() .assertNoFailure() .sink { types in let lightDeviceType = types[OnOffLightDeviceType.self] let fanDeviceType = types[FanDeviceType.self] } }
Receber um atributo de tipo de dispositivo
Os tipos de dispositivo são o ponto de entrada para ler atributos, já que eles decompõem 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 On/Off e dois atributos Level Control.
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, faça referência a um atributo usando uma das duas coleções de atributos em cada tipo de dispositivo.
Para características padrão, ou seja, aquelas que são análogas aos clusters padrão do Matter, use matterTraits. Por exemplo,
para receber um atributo específico para o tipo de dispositivo de luz regulável:
if let dimmableLightDeviceType = await device.types.get(DimmableLightDeviceType.self) { // Accessing standard trait on the type. let levelControlTrait = dimmableLightDeviceType.matterTraits.levelControlTrait.self }
Para atributos do Google, use googleTraits:
if let doorbellDeviceType = await device.types.get(GoogleDoorbellDeviceType.self) { // Accessing Google trait on the type. let doorbellPressTrait = doorbellDeviceType.traits[Google.DoorbellPressTrait.self] }
Para acessar um atributo específico do fabricante, faça referência a ele usando a propriedade traits, mas coloque o nome do pacote do fabricante antes:
let deviceType = await device1?.types.get(OnOffLightDeviceType.self) // Accessing custom trait on the type. if let spinnerTrait = deviceType?.traits[ExampleOrganization.SpinnerTrait.self] { let rpmVal = spinnerTrait.attributes.rpm }
Ler o estado de um dispositivo
Confira este exemplo de verificação do atributo OnOff do atributo
On/Off do dispositivo:
let lightDevices = devices.filter { $0.types.contains(OnOffLightDeviceType.self) } let light1 = lightDevices.first let lightDeviceTypeOptional = await light1?.types.get(OnOffLightDeviceType.self) if let onOffTrait = lightDeviceTypeOptional?.matterTraits.onOffTrait { let onOffVal = onOffTrait.attributes.onOff }
Receber uma lista de dispositivos com um atributo específico
Para receber uma lista de dispositivos que têm um atributo específico, é necessário iterar sobre os dispositivos, os tipos de dispositivo de cada um e os atributos de cada tipo. Por exemplo, para receber uma lista de dispositivos na casa que têm o atributo On/Off:
// Get all light devices that support levelControl var levelControlDevices: [HomeDevice] = [] let allDevices = try await home.devices().list() for device in allDevices { if let deviceType = await device.types.get(OnOffLightDeviceType.self) { if deviceType.traits.contains(Matter.LevelControlTrait.self) { levelControlDevices.append(device) } } }
Consulte o índice de atributos no iOS para ver 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) let lightDevices = try await self.home.devices().list().compactMap { $0.types.contains(DimmableLightDeviceType.self) || $0.types.contains(OnOffLightDeviceType.self) || $0.types.contains(ColorTemperatureLightDeviceType.self) || $0.types.contains(ExtendedColorLightDeviceType.self) }
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 dispositivo precisam ser incluídos.
Consulte os tipos de dispositivo compatíveis com o iOS para ver uma lista completa de tipos de dispositivos e os atributos disponíveis nas APIs Home.
Encontrar o nome do fornecedor, o ID do fornecedor ou o ID do produto de um dispositivo
O atributo BasicInformationTrait
inclui informações como ID do fornecedor, ID do produto, nome do produto e
número de série de um dispositivo:
guard let vendorName = basicInfoTrait.attributes.vendorName else { fatalError("Failed to get vendorName") } guard let vendorID = basicInfoTrait.attributes.vendorID else { fatalError("Failed to get vendorID") } guard let productID = basicInfoTrait.attributes.productID else { fatalError("Failed to get 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 se um tipo de dispositivo é o tipo principal do dispositivo.
if let deviceType = await device?.types.get(HumiditySensorDeviceType.self) { if deviceType.metadata.isPrimaryType { print("Humidity Sensor is the primary type on this device.") } else { print("Humidity Sensor isn't the primary type on this device.") } }
Verificar se um atributo está on-line
Leia a propriedade connectivityState para verificar a conectividade de um atributo:
let levelControlConnectivity = levelControlTrait.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.
let lightConnectivity = dimmableLightDeviceType.metadata.sourceConnectivity .connectivityState
Um estado de partiallyOnline pode ser observado no caso de tipos de dispositivos mistos
quando não há conectividade com a Internet. Os atributos padrão do Matter
ainda podem estar on-line devido ao roteamento local, mas os atributos baseados 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
GeneralDiagnosticsTrait.
Os endereços são retornados como objetos Data, que podem ser formatados como strings IPv4 ou IPv6 padrão usando o framework Network:
func getIpAddresses(trait: Matter.GeneralDiagnosticsTrait) -> [String] {
let interfaces = trait.attributes.networkInterfaces ?? []
var ipAddresses: [String] = []
for interface in interfaces {
for data in interface.iPv4Addresses {
if let ipv4 = IPv4Address(data) {
ipAddresses.append(String(describing: ipv4))
}
}
for data in interface.iPv6Addresses {
if let ipv6 = IPv6Address(data) {
ipAddresses.append(String(describing: ipv6))
}
}
}
return ipAddresses
}
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
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 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.
let levelControlLocality = levelControlTrait.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.
let lightLocality = dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality
Um estado de mixed pode ser observado em um cenário semelhante
ao da conectividade partiallyOnline: algumas características são baseadas na nuvem,
enquanto outras são locais.
Mudar o nome de um dispositivo
Chame o método
setName(_:)
para mudar o nome de um dispositivo:
let updatedDevice = try await theDevice.setName("new device name")
Ao mudar o nome de um dispositivo, o struct HomeDevice original permanece o mesmo, e a mudança é refletida no objeto HomeDevice atualizado retornado.
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 inspecionar a quais
grupos um dispositivo pertence, verifique o
GroupMembershipTrait
no dispositivo:
if let trait = await device.traits.get(Google.GroupMembershipTrait.self) {
for groupId in trait.attributes.groupObjectIdsArray {
print("Device belongs to group: \(groupId)")
}
}
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.