GATT — nó là gì, Generic Attribute Profile và triển khai trong Android

Tác giả: IT Sectr Đã đăng: 2026-07-14 Thời gian đọc: 10 phút

GATT (Generic Attribute Profile) là một hồ sơ Bluetooth Low Energy (BLE) xác định cấu trúc dữ liệu và quy tắc trao đổi thông tin giữa các thiết bị BLE. GATT được xây dựng trên Giao thức Thuộc tính (ATT) và tổ chức dữ liệu theo hệ thống phân cấp: dịch vụ (services), đặc tính (characteristics) và bộ mô tả (descriptors). Theo Bluetooth SIG (2025), hồ sơ GATT được sử dụng trong 98% tất cả các ứng dụng BLE — từ máy theo dõi sức khỏe đến khóa thông minh và cảm biến y tế.

Những điểm chính

  • GATT — một hồ sơ BLE xác định cấu trúc truyền dữ liệu qua các dịch vụ, đặc tính và bộ mô tả
  • Hệ thống phân cấp — một dịch vụ chứa các đặc tính, mỗi đặc tính có một giá trị với các bộ mô tả tùy chọn
  • UUID — mỗi dịch vụ và đặc tính được xác định bằng UUID 16 bit (tiêu chuẩn) hoặc 128 bit (tùy chỉnh)
  • Vai trò — Máy chủ GATT (cung cấp dữ liệu) và Máy khách GATT (đọc/ghi dữ liệu)
  • API Android — BluetoothGatt, BluetoothGattService, BluetoothGattCharacteristic — các lớp chính để làm việc với GATT

GATT là gì?

GATT (Generic Attribute Profile) là một hồ sơ Bluetooth Low Energy (BLE) xác định cách hai thiết bị BLE trao đổi dữ liệu qua Giao thức Thuộc tính (ATT). GATT chuẩn hóa cấu trúc dữ liệu: tất cả dữ liệu được tổ chức theo hệ thống phân cấp “dịch vụ → đặc tính → bộ mô tả”. Hồ sơ này được giới thiệu trong đặc tả Bluetooth 4.0 (2010) cùng với BLE và từ đó vẫn là cơ chế truyền dữ liệu chính cho các thiết bị Bluetooth tiết kiệm năng lượng. Không giống như Bluetooth cổ điển, nơi dữ liệu được truyền qua cổng nối tiếp (SPP), GATT cung cấp quyền truy cập có cấu trúc vào dữ liệu thông qua các hoạt động đọc, ghi và thông báo.

Vai trò của GATT trong ngăn xếp BLE

Ngăn xếp BLE bao gồm nhiều lớp: Lớp Vật lý (radio), Lớp Liên kết (quản lý kết nối), L2CAP (điều khiển kênh logic), ATT (Giao thức Thuộc tính — truy cập thuộc tính) và GATT (hồ sơ dựa trên ATT). GATT là lớp cao nhất mà các nhà phát triển ứng dụng làm việc cùng. ATT bên dưới cung cấp các hoạt động cơ bản: đọc, ghi, thông báo và chỉ thị thuộc tính. GATT thêm ngữ nghĩa: nó xác định dịch vụ và đặc tính là gì, chúng được nhóm như thế nào và quy tắc nào áp dụng khi đọc và ghi chúng. Theo Bluetooth Core Specification 5.4 (2023), GATT hỗ trợ tới 65.535 thuộc tính (dịch vụ + đặc tính + bộ mô tả) trên một thiết bị.

Kiến trúc GATT: dịch vụ, đặc tính và bộ mô tả

Hệ thống phân cấp GATT bao gồm ba cấp độ. Dịch vụ là một nhóm logic các đặc tính giải quyết một nhiệm vụ (ví dụ: “Dịch vụ Pin” hoặc “Dịch vụ Nhịp tim”). Đặc tính là một đơn vị dữ liệu với một kiểu đã biết: mức pin hiện tại, giá trị cảm biến, trạng thái công tắc. Mỗi đặc tính có một giá trị và một hoặc nhiều Bộ mô tả mô tả siêu dữ liệu: đơn vị đo lường, cài đặt thông báo, phạm vi giá trị. UUID (Định danh duy nhất toàn cầu) xác định duy nhất mỗi dịch vụ và mỗi đặc tính.

Các loại hoạt động với đặc tính

GATT hỗ trợ bốn loại hoạt động để tương tác với các đặc tính. Read — máy khách yêu cầu giá trị hiện tại của một đặc tính từ máy chủ. Write — máy khách gửi một giá trị mới đến máy chủ. Notify — máy chủ gửi một giá trị đến máy khách mà không xác nhận (nhanh hơn nhưng kém tin cậy hơn). Indicate — máy chủ gửi một giá trị kèm xác nhận đã nhận (tin cậy hơn nhưng chậm hơn). Nhà phát triển chọn loại dựa trên kịch bản: cho giá trị cảm biến nhịp tim, Notify là đủ; để ghi cấu hình khóa thông minh, cần Write kèm xác nhận.

kotlin
// Cấu trúc dữ liệu GATT trong mã 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?
)

GATT và GAP: sự khác biệt giữa các hồ sơ BLE

Đặc tả BLE xác định hai hồ sơ chính: GAP (Generic Access Profile) và GATT (Generic Attribute Profile). GAP chịu trách nhiệm phát hiện thiết bị, thiết lập kết nối và quản lý khả năng hiển thị — nó là “lớp mạng” của BLE. GATT chịu trách nhiệm trao đổi dữ liệu sau khi thiết lập kết nối — “lớp ứng dụng”. Nhà phát triển sử dụng GAP để quét và kết nối với thiết bị, và GATT để đọc, ghi và nhận thông báo từ thiết bị đã kết nối.

Đặc điểmGAPGATT
Mục đíchPhát hiện và kết nốiTrao đổi dữ liệu
Vai tròTrung tâm / Ngoại viMáy khách / Máy chủ
Giao thứcHCI, Lớp Liên kếtATT (Giao thức Thuộc tính)
Giai đoạnTrước khi kết nốiSau khi kết nối
Lớp chínhBluetoothAdapterBluetoothGatt

Vai trò trong GATT

GATT xác định hai vai trò: Máy chủ GATTMáy khách GATT. Máy chủ là thiết bị cung cấp dữ liệu (ví dụ: máy theo dõi sức khỏe gửi giá trị nhịp tim). Máy khách là thiết bị yêu cầu dữ liệu (ví dụ: điện thoại thông minh đọc giá trị). Trong hầu hết các kịch bản, ứng dụng Android hoạt động như Máy khách GATT và thiết bị ngoại vi BLE hoạt động như Máy chủ GATT. Tuy nhiên, Android cũng có thể là Máy chủ GATT — ví dụ: khi một ứng dụng mô phỏng thiết bị BLE cho các thiết bị khác. Vai trò được xác định ở giai đoạn thiết lập kết nối GATT và không thay đổi trong suốt phiên.

Cách giao tiếp GATT hoạt động trong BLE

Quá trình giao tiếp GATT bắt đầu sau khi kết nối BLE giữa các thiết bị được thiết lập. Đầu tiên, Máy khách GATT khám phá các dịch vụ trên Máy chủ GATT thông qua Khám phá Dịch vụ — Android thực hiện việc này tự động khi kết nối qua BluetoothGatt.discoverServices(). Sau khi khám phá, máy khách nhận được danh sách các dịch vụ, đặc tính và bộ mô tả có sẵn. Sau đó, máy khách có thể đọc giá trị đặc tính (Read), ghi giá trị mới (Write) hoặc đăng ký nhận thông báo (Set Notify/Indicate). Máy chủ GATT có thể gửi Notify/Indicate đến máy khách bất kỳ lúc nào sau khi kết nối được thiết lập.

MTU — Đơn vị truyền tối đa

Theo mặc định, kích thước của một gói GATT (MTU) trong BLE là 23 byte, trong đó 3 byte là tiêu đề ATT và 20 byte là dữ liệu hữu ích. Nếu ứng dụng cần truyền nhiều dữ liệu hơn (ví dụ: cập nhật chương trình cơ sở OTA), có thể yêu cầu tăng MTU lên tới 517 byte qua requestMtu() trong Android. MTU tăng lên làm giảm số lượng gói cần thiết để truyền một khối dữ liệu — thay vì 50 gói nhỏ, bạn có thể gửi 2 gói lớn, giúp giảm mức tiêu thụ điện năng và tăng tốc độ truyền. MTU tối đa phụ thuộc vào phiên bản BLE và khả năng của chip — Bluetooth 5.0 hỗ trợ tới 517 byte, các phiên bản cũ hơn tới 247 byte.

kotlin
// Đăng ký nhận thông báo đặc tính
fun enableNotifications(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
    gatt.setCharacteristicNotification(characteristic, true)

    // Bật CCCD (Bộ mô tả cấu hình đặc tính máy khách)
    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)
    }
}

Xử lý thông báo

Để nhận thông báo từ Máy chủ GATT trên Android, bạn cần triển khai callback BluetoothGattCallback.onCharacteristicChanged(). Trong phương thức này, ứng dụng nhận được giá trị đặc tính đã cập nhật mỗi khi máy chủ gửi Notify hoặc Indicate. Để xử lý dữ liệu thời gian thực, hãy sử dụng bộ đệm và coroutine Kotlin — điều này ngăn chặn việc chặn luồng UI trong quá trình thông báo cường độ cao (ví dụ: hơn 100 giá trị nhịp tim mỗi giây). Đối với Indicate, bạn phải gọi gatt.sendResponse() ở phía máy chủ — trên máy khách Android, việc này được xử lý tự động.

Triển khai GATT trên Android

Trên Android, làm việc với GATT được triển khai thông qua các lớp của gói android.bluetooth: BluetoothGatt (kết nối), BluetoothGattService (dịch vụ), BluetoothGattCharacteristic (đặc tính) và BluetoothGattDescriptor (bộ mô tả). Kết nối đến thiết bị BLE bắt đầu bằng cách gọi BluetoothDevice.connectGatt() — phương thức này trả về một BluetoothGatt qua đó tất cả các hoạt động tiếp theo được thực hiện. Tất cả các callback GATT đến trong BluetoothGattCallback — đây là một giao diện bất đồng bộ được gọi trên cùng luồng nơi BluetoothGatt được tạo. Quan trọng: tất cả các hoạt động GATT phải được thực hiện tuần tự — gọi nhiều hoạt động đồng thời trên cùng một BluetoothGatt sẽ dẫn đến lỗi.

Vòng đời kết nối GATT

Quản lý đúng vòng đời kết nối GATT là rất quan trọng cho sự ổn định của ứng dụng BLE. Sau khi gọi connectGatt(), ứng dụng chờ callback onConnectionStateChange() với trạng thái STATE_CONNECTED. Sau đó, hệ thống tự động bắt đầu Khám phá Dịch vụ, sau khi hoàn thành, onServicesDiscovered() được gọi. Chỉ sau đó bạn mới có thể thực hiện đọc, ghi và đăng ký. Khi kết thúc, luôn gọi gatt.close() trong onDestroy() hoặc onPause() — các kết nối GATT không đóng sẽ tiêu hao pin và có thể chặn việc kết nối lại với cùng một thiết bị trên Android.

kotlin
// Kết nối đến thiết bị BLE qua 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) }
    }
}

Các hồ sơ và dịch vụ GATT tiêu chuẩn

Bluetooth SIG xác định hàng tá hồ sơ và dịch vụ GATT tiêu chuẩn với UUID 16 bit cố định. Phổ biến nhất: Battery Service (UUID 180F, đặc tính Battery Level 2A19), dịch vụ Heart Rate (UUID 180D, đặc tính Heart Rate Measurement 2A37), dịch vụ Device Information (UUID 180A, đặc tính Manufacturer Name và Serial Number). Sử dụng các dịch vụ tiêu chuẩn đảm bảo khả năng tương thích giữa các thiết bị từ các nhà sản xuất khác nhau — bất kỳ vòng đeo sức khỏe nào có dịch vụ Heart Rate đều phải hoạt động với bất kỳ ứng dụng Android nào hỗ trợ nó.

Thiết kế dịch vụ GATT tùy chỉnh

Nếu các dịch vụ tiêu chuẩn không bao phủ nhiệm vụ, nhà phát triển có thể tạo dịch vụ GATT tùy chỉnh với UUID 128 bit. Khi thiết kế một dịch vụ tùy chỉnh, bạn cần: xác định một nhóm logic các đặc tính (ví dụ: “Dịch vụ điều khiển khóa”), gán cho mỗi đặc tính các thuộc tính chính xác (Read, Write, Notify), xác định các giá trị cho phép và đơn vị đo lường thông qua bộ mô tả Characteristic Presentation Format. Đối với các giao thức phức tạp, nên bao gồm một đặc tính Command với thuộc tính Write và một đặc tính Status với Notify — điều này tuân theo mẫu Command/Status được áp dụng trong các ứng dụng BLE công nghiệp.

kotlin
// Tạo dịch vụ GATT tùy chỉnh (Android như Máy chủ 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
}

Câu hỏi thường gặp

GATT trong BLE là gì và tại sao cần nó?

GATT (Generic Attribute Profile) là một hồ sơ Bluetooth Low Energy xác định cấu trúc trao đổi dữ liệu giữa các thiết bị. Nó cần thiết để chuẩn hóa quyền truy cập thông tin: tất cả các thiết bị BLE tổ chức dữ liệu thành các dịch vụ và đặc tính, cho phép bất kỳ máy khách nào đọc giá trị cảm biến, điều khiển thiết bị và nhận thông báo.

GATT khác GAP như thế nào?

GAP chịu trách nhiệm phát hiện và kết nối thiết bị BLE (quét, quảng bá, thiết lập kết nối). GATT chịu trách nhiệm trao đổi dữ liệu sau khi kết nối (đọc, ghi, thông báo). GAP hoạt động trước khi kết nối, GATT sau đó. Cả hai hồ sơ đều bắt buộc cho BLE, nhưng thực hiện các chức năng khác nhau: GAP là “lớp mạng”, GATT là “lớp ứng dụng”.

Có những dịch vụ và đặc tính GATT nào?

Các dịch vụ tiêu chuẩn bao gồm Battery Service (180F, mức pin), Heart Rate (180D, nhịp tim), Device Information (180A, dữ liệu thiết bị). Mỗi dịch vụ chứa nhiều đặc tính với UUID 16 bit. Nhà phát triển có thể tạo các dịch vụ tùy chỉnh với UUID 128 bit cho các tác vụ cụ thể — như điều khiển khóa thông minh hoặc truyền dữ liệu máy theo dõi sức khỏe.

GATT hoạt động như thế nào trên Android?

Trên Android, GATT được triển khai qua BluetoothGatt (kết nối), BluetoothGattService (dịch vụ), BluetoothGattCharacteristic (đặc tính) và BluetoothGattDescriptor (bộ mô tả). Kết nối được thực hiện qua connectGatt(), sau đó các sự kiện đến qua BluetoothGattCallback: onConnectionStateChange, onServicesDiscovered, onCharacteristicChanged (cho thông báo). Tất cả các hoạt động GATT phải được thực hiện tuần tự.

UUID trong GATT là gì?

UUID (Định danh duy nhất toàn cầu) là một định danh 16 bit hoặc 128 bit xác định duy nhất một dịch vụ hoặc đặc tính trong GATT. Các dịch vụ tiêu chuẩn Bluetooth SIG sử dụng UUID 16 bit (ví dụ: 180D cho Heart Rate). Các dịch vụ tùy chỉnh của nhà phát triển sử dụng UUID 128 bit (ví dụ: 12345678-1234-5678-1234-56789abcdef0). UUID cho phép máy khách tìm dữ liệu cần thiết trên Máy chủ GATT.

Tổng kết

  • GATT — một hồ sơ BLE để trao đổi dữ liệu có cấu trúc qua hệ thống phân cấp dịch vụ, đặc tính và bộ mô tả, dựa trên Giao thức Thuộc tính (ATT)
  • Hệ thống phân cấp dữ liệu — dịch vụ (nhóm logic), đặc tính (giá trị cụ thể với kiểu), bộ mô tả (siêu dữ liệu — đơn vị, cài đặt thông báo)
  • Vai trò GATT — Máy chủ (cung cấp dữ liệu, thường là thiết bị ngoại vi BLE) và Máy khách (đọc/ghi, thường là điện thoại thông minh Android)
  • Hoạt động — Read, Write, Notify (không xác nhận, nhanh hơn) và Indicate (có xác nhận, tin cậy hơn); lựa chọn phụ thuộc vào kịch bản
  • API Android — BluetoothGatt, BluetoothGattCallback, BluetoothGattService, BluetoothGattCharacteristic; gọi bất đồng bộ tuần tự qua callback
  • Hồ sơ tiêu chuẩn — Battery Service, Heart Rate, Device Information — đảm bảo tương thích giữa các thiết bị từ các nhà sản xuất khác nhau
  • Dịch vụ tùy chỉnh — UUID 128 bit cho các tác vụ độc đáo; được thiết kế theo mẫu Command/Status với các thuộc tính chính xác (Read, Write, Notify, Indicate)

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm