Організація GATT-обміну з BLE-периферією
Уявіть: ви розробляєте додаток для взаємодії з медичним датчиком пульсу через BLE. Після підключення ви намагаєтеся підписатися на сповіщення про серцевий ритм, але дані не приходять. На Android ви бачите помилку status 133, а на iOS запис характеристики повертає помилку. Ми стикалися з цим у більш ніж 20 проєктах з інтеграції BLE-пристроїв: медичні датчики, фітнес-трекери, промислові контролери. Одна з частих задач — підписка на сповіщення про серцевий ритм або передача великих обсягів даних, наприклад, прошивки розміром 100 КБ. При стандартному MTU в 23 байти на відправку 100 КБ йде близько 5000 пакетів, що займає хвилини. Запит збільшеного MTU до 512 байт скорочує кількість пакетів до ~200 і час передачі до кількох секунд. Ми виробили системний підхід до організації надійного обміну даними з BLE-пристроями: від правильної підписки на сповіщення до черги операцій та MTU-negotiation.
Типи операцій з характеристиками GATT
Кожна GATT-характеристика має набір прапорців properties, які визначають, які операції з нею можливі. Ось таблиця для швидкої довідки:
| Прапорець | iOS (CBCharacteristicProperties) | Android | Операція |
|---|---|---|---|
| Read | .read |
PROPERTY_READ |
Одноразове читання |
| Write | .write |
PROPERTY_WRITE |
Запис з підтвердженням |
| Write Without Response | .writeWithoutResponse |
PROPERTY_WRITE_NO_RESPONSE |
Швидкий запис |
| Notify | .notify |
PROPERTY_NOTIFY |
Сповіщення без підтвердження |
| Indicate | .indicate |
PROPERTY_INDICATE |
Сповіщення з підтвердженням |
Write Without Response швидший — немає ACK від пристрою. Підходить для потокової передачі (аудіо, показники датчиків). Write — для команд, де важлива гарантія доставки.
MTU: як збільшити пропускну здатність BLE-каналу
За замовчуванням MTU (Maximum Transmission Unit) BLE становить 23 байти, з яких корисних — тільки 20. Для передачі 10 КБ даних це означає 500 пакетів. Якщо запросити збільшений MTU (наприклад, 512), кількість пакетів скорочується до ~20 — економія часу до 90%. Ось як це робиться на кожній платформі:
| Платформа | MTU за замовчуванням | Автоматичне узгодження | Ручний запит |
|---|---|---|---|
| iOS | 23 | Так (з iOS 9+) | Непрямо через максимальну довжину запису |
| Android | 23 | Ні | gatt.requestMtu(512) + колбек onMtuChanged |
На практиці більшість BLE-чипів підтримують MTU 247–512 байт. При передачі прошивки або великих конфігурацій це критично.
Як підписатися на сповіщення BLE і не пропустити дані?
Підписка на сповіщення — стандартний спосіб отримувати дані від BLE-пристрою в реальному часі. На iOS достатньо викликати setNotifyValue(true, for:). Але на Android процес складніший: потрібно не тільки ввімкнути сповіщення локально, а й явно записати в дескриптор CCCD (Client Characteristic Configuration Descriptor) значення ENABLE_NOTIFICATION_VALUE. Багато розробників пропускають цей крок — і сповіщення не приходять.
iOS: Notify-підписка та парсинг
// Вмикаємо notify
peripheral.setNotifyValue(true, for: characteristic)
// Отримуємо дані
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
guard error == nil, let data = characteristic.value else { return }
// Приклад: датчик відправляє 3 байти [flags, heartRate, energyExpended]
guard data.count >= 2 else { return }
let flags = data[0]
let heartRate: Int
if flags & 0x01 == 0 {
// heart rate в 1 байті
heartRate = Int(data[1])
} else {
// heart rate в 2 байтах (little-endian)
heartRate = Int(data[1]) | (Int(data[2]) << 8)
}
}Робота з бінарними даними через Data + байтові зсуви. Якщо пристрій нестандартний і документація мізерна — Wireshark + BLE sniffer допомагають розібрати протокол.
Android: Notify + CCCD дескриптор
Підписка на notify вимагає двох кроків: увімкнути notify локально і записати в CCCD на пристрої:
fun enableNotification(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
// Крок 1: вмикаємо locally
gatt.setCharacteristicNotification(characteristic, true)
// Крок 2: пишемо дескриптор на пристрій
val cccd = characteristic.getDescriptor(
UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
) ?: return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
gatt.writeDescriptor(cccd, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
} else {
@Suppress("DEPRECATION")
cccd.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
@Suppress("DEPRECATION")
gatt.writeDescriptor(cccd)
}
}Крок 2 часто пропускають — і сповіщення не приходять. Це найпоширеніша помилка при роботі з notify.
Чому на Android виникає помилка status 133 і як її уникнути?
Одна критична деталь Android BLE: не можна виконувати кілька GATT-операцій одночасно. Тільки одна операція в польоті. Наступну відправляємо тільки після отримання колбека попередньої. Порушення цього правила призводить до помилки status 133 або втрати даних на більшості Android-пристроїв.
Рішення — черга:
class BleOperationQueue {
private val queue: LinkedList<BleOperation> = LinkedList()
private var operationInProgress = false
fun enqueue(operation: BleOperation) {
queue.add(operation)
if (!operationInProgress) {
executeNext()
}
}
fun onOperationCompleted() {
operationInProgress = false
executeNext()
}
private fun executeNext() {
val op = queue.poll() ?: return
operationInProgress = true
op.execute()
}
} Процес впровадження BLE-обміну
Впровадження надійного BLE-обміну ми розбиваємо на етапи:
- Аналіз протоколу пристрою або специфікації GATT-сервісів.
- Проєктування черги операцій та схеми парсингу даних.
- Реалізація на цільових платформах (iOS/Android) з урахуванням MTU, підключення, перепідключення.
- Тестування на реальних пристроях із різними версіями ОС.
- Інтеграція в додаток замовника та передача документації.
Що входить у роботу
У рамках послуги ми надаємо:
- Аналіз та документування поточного протоколу BLE-пристрою.
- Вихідний код модуля обміну даними на Swift/Kotlin з підтримкою черги операцій та MTU.
- Інтеграційне тестування на 3+ реальних пристроях.
- Коротку документацію по API модуля.
- Консультації протягом місяця після здачі.
Ми гарантуємо стабільну роботу підписки на сповіщення, коректний запис команд та обробку помилок на обох платформах. Зв'яжіться з нами для попередньої оцінки вашого проекту. Отримайте консультацію наших інженерів, якщо ви шукаєте готове рішення для інтеграції BLE-пристрою або зіткнулися з помилками обміну даними.
Терміни та вартість
Термін реалізації під ключ — від 3 до 10 днів залежно від складності бінарного протоколу та кількості платформ. Вартість розраховується індивідуально після аналізу вимог.







