GATT (Generic Attribute Profile) คือโปรไฟล์ Bluetooth Low Energy (BLE) ที่กำหนดโครงสร้างข้อมูลและกฎการแลกเปลี่ยนข้อมูลระหว่างอุปกรณ์ BLE GATT สร้างขึ้นบน Attribute Protocol (ATT) และจัดระเบียบข้อมูลในลำดับชั้น: บริการ (services) คุณลักษณะ (characteristics) และตัวอธิบาย (descriptors) ตามข้อมูลของ Bluetooth SIG (2025) โปรไฟล์ GATT ถูกใช้ใน 98% ของแอปพลิเคชัน BLE ทั้งหมด ตั้งแต่อุปกรณ์ติดตามฟิตเนสไปจนถึงล็อคอัจฉริยะและเซ็นเซอร์ทางการแพทย์
ประเด็นสำคัญ
GATT (Generic Attribute Profile) คือโปรไฟล์ Bluetooth Low Energy (BLE) ที่กำหนดว่าอุปกรณ์ BLE สองเครื่องแลกเปลี่ยนข้อมูลผ่าน Attribute Protocol (ATT) อย่างไร GATT ทำให้โครงสร้างข้อมูลเป็นมาตรฐาน: ข้อมูลทั้งหมดถูกจัดระเบียบในลำดับชั้น “บริการ → คุณลักษณะ → ตัวอธิบาย” โปรไฟล์นี้ถูกนำมาใช้ในข้อกำหนด Bluetooth 4.0 (2010) พร้อมกับ BLE และตั้งแต่นั้นมาก็ยังคงเป็นกลไกหลักในการถ่ายโอนข้อมูลสำหรับอุปกรณ์ Bluetooth ที่ประหยัดพลังงาน ซึ่งแตกต่างจาก Bluetooth แบบดั้งเดิมที่ข้อมูลถูกส่งผ่านพอร์ตอนุกรม (SPP) GATT ให้การเข้าถึงข้อมูลที่มีโครงสร้างผ่านการดำเนินการอ่าน เขียน และแจ้งเตือน
สแต็ก BLE ประกอบด้วยหลายชั้น: ชั้นกายภาพ (วิทยุ), ชั้นลิงก์ (การจัดการการเชื่อมต่อ), L2CAP (การควบคุมช่องทางตรรกะ), ATT (Attribute Protocol — การเข้าถึงแอตทริบิวต์) และ GATT (โปรไฟล์บนพื้นฐาน ATT) GATT เป็นชั้นสูงสุดที่นักพัฒนาแอปพลิเคชันทำงานด้วย ATT ที่อยู่ข้างใต้ให้การดำเนินการพื้นฐาน: การอ่าน การเขียน การแจ้งเตือน และการบอกกล่าวแอตทริบิวต์ GATT เพิ่มความหมาย: มันกำหนดว่าบริการและคุณลักษณะคืออะไร จัดกลุ่มอย่างไร และกฎใดที่ใช้กับการอ่านและเขียน ตาม Bluetooth Core Specification 5.4 (2023) GATT รองรับสูงสุด 65,535 แอตทริบิวต์ (บริการ + คุณลักษณะ + ตัวอธิบาย) บนอุปกรณ์เดียว
ลำดับชั้น GATT ประกอบด้วยสามระดับ บริการคือกลุ่มตรรกะของคุณลักษณะที่แก้ไขงานหนึ่งงาน (เช่น “บริการแบตเตอรี่” หรือ “บริการอัตราการเต้นของหัวใจ”) คุณลักษณะคือหน่วยข้อมูลที่มีประเภทที่รู้จัก: ระดับแบตเตอรี่ปัจจุบัน ค่าเซ็นเซอร์ สถานะสวิตช์ แต่ละคุณลักษณะมีค่าและตัวอธิบายหนึ่งรายการขึ้นไปที่อธิบายเมทาดาทา: หน่วยวัด การตั้งค่าการแจ้งเตือน ช่วงค่า UUID (ตัวระบุเฉพาะสากล) ระบุบริการและคุณลักษณะแต่ละรายการโดยไม่ซ้ำกัน
GATT รองรับการดำเนินการสี่ประเภทสำหรับการโต้ตอบกับคุณลักษณะ Read — ไคลเอนต์ขอค่าปัจจุบันของคุณลักษณะจากเซิร์ฟเวอร์ Write — ไคลเอนต์ส่งค่าใหม่ไปยังเซิร์ฟเวอร์ Notify — เซิร์ฟเวอร์ส่งค่าไปยังไคลเอนต์โดยไม่ต้องยืนยัน (เร็วกว่าแต่เชื่อถือได้น้อยกว่า) Indicate — เซิร์ฟเวอร์ส่งค่าพร้อมการยืนยันการรับ (เชื่อถือได้มากกว่าแต่ช้ากว่า) นักพัฒนาเลือกประเภทตามสถานการณ์: สำหรับค่าเซ็นเซอร์อัตราการเต้นของหัวใจ Notify ก็เพียงพอ สำหรับการเขียนการกำหนดค่าล็อคอัจฉริยะ จำเป็นต้องใช้ Write พร้อมการยืนยัน
// โครงสร้างข้อมูล GATT ในโค้ด Android
data class BleService(
val uuid: UUID,
val characteristics: List<BleCharacteristic>
)
data class BleCharacteristic(
val uuid: UUID,
val properties: Int, // READ, WRITE, NOTIFY, INDICATE
val descriptors: List<BleDescriptor>,
var value: ByteArray?
)
ข้อกำหนด BLE กำหนดโปรไฟล์หลักสองโปรไฟล์: GAP (Generic Access Profile) และ GATT (Generic Attribute Profile) GAP รับผิดชอบการค้นหาอุปกรณ์ การสร้างการเชื่อมต่อ และการจัดการการมองเห็น — มันคือ “ชั้นเครือข่าย” ของ BLE GATT รับผิดชอบการแลกเปลี่ยนข้อมูลหลังจากสร้างการเชื่อมต่อ — “ชั้นแอปพลิเคชัน” นักพัฒนาใช้ GAP สำหรับการสแกนและเชื่อมต่อกับอุปกรณ์ และใช้ GATT สำหรับการอ่าน เขียน และรับการแจ้งเตือนจากอุปกรณ์ที่เชื่อมต่อ
| คุณลักษณะ | GAP | GATT |
|---|---|---|
| วัตถุประสงค์ | การค้นหาและการเชื่อมต่อ | การแลกเปลี่ยนข้อมูล |
| บทบาท | ศูนย์กลาง / อุปกรณ์รอบข้าง | ไคลเอนต์ / เซิร์ฟเวอร์ |
| โปรโตคอล | HCI, ชั้นลิงก์ | ATT (Attribute Protocol) |
| ระยะ | ก่อนการเชื่อมต่อ | หลังการเชื่อมต่อ |
| คลาสหลัก | BluetoothAdapter | BluetoothGatt |
GATT กำหนดสองบทบาท: เซิร์ฟเวอร์ GATT และ ไคลเอนต์ GATT เซิร์ฟเวอร์คืออุปกรณ์ที่ให้ข้อมูล (เช่น อุปกรณ์ติดตามฟิตเนสที่ส่งค่าอัตราการเต้นของหัวใจ) ไคลเอนต์คืออุปกรณ์ที่ขอข้อมูล (เช่น สมาร์ทโฟนที่อ่านค่า) ในสถานการณ์ส่วนใหญ่ แอป Android ทำหน้าที่เป็นไคลเอนต์ GATT และอุปกรณ์รอบข้าง BLE ทำหน้าที่เป็นเซิร์ฟเวอร์ GATT อย่างไรก็ตาม Android ก็สามารถเป็นเซิร์ฟเวอร์ GATT ได้ — ตัวอย่างเช่น เมื่อแอปจำลองอุปกรณ์ BLE สำหรับอุปกรณ์อื่น บทบาทจะถูกกำหนดในขั้นตอนการตั้งค่าการเชื่อมต่อ GATT และไม่เปลี่ยนแปลงระหว่างเซสชัน
กระบวนการ การสื่อสาร GATT เริ่มต้นหลังจากสร้างการเชื่อมต่อ BLE ระหว่างอุปกรณ์ ก่อนอื่น ไคลเอนต์ GATT ค้นพบบริการบนเซิร์ฟเวอร์ GATT ผ่านการค้นพบบริการ — Android ทำสิ่งนี้โดยอัตโนมัติเมื่อเชื่อมต่อผ่าน BluetoothGatt.discoverServices() หลังจากการค้นพบ ไคลเอนต์จะได้รับรายการบริการ คุณลักษณะ และตัวอธิบายที่มีอยู่ จากนั้นไคลเอนต์สามารถอ่านค่าคุณลักษณะ (Read) เขียนค่าใหม่ (Write) หรือสมัครรับการแจ้งเตือน (Set Notify/Indicate) เซิร์ฟเวอร์ GATT สามารถส่ง Notify/Indicate ไปยังไคลเอนต์ได้ตลอดเวลาหลังจากสร้างการเชื่อมต่อ
โดยค่าเริ่มต้น ขนาดของแพ็คเก็ต GATT หนึ่งแพ็คเก็ต (MTU) ใน BLE คือ 23 ไบต์ โดยที่ 3 ไบต์เป็นส่วนหัว ATT และ 20 ไบต์เป็นข้อมูลpayload หากแอปพลิเคชันจำเป็นต้องส่งข้อมูลมากขึ้น (เช่น การอัปเดตเฟิร์มแวร์ OTA) สามารถขอเพิ่ม MTU เป็น 517 ไบต์ผ่าน requestMtu() ใน Android การเพิ่ม MTU ช่วยลดจำนวนแพ็คเก็ตที่จำเป็นสำหรับการส่งข้อมูลบล็อกเดียว — แทนที่จะส่ง 50 แพ็คเก็ตเล็ก คุณสามารถส่ง 2 แพ็คเก็ตใหญ่ ซึ่งช่วยลดการใช้พลังงานและเพิ่มความเร็วในการส่ง MTU สูงสุดขึ้นอยู่กับเวอร์ชัน BLE และความสามารถของชิป — Bluetooth 5.0 รองรับสูงสุด 517 ไบต์ เวอร์ชันเก่ากว่ารองรับสูงสุด 247 ไบต์
// สมัครรับการแจ้งเตือนคุณลักษณะ
fun enableNotifications(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
gatt.setCharacteristicNotification(characteristic, true)
// เปิดใช้งาน CCCD (ตัวอธิบายการกำหนดค่าคุณลักษณะไคลเอนต์)
val cccdUuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
val descriptor = characteristic.getDescriptor(cccdUuid)
descriptor?.let {
it.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
gatt.writeDescriptor(it)
}
}
ในการรับการแจ้งเตือนจาก เซิร์ฟเวอร์ GATT บน Android คุณต้องใช้ callback BluetoothGattCallback.onCharacteristicChanged() ในเมธอดนี้ แอปจะได้รับค่าคุณลักษณะที่อัปเดตทุกครั้งที่เซิร์ฟเวอร์ส่ง Notify หรือ Indicate สำหรับการประมวลผลข้อมูลแบบเรียลไทม์ ให้ใช้บัฟเฟอร์และ coroutine ของ Kotlin — ซึ่งจะป้องกันการบล็อกเธรด UI ระหว่างการแจ้งเตือนที่เข้มข้น (เช่น ค่าอัตราการเต้นของหัวใจมากกว่า 100 ครั้งต่อวินาที) สำหรับ Indicate คุณต้องเรียก gatt.sendResponse() ฝั่งเซิร์ฟเวอร์ — บนไคลเอนต์ Android สิ่งนี้ถูกจัดการโดยอัตโนมัติ
บน Android การทำงานกับ GATT ถูกนำไปใช้ผ่านคลาสของแพ็คเกจ android.bluetooth: BluetoothGatt (การเชื่อมต่อ), BluetoothGattService (บริการ), BluetoothGattCharacteristic (คุณลักษณะ) และ BluetoothGattDescriptor (ตัวอธิบาย) การเชื่อมต่อกับอุปกรณ์ BLE เริ่มต้นด้วยการเรียก BluetoothDevice.connectGatt() — เมธอดนี้คืนค่า BluetoothGatt ซึ่งใช้ดำเนินการทั้งหมดต่อไป callback GATT ทั้งหมดมาถึงใน BluetoothGattCallback — นี่คืออินเทอร์เฟซแบบอะซิงโครนัสที่ถูกเรียกบนเธรดเดียวกันกับที่สร้าง BluetoothGatt สำคัญ: การดำเนินการ GATT ทั้งหมดต้องทำตามลำดับ — การเรียกหลายการดำเนินการพร้อมกันบน BluetoothGatt เดียวกันทำให้เกิดข้อผิดพลาด
การจัดการ วงจรชีวิตการเชื่อมต่อ GATT อย่างถูกต้องเป็นสิ่งสำคัญสำหรับความเสถียรของแอป BLE หลังจากเรียก connectGatt() แอปรอ callback onConnectionStateChange() ด้วยสถานะ STATE_CONNECTED จากนั้นระบบจะเริ่มการค้นพบบริการโดยอัตโนมัติ หลังจากเสร็จสิ้นจะเรียก onServicesDiscovered() หลังจากนี้เท่านั้นที่คุณสามารถอ่าน เขียน และสมัครรับข้อมูลได้ เมื่อเสร็จแล้ว ให้เรียก gatt.close() ใน onDestroy() หรือ onPause() เสมอ — การเชื่อมต่อ GATT ที่ไม่ได้ปิดจะทำให้แบตเตอรี่หมดและอาจบล็อกการเชื่อมต่อใหม่กับอุปกรณ์เดียวกันบน Android
// เชื่อมต่อกับอุปกรณ์ BLE ผ่าน GATT
private val gattCallback = object : BluetoothGattCallback() {
override fun onConnectionStateChange(
gatt: BluetoothGatt, status: Int, newState: Int
) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices()
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
val service = gatt.getService(UUID.fromString("180D"))
val characteristic = service?.getCharacteristic(
UUID.fromString("2A37")
)
characteristic?.let { enableNotifications(gatt, it) }
}
}
Bluetooth SIG กำหนดโปรไฟล์และบริการ GATT มาตรฐานหลายสิบรายการด้วย UUID 16 บิตคงที่ ที่พบบ่อยที่สุด: Battery Service (UUID 180F, คุณลักษณะ Battery Level 2A19), บริการ Heart Rate (UUID 180D, คุณลักษณะ Heart Rate Measurement 2A37), บริการ Device Information (UUID 180A, คุณลักษณะ Manufacturer Name และ Serial Number) การใช้บริการมาตรฐานรับประกันความเข้ากันได้ระหว่างอุปกรณ์จากผู้ผลิตต่างๆ — สายรัดฟิตเนสใดๆ ที่มีบริการ Heart Rate ควรทำงานกับแอป Android ใดๆ ที่รองรับ
หากบริการมาตรฐานไม่ครอบคลุมงาน นักพัฒนาสามารถสร้าง บริการ GATT แบบกำหนดเองด้วย UUID 128 บิต เมื่อออกแบบบริการแบบกำหนดเอง คุณต้อง: กำหนดกลุ่มตรรกะของคุณลักษณะ (เช่น “บริการควบคุมล็อค”) กำหนดคุณสมบัติที่ถูกต้องให้แต่ละคุณลักษณะ (Read, Write, Notify) กำหนดค่าที่อนุญาตและหน่วยวัดผ่านตัวอธิบาย Characteristic Presentation Format สำหรับโปรโตคอลที่ซับซ้อน ขอแนะนำให้รวมคุณลักษณะ Command พร้อมคุณสมบัติ Write และคุณลักษณะ Status พร้อม Notify — ซึ่งเป็นไปตามรูปแบบ Command/Status ที่ใช้ในแอปพลิเคชัน BLE อุตสาหกรรม
// สร้างบริการ GATT แบบกำหนดเอง (Android เป็นเซิร์ฟเวอร์ GATT)
private fun createCustomService(): BluetoothGattService {
val serviceUuid = UUID.fromString("12345678-1234-5678-1234-56789abcdef0")
val service = BluetoothGattService(
serviceUuid, BluetoothGattService.SERVICE_TYPE_PRIMARY
)
val charUuid = UUID.fromString("12345678-1234-5678-1234-56789abcdef1")
val characteristic = BluetoothGattCharacteristic(
charUuid,
BluetoothGattCharacteristic.PROPERTY_READ or
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ
)
service.addCharacteristic(characteristic)
return service
}
คำถามที่พบบ่อย
GATT (Generic Attribute Profile) คือโปรไฟล์ Bluetooth Low Energy ที่กำหนดโครงสร้างการแลกเปลี่ยนข้อมูลระหว่างอุปกรณ์ จำเป็นสำหรับการมาตรฐานการเข้าถึงข้อมูล: อุปกรณ์ BLE ทั้งหมดจัดระเบียบข้อมูลในบริการและคุณลักษณะ ทำให้ไคลเอนต์ใดๆ สามารถอ่านค่าเซ็นเซอร์ ควบคุมอุปกรณ์ และรับการแจ้งเตือนได้
GAP รับผิดชอบการค้นหาและการเชื่อมต่ออุปกรณ์ BLE (การสแกน การประกาศ การตั้งค่าการเชื่อมต่อ) GATT รับผิดชอบการแลกเปลี่ยนข้อมูลหลังการเชื่อมต่อ (การอ่าน การเขียน การแจ้งเตือน) GAP ทำงานก่อนการเชื่อมต่อ GATT ทำงานหลังการเชื่อมต่อ ทั้งสองโปรไฟล์จำเป็นสำหรับ BLE แต่ทำหน้าที่ต่างกัน: GAP คือ “ชั้นเครือข่าย” GATT คือ “ชั้นแอปพลิเคชัน”
บริการมาตรฐานรวมถึง Battery Service (180F ระดับแบตเตอรี่), Heart Rate (180D ชีพจร), Device Information (180A ข้อมูลอุปกรณ์) แต่ละบริการประกอบด้วยหลายคุณลักษณะด้วย UUID 16 บิต นักพัฒนาสามารถสร้างบริการแบบกำหนดเองด้วย UUID 128 บิต สำหรับงานเฉพาะ — เช่น การควบคุมล็อคอัจฉริยะหรือการส่งข้อมูลอุปกรณ์ติดตามฟิตเนส
บน Android GATT ถูกนำไปใช้ผ่าน BluetoothGatt (การเชื่อมต่อ), BluetoothGattService (บริการ), BluetoothGattCharacteristic (คุณลักษณะ) และ BluetoothGattDescriptor (ตัวอธิบาย) การเชื่อมต่อทำผ่าน connectGatt() หลังจากนั้นเหตุการณ์จะมาถึงผ่าน BluetoothGattCallback: onConnectionStateChange, onServicesDiscovered, onCharacteristicChanged (สำหรับการแจ้งเตือน) การดำเนินการ GATT ทั้งหมดต้องทำตามลำดับ
UUID (ตัวระบุเฉพาะสากล) คือตัวระบุ 16 บิตหรือ 128 บิตที่ระบุบริการหรือคุณลักษณะใน GATT โดยไม่ซ้ำกัน บริการมาตรฐาน Bluetooth SIG ใช้ UUID 16 บิต (เช่น 180D สำหรับ Heart Rate) บริการแบบกำหนดเองของนักพัฒนาใช้ UUID 128 บิต (เช่น 12345678-1234-5678-1234-56789abcdef0) UUID ช่วยให้ไคลเอนต์ค้นหาข้อมูลที่จำเป็นบนเซิร์ฟเวอร์ GATT
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม