Дескриптор — е помощен атрибут на BLE характеристиката, който предоставя метаданни или конфигурация за нейната стойност. Bluetooth Core Specification 5.4 определя дескрипторите като неотъемлема част от GATT профила: те описват мерни единици, диапазони на стойности, текстови имена и управляват абонамента за известия. Най-известният дескриптор е Client Characteristic Configuration Descriptor (CCCD, 0x2902), който позволява на Central да се абонира за известия от характеристиката. Според Bluetooth SIG, са специфицирани 8 стандартни дескриптора, а персонализирани дескриптори могат да бъдат създадени от разработчика за всяки допълнителни метаданни.
Основни моменти
Дескриптор — е атрибут на GATT протокола, който се прикрепя към характеристиката и предоставя допълнителна информация за нейната стойност или начин на използване. В терминологията на GATT, характеристиката е данните, а дескрипторът е метаданните на тези данни.
Всяка характеристика може да има нула или повече дескриптори. Дескрипторите се определят като отделни атрибути в GATT таблицата и имат собствени 16-битови UUID в пространството на Bluetooth SIG. Дескрипторите не могат да съществуват самостоятелно — те винаги са свързани с конкретна характеристика.
Според Bluetooth Core Specification 5.4 (2023), дескрипторите се делят на две категории: стандартни (определени от Bluetooth SIG) и персонализирани (определяни от разработчика). Стандартните дескриптори имат UUID в диапазона 0x2900–0x2908 и изпълняват строго определени функции. Персонализираните дескриптори използват 128-битови UUID, подобно на персонализираните услуги и характеристики.
Дескрипторите са ключов механизъм за конфигуриране на поведението на BLE връзката. Без CCCD (0x2902) не можете да се абонирате за известия, без Presentation Format (0x2904) Central няма да знае как да интерпретира суровите байтове на характеристиката.
CCCD с UUID 0x2902 е най-важният и най-широко използван дескриптор в BLE. Той управлява абонамента на Central за известия (Notify) и потвърдени известия (Indicate) от характеристиката. Без записване в CCCD, характеристиката няма да изпраща известия, дори ако има свойство Notify.
CCCD е 16-битова стойност, в която най-малкият бит (0x0001) включва Notify, а вторият бит (0x0002) включва Indicate. Central записва желаната стойност в CCCD, като се абонира за известия. Ако Central запише 0x0000 — абонаментът се отменя.
Механизмът на работа на CCCD е следният: когато Central открие характеристика с подкрепа за Notify, той намира нейния CCCD дескриптор и записва 0x0001. След това, всякака когато Peripheral актуализира стойността на характеристиката, тя се изпраща автоматично до абонирания Central чрез Handle Value Notification (без заявка от Central).
Според Apple Core Bluetooth Programming Guide, CCCD се управлява автоматично от системата при извикване на setNotifyValue за характеристиката. Разработчикът няма нужда ръчно да търси и записва CCCD — Core Bluetooth прави това автоматично при активиране на известията.
В iOS абонирането се извършва чрез метода setNotifyValue на обекта CBPeripheral.
import CoreBluetooth
// Абонирайте се за известия на характеристиката
peripheral.setNotifyValue(true, for: characteristic)
// Delegate получава актуализирани стойности
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 | Конфигуриране на сървъра за broadcast | uint16 |
| 0x2904 | Characteristic Presentation Format | Формат за представяне на данни | Структура (7 байта) |
| 0x2905 | Characteristic Aggregate Format | Обединяване на няколко характеристики | Списък на UUID |
| 0x2906 | Valid Range | Диапазон на допустими стойности | uint16 × 2 (min, max) |
| 0x2907 | External Report Reference | Препратка към външен доклад | uint16 |
| 0x2908 | Report Reference | Препратка към вътрешен доклад | uint8 + uint16 |
Characteristic User Description (0x2901) е особено полезен за UI: той съдържа човешки четимо име на характеристиката, което може да се показва в интерфейса на приложението. Например, характеристиката Battery Level може да има дескриптор User Description със стойност „Ниво на зареждане на батерията“.
Characteristic Presentation Format (0x2904) съдържа информация за това как да се интерпретира стойността на характеристиката: формат (uint8, uint16, float), експонент, мерна единица (чрез UUID от регистъра на Bluetooth SIG), пространство от имена и описание. Например, температурата може да бъде int16 с експонент -2 (стойност на деление 0.01°C) и мерна единица „градуси Целзий“.
Достъп до дескрипторите се различава в 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 не са достатъчни. Например, производител на медицински сензори може да добави дескриптор с информация за калибриране на сензора или дескриптор с дневник на грешките.
Персонализиран дескриптор се създава с 128-битов UUID, като персонализирана характеристика. От страна на Peripheral, разработчикът го добавя към характеристиката чрез съответното API. От страна на Central, дескрипторът се открива автоматично при извикване на discoverDescriptors.
При създаване на персонализиран дескриптор спазвайте правилата: дължината на стойността трябва да съответства на очаквания тип данни, правата за достъп (read/write) трябва да бъдат явно посочени. Не използвайте UUID от диапазона на стандартните дескриптори на Bluetooth SIG (0x2900–0x2908) за персонализирани цели.
Характеристика и дескриптор — това са различни нива на GATT атрибутите. Характеристиката е точка на данни, а дескрипторът е нейните метаданни или конфигурация. Разликата се проявява в няколко аспекта: предназначение, UUID и правила за достъп.
Характеристиката има задължителна декларация (declaration), която винаги се намира в GATT таблицата. Дескрипторът е опционален — характеристиката може да няма дескриптори. Характеристиката може да бъде четена, записвана или да изпраща известия независимо. Дескрипторът винаги е свързан с характеристиката и не съществува отделно.
Според Bluetooth Core Specification 5.4, в GATT таблицата редът на атрибутите е следният: декларация на услугата, декларация на характеристиката, стойност на характеристиката, дескриптори на характеристиката (ако има), след което следващата услуга. Този ред е задължителен за коректната работа на GATT клиентите.
Често задавани въпроси
CCCD е нужен за управление на абонамента: свойство Notify казва само, че характеристиката може да изпраща известия, но не ги включва. Central трябва явно да се абонира, като запише 0x0001 в CCCD. Това предотвратява нежеланото изпращане на данни до неподготвен Central.
Спецификацията не ограничава броя на дескрипторите. На практика, всяка характеристика обикновено има 1–3 дескриптора: CCCD (за характеристики с Notify/Indicate), опционално User Description и Presentation Format. Това увеличава размера на GATT таблицата.
В повечето случаи не. Core Bluetooth на iOS и Android автоматично добавят CCCD към характеристиките, които имат свойства Notify или Indicate. Персонализираните дескриптори се създават ръчно само за специфични метаданни.
Не, CCCD има строго определен формат (uint16) и предназначение — управление на известията. Записването на други стойности нарушава Bluetooth спецификацията и може да доведе до неработоспособност на абонамента. За персонализирани данни използвайте персонализирани дескриптори с 128-битов UUID.
User Description съдържа човешки четимо име на характеристиката — например, „Температура на корпуса“ вместо UUID 0x2A6E. Приложението може да покаже това име в интерфейса, правейки взаимодействието с BLE устройството разбираемо за потребителя без твърдо кодирани низове.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също