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. |
Required Traits 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 (incluida la información del modelo), la versión del software y el número de serie 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}") println("serialNumber ${basicInformation.serialNumber}") }
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ándares sigan en línea debido al enrutamiento local, pero los rasgos basados en la nube estarán sin conexión.
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, emite 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) } }
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 rasgo EnergyPreference. El atributo acepta un índice 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) } }
Obtén 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 configuración 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()) } }
Otros parámetros de configuración
También se pueden controlar otros parámetros de configuración a través de las APIs de Home.
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 de Kotlin integrada:
// 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 de la luz 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.
La ventana gráfica se define en un ViewportStruct que contiene cuatro valores, los cuales se usan como las coordenadas de la ventana gráfica. 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 de Kotlin integrada:
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(), ) ) }
Cómo ajustar la sensibilidad de activación del dispositivo
La sensibilidad de activación del dispositivo se usa para conservar la batería, ya que disminuye el rango en el que el dispositivo puede detectar actividad y aumenta el tiempo de activación después de detectar esa actividad.
En las APIs de Home, esto se puede configurar con la propiedad motionSensitivity del objeto triggerOptions en el objeto transportOptions del dispositivo. Estas opciones se definen dentro del rasgo PushAvStreamTransport para cada dispositivo.
La sensibilidad de activación solo se puede establecer en los siguientes valores:
- 1 = Baja
- 5 = Mediana
- 10 = Alto
El proceso de actualización consiste en encontrar la configuración de transporte para los flujos de grabación activos con el comando findTransport y, luego, modificar la configuración con el nuevo valor de sensibilidad con el comando modifyPushTransport:
// Create a struct with the new wake-up sensitivity val toUpdate = TransportOptionsStruct( triggerOptions = TransportTriggerOptionsStruct( motionSensitivity = OptionalValue.present(wakeUpSensitivity.toUByte()) ) ) // Get the configurations for active connections val connections = pushAvStreamTransport.findTransport().transportConfigurations // Update all recording streams with the new transport options. for (connection in connections) { if (connection.transportOptions.getOrNull()?.streamUsage == StreamUsageEnum.Recording) { trait.modifyPushTransport( connectionId = connection.connectionId, transportOptions = toUpdate, ) } }
Cómo ajustar la duración máxima de eventos
La duración máxima del evento es el período durante el cual la cámara grabará un clip para un evento. A través de las APIs de Home, esto se puede configurar, por dispositivo, con las mismas longitudes que a través de GHA, en intervalos de segundos:
- 10 segundos
- 15 segundos
- 30 segundos
- 60 segundos (1 minuto)
- 120 segundos (2 minutos)
- 180 segundos (3 minutos)
En las APIs de Home, esto se puede configurar con la propiedad motionTimeControl del objeto triggerOptions en el objeto transportOptions del dispositivo. Estas opciones se definen dentro del rasgo PushAvStreamTransport para cada dispositivo.
El proceso de actualización consiste en buscar la configuración de transporte para los flujos de grabación activos con el comando findTransport y, luego, modificar la configuración con el nuevo valor de duración del evento usando el comando modifyPushTransport:
// Create a struct with the new max event length // where maxDuration is the length in seconds val toUpdate = TransportOptionsStruct( triggerOptions = TransportTriggerOptionsStruct( motionTimeControl = OptionalValue.present( TransportMotionTriggerTimeControlStruct(maxDuration = it.toUInt()) ) ) ) // Get the configurations for active connections val connections = pushAvStreamTransport.findTransport().transportConfigurations // Update all recording streams with the new transport options. for (connection in connections) { if (connection.transportOptions.getOrNull()?.streamUsage == StreamUsageEnum.Recording) { trait.modifyPushTransport( connectionId = connection.connectionId, transportOptions = toUpdate, ) } }