Leitfaden für Türklingelgeräte für Android

Der Gerätetyp „Türklingel“ wird mit zwei Attributen implementiert: PushAvStreamTransport, das den Transport von Audio- und Videostreams über Push-basierte Protokolle übernimmt, und WebRtcLiveView, das die Steuerung von Livestreams und Gegensprechen ermöglicht.

Prüfen Sie immer, ob ein Gerät Attribute und Befehle unterstützt, bevor Sie Funktionen verwenden oder versuchen, Attribute zu aktualisieren. Weitere Informationen finden Sie unter Geräte aufAndroid steuern.

Gerätetyp für Home-APIs Merkmale Kotlin-Beispiel-App Anwendungsfall

Türklingel

GoogleDoorbellDevice

home.matter.6006.types.0113

Ein Gerät, das durch einen Knopf außerhalb einer Tür betätigt wird und ein akustisches und/oder visuelles Signal erzeugt. Dadurch soll die Aufmerksamkeit einer Person erregt werden, die sich auf der anderen Seite der Tür befindet. Türklingeln können zugängliche Livestreams, Zweiwege-Audio oder Erkennungsereignisse bieten.

Erforderliche Attribute
     google PushAvStreamTransport
     google WebRtcLiveView

Türklingel

Grundlegende Informationen zu einem Gerät abrufen

Das Attribut BasicInformation enthält Informationen wie den Namen des Anbieters, die Anbieter-ID, die Produkt-ID, den Produktnamen (einschließlich Modellinformationen) und die Softwareversion für ein Gerät:

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

Seriennummer abrufen

Verwenden Sie den GetSerialNumber-Befehl des ExtendedBasicInformation-Traits, um die Seriennummer des Geräts abzurufen. Im Beispiel wird die Seriennummer in einer Variablen mit dem Namen serialNumber gespeichert:

val basicInfo: ExtendedBasicInformation = device.getTrait(ExtendedBasicInformation)
val serialNumber = basicInfo.getSerialNumber().serialNumber

Gesprochene Sprache festlegen

Mit der Methode setActiveLocale des Traits LocalizationConfiguration kannst du die aktive gesprochene Sprache eines Geräts auf ein bestimmtes Gebietsschema (z. B. „en_US“) festlegen.

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

Letzten Zeitpunkt des Cloud-Kontakts des Geräts abrufen

Verwende das Attribut lastContactTimestamp des Traits ExtendedGeneralDiagnostics, um den letzten Zeitpunkt zu ermitteln, zu dem das Gerät Kontakt mit der Cloud hatte:

fun getLastContactTimeStamp(trait: ExtendedGeneralDiagnostics): java.time.Instant {
  val timestamp = trait.lastContactTimestamp
  return Instant.ofEpochSecond(timestamp.toLong())
}

Verbindung für ein Gerät prüfen

Die Verbindung für ein Gerät wird auf Gerätetyp-Ebene geprüft, da einige Geräte mehrere Gerätetypen unterstützen. Der zurückgegebene Status ist eine Kombination der Verbindungsstatus für alle Merkmale auf diesem Gerät.

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

Der Status PARTIALLY_ONLINE kann bei gemischten Gerätetypen auftreten, wenn keine Internetverbindung besteht. Matter-Standardmerkmale sind aufgrund des lokalen Routings möglicherweise weiterhin online, cloudbasierte Merkmale sind jedoch offline.

IP-Adresse des Geräts abrufen

Verwende das Attribut networkInterfaces des Traits GeneralDiagnostics, um die IP-Adresse des Geräts zu ermitteln. Die Adressen werden als Byte-Arrays zurückgegeben, die Sie in Standard-IPv4- oder IPv6-Strings formatieren können:

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

Livestream starten

Wenn Sie einen Livestream starten möchten, senden Sie den SDP-String (Session Description Protocol) an die Methode startLiveView() des Traits WebRtcLiveView. Diese gibt ein WebRtcLiveViewTrait.StartLiveViewCommand.Response mit drei Werten zurück:

  • Das SDP für die Sitzung.
  • Die Sitzungsdauer in Sekunden.
  • Die Sitzungs-ID, die zum Verlängern oder Beenden der Sitzung verwendet werden kann.
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)

Livestream verlängern

Livestreams haben eine voreingestellte Dauer, nach der sie ablaufen. Wenn Sie die Dauer eines aktiven Streams verlängern möchten, senden Sie eine Verlängerungsanfrage mit der Methode 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 starten und beenden

Rufen Sie die Methode startTalkback() des Traits WebRtcLiveView auf, um TalkBack zu starten. Verwenden Sie stopTalkback(), um die Aufnahme zu beenden.

// Make sure camera stream is on
suspend fun setTalkback(isOn: Boolean, trait: WebRtcLiveView, mediaSessionId: String) {
  if(isOn) {
    trait.startTalkback(mediaSessionId)
  } else {
    trait.stopTalkback(mediaSessionId)
  }
}

Aufzeichnungsfunktion aktivieren und deaktivieren

Um die Aufnahmefunktion der Kamera zu aktivieren, übergeben Sie TransportStatusEnum.Active an die Methode setTransportStatus() des Traits PushAvStreamTransport. Wenn Sie die Aufnahmefunktion deaktivieren möchten, übergeben Sie TransportStatusEnum.Inactive. Im folgenden Beispiel fassen wir diese Aufrufe in einem einzigen Aufruf zusammen, der ein Boolean verwendet, um die Aufnahmefunktion zu aktivieren oder zu deaktivieren:

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

Das Aktivieren oder Deaktivieren der Aufnahmefunktion der Kamera entspricht dem Ein- oder Ausschalten des Kameravideos. Wenn das Video einer Kamera aktiviert ist, wird es für Ereignisse und zugehörige Clips aufgezeichnet.

Wenn die Aufzeichnungsfunktion deaktiviert ist (das Kameravideo ist deaktiviert):

  • Die Kamera kann gemäß dem connectivityState des Gerätetyps weiterhin als online angezeigt werden.
  • Auf den Livestream kann nicht zugegriffen werden und die Kamera erkennt keine Cloud-Ereignisse.

Prüfen, ob die Aufzeichnungsfunktion aktiviert ist

Wenn Sie feststellen möchten, ob die Aufnahmefunktion einer Kamera aktiviert ist, prüfen Sie, ob Verbindungen aktiv sind. Im folgenden Beispiel werden zwei Funktionen definiert, um dies zu tun:

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

Eine weitere Möglichkeit, dies zu prüfen, ist die Verwendung der Funktion findTransport() mit einem Prädikat:

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

Akkueinstellungen

Über die Home-APIs können verschiedene Akku-Einstellungen gesteuert werden.

Einstellung für die Akkunutzung festlegen

Mit der Einstellung für die Energiebilanz können Sie den Kompromiss zwischen Akkulaufzeit und Leistung für ein Gerät konfigurieren. Sie können verschiedene Akkuprofile erstellen, z. B. „Erweitert“, „Ausgewogen“ und „Leistung“, und zwischen ihnen wechseln.

Diese Funktion wird durch Aktualisieren des Attributs currentEnergyBalance des Traits EnergyPreference implementiert. Das Attribut akzeptiert einen Ganzzahlindex, der einem bestimmten Profil in der energyBalances-Liste des Geräts entspricht (z. B. 0 für EXTENDED, 1 für BALANCED und 2 für PERFORMANCE).

Ein null-Wert für currentEnergyBalance gibt an, dass das Gerät ein benutzerdefiniertes Profil verwendet. Dies ist ein schreibgeschützter Status.

Im Folgenden sehen Sie ein Beispiel für eine Struktur, die vom Attribut currentEnergyBalance verwendet wird, gefolgt vom tatsächlichen Code-Snippet, in dem das Attribut verwendet wird.

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

Automatischen Energiesparmodus aktivieren

Aktualisieren Sie das Attribut currentLowPowerModeSensitivity des Traits EnergyPreference, um diese Funktion zu konfigurieren. Für dieses Attribut wird ein Index verwendet, um eine Vertraulichkeitsstufe auszuwählen. Dabei steht 0 in der Regel für Disabled und 1 für Enabled oder 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) }
}

Akkuladestatus abrufen

Verwende das Attribut batChargeState des Trait PowerSource, um den aktuellen Ladestatus des Geräts abzurufen (wird geladen, vollständig geladen oder wird nicht geladen).

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

Akkustand abrufen

Verwende das Attribut batChargeLevel des Traits PowerSource, um den aktuellen Akkustand abzurufen. Der Wert ist entweder OK, Warning (niedrig) oder 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"
}

Stromquelle

Verwende die Attribute BatPresent und wiredPresent des Traits PowerSource, um die Stromquelle des Geräts zu ermitteln.

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

Audioeinstellungen

Über die Home-APIs lassen sich verschiedene Audioeinstellungen steuern.

Mikrofon ein- und ausschalten

Um das Mikrofon des Geräts zu aktivieren oder zu deaktivieren, aktualisieren Sie das Attribut microphoneMuted des Traits CameraAvStreamManagement mit der integrierten Kotlin-Funktion setMicrophoneMuted:

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

Audioaufnahme ein- oder ausschalten

Wenn Sie die Audioaufnahme für das Gerät aktivieren oder deaktivieren möchten, aktualisieren Sie das Attribut recordingMicrophoneMuted des Traits CameraAvStreamManagement mit der integrierten Kotlin-Funktion setRecordingMicrophoneMuted:

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

Lautsprecherlautstärke anpassen

Wenn Sie die Lautstärke des Lautsprechers für das Gerät anpassen möchten, aktualisieren Sie das Attribut speakerVolumeLevel des Traits CameraAvStreamManagement mit der integrierten Kotlin-Funktion setSpeakerVolumeLevel:

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

Einstellungen für Alarmbereiche

Das ZoneManagement-Merkmal bietet eine Schnittstelle zum Verwalten benutzerdefinierter interessanter Bereiche (Alarmbereiche) auf Kamera- und Türklingelgeräten. Mit diesen Zonen kann die Ereigniserkennung (z. B. Bewegung von Personen oder Fahrzeugen) auf bestimmte Bereiche im Sichtfeld des Geräts gefiltert werden.

Alarmbereiche werden vom Nutzer in einer Partneranwendung konfiguriert. Er kann Bereiche im Sichtfeld der Kamera markieren. Diese benutzerdefinierten Zonen werden dann in die Strukturen übersetzt, die von diesem Merkmal verwendet werden. Weitere Informationen zur Funktionsweise von Alarmbereichen findest du unter Alarmbereiche einrichten und verwenden.

Alarmbereiche werden in der Regel mit 2D-kartesischen Koordinaten definiert. Das Attribut stellt die TwoDCartesianVertexStruct für Eckpunkte und die TwoDCartesianZoneStruct für die Zonendefinition (Name, Eckpunkte, Farbe und Verwendung) bereit.

Alarmbereiche prüfen

Wenn Sie Alarmbereiche anzeigen möchten, prüfen Sie das Attribut zones des Traits 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()
  }

Alarmbereich hinzufügen

Verwenden Sie zum Erstellen einer neuen Zone den Befehl createTwoDCartesianZone. Dieser Befehl verwendet ein TwoDCartesianZoneStruct, das den Namen, die Eckpunkte, die Farbe und die Verwendung der Zone definiert.

Im folgenden Beispiel wird eine Zone mit dem Namen „Front Porch“ (Veranda) mit vier Eckpunkten erstellt, die lachsfarben (#F439A0) ist und für die Bewegungserkennung verwendet wird.

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

Alarmbereich aktualisieren

Verwenden Sie den Befehl updateTwoDCartesianZone, um eine vorhandene Zone zu aktualisieren. Für diesen Befehl sind die zoneId und die aktualisierte TwoDCartesianZoneStruct erforderlich.

private suspend fun ZoneManagement.updateZone(
  zoneId: UShort,
  zone: ZoneManagementTrait.TwoDCartesianZoneStruct
) {
  // Execute the command to update the zone
  this.updateTwoDCartesianZone(zoneId = zoneId, zone = zone)
}

Alarmbereich löschen

Verwenden Sie zum Entfernen einer Zone den Befehl removeZone mit dem entsprechenden zoneId.

private suspend fun ZoneManagement.deleteZone(zoneId: UShort) {
  // Execute the command to remove the zone
  this.removeZone(zoneId = zoneId)
}

Trigger für Geräuschereignisse

Das Attribut AvStreamAnalysis bietet eine Schnittstelle zum Verwalten von Triggern für die Ereigniserkennung auf Kamera- und Türklingelgeräten. Während sichtbasierte Auslöser (z. B. Personen oder Fahrzeuge) zonenbezogen sein können, sind tonbezogene Auslöser in der Regel Konfigurationen auf Geräteebene.

Für die Geräuscherkennung mit dem EventTriggerTypeEnum sind die folgenden Triggertypen verfügbar:

Modus Enum-Wert Beschreibung
Ton Sound Allgemeine Geräuscherkennung.
Sprechende Person PersonTalking Erkennt Sprache.
Hundegebell DogBark Erkennt Hundegebell.
Zerbrechendes Glas GlassBreak Erkennt das Geräusch von zerbrechendem Glas.
Rauchalarm SmokeAlarm Erkennt Rauchmelder, die oft am T3-Signal (drei kurze Pieptöne gefolgt von einer Pause) zu erkennen sind.
Kohlenmonoxidalarm CoAlarm Erkennt Kohlenmonoxid-Alarme (CO-Alarme), die in der Regel am T4-Signal erkannt werden (vier kurze Signaltöne, gefolgt von einer Pause).

Status der Geräuscherkennung prüfen

Um dem Nutzer den aktuellen Zustand der Geräuscherkennung anzuzeigen, müssen Sie prüfen, was das Gerät unterstützt und was von der Gerätehardware aktiviert wird. Die beiden Attribute, die Sie prüfen sollten, sind:

Bei der Android-Entwicklung mit Kotlin-Flows wird das AvStreamAnalysis-Merkmal in der Regel über HomeDevice beobachtet.

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

Aktivierte Trigger aktualisieren

Verwenden Sie den Befehl SetOrUpdateEventDetectionTriggers, der eine Liste von EventTriggerEnablement-Strukturen akzeptiert, um die Gruppe der aktivierten Trigger zu aktualisieren.

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

Aufnahmemodi

Das RecordingMode-Trait bietet eine Schnittstelle zum Verwalten des Verhaltens bei der Video- und Bildaufzeichnung auf Kamera- und Türklingelgeräten. Nutzer können zwischen der Videoaufzeichnung rund um die Uhr, dem ereignisbasierten Videoverlauf oder der vollständigen Deaktivierung der Aufzeichnung (nur Live-Ansicht) wählen.

Der Enum-Wert RecordingModeEnum definiert die verfügbaren Aufzeichnungsstrategien:

Modus Enum-Wert Beschreibung
Deaktiviert Disabled Die Aufzeichnung ist vollständig deaktiviert. Wird hauptsächlich von älteren Geräten verwendet.
CVR (Videoaufzeichnung rund um die Uhr) Cvr Videos werden rund um die Uhr aufgezeichnet. Abo erforderlich (z. B. Google Home Premium).
EBR (Event Based Recording, ereignisbasierter Videoverlauf) Ebr Die Aufzeichnung wird durch Ereignisse (Person, Bewegung) ausgelöst. Die Videolänge hängt von der Dauer des Events und dem Abo ab.
ETR (Event Triggered Recording, ereignisbasierte Aufzeichnung) Etr Kurze Vorschauaufnahmen (z. B. 10 Sekunden), die durch Ereignisse ausgelöst werden.
Live View LiveView Die Aufzeichnung ist deaktiviert, Nutzer können aber weiterhin auf den Livestream zugreifen.
Standbilder Images Bei Ereignissen werden Momentaufnahmen anstelle von Videos aufgezeichnet.

Aufnahmemodi prüfen

Die aktuelle Aufzeichnungskonfiguration wird in den Attributen des Traits RecordingMode angezeigt:

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

Aufnahmemodus ändern

Prüfen Sie vor dem Aktualisieren, ob der ausgewählte Index aus dem Attribut supportedRecordingModes im Attribut availableRecordingModes vorhanden ist.

Verwenden Sie die Funktion setSelectedRecordingMode, um den ausgewählten Modus zu aktualisieren. Übergeben Sie dazu den Index des ausgewählten Modus:

private suspend fun RecordingMode.updateRecordingMode(index: Int) {
    // Execute the command to update the selected mode
    this.setSelectedRecordingMode(index.toUByte())
}

Weitere Einstellungen

Über die Home-APIs lassen sich verschiedene andere Einstellungen steuern.

Nachtsichtmodus aktivieren oder deaktivieren

Wenn du die Nachtsicht für die Kamera aktivieren oder deaktivieren möchtest, verwende TriStateAutoEnum, um das Attribut nightVision des Traits CameraAvStreamManagement mit der integrierten Kotlin-Funktion setNightVision zu aktualisieren:

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

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

Helligkeit der Status-LED ändern

Wenn Sie die Helligkeit der Status-LED ändern möchten, verwenden Sie ThreeLevelAutoEnum, um das Attribut statusLightBrightness des Traits CameraAvStreamManagement mit der integrierten Kotlin-Funktion setStatusLightBrightness zu aktualisieren:

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

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

Kamera-Darstellungsbereich ändern

Die Kameraansicht entspricht der Funktion „Zoomen und zuschneiden“, die im Hilfeartikel zum Zoomen und Optimieren von Nest-Kameravideos beschrieben wird.

Der Viewport wird in einem ViewportStruct definiert, das vier Werte enthält, die als Koordinaten des Viewports verwendet werden. Die Koordinaten sind so definiert:

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

Die Werte für ViewportStruct hängen von der Benutzeroberfläche und der Kameraimplementierung einer App ab. Um den Viewport des Kameravideos festzulegen, müssen Sie das Attribut viewport des Traits CameraAvStreamManagement mit einem ViewportStruct aktualisieren. Verwenden Sie dazu die integrierte Kotlin-Funktion setViewport:

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

Analyse aktivieren oder deaktivieren

Jedes Gerät kann einzeln zustimmen, detaillierte Analysedaten an die Google Home-Cloud zu senden (siehe Cloud Monitoring for Home APIs).

Wenn Sie die Analyse für ein Gerät aktivieren möchten, legen Sie die Eigenschaft analyticsEnabled von ExtendedGeneralDiagnosticsTrait auf true fest. Wenn Sie analyticsEnabled festlegen, wird automatisch eine weitere Property, logUploadEnabled, auf true gesetzt. Dadurch können die Analyselogdateien in die Google Home-Cloud hochgeladen werden.

// Enable analytics
extendedGeneralDiagnostics.update {
  setAnalyticsEnabled(true)
}

// Disable analytics
extendedGeneralDiagnostics.update {
  setAnalyticsEnabled(false)
}

Transport- und Aufnahmekonfigurationen

In diesem Abschnitt werden Einstellungen für die Streamingqualität der Kamera und die Ereignisauslösung behandelt. Diese Einstellungen werden über das Merkmal PushAvStreamTransport verwaltet.

Transporteinstellungen lesen

In diesem Abschnitt wird gezeigt, wie Sie die aktuelle Konfiguration eines Kamera- oder Türklingelgeräts abrufen. Es ruft das PushAvStreamTransport-Trait ab, sucht nach der für die Aufzeichnung verwendeten Verbindung und extrahiert dann die aktuellen Werte für Bandbreitenqualität, Empfindlichkeit für die Beendigung des Ruhemodus und maximale Ereignislänge.

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

Transporteinstellungen aktualisieren

In diesem Abschnitt wird beschrieben, wie Sie die Transporteinstellungen ändern. Dabei wird ein neues TransportOptionsStruct mit den neuen Werten erstellt und dann mit dem Befehl modifyPushTransport an das Gerät gesendet. Die aktualisierten Einstellungen werden auf die im vorherigen Schritt gefundene Aufzeichnungsverbindung angewendet.

Verwenden Sie den Befehl modifyPushTransport mit einem TransportOptionsStruct, um diese Einstellungen zu ändern.

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

Bandbreitenqualität ermitteln

Die Eigenschaft videoStreamId des TransportOptionsStruct entspricht einer bestimmten Videostreamkonfiguration.

Die unterstützten Videostreams finden Sie im Attribut allocatedVideoStreams, das eine Liste von VideoStreamStructs ist. aus dem CameraAvStreamManagement-Trait für das Gerät.

Empfindlichkeit für die Beendigung des Ruhemodus anpassen

Das Attribut motionSensitivity des TransportTriggerOptionsStruct entspricht den folgenden Werten:

Label Wert (UByte)
Niedrig 1 Einheit
Mittel 5u
Hoch 10u

Maximale Ereignisdauer anpassen

Die maxDuration-Property von TransportMotionTriggerTimeControlStruct entspricht den folgenden Zeiträumen (in Sekunden):

  • 10u, 15u, 30u, 60u, 120u, 180u

Glockeneinstellungen

Über die Home-APIs lassen sich verschiedene Einstellungen für den Glockenton der Türklingel steuern.

Glockenton ändern

Wenn Sie den Klingelton der Türklingel ändern möchten, rufen Sie zuerst die Liste der Klingeltöne ab, die auf dem Gerät installiert sind. Verwenden Sie dazu das Attribut installedChimeSounds des Traits 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()

Aktualisieren Sie dann das Attribut selectedChime des Traits Chime mit der integrierten Kotlin-Funktion setSelectedChime:

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

Externe Glocke verwenden

Die Türklingel kann so konfiguriert werden, dass sie eine externe Glocke verwendet, z. B. eine mechanische Glocke im Haus. Dies sollte bei der Installation der Türklingel konfiguriert werden, um potenzielle Schäden an der externen Glocke zu vermeiden.

Um anzugeben, welcher Typ von externem Gong installiert ist, verwenden Sie ExternalChimeType, um das Attribut externalChime des Chime-Traits mit der integrierten Kotlin-Funktion setExternalChime zu aktualisieren:

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

Dauer des externen Glockentons ändern

Die Dauer, in Sekunden, die ein externer Gong klingelt, kann über die Home-APIs konfiguriert werden. Wenn die externe Glocke eine Dauer für den Glockenton unterstützt, kann der Nutzer diese konfigurieren.

Der hier festgelegte Wert hängt von den Spezifikationen des externen Gonges und der empfohlenen Gongdauer ab.

Wenn Sie die Dauer des externen Glockentons ändern möchten, aktualisieren Sie das Attribut externalChimeDurationSeconds des Traits Chime mit der integrierten Kotlin-Funktion setExternalChimeDurationSeconds:

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

Klingelton-Design aktivieren

Einige Türklingeln haben möglicherweise Klingeltöne, die Nutzern nur für begrenzte Zeit zur Verfügung stehen. Das können beispielsweise Glockenspiele für Feiertage sein. Sie werden als Glockenspiel-Themen bezeichnet.

Wenn Sie sehen möchten, welche Chime-Designs für einen Nutzer verfügbar sind, erstellen Sie einen Timebox-Filter und verwenden Sie ihn, um die Ergebnisse des Befehls getAvailableThemes() aus dem Trait ChimeThemes zu filtern. Daraufhin wird eine Liste der verfügbaren Designs mit den jeweiligen Namen zurückgegeben.

Im folgenden Beispiel wird gezeigt, wie die Liste gefiltert wird. Ein Thema gilt als aktiv, wenn die aktuelle Zeit innerhalb des Start- und Endzeitpunkts liegt (die Werte startTimeSeconds bzw. endTimeSeconds). Wenn keine Startzeit festgelegt ist, gilt sie als von Anfang an aktiv. Wenn keine Endzeit festgelegt ist, bleibt sie auf unbestimmte Zeit aktiv. Wenn beide fehlen, ist das Design immer aktiv.

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

Sobald Sie den Namen des gewünschten Designs haben, z. B. Christmas, können Sie es mit der Funktion setSelectedTimeboxedThemeName() für das Merkmal ChimeThemes auswählen:

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