El tipo de dispositivo Cámara se implementa con dos rasgos: PushAvStreamTransport, que controla el transporte de transmisiones de audio y video con protocolos basados en la transmisión, y WebRtcLiveView, que proporciona la capacidad de controlar transmisiones en vivo y la función de intercomunicador.
Siempre verifica la compatibilidad de los atributos y los comandos de un dispositivo antes de usar cualquier función o intentar actualizar los atributos. Consulta Cómo controlar dispositivos enAndroid para obtener más información.
| Tipo de dispositivo de las APIs de Home | Rasgos | App de ejemplo de Kotlin | Caso de uso |
|---|---|---|---|
|
Cámara
Dispositivo que captura imágenes fijas o videos. Las cámaras pueden incluir transmisiones en vivo accesibles, intercomunicador bidireccional o eventos de detección. |
Rasgos obligatorios google PushAvStreamTransport google WebRtcLiveView |
Cámara |
Obtén información básica sobre un dispositivo
El rasgo BasicInformation incluye información como el nombre del proveedor, el ID del proveedor, el ID del producto, el nombre del producto (incluye información del modelo) y la versión del software de un dispositivo:
// Get device basic information. All general information traits are on the RootNodeDevice type. device.type(RootNodeDevice).first().standardTraits.basicInformation?.let { basicInformation -> println("vendorName ${basicInformation.vendorName}") println("vendorId ${basicInformation.vendorId}") println("productId ${basicInformation.productId}") println("productName ${basicInformation.productName}") println("softwareVersion ${basicInformation.softwareVersion}") }
Obtener número de serie
Para obtener el número de serie del dispositivo, usa el comando GetSerialNumber del rasgo ExtendedBasicInformation.
En el ejemplo, se muestra cómo guardar el número de serie en una variable llamada serialNumber:
val basicInfo: ExtendedBasicInformation = device.getTrait(ExtendedBasicInformation) val serialNumber = basicInfo.getSerialNumber().serialNumber
Obtén la fecha y hora más recientes en que el dispositivo se conectó a la nube
Para encontrar la hora más reciente en la que el dispositivo tuvo contacto con la nube, usa el atributo lastContactTimestamp del rasgo ExtendedGeneralDiagnostics:
fun getLastContactTimeStamp(trait: ExtendedGeneralDiagnostics): java.time.Instant { val timestamp = trait.lastContactTimestamp return Instant.ofEpochSecond(timestamp.toLong()) }
Parámetros de configuración del tipo de soporte de la cámara
El rasgo Mount contiene la configuración de la cámara y la información de estado. Puedes leer atributos como el estado de montaje, el tipo de detección y el nombre del tipo de montaje. Además, puedes usar el rasgo Mount para anular la configuración predeterminada del tipo de montaje.
// Get the Mount trait val mountTrait: Mount = device.getTrait(Mount) // Read the current mount state and detection type val mountState = mountTrait.mountState val mountDetectionType = mountTrait.mountDetectionType // Read the current mount type name val mountTypeName = mountTrait.mountTypeName // Update the mount type override mountTrait.update { setMountTypeOverride(MountTrait.MountTypeOverrideEnum.Official) }
Cómo verificar la conectividad de un dispositivo
En realidad, la conectividad de un dispositivo se verifica a nivel del tipo de dispositivo, ya que algunos dispositivos admiten varios tipos. El estado que se devuelve es una combinación de los estados de conectividad de todas las características del dispositivo.
val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState
Se puede observar un estado de PARTIALLY_ONLINE en el caso de tipos de dispositivos mixtos cuando no hay conectividad a Internet.
Es posible que los rasgos Matter estándar sigan en línea debido al enrutamiento local, pero los rasgos basados en la nube estarán sin conexión.
Obtén la dirección IP del dispositivo
Para encontrar la dirección IP del dispositivo, usa el atributo networkInterfaces del rasgo GeneralDiagnostics. Las direcciones se devuelven como arrays de bytes, que puedes formatear en cadenas IPv4 o IPv6 estándar:
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()
Cómo iniciar una transmisión en vivo
Para iniciar una transmisión en vivo, envía la cadena del Protocolo de descripción de sesión (SDP) al método startLiveView() del rasgo WebRtcLiveView, que devuelve un objeto WebRtcLiveViewTrait.StartLiveViewCommand.Response que contiene tres valores:
- Es el SDP de la sesión.
- Es la duración de la sesión en segundos.
- Es el ID de sesión, que se puede usar para extender o finalizar la sesión.
suspend fun getWebRtcLiveViewTrait(cameraDevice: HomeDevice) { return cameraDevice.type(GoogleCameraDevice).trait(WebRtcLiveView).first { it?.metadata?.sourceConnectivity?.connectivityState == ConnectivityState.ONLINE } } // Start the live view suspend fun startCameraStream(trait: WebRtcLiveView, offerSdp: String) { val response = trait.startLiveView(offerSdp) // Response contains three fields (see below) return response } ... // This is used to manage the WebRTC connection val peerConnection: RTCPeerConnection = ... ... val startResponse = startCameraStream(sdp) val answerSdp = startResponse?.answerSdp val sessionDuration = startResponse?.liveSessionDurationSeconds val mediaSessionId = startResponse?.mediaSessionId peerConnection.setRemoteDescription(SessionDescription.Type.ANSWER, answerSdp)
Cómo extender una transmisión en vivo
Las transmisiones en vivo tienen una duración predeterminada después de la cual vencen. Para extender la duración de una transmisión activa, envía una solicitud de extensión con el método WebRtcLiveView.extendLiveView():
// Assuming camera stream has just been started suspend fun scheduleExtension(trait: WebRtcLiveView, mediaSessionId: String, liveSessionDurationSeconds: UShort ) { delay(liveSessionDurationSeconds - BUFFER_SECONDS * 1000) val response = trait.extendLiveView(mediaSessionId) // returns how long the session will be live for return response.liveSessionDurationSeconds }
Cómo iniciar y detener TalkBack
Para iniciar TalkBack, llama al método startTalkback() del rasgo WebRtcLiveView. Para detenerlo, usa stopTalkback().
// Make sure camera stream is on suspend fun setTalkback(isOn: Boolean, trait: WebRtcLiveView, mediaSessionId: String) { if(isOn) { trait.startTalkback(mediaSessionId) } else { trait.stopTalkback(mediaSessionId) } }
Administra la transmisión en vivo
Ajustar la calidad de la transmisión en vivo es útil para optimizar el uso del ancho de banda según el contexto de visualización del cliente (por ejemplo, cambiar a una resolución más baja cuando se muestra un mosaico de vista previa más pequeño, la vista de cuadrícula o el modo de pantalla en pantalla).
El rasgo WebRtcLiveView administra específicamente la resolución de la sesión de transmisión en vivo activa en un cliente en particular. No es lo mismo que configurar un parámetro de configuración de uso de ancho de banda para todo el dispositivo directamente en él, lo que afectaría a todos los usuarios simultáneos y la calidad de las grabaciones de video históricas guardadas en la nube.
En el siguiente ejemplo, se muestra cómo recuperar y actualizar la calidad de la transmisión en vivo de un dispositivo:
Recupera las opciones de calidad admitidas: Obtén las resoluciones de transmisión disponibles que admite el dispositivo. El código consulta el atributo
supportedQualityHintsdel rasgoWebRtcLiveViewen el flujo del tipo de dispositivo y expone las calidades admitidas como unStateFlowque contiene una lista de valoresQualityHint(comoQUALITY_HINT_SD,QUALITY_HINT_HD,QUALITY_HINT_FHD,QUALITY_HINT_QHDoQUALITY_HINT_UHD).Cambia la calidad de la transmisión en vivo: Aplica un
QualityHintseleccionado para cambiar la resolución de la transmisión en vivo activa (por ejemplo, cambiar de definición estándar a alta definición). La funciónchangeQualityresuelve el rasgo de transmisión en vivo del dispositivo y llama achangeLiveViewQualitycon elmediaSessionIdactivo y la configuración deQualityHintdeseada.
// Assuming you have a HomeDevice instance 'device' val availableQualityHints: StateFlow<List> = device.type(GoogleCameraDevice) .trait(WebRtcLiveView) .map { trait -> trait?.supportedQualityHints ?: emptyList() } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList()) // Assuming you have a HomeDevice instance 'device' suspend fun changeQuality(mediaSessionId: String, qualityHint: QualityHint) { // Get the trait from the device val trait = device.type(GoogleCameraDevice).trait(WebRtcLiveView).first() ?: return try { trait.changeLiveViewQuality(mediaSessionId, qualityHint) } catch (e: Exception) { // Handle error } }
Cómo habilitar e inhabilitar la capacidad de grabación
Para habilitar la capacidad de grabación de la cámara, pasa TransportStatusEnum.Active al método setTransportStatus() del rasgo PushAvStreamTransport. Para inhabilitar la capacidad de grabación, pasa TransportStatusEnum.Inactive.
En el siguiente ejemplo, incluimos estas llamadas en una sola llamada que usa un Boolean para activar o desactivar la capacidad de grabación:
// Start or stop recording for all connections. suspend fun setCameraRecording(trait: PushAvStreamTransport, isOn: Boolean) { if(isOn) { trait.setTransportStatus(TransportStatusEnum.Active) } else { trait.setTransportStatus(TransportStatusEnum.Inactive) } }
Habilitar o inhabilitar la capacidad de grabación de la cámara es lo mismo que encender o apagar el video de la cámara. Cuando el video de una cámara está encendido, se está grabando (para fines de eventos y clips relacionados).
Cuando la capacidad de grabación está inhabilitada (el video de la cámara está desactivado):
- La cámara aún puede mostrarse como en línea según el
connectivityStatedel tipo de dispositivo. - No se puede acceder a la transmisión en vivo ni la cámara detecta eventos en la nube.
Verifica si la capacidad de grabación está habilitada
Para determinar si la capacidad de grabación de una cámara está habilitada, verifica si hay conexiones activas. En el siguiente ejemplo, se definen dos funciones para realizar esta acción:
// Get the on/off state suspend fun onOffState(pushAvStreamTransport: PushAvStreamTransport) { return pushAvStreamTransport .currentConnections?.any { it.transportStatus == TransportStatusEnum.Active } ?: false } // Check if the camera's recording capability is enabled fun PushAvStreamTransport.recordModeActive(): Boolean { return currentConnections?.any { it.transportStatus == TransportStatusEnum.Active } ?: false }
Otra forma de verificarlo es usar la función findTransport() con un predicado:
// Fetch the current connections suspend fun queryRecordModeState(trait: PushAvStreamTransport) { return trait.findTransport().let { it.transportConfigurations.any { it.transportStatus == TransportStatusEnum.Active } }
Configuración de la batería
Se pueden controlar varios parámetros de configuración de la batería a través de las APIs de Home.
Cómo establecer la preferencia de uso de la batería
Configurar el balance energético te permite establecer el equilibrio entre la duración de la batería y el rendimiento de un dispositivo. Puedes crear diferentes perfiles de batería, como "Extendido", "Equilibrado" y "Rendimiento", y cambiar entre ellos.
Esta función se implementa actualizando el atributo currentEnergyBalance del arquetipo EnergyPreference. El atributo acepta un índice de número entero que corresponde a un perfil específico definido en la lista energyBalances del dispositivo (por ejemplo, 0 para EXTENDED, 1 para BALANCED y 2 para PERFORMANCE).
Un valor de null para currentEnergyBalance indica que el dispositivo usa un perfil personalizado. Este es un estado de solo lectura.
A continuación, se muestra un ejemplo de una estructura que usará el atributo currentEnergyBalance, seguido del fragmento de código real que usa el atributo.
// Example energyBalances list energy_balances: [ { step: 0, label: "EXTENDED" }, { step: 50, label: "BALANCED" }, { step: 100, label: "PERFORMANCE" } ]
// The index parameter must be within the UByte range (0-255). suspend fun setEnergyBalance(trait: EnergyPreference, index: Int) { trait.update { setCurrentEnergyBalance(index.toUByte()) } } // Setting the battery usage to more recording ie performance setEnergyBalance(energyPreference, 2)
Cómo activar el Ahorro de batería automático
Para configurar esta función, actualiza el atributo currentLowPowerModeSensitivity del rasgo EnergyPreference. Este atributo usa un índice para seleccionar un nivel de sensibilidad, en el que 0 suele representar Disabled y 1 representa Enabled o Automatic.
suspend fun setAutomaticBatterySaver(enable: Boolean, trait: EnergyPreference) { // 0 is Disabled, 1 is Enabled val value = if (enable) 1.toUByte() else 0.toUByte() trait.update { setCurrentLowPowerModeSensitivity(value) } }
Cómo obtener el estado de carga de la batería
Para obtener el estado de carga actual del dispositivo (cargando, completamente cargado o sin cargar), usa el atributo batChargeState del rasgo PowerSource.
// Get the battery charging state val batteryChargeState = powerSource.batChargeState when (batteryChargeState) { PowerSourceTrait.BatChargeStateEnum.IsCharging -> "Charging" PowerSourceTrait.BatChargeStateEnum.IsAtFullCharge -> "Full" PowerSourceTrait.BatChargeStateEnum.IsNotCharging -> "Not Charging" else -> "Unknown" }
Cómo obtener el nivel de batería
Para obtener el nivel de batería actual, usa el atributo batChargeLevel del rasgo PowerSource. El nivel es OK, Warning (bajo) o Critical.
// Get the battery charge level val batteryLevel = powerSourceTrait.batChargeLevel when (batteryLevel) { PowerSourceTrait.BatChargeLevelEnum.OK -> "OK" PowerSourceTrait.BatChargeLevelEnum.Warning -> "Warning" PowerSourceTrait.BatChargeLevelEnum.Critical -> "Critical" else -> "Unknown" }
Obtén la fuente de alimentación
Para determinar la fuente de alimentación que usa el dispositivo, usa los atributos BatPresent y wiredPresent del rasgo PowerSource.
val trait: PowerSource val isWired = trait.wiredPresent val hasBattery = trait.batPresent
Configuración de audio
Se pueden controlar varios parámetros de audio a través de las APIs de Home.
Activar o desactivar el micrófono
Para activar o desactivar el micrófono del dispositivo, actualiza el atributo microphoneMuted del rasgo CameraAvStreamManagement con la función setMicrophoneMuted de Kotlin integrada:
// Turn the device's microphone on or off suspend fun turnOffMicrophone(disableMicrophone: Boolean, trait: CameraAvStreamManagement) { trait.update { setMicrophoneMuted(disableMicrophone) } }
Cómo activar o desactivar la grabación de audio
Para activar o desactivar la grabación de audio en el dispositivo, actualiza el atributo recordingMicrophoneMuted del rasgo CameraAvStreamManagement con la función setRecordingMicrophoneMuted de Kotlin integrada:
// Turn audio recording on or off for the device suspend fun turnOffAudioRecording(disableAudioRecording: Boolean, trait: CameraAvStreamManagement) { trait.update { setRecordingMicrophoneMuted(disableAudioRecording) } }
Cómo ajustar el volumen de la bocina
Para ajustar el volumen del altavoz del dispositivo, actualiza el atributo speakerVolumeLevel del rasgo CameraAvStreamManagement con la función setSpeakerVolumeLevel de Kotlin integrada:
// Adjust the camera speaker volume suspend fun adjustSpeakerVolume(volume: Int, trait: CameraAvStreamManagement) { trait.update { setSpeakerVolumeLevel(volume.toUbyte()) } }
Configuración de zonas de actividad
El rasgo ZoneManagement proporciona una interfaz para administrar regiones de interés (zonas de actividad) personalizadas en dispositivos de cámara y timbre.
Estas zonas se usan para filtrar la detección de eventos (como el movimiento de personas o vehículos) en áreas específicas dentro del campo visual del dispositivo.
El usuario configura las zonas de actividad en una aplicación de socio, lo que le permite dibujar zonas sobre áreas específicas del campo visual de la cámara. Luego, estas zonas definidas por el usuario se traducen en las estructuras que usa este rasgo. Para obtener más información sobre cómo funcionan las zonas de actividad, consulta Cómo configurar y usar las Zonas de actividad.
Las zonas de actividad suelen definirse con coordenadas cartesianas 2D.
El rasgo proporciona TwoDCartesianVertexStruct para los vértices y TwoDCartesianZoneStruct para la definición de la zona (nombre, vértices, color y uso).
Cómo revisar las zonas de actividad
Para mostrar las zonas de actividad, verifica el atributo zones del rasgo ZoneManagement.
// 1. Obtain the trait flow from the device private val zoneManagementFlow: Flow= device.type(CAMERA_TYPE).flatMapLatest { it.trait(ZoneManagement) } // 2. Map the flow to the list of zone structures val activityZones: Flow<List<ZoneManagementTrait.ZoneInformationStruct>> = zoneManagementFlow.map { trait -> trait.zones ?: emptyList() }
Cómo agregar una zona de actividad
Para crear una zona nueva, usa el comando createTwoDCartesianZone. Este comando toma un TwoDCartesianZoneStruct, que define el nombre, los vértices, el color y el uso de la zona.
En el siguiente ejemplo, se muestra cómo crear una zona llamada "Porche delantero" con cuatro vértices, de color salmón (código hexadecimal #F439A0) y que se usa para la detección de movimiento.
import com.google.home.google.ZoneManagement import com.google.home.google.ZoneManagementTrait import com.google.home.matter.serialization.OptionalValue /** * Creates a custom activity zone named "Front Porch" with a salmon color * configured for motion detection. */ suspend fun createFrontPorchZone(zoneManagement: ZoneManagement) { // 1. Define the vertices for the zone (2D Cartesian coordinates) // Values are typically scaled to a maximum defined by the device's twoDCartesianMax attribute. val vertices = listOf( ZoneManagementTrait.TwoDCartesianVertexStruct(x = 260u, y = 422u), ZoneManagementTrait.TwoDCartesianVertexStruct(x = 1049u, y = 0u), ZoneManagementTrait.TwoDCartesianVertexStruct(x = 2048u, y = 0u), ZoneManagementTrait.TwoDCartesianVertexStruct(x = 2048u, y = 950u), ZoneManagementTrait.TwoDCartesianVertexStruct(x = 1630u, y = 1349u), ZoneManagementTrait.TwoDCartesianVertexStruct(x = 880u, y = 2048u), ZoneManagementTrait.TwoDCartesianVertexStruct(x = 0u, y = 2048u), ZoneManagementTrait.TwoDCartesianVertexStruct(x = 638u, y = 1090u) ) // 2. Define the zone structure val newZone = ZoneManagementTrait.TwoDCartesianZoneStruct( name = "Front Porch", vertices = vertices, // Usage defines what the zone filters (for example, Motion, Person, Vehicle) use = listOf(ZoneManagementTrait.ZoneUseEnum.Motion), // Color is typically a hex string (for example, Salmon/Pink) color = OptionalValue.present("#F439A0") ) try { // 3. Execute the command to add the zone to the device zoneManagement.createTwoDCartesianZone(newZone) println("Successfully created activity zone.") } catch (e: Exception) { // Handle potential HomeException or Timeout println("Failed to create activity zone: ${e.message}") } }
Actualiza una zona de actividad
Para actualizar una zona existente, usa el comando updateTwoDCartesianZone. Este comando requiere el zoneId y el TwoDCartesianZoneStruct actualizado.
private suspend fun ZoneManagement.updateZone( zoneId: UShort, zone: ZoneManagementTrait.TwoDCartesianZoneStruct ) { // Execute the command to update the zone this.updateTwoDCartesianZone(zoneId = zoneId, zone = zone) }
Cómo borrar una zona de actividad
Para quitar una zona, usa el comando removeZone con el zoneId específico.
private suspend fun ZoneManagement.deleteZone(zoneId: UShort) { // Execute the command to remove the zone this.removeZone(zoneId = zoneId) }
Activadores de eventos de sonido
El rasgo AvStreamAnalysis proporciona una interfaz para administrar los activadores de detección de eventos en cámaras y timbres. Si bien los activadores basados en la visión (como personas o vehículos) pueden ser específicos de una zona, los activadores relacionados con el sonido suelen ser configuraciones a nivel del dispositivo.
Los siguientes tipos de activadores están disponibles para la detección de sonido con EventTriggerTypeEnum:
| Modo | Valor enumerado | Descripción |
|---|---|---|
| Sonido | Sound |
Detección de sonido general |
| Persona que habla | PersonTalking |
Detecta la voz. |
| Ladrido de perro | DogBark |
Detecta las vocalizaciones caninas. |
| Rotura de vidrio | GlassBreak |
Detecta el sonido de rotura de vidrio. |
| Alarma de humo | SmokeAlarm |
Detecta alarmas de humo, que a menudo se reconocen por el patrón audible T3 (tres sonidos cortos seguidos de una pausa). |
| alarma de monóxido de carbono | CoAlarm |
Detecta alarmas de monóxido de carbono (CO), que suelen reconocerse por el patrón audible T4 (cuatro sonidos breves seguidos de una pausa). |
Cómo verificar el estado de la detección de sonido
Para mostrarle al usuario el estado actual de la detección de sonido, debes verificar qué admite el dispositivo y qué está habilitado por el hardware del dispositivo. Los dos atributos que se deben verificar son los siguientes:
En el desarrollo de Android con flujos de Kotlin, por lo general, observarías el rasgo AvStreamAnalysis del HomeDevice.
// Example structure to store the data class EventTriggerAttribute(val type: EventTriggerTypeEnum, val enabled: Boolean) // 1. Obtain the trait flow from the device private val avStreamAnalysisFlow: Flow<AvStreamAnalysis> = device.traitFromType(AvStreamAnalysis, CAMERA_TYPES.first { device.has(it) }) // 2. Map the flow to a list of sound event attributes val soundEventTriggersState: Flow<List<EventTriggerAttribute>> = avStreamAnalysisFlow.map { trait -> // Get raw lists from the trait attributes val supported = trait.supportedEventTriggers ?: emptyList() val enabled = trait.enabledEventTriggers ?: emptyList() // Define sound-specific triggers to filter for val soundTypes = setOf( EventTriggerTypeEnum.Sound, EventTriggerTypeEnum.PersonTalking, EventTriggerTypeEnum.DogBark, EventTriggerTypeEnum.GlassBreak, EventTriggerTypeEnum.SmokeAlarm, EventTriggerTypeEnum.CoAlarm, ) // Filter and associate status supported .filter { soundTypes.contains(it) } .map { type -> EventTriggerAttribute( type = type, enabled = enabled.contains(type) ) } }
Actualiza el conjunto de activadores habilitados
Para actualizar el conjunto de activadores habilitados, usa el comando SetOrUpdateEventDetectionTriggers, que toma una lista de estructuras EventTriggerEnablement.
private suspend fun AvStreamAnalysis.updateEventTriggers( eventTriggers: List<EventTriggerAttribute> ) { val toUpdate = eventTriggers.map { EventTriggerEnablement( eventTriggerType = it.type, enablementStatus = if (it.enabled) { EnablementStatusEnum.Enabled } else { EnablementStatusEnum.Disabled }, ) } // Execute the command on the device setOrUpdateEventDetectionTriggers(toUpdate) }
Modos de grabación
El rasgo RecordingMode proporciona una interfaz para administrar el comportamiento de grabación de video y de imágenes en dispositivos de cámara y timbre. Permite a los usuarios elegir entre la grabación continua, la grabación basada en eventos o inhabilitar la grabación por completo (solo en Live View).
El objeto RecordingModeEnum define las estrategias de grabación disponibles:
| Modo | Valor enumerado | Descripción |
|---|---|---|
| Inhabilitada | Disabled |
La grabación está completamente inhabilitada. Se usa principalmente en dispositivos heredados. |
| CVR (grabación de video continua) | Cvr |
El video se graba las 24 horas, todos los días. Requiere una suscripción (por ejemplo, Google Home Premium). |
| EBR (grabación basada en eventos) | Ebr |
La grabación se activa por eventos (persona, movimiento). La duración del video depende de la duración del evento y de la suscripción. |
| ETR (grabación activada por eventos) | Etr |
Grabación de vista previa corta (por ejemplo, de 10 segundos) activada por eventos. |
| Live View | LiveView |
La grabación está inhabilitada, pero los usuarios aún pueden acceder a la transmisión en vivo. |
| Imágenes fijas | Images |
Cuando ocurren eventos, se graban instantáneas en lugar de videos. |
Verifica los modos de grabación
Para mostrar la configuración de grabación actual, verifica los atributos del rasgo RecordingMode:
supportedRecordingModes: Todos los modos potencialesavailableRecordingModes: Modos seleccionablesselectedRecordingMode: El modo activo
// 1. Obtain the trait flow from the device private val recordingModeTraitFlow: Flow= device.traitFromType(RecordingMode, CAMERA_TYPES.first { device.has(it) }) // 2. Map the flow to recording mode options data class RecordingModeOptions( val recordingMode: RecordingModeTrait.RecordingModeEnum, val index: Int, val available: Boolean, val readableString: String, ) private val recordingModeOptions: Flow<List > = recordingModeTraitFlow.map { trait -> val supported = trait.supportedRecordingModes?.map { it.recordingMode } ?: emptyList() val available = trait.availableRecordingModes?.map { it.toInt() } ?: emptyList() supported.withIndex().map { (index, mode) -> RecordingModeOptions( recordingMode = mode, index = index, available = available.contains(index), readableString = mode.toReadableString(), ) } }
Cómo cambiar el modo de grabación
Antes de actualizar, asegúrate de que el índice elegido del atributo supportedRecordingModes esté presente en el atributo availableRecordingModes.
Para actualizar el modo seleccionado, usa la función setSelectedRecordingMode y pasa el índice del modo elegido:
private suspend fun RecordingMode.updateRecordingMode(index: Int) { // Execute the command to update the selected mode this.setSelectedRecordingMode(index.toUByte()) }
Otros parámetros de configuración
A través de las APIs de Home, se pueden controlar varios otros parámetros de configuración.
Cómo cambiar la orientación de la imagen
Se puede rotar la orientación de la imagen de la cámara (video). El video solo se puede rotar 180 grados.
Para cambiar la orientación de la imagen de la cámara, actualiza el atributo imageRotation del rasgo CameraAvStreamManagement con la función setImageRotation de Kotlin integrada:
// Change the camera's image orientation val isRotated = false cameraAvStreamManagement.update { setImageRotation(if (isRotated) 180.toUShort() else 0.toUShort()) }
Cómo activar o desactivar la Visión nocturna
Para activar o desactivar la visión nocturna de la cámara, usa TriStateAutoEnum para actualizar el atributo nightVision del rasgo CameraAvStreamManagement con la función setNightVision integrada de Kotlin:
// Turn night vision on cameraAvStreamManagement.update { setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.On) } // Turn night vision off CameraAvStreamManagement.update { setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.Off) }
Cómo cambiar el brillo del LED de estado
Para cambiar el brillo de la luz LED de estado, usa ThreeLevelAutoEnum para actualizar el atributo statusLightBrightness del rasgo CameraAvStreamManagement con la función setStatusLightBrightness de Kotlin integrada:
// Set the LED brightness to high cameraAvStreamManagement.update { setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.High) } // Set the LED brightness to low cameraAvStreamManagement.update { setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.Low) }
Cómo cambiar el viewport de la cámara
El visor de la cámara es el mismo que la función Zoom and Crop que se describe en el artículo de asistencia técnica sobre cómo hacer zoom en el video de la cámara Nest y mejorar la detección.
El viewport se define en un ViewportStruct que contiene cuatro valores, los cuales se usan como las coordenadas del viewport. Las coordenadas se definen de la siguiente manera:
(x1,y1) -- (x2,y1) | | (x1,y2) -- (x2,y2)
La determinación de los valores de ViewportStruct depende de la IU y la implementación de la cámara de una app. En un nivel muy básico, para establecer el viewport del video de la cámara, actualiza el atributo viewport del rasgo CameraAvStreamManagement con un ViewportStruct, usando la función setViewport integrada de Kotlin:
cameraAvStreamManagement .update { setViewport( CameraAvStreamManagementTrait.ViewportStruct( x1 = horizontalRange.rangeStart.roundToInt().toUShort(), x2 = horizontalRange.rangeEnd.roundToInt().toUShort(), y1 = verticalRange.rangeStart.roundToInt().toUShort(), y2 = verticalRange.rangeEnd.roundToInt().toUShort(), ) ) }
Habilita o inhabilita las estadísticas
Cada dispositivo puede habilitar de forma individual el envío de datos de análisis detallados a la nube de Google Home (consulta Cloud Monitoring for Home APIs).
Para habilitar las estadísticas de un dispositivo, establece la propiedad analyticsEnabled de ExtendedGeneralDiagnosticsTrait en true. Cuando configuras analyticsEnabled, otra propiedad, logUploadEnabled, se configura automáticamente como true, lo que permite que los archivos de registro de análisis se suban a la nube de Google Home.
// Enable analytics extendedGeneralDiagnostics.update { setAnalyticsEnabled(true) } // Disable analytics extendedGeneralDiagnostics.update { setAnalyticsEnabled(false) }
Configuraciones de transporte y grabación
En esta sección, se abordan los parámetros de configuración relacionados con la calidad de la transmisión de la cámara y la activación de eventos. Estos parámetros de configuración se administran con el rasgo PushAvStreamTransport.
Leer la configuración de transporte
En esta sección, se muestra cómo recuperar la configuración actual de una cámara o un timbre. Recupera el rasgo PushAvStreamTransport, busca la conexión específica que se usó para la grabación y, luego, extrae los valores actuales de la calidad del ancho de banda, la sensibilidad de activación y la duración máxima del evento.
val trait: PushAvStreamTransport = device.getTrait(PushAvStreamTransport) val connections = trait.findTransport().transportConfigurations // Locate the connection designated for recording val recordingConnection = connections.firstOrNull { it.transportOptions.getOrNull()?.streamUsage == StreamUsageEnum.Recording } val options = recordingConnection?.transportOptions?.getOrNull() // 1. Bandwidth Quality (Video Stream ID) val videoStreamId = options?.videoStreamId?.getOrNull() // 2. Wake-up Sensitivity (Motion Sensitivity) val wakeUpSensitivity = options?.triggerOptions?.motionSensitivity?.getOrNull() // 3. Max Event Length (Motion Trigger Time Control) val maxEventLength = options?.triggerOptions?.motionTimeControl?.getOrNull()?.maxDuration
Actualiza la configuración de transporte
En esta sección, se muestra cómo cambiar la configuración de transporte.
Crea un nuevo TransportOptionsStruct que contiene los valores nuevos y, luego, usa el comando modifyPushTransport para enviar estos parámetros de configuración actualizados al dispositivo y aplicarlos a la conexión de grabación que se encontró en el paso anterior.
Para modificar estos parámetros de configuración, usa el comando modifyPushTransport con un TransportOptionsStruct.
val toUpdate = TransportOptionsStruct( videoStreamId = OptionalValue.present(2u), // e.g., Max Quality triggerOptions = TransportTriggerOptionsStruct( motionSensitivity = OptionalValue.present(5u), // e.g., Medium motionTimeControl = OptionalValue.present( TransportMotionTriggerTimeControlStruct(maxDuration = 30u) ) ) ) if (recordingConnection != null) { trait.modifyPushTransport( connectionId = recordingConnection.connectionId, transportOptions = toUpdate ) }
Cómo determinar la calidad del ancho de banda
La propiedad videoStreamId del objeto TransportOptionsStruct corresponde a una configuración específica de transmisión de video.
Para obtener los flujos de video admitidos, consulta el atributo allocatedVideoStreams, que es una lista de VideoStreamStructs.
del rasgo CameraAvStreamManagement para el dispositivo.
Cómo ajustar la sensibilidad de activación del dispositivo
La propiedad motionSensitivity del objeto TransportTriggerOptionsStruct corresponde a los siguientes valores:
| Etiqueta | Valor (UByte) |
|---|---|
| Bajo | 1u |
| Medio | 5u |
| Alta | 10u |
Cómo ajustar la duración máxima de eventos
La propiedad maxDuration del objeto TransportMotionTriggerTimeControlStruct corresponde a las siguientes duraciones (en segundos):
- 10 min, 15 min, 30 min, 60 min, 120 min, 180 min