Przewodnik po dzwonku do drzwi na Androida

Typ urządzenia Dzwonek jest implementowany za pomocą 2 cech:PushAvStreamTransport, która obsługuje transport strumieni audio i wideo za pomocą protokołów opartych na push, orazWebRtcLiveView, która umożliwia sterowanie transmisjami na żywo i funkcją talkback.

Przed użyciem jakichkolwiek funkcji lub próbą zaktualizowania atrybutów zawsze sprawdzaj, czy urządzenie obsługuje atrybuty i polecenia. Więcej informacji znajdziesz w artykule Sterowanie urządzeniami na Android.

Typ urządzenia interfejsów Home API Cechy Przykładowa aplikacja w Kotlinie Przypadek użycia

Dzwonek

GoogleDoorbellDevice

home.matter.6006.types.0113

Urządzenie uruchamiane przyciskiem na zewnątrz drzwi, które emituje sygnał dźwiękowy lub wizualny, używane do zwrócenia uwagi osoby znajdującej się po drugiej stronie drzwi. Dzwonki do drzwi mogą mieć funkcje transmisji na żywo z ułatwieniami dostępu, dwukierunkowego odtwarzania dźwięku lub wykrywania zdarzeń.

Wymagane cechy
     google PushAvStreamTransport
     google WebRtcLiveView

Dzwonek

Rozpoczynanie transmisji na żywo

Aby rozpocząć transmisję na żywo, wyślij ciąg znaków protokołu SDP (Session Description Protocol) do metody startLiveView() cechy WebRtcLiveView, która zwraca obiekt WebRtcLiveViewTrait.StartLiveViewCommand.Response zawierający 3 wartości:

  • SDP sesji.
  • Czas trwania sesji w sekundach.
  • Identyfikator sesji, który może służyć do przedłużenia lub zakończenia sesji.
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)

Przedłużanie transmisji na żywo

Transmisje na żywo mają z góry określony czas trwania, po którym wygasają. Aby wydłużyć czas trwania aktywnego strumienia, wyślij prośbę o przedłużenie za pomocą metody 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
}

Włączanie i wyłączanie TalkBack

Aby rozpocząć rozmowę, wywołaj metodę startTalkback() cechy WebRtcLiveView talkback. Aby zatrzymać, użyj 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)
  }
}

Włączanie i wyłączanie możliwości nagrywania

Aby włączyć funkcję nagrywania kamery, przekaż wartość TransportStatusEnum.Active do metody PushAvStreamTransport cechy setTransportStatus(). Aby wyłączyć możliwość nagrywania, przekaż wartość TransportStatusEnum.Inactive. W poniższym przykładzie umieszczamy te wywołania w jednym wywołaniu, które używa Boolean, aby włączać i wyłączać możliwość nagrywania:

// Start or stop recording for all connections.
suspend fun setCameraRecording(isOn: Boolean) {
  val pushAvStreamTransport = getPushAvStreamTransport
  if(isOn) {
    pushAvStreamTransport.setTransportStatus(TransportStatusEnum.Active)
  } else {
    pushAvStreamTransport.setTransportStatus(TransportStatusEnum.Inactive)
  }
}

Włączenie lub wyłączenie funkcji nagrywania kamery jest równoznaczne z włączeniem lub wyłączeniem wideo z kamery. Gdy wideo z kamery jest włączone, kamera nagrywa (na potrzeby zdarzeń i powiązanych klipów).

Gdy funkcja nagrywania jest wyłączona (wideo z kamery jest wyłączone):

  • Kamera może nadal być widoczna jako online zgodnie z connectivityStatetypu urządzenia.
  • Nie można uzyskać dostępu do transmisji na żywo, a kamera nie wykrywa żadnych zdarzeń w chmurze.

Sprawdzanie, czy funkcja nagrywania jest włączona

Aby sprawdzić, czy funkcja nagrywania kamery jest włączona, sprawdź, czy są aktywne jakiekolwiek połączenia. Poniższy przykład definiuje 2 funkcje, które to umożliwiają:

// Get the on/off state
suspend fun onOffState(cameraDevice: HomeDevice, cameraDeviceType) {
  // Query the device for pushAvStreamTransport
  val pushAvTrait = getPushAvStreamTransport()
  return pushAvTrait.recordModeActive()
}

// Check if the camera's recording capability is enabled
fun PushAvStreamTransport.recordModeActive(): Boolean {
  return currentConnections?.any { it.transportStatus == TransportStatusEnum.Active } ?: false
}

Innym sposobem sprawdzenia jest użycie funkcji findTransport() z predykatem:

// Fetch the current connections
suspend fun queryRecordModeState(cameraDevice: HomeDevice, cameraDeviceType) {
  val pushAvStreamTransport = getPushAvStreamTransport()
  return pushAvStreamTransport.findTransport().let {
      it.transportConfigurations.any { it.transportStatus == TransportStatusEnum.Active
    }
}

Ustawienia dźwięku

Różnymi ustawieniami dźwięku kamery można sterować za pomocą interfejsów API Home.

Włączanie i wyłączanie mikrofonu

Aby włączyć lub wyłączyć mikrofon urządzenia, zaktualizuj atrybut microphoneMuted cechy CameraAvStreamManagement za pomocą wbudowanej funkcji setMicrophoneMuted w języku Kotlin:

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

Włączanie i wyłączanie nagrywania dźwięku

Aby włączyć lub wyłączyć nagrywanie dźwięku na urządzeniu, zaktualizuj atrybut recordingMicrophoneMuted cechy CameraAvStreamManagement za pomocą wbudowanej funkcji setRecordingMicrophoneMuted w języku Kotlin:

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

Dostosowywanie głośności głośnika

Aby dostosować głośność głośnika urządzenia, zaktualizuj atrybut speakerVolumeLevel cechy CameraAvStreamManagement za pomocą wbudowanej funkcji setSpeakerVolumeLevel w języku Kotlin:

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

Inne ustawienia

Za pomocą interfejsów API Home można sterować różnymi innymi ustawieniami kamery.

Włączanie i wyłączanie widzenia w nocy

Aby włączyć lub wyłączyć tryb nocny w przypadku kamery, użyj TriStateAutoEnum, aby zaktualizować atrybut nightVision cechy CameraAvStreamManagement za pomocą wbudowanej funkcji setNightVision Kotlin:

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

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

Zmiana jasności diody LED stanu

Aby zmienić jasność diody LED stanu, użyj ThreeLevelAutoEnum do zaktualizowania atrybutu statusLightBrightness cechy CameraAvStreamManagement za pomocą wbudowanej funkcji 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)
}

Zmiana widocznego obszaru kamery

Widok z kamery jest taki sam jak w przypadku funkcji powiększania i kadrowania opisanej w artykule pomocy Powiększanie i ulepszanie obrazu z kamery Nest.

Obszar wyświetlania jest zdefiniowany w ViewportStruct, który zawiera 4 wartości używane jako współrzędne obszaru wyświetlania. Współrzędne są zdefiniowane w ten sposób:

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

Określanie wartości parametru ViewportStruct zależy od interfejsu aplikacji i implementacji kamery. Aby ustawić pole widzenia kamery wideo na bardzo podstawowym poziomie, zaktualizuj atrybut viewport cechy CameraAvStreamManagement za pomocą ViewportStruct, używając wbudowanej funkcji setViewport w języku 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(),
    )
) }

Dostosowywanie czułości wybudzania urządzenia

Czułość wybudzania urządzenia służy do oszczędzania baterii poprzez zmniejszenie zakresu, w którym urządzenie może wykrywać aktywność, i wydłużenie czasu wybudzania po wykryciu tej aktywności.

W interfejsach Home API można to ustawić za pomocą właściwości motionSensitivity elementu triggerOptionstransportOptions urządzenia. Te opcje są zdefiniowane w PushAvStreamTransport dla każdego urządzenia.

Czułość wybudzania można ustawić tylko na te wartości:

  • 1 = Niski
  • 5 = Średni
  • 10 = Wysoki

Aby zaktualizować konfigurację, znajdź konfigurację transportu dla aktywnych strumieni nagrywania za pomocą polecenia findTransport, a następnie zmodyfikuj konfigurację, podając nową wartość czułości za pomocą polecenia 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,
      )
    }
  }

Dostosowywanie maksymalnego czasu trwania zdarzenia

Maksymalna długość zdarzenia to czas, przez jaki kamera będzie nagrywać klip w przypadku zdarzenia. Za pomocą interfejsów Home API można skonfigurować dla każdego urządzenia te same długości, co w przypadku Google Home app (GHA), w odstępach sekund:

  • 10 sekund
  • 15 sekund
  • 30 sekund
  • 60 sekund (1 minuta)
  • 120 sekund (2 minuty)
  • 180 sekund (3 minuty)

W interfejsach Home API można to ustawić za pomocą właściwości motionTimeControl elementu triggerOptionstransportOptions urządzenia. Te opcje są zdefiniowane w PushAvStreamTransport dla każdego urządzenia.

Aby zaktualizować konfigurację, znajdź konfigurację transportu dla aktywnych strumieni nagrywania za pomocą polecenia findTransport, a następnie zmodyfikuj konfigurację, podając nową wartość długości zdarzenia za pomocą polecenia 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,
      )
    }
  }

Ustawienia dzwonka

Różnymi ustawieniami dzwonka można sterować za pomocą interfejsów Home API.

Zmienianie dźwięku gongu

Aby zmienić dźwięk dzwonka, najpierw pobierz listę dźwięków dzwonka zainstalowanych na urządzeniu, korzystając z atrybutu installedChimeSounds cechy 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()

Następnie zaktualizuj atrybut selectedChime cechy Chime za pomocą wbudowanej funkcji setSelectedChime Kotlin:

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

Używanie zewnętrznego dzwonka

Dzwonek można skonfigurować tak, aby korzystał z zewnętrznego dzwonka, np. mechanicznego dzwonka zainstalowanego w domu. Należy to skonfigurować podczas instalacji dzwonka, aby uniknąć potencjalnych uszkodzeń zewnętrznego dzwonka.

Aby wskazać typ zainstalowanego dzwonka zewnętrznego, użyj ExternalChimeType do zaktualizowania atrybutu externalChime cechy Chime za pomocą wbudowanej funkcji setExternalChime Kotlin:

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

Zmiana czasu trwania zewnętrznego gongu

Czas dzwonienia zewnętrznego dzwonka w sekundach można skonfigurować za pomocą interfejsów Home API. Jeśli dzwonek zewnętrzny obsługuje czas trwania dzwonka, użytkownik może chcieć go skonfigurować.

Wartość ustawiona w tym miejscu zależy od specyfikacji zewnętrznego dzwonka i zalecanej długości dzwonka.

Aby zmienić czas trwania zewnętrznego dzwonka, zaktualizuj atrybut externalChimeDurationSeconds cechy Chime za pomocą wbudowanej funkcji setExternalChimeDurationSeconds Kotlin:

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