Il tipo di dispositivo Campanello è implementato utilizzando due tratti:
PushAvStreamTransport,
che gestisce il trasporto di stream audio e video utilizzando protocolli basati su push e
WebRtcLiveView,
che offre la possibilità di controllare le trasmissioni live e la funzionalità TalkBack.
Prima di utilizzare qualsiasi funzionalità o tentare di aggiornare gli attributi, controlla sempre il supporto di attributi e comandi per un dispositivo. Per ulteriori informazioni, consulta Controllare i dispositivi su Android.
| Tipo di dispositivo delle API Home | Tratti | App di esempio Kotlin | Caso d'uso |
|---|---|---|---|
|
Campanello
Un dispositivo azionato da un pulsante all'esterno di una porta che emette un segnale acustico e/o visivo, utilizzato per richiedere l'attenzione di una persona che si trova da qualche parte dall'altro lato della porta. I campanelli possono includere live streaming accessibili, comunicazione bidirezionale o eventi di rilevamento. |
Tratti obbligatori google PushAvStreamTransport google WebRtcLiveView |
Campanello |
Recuperare informazioni di base su un dispositivo
Implementato nell'app di esempio per Android
La caratteristica BasicInformation
include informazioni quali nome del fornitore, ID fornitore, ID prodotto,
nome del prodotto (incluse le informazioni sul modello) e versione software per 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}") }
Recupera il numero di serie
Per ottenere il numero di serie del dispositivo, utilizza il comando GetSerialNumber del tratto ExtendedBasicInformation.
L'esempio mostra il salvataggio del numero di serie in una variabile denominata serialNumber:
val basicInfo: ExtendedBasicInformation = device.getTrait(ExtendedBasicInformation) val serialNumber = basicInfo.getSerialNumber().serialNumber
Risposte rapide
La funzionalità Risposte rapide consente all'utente di inviare un messaggio predefinito a un campanello.
Questa funzionalità è disponibile solo sui campanelli. L'elenco dei messaggi predefiniti è disponibile per l'app partner, che può presentarli all'utente tra cui scegliere. I messaggi predefiniti non sono modificabili dall'utente.
Le risposte rapide vengono implementate tramite il tratto
PresetMessage.
Riprodurre un messaggio preimpostato
Per riprodurre un messaggio preimpostato, chiama il metodo
playPresetMessage, passando uno dei valori stringa trovati nella proprietà
availablePhraseTypes.
import com.google.home.HomeDevice
import com.google.home.HomeException
import com.google.home.google.GoogleDoorbellDevice
import com.google.home.google.PresetMessage
import kotlinx.coroutines.flow.first
suspend fun playDoorbellPresetMessage(device: HomeDevice, phraseTypeString: String) {
try {
// 1. Retrieve the first snapshot of the doorbell device type
val doorbellDevice = device.type(GoogleDoorbellDevice).first()
// 2. Extract the PresetMessage trait
val presetMessageTrait = doorbellDevice.trait(PresetMessage)
if (presetMessageTrait == null) {
println("PresetMessage trait is not supported on this doorbell device.")
return
}
// 3. (Optional) Check available phrase types supported by the device
val availablePhrases = presetMessageTrait.availablePhraseTypes
if (availablePhrases != null) {
val phraseTypesList = availablePhrases.map { it.phraseType }
println("Supported quick response phrases: $phraseTypesList")
}
// 4. Send the playPresetMessage command to the doorbell
presetMessageTrait.playPresetMessage(phraseType = phraseTypeString)
println("Preset message command sent successfully.")
} catch (e: HomeException) {
println("Home API error occurred: ${e.message}")
} catch (e: Exception) {
println("Unexpected failure: ${e.message}")
}
}
Impostare la lingua parlata
Imposta la lingua parlata attiva di un dispositivo su impostazioni internazionali specifiche
(ad esempio "en_US") utilizzando il metodo setActiveLocale dell'attributo
LocalizationConfiguration.
import java.util.Locale // Convert underscore format (en_US) to Java Locale fun String.toLocale(): Locale = Locale.forLanguageTag(this.replace('_', '-')) // Setting the active language val trait: LocalizationConfiguration = device.getTrait(LocalizationConfiguration) val selectedLocale = "en_US" // Target locale string trait.update { setActiveLocale(selectedLocale) }
Visualizzare l'ultima volta che il dispositivo ha contattato il cloud
Per trovare l'ultima volta in cui il dispositivo ha avuto contatti con il cloud, utilizza
l'attributo lastContactTimestamp del
tratto ExtendedGeneralDiagnostics:
fun getLastContactTimeStamp(trait: ExtendedGeneralDiagnostics): java.time.Instant { val timestamp = trait.lastContactTimestamp return Instant.ofEpochSecond(timestamp.toLong()) }
Impostazioni del tipo di supporto per videocamera
La caratteristica Mount contiene
le impostazioni di montaggio della videocamera e le informazioni sullo stato. Puoi leggere attributi come
lo stato di montaggio, il tipo di rilevamento e il nome del tipo di montaggio. Inoltre,
puoi utilizzare il tratto Mount per ignorare la configurazione predefinita del tipo di supporto.
// 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) }
Controllare la connettività di un dispositivo
La connettività di un dispositivo viene controllata a livello di tipo di dispositivo perché alcuni dispositivi supportano più tipi di dispositivi. Lo stato restituito è una combinazione degli stati di connettività per tutte le caratteristiche del dispositivo.
Implementato nell'app di esempio per Androidval lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState
In caso di tipi di dispositivi misti, se non è presente una connettività a internet, potrebbe essere osservato uno stato di PARTIALLY_ONLINE.
Le funzionalità standard di Matter potrebbero essere ancora online a causa del routing locale, ma le funzionalità basate sul cloud saranno offline.
Ottieni l'indirizzo IP del dispositivo
Per trovare l'indirizzo IP del dispositivo, utilizza l'attributo networkInterfaces del tratto GeneralDiagnostics. Gli indirizzi vengono restituiti come array di byte, che puoi formattare in
stringhe IPv4 o IPv6 standard:
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()
Avviare un live streaming
Implementato nell'app di esempio per Android
Per avviare un live streaming, invia la stringa Session Description Protocol (SDP)
al metodo
WebRtcLiveView
dell'attributo
startLiveView(), che restituisce un
WebRtcLiveViewTrait.StartLiveViewCommand.Response
contenente tre valori:
- L'SDP per la sessione.
- La durata della sessione in secondi.
- L'ID sessione, che può essere utilizzato per estendere o terminare la sessione.
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)
Estendere un live streaming
Implementato nell'app di esempio per Android
I live streaming hanno una durata preimpostata dopo la quale scadono. Per estendere la
durata di uno stream attivo, invia una richiesta di estensione utilizzando il
metodo
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 }
Avviare e interrompere TalkBack
Implementato nell'app di esempio per Android
Per avviare TalkBack, chiama il metodo startTalkback() del tratto WebRtcLiveView. Per interrompere, utilizza
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) } }
Attivare e disattivare la funzionalità di registrazione
Per attivare la funzionalità di registrazione della videocamera, passa
TransportStatusEnum.Active
al metodo
PushAvStreamTransport
dell'attributo
setTransportStatus(). Per disattivare la funzionalità di registrazione, passa
TransportStatusEnum.Inactive.
Nel seguente esempio, racchiudiamo queste chiamate in una singola chiamata che utilizza un
Boolean per attivare/disattivare la funzionalità di registrazione:
// 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) } }
L'attivazione o la disattivazione della funzionalità di registrazione della videocamera equivale ad accendere o spegnere il video della videocamera. Quando il video di una videocamera è attivo, la videocamera registra (ai fini di eventi e clip correlati).
Quando la funzionalità di registrazione è disattivata (il video della videocamera è spento):
- La videocamera può comunque essere visualizzata come online in base all'
connectivityStatedel tipo di dispositivo. - Non è possibile accedere al live streaming e la videocamera non rileva eventi sul cloud.
Controllare se la funzionalità di registrazione è attiva
Per determinare se la funzionalità di registrazione di una videocamera è attiva, controlla se sono attive connessioni. L'esempio seguente definisce due funzioni per farlo:
// 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 }
Un altro modo per verificare è utilizzare la funzione findTransport() con un predicato:
// Fetch the current connections suspend fun queryRecordModeState(trait: PushAvStreamTransport) { return trait.findTransport().let { it.transportConfigurations.any { it.transportStatus == TransportStatusEnum.Active } }
Recuperare gli snapshot della videocamera
Utilizza il tratto CameraSnapshot per recuperare istantanee di immagini statiche da una videocamera.
Questi snapshot sono utili per diversi scenari:
- Come riquadro segnaposto nell'interfaccia utente durante il caricamento di uno stream live WebRTC.
- Come immagine di anteprima statica che viene aggiornata a una live streaming quando l'utente interagisce.
- Come sfondo per disegnare e configurare zone di attività personalizzate.
Il tratto CameraSnapshot offre due modi per recuperare gli snapshot, a seconda che tu abbia bisogno di uno snapshot memorizzato nella cache per un rendering rapido o di uno snapshot live on demand.
Visualizzare un'anteprima snapshot memorizzata nella cache
Un'istantanea di anteprima è un'immagine memorizzata nella cache che l'SDK può recuperare senza attivare la videocamera. Questo è il metodo più rapido per recuperare un'immagine statica ed è ideale per le pagine di panoramica della videocamera o le griglie della dashboard.
Per ottenere l'istantanea dell'anteprima, leggi l'attributo del tratto preview_image_url:
// Get a flow of the CameraSnapshot trait val cameraSnapshotFlow: Flow<CameraSnapshot?> = cameraDevice .type(GoogleCameraDevice) .trait(CameraSnapshot) // Get the current trait state val cameraSnapshot = cameraSnapshotFlow.firstOrNull() if (cameraSnapshot != null) { val previewImageUrl = cameraSnapshot.previewImageUrl // Load the preview image from the URL } else { // CameraSnapshot trait not supported on this device }
A seconda della configurazione e dell'attività della videocamera, l'URL di anteprima punta a un'immagine memorizzata nella cache generata da riprese video recenti (il primo I-frame dell'ultimo frammento video) o a un'istantanea caricata periodicamente dalla videocamera.
Per indicare la freschezza dell'immagine, il cloud Google Home incorpora un'intestazione
X-Home-Image-Captured-At nell'immagine
JPEG/PNG pubblicata, formattata in formato UTC. Puoi analizzare questa intestazione sul
lato client per visualizzare l'età dello snapshot in un'app.
Ottenere uno snapshot live on demand
Per i percorsi utente che richiedono la visione in diretta attuale della videocamera, ad esempio la configurazione delle zone attive, puoi richiedere un'istantanea in diretta. L'attivazione di un'istantanea live indica alla videocamera di attivarsi, acquisire un nuovo frame e caricarlo sul cloud.
Per richiedere uno snapshot live, utilizza il comando getLiveSnapshot():
try { val response = cameraSnapshot.getLiveSnapshot() val snapshotUrl = response.snapshotUrl // Load the live snapshot image from the URL } catch (e: Exception) { Log.e("CameraSnapshot", "Failed to get live snapshot: ${e.message}") }
Autenticare le richieste di snapshot
Tutti gli URL degli snapshot puntano a contenuti multimediali sicuri e richiedono un token OAuth 2.0 per l'ambito
delle API Home v2. Per scaricare e visualizzare le immagini, il token OAuth deve essere
inserito come token Bearer nell'intestazione Authorization della richiesta HTTP.
Il seguente esempio mostra come configurare una richiesta di rete sicura per scaricare uno snapshot:
import android.graphics.Bitmap import android.graphics.BitmapFactory import java.io.IOException import java.net.HttpURLConnection import java.net.URL import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext /** * Downloads a snapshot from a URL using an OAuth access token. */ suspend fun loadSnapshotImage(urlString: String, oauthToken: String): Bitmap? = withContext(Dispatchers.IO) { var connection: HttpURLConnection? = null try { val url = URL(urlString) connection = url.openConnection() as HttpURLConnection // 1. Configure the HTTP GET request with the Bearer token connection.setRequestProperty("Authorization", "Bearer $oauthToken") // 2. Fetch the image data if (connection.responseCode == HttpURLConnection.HTTP_OK) { connection.inputStream.use { inputStream -> BitmapFactory.decodeStream(inputStream) } } else { null } } catch (e: IOException) { e.printStackTrace() null } finally { connection?.disconnect() } }
Gestire il live streaming
La regolazione della qualità dello stream live è utile per ottimizzare l'utilizzo della larghezza di banda in base al contesto di visualizzazione del client (ad esempio, il passaggio a una risoluzione inferiore quando viene visualizzata una miniatura di anteprima più piccola, la visualizzazione a griglia o la modalità Picture in picture).
La modifica dinamica della qualità utilizzando l'attributo
WebRtcLiveView
gestisce in modo specifico la risoluzione della sessione di live streaming attiva
su un determinato client. Non è la stessa cosa di configurare un'impostazione di utilizzo della larghezza di banda a livello di dispositivo direttamente sul dispositivo, il che influirebbe su tutti gli spettatori simultanei e sulla qualità delle registrazioni video storiche salvate sul cloud.
Il seguente esempio mostra come recuperare e aggiornare la qualità dello streaming live per un dispositivo:
Recupera le opzioni di qualità supportate: ottieni le risoluzioni di streaming disponibili supportate dal dispositivo. Il codice esegue query sull'attributo
supportedQualityHintsdel trattoWebRtcLiveViewnel flusso del tipo di dispositivo ed espone le qualità supportate comeStateFlowcontenente un elenco di valoriQualityHint(ad esempioQUALITY_HINT_SD,QUALITY_HINT_HD,QUALITY_HINT_FHD,QUALITY_HINT_QHDoQUALITY_HINT_UHD).Modifica la qualità del live streaming: applica una
QualityHintselezionata per modificare la risoluzione dello streaming del live streaming attivo (ad esempio, passando dalla definizione standard all'alta definizione). La funzionechangeQualityrisolve il tratto di live streaming del dispositivo e chiamachangeLiveViewQualitycon la configurazionemediaSessionIdattiva e la configurazioneQualityHintscelta.
// Assuming you have a HomeDevice instance 'device' val availableQualityHints: StateFlow<List> = device.type(GoogleDoorbellDevice) .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(GoogleDoorbellDevice).trait(WebRtcLiveView).first() ?: return try { trait.changeLiveViewQuality(mediaSessionId, qualityHint) } catch (e: Exception) { // Handle error } }
Impostazioni della batteria
È possibile controllare varie impostazioni della batteria tramite le API Home.
Impostare la preferenza di utilizzo della batteria
L'impostazione del bilancio energetico consente di configurare il compromesso tra durata della batteria e prestazioni di un dispositivo. Puoi creare diversi profili batteria, ad esempio "Esteso", "Bilanciato" e "Prestazioni", e passare da uno all'altro.
Questa funzionalità viene implementata aggiornando l'attributo
currentEnergyBalance
del tratto
EnergyPreference. L'attributo accetta un indice
intero che corrisponde a un profilo specifico definito nell'elenco
energyBalances del dispositivo (ad esempio, 0 per EXTENDED,
1 per BALANCED e 2 per PERFORMANCE).
Un valore null per currentEnergyBalance indica che il dispositivo utilizza un profilo personalizzato. Questo è uno stato di sola lettura.
Di seguito è riportato un esempio di struttura che verrà utilizzata dall'attributo currentEnergyBalance, seguito dallo snippet di codice effettivo che utilizza l'attributo.
// 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)
Attivare il risparmio energetico automatico
Per configurare questa funzionalità, aggiorna l'attributo
currentLowPowerModeSensitivity
del tratto EnergyPreference. Questo attributo utilizza un indice
per selezionare un livello di sensibilità, dove 0 in genere rappresenta Disabled
e 1 rappresenta 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) } }
Ottenere lo stato di ricarica della batteria
Per ottenere lo stato di ricarica attuale del dispositivo (in ricarica, completamente carico o non
in ricarica), utilizza l'attributo
batChargeState
del tratto
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" }
Ottenere il livello della batteria
Per ottenere il livello attuale della batteria, utilizza l'attributo
batChargeLevel
del tratto
PowerSource. Il livello è OK, Warning (basso) 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" }
Recuperare la fonte di alimentazione
Per determinare la fonte di alimentazione utilizzata dal dispositivo,
utilizza gli attributi
BatPresent
e
wiredPresent
del tratto
PowerSource.
val trait: PowerSource val isWired = trait.wiredPresent val hasBattery = trait.batPresent
Controlla se è necessario sostituire la batteria.
L'attributo batReplaceability
indica se la batteria non è sostituibile, sostituibile dall'utente o
sostituibile in fabbrica.
L'attributo
batReplacementNeeded
del tratto
PowerSource
indica se è necessario sostituire la batteria.
// Get the battery replacement status val batteryStatus = powerSourceTrait.batReplacementNeeded if (batteryStatus) { println("Replace the battery.") }
Quando la batteria è sostituibile dall'utente, il
batReplacementDescription
descrive la batteria, incluse informazioni quali fattore di forma, composizione chimica e
produttore preferito.
Impostazioni audio
È possibile controllare varie impostazioni audio tramite le API Home.
Attivare o disattivare il microfono
Per attivare o disattivare il microfono del dispositivo, aggiorna l'attributo
microphoneMuted
del tratto CameraAvStreamManagement utilizzando la funzione
setMicrophoneMuted Kotlin integrata:
// Turn the device's microphone on or off suspend fun turnOffMicrophone(disableMicrophone: Boolean, trait: CameraAvStreamManagement) { trait.update { setMicrophoneMuted(disableMicrophone) } }
Attivare o disattivare la registrazione audio
Per attivare o disattivare la registrazione audio per il dispositivo, aggiorna l'attributo
recordingMicrophoneMuted
del tratto CameraAvStreamManagement utilizzando la funzione
Kotlin setRecordingMicrophoneMuted integrata:
// Turn audio recording on or off for the device suspend fun turnOffAudioRecording(disableAudioRecording: Boolean, trait: CameraAvStreamManagement) { trait.update { setRecordingMicrophoneMuted(disableAudioRecording) } }
Regolare il volume dello speaker
Per regolare il volume dello speaker del dispositivo, aggiorna l'attributo
speakerVolumeLevel
del tratto CameraAvStreamManagement utilizzando la funzione Kotlin
setSpeakerVolumeLevel integrata:
// Adjust the camera speaker volume suspend fun adjustSpeakerVolume(volume: Int, trait: CameraAvStreamManagement) { trait.update { setSpeakerVolumeLevel(volume.toUbyte()) } }
Impostazioni delle zone attive
Implementato nell'app di esempio per Android
La caratteristica ZoneManagement fornisce un'interfaccia per la gestione di regioni di interesse (zone attive) personalizzate su videocamere e campanelli.
Queste zone vengono utilizzate per filtrare il rilevamento di eventi (ad esempio movimento di persone o veicoli) in aree specifiche all'interno del campo visivo del dispositivo.
Le zone attive vengono configurate dall'utente all'interno di un'applicazione partner, consentendogli di disegnare zone su aree specifiche del campo visivo della videocamera. Queste zone definite dall'utente vengono poi tradotte nelle strutture utilizzate da questo tratto. Per maggiori informazioni su come funzionano le zone attive, consulta Configurare e usare le zone attive.
Le zone attive vengono in genere definite utilizzando coordinate cartesiane 2D.
Il tratto fornisce le
TwoDCartesianVertexStruct per i vertici e le
TwoDCartesianZoneStruct
per la definizione della zona (nome, vertici, colore e utilizzo).
Controllare le zone attive
Per visualizzare le zone attive, seleziona l'attributo
zones
del tratto 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() }
Aggiungere una Zona attiva
Per creare una nuova zona, utilizza il comando
createTwoDCartesianZone. Questo comando accetta un TwoDCartesianZoneStruct,
che definisce il nome, i vertici, il colore e l'utilizzo della zona.
L'esempio seguente mostra come creare una zona denominata "Front Porch" (Veranda) con quattro vertici, color salmone (#F439A0) e utilizzata per il rilevamento del movimento.
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}") } }
Aggiornare una zona attiva
Per aggiornare una zona esistente, utilizza il
comando updateTwoDCartesianZone. Questo comando richiede zoneId e l'TwoDCartesianZoneStruct aggiornato.
private suspend fun ZoneManagement.updateZone( zoneId: UShort, zone: ZoneManagementTrait.TwoDCartesianZoneStruct ) { // Execute the command to update the zone this.updateTwoDCartesianZone(zoneId = zoneId, zone = zone) }
Eliminare una zona attiva
Per rimuovere una zona, utilizza il
comando removeZone
con il zoneId specifico.
private suspend fun ZoneManagement.deleteZone(zoneId: UShort) { // Execute the command to remove the zone this.removeZone(zoneId = zoneId) }
Trigger eventi sonori
La caratteristica AvStreamAnalysis fornisce un'interfaccia per la gestione dei trigger di rilevamento degli eventi su videocamere e campanelli. Mentre i trigger basati sulla visione
(come persone o veicoli) possono essere specifici per zona, i trigger correlati al suono
sono in genere configurazioni a livello di dispositivo.
Per il rilevamento dei suoni con EventTriggerTypeEnum sono disponibili i seguenti tipi di attivatori:
| Modalità | Valore enum | Descrizione |
|---|---|---|
| Suono | Sound |
Rilevamento dei suoni generale. |
| Persona che parla | PersonTalking |
Rileva la voce. |
| Cane che abbaia | DogBark |
Rileva le vocalizzazioni canine. |
| Vetri rotti | GlassBreak |
Rileva il rumore di vetri infranti. |
| Allarme fumo | SmokeAlarm |
Rileva gli allarmi fumo, spesso riconosciuti dal pattern sonoro T3 (tre brevi segnali acustici seguiti da una pausa). |
| Allarme CO | CoAlarm |
Rileva gli allarmi di monossido di carbonio (CO), in genere riconosciuti dal modello acustico T4 (quattro brevi segnali acustici seguiti da una pausa). |
Controllare lo stato del rilevamento dei suoni
Per mostrare all'utente lo stato attuale del rilevamento del suono, devi verificare cosa supporta il dispositivo e cosa è abilitato dall'hardware del dispositivo. I due attributi da controllare sono:
Nello sviluppo Android utilizzando Kotlin Flows, in genere si osserva il tratto
AvStreamAnalysis da 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) ) } }
Aggiorna l'insieme di trigger abilitati
Per aggiornare l'insieme di trigger abilitati, utilizza il
comando SetOrUpdateEventDetectionTriggers, che accetta un elenco di strutture 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) }
Modalità di registrazione
Implementato nell'app di esempio per Android
La caratteristica RecordingMode fornisce un'interfaccia per gestire il comportamento di registrazione di video e immagini su videocamere e campanelli. Consente
agli utenti di scegliere tra registrazione continua, registrazione basata sugli eventi
o disattivazione completa della registrazione (solo Live View).
RecordingModeEnum
definisce le strategie di registrazione disponibili:
| Modalità | Valore enum | Descrizione |
|---|---|---|
| Disabilitata | Disabled |
La registrazione è completamente disattivata. Utilizzato principalmente dai dispositivi legacy. |
| CVR (registrazione video continua) | Cvr |
Il video viene registrato 24 ore su 24, 7 giorni su 7. Richiede un abbonamento (ad esempio, Google Home Premium). |
| EBR (registrazione basata sugli eventi) | Ebr |
La registrazione viene attivata da eventi (persona, movimento). La durata del video dipende dalla durata dell'evento e dall'abbonamento. |
| ETR (registrazione attivata da eventi) | Etr |
Registrazione di un'anteprima breve (ad esempio, 10 secondi) attivata da eventi. |
| Live View | LiveView |
La registrazione è disattivata, ma gli utenti possono comunque accedere allo streaming live. |
| Immagini statiche | Images |
Quando si verificano eventi, vengono registrate istantanee anziché video. |
Controllare le modalità di registrazione
Per visualizzare la configurazione di registrazione attuale, controlla gli attributi
del tratto RecordingMode:
supportedRecordingModes- Tutte le modalità potenzialiavailableRecordingModes- Modalità selezionabiliselectedRecordingMode- La modalità attiva
// 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(), ) } }
Modificare la modalità di registrazione
Prima dell'aggiornamento, assicurati che l'indice scelto dall'attributo supportedRecordingModes
sia presente nell'attributo availableRecordingModes.
Per aggiornare la modalità selezionata, utilizza la
funzione setSelectedRecordingMode, passando l'indice della modalità scelta:
private suspend fun RecordingMode.updateRecordingMode(index: Int) { // Execute the command to update the selected mode this.setSelectedRecordingMode(index.toUByte()) }
Altre impostazioni
Varie altre impostazioni possono essere controllate tramite le API Home.
Attivare o disattivare la visione notturna
Per attivare o disattivare la visione notturna per la videocamera, utilizza TriStateAutoEnum
per aggiornare l'attributo
nightVision
del tratto CameraAvStreamManagement utilizzando la funzione
setNightVision Kotlin integrata:
// Turn night vision on cameraAvStreamManagement.update { setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.On) } // Turn night vision off CameraAvStreamManagement.update { setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.Off) }
Modificare la luminosità del LED di stato
Per modificare la luminosità del LED di stato, utilizza
ThreeLevelAutoEnum
per aggiornare l'attributo
statusLightBrightness
del tratto CameraAvStreamManagement utilizzando la funzione Kotlin
setStatusLightBrightness integrata:
// Set the LED brightness to high cameraAvStreamManagement.update { setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.High) } // Set the LED brightness to low cameraAvStreamManagement.update { setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.Low) }
Modificare il viewport della videocamera
La finestra della videocamera è la stessa della funzionalità Zoom e ritaglio descritta nell'articolo del Centro assistenza Aumentare lo zoom e migliorare i video della videocamera Nest.
La finestra è definita in un ViewportStruct che contiene quattro valori, che
vengono utilizzati come coordinate della finestra. Le coordinate sono definite come segue:
(x1,y1) -- (x2,y1) | | (x1,y2) -- (x2,y2)
La determinazione dei valori per ViewportStruct dipende dall'interfaccia utente e dall'implementazione della fotocamera di un'app. A un livello molto base, per impostare la visualizzazione del video della videocamera, aggiorna l'attributo viewport del tratto CameraAvStreamManagement con un ViewportStruct, utilizzando la funzione Kotlin setViewport integrata:
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(), ) ) }
Attivare o disattivare l'analisi
Ogni dispositivo può attivare individualmente l'invio di dati di analisi dettagliati al cloud Google Home (vedi Cloud Monitoring per le API Home).
Per attivare l'analisi per un dispositivo, imposta la proprietà
analyticsEnabled
di
ExtendedGeneralDiagnosticsTrait
su true. Quando imposti analyticsEnabled,
un'altra proprietà, logUploadEnabled, viene impostata automaticamente su true, il che
consente di caricare i file di log di analisi sul cloud Google Home.
// Enable analytics extendedGeneralDiagnostics.update { setAnalyticsEnabled(true) } // Disable analytics extendedGeneralDiagnostics.update { setAnalyticsEnabled(false) }
Configurazioni di trasporto e registrazione
Questa sezione riguarda le impostazioni relative alla qualità dello streaming della videocamera e
all'attivazione degli eventi. Queste impostazioni sono gestite dal tratto
PushAvStreamTransport.
Leggi le impostazioni di trasporto
Questa sezione mostra come recuperare la configurazione attuale da
una videocamera o un campanello. Recupera il tratto PushAvStreamTransport,
trova la connessione specifica utilizzata per la registrazione ed estrae
i valori correnti per la qualità della larghezza di banda, la sensibilità di riattivazione
e la durata massima dell'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
Aggiornare le impostazioni di trasporto
Questa sezione mostra come modificare le impostazioni di trasporto.
Crea un nuovo TransportOptionsStruct contenente i nuovi valori e
poi utilizza il comando modifyPushTransport per inviare queste impostazioni aggiornate
al dispositivo, applicandole alla connessione di registrazione trovata
nel passaggio precedente.
Per modificare queste impostazioni, utilizza il 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 ) }
Determinare la qualità della larghezza di banda
La proprietà videoStreamId
di TransportOptionsStruct corrisponde a una
configurazione specifica dello stream video.
Per ottenere gli stream video supportati, fai riferimento all'attributo
allocatedVideoStreams,
che è un elenco di VideoStreamStructs.
dalla caratteristica CameraAvStreamManagement per il dispositivo.
Regolare la sensibilità alla riattivazione del dispositivo
La proprietà motionSensitivity
di TransportTriggerOptionsStruct corrisponde ai
seguenti valori:
| Etichetta | Valore (UByte) |
|---|---|
| Bassa | 1u |
| Media | 5u |
| Alta | 10u |
Regolare la durata massima degli eventi
La proprietà maxDuration di TransportMotionTriggerTimeControlStruct corrisponde alle seguenti durate (in secondi):
- 10u, 15u, 30u, 60u, 120u, 180u
Impostazioni del cicalino
È possibile controllare varie impostazioni del suono del campanello tramite le API Home.
Modificare il suono del cicalino
Per modificare il suono della suoneria del campanello, recupera prima l'elenco dei suoni della suoneria installati sul dispositivo utilizzando l'attributo
installedChimeSounds
del tratto 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()
Quindi, aggiorna l'attributo
selectedChime
del tratto Chime utilizzando la funzione Kotlin setSelectedChime integrata:
// Set the chime using the chimeId from the installed list chimeSounds.firstOrNull { it.name == name }?.let { setSelectedChime(it.chimeId) }
Utilizzare un cicalino esterno
Implementato nell'app di esempio per Android
Il campanello può essere configurato per utilizzare un cicalino esterno, ad esempio una campana meccanica installata all'interno della casa. Questa impostazione deve essere configurata durante l'installazione del campanello per evitare potenziali danni al cicalino esterno.
Per indicare il tipo di campanello esterno installato, utilizza
ExternalChimeType
per aggiornare l'attributo
externalChime
del tratto Chime utilizzando la funzione
setExternalChime Kotlin integrata:
// Indicate the external chime is mechanical chime.update { setExternalChime(ChimeTrait.ExternalChimeType.Mechanical) }
Modificare la durata del suono del cicalino esterno
La durata, in secondi, del suono di un campanello esterno può essere configurata tramite le API Home. Se il suono esterno supporta una durata, un utente potrebbe volerla configurare.
Il valore impostato qui dipende dalle specifiche del campanello esterno e dalla durata consigliata del suono.
Per modificare la durata del suono di avviso esterno, aggiorna l'attributo
externalChimeDurationSeconds
del tratto Chime utilizzando la funzione Kotlin
setExternalChimeDurationSeconds integrata:
// Change the external chime duration chime.update { setExternalChimeDurationSeconds(newDuration.toUShort()) }
Attivare un tema per il suono di notifica
Implementato nell'app di esempio per Android
Alcuni campanelli potrebbero avere suonerie disponibili solo per un periodo di tempo limitato. Ad esempio, suoni specifici per le festività. Questi si chiamano temi di notifica.
Per vedere quali temi di suono sono disponibili per un utente, crea un filtro timebox
e utilizzalo per filtrare i risultati del comando
getAvailableThemes()
dall'attributo
ChimeThemes. Viene restituito un elenco di temi disponibili, inclusi i nomi dei temi.
Il seguente esempio mostra come filtrare l'elenco.
Un tema è considerato attivo se l'ora corrente rientra
nell'intervallo tra l'ora di inizio e l'ora di fine (i valori startTimeSeconds e endTimeSeconds,
rispettivamente). Se non è impostata un'ora di inizio, la regola viene considerata attiva dall'inizio dei tempi. Se non viene impostata un'ora di fine, la regola rimane attiva
a tempo indeterminato. Se mancano entrambi, il tema è sempre attivo.
// 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()
Una volta ottenuto il nome del tema che vuoi, ad esempio Christmas, puoi
selezionarlo utilizzando la funzione setSelectedTimeboxedThemeName() nell'attributo
ChimeThemes:
// Select a theme using the ChimeThemes trait val themeToSelect = "Christmas" if (themeToSelect in availableThemeNames) { doorbellChimeThemesTraitFlow.first().setSelectedTimeboxedThemeName(themeToSelect) }
Impostazioni degli annunci visite
Puoi eseguire query e gestire le impostazioni di Annuncio visite per i campanelli utilizzando
il tratto
VisitorAnnouncement
delle API Home. Questa caratteristica controlla se la presenza di un visitatore viene annunciata su speaker o display
Google smart quando qualcuno suona il campanello.
L'esempio seguente mostra come verificare se gli annunci visite sono attivati e come aggiornare questa impostazione:
// Read the current visitor announcements state val isEnabled = visitorAnnouncementTrait.visitorAnnouncementsEnabled // Toggle the visitor announcements setting visitorAnnouncementTrait.update { setVisitorAnnouncementsEnabled(true) }