As APIs de estrutura 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.Id
import com.google.home.Structure
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.
Exemplos de chamadas
Receber uma lista de estruturas
Depois de inicializada, uma chamada structures() retorna um fluxo de estruturas
acessíveis para você:
// Get a flow of all structures accessible to the user val allStructuresFlow: HomeObjectsFlow<Structure> = home.structures() // Calling list() on a HomeObjectsFlow returns the first Set of elements. val allStructures: Set<Structure> = allStructuresFlow.list()
A API structures() é um fluxo que pode não retornar imediatamente uma lista válida de estruturas. Se o app for reativo e se inscrever nesse fluxo para
controlar a interface, uma lista válida de estruturas será retornada.
Há outras situações em que uma lista de estruturas vazia pode ser retornada, por
exemplo, se o smartphone do usuário perder a conectividade ou se o usuário
revogar as permissões do app. É importante lidar com esses casos
no app.
Como alternativa, se a programação imperativa for estritamente necessária em vez da programação reativa, um operador de fluxo de terminal poderá ser usado:
val everyStructure = withTimeout(5000) { home.structures().first { it.isNotEmpty() } }
Essa chamada aguarda uma lista válida de estruturas passar pelo fluxo e atinge o tempo limite se a lista não for recebida dentro de um tempo limite designado pelo app.
Ver propriedades da estrutura
Com a lista de estruturas em mãos, você pode acessar as propriedades delas:
// Get a flow on a structure. Flow emits new values on structure metadata changes: name. val structureFlow: Flow<Structure> = home.structures().itemFlow(myStructureId) // Get a snapshot of the structure. val structure: Structure = structureFlow.first() // Get structure properties println("id ${structure.id}") println("name ${structure.name}")
Encontrar uma estrutura pelo nome
Se você souber o nome de uma estrutura, também poderá acessá-la usando a propriedade
name:
val myHome = home.structures().list().first { it.name == "My home" }
A partir daí, as propriedades, os ambientes e os dispositivos de cada estrutura ficam acessíveis.
Trabalhar com várias estruturas
Para usar mais de uma estrutura, receba uma referência separada para cada uma:
var structure1: Structure? = null var structure2: Structure? = null try { structure1 = home.structures().list().firstOrNull { it.name == "Main House" } } catch (e: HomeException) { // Code for handling the exception } try { structure2 = home.structures().list().firstOrNull { it.name == "Guest Cottage" } } catch (e: HomeException) { // Code for handling the exception }
Receber uma lista de salas
Com uma estrutura em mãos, é possível acessar uma lista de ambientes e as propriedades deles:
val allRoomsFlow: HomeObjectsFlow<Room> = structure.rooms() val allRooms: Set<Room> = allRoomsFlow.list() val room: Room = allRooms.first() println("id ${room.id}") println("name ${room.name}")
Criar uma sala
Para criar um novo ambiente:
val testName = "Test Room Name" val newRoom: Room = structure.createRoom(testName)
Excluir um ambiente
Como alternativa, você pode excluir um ambiente:
val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull() structure.deleteRoom(roomToDelete!!)
Também é possível excluir um espaço usando apenas um ID:
val roomToDelete1 = allRooms.filter { it.id == testRoomId }.firstOrNull() structure.deleteRoom(roomToDelete1!!)
Se um ambiente com dispositivos for excluído, os dispositivos ainda estarão na estrutura, mas não serão mais atribuídos a um ambiente.
Mover dispositivos para outro ambiente
Depois de criar uma estrutura, você pode mover dispositivos para um ambiente diferente dentro dela:
val room2 = structure.rooms().get(Id("room_id_other_structure")) val device1 = structure.devices().get(Id("device_id1")) structure.moveDevicesToRoom(room2!!, listOf(device1!!))
Se você tiver apenas os IDs de dispositivo e de ambiente, também poderá mover dispositivos:
structure.moveDevicesToRoom(Id("room_id_other_structure"), listOf(Id("device_id1")))
Mudar o nome de um ambiente
Chame o método setName()
para mudar o nome de um ambiente:
livingRoom.setName("Living Room")
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.
Ver os tipos de dispositivos para os quais um usuário concedeu permissões
No ecossistema do Google Home, para a maioria dos tipos de dispositivo, os usuários podem conceder permissões para todos os dispositivos desse tipo de uma só vez. Para tipos de dispositivos sensíveis ou restritos, como fechaduras, câmeras ou campainhas, os usuários precisam conceder permissão individualmente.
Para determinar se um usuário concedeu permissão para acessar um tipo de dispositivo sensível ou
restrito, use a função consentedDeviceTypes()
no nível da estrutura:
import com.google.home.Structure
import com.google.home.DeviceType
import com.google.home.DeviceTypeFactory
import com.google.home.consentedDeviceTypes // Extension function from the SDK
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
/**
* Example of how an app may monitor which device types have been granted access by a user.
*/
fun monitorDeviceConsent(structure: Structure, myScope: CoroutineScope) {
// Obtain the flow of consented device type factories
val consentedTypesFlow: Flow<Set<DeviceTypeFactory<out DeviceType>>> =
structure.consentedDeviceTypes()
myScope.launch {
consentedTypesFlow.collect { consentedSet ->
// Check if the user has consented to share a specific restricted
// type, such as a Doorbell or Camera.
val hasCameraAccess = consentedSet.any {
it.toString() == "matter.google.type.GoogleDoorbellDevice"
}
if (hasCameraAccess) {
// Enable features that require camera access
} else {
// Inform the user or disable camera-specific features
}
}
}
}
Grupos de dispositivos
Um grupo de dispositivos representa uma coleção de dispositivos definida pelo usuário em uma única estrutura. A participação no grupo é mantida nos Serviços do Google e fica visível para outros membros da estrutura e outros apps com acesso a ela.
Assim como os ambientes físicos, os grupos de dispositivos pertencem a uma única estrutura. No entanto, ao contrário dos ambientes, os grupos de dispositivos são agrupamentos lógicos. Um dispositivo pode pertencer a vários grupos de dispositivos simultaneamente. Os grupos de dispositivos podem conter até 100 dispositivos.
Os grupos de dispositivos são representados pela entidadeDeviceGroup, que é diferente de HomeDevice. Para
consultar e interagir com grupos de dispositivos, inclua DeviceGroup na
lista entityTypes ao inicializar o
FactoryRegistry, junto
com as características
Group,
GroupManagement
e
GroupMembership.
É possível interagir com os dispositivos em um grupo iterando diretamente sobre os
dispositivos membros (consulte
Interagir com dispositivos membros do grupo) ou segmentando
uma parte do tipo de dispositivo no DeviceGroup (consulte
Controlar um grupo de dispositivos).
Receber uma lista de grupos de dispositivos
Para observar todos os grupos de dispositivos em uma estrutura, chame home.entities(DeviceGroup)
e filtre pelo ID da estrutura:
home.entities(DeviceGroup).collect { allGroups ->
val structureGroups = allGroups.filter { it.structureId == structure.id }
for (group in structureGroups) {
val groupName = group.trait(Group)?.Name
println("Found group: $groupName with ID: ${group.id.id}")
}
}
Interagir com dispositivos de membros do grupo
A iteração nos dispositivos de um grupo com group.devices() oferece
controle detalhado sobre os membros individuais, permite agrupar comandos em uma
única solicitação e permite agregar ou gravar atributos entre os membros.
Por exemplo, para enviar uma única solicitação em lote com comandos para um atributo em todos os membros compatíveis de um grupo:
val members = group.devices(enableMultipartDevices = true).first()
val onOffTraits = members.mapNotNull { device ->
device.partOrNull(OnOffLightDevice).first()?.standardTraits?.onOff
}
val responses = home.sendBatchedCommands {
onOffTraits.map { onOff ->
add(onOff.onBatchable())
}
}
for (response in responses) {
response.getOrThrow()
}
Também é possível atualizar um atributo em todos os dispositivos membros correspondentes em um grupo
(por exemplo, definir onTransitionTime como 1u em todos os membros
DimmableLightDevice) e aguardar a conclusão dentro de um prazo:
val members = group.devices(enableMultipartDevices = true).first()
withTimeout(5.seconds) {
members.map { device ->
async {
val light = device.partOrNull(DimmableLightDevice).first()
val levelControl = light?.standardTraits?.levelControl
if (
levelControl?.supports(
LevelControl.Attribute.onTransitionTime
) == true
) {
levelControl.update { setOnTransitionTime(1u) }
}
}
}.awaitAll()
}
Para agregar um atributo entre os membros de um grupo, como encontrar a
colorTempPhysicalMaxMireds mínima em todas as luzes de temperatura da cor no
grupo:
val members = group.devices(enableMultipartDevices = true).first()
val minMaxMireds: UShort? = members.mapNotNull { device ->
val light = device.partOrNull(ColorTemperatureLightDevice).first()
light?.standardTraits?.colorControl?.colorTempPhysicalMaxMireds
}.minOrNull()
Criar um grupo de dispositivos
Use
GroupManagement
na estrutura para criar um grupo de dispositivos:
val groupManagement = structure.trait(GroupManagementTrait)
val response = groupManagement?.createUserDefinedGroup(
name = "Living room lights",
memberDeviceObjectIds = listOf(light1.id.id, light2.id.id)
)
Gerenciar associação a grupos
Para adicionar participantes a um grupo:
structure.trait(GroupManagementTrait)?.addGroupMembers(
groupObjectId = group.id.id,
memberDeviceObjectIds = listOf(light3.id.id)
)
Para remover participantes de um grupo:
structure.trait(GroupManagementTrait)?.removeGroupMembers(
groupObjectId = group.id.id,
memberDeviceObjectIds = listOf(light1.id.id)
)
Mudar o nome de um grupo de dispositivos
Para renomear um grupo de dispositivos, atualize o atributo de nome no GroupTrait do grupo:
group.trait(GroupTrait)?.update {
name = "Movie corner"
}
Excluir um grupo de dispositivos
Para excluir um grupo de dispositivos de uma estrutura:
structure.trait(GroupManagementTrait)?.deleteGroup(
groupObjectId = group.id.id
)
Automações
O ponto de entrada para a API Automation é uma estrutura. Para saber mais sobre as automações nas APIs Home, consulte a visão geral da API Automation no Android.