Descriptor هو سمة مساعدة لخاصية BLE توفر بيانات وصفية أو تكويناً لقيمتها. يحدد Bluetooth Core Specification 5.4 الواصفات كجزء لا يتجزأ من ملف GATT: فهي تصف وحدات القياس ونطاقات القيم والأسماء النصية وتدير الاشتراك في الإشعارات. أشهر واصف هو Client Characteristic Configuration Descriptor (CCCD, 0x2902)، الذي يسمح للمركز (Central) بالاشتراك في إشعارات الخاصية. وفقاً لـ Bluetooth SIG، هناك 8 واصفات قياسية محددة، ويمكن للمطور إنشاء واصفات مخصصة لأي بيانات وصفية إضافية.
النقاط الرئيسية
Descriptor هو سمة من سمات بروتوكول GATT تُلحق بالخاصية وتوفر معلومات إضافية عن قيمتها أو طريقة استخدامها. في مصطلحات GATT، الخاصية هي البيانات، والواصف هو البيانات الوصفية لتلك البيانات.
يمكن أن تحتوي كل خاصية على صفر أو أكثر من الواصفات. تُعرّف الواصفات كسمات منفصلة في جدول GATT ولها معرفات UUID خاصة بها بحجم 16 بت في مساحة Bluetooth SIG. لا يمكن للواصفات أن توجد بشكل مستقل — فهي مرتبطة دائماً بخاصية محددة.
وفقاً لـ Bluetooth Core Specification 5.4 (2023)، تنقسم الواصفات إلى فئتين: قياسية (محددة من قبل Bluetooth SIG) ومخصصة (يحددها المطور). الواصفات القياسية لها معرفات UUID في النطاق 0x2900–0x2908 وتؤدي وظائف محددة بدقة. تستخدم الواصفات المخصصة معرفات UUID بحجم 128 بت، على غرار الخدمات والخصائص المخصصة.
الواصفات هي آلية رئيسية لـ تكوين سلوك اتصال BLE. بدون CCCD (0x2902) يستحيل الاشتراك في الإشعارات، بدون Presentation Format (0x2904) لن يعرف المركز كيفية تفسير البايتات الأولية للخاصية.
CCCD بمعرف UUID 0x2902 هو أهم وأوسع واصف استخداماً في BLE. يدير اشتراك المركز في إشعارات Notify و Indicate من الخاصية. بدون الكتابة في CCCD، لن ترسل الخاصية الإشعارات، حتى لو كانت تمتلك خاصية Notify.
CCCD هو قيمة بحجم 16 بت حيث البت الأقل أهمية (0x0001) يفعل Notify، والبت الثاني (0x0002) يفعل Indicate. يكتب المركز القيمة المطلوبة في CCCD، وبالتالي يشترك في الإشعارات. إذا كتب المركز 0x0000 — يتم إلغاء الاشتراك.
آلية عمل CCCD كما يلي: عندما يكتشف المركز خاصية تدعم Notify، يجد واصف CCCD الخاص بها ويكتب 0x0001. بعد ذلك، في كل مرة يقوم الطرف المحيط (Peripheral) بتحديث قيمة الخاصية، يتم إرسالها تلقائياً إلى المركز المشترك عبر Handle Value Notification (بدون طلب من المركز).
وفقاً لـ Apple Core Bluetooth Programming Guide، يتم إدارة CCCD تلقائياً بواسطة النظام عند استدعاء setNotifyValue لخاصية معينة. لا يحتاج المطور إلى البحث والكتابة يدوياً في CCCD — يقوم Core Bluetooth بذلك تلقائياً عند تفعيل الإشعارات.
في iOS، يتم الاشتراك من خلال طريقة setNotifyValue على كائن CBPeripheral.
import CoreBluetooth
// الاشتراك في إشعارات الخاصية
peripheral.setNotifyValue(true, for: characteristic)
// يتلقى المفوض القيم المحدثة
func peripheral(
_ peripheral: CBPeripheral,
didUpdateValueFor characteristic: CBCharacteristic,
error: Error?
) {
// characteristic.value يحتوي على بيانات جديدة
guard let data = characteristic.value else { return }
}
في Android، يتم الاشتراك في الإشعارات من خلال BluetoothGatt.setCharacteristicNotification. يجب على المطور أيضاً كتابة القيمة 0x0001 يدوياً في CCCD.
import android.bluetooth.*;
// تفعيل الإشعارات
bluetoothGatt.setCharacteristicNotification(characteristic, true);
// كتابة 0x0001 في CCCD
BluetoothGattDescriptor descriptor = characteristic
.getDescriptor(
UUID.fromString("00002902-0000-1000-8000-00805F9B34FB")
);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
Bluetooth SIG حدد 8 واصفات قياسية للمهام الشائعة لتكوين الخصائص. كل واصف له UUID محدد بدقة وتنسيق قيمة محدد.
| UUID | اسم الواصف | الغرض | نوع القيمة |
|---|---|---|---|
| 0x2900 | Characteristic Extended Properties | خصائص إضافية للخاصية | uint16 (قناع بت) |
| 0x2901 | Characteristic User Description | الاسم النصي للخاصية | سلسلة UTF-8 |
| 0x2902 | Client Characteristic Configuration | إدارة الإشعارات | uint16 |
| 0x2903 | Server Characteristic Configuration | تكوين الخادم للبث | uint16 |
| 0x2904 | Characteristic Presentation Format | تنسيق عرض البيانات | هيكل (7 بايت) |
| 0x2905 | Characteristic Aggregate Format | دمج خصائص متعددة | قائمة UUIDs |
| 0x2906 | Valid Range | نطاق القيم الصالحة | uint16 × 2 (min, max) |
| 0x2907 | External Report Reference | مرجع تقرير خارجي | uint16 |
| 0x2908 | Report Reference | مرجع تقرير داخلي | uint8 + uint16 |
Characteristic User Description (0x2901) مفيد بشكل خاص لواجهة المستخدم: يحتوي على اسم مقروء للخاصية يمكن عرضه في واجهة التطبيق. على سبيل المثال، خاصية Battery Level قد تحتوي على واصف User Description بالقيمة «مستوى شحن البطارية».
Characteristic Presentation Format (0x2904) يحتوي على معلومات حول كيفية تفسير قيمة الخاصية: التنسيق (uint8, uint16, float)، الأس، وحدة القياس (عبر UUID من سجل Bluetooth SIG)، مساحة الأسماء والوصف. على سبيل المثال، يمكن أن تكون درجة الحرارة int16 بأس -2 (قيمة التقسيم 0.01°م) ووحدة قياس «درجة مئوية».
الوصول إلى الواصفات يختلف في iOS و Android. يدير Core Bluetooth تلقائياً CCCD عند تفعيل الإشعارات، بينما يتطلب Android كتابة يدوية للقيمة في الواصف. دعنا ننظر في كلا النهجين.
في iOS، لا يتفاعل المطور عادة مع الواصفات مباشرة. يجد Core Bluetooth تلقائياً CCCD ويكتب القيمة المطلوبة عند استدعاء setNotifyValue. لقراءة الواصفات يستخدم طريقة discoverDescriptors.
// اكتشاف الواصفات
peripheral.discoverDescriptors(for: characteristic)
// قراءة قيمة User Description
func peripheral(
_ peripheral: CBPeripheral,
didDiscoverDescriptorsFor characteristic: CBCharacteristic,
error: Error?
) {
for descriptor in characteristic.descriptors ?? [] {
if descriptor.uuid == CBUUID("2901") {
peripheral.readValue(for: descriptor)
}
}
}
في Android، يجب على المطور أن يجد واصف CCCD للخاصية ويكتب القيمة لتفعيل الإشعارات. هذه خطوة إضافية مقارنة بنظام iOS.
// قراءة قيمة واصف User Description
BluetoothGattDescriptor userDesc = characteristic
.getDescriptor(
UUID.fromString("00002901-0000-1000-8000-00805F9B34FB")
);
if (userDesc != null) {
bluetoothGatt.readDescriptor(userDesc);
}
الواصفات المخصصة تستخدم عندما لا تكون الواصفات القياسية لـ Bluetooth SIG كافية. على سبيل المثال، قد يضيف مصنع أجهزة استشعار طبية واصفاً بمعلومات معايرة المستشعر أو واصفاً بسجل الأخطاء.
يتم إنشاء واصف مخصص بمعرف UUID بحجم 128 بت، على غرار الخاصية المخصصة. على جانب Peripheral، يضيفه المطور إلى الخاصية عبر API المناسب. على جانب Central، يتم اكتشاف الواصف تلقائياً عند استدعاء discoverDescriptors.
عند إنشاء واصف مخصص، اتبع القواعد التالية: يجب أن يتطابق طول القيمة مع نوع البيانات المتوقع، ويجب تحديد حقوق الوصول (قراءة/كتابة) صراحة. لا تستخدم معرفات UUID من نطاق الواصفات القياسية لـ Bluetooth SIG (0x2900–0x2908) للأغراض المخصصة.
الخاصية والواصف هما مستويان مختلفان من سمات GATT. الخاصية هي نقطة بيانات، بينما الواصف هو بياناتها الوصفية أو تكوينها. يتجلى الفرق في عدة جوانب: الغرض، UUID، وقواعد الوصول.
الخاصية لها إعلان إلزامي موجود دائماً في جدول GATT. الواصف اختياري — قد لا تحتوي الخاصية على واصفات. يمكن قراءة الخاصية أو كتابتها أو إرسال إشعارات بشكل مستقل. الواصف مرتبط دائماً بخاصية ولا يوجد بشكل منفصل.
وفقاً لـ Bluetooth Core Specification 5.4، ترتيب السمات في جدول GATT هو كالتالي: إعلان الخدمة، إعلان الخاصية، قيمة الخاصية، واصفات الخاصية (إن وجدت)، ثم الخدمة التالية. هذا الترتيب إلزامي للتشغيل الصحيح لعملاء GATT.
الأسئلة الشائعة
CCCD ضروري لإدارة الاشتراك: خاصية Notify تشير فقط إلى أن الخاصية يمكنها إرسال الإشعارات، ولكنها لا تفعلها. يجب على المركز الاشتراك صراحة بكتابة 0x0001 في CCCD. هذا يمنع إرسال البيانات غير المرغوب فيها إلى مركز غير مستعد.
المواصفة لا تحد من عدد الواصفات. عملياً، تحتوي كل خاصية عادة على 1–3 واصفات: CCCD (للخصائص مع Notify/Indicate)، اختيارياً User Description و Presentation Format. كثرة الواصفات تزيد من حجم جدول GATT.
في معظم الحالات، لا. يقوم Core Bluetooth على iOS و Android بإضافة CCCD تلقائياً إلى الخصائص التي تمتلك خصائص Notify أو Indicate. يتم إنشاء الواصفات المخصصة يدوياً فقط لبيانات وصفية محددة.
لا، CCCD له تنسيق محدد بدقة (uint16) وغرض — إدارة الإشعارات. كتابة قيم أخرى تخالف مواصفة Bluetooth وقد تؤدي إلى توقف الاشتراك عن العمل. للبيانات المخصصة، استخدم واصفات مخصصة بمعرفات UUID بحجم 128 بت.
User Description يحتوي على اسم مقروء للخاصية — على سبيل المثال، «درجة حرارة الجهاز» بدلاً من UUID 0x2A6E. يمكن للتطبيق عرض هذا الاسم في الواجهة، مما يجعل التفاعل مع جهاز BLE مفهوماً للمستخدم دون سلاسل نصية مقننة.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.