Descriptor คือแอตทริบิวต์เสริมของคุณลักษณะ BLE ที่ให้ข้อมูลเมตาหรือการกำหนดค่าสำหรับค่าของมัน Bluetooth Core Specification 5.4 กำหนดดิสคริปเตอร์เป็นส่วนสำคัญของโปรไฟล์ GATT: อธิบายหน่วยวัด ช่วงค่า ชื่อข้อความ และจัดการการสมัครรับการแจ้งเตือน ดิสคริปเตอร์ที่รู้จักมากที่สุดคือ Client Characteristic Configuration Descriptor (CCCD, 0x2902) ซึ่งอนุญาตให้ Central สมัครรับการแจ้งเตือนจากคุณลักษณะ ตามข้อมูลของ Bluetooth SIG มีการระบุดิสคริปเตอร์มาตรฐาน 8 ตัว และดิสคริปเตอร์ที่กำหนดเองสามารถสร้างขึ้นโดยนักพัฒนาสำหรับข้อมูลเมตาเพิ่มเติมใด ๆ
ประเด็นสำคัญ
Descriptor คือแอตทริบิวต์ของโปรโตคอล GATT ที่แนบมากับ Characteristic และให้ข้อมูลเพิ่มเติมเกี่ยวกับค่าหรือวิธีการใช้งาน ในคำศัพท์ของ GATT คุณลักษณะคือข้อมูล และดิสคริปเตอร์คือข้อมูลเมตาของข้อมูลนั้น
แต่ละ Characteristic สามารถมีดิสคริปเตอร์เป็นศูนย์หรือมากกว่า ดิสคริปเตอร์ถูกกำหนดเป็นแอตทริบิวต์แยกต่างหากในตาราง GATT และมี UUID 16 บิต ของตัวเองในพื้นที่ Bluetooth SIG ดิสคริปเตอร์ไม่สามารถดำรงอยู่อย่างอิสระ — มักถูกผูกไว้กับคุณลักษณะเฉพาะเสมอ
ตาม Bluetooth Core Specification 5.4 (2023) ดิสคริปเตอร์แบ่งออกเป็นสองประเภท: มาตรฐาน (กำหนดโดย Bluetooth SIG) และกำหนดเอง (กำหนดโดยนักพัฒนา) ดิสคริปเตอร์มาตรฐานมี UUID ในช่วง 0x2900–0x2908 และทำหน้าที่ที่กำหนดอย่างเคร่งครัด ดิสคริปเตอร์ที่กำหนดเองใช้ UUID 128 บิต เช่นเดียวกับบริการและคุณลักษณะที่กำหนดเอง
ดิสคริปเตอร์เป็นกลไกสำคัญสำหรับ การกำหนดค่าพฤติกรรม ของการเชื่อมต่อ 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)
// ตัวแทนรับค่าที่อัปเดต
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 | การรวมหลายคุณลักษณะ | รายการ UUID |
| 0x2906 | Valid Range | ช่วงค่าที่ถูกต้อง | uint16 × 2 (ต่ำสุด, สูงสุด) |
| 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 Blockchain จัดการ CCCD โดยอัตโนมัติเมื่อเปิดใช้งานการแจ้งเตือน ในขณะที่ Android ต้องเขียนค่าลงในดิสคริปเตอร์ด้วยตนเอง มาดูทั้งสองวิธี
ใน iOS นักพัฒนามักไม่ได้โต้ตอบกับดิสคริปเตอร์โดยตรง Core Blockchain จะค้นหา 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 client
คำถามที่พบบ่อย
CCCD จำเป็นสำหรับการจัดการการสมัคร: คุณสมบัติ Notify บ่งชี้ว่าคุณสามารถส่งการแจ้งเตือนได้ แต่ไม่ได้เปิดใช้งาน Central ต้องสมัครอย่างชัดเจนโดยเขียน 0x0001 ไปยัง CCCD ซึ่งป้องกันการส่งข้อมูลที่ไม่ต้องการไปยัง Central ที่ไม่พร้อม
ข้อกำหนดไม่ได้จำกัดจำนวนดิสคริปเตอร์ ในทางปฏิบัติ แต่ละคุณลักษณะมักมี 1–3 ดิสคริปเตอร์: CCCD (สำหรับคุณลักษณะที่มี Notify/Indicate), เลือกได้ User Description และ Presentation Format ดิสคริปเตอร์มากเกินไปจะเพิ่มขนาดของตาราง GATT
ในกรณีส่วนใหญ่ ไม่จำเป็น Core Blockchain บน iOS และ Android เพิ่ม CCCD โดยอัตโนมัติให้กับคุณลักษณะที่มีคุณสมบัติ Notify หรือ Indicate ดิสคริปเตอร์ที่กำหนดเองจะถูกสร้างขึ้นด้วยตนเองสำหรับข้อมูลเมตาเฉพาะเท่านั้น
ไม่ CCCD มีรูปแบบ (uint16) และวัตถุประสงค์ที่กำหนดอย่างเคร่งครัด — การจัดการ การแจ้งเตือน การเขียนค่าอื่นละเมิดข้อกำหนด Bluetooth และอาจทำให้การสมัครหยุดทำงาน สำหรับข้อมูลที่กำหนดเอง ให้ใช้ดิสคริปเตอร์ที่กำหนดเองด้วย UUID 128 บิต
User Description มีชื่อที่มนุษย์อ่านได้ของคุณลักษณะ — ตัวอย่างเช่น “อุณหภูมิอุปกรณ์” แทน UUID 0x2A6E แอปพลิเคชันสามารถแสดงชื่อนี้ในอินเทอร์เฟซ ทำให้การโต้ตอบกับอุปกรณ์ BLE เข้าใจได้สำหรับผู้ใช้โดยไม่ต้องใช้สตริงที่ถูกกำหนดตายตัว
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ