คู่มืออุปกรณ์กล้องสำหรับ 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}")
    }

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

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

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

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

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

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

การตั้งค่าประเภทขายึดกล้อง

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

// Get the Mount trait
val mountTrait: Mount = device.getTrait(Mount)

// Read the current mount state and detection type
val mountState = mountTrait.mountState
val mountDetectionType = mountTrait.mountDetectionType

// Read the current mount type name
val mountTypeName = mountTrait.mountTypeName

// Update the mount type override
mountTrait.update {
  setMountTypeOverride(MountTrait.MountTypeOverrideEnum.Official)
}

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

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

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

จัดการไลฟ์สด

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

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

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

  • เรียกตัวเลือกคุณภาพที่รองรับ: รับความละเอียดในการสตรีมที่มี ซึ่งอุปกรณ์รองรับ โค้ดจะค้นหาแอตทริบิวต์ WebRtcLiveView trait's supportedQualityHints ในโฟลว์ประเภทอุปกรณ์และแสดง คุณภาพที่รองรับเป็น StateFlow ที่มีรายการQualityHint ค่า (เช่น QUALITY_HINT_SD, QUALITY_HINT_HD, QUALITY_HINT_FHD, QUALITY_HINT_QHD หรือ QUALITY_HINT_UHD)

  • เปลี่ยนคุณภาพไลฟ์สด: ใช้QualityHintที่เลือกเพื่อเปลี่ยน ความละเอียดการสตรีมของไลฟ์สดที่ทำงานอยู่ (เช่น เปลี่ยนจากความละเอียดมาตรฐานเป็นความละเอียดสูง) ฟังก์ชัน changeQuality จะระบุลักษณะการไลฟ์สดของอุปกรณ์ และเรียกใช้ changeLiveViewQuality ด้วย mediaSessionId ที่ใช้งานอยู่ และการกำหนดค่า QualityHint ที่ต้องการ

// Assuming you have a HomeDevice instance 'device'
val availableQualityHints: StateFlow<List> =
    device.type(GoogleCameraDevice)
        .trait(WebRtcLiveView)
        .map { trait -> 
            trait?.supportedQualityHints ?: emptyList() 
        }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())

// Assuming you have a HomeDevice instance 'device'
suspend fun changeQuality(mediaSessionId: String, qualityHint: QualityHint) {
    // Get the trait from the device
    val trait = device.type(GoogleCameraDevice).trait(WebRtcLiveView).first() ?: return
    try {
        trait.changeLiveViewQuality(mediaSessionId, qualityHint)
    } catch (e: Exception) {
        // Handle error
    }
}

เปิดและปิดใช้ความสามารถในการบันทึก

หากต้องการเปิดใช้ความสามารถในการบันทึกของกล้อง ให้ส่ง 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 โดยใช้ฟังก์ชัน setSpeakerVolumeLevel Kotlin ในตัว ดังนี้

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

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

คุณหมุนการวางแนวของรูปภาพ (วิดีโอ) จากกล้องได้ หมุนวิดีโอได้ 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 โดยใช้ฟังก์ชัน Kotlin setStatusLightBrightness ในตัว

// 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 ของลักษณะภาษา 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