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 αποτελείται από πολλά επίπεδα: Physical Layer (ραδιόφωνο), Link Layer (διαχείριση σύνδεσης), L2CAP (λογική μετάδοση καναλιού), ATT (Attribute Protocol — πρόσβαση σε χαρακτηριστικά) και GATT (προφίλ βασισμένο στο ATT). Το GATT είναι το υψηλότερο επίπεδο με το οποίο εργάζεται ο προγραμματιστής εφαρμογών. Το υποκείμενο ATT παρέχει βασικές λειτουργίες: ανάγνωση, εγγραφή, ειδοποίηση και ένδειξη χαρακτηριστικών. Το GATT προσθέτει σημασιολογία: καθορίζει τι είναι υπηρεσία, τι είναι χαρακτηριστικό, πώς ομαδοποιούνται και ποιοι κανόνες ισχύουν κατά την ανάγνωση και εγγραφή τους. Σύμφωνα με το Bluetooth Core Specification 5.4 (2023), το GATT υποστηρίζει έως 65.535 χαρακτηριστικά (υπηρεσίες + χαρακτηριστικά + περιγραφείς) σε μία συσκευή.
Η ιεραρχία GATT αποτελείται από τρία επίπεδα. Υπηρεσία (Service) — λογική ομάδα χαρακτηριστικών που επιλύει μία εργασία (π.χ. “Υπηρεσία μπαταρίας” ή “Υπηρεσία καρδιακών παλμών”). Χαρακτηριστικό (Characteristic) — μονάδα δεδομένων με γνωστό τύπο: τρέχον επίπεδο φόρτισης, ενδείξεις αισθητήρα, κατάσταση διακόπτη. Κάθε χαρακτηριστικό έχει μια τιμή (value) και έναν ή περισσότερους περιγραφείς (Descriptors) που περιγράφουν μεταδεδομένα: μονάδες μέτρησης, ρυθμίσεις ειδοποιήσεων, εύρος τιμών. Το UUID (Universally Unique Identifier) αναγνωρίζει μοναδικά κάθε υπηρεσία και κάθε χαρακτηριστικό.
Το 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, // ΑΝΑΓΝΩΣΗ, ΕΓΓΡΑΦΗ, ΕΙΔΟΠΟΙΗΣΗ, ΕΝΔΕΙΞΗ
val descriptors: List<BleDescriptor>,
var value: ByteArray?
)
Στην προδιαγραφή BLE ορίζονται δύο κύρια προφίλ: GAP (Generic Access Profile) και GATT (Generic Attribute Profile). Το GAP είναι υπεύθυνο για την ανίχνευση συσκευών, τη δημιουργία σύνδεσης και τη διαχείριση ορατότητας — αυτό είναι το “επίπεδο δικτύου” του BLE. Το GATT — για την ανταλλαγή δεδομένων μετά τη δημιουργία σύνδεσης, δηλαδή το “επίπεδο εφαρμογής”. Ο προγραμματιστής χρησιμοποιεί το GAP για σάρωση και σύνδεση σε μια συσκευή, και το GATT — για ανάγνωση, εγγραφή και λήψη ειδοποιήσεων από τη συνδεδεμένη συσκευή.
| Χαρακτηριστικό | GAP | GATT |
|---|---|---|
| Σκοπός | Ανίχνευση και σύνδεση | Ανταλλαγή δεδομένων |
| Ρόλοι | Central / Peripheral | Client / Server |
| Πρωτόκολλο | HCI, Link Layer | ATT (Attribute Protocol) |
| Στάδιο | Πριν από τη σύνδεση | Μετά τη σύνδεση |
| Κύρια κλάση | BluetoothAdapter | BluetoothGatt |
Το GATT ορίζει δύο ρόλους: GATT Server και GATT Client. Διακομιστής — συσκευή που παρέχει δεδομένα (π.χ. ιχνηλάτης γυμναστικής που μεταδίδει ενδείξεις παλμού). Πελάτης — συσκευή που ζητά δεδομένα (π.χ. smartphone που διαβάζει μετρήσεις). Στα περισσότερα σενάρια, η εφαρμογή Android λειτουργεί ως GATT Client και η περιφερειακή συσκευή BLE ως GATT Server. Ωστόσο, το Android μπορεί επίσης να είναι GATT Server — για παράδειγμα, εάν η εφαρμογή εξομοιώνει μια συσκευή BLE για άλλες συσκευές. Ο ρόλος καθορίζεται στο στάδιο δημιουργίας της σύνδεσης GATT και δεν αλλάζει κατά τη διάρκεια της συνεδρίας.
Η διαδικασία επικοινωνίας GATT ξεκινά μετά τη δημιουργία σύνδεσης BLE μεταξύ των συσκευών. Πρώτα, ο GATT Client ανιχνεύει υπηρεσίες στον GATT Server μέσω της λειτουργίας Service Discovery — το Android το εκτελεί αυτόματα κατά τη σύνδεση μέσω BluetoothGatt.discoverServices(). Μετά την ανίχνευση, ο πελάτης λαμβάνει μια λίστα διαθέσιμων υπηρεσιών, χαρακτηριστικών και περιγραφέων. Στη συνέχεια, ο πελάτης μπορεί να διαβάσει τιμές χαρακτηριστικών (Read), να γράψει νέες τιμές (Write) ή να εγγραφεί σε ειδοποιήσεις (Set Notify/Indicate). Ο GATT Server μπορεί να στείλει Notify/Indicate στον πελάτη οποιαδήποτε στιγμή μετά τη δημιουργία της σύνδεσης.
Από προεπιλογή, το μέγεθος ενός πακέτου GATT (MTU, Maximum Transmission Unit) στο BLE είναι 23 byte, εκ των οποίων 3 byte είναι κεφαλίδα ATT και 20 byte είναι χρήσιμα δεδομένα. Εάν η εφαρμογή χρειάζεται να μεταδώσει περισσότερα δεδομένα (π.χ. ενημέρωση υλικολογισμικού OTA), μπορεί να ζητήσει αύξηση του MTU σε 517 byte μέσω requestMtu() στο Android. Το αυξημένο MTU μειώνει τον αριθμό πακέτων που απαιτούνται για τη μετάδοση ενός μπλοκ δεδομένων — αντί για 50 μικρά πακέτα μπορούν να σταλούν 2 μεγάλα, γεγονός που μειώνει την κατανάλωση ενέργειας και επιταχύνει τη μετάδοση. Το μέγιστο MTU εξαρτάται από την έκδοση BLE και τις δυνατότητες του τσιπ — Bluetooth 5.0 υποστηρίζει έως 517 byte, παλαιότερες εκδόσεις έως 247 byte.
// Εγγραφή σε ειδοποιήσεις χαρακτηριστικού
fun enableNotifications(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
gatt.setCharacteristicNotification(characteristic, true)
// Ενεργοποίηση 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)
}
}
Για τη λήψη ειδοποιήσεων από τον GATT Server στο Android, πρέπει να υλοποιηθεί η επιστροφή κλήσης BluetoothGattCallback.onCharacteristicChanged(). Σε αυτήν τη μέθοδο, η εφαρμογή λαμβάνει την ενημερωμένη τιμή του χαρακτηριστικού κάθε φορά που ο διακομιστής στέλνει Notify ή Indicate. Για επεξεργασία δεδομένων σε πραγματικό χρόνο, χρησιμοποιήστε buffer και coroutines Kotlin — αυτό θα αποτρέψει το μπλοκάρισμα του νήματος UI σε έντονες ειδοποιήσεις (π.χ. 100+ ενδείξεις παλμού ανά δευτερόλεπτο). Σε ενδείξεις (Indicate), καλέστε υποχρεωτικά το gatt.sendResponse() στην πλευρά του διακομιστή — στον πελάτη Android αυτό γίνεται αυτόματα.
Στο Android, η εργασία με το GATT υλοποιείται μέσω των κλάσεων του πακέτου android.bluetooth: BluetoothGatt (σύνδεση), BluetoothGattService (υπηρεσία), BluetoothGattCharacteristic (χαρακτηριστικό) και BluetoothGattDescriptor (περιγραφέας). Η σύνδεση σε μια συσκευή BLE ξεκινά με την κλήση BluetoothDevice.connectGatt() — αυτή η μέθοδος επιστρέφει BluetoothGatt, μέσω του οποίου εκτελούνται όλες οι επόμενες λειτουργίες. Όλες οι επιστροφές κλήσης GATT έρχονται στο BluetoothGattCallback — αυτή είναι μια ασύγχρονη διεπαφή που καλείται στο ίδιο νήμα όπου δημιουργήθηκε το BluetoothGatt. Σημαντικό: όλες οι λειτουργίες GATT πρέπει να εκτελούνται σειριακά — η ταυτόχρονη κλήση πολλών λειτουργιών στο ίδιο BluetoothGatt οδηγεί σε σφάλματα.
Η σωστή διαχείριση του κύκλου ζωής της σύνδεσης GATT είναι κρίσιμη για τη σταθερότητα της εφαρμογής BLE. Μετά την κλήση connectGatt(), η εφαρμογή αναμένει την επιστροφή κλήσης onConnectionStateChange() με κατάσταση STATE_CONNECTED. Στη συνέχεια, το σύστημα ξεκινά αυτόματα το Service Discovery, μετά την ολοκλήρωση του οποίου καλείται το 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 (Special Interest Group) ορίζει δεκάδες τυπικά προφίλ και υπηρεσίες GATT με σταθερά 16-bit UUID. Τα πιο συνηθισμένα: υπηρεσία 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 με 128-bit UUID (προσαρμοσμένα UUID). Κατά το σχεδιασμό μιας προσαρμοσμένης υπηρεσίας, πρέπει: να ορίσετε τη λογική ομάδα χαρακτηριστικών (π.χ. “Υπηρεσία διαχείρισης κλειδαριάς”), να δώσετε σε κάθε χαρακτηριστικό τις σωστές ιδιότητες (Read, Write, Notify), να καθορίσετε επιτρεπόμενες τιμές και μονάδες μέτρησης μέσω του περιγραφέα Characteristic Presentation Format. Για σύνθετα πρωτόκολλα, συνιστάται να συμπεριλάβετε στην υπηρεσία ένα χαρακτηριστικό Command με ιδιότητα Write και ένα χαρακτηριστικό Status με Notify — αυτό αντιστοιχεί στο μοτίβο Command/Status που είναι αποδεκτό σε βιομηχανικές εφαρμογές BLE.
// Δημιουργία προσαρμοσμένης υπηρεσίας GATT (Android ως 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
}
Συχνές ερωτήσεις
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, δεδομένα συσκευής). Κάθε υπηρεσία περιέχει πολλά χαρακτηριστικά με 16-bit UUID. Οι προγραμματιστές μπορούν να δημιουργήσουν προσαρμοσμένες υπηρεσίες με 128-bit UUID για συγκεκριμένες εργασίες — για παράδειγμα, έλεγχο έξυπνης κλειδαριάς ή μετάδοση δεδομένων ιχνηλάτη γυμναστικής.
Στο Android, το GATT υλοποιείται μέσω BluetoothGatt (σύνδεση), BluetoothGattService (υπηρεσία), BluetoothGattCharacteristic (χαρακτηριστικό) και BluetoothGattDescriptor (περιγραφέας). Η σύνδεση γίνεται μέσω connectGatt(), μετά την οποία τα συμβάντα έρχονται στην επιστροφή κλήσης BluetoothGattCallback: onConnectionStateChange, onServicesDiscovered, onCharacteristicChanged (για ειδοποιήσεις). Όλες οι λειτουργίες GATT πρέπει να εκτελούνται σειριακά.
UUID (Universally Unique Identifier) — 16-bit ή 128-bit αναγνωριστικό που καθορίζει μοναδικά μια υπηρεσία ή χαρακτηριστικό στο GATT. Οι τυπικές υπηρεσίες Bluetooth SIG χρησιμοποιούν 16-bit UUID (π.χ. 180D για Heart Rate). Οι προσαρμοσμένες υπηρεσίες προγραμματιστών — 128-bit UUID (π.χ. 12345678-1234-5678-1234-56789abcdef0). Το UUID επιτρέπει στον πελάτη να βρει τα απαραίτητα δεδομένα στον GATT Server.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης