คู่มืออุปกรณ์กล้องสำหรับ Android

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

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

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

กล้อง

GoogleCameraDevice

home.matter.6006.types.0158

อุปกรณ์ที่ถ่ายภาพนิ่งหรือวิดีโอ กล้องอาจมีฟีเจอร์สตรีมแบบสดที่เข้าถึงได้ การพูดโต้ตอบแบบ 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}")
        println("serialNumber ${basicInformation.serialNumber}")
    }

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

หากต้องการดูเวลาล่าสุดที่อุปกรณ์ติดต่อกับระบบคลาวด์ ให้ใช้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 ลักษณะมาตรฐานอาจยังออนไลน์อยู่เนื่องจากการกำหนดเส้นทางในพื้นที่ แต่ลักษณะที่อิงตามระบบคลาวด์จะออฟไลน์

เริ่มไลฟ์สด

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

  • SDP สำหรับเซสชัน
  • ระยะเวลาเซสชันเป็นวินาที
  • รหัสเซสชัน ซึ่งอาจใช้เพื่อขยายหรือสิ้นสุดเซสชัน
suspend fun getWebRtcLiveViewTrait(cameraDevice: HomeDevice) {
 return cameraDevice.type(GoogleCameraDevice).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 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

เปลี่ยนการวางแนวรูปภาพ

คุณหมุนการวางแนวของรูปภาพ (วิดีโอ) จากกล้องได้ วิดีโอจะหมุนได้ 180 องศาเท่านั้น

หากต้องการเปลี่ยนการวางแนวรูปภาพของกล้อง ให้อัปเดตแอตทริบิวต์ imageRotation ของลักษณะ CameraAvStreamManagement โดยใช้ฟังก์ชัน setImageRotation Kotlin ในตัว ดังนี้

// Change the camera's image orientation
val isRotated = false

cameraAvStreamManagement.update { setImageRotation(if (isRotated) 180.toUShort() else 0.toUShort()) }

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

หากต้องการเปิดหรือปิดภาพกลางคืนสำหรับกล้อง ให้ใช้ 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(),
    )
) }

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

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

ใน Home API คุณตั้งค่านี้ได้โดยใช้พร็อพเพอร์ตี้ motionSensitivity ของ triggerOptions ใน transportOptions ของอุปกรณ์ ตัวเลือกเหล่านี้กำหนดไว้ ใน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 คุณตั้งค่านี้ได้โดยใช้พร็อพเพอร์ตี้ motionTimeControl ของ triggerOptions ใน transportOptions ของอุปกรณ์ ตัวเลือกเหล่านี้กำหนดไว้ ใน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,
      )
    }
  }

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

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

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

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

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