O tipo de dispositivo campainha é implementado usando duas características:
PushAvStreamTransport,
que processa o transporte de streams de áudio e vídeo usando protocolos baseados em push, e
WebRtcLiveView,
que oferece a capacidade de controlar transmissões ao vivo e o recurso TalkBack.
Sempre verifique se um dispositivo é compatível com atributos e comandos antes de usar qualquer recurso ou tentar atualizar atributos. Consulte Controlar dispositivos no Android para mais informações.
| Tipo de dispositivo das APIs do Google Home | Características | App de exemplo em Kotlin | Caso de uso |
|---|---|---|---|
|
Campainha
Um dispositivo acionado por um botão do lado de fora de uma porta que emite um sinal audível e/ou visual, usado para chamar a atenção de uma pessoa que está do outro lado da porta. As campainhas podem ter transmissões ao vivo acessíveis, comunicação bidirecional ou eventos de detecção. |
Características obrigatórias google PushAvStreamTransport google WebRtcLiveView |
Campainha |
Receber informações básicas sobre um dispositivo
O traço BasicInformation
inclui informações como nome do fornecedor, ID do fornecedor, ID do produto,
nome do produto (inclui informações do modelo), versão do software
e o número de série de um 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}") }
Verificar a conectividade de um dispositivo
A conectividade de um dispositivo é verificada no nível do tipo de dispositivo porque alguns dispositivos são compatíveis com vários tipos. O estado retornado é uma combinação dos estados de conectividade de todas as características do dispositivo.
val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState
Um estado de PARTIALLY_ONLINE pode ser observado no caso de tipos de dispositivos mistos quando não há conectividade com a Internet.
Os Matter traços padrão ainda podem estar on-line devido ao roteamento local, mas os traços baseados na nuvem vão ficar off-line.
Iniciar uma transmissão ao vivo
Para iniciar uma transmissão ao vivo, envie a string do Session Description Protocol (SDP)
para o método
startLiveView()
do traço
WebRtcLiveView, que retorna um
WebRtcLiveViewTrait.StartLiveViewCommand.Response
com três valores:
- O SDP da sessão.
- A duração da sessão em segundos.
- O ID da sessão, que pode ser usado para estender ou encerrar a sessão.
suspend fun getWebRtcLiveViewTrait(cameraDevice: HomeDevice) { return cameraDevice.type(GoogleDoorbellDevice).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)
Estender uma transmissão ao vivo
As transmissões ao vivo têm uma duração predefinida após a qual expiram. Para aumentar a duração de um stream ativo, envie uma solicitação de extensão usando o 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 }
Iniciar e interromper o TalkBack
Para iniciar o talkback, chame o método
startTalkback()
da característica
WebRtcLiveView. Para parar, use
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) } }
Ativar e desativar a capacidade de gravação
Para ativar a capacidade de gravação da câmera, transmita
TransportStatusEnum.Active
ao método
PushAvStreamTransport
da característica
setTransportStatus(). Para desativar a capacidade de gravação, transmita-a
TransportStatusEnum.Inactive.
No exemplo a seguir, agrupamos essas chamadas em uma única chamada que usa um
Boolean para ativar ou desativar a capacidade de gravação:
// 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) } }
Ativar ou desativar a capacidade de gravação da câmera é o mesmo que ligar ou desligar o vídeo dela. Quando o vídeo de uma câmera está ativado, ela está gravando (para fins de eventos e clipes relacionados).
Quando a capacidade de gravação está desativada (o vídeo da câmera está desligado):
- A câmera ainda pode aparecer como on-line de acordo com o
connectivityStatedo tipo de dispositivo. - Não é possível acessar a transmissão ao vivo, e a câmera não detecta eventos na nuvem.
Verificar se a capacidade de gravação está ativada
Para determinar se a capacidade de gravação de uma câmera está ativada, verifique se há conexões ativas. O exemplo a seguir define duas funções para fazer isso:
// 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 }
Outra maneira de verificar é usar a função findTransport() com um predicado:
// Fetch the current connections suspend fun queryRecordModeState(trait: PushAvStreamTransport) { return trait.findTransport().let { it.transportConfigurations.any { it.transportStatus == TransportStatusEnum.Active } }
Configurações de bateria
Várias configurações de bateria podem ser controladas pelas APIs Home.
Definir a preferência de uso da bateria
Ao definir o equilíbrio energético, você configura a compensação entre a duração da bateria e o desempenho de um dispositivo. Você pode criar diferentes perfis de bateria, como "Estendido", "Equilibrado" e "Performance", e alternar entre eles.
Esse recurso é implementado atualizando o
atributo
currentEnergyBalance
da característica
EnergyPreference. O atributo aceita um índice inteiro que corresponde a um perfil específico definido na lista energyBalances do dispositivo (por exemplo, 0 para EXTENDED, 1 para BALANCED e 2 para PERFORMANCE).
Um valor null para currentEnergyBalance indica que o dispositivo está usando um
perfil personalizado. Este é um estado somente leitura.
A seguir, mostramos um exemplo de estrutura que o atributo currentEnergyBalance
vai usar, seguido pelo snippet de código real que usa o 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)
Ativar a Economia de bateria automática
Para configurar esse recurso, atualize o atributo
currentLowPowerModeSensitivity
da característica
EnergyPreference. Esse atributo usa um índice para selecionar um nível de sensibilidade, em que 0 geralmente representa Disabled e 1 representa Enabled ou 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) } }
Receber o estado de carregamento da bateria
Para saber o estado de carregamento atual do dispositivo (carregando, totalmente carregado ou não
carregando), use o atributo
batChargeState
da característica
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" }
Receber o nível da bateria
Para saber o nível atual da bateria, use o atributo
batChargeLevel
da característica
PowerSource. O nível é OK, Warning (baixo) ou 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" }
Encontre a fonte de alimentação
Para determinar a fonte de energia que o dispositivo está usando, use os atributos BatPresent e wiredPresent da característica PowerSource.
val trait: PowerSource val isWired = trait.wiredPresent val hasBattery = trait.batPresent
Configurações de áudio
Várias configurações de áudio podem ser controladas pelas APIs Home.
Ativar ou desativar o microfone
Para ativar ou desativar o microfone do dispositivo, atualize o atributo
microphoneMuted
da característica CameraAvStreamManagement usando a função
setMicrophoneMuted do Kotlin:
// Turn the device's microphone on or off suspend fun turnOffMicrophone(disableMicrophone: Boolean, trait: CameraAvStreamManagement) { trait.update { setMicrophoneMuted(disableMicrophone) } }
Ativar ou desativar a gravação de áudio
Para ativar ou desativar a gravação de áudio no dispositivo, atualize o atributo
recordingMicrophoneMuted
da característica CameraAvStreamManagement usando a função
setRecordingMicrophoneMuted do Kotlin integrada:
// Turn audio recording on or off for the device suspend fun turnOffAudioRecording(disableAudioRecording: Boolean, trait: CameraAvStreamManagement) { trait.update { setRecordingMicrophoneMuted(disableAudioRecording) } }
Ajustar o volume do alto-falante
Para ajustar o volume do alto-falante do dispositivo, atualize o atributo
speakerVolumeLevel
da característica CameraAvStreamManagement usando a função
setSpeakerVolumeLevel do Kotlin integrada:
// Adjust the camera speaker volume suspend fun adjustSpeakerVolume(volume: Int, trait: CameraAvStreamManagement) { trait.update { setSpeakerVolumeLevel(volume.toUbyte()) } }
Outras configurações
Várias outras configurações podem ser controladas pelas APIs Home.
Ativar ou desativar a visão noturna
Para ativar ou desativar a visão noturna da câmera, use TriStateAutoEnum
para atualizar o atributo
nightVision
da característica CameraAvStreamManagement usando a função
setNightVision do Kotlin:
// Turn night vision on cameraAvStreamManagement.update { setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.On) } // Turn night vision off CameraAvStreamManagement.update { setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.Off) }
Mudar o brilho do LED de status
Para mudar o brilho do LED de status, use
ThreeLevelAutoEnum
para atualizar o atributo
statusLightBrightness
da característica CameraAvStreamManagement usando a função
setStatusLightBrightness do 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) }
Mudar a janela de visualização da câmera
A janela de visualização da câmera é a mesma do recurso de zoom e corte descrito no artigo de suporte Zoom e modo Enhance no vídeo da câmera Nest.
A janela de visualização é definida em um ViewportStruct que contém quatro valores, usados como coordenadas da janela. As coordenadas são definidas como:
(x1,y1) -- (x2,y1) | | (x1,y2) -- (x2,y2)
A determinação dos valores para ViewportStruct depende da interface do app e da implementação da câmera. Em um nível muito básico, para definir a janela de visualização do vídeo da câmera, atualize o atributo viewport da característica CameraAvStreamManagement com um ViewportStruct, usando a função setViewport integrada do 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(), ) ) }
Ajustar a sensibilidade de ativação do dispositivo
A sensibilidade de ativação do dispositivo é usada para economizar bateria, diminuindo o alcance em que o dispositivo pode detectar atividade e aumentando o tempo para ativar após detectar essa atividade.
Nas APIs Home, isso pode ser definido usando a propriedade motionSensitivity do
triggerOptions no transportOptions do dispositivo. Essas opções são definidas
no traço PushAvStreamTransport de cada dispositivo.
A sensibilidade de ativação só pode ser definida com os seguintes valores:
- 1 = Baixa
- 5 = Médio
- 10 = Alto
Para atualizar, encontre a configuração de transporte para fluxos de gravação ativos usando o comando findTransport e modifique a configuração com o novo valor de sensibilidade usando o 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, ) } }
Ajustar a duração máxima de eventos
A duração máxima de eventos é o tempo que a câmera vai gravar um clipe para um evento. Usando as APIs Home, isso pode ser configurado por dispositivo com os mesmos comprimentos que no GHA, em intervalos de segundos:
- 10 segundos
- 15 segundos
- 30 segundos
- 60 segundos (1 minuto)
- 120 segundos (2 minutos)
- 180 segundos (3 minutos)
Nas APIs Home, isso pode ser definido usando a propriedade motionTimeControl do
triggerOptions no transportOptions do dispositivo. Essas opções são definidas
no traço PushAvStreamTransport de cada dispositivo.
Para atualizar, encontre a configuração de transporte para fluxos de gravação ativos usando o comando findTransport e modifique a configuração com o novo valor de duração do evento usando o 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, ) } }
Configurações da campainha
Várias configurações de toque da campainha podem ser controladas pelas APIs Home.
Mudar o som da campainha
Para mudar o som da campainha, primeiro acesse a lista de sons instalados no dispositivo usando o atributo installedChimeSounds da característica Chime:
// Get a list of chimes and identify the currently selected one private val doorbellChimeTraitFlow: Flow= device.traitFromType(Chime, GoogleDoorbellDevice) val chimeSounds = doorbellChimeTraitFlow.first().installedChimeSounds ?: emptyList()
Em seguida, atualize o atributo
selectedChime
da característica Chime usando a função setSelectedChime Kotlin
integrada:
// Set the chime using the chimeId from the installed list chimeSounds.firstOrNull { it.name == name }?.let { setSelectedChime(it.chimeId) }
Usar uma campainha externa
A campainha pode ser configurada para usar um sino externo, como uma campainha mecânica instalada dentro de casa. Isso precisa ser configurado durante a instalação da campainha para evitar possíveis danos ao sino externo.
Para indicar o tipo de campainha externa instalada, use
ExternalChimeType
para atualizar o atributo
externalChime
do traço Chime usando a função
setExternalChime do Kotlin:
// Indicate the external chime is mechanical chime.update { setExternalChime(ChimeTrait.ExternalChimeType.Mechanical) }
Mudar a duração da campainha externa
A duração, em segundos, que um toque externo toca pode ser configurada pelas APIs Home. Se o sino externo tiver suporte para uma duração de toque, o usuário poderá configurar isso.
O valor definido aqui depende das especificações do toque externo e da duração recomendada.
Para mudar a duração do toque externo, atualize o atributo
externalChimeDurationSeconds
da característica Chime usando a função
setExternalChimeDurationSeconds do Kotlin:
// Change the external chime duration chime.update { setExternalChimeDurationSeconds(newDuration.toUShort()) }
Ativar um tema de toque
Alguns campainhas podem ter toques disponíveis apenas para usuários por um tempo limitado. Por exemplo, toques específicos para feriados. Esses são os temas de toque.
Para saber quais temas de toque estão disponíveis para um usuário, crie um filtro de timebox
e use-o para filtrar os resultados do comando
getAvailableThemes()
do traço
ChimeThemes. Isso retorna uma lista de temas disponíveis, incluindo os nomes deles.
O exemplo a seguir mostra como filtrar a lista.
Um tema é considerado ativo se o horário atual estiver dentro dos horários de início e término (os valores startTimeSeconds e endTimeSeconds, respectivamente). Se um horário de início não for definido, ele será considerado ativo desde o
início. Se um horário de término não for definido, ele vai continuar ativo
indefinidamente. Se os dois estiverem ausentes, o tema vai estar sempre ativo.
// Get themes from the ChimeThemes trait fun List<ChimeThemesTrait.ThemeStruct>.filterTimeboxedThemes(): List<ChimeThemesTrait.ThemeStruct> { val now = timeSource.instant().epochSecond.toULong() return filter { chimeStruct: ChimeThemesTrait.ThemeStruct -> val startTime: ULong = chimeStruct.startTimeSeconds.getOrNull() ?: 0UL val endTime: ULong = chimeStruct.endTimeSeconds.getOrNull() ?: MAX_VALUE startTime <= now && now <= endTime } } val availableThemes = doorbellChimeThemesTraitFlow .first() .getAvailableThemes() .themes .filterTimeboxedThemes()
Depois de ter o nome do tema desejado, como Christmas, selecione-o usando a função setSelectedTimeboxedThemeName() no traço ChimeThemes:
// Select a theme using the ChimeThemes trait val themeToSelect = "Christmas" if (themeToSelect in availableThemeNames) { doorbellChimeThemesTraitFlow.first().setSelectedTimeboxedThemeName(themeToSelect) }