GATT (Generic Attribute Profile) — profil Bluetooth Low Energy (BLE), který definuje strukturu dat a pravidla výměny informací mezi zařízeními BLE. GATT je postaven nad Attribute Protocol (ATT) a organizuje data do hierarchie: služby (services), charakteristiky (characteristics) a deskriptory (descriptors). Podle údajů Bluetooth SIG (2025) je profil GATT používán v 98% všech BLE aplikací — od fitness trackerů po chytré zámky a lékařské senzory.
Hlavní body
GATT (Generic Attribute Profile) — je profil Bluetooth Low Energy (BLE), který určuje, jak si dvě zařízení BLE vyměňují data prostřednictvím Attribute Protocol (ATT). GATT standardizuje strukturu dat: všechna data jsou organizována v hierarchii „služba → charakteristika → deskriptor”. Profil byl představen ve specifikaci Bluetooth 4.0 (2010) společně s BLE a od té doby zůstává hlavním mechanismem přenosu dat pro energeticky účinná zařízení Bluetooth. Na rozdíl od klasického Bluetooth, kde jsou data přenášena přes sériový port (SPP), GATT poskytuje strukturovaný přístup k datům prostřednictvím operací čtení, zápisu a oznámení.
Zásobník BLE se skládá z několika vrstev: Physical Layer (rádio), Link Layer (řízení připojení), L2CAP (logický kanálový přenos), ATT (Attribute Protocol — přístup k atributům) a GATT (profil založený na ATT). GATT je nejvyšší vrstva, se kterou pracuje vývojář aplikací. Níže ležící ATT poskytuje základní operace: čtení, zápis, oznámení a indikaci atributů. GATT přidává sémantiku: definuje, co je služba, charakteristika, jak jsou seskupeny a jaká pravidla platí při jejich čtení a zápisu. Podle Bluetooth Core Specification 5.4 (2023) podporuje GATT až 65 535 atributů (služeb + charakteristik + deskriptorů) na jednom zařízení.
Hierarchie GATT se skládá ze tří úrovní. Služba (Service) — logická skupina charakteristik řešící jeden úkol (např. „Služba baterie” nebo „Služba Heart Rate”). Charakteristika (Characteristic) — datová jednotka se známým typem: aktuální úroveň nabití, údaje ze senzoru, stav spínače. Každá charakteristika má hodnotu (value) a jeden nebo více deskriptorů (Descriptors) popisujících metadata: měrné jednotky, nastavení oznámení, rozsah hodnot. UUID (Universally Unique Identifier) jednoznačně identifikuje každou službu a každou charakteristiku.
GATT podporuje čtyři typy operací pro interakci s charakteristikami. Read — klient požaduje aktuální hodnotu charakteristiky od serveru. Write — klient odesílá novou hodnotu na server. Notify — server odesílá hodnotu klientovi bez potvrzení (rychlejší, ale méně spolehlivý způsob). Indicate — server odesílá hodnotu s potvrzením přijetí (spolehlivější, ale pomalejší). Vývojář volí typ podle scénáře: pro údaje ze senzoru pulsu stačí Notify, pro zápis konfigurace chytrého zámku — Write s potvrzením.
// Struktura dat GATT v kódu Android
data class BleService(
val uuid: UUID,
val characteristics: List<BleCharacteristic>
)
data class BleCharacteristic(
val uuid: UUID,
val properties: Int, // ČTENÍ, ZÁPIS, OZNÁMENÍ, INDIKACE
val descriptors: List<BleDescriptor>,
var value: ByteArray?
)
Ve specifikaci BLE jsou definovány dva hlavní profily: GAP (Generic Access Profile) a GATT (Generic Attribute Profile). GAP je zodpovědný za detekci zařízení, navázání spojení a správu viditelnosti — to je „síťová vrstva” BLE. GATT — za výměnu dat po navázání spojení, tedy „aplikační vrstva”. Vývojář používá GAP pro skenování a připojení k zařízení a GATT — pro čtení, zápis a přijímání oznámení od připojeného zařízení.
| Vlastnost | GAP | GATT |
|---|---|---|
| Účel | Detekce a připojení | Výměna dat |
| Role | Central / Peripheral | Client / Server |
| Protokol | HCI, Link Layer | ATT (Attribute Protocol) |
| Fáze | Před připojením | Po připojení |
| Hlavní třída | BluetoothAdapter | BluetoothGatt |
GATT definuje dvě role: GATT Server a GATT Client. Server — zařízení poskytující data (např. fitness tracker přenášející údaje o pulsu). Klient — zařízení požadující data (např. smartphone čtoucí měření). Ve většině scénářů aplikace pro Android vystupuje jako GATT Client a periferie BLE jako GATT Server. Android však může být také GATT Server — například pokud aplikace emuluje zařízení BLE pro jiná zařízení. Role je určena ve fázi navazování GATT spojení a během relace se nemění.
Proces komunikace GATT začíná po navázání BLE spojení mezi zařízeními. Nejprve GATT Client detekuje služby na GATT Serveru pomocí operace Service Discovery — Android ji provádí automaticky při připojení prostřednictvím BluetoothGatt.discoverServices(). Po detekci klient obdrží seznam dostupných služeb, charakteristik a deskriptorů. Poté může klient číst hodnoty charakteristik (Read), zapisovat nové hodnoty (Write) nebo se přihlásit k odběru oznámení (Set Notify/Indicate). GATT Server může kdykoli po navázání spojení odeslat klientovi Notify/Indicate.
Ve výchozím nastavení je velikost jednoho GATT paketu (MTU, Maximum Transmission Unit) v BLE 23 bytů, z čehož 3 byty tvoří hlavička ATT a 20 bytů užitečná data. Pokud aplikace potřebuje přenést více dat (např. OTA aktualizaci firmwaru), lze požádat o zvýšení MTU na 517 bytů pomocí requestMtu() v Androidu. Zvýšené MTU snižuje počet paketů potřebných k přenosu jednoho bloku dat — místo 50 malých paketů lze odeslat 2 velké, což snižuje spotřebu energie a zrychluje přenos. Maximální MTU závisí na verzi BLE a možnostech čipu — Bluetooth 5.0 podporuje až 517 bytů, starší verze až 247 bytů.
// Přihlásit se k odběru oznámení charakteristiky
fun enableNotifications(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
gatt.setCharacteristicNotification(characteristic, true)
// Povolit 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)
}
}
Pro příjem oznámení od GATT Server v Androidu je nutné implementovat callback BluetoothGattCallback.onCharacteristicChanged(). V této metodě aplikace obdrží aktualizovanou hodnotu charakteristiky pokaždé, když server odešle Notify nebo Indicate. Pro zpracování dat v reálném čase použijte buffer a Kotlin korutiny — to zabrání blokování vlákna UI při intenzivních oznámeních (např. 100+ údajů o pulsu za sekundu). Při indikacích (Indicate) vždy volejte gatt.sendResponse() na straně serveru — v klientovi Android je to zpracováno automaticky.
Na Androidu se práce s GATT realizuje prostřednictvím tříd balíčku android.bluetooth: BluetoothGatt (připojení), BluetoothGattService (služba), BluetoothGattCharacteristic (charakteristika) a BluetoothGattDescriptor (deskriptor). Připojení k zařízení BLE začíná voláním BluetoothDevice.connectGatt() — tato metoda vrací BluetoothGatt, přes který se provádějí všechny další operace. Všechny GATT callbacky přicházejí do BluetoothGattCallback — to je asynchronní rozhraní volané ve stejném vlákně, ve kterém byl vytvořen BluetoothGatt. Důležité: všechny operace GATT musí být prováděny sekvenčně — současné volání více operací na stejném BluetoothGattu vede k chybám.
Správné řízení životního cyklu GATT připojení je kritické pro stabilitu BLE aplikace. Po volání connectGatt() aplikace očekává callback onConnectionStateChange() se stavem STATE_CONNECTED. Poté systém automaticky spustí Service Discovery, po jehož dokončení je voláno onServicesDiscovered(). Teprve poté lze provádět čtení, zápis a odběr. Po ukončení práce vždy volejte gatt.close() v onDestroy() nebo onPause() — neuzavřená GATT připojení spotřebovávají baterii a mohou blokovat opětovné připojení ke stejnému zařízení na Androidu.
// Připojit se k zařízení BLE přes 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) definuje desítky standardních profilů a služeb GATT s pevnými 16bitovými UUID. Nejběžnější: služba Battery Service (UUID 180F, charakteristika Battery Level 2A19), služba Heart Rate (UUID 180D, charakteristika Heart Rate Measurement 2A37), služba Device Information (UUID 180A, charakteristiky Manufacturer Name, Serial Number). Používání standardních služeb zaručuje kompatibilitu mezi zařízeními různých výrobců — jakýkoli fitness náramek se službou Heart Rate by měl fungovat s jakoukoli aplikací pro Android, která ji podporuje.
Pokud standardní služby nepokrývají úkol, může vývojář vytvořit vlastní služby GATT s 128bitovými UUID (vlastní UUID). Při navrhování vlastní služby je třeba: definovat logickou skupinu charakteristik (např. „Služba správy zámku”), přiřadit každé charakteristice správné vlastnosti (Read, Write, Notify), určit povolené hodnoty a měrné jednotky prostřednictvím deskriptoru Characteristic Presentation Format. Pro složité protokoly se doporučuje zahrnout do služby charakteristiku Command s vlastností Write a charakteristiku Status s Notify — to odpovídá vzoru Command/Status přijatému v průmyslových aplikacích BLE.
// Vytvořit vlastní službu GATT (Android jako 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
}
Často kladené otázky
GATT (Generic Attribute Profile) — je profil Bluetooth Low Energy definující strukturu výměny dat mezi zařízeními. Je potřebný pro standardizaci přístupu k informacím: všechna zařízení BLE organizují data do služeb a charakteristik, což umožňuje libovolnému klientovi číst údaje ze senzorů, ovládat zařízení a přijímat oznámení.
GAP je zodpovědný za detekci a připojování zařízení BLE (skenování, reklama, navazování spojení). GATT — za výměnu dat po připojení (čtení, zápis, oznámení). GAP pracuje před připojením, GATT — po něm. Oba profily jsou pro BLE povinné, ale plní různé funkce: GAP je „síťová vrstva”, GATT je „aplikační vrstva”.
Standardní služby zahrnují Battery Service (180F, úroveň nabití), Heart Rate (180D, puls), Device Information (180A, údaje o zařízení). Každá služba obsahuje několik charakteristik s 16bitovými UUID. Vývojáři mohou vytvářet vlastní služby s 128bitovými UUID pro specifické úkoly — například ovládání chytrého zámku nebo přenos dat fitness trackeru.
Na Androidu je GATT implementován prostřednictvím BluetoothGatt (připojení), BluetoothGattService (služba), BluetoothGattCharacteristic (charakteristika) a BluetoothGattDescriptor (deskriptor). Připojení se provádí prostřednictvím connectGatt(), poté události přicházejí v callbacku BluetoothGattCallback: onConnectionStateChange, onServicesDiscovered, onCharacteristicChanged (pro oznámení). Všechny operace GATT musí být prováděny sekvenčně.
UUID (Universally Unique Identifier) — 16bitový nebo 128bitový identifikátor jednoznačně určující službu nebo charakteristiku v GATT. Standardní služby Bluetooth SIG používají 16bitová UUID (např. 180D pro Heart Rate). Vlastní služby vývojářů — 128bitová UUID (např. 12345678-1234-5678-1234-56789abcdef0). UUID umožňuje klientovi najít potřebná data na GATT Serveru.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také