Android 裝置的門鈴裝置指南

門鈴裝置類型是透過兩種特徵實作:PushAvStreamTransport,可使用以推送為基礎的通訊協定處理音訊和影片串流傳輸;WebRtcLiveView,可控制即時串流和對講功能。

使用任何功能或嘗試更新屬性之前,請務必先檢查裝置是否支援屬性和指令。詳情請參閱「透過Android 控制裝置」。

Home API 裝置類型 特徵 Kotlin 範例應用程式 用途

門鈴

GoogleDoorbellDevice

home.matter.6006.types.0113

門外的按鈕啟動裝置,會發出聲音和/或視覺信號,用於請求門另一側的人注意。門鈴可能提供無障礙直播、雙向對講或偵測事件。

必要特徵
     google PushAvStreamTransport
     google WebRtcLiveView

門鈴

取得裝置的基本資訊

BasicInformation 特徵包括供應商名稱、供應商 ID、產品 ID、產品名稱 (包括型號資訊)、軟體版本和裝置序號等資訊:

// 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}")
    }

檢查裝置的連線狀態

裝置的連線狀態實際上是在裝置類型層級檢查,因為部分裝置支援多種裝置類型。傳回的狀態是該裝置上所有特徵的連線狀態組合。

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

如果沒有網際網路連線,且裝置類型混用,可能會出現 PARTIALLY_ONLINE 狀態。Matter 標準特徵碼可能仍會因本機路由而處於連線狀態,但雲端特徵碼會離線。

開始直播

如要開始直播,請將工作階段描述通訊協定 (SDP) 字串傳送至 WebRtcLiveView 特徵的 startLiveView() 方法,該方法會傳回 WebRtcLiveViewTrait.StartLiveViewCommand.Response,其中包含三個值:

  • 工作階段的 SDP。
  • 工作階段時間長度 (以秒為單位)。
  • 工作階段 ID,可用於延長或終止工作階段。
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)

延長直播時間

直播有預設時長,時間一到就會過期。如要延長有效串流的時長,請使用 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
}

啟動及停止 TalkBack

如要啟動 TalkBack,請呼叫 WebRtcLiveView 特徵的 startTalkback() 方法。如要停止,請使用 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)
  }
}

啟用及停用錄製功能

如要啟用攝影機的錄影功能,請將 TransportStatusEnum.Active 傳遞至 PushAvStreamTransport 特徵的 setTransportStatus() 方法。如要停用錄製功能,請傳遞 TransportStatusEnum.Inactive。 在以下範例中,我們將這些呼叫包裝在單一呼叫中,並使用 Boolean 切換錄音功能:

// 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)
  }
}

啟用或停用攝影機的錄影功能,等同於開啟或關閉攝影機影像。攝影機影像開啟時,攝影機就會錄影 (用於事件和相關影像片段)。

錄製功能停用時 (攝影機影片關閉):

  • 攝影機仍會顯示為connectivityState裝置類型的線上狀態。
  • 無法存取即時串流影像,攝影機也未偵測到任何雲端事件。

確認是否已啟用錄製功能

如要判斷攝影機是否已啟用錄影功能,請檢查是否有任何連線處於啟用狀態。以下範例定義了兩個函式來執行這項操作:

// 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
}

您也可以使用含述詞的 findTransport() 函式進行檢查:

// Fetch the current connections
suspend fun queryRecordModeState(trait: PushAvStreamTransport) {
  return trait.findTransport().let {
      it.transportConfigurations.any { it.transportStatus == TransportStatusEnum.Active
    }
}

電池設定

你可以透過 Home API 控制各種電池設定。

設定電池用量偏好設定

設定能源平衡可讓您在裝置的電池續航力和效能之間取捨。你可以建立不同的電池設定檔,例如「延長續航力」、「平衡」和「效能」,並在這些設定檔之間切換。

如要實作這項功能,請更新 EnergyPreference 特徵的 currentEnergyBalance 屬性。這個屬性接受與裝置 energyBalances 清單中定義的特定設定檔對應的整數索引 (例如 EXTENDED0BALANCED1,以及 PERFORMANCE2)。

currentEnergyBalancenull 值表示裝置使用自訂設定檔。這是唯讀狀態。

以下範例顯示 currentEnergyBalance 屬性使用的結構,接著是使用該屬性的實際程式碼片段。

// 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)

開啟自動省電模式

如要設定這項功能,請更新 EnergyPreference 特徵的 currentLowPowerModeSensitivity 屬性。這項屬性會使用索引選取感應程度,其中 0 通常代表 Disabled,而 1 代表 EnabledAutomatic

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) }
}

取得電池充電狀態

如要取得裝置目前的充電狀態 (充電中、已充飽電或未充電),請使用 PowerSource 特徵的 batChargeState 屬性。

// 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"
}

取得電池電量

如要取得目前的電池電量,請使用 PowerSource 特徵的 batChargeLevel 屬性。層級可以是 OKWarning (低) 或 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"
}

取得電源

如要判斷裝置使用的電源,請使用 PowerSource 特徵的 BatPresentwiredPresent 屬性。

  val trait: PowerSource
  val isWired = trait.wiredPresent
  val hasBattery = trait.batPresent

音訊設定

你可以透過 Home API 控制各種音訊設定。

開啟或關閉麥克風

如要開啟或關閉裝置的麥克風,請使用內建的 setMicrophoneMuted Kotlin 函式,更新 CameraAvStreamManagement 特徵的 microphoneMuted 屬性:

// Turn the device's microphone on or off
suspend fun turnOffMicrophone(disableMicrophone: Boolean, trait: CameraAvStreamManagement) {
  trait.update { setMicrophoneMuted(disableMicrophone) }
}

開啟或關閉錄音功能

如要開啟或關閉裝置的錄音功能,請使用內建的 setRecordingMicrophoneMuted Kotlin 函式,更新 CameraAvStreamManagement 特徵的 recordingMicrophoneMuted 屬性:

// Turn audio recording on or off for the device
suspend fun turnOffAudioRecording(disableAudioRecording: Boolean, trait: CameraAvStreamManagement) {
  trait.update { setRecordingMicrophoneMuted(disableAudioRecording) }
}

調整音箱音量

如要調整裝置的音箱音量,請使用內建的 setSpeakerVolumeLevel Kotlin 函式,更新 CameraAvStreamManagement 特徵的 speakerVolumeLevel 屬性:

// Adjust the camera speaker volume
suspend fun adjustSpeakerVolume(volume: Int, trait: CameraAvStreamManagement) {
  trait.update { setSpeakerVolumeLevel(volume.toUbyte()) }
}

其他設定

您也可以透過 Home API 控制其他各種設定。

開啟或關閉夜視模式

如要開啟或關閉攝影機的夜視功能,請使用 TriStateAutoEnum 更新 CameraAvStreamManagement 特徵的 nightVision 屬性,方法是使用內建的 setNightVision Kotlin 函式:

// Turn night vision on
cameraAvStreamManagement.update {
  setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.On)
}

// Turn night vision off
CameraAvStreamManagement.update {
  setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.Off)
}

變更狀態 LED 燈的亮度

如要變更狀態 LED 的亮度,請使用 ThreeLevelAutoEnum 更新 CameraAvStreamManagement 特徵的 statusLightBrightness 屬性,方法是使用內建的 setStatusLightBrightness Kotlin 函式:

// Set the LED brightness to high
cameraAvStreamManagement.update {
  setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.High)
}

// Set the LED brightness to low
cameraAvStreamManagement.update {
  setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.Low)
}

變更攝影機可視區域

攝影機檢視區塊與「縮放加強 Nest 攝影機影像」支援文章中說明的「縮放及裁剪」功能相同。

視埠定義於包含四個值的 ViewportStruct 中,這些值會做為視埠的座標。座標定義如下:

(x1,y1) -- (x2,y1)
   |          |
(x1,y2) -- (x2,y2)

判斷 ViewportStruct 的值取決於應用程式的 UI 和相機實作方式。在最基本的層級,如要設定攝影機影片的檢視區塊,請使用內建的 setViewport Kotlin 函式,透過 ViewportStruct 更新 CameraAvStreamManagement 特徵的 viewport 屬性:

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(),
    )
) }

調整裝置喚醒靈敏度

裝置的喚醒敏感度可縮減裝置感應活動的範圍,並延長偵測到活動後喚醒裝置的時間,藉此節省電量。

在 Home API 中,這項屬性可透過裝置 transportOptions 中的 motionSensitivity 屬性設定。triggerOptions這些選項是在每個裝置的 PushAvStreamTransport 特徵中定義。

喚醒敏感度只能設為下列值:

  • 1 = 低
  • 5 = 中
  • 10 = 高

如要更新,請使用 findTransport 指令找出有效錄製串流的傳輸設定,然後使用 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,
      )
    }
  }

調整事件錄影時間上限

事件錄影時間上限是指攝影機錄製事件影像片段的時間長度。透過 Home API,您可以為每個裝置設定與透過 GHA 相同的長度,間隔為秒:

  • 10 秒
  • 15 秒
  • 30 秒
  • 60 秒 (1 分鐘)
  • 120 秒 (2 分鐘)
  • 180 秒 (3 分鐘)

在 Home API 中,這項屬性可透過裝置 transportOptions 中的 motionTimeControl 屬性設定。triggerOptions這些選項是在每個裝置的 PushAvStreamTransport 特徵中定義。

如要更新,請使用 findTransport 指令找出有效錄製串流的傳輸設定,然後使用 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,
      )
    }
  }

鈴聲設定

你可以透過 Home API 控制各種門鈴鈴聲設定。

變更鈴聲音效

如要變更門鈴鈴聲,請先使用 Chime 特徵的 installedChimeSounds 屬性,取得裝置上安裝的鈴聲清單:

// 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()

然後,使用內建的 setSelectedChime Kotlin 函式,更新 Chime 特徵的 selectedChime 屬性:

// Set the chime using the chimeId from the installed list
chimeSounds.firstOrNull { it.name == name }?.let { setSelectedChime(it.chimeId) }

使用外部鈴聲

你可以將門鈴設定為使用外部鈴聲,例如安裝在住家內的機械式電鈴。安裝門鈴時應設定這項功能,以免外部鈴聲可能損壞。

如要指出安裝的外部鈴聲類型,請使用 ExternalChimeType 更新 Chime 特徵的 externalChime 屬性,方法是使用內建的 setExternalChime Kotlin 函式:

// Indicate the external chime is mechanical
chime.update {
  setExternalChime(ChimeTrait.ExternalChimeType.Mechanical)
}

變更外部電鈴時長

你可以透過 Home API 設定外部鈴聲的響鈴時間 (以秒為單位)。如果外部鈴聲支援鈴聲持續時間,使用者可能需要設定這項功能。

此處設定的值取決於外部鈴聲本身的規格,以及建議的鈴聲長度。

如要變更外部鈴聲的持續時間,請使用內建的 setExternalChimeDurationSeconds Kotlin 函式,更新 Chime 特徵的 externalChimeDurationSeconds 屬性:

// Change the external chime duration
chime.update {
  setExternalChimeDurationSeconds(newDuration.toUShort())
}

啟用鈴聲主題

部分門鈴可能提供限時鈴聲。例如節慶專屬鈴聲。這些稱為鈴聲主題。

如要查看使用者可用的鈴聲主題,請建立時間範圍篩選器,並使用該篩選器篩選 ChimeThemes 特徵的 getAvailableThemes() 指令結果。這樣會傳回可用主題清單,包括主題名稱。

以下範例說明如何篩選清單。如果目前時間介於主題的開始和結束時間 (分別為 startTimeSecondsendTimeSeconds 值) 之間,系統就會將該主題視為有效。如果未設定開始時間,系統會將其視為從時間開始起就處於有效狀態。如果未設定結束時間,廣告活動會無限期持續放送。如果兩者皆未提供,主題一律會處於啟用狀態。

// 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()

取得所需主題的名稱 (例如 Christmas) 後,即可使用 ChimeThemes 特徵的 setSelectedTimeboxedThemeName() 函式選取該主題:

// Select a theme using the ChimeThemes trait
val themeToSelect = "Christmas"
if (themeToSelect in availableThemeNames) {
  doorbellChimeThemesTraitFlow.first().setSelectedTimeboxedThemeName(themeToSelect)
}