GATT — что это, Generic Attribute Profile и реализация в Android

Автор: IT Sectr Опубликовано: 2026-07-14 Время чтения: 10 мин

GATT (Generic Attribute Profile) — профиль Bluetooth Low Energy (BLE), определяющий структуру данных и правила обмена информацией между BLE-устройствами. GATT построен поверх Attribute Protocol (ATT) и организует данные в иерархию: сервисы (services), характеристики (characteristics) и дескрипторы (descriptors). По данным Bluetooth SIG (2025), GATT-профиль используется в 98% всех BLE-приложений — от фитнес-трекеров до умных замков и медицинских датчиков.

Главное

  • GATT — профиль BLE, определяющий структуру передачи данных через сервисы, характеристики и дескрипторы
  • Иерархия — сервис (служба) содержит характеристики, каждая характеристика — одно значение с опциональными дескрипторами
  • UUID — каждый сервис и характеристика идентифицируются 16-битным (стандартные) или 128-битным (кастомные) UUID
  • Роли — GATT Server (предоставляет данные) и GATT Client (читает/пишет данные)
  • Android API — BluetoothGatt, BluetoothGattService, BluetoothGattCharacteristic — основные классы для работы с GATT

Что такое GATT?

GATT (Generic Attribute Profile) — это профиль Bluetooth Low Energy (BLE), который определяет, как два BLE-устройства обмениваются данными через Attribute Protocol (ATT). GATT стандартизирует структуру данных: все данные организованы в иерархию «сервис → характеристика → дескриптор». Профиль был представлен в спецификации Bluetooth 4.0 (2010) вместе с BLE и с тех пор остаётся основным механизмом передачи данных для энергоэффективных Bluetooth-устройств. В отличие от классического Bluetooth, где данные передаются через последовательный порт (SPP), GATT предоставляет структурированный доступ к данным через операции чтения, записи и уведомлений.

Роль GATT в стеке BLE

BLE-стек состоит из нескольких уровней: Physical Layer (радио), Link Layer (управление соединением), L2CAP (логическая канальная передача), ATT (Attribute Protocol — доступ к атрибутам) и GATT (профиль на основе ATT). GATT — самый верхний уровень, с которым работает разработчик приложения. Нижележащий ATT предоставляет базовые операции: чтение, запись, уведомление и индикацию атрибутов. GATT же добавляет семантику: определяет, что такое сервис, характеристика, как они группируются и какие правила действуют при их чтении и записи. По данным Bluetooth Core Specification 5.4 (2023), GATT поддерживает до 65 535 атрибутов (сервисов + характеристик + дескрипторов) на одном устройстве.

Архитектура GATT: сервисы, характеристики и дескрипторы

GATT-иерархия состоит из трёх уровней. Сервис (Service) — логическая группа характеристик, решающая одну задачу (например, «Сервис батареи» или «Сервис Heart Rate»). Характеристика (Characteristic) — это единица данных с известным типом: текущий уровень заряда, показания датчика, состояние переключателя. Каждая характеристика имеет значение (value) и один или несколько дескрипторов (Descriptors), описывающих метаданные: единицы измерения, настройки уведомлений, диапазон значений. UUID (Universally Unique Identifier) однозначно идентифицирует каждый сервис и каждую характеристику.

Типы операций с характеристиками

GATT поддерживает четыре типа операций для взаимодействия с характеристиками. Read — клиент запрашивает текущее значение характеристики у сервера. Write — клиент отправляет новое значение на сервер. Notify — сервер отправляет значение клиенту без подтверждения (более быстрый, но менее надёжный способ). Indicate — сервер отправляет значение с подтверждением получения (надёжнее, но медленнее). Разработчик выбирает тип в зависимости от сценария: для показаний датчика пульса достаточно Notify, для записи конфигурации умного замка — Write с подтверждением.

kotlin
// GATT data structure in Android code
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 и GAP: различия профилей BLE

В спецификации BLE определены два основных профиля: GAP (Generic Access Profile) и GATT (Generic Attribute Profile). GAP отвечает за обнаружение устройств, установление соединения и управление видимостью — это «сетевой уровень» BLE. GATT — за обмен данными после установления соединения, то есть «прикладной уровень». Разработчик использует GAP для сканирования и подключения к устройству, а GATT — для чтения, записи и получения уведомлений от подключённого устройства.

ХарактеристикаGAPGATT
НазначениеОбнаружение и подключениеОбмен данными
РолиCentral / PeripheralClient / Server
ПротоколHCI, Link LayerATT (Attribute Protocol)
ЭтапДо подключенияПосле подключения
Основной классBluetoothAdapterBluetoothGatt

Роли в GATT

GATT определяет две роли: GATT Server и GATT Client. Сервер — устройство, которое предоставляет данные (например, фитнес-трекер, передающий показания пульса). Клиент — устройство, которое запрашивает данные (например, смартфон, читающий показания). В большинстве сценариев Android-приложение выступает GATT Client, а BLE-периферия — GATT Server. Однако Android также может быть GATT Server — например, если приложение эмулирует BLE-устройство для других устройств. Роль определяется на этапе установки GATT-соединения и не меняется в течение сессии.

Как работает GATT-коммуникация в BLE

Процесс GATT-коммуникации начинается после установления BLE-соединения между устройствами. Сначала GATT Client обнаруживает сервисы на GATT Server через операцию Service Discovery — Android выполняет её автоматически при подключении через BluetoothGatt.discoverServices(). После обнаружения клиент получает список доступных сервисов, характеристик и дескрипторов. Затем клиент может читать значения характеристик (Read), записывать новые значения (Write) или подписываться на уведомления (Set Notify/Indicate). GATT Server может отправлять Notify/Indicate клиенту в любой момент после установления соединения.

MTU — максимальный размер пакета

По умолчанию размер одного GATT-пакета (MTU, Maximum Transmission Unit) в BLE составляет 23 байта, из которых 3 байта — заголовок ATT, и 20 байт — полезные данные. Если приложению нужно передать больше данных (например, OTA-обновление прошивки), можно запросить увеличение MTU до 517 байт через requestMtu() в Android. Увеличенный MTU сокращает количество пакетов для передачи одного блока данных — вместо 50 маленьких пакетов можно отправить 2 больших, что снижает энергопотребление и ускоряет передачу. Максимальный MTU зависит от версии BLE и возможностей чипа — Bluetooth 5.0 поддерживает до 517 байт, более старые версии — до 247 байт.

kotlin
// Subscribe to characteristic notifications
fun enableNotifications(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
    gatt.setCharacteristicNotification(characteristic, true)

    // Enable 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. Для обработки данных в реальном времени используйте буфер и корутины Kotlin — это позволит не блокировать UI-поток при интенсивных уведомлениях (например, 100+ показаний пульса в секунду). При индикациях (Indicate) обязательно вызывайте gatt.sendResponse() на стороне сервера — в Android-клиенте это обрабатывается автоматически.

Реализация GATT на Android

На Android работа с GATT реализуется через классы пакета android.bluetooth: BluetoothGatt (соединение), BluetoothGattService (сервис), BluetoothGattCharacteristic (характеристика) и BluetoothGattDescriptor (дескриптор). Подключение к BLE-устройству начинается с вызова BluetoothDevice.connectGatt() — этот метод возвращает BluetoothGatt, через который выполняются все дальнейшие операции. Все GATT-колбэки приходят в BluetoothGattCallback — это асинхронный интерфейс, вызываемый в том же потоке, где был создан BluetoothGatt. Важно: все операции GATT должны выполняться последовательно — одновременный вызов нескольких операций на одном BluetoothGatt приводит к ошибкам.

Жизненный цикл GATT-соединения

Правильное управление жизненным циклом GATT-соединения критично для стабильности BLE-приложения. После вызова connectGatt() приложение ожидает колбэк onConnectionStateChange() с состоянием STATE_CONNECTED. Затем система автоматически запускает Service Discovery, после завершения которого вызывается onServicesDiscovered(). Только после этого можно выполнять чтение, запись и подписку. При завершении работы обязательно вызовите gatt.close() в onDestroy() или onPause() — незакрытые GATT-соединения потребляют батарею и могут блокировать повторное подключение к тому же устройству на Android.

kotlin
// Connect to BLE device via 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) }
    }
}

Стандартные GATT-профили и сервисы

Bluetooth SIG (Special Interest Group) определяет десятки стандартных GATT-профилей и сервисов с фиксированными 16-битными 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-сервисов

Если стандартные сервисы не покрывают задачу, разработчик может создать собственные GATT-сервисы с 128-битными UUID (кастомные UUID). При проектировании кастомного сервиса нужно: определить логическую группу характеристик (например, «Сервис управления замком»), задать каждой характеристике правильные свойства (Read, Write, Notify), определить допустимые значения и единицы измерения через дескриптор Characteristic Presentation Format. Для сложных протоколов рекомендуется включать в сервис характеристику Command с Write-свойством и характеристику Status с Notify — это соответствует шаблону Command/Status, принятому в промышленных BLE-приложениях.

kotlin
// Create custom GATT service (Android as 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 в BLE и зачем он нужен?

GATT (Generic Attribute Profile) — это профиль Bluetooth Low Energy, определяющий структуру обмена данными между устройствами. Он нужен для стандартизации доступа к информации: все BLE-устройства организуют данные в сервисы и характеристики, что позволяет любому клиенту читать показания датчиков, управлять устройствами и получать уведомления.

Чем GATT отличается от GAP?

GAP отвечает за обнаружение и подключение BLE-устройств (сканирование, реклама, установка соединения). GATT — за обмен данными после подключения (чтение, запись, уведомления). GAP работает до соединения, GATT — после. Оба профиля обязательны для BLE, но выполняют разные функции: GAP — «сетевой уровень», GATT — «прикладной».

Какие существуют GATT-сервисы и характеристики?

Стандартные сервисы включают Battery Service (180F, уровень заряда), Heart Rate (180D, пульс), Device Information (180A, данные устройства). Каждый сервис содержит несколько характеристик с 16-битными UUID. Разработчики могут создавать кастомные сервисы с 128-битными UUID для специфических задач — например, управления умным замком или передачи данных фитнес-трекера.

Как работает GATT на Android?

На Android GATT реализуется через BluetoothGatt (соединение), BluetoothGattService (сервис), BluetoothGattCharacteristic (характеристика) и BluetoothGattDescriptor (дескриптор). Подключение выполняется через connectGatt(), после чего в колбэке BluetoothGattCallback приходят события: onConnectionStateChange, onServicesDiscovered, onCharacteristicChanged (для уведомлений). Все GATT-операции должны выполняться последовательно.

Что такое UUID в GATT?

UUID (Universally Unique Identifier) — 16-битный или 128-битный идентификатор, однозначно определяющий сервис или характеристику в GATT. Стандартные сервисы Bluetooth SIG используют 16-битные UUID (например, 180D для Heart Rate). Кастомные сервисы разработчиков — 128-битные UUID (например, 12345678-1234-5678-1234-56789abcdef0). UUID позволяет клиенту найти нужные данные на GATT Server.

Итоги

  • GATT — профиль BLE для структурированного обмена данными через иерархию сервисов, характеристик и дескрипторов, основанный на Attribute Protocol (ATT)
  • Иерархия данных — сервис (логическая группа), характеристика (конкретное значение с типом), дескриптор (метаданные — единицы, настройки уведомлений)
  • Роли GATT — Server (предоставляет данные, обычно BLE-периферия) и Client (читает/пишет, обычно Android-смартфон)
  • Операции — Read, Write, Notify (без подтверждения, быстрее) и Indicate (с подтверждением, надёжнее); выбор зависит от сценария
  • Android API — BluetoothGatt, BluetoothGattCallback, BluetoothGattService, BluetoothGattCharacteristic; последовательные асинхронные вызовы через колбэки
  • Стандартные профили — Battery Service, Heart Rate, Device Information — обеспечивают совместимость между устройствами разных производителей
  • Кастомные сервисы — 128-битные UUID для уникальных задач; проектируются по шаблону Command/Status с правильными свойствами (Read, Write, Notify, Indicate)

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также