GATT (Generic Attribute Profile) — profilul Bluetooth Low Energy (BLE) care definește structura datelor și regulile de schimb de informații între dispozitivele BLE. GATT este construit deasupra Attribute Protocol (ATT) și organizează datele într-o ierarhie: servicii (services), caracteristici (characteristics) și descriptori (descriptors). Conform datelor Bluetooth SIG (2025), profilul GATT este utilizat în 98% din toate aplicațiile BLE — de la trackere fitness până la încuietori inteligente și senzori medicali.
Principalele puncte
GATT (Generic Attribute Profile) — este profilul Bluetooth Low Energy (BLE) care definește modul în care două dispozitive BLE fac schimb de date prin Attribute Protocol (ATT). GATT standardizează structura datelor: toate datele sunt organizate în ierarhia „serviciu → caracteristică → descriptor”. Profilul a fost introdus în specificația Bluetooth 4.0 (2010) împreună cu BLE și de atunci rămâne mecanismul principal de transmitere a datelor pentru dispozitivele Bluetooth eficiente energetic. Spre deosebire de Bluetooth clasic, unde datele sunt transmise printr-un port serial (SPP), GATT oferă acces structurat la date prin operații de citire, scriere și notificări.
Stiva BLE este formată din mai multe straturi: Physical Layer (radio), Link Layer (gestionarea conexiunii), L2CAP (transmisie logică pe canal), ATT (Attribute Protocol — acces la atribute) și GATT (profil bazat pe ATT). GATT este cel mai înalt nivel cu care lucrează dezvoltatorul de aplicații. ATT subiacent oferă operații de bază: citire, scriere, notificare și indicare a atributelor. GATT adaugă semantică: definește ce este un serviciu, o caracteristică, cum sunt grupate și ce reguli se aplică la citirea și scrierea lor. Conform Bluetooth Core Specification 5.4 (2023), GATT suportă până la 65.535 de atribute (servicii + caracteristici + descriptori) pe un singur dispozitiv.
Ierarhia GATT este formată din trei niveluri. Serviciul (Service) — un grup logic de caracteristici care rezolvă o singură sarcină (de exemplu, „Serviciul bateriei” sau „Serviciul Heart Rate”). Caracteristica (Characteristic) — o unitate de date cu un tip cunoscut: nivelul curent de încărcare, citirile senzorului, starea comutatorului. Fiecare caracteristică are o valoare (value) și unul sau mai mulți descriptori (Descriptors) care descriu metadatele: unități de măsură, setări de notificări, intervalul valorilor. UUID (Universally Unique Identifier) identifică unic fiecare serviciu și fiecare caracteristică.
GATT suportă patru tipuri de operații pentru interacțiunea cu caracteristicile. Read — clientul solicită valoarea curentă a caracteristicii de la server. Write — clientul trimite o nouă valoare către server. Notify — serverul trimite valoarea către client fără confirmare (mod mai rapid, dar mai puțin fiabil). Indicate — serverul trimite valoarea cu confirmare de primire (mai fiabil, dar mai lent). Dezvoltatorul alege tipul în funcție de scenariu: pentru citirile senzorului de puls este suficient Notify, pentru scrierea configurației unei încuietori inteligente — Write cu confirmare.
// Structura datelor GATT în codul Android
data class BleService(
val uuid: UUID,
val characteristics: List<BleCharacteristic>
)
data class BleCharacteristic(
val uuid: UUID,
val properties: Int, // CITIRE, SCRIERE, NOTIFICARE, INDICARE
val descriptors: List<BleDescriptor>,
var value: ByteArray?
)
În specificația BLE sunt definite două profile principale: GAP (Generic Access Profile) și GATT (Generic Attribute Profile). GAP se ocupă de detectarea dispozitivelor, stabilirea conexiunii și gestionarea vizibilității — acesta este „stratul de rețea” al BLE. GATT — pentru schimbul de date după stabilirea conexiunii, adică „stratul de aplicație”. Dezvoltatorul folosește GAP pentru scanarea și conectarea la un dispozitiv, iar GATT — pentru citirea, scrierea și primirea notificărilor de la dispozitivul conectat.
| Caracteristică | GAP | GATT |
|---|---|---|
| Scop | Detectare și conectare | Schimb de date |
| Roluri | Central / Peripheral | Client / Server |
| Protocol | HCI, Link Layer | ATT (Attribute Protocol) |
| Etapă | Înainte de conectare | După conectare |
| Clasa principală | BluetoothAdapter | BluetoothGatt |
GATT definește două roluri: GATT Server și GATT Client. Serverul — dispozitivul care furnizează date (de exemplu, un tracker fitness care transmite citirile pulsului). Clientul — dispozitivul care solicită date (de exemplu, un smartphone care citește măsurătorile). În majoritatea scenariilor, aplicația Android acționează ca GATT Client, iar perifericele BLE ca GATT Server. Cu toate acestea, Android poate fi și GATT Server — de exemplu, dacă aplicația emulează un dispozitiv BLE pentru alte dispozitive. Rolul este determinat în faza de stabilire a conexiunii GATT și nu se schimbă pe parcursul sesiunii.
Procesul de comunicare GATT începe după stabilirea conexiunii BLE între dispozitive. Mai întâi, GATT Client detectează serviciile pe GATT Server prin operația Service Discovery — Android o execută automat la conectare prin BluetoothGatt.discoverServices(). După detectare, clientul primește lista serviciilor, caracteristicilor și descriptorilor disponibili. Apoi clientul poate citi valorile caracteristicilor (Read), scrie valori noi (Write) sau se poate abona la notificări (Set Notify/Indicate). GATT Server poate trimite Notify/Indicate clientului în orice moment după stabilirea conexiunii.
În mod implicit, dimensiunea unui pachet GATT (MTU, Maximum Transmission Unit) în BLE este de 23 de octeți, dintre care 3 octeți sunt antetul ATT și 20 de octeți sunt date utile. Dacă aplicația trebuie să transmită mai multe date (de exemplu, actualizarea OTA a firmware-ului), se poate solicita creșterea MTU la 517 octeți prin requestMtu() în Android. MTU mărit reduce numărul de pachete necesare pentru transmiterea unui bloc de date — în loc de 50 de pachete mici se pot trimite 2 mari, ceea ce reduce consumul de energie și accelerează transmisia. MTU maxim depinde de versiunea BLE și de capacitățile cipului — Bluetooth 5.0 suportă până la 517 octeți, versiunile mai vechi — până la 247 de octeți.
// Abonați-vă la notificările caracteristicii
fun enableNotifications(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
gatt.setCharacteristicNotification(characteristic, true)
// Activați CCCD (Client Characteristic Configuration Descriptor)
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)
}
}
Pentru a primi notificări de la GATT Server în Android, trebuie implementat callback-ul BluetoothGattCallback.onCharacteristicChanged(). În această metodă, aplicația primește valoarea actualizată a caracteristicii de fiecare dată când serverul trimite Notify sau Indicate. Pentru procesarea datelor în timp real, utilizați un buffer și corutine Kotlin — acest lucru va permite să nu blocați firul UI la notificări intense (de exemplu, 100+ citiri ale pulsului pe secundă). La indicații (Indicate), apelați obligatoriu gatt.sendResponse() pe partea serverului — în clientul Android acest lucru este gestionat automat.
Pe Android, lucrul cu GATT se realizează prin clasele pachetului android.bluetooth: BluetoothGatt (conexiune), BluetoothGattService (serviciu), BluetoothGattCharacteristic (caracteristică) și BluetoothGattDescriptor (descriptor). Conectarea la un dispozitiv BLE începe cu apelarea BluetoothDevice.connectGatt() — această metodă returnează BluetoothGatt, prin care se execută toate operațiile ulterioare. Toate callback-urile GATT vin în BluetoothGattCallback — aceasta este o interfață asincronă apelată în același fir în care a fost creat BluetoothGatt. Important: toate operațiile GATT trebuie executate secvențial — apelarea simultană a mai multor operații pe același BluetoothGatt duce la erori.
Gestionarea corectă a ciclului de viață al conexiunii GATT este critică pentru stabilitatea aplicației BLE. După apelarea connectGatt(), aplicația așteaptă callback-ul onConnectionStateChange() cu starea STATE_CONNECTED. Apoi sistemul pornește automat Service Discovery, după finalizarea căruia se apelează onServicesDiscovered(). Abia după aceasta se pot executa citirea, scrierea și abonarea. La finalizarea lucrului, apelați obligatoriu gatt.close() în onDestroy() sau onPause() — conexiunile GATT neînchise consumă baterie și pot bloca reconectarea la același dispozitiv pe Android.
// Conectați-vă la dispozitivul BLE prin 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 (Special Interest Group) definește zeci de profile și servicii GATT standard cu UUID-uri fixe de 16 biți. Cele mai comune: serviciul Battery Service (UUID 180F, caracteristica Battery Level 2A19), serviciul Heart Rate (UUID 180D, caracteristica Heart Rate Measurement 2A37), serviciul Device Information (UUID 180A, caracteristicile Manufacturer Name, Serial Number). Utilizarea serviciilor standard garantează compatibilitatea între dispozitivele diferiților producători — orice brățară fitness cu serviciul Heart Rate ar trebui să funcționeze cu orice aplicație Android care îl suportă.
Dacă serviciile standard nu acoperă sarcina, dezvoltatorul poate crea propriile servicii GATT cu UUID-uri de 128 de biți (UUID-uri personalizate). La proiectarea unui serviciu personalizat, trebuie: să definiți grupul logic de caracteristici (de exemplu, „Serviciul de gestionare a încuietorii”), să atribuiți fiecărei caracteristici proprietățile corecte (Read, Write, Notify), să determinați valorile admisibile și unitățile de măsură prin descriptorul Characteristic Presentation Format. Pentru protocoale complexe, se recomandă includerea în serviciu a unei caracteristici Command cu proprietatea Write și a unei caracteristici Status cu Notify — aceasta corespunde modelului Command/Status adoptat în aplicațiile industriale BLE.
// Creați un serviciu GATT personalizat (Android ca GATT Server)
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
}
Întrebări frecvente
GATT (Generic Attribute Profile) — este profilul Bluetooth Low Energy care definește structura schimbului de date între dispozitive. Este necesar pentru standardizarea accesului la informații: toate dispozitivele BLE organizează datele în servicii și caracteristici, ceea ce permite oricărui client să citească citirile senzorilor, să controleze dispozitivele și să primească notificări.
GAP se ocupă de detectarea și conectarea dispozitivelor BLE (scanare, publicitate, stabilirea conexiunii). GATT — pentru schimbul de date după conectare (citire, scriere, notificări). GAP funcționează înainte de conectare, GATT — după. Ambele profile sunt obligatorii pentru BLE, dar au funcții diferite: GAP este „stratul de rețea”, GATT este „stratul de aplicație”.
Serviciile standard includ Battery Service (180F, nivelul de încărcare), Heart Rate (180D, pulsul), Device Information (180A, datele dispozitivului). Fiecare serviciu conține mai multe caracteristici cu UUID-uri de 16 biți. Dezvoltatorii pot crea servicii personalizate cu UUID-uri de 128 de biți pentru sarcini specifice — de exemplu, controlul unei încuietori inteligente sau transmiterea datelor unui tracker fitness.
Pe Android, GATT este implementat prin BluetoothGatt (conexiune), BluetoothGattService (serviciu), BluetoothGattCharacteristic (caracteristică) și BluetoothGattDescriptor (descriptor). Conectarea se realizează prin connectGatt(), după care evenimentele vin în callback-ul BluetoothGattCallback: onConnectionStateChange, onServicesDiscovered, onCharacteristicChanged (pentru notificări). Toate operațiile GATT trebuie executate secvențial.
UUID (Universally Unique Identifier) — un identificator de 16 biți sau 128 de biți care definește unic un serviciu sau o caracteristică în GATT. Serviciile standard Bluetooth SIG utilizează UUID-uri de 16 biți (de exemplu, 180D pentru Heart Rate). Serviciile personalizate ale dezvoltatorilor — UUID-uri de 128 de biți (de exemplu, 12345678-1234-5678-1234-56789abcdef0). UUID permite clientului să găsească datele necesare pe GATT Server.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și