يمكن الوصول إلى واجهات برمجة التطبيقات الخاصة بالأجهزة من خلال واجهات برمجة تطبيقات Home لأجهزة Android. استورِد هذه الحزم إلى تطبيقك:
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id
لاستخدام أنواع أو سمات أجهزة معيّنة مع واجهات برمجة تطبيقات الأجهزة، يجب استيرادها بشكل فردي.
على سبيل المثال، لاستخدام سمة التشغيل/الإيقاف Matter ونوع الجهاز "وحدة توصيل التشغيل/الإيقاف"، استورِد الحِزم التالية إلى تطبيقك:
import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice
لمزيد من المعلومات، يُرجى الاطّلاع على نموذج البيانات على Android.
معالجة الأخطاء
يمكن لأي طريقة في Home APIs أن تؤدي إلى ظهور
HomeException، لذا ننصحك باستخدام مجموعة try-catch
لرصد HomeException في جميع الطلبات.
عند التعامل مع HomeException، تحقَّق من حقلَي
error.code و
error.message لمعرفة الخطأ الذي حدث. قد تكون هناك رموز أخطاء فرعية
أيضًا، لذا يمكنك استدعاء طريقة
getSubErrorCodes() والتحقّق من النتيجة.
ستؤدي أي استثناءات لم تتم معالجتها إلى تعطُّل تطبيقك.
لمزيد من المعلومات، يُرجى الاطّلاع على معالجة الأخطاء.
يمكنك الاطّلاع على إرسال أمر إلى جهاز للحصول على مثال.
عيّنة من المكالمات
الحصول على قائمة بالأجهزة
بعد الحصول على مرجع لمثيل Structure، يؤدي طلب devices() إلى عرض Flow من الأجهزة التي يمكنك الوصول إليها من تلك البنية:
// Get a flow of all devices accessible to the user val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices() // Calling list() on a HomeObjectsFlow returns the first Set of elements. val allDevices: Set<HomeDevice> = allDevicesFlow.list()
ومن هناك، يمكنك الوصول إلى حالات كل جهاز وإرسال الأوامر إلى الأجهزة.
في الإصدار 1.8 من واجهات برمجة تطبيقات Home، يمكنك اختيار أن تمثّل واجهة برمجة التطبيقات
كل جهاز متعدّد الأجزاء كجهاز واحد من خلال ضبط مَعلمة enableMultipartDevices في طريقة devices() على true. لمزيد من المعلومات، يُرجى الاطّلاع على الأجهزة المتعددة الأجزاء على Android.
قراءة حالة الجهاز
إليك مثال على التحقّق من السمة OnOff من سمة التشغيل/الإيقاف في الجهاز. باستخدام نموذج بيانات سمات واجهات برمجة تطبيقات Home، حيث يتم تحديد هذه السمة على أنّها OnOff، يمكنك استرداد بيانات السمات من خلال فئة standardTraits لنوع الجهاز:
// Assuming we have a device. val deviceFlow = home.devices().itemFlow(myDeviceId) val device = deviceFlow.first() // Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger // on the specific trait changes and not the whole type. val onOffTraitFlow: Flow<OnOff?> = device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged() val onOffTrait: OnOff = onOffTraitFlow.first()!!
يمكنك الاطّلاع على
distinctUntilChanged
لمزيد من المعلومات حول دالة Kotlin flow.
إبطال الحالة في اشتراك في سمة
تتيح واجهة TraitStateInvalidation إبطال حالة تم استردادها من خلال الاشتراكات في جهاز الاختبار في الحالات التي لا يتم فيها الإبلاغ عن الحالة بشكل صحيح.
ومن الأمثلة على الحالات التي قد لا يتم فيها الإبلاغ عن الحالة بشكل صحيح
استخدام سمات في سمات Matter بجودة "C"
أو بسبب تنفيذ الجهاز الذي يتسبب في حدوث المشكلة بشكل غير متوقع.
تُصدر واجهة برمجة التطبيقات هذه قراءة إلزامية لحالة السمة الحالية وتعرض النتيجة من خلال مسارات السمات الحالية.
احصل على السمة، ثم شغِّل forceRead على السمة:
val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()
الحصول على قائمة بسمات نوع الجهاز
يجب استخدام أنواع الأجهزة كنقطة دخول لقراءة السمات، لأنّها تقسّم الجهاز إلى أجزاء وظيفية (مثل نقاط النهاية في Matter).
وتراعي أيضًا تداخل السمات في حال كان الجهاز يتضمّن نوعَين من الأجهزة، وقد يكون لكليهما السمة نفسها. على سبيل المثال، إذا كان الجهاز مكبّر صوت ومصباحًا قابلاً للتعتيم، سيكون له سمتان للتشغيل/الإيقاف وسمتان للتحكّم في المستوى.
للحصول على قائمة بالسمات المتاحة لنوع الجهاز "مصباح قابل للتعتيم"، اتّبِع الخطوات التالية:
// Get all types available on this device. Requires the types to be part of the registry during // SDK initialization. val typesFlow: Flow<Set<DeviceType>> = device.types() // Get a snapshot of all types. val types: Set<DeviceType> = typesFlow.first() // Get the DimmableLightDevice instance from the set of types. val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull() // Get all traits in the type + traits registered val allTraits: Set<Trait> = dimmableLightDevice!!.traits()
يمكن أن يحدث نوع آخر من تعارض السمات عندما يتضمّن الجهاز سمتَين بالاسم نفسه. على سبيل المثال، يمكن أن تشير السمة onOff إلى مثيل للسمة العادية
OnOff، أو يمكن أن تشير إلى مثيل للسمة OnOff
التي تحدّدها الشركة المصنّعة. To eliminate any potential ambiguity as to which trait is
intended, a Trait instance referenced through a device should be preceded by a
qualifying namespace. بالنسبة إلى السمات العادية، أي تلك التي تشبه
مجموعات Matter العادية، استخدِم standardTraits. بالنسبة إلى سمات Google، استخدِم googleTraits:
// Accessing standard traits on the type. val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl
للوصول إلى سمة خاصة بشركة مصنّعة، يمكنك الإشارة إليها مباشرةً:
// Accessing a custom trait on the type. val customTrait = dimmableLightDevice.trait(MyCustomTrait)
الحصول على قائمة بالأجهزة التي تتضمّن سمة معيّنة
يمكن استخدام الدالة filter في Kotlin لتحسين طلبات البيانات من واجهة برمجة التطبيقات بشكل أكبر. على سبيل المثال، للحصول على قائمة بالأجهزة في المنزل التي تتضمّن جميعها سمة التشغيل/الإيقاف:
// Get all devices that support OnOff val onOffDevices: Flow<List<HomeDevice>> = home.devices().map { devices -> devices.filter { it.has(OnOff) } }
يمكنك الاطّلاع على واجهة Trait للحصول على قائمة كاملة بالسمات المتاحة في واجهات برمجة تطبيقات Home.
الحصول على قائمة بالأجهزة ذات الأنواع المشابهة
للحصول على قائمة بالأجهزة التي تمثّل جميع المصابيح في المنزل:
// Get a list of devices with similar device types (lights) val lightDevices = home.devices().map { devices -> devices.filter { it.has(DimmableLightDevice) || it.has(OnOffLightDevice) || it.has(ColorTemperatureLightDevice) || it.has(ExtendedColorLightDevice) } }
هناك أنواع متعددة من الأجهزة في واجهات برمجة تطبيقات Home التي يمكن أن تمثّل نوع جهاز أساسي. على سبيل المثال، لا يتوفّر نوع جهاز "مصباح". بدلاً من ذلك، هناك أربعة أنواع مختلفة من الأجهزة التي يمكن أن تمثل ضوءًا، كما هو موضح في المثال السابق. لذلك، للحصول على نظرة شاملة على نوع الجهاز ذي المستوى الأعلى في المنزل، يجب تضمين أنواع أجهزة متعددة في التدفقات التي تمت تصفيتها.
يمكنك الاطّلاع على واجهة DeviceType للحصول على قائمة كاملة بأنواع الأجهزة المتاحة في واجهات برمجة تطبيقات Home.
الحصول على معرّف المورّد أو معرّف المنتج لجهاز
تتضمّن السمة BasicInformation معلومات مثل معرّف المورّد ومعرّف المنتج واسم المنتج والرقم التسلسلي للجهاز:
// Get device basic information. All general information traits are on the RootNodeDevice type. val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!! println("vendorName ${basicInformation.vendorName}") println("vendorId ${basicInformation.vendorId}") println("productId ${basicInformation.productId}")
تحديد هوية الأجهزة من السحابة الإلكترونية إلى السحابة الإلكترونية للشركات المصنّعة للأجهزة
إذا كنت من صانعي الأجهزة وتصنع أجهزة Cloud-to-cloud،
يمكنك تضمين حقول السلسلة هذه في
استجابة SYNC لتحديد أجهزة
Cloud-to-cloud من خلال
سمة BasicInformation:
رقم تعريف المورّد الصادر عن Connectivity Standards Alliance (Alliance):
"matterOriginalVendorId": "0xfff1",معرّف منتج يحدّد بشكل فريد منتجًا تابعًا لمورّد:
"matterOriginalProductId": "0x1234",معرّف فريد للجهاز، يتم إنشاؤه بطريقة خاصة بالشركة المصنّعة:
"matterUniqueId": "matter-device-id",
عند إدخال حقول السلسلة هذه، استخدِم Matter
معرّفات المورّدين والمنتجات إذا كانت لديك. إذا لم تكن عضوًا في Alliance ولم يتم منحك رقمَي التعريف هذين، يمكنك ترك الحقلَين matterOriginalVendorId وmatterOriginalProductId فارغَين وتقديم matterUniqueId كمعرّف.
يوضّح نموذج استجابة SYNC استخدام هذه الحقول:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"agentUserId": "1836.15267389",
"devices": [
{
"id": "456",
"type": "action.devices.types.LIGHT",
"traits": [
"action.devices.traits.OnOff",
"action.devices.traits.Brightness",
"action.devices.traits.ColorSetting",
],
"willReportState": true,
"deviceInfo": { ... },
"matterOriginalVendorId": "0xfff1",
"matterOriginalProductId": "0x1234",
"matterUniqueId": "matter-device-id",
"otherDeviceIds": [
{
"deviceId": "local-device-id",
}
]
}
]
}
}
لمزيد من المعلومات، يمكنك الاطّلاع على
مستندات Cloud-to-cloud SYNC.
البيانات الوصفية للأجهزة والسمات
تحتوي الأجهزة والسمات في واجهات برمجة تطبيقات Home على بيانات وصفية مرتبطة بها، والتي يمكن أن تساعد في إدارة تجربة المستخدم في أحد التطبيقات.
تحتوي كل سمة في واجهات برمجة تطبيقات Home على السمة
sourceConnectivity
التي تتضمّن معلومات عن حالة السمة على الإنترنت وموقعها الجغرافي
(التوجيه المحلي أو عن بُعد).
الحصول على النوع الأساسي للجهاز
قد تعرض بعض الأجهزة أنواعًا متعددة من الأجهزة من خلال واجهات برمجة تطبيقات Home. لضمان عرض الخيارات المناسبة للمستخدمين في تطبيق (مثل التحكّم في الجهاز وعمليات التشغيل الآلي المقترَحة) لأجهزتهم، من المفيد التحقّق من نوع الجهاز الأساسي.
أولاً، احصل على أنواع الجهاز باستخدام
type()،
ثم حدِّد الأنواع الأساسية:
val types = device.types().first() val primaryTypes = types.filter { it.metadata.isPrimaryType }
التحقّق مما إذا كانت السمة متصلة بالإنترنت
استخدِم طريقة connectivityState() للتحقّق من إمكانية اتصال السمة:
val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState
قد تظهر بعض السمات، عادةً سمات Google smart home، على أنّها غير متصلة بالإنترنت إذا لم يكن الجهاز متصلاً بالإنترنت. ويرجع ذلك إلى أنّ هذه السمات مستندة إلى السحابة الإلكترونية ولا تتضمّن توجيهًا محليًا.
التحقّق من اتصال جهاز
يتم التحقّق من إمكانية الاتصال بجهاز معيّن على مستوى نوع الجهاز لأنّ بعض الأجهزة تتوافق مع أنواع متعددة من الأجهزة. الحالة التي يتم عرضها هي مزيج من حالات الاتصال لجميع السمات على هذا الجهاز.
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()
التحقّق من توجيه الشبكة لسمة معيّنة
تتوفّر أيضًا سمة "الموقع" في واجهات برمجة تطبيقات Home. يشير dataSourceLocality إلى ما إذا كان يتم توجيه السمة عن بُعد (من خلال السحابة الإلكترونية) أو محليًا (من خلال مركز محلي) أو من جهاز إلى آخر (مباشرةً من جهاز إلى جهاز، بدون مركز).
يمكن أن تظهر قيمة الموقع الجغرافي غير المعروفة UNSPECIFIED، على سبيل المثال، أثناء تشغيل التطبيق وقبل أن يتصل بمركز أو خادم لإمكانية اتصال الجهاز. لا يمكن الوصول إلى هذه الأجهزة، ولن تنجح طلبات التفاعل من الأوامر أو الأحداث. ويعود الأمر إلى العميل لتحديد كيفية التعامل مع هذه الأجهزة.
val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality
التحقّق من توجيه الشبكة لجهاز
مثل إمكانية الاتصال، يتم التحقّق من المنطقة المحلية على مستوى نوع الجهاز. والحالة التي يتم عرضها هي مزيج من الموقع الجغرافي لجميع السمات على هذا الجهاز.
val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality
قد تظهر حالة MIXED في سيناريو مشابه
لسيناريو إمكانية اتصال PARTIALLY_ONLINE: بعض السمات مستندة إلى السحابة الإلكترونية بينما
البعض الآخر محلي.
تغيير اسم جهاز
استخدِم طريقة setName() لتغيير اسم الجهاز:
mixerDevice.setName("Grendel")
سيتم اقتطاع الأسماء إذا تجاوزت الحدّ الأقصى المسموح به وهو 60 قيمة موضع رمز يونيكود (حرف)، ولن تظهر أي أخطاء. يتحمّل المطوّرون مسؤولية التعامل مع الأسماء الطويلة، ويمكنهم، على سبيل المثال، تحديد ما إذا كانوا يريدون إبلاغ المستخدمين بأنّ الأسماء سيتم اقتطاعها.
التحقّق من عضوية مجموعة لجهاز
يمكن أن ينتمي الجهاز الفعلي إلى مجموعة أجهزة واحدة أو أكثر. لمعرفة المجموعات التي ينتمي إليها الجهاز، يُرجى الاطّلاع على السمة GroupMembership في الجهاز:
val groupIds = device.trait(GroupMembershipTrait)?.groupObjectIds.orEmpty()
for (groupId in groupIds) {
println("HomeAPI", "Device belongs to group: $groupId")
}
في المقابل، يمكنك الاطّلاع على جميع الأجهزة الأعضاء التي تنتمي إلى
DeviceGroup من خلال استدعاء
مسار devices() على DeviceGroup:
group.devices(enableMultipartDevices = true).collect { members ->
println("HomeAPI", "Group contains ${members.size} devices")
}
لفحص أنواع الأجهزة التي تتيحها DeviceGroup وإرسال الأوامر إلى المجموعة ككيان واحد، يُرجى الاطّلاع على التحكّم في مجموعة أجهزة.