Characteristic คือหน่วยข้อมูลพื้นฐานใน Bluetooth Low Energy ที่ Central ใช้อ่านหรือเขียนข้อมูลบนอุปกรณ์ Peripheral โดยแต่ละ Characteristic จะอยู่ใน GATT-เซอร์วิสที่กำหนด มี UUID เฉพาะตัวและชุดคุณสมบัติ (read, write, notify, indicate) ที่กำหนดการดำเนินการที่ทำได้ ตาม Bluetooth Core Specification 5.4 (2023), Bluetooth SIG ได้กำหนดลักษณะมาตรฐานมากกว่า 500 รายการสำหรับอุปกรณ์ทางการแพทย์ ฟิตเนส และอุตสาหกรรม นักพัฒนาสามารถสร้างลักษณะแบบกำหนดเองสำหรับส่งข้อมูลผู้ใช้ใดๆ ตั้งแต่ค่าจากเซนเซอร์ไปจนถึงคำสั่งควบคุมอุปกรณ์
ประเด็นสำคัญ
Characteristic คือแอตทริบิวต์ของ GATT-โปรโตคอลที่ประกอบด้วยค่า (value) และข้อมูลเมตา ในสถาปัตยกรรม BLE ข้อมูลจะไม่ถูกส่งโดยตรงระหว่างอุปกรณ์ แต่ผ่านการอ่านและเขียนค่าของลักษณะในเซอร์วิส หากเซอร์วิสเป็นโฟลเดอร์ Characteristic ก็คือไฟล์ภายในโฟลเดอร์นั้น
แต่ละ Characteristic ประกอบด้วยสามส่วน: การประกาศ (declaration), ค่า (value) และ descriptor การประกาศประกอบด้วย UUID และคุณสมบัติของลักษณะ ค่าคือข้อมูลที่ส่งระหว่าง Central และ Peripheral Descriptor ให้การกำหนดค่าเพิ่มเติม
ตาม Bluetooth Core Specification 5.4 (2023) การแลกเปลี่ยนข้อมูลทั้งหมดใน BLE เกิดขึ้นผ่านการดำเนินการกับลักษณะ แม้แต่โปรไฟล์มาตรฐานอย่าง Heart Rate Profile หรือ Battery Service ก็สร้างขึ้นจากชุดของลักษณะที่มี UUID ที่กำหนดไว้ล่วงหน้า ซึ่งช่วยให้อุปกรณ์จากผู้ผลิตต่างกันทำงานร่วมกันได้โดยไม่ต้องตั้งค่าล่วงหน้า
นักพัฒนาต้องเข้าใจว่า: แต่ละ Characteristic สามารถรองรับ การผสมผสานคุณสมบัติที่แตกต่างกัน ลักษณะหนึ่งอาจอ่านได้อย่างเดียว อีกแบบเขียนได้อย่างเดียว หรือแบบที่สามใช้สำหรับการแจ้งเตือน การเลือกคุณสมบัติที่ถูกต้องกำหนดรูปแบบการใช้งานและการใช้พลังงานของอุปกรณ์
คุณสมบัติ (properties) ของลักษณะกำหนดว่าการดำเนินการใดบ้างที่ได้รับอนุญาต เป็นบิตมาสก์ที่แต่ละบิตเปิดหรือปิดการดำเนินการเฉพาะ ด้านล่างคือคุณสมบัติหลัก
| คุณสมบัติ | บิต | คำอธิบาย | การใช้งานทั่วไป |
|---|---|---|---|
| Read | 0x02 | Central สามารถอ่านค่าปัจจุบันได้ | สถานะ ระดับแบตเตอรี่ การกำหนดค่า |
| Write | 0x08 | Central สามารถเขียนค่าใหม่ได้ | คำสั่งควบคุม การตั้งค่า |
| Notify | 0x10 | Peripheral ส่งค่าโดยไม่ยืนยัน | ข้อมูลสตรีมมิ่ง (ชีพจร อุณหภูมิ) |
| Indicate | 0x20 | Peripheral ส่งค่าพร้อมการยืนยัน | ข้อมูลสำคัญ (สัญญาณเตือน สถานะ) |
| Write Without Response | 0x04 | เขียนโดยไม่รอการยืนยันจากเซิร์ฟเวอร์ | การส่งคำสั่งความเร็วสูง |
การอนุญาต (permissions) คือระดับการเข้าถึงในระดับ GATT-เซิร์ฟเวอร์ ต่างจากคุณสมบัติที่ประกาศไว้ การอนุญาตจะถูกตรวจสอบในการดำเนินการแต่ละครั้ง ซึ่งอาจรวมถึงข้อกำหนดด้านการเข้ารหัสและการยืนยันตัวตน
Bluetooth SIG ได้กำหนดลักษณะมาตรฐานมากกว่า 500 รายการที่ครอบคลุมกรณีการใช้งาน BLE ทั่วไปส่วนใหญ่ การใช้ UUID มาตรฐานรับประกันว่าอุปกรณ์รับใดๆ จะตีความข้อมูลได้อย่างถูกต้องโดยไม่ต้องตั้งค่าล่วงหน้า
ด้านล่างคือลักษณะมาตรฐานที่ใช้บ่อยที่สุด:
| UUID | ชื่อ | ชนิดข้อมูล | เซอร์วิส |
|---|---|---|---|
| 0x2A19 | Battery Level | uint8 (0–100%) | Battery Service |
| 0x2A37 | Heart Rate Measurement | uint8 + แฟล็ก | Heart Rate |
| 0x2A6E | Temperature | int16 (0.01°C) | Environmental Sensing |
| 0x2A6F | Humidity | uint16 (0.01%) | Environmental Sensing |
| 0x2A00 | Device Name | UTF-8 string | Generic Access |
| 0x2A01 | Appearance | uint16 | Generic Access |
หากลักษณะมาตรฐานที่มีอยู่ครอบคลุมงานของคุณ — ให้ใช้มัน ซึ่งจะ ช่วยลดความซับซ้อนในการรับรอง Bluetooth และเพิ่มความเข้ากันได้กับระบบนิเวศ ให้สร้างลักษณะแบบกำหนดเองสำหรับข้อมูลเฉพาะที่ไม่มีในรีจิสทรีของ SIG เท่านั้น
การสร้างลักษณะ ดำเนินการบนฝั่ง Peripheral — อุปกรณ์ที่ให้ข้อมูล มาดูการนำไปใช้บน iOS (Swift) และ Android (Java)
Core Bluetooth มีคลาส CBMutableCharacteristic สำหรับสร้างลักษณะโดยระบุ UUID คุณสมบัติ และค่าเริ่มต้น
import CoreBluetooth
let characteristicUUID = CBUUID("2A19") // Battery Level characteristic
let characteristic = CBMutableCharacteristic(
type: characteristicUUID,
properties: [.read, .notify],
value: nil,
permissions: [.readable]
)
// อัปเดตค่าเมื่อมีการเปลี่ยนแปลง
let batteryData = Data([batteryLevel]) // uint8
peripheralManager.updateValue(
batteryData,
for: characteristic,
onSubscribedCentrals: nil
)
บน Android ลักษณะถูกสร้างผ่าน BluetoothGattCharacteristic โดยระบุ UUID คุณสมบัติ และ Permission
import android.bluetooth.*;
UUID charUuid = UUID.fromString("00002A19-0000-1000-8000-00805F9B34FB");
BluetoothGattCharacteristic characteristic =
new BluetoothGattCharacteristic(
charUuid,
BluetoothGattCharacteristic.PROPERTY_READ
| BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ
);
// ตั้งค่า
characteristic.setValue(batteryLevel, BluetoothGattCharacteristic.FORMAT_UINT8, 0);
gattServer.notifyCharacteristicChanged(device, characteristic, false);
การดำเนินการกับ Characteristic แบ่งเป็นสามประเภท: การอ่าน (read), การเขียน (write) และการแจ้งเตือน (notify/indicate) การเลือกดำเนินการขึ้นอยู่กับสถานการณ์: ข้อมูลตามคำขอใช้การอ่าน, คำสั่งใช้การเขียน, ข้อมูลสตรีมมิ่งใช้การสมัครรับการแจ้งเตือน
Read — Central ส่งคำขออ่านค่าของลักษณะ Peripheral ตอบกลับด้วยค่าปัจจุบัน การดำเนินการเป็นแบบซิงโครนัสและต้องมีการร้องขอที่ชัดเจนในแต่ละครั้ง ใช้สำหรับข้อมูลที่เปลี่ยนแปลงน้อยครั้ง: เวอร์ชันเฟิร์มแวร์, หมายเลขซีเรียล, การตั้งค่า
Write — Central ส่งข้อมูลไปยัง Peripheral มีสองโหมด: Write with Response (การยืนยันจาก Peripheral) และ Write Without Response (ไม่มีการยืนยัน) Write with Response รับประกันการส่ง — Peripheral ส่งการยืนยันหลังการเขียน Write Without Response เร็วกว่าแต่ไม่รับประกันการส่ง
Notify และ Indicate — Peripheral เริ่มต้นการส่งข้อมูลไปยัง Central ใน Notify ข้อมูลจะถูกส่งโดยไม่มีการยืนยัน — ถ้า Central ไม่สามารถรับแพ็กเก็ตได้ ข้อมูลจะสูญหาย ใน Indicate Central ส่งการยืนยัน (ระดับ PDU) ซึ่งรับประกันการส่ง Indicate ช้ากว่าแต่เชื่อถือได้มากกว่า สำหรับการสมัครรับการแจ้งเตือน Central เขียนค่า 0x0001 ไปยัง CCCD (Client Characteristic Configuration Descriptor)
MTU (Maximum Transmission Unit) กำหนดขนาดสูงสุดของแพ็กเก็ตข้อมูล BLE หนึ่งชุด โดยค่าเริ่มต้น MTU คือ 23 ไบต์ โดย 3 ไบต์เป็นส่วนหัว — เพย์โหลด (ATT payload) เท่ากับ 20 ไบต์ ซึ่งเพียงพอสำหรับข้อมูลเซนเซอร์ส่วนใหญ่ แต่ไม่เพียงพอสำหรับการส่งไฟล์หรือการกำหนดค่าขนาดใหญ่
Bluetooth Core Specification 5.4 รองรับ MTU negotiation (การเจรจา MTU) — Central และ Peripheral สามารถตกลงเรื่องขนาดแพ็กเก็ตที่ใหญ่ขึ้นได้ถึง 517 ไบต์ กระบวนการเป็นดังนี้: Central ส่งคำขอ MTU Exchange พร้อมข้อเสนอ MTU ของตัวเอง; Peripheral ตอบกลับด้วย MTU ของตัวเอง; ใช้ค่าที่น้อยกว่าจากสองค่า
// iOS ขอ MTU เมื่อเชื่อมต่อ
// MTU สูงสุดใน iOS คือ 185 ไบต์
func peripheral(
_ peripheral: CBPeripheral,
didDiscoverServices error: Error?
) {
// ขอ MTU สำหรับอุปกรณ์ Peripheral เฉพาะ
peripheral.maximumWriteValueLength(for: .withResponse)
}
ตามข้อมูลจาก Bluetooth SIG (2023) การเพิ่ม MTU จาก 23 เป็น 185 ไบต์ช่วยลดค่าใช้จ่ายในการส่งข้อมูลได้ถึง 80% เนื่องจากจำนวนแพ็กเก็ตที่ลดลง สำหรับแอปพลิเคชันที่ส่งค่าด้วยความถี่สูง (เช่น ECG หรือ accelerometer) การเพิ่ม MTU มีความสำคัญต่อความเสถียรของสตรีม
คำถามที่พบบ่อย
ข้อมูลจำเพาะ BLE ไม่ได้จำกัดจำนวนลักษณะในเซอร์วิส ในทางปฏิบัติ ข้อจำกัดขึ้นอยู่กับ หน่วยความจำที่มี ของ GATT-เซิร์ฟเวอร์และข้อกำหนดด้านประสิทธิภาพ สำหรับอุปกรณ์ฝังตัว แนะนำให้ไม่เกิน 10–15 ลักษณะต่อเซอร์วิส
Notify ส่งข้อมูลโดยไม่มีการยืนยัน — แพ็กเก็ตอาจสูญหายโดยไม่แจ้งผู้ส่ง Indicate ต้องการการยืนยัน (ACK) ในระดับโปรโตคอล ซึ่งรับประกันการส่ง Indicate ช้ากว่าแต่เชื่อถือได้มากกว่า สำหรับข้อมูลสำคัญ (สัญญาณเตือน คำสั่ง) ให้ใช้ Indicate
ใช่ ลักษณะสามารถมี การผสมผสานคุณสมบัติได้ ตัวอย่างเช่น ลักษณะการตั้งค่าสามารถรองรับทั้ง Read (อ่านค่าปัจจุบัน) และ Write (เปลี่ยนแปลงการตั้งค่า) ผสมผสานคุณสมบัติตามสถานการณ์การใช้งานของคุณ
ใช้ MTU negotiation เพื่อเพิ่มขนาดแพ็กเก็ตเป็น 185–517 ไบต์ หากข้อมูลยังใหญ่เกินไป — ให้ทำ fragment ในระดับแอปพลิเคชัน: แบ่งข้อมูลเป็นคำขอต่อเนื่องหลายชุดพร้อมควบคุมความสมบูรณ์
หากงานของคุณครอบคลุมโดยลักษณะมาตรฐาน — ให้ใช้ UUID จากรีจิสทรีของ Bluetooth SIG ซึ่งช่วยให้การรับรองง่ายขึ้นและรับประกันความเข้ากันได้กับระบบนิเวศ ให้สร้าง UUID แบบกำหนดเองสำหรับข้อมูลเฉพาะของผู้ผลิตภายนอกเท่านั้น
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ