يتم تنفيذ نوع الجهاز "الكاميرا" باستخدام سمتَين:
PushAvStreamTransport،
التي تتعامل مع نقل بث الصوت والفيديو باستخدام بروتوكولات مستندة إلى الإرسال،
وWebRtcLiveView،
التي تتيح التحكّم في البث المباشر ووظيفة "التحدث المباشر".
يجب دائمًا التحقّق من توفّر السمات والأوامر لجهاز معيّن قبل استخدام أي ميزات أو محاولة تعديل السمات. لمزيد من المعلومات، اطّلِع على مقالة التحكّم في الأجهزة على Android.
| نوع الجهاز في Home APIs | السمات | نموذج تطبيق Kotlin | حالة الاستخدام |
|---|---|---|---|
الكاميرا
جهاز يلتقط صورًا ثابتة أو فيديوهات قد تتضمّن الكاميرات بثًا مباشرًا يسهل الوصول إليه أو ميزة "التحدّث والاستماع" أو أحداث الرصد. |
السمات المطلوبة google PushAvStreamTransport google WebRtcLiveView |
الكاميرا |
بدء بث مباشر
لبدء بث مباشر، أرسِل سلسلة Session Description Protocol (SDP) إلى طريقة startLiveView() في السمة WebRtcLiveView، والتي تعرض WebRtcLiveViewTrait.StartLiveViewCommand.Response يحتوي على ثلاث قيم:
- تمثّل هذه السمة وصف الجلسة (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لنوع الجهاز. - لا يمكن الوصول إلى البث المباشر، ولا ترصد الكاميرا أي أحداث على السحابة الإلكترونية.
التحقّق من تفعيل إمكانية التسجيل
لتحديد ما إذا كانت إمكانية التسجيل في الكاميرا مفعَّلة، تحقَّق مما إذا كان أي من عمليات الربط نشطًا. يحدّد المثال التالي دالتَين لإجراء ذلك:
// 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.
تفعيل الميكروفون أو إيقافه
لتفعيل ميكروفون الجهاز أو إيقافه، عدِّل السمة
microphoneMuted
لسمة CameraAvStreamManagement باستخدام دالة
setMicrophoneMuted Kotlin المضمّنة:
// Turn the device's microphone on or off suspend fun turnOffMicrophone(disableMicrophone: Boolean, trait: CameraAvStreamManagement) { trait.update { setMicrophoneMuted(disableMicrophone) } }
تفعيل التسجيل الصوتي أو إيقافه
لتفعيل تسجيل الصوت أو إيقافه على الجهاز، عدِّل السمة
recordingMicrophoneMuted
لسمة CameraAvStreamManagement باستخدام دالة
setRecordingMicrophoneMuted Kotlin المضمّنة:
// 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()) } }
إعدادات أخرى
يمكن التحكّم في إعدادات أخرى متنوّعة للكاميرا من خلال واجهات برمجة التطبيقات Home.
تغيير اتجاه الصورة
يمكن تدوير اتجاه صورة الكاميرا (الفيديو). يمكن تدوير الفيديو بمقدار 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 يحتوي على أربع قيم تُستخدَم كإحداثيات لإطار العرض. يتم تحديد الإحداثيات على النحو التالي:
(x1,y1) -- (x2,y1) | | (x1,y2) -- (x2,y2)
يعتمد تحديد قيم ViewportStruct على واجهة مستخدم التطبيق وطريقة تنفيذ الكاميرا. على مستوى أساسي جدًا، لضبط إطار عرض فيديو الكاميرا، عدِّل السمة 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(), ) ) }
ضبط حساسية أجهزة الاستشعار لتشغيل الكاميرا
يتم استخدام حساسية التنشيط في الجهاز للحفاظ على البطارية من خلال تقليل النطاق الذي يمكن للجهاز من خلاله استشعار النشاط وزيادة الوقت اللازم لتنشيط الجهاز بعد رصد هذا النشاط.
في واجهات برمجة التطبيقات الخاصة بالمنزل، يمكن ضبط هذا الإعداد باستخدام السمة 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، لكل جهاز، على المدد نفسها التي يمكن ضبطها من خلال GHA، وذلك بفواصل زمنية بالثواني:
- 10 ثوانٍ
- 15 ثانية
- 30 ثانية
- 60 ثانية (دقيقة واحدة)
- 120 ثانية (دقيقتان)
- 180 ثانية (3 دقائق)
في واجهات برمجة التطبيقات الخاصة بالمنزل، يمكن ضبط هذا الإعداد باستخدام السمة 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, ) } }