Se puede acceder a las APIs de Structure a través de las APIs de Home para iOS.
Para trabajar con las APIs de Structure, primero importa el paquete GoogleHomeSDK a
tu app:
import GoogleHomeSDK
Manejo de errores
Algunos métodos de las APIs de Home arrojan una
HomeError, por lo que te recomendamos que uses un bloque do-catch para detectar
HomeError en esas llamadas.
Cuando manejes HomeError, verifica sus campos code y message para saber qué salió mal.
Cualquier error no controlado hará que tu app falle.
Para obtener más información, consulta Manejo de errores.
API de Structure
Home representa el Home Graph y es el punto de entrada a la API de Structure.
Proporciona referencias a estructuras, habitaciones y dispositivos.
Structure representa una estructura en tu Home Graph. Proporciona acceso a
los metadatos de la estructura, como id y name.
Usa structures() para
obtener todas las estructuras de tu cuenta. Las estructuras se devuelven en forma de
Query, que ofrece una variedad
de formas de consumir sus datos:
| API | Descripción |
|---|---|
stream() |
Devuelve un Publisher que emite cada objeto de forma individual a medida que se producen los cambios. |
batched() |
Devuelve un Publisher que emite el resultado actual como un Set de objetos. Cada Set emitido representa el estado actual del gráfico de objetos. |
list() |
Devuelve el resultado actual como un Set de objetos. |
Es posible que la llamada a structures().list() no devuelva de inmediato un conjunto válido de estructuras. Si tu app es reactiva y llama a stream() para suscribirse a todos los cambios de estructura para controlar la IU, se debería devolver una lista válida de estructuras. Existen otras situaciones en las que se podría devolver 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.
@Published public private(set) var structures: [Structure] = []
private var structuresCancellable: AnyCancellable?
self.structuresCancellable = home
.structures()
.batched()
.receive(on: DispatchQueue.main)
.map { Array($0) }
.catch {
// Failed to load structures
return Just([Structure]())
}
.assign(to: \.structures, on: self)
Llamadas de Sample Structure
Obtener un conjunto de estructuras
Si llamas a list() en un Query<Structure>, se devuelve el Set de elementos más reciente:
// Get a stream of all structures accessible to the user let allStructuresChanges = self.home.structures() let allStructures = try? await allStructuresChanges.list()
Cuando diseñes una app reactiva, te recomendamos que uses llamadas a batched() y stream() en lugar de list(), ya que estas producen datos automáticamente cuando cambia el gráfico de la casa.
Obtener propiedades de la estructura
Con la lista de estructuras en mano, puedes acceder a sus propiedades:
// Get a stream of changes taking place on a structure. let structureChanges = try await home.structures().list().filter { $0.id == structureID } // Get a snapshot of the structure. let structure = structureChanges.first! // Get structure properties print("id \(structure.id) ") print("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:
do { structure1 = try await home.structures().list().first(where: { $0.name == "Main House" }) } catch let _ as HomeError { // Code for handling the exception }
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! var structure2: Structure! do { structure1 = try await home.structures().list().first(where: { $0.name == "Main House" }) } catch let _ as HomeError { // Code for handling the exception } do { structure2 = try await home.structures().list().first(where: { $0.name == "Guest Cottage" }) } catch let _ as HomeError { // Code for handling the exception }
Habitaciones
Una habitación contiene un grupo de dispositivos. Una habitación siempre forma parte de una estructura, y una estructura puede tener varias habitaciones. Quitar una habitación de una estructura no quita los dispositivos de esa habitación de la estructura. Sin embargo, si se borra la sala, los dispositivos que se encuentran en ella dejarán de estar asignados.
Usa Home.rooms() para
recuperar todas las habitaciones de la cuenta y, luego, usa roomID = device.roomID para
mostrar los dispositivos correspondientes en cada habitación.
self.home.rooms().batched()
.combineLatest(self.home.devices().batched())
.receive(on: DispatchQueue.main)
.catch { error in
// Failed to load rooms and devices
return Just((Set<Room>(), Set<HomeDevice>()))
}
.map { rooms, devices in
var devicesByRoom = [Room: [HomeDevice]]()
for room in rooms where room.structureID == currentStructureID {
devicesByRoom[room] = devices.filter { $0.roomID == room.id }
}
return devicesByRoom
}.assign(to: &self.$devicesByRoom)
Llamadas de muestra de Room
Obtén una lista de salas
Con la clase Home, puedes obtener una lista de salas y acceder a sus propiedades:
let allRoomsChanges = self.home.rooms() let allRooms = try await allRoomsChanges.list() let room = allRooms.first! XCTAssertTrue(allRooms.contains(room)) print("id \(room.id) ") print("name \(room.name) ")
Crear una sala
Para crear una sala nueva en un Structure, sigue estos pasos:
let testName = "Test Room Name" var newRoom: Room! do { newRoom = try await structure.createRoom(name: testName) XCTAssertNotNil(newRoom) } catch let _ as HomeError { // Code for handling the exception }
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 su ID:
let roomToDelete = allRooms.first(where: { $0.id == room.id }) if let roomToDelete1 = roomToDelete { do { try await structure.deleteRoom(roomToDelete1) } catch let _ as HomeError { // Code for handling the exception } }
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
Structure también te permite mover un dispositivo a otra habitación:
do { try await structure.move(device: light, to: room) } catch let _ as HomeError { // Code for handling the exception }
Cómo cambiar el nombre de una habitación
Llama al método
setName(_:)
para cambiar el nombre de una sala:
let updatedRoom = try await theRoom.setName("new room name")
Cuando se cambia el nombre de una sala, el struct Room original sigue siendo el mismo y
el cambio se refleja en el objeto Room actualizado que se devuelve.
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.
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 interactuar
con los grupos de dispositivos, incluye los tipos y las características de dispositivos pertinentes cuando
configures
ReferencedAutomationTypes
en Home.configure, junto con las características
GroupTrait,
GroupManagementTrait
y
GroupMembershipTrait.
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 consultar todos los grupos de dispositivos de la casa, haz lo siguiente:
let groups = try await home.entities(DeviceGroup.self).list()
for group in groups {
let groupTrait = await group.traits.get(Google.GroupTrait.self)
let name = groupTrait?.attributes.name ?? "Device Group"
print("Found group: \(name) with ID: \(group.id)")
}
Interactúa con los dispositivos de los miembros del grupo
La iteración en los dispositivos miembros de un grupo te brinda un control detallado sobre los miembros individuales, te permite agrupar comandos en una sola solicitud y agregar o escribir atributos en todos los miembros.
Primero, filtra los dispositivos de la casa verificando el GroupMembershipTrait de cada dispositivo para el ID del grupo de destino:
let allDevices = try await home.devices().list()
var members: [HomeDevice] = []
for device in allDevices {
if let membership = await device.traits.get(
Google.GroupMembershipTrait.self
),
membership.attributes.groupObjectIdsArray.contains(group.id) {
members.append(device)
}
}
Para enviar una sola solicitud por lotes con comandos para un rasgo en todos los miembros compatibles de un grupo, haz lo siguiente:
var onOffTraits: [Matter.OnOffTrait] = []
for device in members {
if let light = await device.types.get(OnOffLightDeviceType.self),
let onOff = light.matterTraits.onOffTrait {
onOffTraits.append(onOff)
}
}
let traitsToUse = onOffTraits
let responses = try await home.sendBatchedCommands { batcher in
return try traitsToUse.map { batcher.add(try $0.onBatchable()) }
}
for response in responses {
try response.getOrThrow()
}
También puedes actualizar un atributo en todos los dispositivos miembros que coincidan en un grupo
(por ejemplo, establecer onTransitionTime en 1 en todos los
miembros de DimmableLightDeviceType) de forma simultánea y esperar a que se complete dentro de un
plazo:
try await withThrowingTaskGroup(of: Void.self) { taskGroup in
taskGroup.addTask {
try await Task.sleep(for: .seconds(5))
throw CancellationError()
}
for device in members {
taskGroup.addTask {
guard let light = await device.types.get(DimmableLightDeviceType.self),
let levelControl = light.matterTraits.levelControlTrait,
levelControl.attributes.$onTransitionTime.isSupported
else { return }
_ = try await levelControl.update {
$0.setOnTransitionTime(1)
}
}
}
for _ in 0..<members.count {
try await taskGroup.next()
}
taskGroup.cancelAll()
}
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:
var maxMiredsValues: [UInt16] = []
for device in members {
if let light = await device.types.get(ColorTemperatureLightDeviceType.self),
let mireds = light.matterTraits.colorControlTrait?.attributes
.colorTempPhysicalMaxMireds {
maxMiredsValues.append(mireds)
}
}
let minMaxMireds = maxMiredsValues.min()
Crea un grupo de dispositivos
Usa
GroupManagementTrait
en la estructura para crear un grupo de dispositivos:
let groupsManagementTrait =
try await structure.traits(Google.GroupManagementTrait)
let _ = try await groupsManagementTrait.createUserDefinedGroup(
withName: "Kitchen Lights",
withDevices: [light1, light2]
)
Administra la pertenencia a grupos
Para agregar miembros a un grupo existente, sigue estos pasos:
let groupManagementTrait =
try await structure.traits(Google.GroupManagementTrait.self)
groupManagementTrait.addGroupMembers(
groupObjectId: group.id,
memberDeviceObjectIds = [light3.id],
)
Para quitar miembros de un grupo, sigue estos pasos:
let groupManagementTrait =
try await structure.traits(Google.GroupManagementTrait.self)
_ = try await groupManagementTrait.removeGroupMembers(
groupObjectId: group.id,
memberDeviceObjectIdsArray: Array(removedIDs)
)
Cómo cambiar el nombre de un grupo de dispositivos
Para cambiar el nombre de un grupo de dispositivos, actualiza el campo name de GroupTrait:
let groupTrait = group.traits.get(Google.GroupTrait.self)
_ = try await groupTrait.update { $0.name = "Movie Corner" }
Borra un grupo de dispositivos
Para borrar un grupo de dispositivos de una estructura, haz lo siguiente:
let groupManagementTrait =
try await structure.traits.get(Google.GroupManagementTrait.self)
_ = try await groupManagementTrait.deleteGroup(groupObjectId: group.id)