Loại thiết bị Camera được triển khai bằng ba đặc điểm:
PushAvStreamTransport,
xử lý việc truyền tải luồng âm thanh và video bằng các giao thức dựa trên phương thức đẩy,
WebRtcLiveView,
cung cấp khả năng điều khiển các sự kiện phát trực tiếp và tính năng đàm thoại hai chiều, và
CameraSnapshot,
cung cấp ảnh chụp nhanh xem trước được lưu vào bộ nhớ đệm và ảnh chụp nhanh trực tiếp.
Luôn kiểm tra khả năng hỗ trợ thuộc tính và lệnh cho một thiết bị trước khi sử dụng bất kỳ tính năng nào hoặc cố gắng cập nhật thuộc tính. Hãy xem bài viết Điều khiển thiết bị trên Android để biết thêm thông tin.
| Loại thiết bị Home API | Đặc điểm | Ứng dụng mẫu Kotlin | Trường hợp sử dụng |
|---|---|---|---|
|
Máy ảnh
Thiết bị chụp ảnh tĩnh hoặc quay video. Camera có thể có tính năng phát trực tiếp, đàm thoại hai chiều hoặc phát hiện sự kiện. |
Đặc điểm bắt buộc google PushAvStreamTransport google WebRtcLiveView |
Camera |
Xem thông tin cơ bản về thiết bị
Được triển khai trong Ứng dụng mẫu cho Android
Đặc điểm BasicInformation bao gồm các thông tin như tên nhà cung cấp, mã nhà cung cấp, mã sản phẩm, tên sản phẩm (bao gồm cả thông tin về kiểu máy) và phiên bản phần mềm của thiết bị:
// 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}") }
Lấy số sê-ri
Để lấy số sê-ri của thiết bị, hãy sử dụng lệnh GetSerialNumber của đặc điểm ExtendedBasicInformation.
Ví dụ sau đây minh hoạ cách lưu số sê-ri vào một biến có tên là serialNumber:
val basicInfo: ExtendedBasicInformation = device.getTrait(ExtendedBasicInformation) val serialNumber = basicInfo.getSerialNumber().serialNumber
Lấy thời gian gần đây nhất mà thiết bị liên hệ với đám mây
Để tìm thời gian gần đây nhất mà thiết bị liên hệ với đám mây, hãy sử dụng thuộc tính lastContactTimestamp của đặc điểm ExtendedGeneralDiagnostics:
fun getLastContactTimeStamp(trait: ExtendedGeneralDiagnostics): java.time.Instant { val timestamp = trait.lastContactTimestamp return Instant.ofEpochSecond(timestamp.toLong()) }
Chế độ cài đặt loại ngàm gắn camera
Đặc điểm Mount chứa chế độ cài đặt giá gắn camera và thông tin trạng thái. Bạn có thể đọc các thuộc tính như trạng thái gắn, loại phát hiện và tên loại gắn. Ngoài ra,
bạn có thể sử dụng đặc điểm Mount để ghi đè cấu hình loại gắn kết mặc định.
// 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) }
Kiểm tra khả năng kết nối của thiết bị
Khả năng kết nối của một thiết bị thực sự được kiểm tra ở cấp loại thiết bị vì một số thiết bị hỗ trợ nhiều loại thiết bị. Trạng thái được trả về là sự kết hợp của các trạng thái kết nối cho tất cả các đặc điểm trên thiết bị đó.
val cameraConnectivity = cameraDevice.metadata.sourceConnectivity.connectivityState
Bạn có thể thấy trạng thái PARTIALLY_ONLINE trong trường hợp có nhiều loại thiết bị khi không có kết nối Internet.
Matter đặc điểm tiêu chuẩn vẫn có thể hoạt động do định tuyến cục bộ, nhưng các đặc điểm dựa trên đám mây sẽ không hoạt động.
Lấy địa chỉ IP của thiết bị
Để tìm địa chỉ IP của thiết bị, hãy sử dụng thuộc tính networkInterfaces của đặc điểm GeneralDiagnostics. Địa chỉ được trả về dưới dạng mảng byte mà bạn có thể định dạng thành chuỗi IPv4 hoặc IPv6 chuẩn:
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()
Bắt đầu sự kiện phát trực tiếp
Được triển khai trong Ứng dụng mẫu cho Android
Để bắt đầu một sự kiện phát trực tiếp, hãy gửi chuỗi Giao thức mô tả phiên (SDP) đến phương thức startLiveView() của đặc điểm WebRtcLiveView. Phương thức này sẽ trả về một WebRtcLiveViewTrait.StartLiveViewCommand.Response chứa 3 giá trị:
- SDP cho phiên.
- Thời lượng phiên tính bằng giây.
- Mã phiên, có thể dùng để gia hạn hoặc chấm dứt phiên.
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)
Kéo dài sự kiện phát trực tiếp
Được triển khai trong Ứng dụng mẫu cho Android
Sự kiện phát trực tiếp có thời hạn đặt trước và sẽ hết hạn sau thời hạn đó. Để kéo dài thời lượng của một sự kiện phát trực tiếp đang diễn ra, hãy gửi yêu cầu gia hạn bằng phương thức 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 }
Bắt đầu và dừng TalkBack
Được triển khai trong Ứng dụng mẫu cho Android
Để bắt đầu tính năng TalkBack, hãy gọi phương thức startTalkback() của đặc điểm WebRtcLiveView. Để dừng, hãy sử dụng
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) } }
Quản lý sự kiện phát trực tiếp
Việc điều chỉnh chất lượng sự kiện phát trực tiếp giúp tối ưu hoá mức sử dụng băng thông dựa trên bối cảnh xem của ứng dụng khách (ví dụ: chuyển sang độ phân giải thấp hơn khi hiển thị ô xem trước nhỏ hơn, chế độ xem lưới hoặc chế độ hình trong hình).
Việc thay đổi chất lượng một cách linh động bằng cách sử dụng đặc điểm WebRtcLiveView sẽ quản lý cụ thể độ phân giải của phiên phát trực tiếp đang hoạt động trên một ứng dụng cụ thể. Chế độ này không giống như việc định cấu hình chế độ cài đặt mức sử dụng băng thông trên toàn thiết bị ngay trên thiết bị, vì việc này sẽ ảnh hưởng đến tất cả người xem đồng thời và chất lượng của các bản ghi video trước đây được lưu vào đám mây.
Ví dụ sau đây minh hoạ cách truy xuất và cập nhật chất lượng sự kiện phát trực tiếp cho một thiết bị:
Truy xuất các lựa chọn chất lượng được hỗ trợ: Lấy các độ phân giải phát trực tuyến có sẵn mà thiết bị hỗ trợ. Mã này truy vấn thuộc tính
supportedQualityHintscủa đặc điểmWebRtcLiveViewtrên luồng loại thiết bị và hiển thị các chất lượng được hỗ trợ dưới dạngStateFlowchứa danh sách các giá trịQualityHint(chẳng hạn nhưQUALITY_HINT_SD,QUALITY_HINT_HD,QUALITY_HINT_FHD,QUALITY_HINT_QHDhoặcQUALITY_HINT_UHD).Thay đổi chất lượng sự kiện phát trực tiếp: Áp dụng
QualityHintđã chọn để thay đổi độ phân giải của sự kiện phát trực tiếp đang diễn ra (ví dụ: chuyển từ độ phân giải chuẩn sang độ phân giải cao). HàmchangeQualityphân giải đặc điểm phát trực tiếp của thiết bị và gọichangeLiveViewQualitybằngmediaSessionIdđang hoạt động và cấu hìnhQualityHintđã chọn.
// 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 } }
Bật và tắt tính năng ghi lại
Để bật tính năng ghi hình của camera, hãy truyền TransportStatusEnum.Active đến phương thức setTransportStatus() của đặc điểm PushAvStreamTransport. Để tắt tính năng ghi, hãy truyền TransportStatusEnum.Inactive.
Trong ví dụ sau, chúng ta gói các lệnh gọi này vào một lệnh gọi duy nhất sử dụng Boolean để bật/tắt chức năng ghi:
// 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) } }
Việc bật hoặc tắt chức năng ghi hình của camera cũng giống như việc bật hoặc tắt video của camera. Khi video của camera ở trạng thái bật, camera sẽ ghi hình (cho mục đích ghi lại sự kiện và các đoạn video liên quan).
Khi tính năng ghi hình bị tắt (video của camera tắt):
- Camera vẫn có thể hiển thị là đang trực tuyến theo
connectivityStatecủa loại thiết bị. - Bạn không thể truy cập vào sự kiện phát trực tiếp và camera cũng không phát hiện thấy sự kiện nào trên đám mây.
Kiểm tra xem tính năng ghi lại đã được bật hay chưa
Để xác định xem khả năng ghi hình của camera có được bật hay không, hãy kiểm tra xem có kết nối nào đang hoạt động hay không. Ví dụ sau đây xác định hai hàm để thực hiện việc này:
// 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 }
Một cách khác để kiểm tra là sử dụng hàm findTransport() với một vị từ:
// Fetch the current connections suspend fun queryRecordModeState(trait: PushAvStreamTransport) { return trait.findTransport().let { it.transportConfigurations.any { it.transportStatus == TransportStatusEnum.Active } }
Truy xuất ảnh chụp nhanh bằng camera
Được triển khai trong Ứng dụng mẫu cho Android
Sử dụng đặc điểm CameraSnapshot để truy xuất ảnh chụp nhanh hình ảnh tĩnh từ camera.
Những ảnh chụp nhanh này hữu ích trong một số trường hợp:
- Làm ô giữ chỗ trong giao diện người dùng trong khi sự kiện phát trực tiếp WebRTC đang tải.
- Dưới dạng hình ảnh xem trước tĩnh, sau đó nâng cấp thành sự kiện phát trực tiếp khi người dùng tương tác.
- Làm nền để vẽ và định cấu hình vùng hoạt động tuỳ chỉnh.
Đặc điểm CameraSnapshot cung cấp hai cách để tìm nạp ảnh chụp nhanh, tuỳ thuộc vào việc bạn cần ảnh chụp nhanh được lưu vào bộ nhớ đệm để kết xuất nhanh hay ảnh chụp nhanh trực tiếp theo yêu cầu.
Lấy ảnh chụp nhanh bản xem trước được lưu vào bộ nhớ đệm
Ảnh chụp nhanh xem trước là một hình ảnh được lưu vào bộ nhớ đệm mà SDK có thể truy xuất mà không cần bật máy ảnh. Đây là phương thức nhanh nhất để tìm nạp hình ảnh tĩnh và là phương thức lý tưởng cho các trang tổng quan về camera hoặc lưới trang tổng quan.
Để lấy ảnh chụp nhanh của bản xem trước, hãy đọc thuộc tính đặc điểm preview_image_url:
// Get a flow of the CameraSnapshot trait val cameraSnapshotFlow: Flow<CameraSnapshot?> = cameraDevice .type(GoogleCameraDevice) .trait(CameraSnapshot) // Get the current trait state val cameraSnapshot = cameraSnapshotFlow.firstOrNull() if (cameraSnapshot != null) { val previewImageUrl = cameraSnapshot.previewImageUrl // Load the preview image from the URL } else { // CameraSnapshot trait not supported on this device }
Tuỳ thuộc vào cấu hình và hoạt động của camera, URL xem trước sẽ trỏ đến một hình ảnh được lưu vào bộ nhớ đệm, được tạo từ cảnh quay video gần đây (khung hình I đầu tiên của đoạn video mới nhất) hoặc ảnh chụp nhanh do camera tải lên định kỳ.
Để cho biết độ mới của hình ảnh, đám mây Google Home sẽ nhúng tiêu đề X-Home-Image-Captured-At vào hình ảnh JPEG/PNG được phân phát, được định dạng theo giờ UTC. Bạn có thể phân tích cú pháp tiêu đề này ở phía máy khách để hiển thị tuổi của ảnh chụp nhanh trong một ứng dụng.
Xem nhanh thông tin trực tiếp theo yêu cầu
Đối với những hành trình của người dùng cần có chế độ xem trực tiếp hiện tại của camera (chẳng hạn như thiết lập Vùng hoạt động), bạn có thể yêu cầu ảnh chụp nhanh trực tiếp. Việc kích hoạt ảnh chụp nhanh trực tiếp sẽ hướng dẫn camera bật lên, chụp một khung hình mới và tải khung hình đó lên đám mây.
Để yêu cầu ảnh chụp nhanh trực tiếp, hãy sử dụng lệnh getLiveSnapshot():
try { val response = cameraSnapshot.getLiveSnapshot() val snapshotUrl = response.snapshotUrl // Load the live snapshot image from the URL } catch (e: Exception) { Log.e("CameraSnapshot", "Failed to get live snapshot: ${e.message}") }
Xác thực yêu cầu ảnh chụp nhanh
Được triển khai trong Ứng dụng mẫu cho Android
Tất cả URL ảnh chụp nhanh đều trỏ đến nội dung nghe nhìn an toàn và yêu cầu mã thông báo OAuth 2.0 cho phạm vi Home APIs phiên bản 2. Để tải xuống và hiển thị hình ảnh, mã thông báo OAuth phải được chèn dưới dạng mã thông báo truy cập trong tiêu đề Authorization của yêu cầu HTTP.
Ví dụ sau đây minh hoạ cách định cấu hình một yêu cầu mạng an toàn để tải ảnh chụp nhanh xuống:
import android.graphics.Bitmap import android.graphics.BitmapFactory import java.io.IOException import java.net.HttpURLConnection import java.net.URL import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext /** * Downloads a snapshot from a URL using an OAuth access token. */ suspend fun loadSnapshotImage(urlString: String, oauthToken: String): Bitmap? = withContext(Dispatchers.IO) { var connection: HttpURLConnection? = null try { val url = URL(urlString) connection = url.openConnection() as HttpURLConnection // 1. Configure the HTTP GET request with the Bearer token connection.setRequestProperty("Authorization", "Bearer $oauthToken") // 2. Fetch the image data if (connection.responseCode == HttpURLConnection.HTTP_OK) { connection.inputStream.use { inputStream -> BitmapFactory.decodeStream(inputStream) } } else { null } } catch (e: IOException) { e.printStackTrace() null } finally { connection?.disconnect() } }
Cài đặt pin
Bạn có thể kiểm soát nhiều chế độ cài đặt pin thông qua Home API.
Đặt lựa chọn ưu tiên về mức sử dụng pin
Việc đặt mức cân bằng năng lượng cho phép bạn định cấu hình sự đánh đổi giữa thời lượng pin và hiệu suất cho một thiết bị. Bạn có thể tạo nhiều hồ sơ pin, chẳng hạn như "Kéo dài", "Cân bằng" và "Hiệu suất", rồi chuyển đổi giữa các hồ sơ đó.
Tính năng này được triển khai bằng cách cập nhật thuộc tính currentEnergyBalance của đặc điểm EnergyPreference. Thuộc tính này chấp nhận một chỉ mục số nguyên tương ứng với một hồ sơ cụ thể được xác định trong danh sách energyBalances của thiết bị (ví dụ: 0 cho EXTENDED, 1 cho BALANCED và 2 cho PERFORMANCE).
Giá trị null cho currentEnergyBalance cho biết thiết bị đang sử dụng một hồ sơ tuỳ chỉnh. Đây là trạng thái chỉ đọc.
Phần sau đây cho thấy ví dụ về cấu trúc mà thuộc tính currentEnergyBalance sẽ sử dụng, theo sau là đoạn mã thực tế sử dụng thuộc tính này.
// 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)
Bật trình tiết kiệm pin tự động
Để định cấu hình tính năng này, hãy cập nhật thuộc tính currentLowPowerModeSensitivity của đặc điểm EnergyPreference. Thuộc tính này sử dụng một chỉ mục để chọn mức độ nhạy cảm, trong đó 0 thường đại diện cho Disabled và 1 đại diện cho Enabled hoặc 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) } }
Lấy trạng thái sạc pin
Để biết trạng thái sạc hiện tại của thiết bị (đang sạc, đã sạc đầy hoặc không sạc), hãy sử dụng thuộc tính batChargeState của đặc điểm 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" }
Xem mức pin
Để biết mức pin hiện tại, hãy sử dụng thuộc tính batChargeLevel của đặc điểm PowerSource. Cấp độ có thể là OK, Warning (thấp) hoặc 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" }
Lấy nguồn điện
Để xác định nguồn điện mà thiết bị đang sử dụng, hãy dùng các thuộc tính BatPresent và wiredPresent của đặc điểm PowerSource.
val trait: PowerSource val isWired = trait.wiredPresent val hasBattery = trait.batPresent
Kiểm tra xem có cần thay pin không
Thuộc tính batReplaceability cho biết pin không thể thay thế, người dùng có thể thay thế hay nhà máy có thể thay thế.
Thuộc tính batReplacementNeeded của đặc điểm PowerSource cho bạn biết liệu có cần thay pin hay không.
// Get the battery replacement status val batteryStatus = powerSourceTrait.batReplacementNeeded if (batteryStatus) { println("Replace the battery.") }
Khi người dùng có thể thay pin,
batReplacementDescription
sẽ mô tả pin, bao gồm cả thông tin như kiểu dáng, thành phần hoá học và
nhà sản xuất ưu tiên.
Cài đặt âm thanh
Bạn có thể kiểm soát nhiều chế độ cài đặt âm thanh thông qua Home API.
Bật hoặc tắt micrô
Để bật hoặc tắt micrô của thiết bị, hãy cập nhật thuộc tính microphoneMuted của đặc điểm CameraAvStreamManagement bằng hàm Kotlin setMicrophoneMuted tích hợp sẵn:
// Turn the device's microphone on or off suspend fun turnOffMicrophone(disableMicrophone: Boolean, trait: CameraAvStreamManagement) { trait.update { setMicrophoneMuted(disableMicrophone) } }
Bật hoặc tắt chế độ cài đặt bản ghi âm
Để bật hoặc tắt tính năng ghi âm cho thiết bị, hãy cập nhật thuộc tính recordingMicrophoneMuted của đặc điểm CameraAvStreamManagement bằng hàm Kotlin setRecordingMicrophoneMuted tích hợp sẵn:
// Turn audio recording on or off for the device suspend fun turnOffAudioRecording(disableAudioRecording: Boolean, trait: CameraAvStreamManagement) { trait.update { setRecordingMicrophoneMuted(disableAudioRecording) } }
Điều chỉnh âm lượng loa
Để điều chỉnh âm lượng loa cho thiết bị, hãy cập nhật thuộc tính speakerVolumeLevel của đặc điểm CameraAvStreamManagement bằng hàm Kotlin setSpeakerVolumeLevel tích hợp sẵn:
// Adjust the camera speaker volume suspend fun adjustSpeakerVolume(volume: Int, trait: CameraAvStreamManagement) { trait.update { setSpeakerVolumeLevel(volume.toUbyte()) } }
Cài đặt vùng hoạt động
Được triển khai trong Ứng dụng mẫu cho Android
Đặc điểm ZoneManagement cung cấp một giao diện để quản lý các khu vực quan tâm tuỳ chỉnh (vùng hoạt động) trên thiết bị camera và chuông cửa.
Các vùng này được dùng để lọc tính năng phát hiện sự kiện (chẳng hạn như chuyển động của người
hoặc xe) cho các khu vực cụ thể trong trường nhìn của thiết bị.
Người dùng định cấu hình vùng hoạt động trong ứng dụng của đối tác, cho phép họ vẽ các vùng trên những khu vực cụ thể trong trường nhìn của camera. Sau đó, các vùng do người dùng xác định này sẽ được chuyển thành các cấu trúc mà đặc điểm này sử dụng. Để biết thêm thông tin về cách hoạt động của vùng hoạt động, hãy xem bài viết Thiết lập và sử dụng Vùng hoạt động.
Vùng hoạt động thường được xác định bằng toạ độ Descartes 2D.
Đặc điểm này cung cấp
TwoDCartesianVertexStruct cho các đỉnh và
TwoDCartesianZoneStruct
cho định nghĩa vùng (tên, đỉnh, màu và mức sử dụng).
Kiểm tra vùng hoạt động
Để hiển thị vùng hoạt động, hãy kiểm tra thuộc tính zones của đặc điểm 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() }
Thêm vùng hoạt động
Để tạo một vùng mới, hãy dùng lệnh createTwoDCartesianZone. Lệnh này nhận một TwoDCartesianZoneStruct,
xác định tên, đỉnh, màu sắc và cách sử dụng của vùng.
Ví dụ sau đây cho thấy cách tạo một vùng có tên là "Hiên trước" với 4 đỉnh, màu cá hồi (#F439A0) và được dùng để phát hiện chuyển động.
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}") } }
Cập nhật vùng hoạt động
Để cập nhật một vùng hiện có, hãy sử dụng lệnh updateTwoDCartesianZone. Lệnh này yêu cầu zoneId và TwoDCartesianZoneStruct đã cập nhật.
private suspend fun ZoneManagement.updateZone( zoneId: UShort, zone: ZoneManagementTrait.TwoDCartesianZoneStruct ) { // Execute the command to update the zone this.updateTwoDCartesianZone(zoneId = zoneId, zone = zone) }
Xoá vùng hoạt động
Để xoá một vùng, hãy sử dụng lệnh removeZone với zoneId cụ thể.
private suspend fun ZoneManagement.deleteZone(zoneId: UShort) { // Execute the command to remove the zone this.removeZone(zoneId = zoneId) }
Trình kích hoạt sự kiện âm thanh
Đặc điểm AvStreamAnalysis cung cấp một giao diện để quản lý các điều kiện kích hoạt phát hiện sự kiện trên thiết bị camera và chuông cửa. Mặc dù các điều kiện kích hoạt dựa trên hình ảnh (chẳng hạn như người hoặc xe) có thể áp dụng cho từng vùng cụ thể, nhưng các điều kiện kích hoạt liên quan đến âm thanh thường là cấu hình ở cấp thiết bị.
Sau đây là các loại điều kiện kích hoạt hiện có để phát hiện âm thanh bằng
EventTriggerTypeEnum:
| Chế độ | Giá trị enum | Mô tả |
|---|---|---|
| Âm thanh | Sound |
Phát hiện âm thanh chung. |
| Tiếng người nói | PersonTalking |
Phát hiện giọng nói. |
| Tiếng chó sủa | DogBark |
Phát hiện tiếng chó sủa. |
| Tiếng kính vỡ | GlassBreak |
Phát hiện tiếng kính vỡ. |
| Chuông báo khói | SmokeAlarm |
Phát hiện chuông báo khói, thường được nhận dạng bằng mẫu âm thanh T3 (ba tiếng bíp ngắn, sau đó là một khoảng dừng). |
| chuông báo khí CO | CoAlarm |
Phát hiện chuông báo khí cacbon monoxit (CO), thường được nhận dạng bằng mẫu âm thanh T4 (bốn tiếng bíp ngắn, sau đó tạm dừng). |
Kiểm tra trạng thái phát hiện âm thanh
Để hiển thị trạng thái hiện tại của tính năng phát hiện âm thanh cho người dùng, bạn phải kiểm tra xem thiết bị hỗ trợ những gì và phần cứng thiết bị đã bật những gì. Hai thuộc tính cần kiểm tra là:
Trong quá trình phát triển Android bằng Kotlin Flow, bạn thường sẽ quan sát đặc điểm AvStreamAnalysis từ 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) ) } }
Cập nhật nhóm trình kích hoạt đã bật
Để cập nhật tập hợp các điều kiện kích hoạt đã bật, hãy sử dụng lệnh SetOrUpdateEventDetectionTriggers. Lệnh này sẽ lấy danh sách các cấu trúc 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) }
Chế độ ghi
Được triển khai trong Ứng dụng mẫu cho Android
Đặc điểm RecordingMode cung cấp một giao diện để quản lý hành vi quay video và chụp ảnh trên thiết bị camera và chuông cửa. Tính năng này cho phép người dùng chọn giữa chế độ ghi hình liên tục, ghi hình theo sự kiện hoặc tắt hoàn toàn tính năng ghi hình (chỉ xem trực tiếp).
RecordingModeEnum xác định các chiến lược ghi âm có sẵn:
| Chế độ | Giá trị enum | Mô tả |
|---|---|---|
| Đã tắt | Disabled |
Tính năng ghi âm bị tắt hoàn toàn. Chủ yếu được dùng cho các thiết bị cũ. |
| CVR (Quay video liên tục) | Cvr |
Video được ghi lại 24/7. Cần có gói thuê bao (ví dụ: Google Home Premium. |
| EBR (Ghi hình theo sự kiện) | Ebr |
Quá trình ghi hình được kích hoạt theo sự kiện (người, chuyển động). Thời lượng video phụ thuộc vào thời lượng sự kiện và gói thuê bao. |
| ETR (Ghi hình khi có sự kiện) | Etr |
Bản ghi xem trước ngắn (ví dụ: 10 giây) được kích hoạt theo sự kiện. |
| Chế độ xem trực tiếp | LiveView |
Tính năng ghi lại bị tắt nhưng người dùng vẫn có thể truy cập vào sự kiện phát trực tiếp. |
| Hình ảnh tĩnh | Images |
Ảnh chụp nhanh được ghi lại thay vì video khi sự kiện xảy ra. |
Kiểm tra các chế độ ghi
Để hiển thị cấu hình ghi hiện tại, hãy kiểm tra các thuộc tính
của đặc điểm RecordingMode:
supportedRecordingModes– Tất cả các chế độ tiềm năngavailableRecordingModes– Các chế độ có thể chọnselectedRecordingMode– Chế độ đang hoạt động
// 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(), ) } }
Thay đổi chế độ ghi
Trước khi cập nhật, hãy đảm bảo rằng chỉ mục đã chọn từ thuộc tính supportedRecordingModes có trong thuộc tính availableRecordingModes.
Để cập nhật chế độ đã chọn, hãy sử dụng hàm setSelectedRecordingMode, truyền chỉ mục của chế độ đã chọn:
private suspend fun RecordingMode.updateRecordingMode(index: Int) { // Execute the command to update the selected mode this.setSelectedRecordingMode(index.toUByte()) }
Chế độ cài đặt khác
Bạn có thể kiểm soát nhiều chế độ cài đặt khác thông qua Home API.
Thay đổi hướng của hình ảnh
Bạn có thể xoay hướng của hình ảnh camera (video). Bạn chỉ có thể xoay video 180 độ.
Để thay đổi hướng hình ảnh của camera, hãy cập nhật thuộc tính imageRotation của đặc điểm CameraAvStreamManagement bằng hàm Kotlin setImageRotation tích hợp sẵn:
// Change the camera's image orientation val isRotated = false cameraAvStreamManagement.update { setImageRotation(if (isRotated) 180.toUShort() else 0.toUShort()) }
Bật hoặc tắt chế độ cảnh đêm
Để bật hoặc tắt chế độ nhìn ban đêm cho camera, hãy sử dụng TriStateAutoEnum để cập nhật thuộc tính nightVision của đặc điểm CameraAvStreamManagement bằng hàm Kotlin setNightVision tích hợp sẵn:
// Turn night vision on cameraAvStreamManagement.update { setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.On) } // Turn night vision off CameraAvStreamManagement.update { setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.Off) }
Thay đổi độ sáng của đèn LED trạng thái
Để thay đổi độ sáng của đèn LED trạng thái, hãy sử dụng ThreeLevelAutoEnum để cập nhật thuộc tính statusLightBrightness của đặc điểm CameraAvStreamManagement bằng hàm Kotlin setStatusLightBrightness tích hợp sẵn:
// Set the LED brightness to high cameraAvStreamManagement.update { setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.High) } // Set the LED brightness to low cameraAvStreamManagement.update { setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.Low) }
Thay đổi khung nhìn của camera
Khung nhìn của camera giống với tính năng Thu phóng và Cắt được mô tả trong bài viết trợ giúp Thu phóng và cải thiện video trên camera Nest.
Khung nhìn được xác định trong một ViewportStruct chứa 4 giá trị, được dùng làm toạ độ của khung nhìn. Toạ độ được xác định như sau:
(x1,y1) -- (x2,y1) | | (x1,y2) -- (x2,y2)
Việc xác định giá trị cho ViewportStruct phụ thuộc vào giao diện người dùng và cách triển khai camera của ứng dụng. Ở mức cơ bản nhất, để đặt khung nhìn của video camera, hãy cập nhật thuộc tính viewport của đặc điểm CameraAvStreamManagement bằng ViewportStruct, sử dụng hàm Kotlin setViewport tích hợp sẵn:
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(), ) ) }
Bật hoặc tắt tính năng phân tích
Mỗi thiết bị có thể chọn tham gia riêng để gửi dữ liệu số liệu phân tích chi tiết đến đám mây Google Home (xem phần Giám sát đám mây cho Home API).
Để bật tính năng phân tích cho một thiết bị, hãy đặt thuộc tính analyticsEnabled của ExtendedGeneralDiagnosticsTrait thành true. Khi bạn đặt analyticsEnabled, một thuộc tính khác là logUploadEnabled sẽ tự động được đặt thành true, cho phép tải các tệp nhật ký phân tích lên đám mây Google Home.
// Enable analytics extendedGeneralDiagnostics.update { setAnalyticsEnabled(true) } // Disable analytics extendedGeneralDiagnostics.update { setAnalyticsEnabled(false) }
Cấu hình truyền tải và ghi lại
Phần này trình bày các chế độ cài đặt liên quan đến chất lượng luồng video của camera và việc kích hoạt sự kiện. Các chế độ cài đặt này do đặc điểm PushAvStreamTransport quản lý.
Đọc chế độ cài đặt phương tiện vận chuyển
Phần này minh hoạ cách truy xuất cấu hình hiện tại từ thiết bị camera hoặc chuông cửa. Thao tác này sẽ tìm nạp đặc điểm PushAvStreamTransport,
tìm kết nối cụ thể dùng để ghi, sau đó trích xuất
các giá trị hiện tại cho chất lượng băng thông, độ nhạy đánh thức
và thời lượng sự kiện tối đa.
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
Cập nhật chế độ cài đặt phương tiện vận chuyển
Phần này trình bày cách thay đổi chế độ cài đặt phương tiện di chuyển.
Thao tác này sẽ tạo một TransportOptionsStruct mới chứa các giá trị mới, sau đó sử dụng lệnh modifyPushTransport để gửi các chế độ cài đặt đã cập nhật này trở lại thiết bị, áp dụng các chế độ cài đặt đó cho kết nối ghi âm tìm thấy ở bước trước.
Để sửa đổi các chế độ cài đặt này, hãy sử dụng lệnh modifyPushTransport có 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 ) }
Xác định chất lượng băng thông
Thuộc tính videoStreamId của TransportOptionsStruct tương ứng với một cấu hình luồng video cụ thể.
Để lấy các luồng video được hỗ trợ, hãy tham khảo thuộc tính allocatedVideoStreams, đây là danh sách VideoStreamStructs.
từ đặc điểm CameraAvStreamManagement của thiết bị.
Điều chỉnh độ nhạy đánh thức của thiết bị
Thuộc tính motionSensitivity của TransportTriggerOptionsStruct tương ứng với các giá trị sau:
| Hãng nhạc | Giá trị (UByte) |
|---|---|
| Thấp | 1u |
| Trung bình | 5u |
| Cao | 10u |
Điều chỉnh thời lượng tối đa của sự kiện
Thuộc tính maxDuration của TransportMotionTriggerTimeControlStruct tương ứng với các khoảng thời gian sau (tính bằng giây):
- 10u, 15u, 30u, 60u, 120u, 180u
Ngừng sử dụng thiết bị
Để xoá camera khỏi một công trình, hãy gọi device.decommissionDevice(). Khi ngừng hoạt động, người dùng sẽ thấy một màn hình xác nhận do Google quản lý, cảnh báo rằng tất cả nhật ký quay video 24/7, nhật ký sự kiện, đoạn video và dữ liệu thư viện khuôn mặt quen thuộc đã ghi lại sẽ bị xoá vĩnh viễn khỏi cấu trúc.
Để biết hướng dẫn chi tiết và ví dụ về mã, hãy xem phần Xoá thiết bị.