คู่มืออุปกรณ์กริ่งประตูสำหรับ Android

ประเภทอุปกรณ์กริ่งประตูจะใช้งานโดยใช้ลักษณะ 2 อย่าง PushAvStreamTransport ซึ่งจัดการการรับส่งสตรีมเสียงและวิดีโอโดยใช้โปรโตคอลแบบพุช และ WebRtcLiveView ซึ่งช่วยให้ควบคุมสตรีมแบบสดและฟีเจอร์ Talkback ได้

โปรดตรวจสอบการรองรับแอตทริบิวต์และคำสั่งของอุปกรณ์เสมอก่อนที่จะใช้ฟีเจอร์หรือพยายามอัปเดตแอตทริบิวต์ ดูข้อมูลเพิ่มเติมได้ที่ควบคุมอุปกรณ์ใน Android

ประเภทอุปกรณ์ API สำหรับ Home ลักษณะ แอปตัวอย่าง Kotlin กรณีการใช้งาน

กริ่งประตู

GoogleDoorbellDevice

home.matter.6006.types.0113

อุปกรณ์ที่ทำงานด้วยปุ่มนอกประตูซึ่งส่งสัญญาณเสียงและ/หรือภาพ ใช้เพื่อขอความสนใจจากบุคคลที่อยู่ด้านในประตู กริ่งประตูอาจมีสตรีมแบบสดที่เข้าถึงได้ การโต้ตอบด้วยเสียงแบบ 2 ทาง หรือเหตุการณ์การตรวจจับ

ลักษณะที่ต้องระบุ
     google PushAvStreamTransport
     google WebRtcLiveView

กริ่งประตู

ดูข้อมูลพื้นฐานเกี่ยวกับอุปกรณ์

ลักษณะ BasicInformation ประกอบด้วยข้อมูลต่างๆ เช่น ชื่อผู้ให้บริการ รหัสผู้ให้บริการ รหัสผลิตภัณฑ์ ชื่อผลิตภัณฑ์ (รวมถึงข้อมูลรุ่น) และเวอร์ชันซอฟต์แวร์ของอุปกรณ์

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

รับหมายเลขซีเรียล

หากต้องการรับหมายเลขซีเรียลของอุปกรณ์ ให้ใช้คำสั่ง GetSerialNumber ของลักษณะ ExtendedBasicInformation ตัวอย่างแสดงการบันทึกหมายเลขซีเรียลในตัวแปรชื่อ serialNumber

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

ตั้งค่าภาษาที่พูด

ตั้งค่าภาษาที่พูดที่ใช้งานอยู่ของอุปกรณ์เป็นภาษาเฉพาะ (เช่น "en_US") โดยใช้setActiveLocaleเมธอดของลักษณะ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)
}

รับเวลาล่าสุดที่อุปกรณ์ติดต่อกับระบบคลาวด์

หากต้องการดูเวลาล่าสุดที่อุปกรณ์ติดต่อกับระบบคลาวด์ ให้ใช้lastContactTimestampแอตทริบิวต์ของลักษณะExtendedGeneralDiagnostics ดังนี้

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

ตรวจสอบการเชื่อมต่อสำหรับอุปกรณ์

ระบบจะตรวจสอบการเชื่อมต่อของอุปกรณ์ที่ระดับประเภทอุปกรณ์เนื่องจาก อุปกรณ์บางเครื่องรองรับอุปกรณ์หลายประเภท สถานะที่ส่งคืนคือ การรวมสถานะการเชื่อมต่อสำหรับลักษณะทั้งหมดในอุปกรณ์นั้น

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

สถานะ PARTIALLY_ONLINE อาจปรากฏในกรณี ของอุปกรณ์หลายประเภทเมื่อไม่มีการเชื่อมต่ออินเทอร์เน็ต Matter ลักษณะมาตรฐานอาจยังคงออนไลน์อยู่เนื่องจากการกำหนดเส้นทางในพื้นที่ แต่ลักษณะที่อิงตามระบบคลาวด์จะออฟไลน์

รับที่อยู่ IP ของอุปกรณ์

หากต้องการค้นหาที่อยู่ IP ของอุปกรณ์ ให้ใช้แอตทริบิวต์ networkInterfaces ของลักษณะ GeneralDiagnostics ระบบจะแสดงที่อยู่เป็นอาร์เรย์ไบต์ ซึ่งคุณจัดรูปแบบเป็นสตริง IPv4 หรือ IPv6 มาตรฐานได้

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

เริ่มไลฟ์สด

หากต้องการเริ่มไลฟ์สด ให้ส่งสตริง Session Description Protocol (SDP) ไปยังเมธอด WebRtcLiveView ของลักษณะ startLiveView() ซึ่งจะแสดงผล WebRtcLiveViewTrait.StartLiveViewCommand.Response ที่มีค่า 3 ค่า ได้แก่

  • SDP สำหรับเซสชัน
  • ระยะเวลาเซสชันเป็นวินาที
  • รหัสเซสชัน ซึ่งอาจใช้เพื่อขยายหรือสิ้นสุดเซสชัน
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 ให้เรียกใช้เมธอด startTalkback() ของลักษณะ WebRtcLiveView หากต้องการหยุด ให้ใช้ 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 ไปยังเมธอด setTransportStatus() ของลักษณะ PushAvStreamTransport หากต้องการปิดใช้ความสามารถในการบันทึก ให้ส่ง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ของ ประเภทอุปกรณ์
  • เข้าถึงไลฟ์สดไม่ได้ และกล้องไม่ตรวจพบเหตุการณ์ในระบบคลาวด์

ตรวจสอบว่าได้เปิดใช้ความสามารถในการบันทึกแล้ว

หากต้องการดูว่าเปิดใช้ความสามารถในการบันทึกของกล้องหรือไม่ ให้ตรวจสอบว่ามีการเชื่อมต่อที่ใช้งานอยู่หรือไม่ ตัวอย่างต่อไปนี้กำหนดฟังก์ชัน 2 รายการเพื่อดำเนินการนี้

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

ตั้งค่ากำหนดการใช้งานแบตเตอรี่

การตั้งค่าสมดุลพลังงานช่วยให้คุณกำหนดค่าการแลกเปลี่ยนระหว่างระยะเวลาการใช้งานแบตเตอรี่กับประสิทธิภาพของอุปกรณ์ได้ คุณสร้างโปรไฟล์แบตเตอรี่ต่างๆ ได้ เช่น "ขยายเวลา" "สมดุล" และ "ประสิทธิภาพ" แล้วสลับไปมาระหว่างโปรไฟล์เหล่านั้นได้

ฟีเจอร์นี้ใช้งานได้โดยการอัปเดตแอตทริบิวต์ currentEnergyBalance ของลักษณะ EnergyPreference แอตทริบิวต์นี้ยอมรับดัชนีจำนวนเต็ม ที่สอดคล้องกับโปรไฟล์ที่เฉพาะเจาะจงซึ่งกำหนดไว้ในรายการ energyBalances ของอุปกรณ์ (เช่น 0 สำหรับ EXTENDED, 1 สำหรับ BALANCED และ 2 สำหรับ PERFORMANCE)

null ค่าสำหรับ currentEnergyBalance แสดงว่าอุปกรณ์ใช้โปรไฟล์ที่กำหนดเอง นี่เป็นสถานะแบบอ่านอย่างเดียว

ต่อไปนี้คือตัวอย่างโครงสร้างที่แอตทริบิวต์ 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)

เปิดโหมดประหยัดแบตเตอรี่อัตโนมัติ

หากต้องการกำหนดค่าฟีเจอร์นี้ ให้อัปเดตแอตทริบิวต์ currentLowPowerModeSensitivity ของลักษณะ EnergyPreference แอตทริบิวต์นี้ใช้ดัชนี เพื่อเลือกระดับความละเอียด โดยที่ 0 มักจะแสดง Disabled และ 1 แสดง Enabled หรือ 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) }
}

รับสถานะการชาร์จแบตเตอรี่

หากต้องการดูสถานะการชาร์จปัจจุบันของอุปกรณ์ (กำลังชาร์จ ชาร์จเต็มแล้ว หรือไม่ได้ชาร์จ) ให้ใช้แอตทริบิวต์ batChargeState ของลักษณะ 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"
}

ดูระดับแบตเตอรี่

หากต้องการดูระดับแบตเตอรี่ปัจจุบัน ให้ใช้แอตทริบิวต์ batChargeLevel ของลักษณะ PowerSource ระดับจะเป็น OK, Warning (ต่ำ) หรือ 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"
}

เตรียมแหล่งจ่ายไฟ

หากต้องการระบุแหล่งพลังงานที่อุปกรณ์ใช้ ให้ใช้แอตทริบิวต์ BatPresent และ wiredPresent ของลักษณะ PowerSource

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

การตั้งค่าเสียง

คุณควบคุมการตั้งค่าเสียงต่างๆ ได้ผ่าน Home API

เปิดหรือปิดไมโครโฟน

หากต้องการเปิดหรือปิดไมโครโฟนของอุปกรณ์ ให้อัปเดตแอตทริบิวต์ microphoneMuted ของลักษณะ CameraAvStreamManagement โดยใช้ฟังก์ชัน Kotlin setMicrophoneMuted ในตัว ดังนี้

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

เปิดหรือปิดการบันทึกเสียง

หากต้องการเปิดหรือปิดเสียงที่บันทึกไว้สำหรับอุปกรณ์ ให้อัปเดตแอตทริบิวต์ recordingMicrophoneMuted ของลักษณะCameraAvStreamManagementโดยใช้ฟังก์ชัน Kotlin setRecordingMicrophoneMuted ในตัว ดังนี้

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

ปรับระดับเสียงของลำโพง

หากต้องการปรับระดับเสียงของลำโพงสำหรับอุปกรณ์ ให้อัปเดตแอตทริบิวต์ speakerVolumeLevel ของลักษณะ CameraAvStreamManagement โดยใช้ฟังก์ชัน Kotlin setSpeakerVolumeLevel ในตัว ดังนี้

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

การตั้งค่าโซนตรวจจับกิจกรรม

ZoneManagement ลักษณะนี้มีอินเทอร์เฟซสำหรับจัดการภูมิภาคที่กำหนดเองที่สนใจ (โซนตรวจจับกิจกรรม) ในอุปกรณ์กล้องและกริ่งประตู ระบบจะใช้โซนเหล่านี้เพื่อกรองการตรวจหาเหตุการณ์ (เช่น การเคลื่อนไหวของบุคคล หรือยานพาหนะ) ไปยังพื้นที่ที่เฉพาะเจาะจงภายในขอบเขตการมองเห็นของอุปกรณ์

ผู้ใช้จะกำหนดค่าโซนตรวจจับกิจกรรมได้ภายในแอปพลิเคชันพาร์ทเนอร์ ซึ่งจะช่วยให้วาดโซนเหนือพื้นที่ที่เฉพาะเจาะจงในขอบเขตการมองเห็นของกล้องได้ จากนั้นระบบจะแปลโซนที่ผู้ใช้กำหนดเหล่านี้เป็นโครงสร้างที่ลักษณะนี้ใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของโซนตรวจจับกิจกรรมได้ที่ตั้งค่าและใช้โซนตรวจจับกิจกรรม

โดยปกติแล้ว โซนตรวจจับกิจกรรมจะกำหนดโดยใช้พิกัดคาร์ทีเซียน 2 มิติ ลักษณะนี้ระบุ TwoDCartesianVertexStructสำหรับจุดยอดและ TwoDCartesianZoneStruct สำหรับการกำหนดโซน (ชื่อ จุดยอด สี และการใช้งาน)

ตรวจสอบโซนตรวจจับกิจกรรม

หากต้องการแสดงโซนตรวจจับกิจกรรม ให้ตรวจสอบแอตทริบิวต์ zones ของลักษณะ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()
  }

เพิ่มโซนตรวจจับกิจกรรม

หากต้องการสร้างโซนใหม่ ให้ใช้คำสั่ง createTwoDCartesianZone คำสั่งนี้ใช้ TwoDCartesianZoneStruct ซึ่งกำหนดชื่อ จุดยอด สี และการใช้งานของโซน

ตัวอย่างต่อไปนี้แสดงวิธีสร้างโซนชื่อ "Front Porch" ที่มีจุดยอด 4 จุด เป็นสีแซลมอน (#F439A0) และใช้สำหรับการตรวจจับการเคลื่อนไหว

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

อัปเดตโซนตรวจจับกิจกรรม

หากต้องการอัปเดตโซนที่มีอยู่ ให้ใช้คำสั่ง updateTwoDCartesianZone คำสั่งนี้ต้องใช้ zoneId และ TwoDCartesianZoneStruct ที่อัปเดตแล้ว

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

ลบโซนตรวจจับกิจกรรม

หากต้องการนำโซนออก ให้ใช้คำสั่ง removeZone พร้อมด้วย zoneId ที่เฉพาะเจาะจง

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

ทริกเกอร์เหตุการณ์ที่มีเสียง

AvStreamAnalysis ลักษณะนี้มีอินเทอร์เฟซสำหรับการจัดการทริกเกอร์การตรวจจับเหตุการณ์ ในอุปกรณ์กล้องและกริ่งประตู แม้ว่าทริกเกอร์ที่อิงตามวิสัยทัศน์ (เช่น ผู้คนหรือยานพาหนะ) จะเฉพาะเจาะจงโซนได้ แต่โดยทั่วไปแล้วทริกเกอร์ที่เกี่ยวข้องกับเสียง จะเป็นการกำหนดค่าระดับอุปกรณ์

ทริกเกอร์ประเภทต่อไปนี้ใช้ได้กับการตรวจจับเสียงด้วย EventTriggerTypeEnum

โหมด ค่า enum คำอธิบาย
เสียง Sound การตรวจจับเสียงทั่วไป
คนพูดคุย PersonTalking ตรวจจับคำพูด
เสียงสุนัขเห่า DogBark ตรวจจับเสียงร้องของสุนัข
กระจกแตก GlassBreak ตรวจจับเสียงกระจกแตก
สัญญาณเตือนควัน SmokeAlarm ตรวจจับสัญญาณเตือนควัน ซึ่งมักจะจดจำได้จากรูปแบบเสียงที่ได้ยิน T3 (เสียงบี๊บสั้นๆ 3 ครั้งแล้วหยุด)
สัญญาณเตือนคาร์บอนมอนอกไซด์ CoAlarm ตรวจจับสัญญาณเตือนคาร์บอนมอนอกไซด์ (CO) ซึ่งโดยทั่วไปจะ สังเกตได้จากรูปแบบเสียงที่ได้ยินของ T4 (เสียงบี๊บสั้นๆ 4 ครั้ง ตามด้วยการหยุดชั่วคราว)

ตรวจสอบสถานะการตรวจจับเสียง

หากต้องการแสดงสถานะปัจจุบันของการตรวจจับเสียงต่อผู้ใช้ คุณต้องตรวจสอบ สิ่งที่อุปกรณ์รองรับและสิ่งที่ฮาร์ดแวร์ของอุปกรณ์เปิดใช้ แอตทริบิวต์ 2 รายการที่ต้องตรวจสอบมีดังนี้

ในการพัฒนา Android โดยใช้ Kotlin Flow คุณมักจะสังเกตAvStreamAnalysis ลักษณะจาก 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)
        )
      }
  }

อัปเดตชุดทริกเกอร์ที่เปิดใช้

หากต้องการอัปเดตชุดทริกเกอร์ที่เปิดใช้ ให้ใช้คำสั่ง SetOrUpdateEventDetectionTriggers ซึ่งรับรายการโครงสร้าง 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)
}

โหมดการบันทึก

คุณลักษณะ RecordingMode มีอินเทอร์เฟซสำหรับจัดการลักษณะการทำงานของการบันทึกวิดีโอและรูปภาพในอุปกรณ์กล้องและกริ่งประตู ซึ่งช่วยให้ผู้ใช้เลือกระหว่างการบันทึกต่อเนื่อง การบันทึกเมื่อเกิดเหตุการณ์ หรือปิดใช้การบันทึกทั้งหมด (เฉพาะมุมมองสด)

RecordingModeEnum กำหนดกลยุทธ์การบันทึกที่ใช้ได้ ดังนี้

โหมด ค่า enum คำอธิบาย
ปิดใช้แล้ว Disabled ปิดใช้การบันทึกโดยสมบูรณ์ อุปกรณ์รุ่นเดิมใช้เป็นหลัก
CVR (การบันทึกวิดีโอต่อเนื่อง) Cvr บันทึกวิดีโอทุกวันตลอด 24 ชั่วโมง ต้องมีการสมัครใช้บริการ (เช่น Google Home Premium
EBR (การบันทึกเมื่อเกิดเหตุการณ์) Ebr การบันทึกจะทริกเกอร์โดยเหตุการณ์ (บุคคล การเคลื่อนไหว) ความยาววิดีโอจะขึ้นอยู่กับระยะเวลาของกิจกรรมและการสมัครใช้บริการ
ETR (การบันทึกเมื่อเกิดเหตุการณ์) Etr การบันทึกตัวอย่าง Shorts (เช่น 10 วินาที) ที่ทริกเกอร์โดยเหตุการณ์
ดูภาพสด LiveView ระบบจะปิดใช้การบันทึก แต่ผู้ใช้จะยังเข้าถึงไลฟ์สดได้
ภาพนิ่ง Images ระบบจะบันทึกสแนปชอตแทนวิดีโอเมื่อเกิดเหตุการณ์

ตรวจสอบโหมดการบันทึก

หากต้องการแสดงการกำหนดค่าการบันทึกปัจจุบัน ให้ตรวจสอบแอตทริบิวต์ ของลักษณะRecordingMode

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

เปลี่ยนโหมดการบันทึก

ก่อนอัปเดต โปรดตรวจสอบว่าดัชนีที่เลือกจากแอตทริบิวต์ supportedRecordingModes อยู่ในแอตทริบิวต์ availableRecordingModes

หากต้องการอัปเดตโหมดที่เลือก ให้ใช้ฟังก์ชัน setSelectedRecordingMode โดยส่งดัชนีของโหมดที่เลือก

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

การตั้งค่าอื่นๆ

คุณควบคุมการตั้งค่าอื่นๆ ได้ผ่าน Home API

เปิดหรือปิดฟีเจอร์ภาพกลางคืน

หากต้องการเปิดหรือปิดภาพกลางคืนสำหรับกล้อง ให้ใช้ TriStateAutoEnum เพื่ออัปเดตแอตทริบิวต์ nightVision ของลักษณะ CameraAvStreamManagement โดยใช้ฟังก์ชัน 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 เพื่ออัปเดตแอตทริบิวต์ statusLightBrightness ของลักษณะ CameraAvStreamManagement โดยใช้ฟังก์ชัน 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 ที่มีค่า 4 ค่า ซึ่งใช้เป็นพิกัดของวิวพอร์ต โดยพิกัดจะได้รับการกําหนดดังนี้

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

การกำหนดค่าสำหรับ ViewportStruct ขึ้นอยู่กับ UI ของแอปและการติดตั้งใช้งานกล้อง ในระดับพื้นฐานมากที่สุด หากต้องการตั้งค่า Viewport ของวิดีโอจากกล้อง ให้อัปเดตแอตทริบิวต์ viewport ของลักษณะ CameraAvStreamManagement ด้วย ViewportStruct โดยใช้ ฟังก์ชัน setViewport 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(),
    )
) }

เปิดหรือปิดใช้ข้อมูลวิเคราะห์

อุปกรณ์แต่ละเครื่องอาจเลือกที่จะส่งข้อมูลวิเคราะห์แบบละเอียดไปยัง ระบบคลาวด์ของ Google Home (ดูการตรวจสอบระบบคลาวด์สำหรับ Home API)

หากต้องการเปิดใช้ข้อมูลวิเคราะห์สำหรับอุปกรณ์ ให้ตั้งค่าพร็อพเพอร์ตี้ analyticsEnabled ของ ExtendedGeneralDiagnosticsTrait เป็น true เมื่อตั้งค่า analyticsEnabled พร็อพเพอร์ตี้อื่น logUploadEnabled จะได้รับการตั้งค่าเป็น true โดยอัตโนมัติ ซึ่ง จะอนุญาตให้อัปโหลดไฟล์บันทึกการวิเคราะห์ไปยังระบบคลาวด์ของ Google Home

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

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

การกำหนดค่าการขนส่งและการบันทึก

ส่วนนี้ครอบคลุมการตั้งค่าที่เกี่ยวข้องกับคุณภาพการสตรีมของกล้องและ การทริกเกอร์เหตุการณ์ การตั้งค่าเหล่านี้ได้รับการจัดการโดยลักษณะ PushAvStreamTransport

อ่านการตั้งค่าการรับส่ง

ส่วนนี้จะสาธิตวิธีดึงข้อมูลการกำหนดค่าปัจจุบันจากอุปกรณ์กล้องหรือกริ่งประตู โดยจะดึงข้อมูลลักษณะ PushAvStreamTransport ค้นหาการเชื่อมต่อที่เฉพาะเจาะจงซึ่งใช้สำหรับการบันทึก แล้วแยกค่าปัจจุบันสำหรับคุณภาพแบนด์วิดท์ ความไวในการปลุกระบบ และระยะเวลาสูงสุดของเหตุการณ์

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

อัปเดตการตั้งค่าการรับส่ง

ส่วนนี้จะแสดงวิธีเปลี่ยนการตั้งค่าการขนส่ง โดยจะสร้าง TransportOptionsStruct ใหม่ที่มีค่าใหม่ แล้วใช้คำสั่ง modifyPushTransport เพื่อส่งการตั้งค่าที่อัปเดตแล้วเหล่านี้กลับไปยังอุปกรณ์ และใช้การตั้งค่าดังกล่าวกับการเชื่อมต่อการบันทึกที่พบในขั้นตอนก่อนหน้า

หากต้องการแก้ไขการตั้งค่าเหล่านี้ ให้ใช้modifyPushTransportคำสั่งที่มี 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
    )
}

พิจารณาคุณภาพแบนด์วิดท์

พร็อพเพอร์ตี้ videoStreamId ของ TransportOptionsStruct ตรงกับการกำหนดค่าสตรีมวิดีโอ ที่เฉพาะเจาะจง

หากต้องการดูสตรีมวิดีโอที่รองรับ ให้ดูแอตทริบิวต์ allocatedVideoStreams ซึ่งเป็นรายการของ VideoStreamStructs จากลักษณะ CameraAvStreamManagement ของอุปกรณ์

ปรับความไวในการปลุกระบบของอุปกรณ์

พร็อพเพอร์ตี้ motionSensitivity ของ TransportTriggerOptionsStruct สอดคล้องกับค่าต่อไปนี้

ป้ายกำกับ ค่า (UByte)
ต่ำ 1u
ปานกลาง 5u
สูง 10u

ปรับระยะเวลาสูงสุดของเหตุการณ์

พร็อพเพอร์ตี้ maxDuration ของ TransportMotionTriggerTimeControlStruct สอดคล้องกับระยะเวลาต่อไปนี้ (เป็นวินาที)

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

การตั้งค่ากริ่ง

คุณควบคุมการตั้งค่าเสียงกริ่งประตูต่างๆ ได้ผ่าน Home API

เปลี่ยนเสียงกริ่ง

หากต้องการเปลี่ยนเสียงกริ่งประตู ให้รับรายการเสียงกริ่งที่ติดตั้งในอุปกรณ์ก่อนโดยใช้แอตทริบิวต์ installedChimeSounds ของลักษณะ 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()

จากนั้นอัปเดตแอตทริบิวต์ selectedChime ของลักษณะ Chime โดยใช้ฟังก์ชัน setSelectedChime Kotlin ในตัว

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

ใช้กริ่งภายนอก

คุณกำหนดค่ากริ่งประตูให้ใช้กริ่งภายนอกได้ เช่น กริ่งกลไก ที่ติดตั้งภายในบ้าน คุณควรกำหนดค่านี้ในระหว่างการติดตั้งกริ่งประตู เพื่อหลีกเลี่ยงความเสียหายที่อาจเกิดขึ้นกับกริ่งภายนอก

หากต้องการระบุประเภทกริ่งภายนอกที่ติดตั้ง ให้ใช้ ExternalChimeType เพื่ออัปเดตแอตทริบิวต์ externalChime ของลักษณะ Chime โดยใช้ฟังก์ชัน setExternalChime Kotlin ในตัว

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

เปลี่ยนระยะเวลาของกริ่งภายนอก

คุณกำหนดค่าระยะเวลาเป็นวินาทีที่กริ่งภายนอกจะดังได้ผ่าน Home API หากกริ่งภายนอกรองรับระยะเวลาเสียงกริ่ง ผู้ใช้อาจต้องการ กำหนดค่านี้

ค่าที่ตั้งไว้ที่นี่ขึ้นอยู่กับข้อกำหนดของกริ่งภายนอก เอง และระยะเวลาของเสียงกริ่งที่แนะนำ

หากต้องการเปลี่ยนระยะเวลาเสียงกริ่งภายนอก ให้อัปเดตแอตทริบิวต์ externalChimeDurationSeconds ของลักษณะ Chime โดยใช้ฟังก์ชัน Kotlin setExternalChimeDurationSeconds ในตัว ดังนี้

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

เปิดใช้ธีมเสียงกริ่ง

กริ่งประตูบางรุ่นอาจมีเสียงกริ่งที่พร้อมให้บริการแก่ผู้ใช้เป็น ระยะเวลาจำกัดเท่านั้น เช่น เสียงกริ่งเฉพาะสำหรับวันหยุด ซึ่งเรียกว่าธีมเสียงกริ่ง

หากต้องการดูว่าธีมเสียงกริ่งใดบ้างที่พร้อมใช้งานสำหรับผู้ใช้ ให้สร้างตัวกรอง Timebox แล้วใช้เพื่อกรองผลลัพธ์ของคำสั่ง getAvailableThemes() จากลักษณะ ChimeThemes ซึ่งจะแสดงรายการธีมที่ใช้ได้ รวมถึงชื่อธีม

ตัวอย่างต่อไปนี้แสดงวิธีกรองรายการ ระบบจะถือว่าธีมทำงานอยู่หากเวลาปัจจุบันอยู่ภายในเวลาเริ่มต้นและเวลาสิ้นสุด (ค่า startTimeSeconds และ endTimeSeconds ตามลำดับ) หากไม่ได้ตั้งเวลาเริ่มต้น ระบบจะถือว่าใช้งานได้ตั้งแต่ต้น หากไม่ได้ตั้งเวลาสิ้นสุดไว้ การตั้งค่าจะยังคงใช้งานได้ ต่อไปเรื่อยๆ หากไม่มีทั้ง 2 อย่าง ธีมจะใช้งานอยู่เสมอ

// 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 คุณสามารถ เลือกธีมนั้นได้โดยใช้ฟังก์ชัน setSelectedTimeboxedThemeName() ในลักษณะ ChimeThemes ดังนี้

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