Se puede acceder a las APIs de Structure a través de las APIs de Home para Android. Importa estos paquetes a tu app:
import com.google.home.Home
import com.google.home.Id
import com.google.home.Structure
Manejo de errores
Cualquier método de las APIs de Home puede arrojar una
HomeException, por lo que te recomendamos que uses un bloque try-catch para detectar HomeException en todas las llamadas.
Cuando controles HomeException, verifica sus campos
error.code y
error.message para saber qué ocurrió. También puede haber códigos de error secundarios, por lo que debes llamar al método
getSubErrorCodes() y verificar el resultado.
Cualquier excepción no controlada hará que tu app falle.
Para obtener más información, consulta Manejo de errores.
Llamadas de muestra
Obtén una lista de estructuras
Una vez inicializada, una llamada a structures() devuelve un flujo de estructuras a las que puedes acceder:
// 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()
La API de structures() es un flujo que podría no devolver de inmediato una lista válida de estructuras. Si tu app es reactiva y se suscribe a ese flujo para controlar la IU, con el tiempo, se debería mostrar una lista válida de estructuras.
Existen otras situaciones en las que se podría mostrar una lista de estructuras vacía, por ejemplo, si el teléfono del usuario pierde la conectividad o si el usuario revocó los permisos de tu app. Asegúrate de controlar estos casos en tu app.
Como alternativa, si se requiere programación imperativa en lugar de programación reactiva, se puede usar un operador de flujo de terminal:
val everyStructure = withTimeout(5000) { home.structures().first { it.isNotEmpty() } }
Esta llamada espera que llegue una lista válida de estructuras a través del flujo y se agota el tiempo de espera si no se recibe la lista dentro de un tiempo de espera designado por la app.
Obtener propiedades de la estructura
Con la lista de estructuras en mano, puedes acceder a sus propiedades:
// 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}")
Busca una estructura por nombre
Si conoces el nombre de una estructura, también puedes acceder a ella con la propiedad
name:
val myHome = home.structures().list().first { it.name == "My home" }
Desde allí, se puede acceder a las propiedades, las habitaciones y los dispositivos de cada estructura.
Trabaja con varias estructuras
Para usar más de una estructura, obtén una referencia independiente para cada una:
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 }
Obtén una lista de salas
Con una estructura en mano, puedes obtener una lista de habitaciones y acceder a sus propiedades:
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}")
Crear una sala
Para crear una sala nueva, sigue estos pasos:
val testName = "Test Room Name" val newRoom: Room = structure.createRoom(testName)
Cómo borrar una habitación
Como alternativa, puedes borrar una sala de la siguiente manera:
val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull() structure.deleteRoom(roomToDelete!!)
También puedes borrar una sala con solo un ID:
val roomToDelete1 = allRooms.filter { it.id == testRoomId }.firstOrNull() structure.deleteRoom(roomToDelete1!!)
Si se borra una habitación con dispositivos, estos seguirán estando en la estructura, pero ya no estarán asignados a una habitación.
Cómo mover dispositivos a otra habitación
Una vez que tengas una estructura, podrás mover los dispositivos a otra habitación dentro de ella:
val room2 = structure.rooms().get(Id("room_id_other_structure")) val device1 = structure.devices().get(Id("device_id1")) structure.moveDevicesToRoom(room2!!, listOf(device1!!))
Si solo tienes los IDs de dispositivo y de habitación, también puedes mover los dispositivos de la siguiente manera:
structure.moveDevicesToRoom(Id("room_id_other_structure"), listOf(Id("device_id1")))
Cómo cambiar el nombre de una habitación
Llama al método setName()
para cambiar el nombre de una sala:
livingRoom.setName("Living Room")
Los nombres se truncarán si superan el límite de 60 puntos de código Unicode (caracteres) y no se arrojarán errores. Los desarrolladores son responsables de controlar los nombres largos y, por ejemplo, pueden decidir si quieren informar a los usuarios que se truncarán los nombres.
Cómo ver los tipos de dispositivos para los que un usuario otorgó permisos
En el ecosistema de Google Home, para la mayoría de los tipos de dispositivos, los usuarios pueden otorgar permisos para todos los dispositivos de ese tipo a la vez. En el caso de los tipos de dispositivos sensibles o restringidos, como cerraduras, cámaras o timbres, los usuarios deben otorgarles permiso de forma individual.
Para determinar si un usuario otorgó permiso para acceder a un tipo de dispositivo sensible o restringido, usa la función consentedDeviceTypes() a nivel de la estructura:
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
Un grupo de dispositivos representa una colección de dispositivos definida por el usuario dentro de una sola estructura. La membresía del grupo se conserva en los servicios de Google y es visible para otros miembros de la estructura y otras apps con acceso a la estructura.
Al igual que las habitaciones físicas, los grupos de dispositivos pertenecen a una sola estructura. Sin embargo, a diferencia de las habitaciones, los grupos de dispositivos son agrupaciones lógicas. Un dispositivo puede pertenecer a varios grupos de dispositivos de forma simultánea. Los grupos de dispositivos pueden contener hasta 100 dispositivos.
Los grupos de dispositivos se representan con la entidadDeviceGroup, que es distinta de HomeDevice. Para
consultar grupos de dispositivos y, también, interactuar con ellos, incluye DeviceGroup en la
lista entityTypes cuando inicialices tu
FactoryRegistry, junto
con los atributos Group,
GroupManagement
y
GroupMembership.
Puedes interactuar con los dispositivos de un grupo iterando directamente
en sus dispositivos miembros (consulta
Cómo interactuar con los dispositivos miembros de un grupo) o segmentando
una parte del tipo de dispositivo en el DeviceGroup (consulta
Cómo controlar un grupo de dispositivos).
Obtén una lista de grupos de dispositivos
Para observar todos los grupos de dispositivos de una estructura, llama a home.entities(DeviceGroup) y filtra por el ID de la estructura:
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}")
}
}
Interactúa con los dispositivos de los miembros del grupo
La iteración en los dispositivos miembros de un grupo con group.devices() te brinda
un control detallado sobre los miembros individuales, te permite agrupar comandos en una
sola solicitud y te permite agregar o escribir atributos en todos los miembros.
Por ejemplo, para enviar una sola solicitud por lotes con comandos para un rasgo en todos los miembros compatibles de un grupo, haz lo siguiente:
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()
}
También puedes actualizar un atributo en todos los dispositivos miembros que coincidan en un grupo
(por ejemplo, establecer onTransitionTime en 1u en todos los miembros
DimmableLightDevice) y esperar a que se complete dentro de un plazo:
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 un atributo entre los miembros de un grupo, como encontrar el
colorTempPhysicalMaxMireds mínimo en todas las luces de temperatura de color del
grupo, haz lo siguiente:
val members = group.devices(enableMultipartDevices = true).first()
val minMaxMireds: UShort? = members.mapNotNull { device ->
val light = device.partOrNull(ColorTemperatureLightDevice).first()
light?.standardTraits?.colorControl?.colorTempPhysicalMaxMireds
}.minOrNull()
Crea un grupo de dispositivos
Usa
GroupManagement
en la estructura para crear un grupo de dispositivos:
val groupManagement = structure.trait(GroupManagementTrait)
val response = groupManagement?.createUserDefinedGroup(
name = "Living room lights",
memberDeviceObjectIds = listOf(light1.id.id, light2.id.id)
)
Administra la pertenencia a grupos
Para agregar miembros a un grupo existente, sigue estos pasos:
structure.trait(GroupManagementTrait)?.addGroupMembers(
groupObjectId = group.id.id,
memberDeviceObjectIds = listOf(light3.id.id)
)
Para quitar miembros de un grupo, sigue estos pasos:
structure.trait(GroupManagementTrait)?.removeGroupMembers(
groupObjectId = group.id.id,
memberDeviceObjectIds = listOf(light1.id.id)
)
Cómo cambiar el nombre de un grupo de dispositivos
Para cambiar el nombre de un grupo de dispositivos, actualiza el atributo de nombre en el GroupTrait del grupo:
group.trait(GroupTrait)?.update {
name = "Movie corner"
}
Borra un grupo de dispositivos
Para borrar un grupo de dispositivos de una estructura, haz lo siguiente:
structure.trait(GroupManagementTrait)?.deleteGroup(
groupObjectId = group.id.id
)
Automatizaciones
El punto de entrada a la API de Automation es a través de una estructura. Para obtener más información sobre las automatizaciones en las APIs de Home, consulta la descripción general de la API de Automation en Android.