MTU (Maximum Transmission Unit) е максималният размер на полезни данни в един BLE пакет, който може да бъде пренесен между устройства в една GATT транзакция. В BLE Classic (4.x) MTU е фиксиран на 23 байта, достатъчен за малки отчитания на сензори, но недостатъчен за пренос на файлове или OTA обновления. Bluetooth Core Specification 4.2 (2014) въведе процедурата MTU Size Request, позволяваща съгласяване на по-голям MTU — до 247 байта (BLE 5.0 — до 251 байта). Правилното конфигуриране на MTU е един от ключовите фактори за производителност на BLE приложенията, пренасящи големи обеми от данни.
Основни моменти
Maximum Transmission Unit (MTU) в контекста на BLE — е максималният размер на Application Protocol Data Unit (APDU), който устройството може да приеме в една GATT заявка. MTU се определя на ниво ATT (Attribute Protocol) и включва ATT хедър (1 байт) + полезни данни. По подразбиране всички BLE устройства поддържат MTU от 23 байта (23 = 1 байт ATT хедър + 22 байта данни).
MTU не е физическо ограничение на радиоканала, а споразумение между устройствата на ниво GATT. Физическият размер на BLE пакета на ниво Link Layer може да бъде по-голям (до 27 байта в BLE 4.0, до 257 байта в BLE 5.0 с Data Length Extension), но GATT слойт ограничава колко данни да бъдат пренесени в една транзакция. Data Length Extension (DLE) — е отделен механизъм на ниво Link Layer, който увеличава физическия пакет до 251 байта и трябва да бъде съгласуван отделно.
Разликата между MTU и DLE: ATT MTU — колко данни се пренасят в една GATT заявка, DLE — колко данни се пазват в един Link Layer пакет. За максимална скорост и двата параметъра трябва да бъдат съгласувани. Без DLE дори при MTU от 247 байта данните ще бъдат фрагментирани в няколко Link Layer пакета от 27 байта, намалявайки пропускателната способност.
MTU Size Request — процедура, инициирана от Central след установяване на GATT връзка. Central изпраща MTU Request с посочване на своята MTU капацитет (максималният размер, който може да приеме). Peripheral отговаря с MTU Response с своята стойност. Използваният MTU е минимумът от двете стойности. Ако Central предложи MTU 512, а Peripheral поддържа само 128, връзката ще използва MTU 128.
import CoreBluetooth
// Изискване на максимален MTU в iOS
func requestMTU(central: CBCentralManager,
peripheral: CBPeripheral) {
peripheral.maximumWriteValueLength(
for: .withoutResponse
)
// iOS автоматично съгласява MTU при свързване
// MTU = 512 за BLE 5.0 устройства
let mtu = peripheral.maximumWriteValueLength(
for: .withResponse
)
print("Съгласуван MTU: " +
String(mtu))
}
Време за съгласяване: MTU Request трябва да бъде изпратен след откриване на услугите (discoverServices), но преди започване на активния пренос на данни. В iOS Core Bluetooth автоматично съгласява MTU при свързване — разработчикът няма нужда да изпраща MTU Request ръчно. В Android трябва изрично да се извика requestMTU. След съгласяване MTU остава фиксиран за тази връзка — повторно съгласяване е невъзможно без прекъсване и повторно свързване.
ATT (Attribute Protocol) — протоколът, върху който е изграден GATT. ATT пакетът има максимален размер от 257 байта (ATT_MTU-1). От тях 1 байт е Opcode (тип операция), 1 байт е Handle, и до 255 байта е Value. Поради това максималният MTU, разрешен от ATT спецификацията, е 257 байта (в практика се използва до 251 байта, тъй като някои обслужващи полета пак са необходими).
За изпращане на данни, по-големи от MTU, се използва фрагментация на ниво приложение. Разработчикът сам разделя данните на парчета с големина ≤ MTU и ги изпраща последователно. Всяко парче е формално отделно GATT Write Request. Приемащата страна събира парчетата в единен буфер. В GATT няма вградена поддръжка за фрагментация — това е задача на разработчика.
| BLE версия | Макс. MTU | Макс. DLE | ATT MTU лимит |
|---|---|---|---|
| BLE 4.0 / 4.1 | 23 байта | 27 байта | ATT фиксиран |
| BLE 4.2 | 247 байта | 251 байт | 257 байта |
| BLE 5.0 | 251 байт | 251 байт | 257 байта |
| Android + iOS | 512 / 517 | 251 байт | Надвишаване на ATT |
Любопитен факт: iOS и Android изискват MTU съответно 512 и 517 байта, но тази стойност надвишава ATT лимита. В практика BLE стекът автоматично фрагментира такива данни, като ги изпраща като няколко последователни GATT заявки от максимум 251 байта. За разработчика разликата е незабележима — writeValue работи с всякаква големина до 512 байта в iOS.
Размерът на MTU пряко повлиява пропускателната способност на BLE връзката. При MTU от 23 байта максималната полезна скорост на пренос е около 7–10 KB/s при идеални условия. Увеличаването на MTU до 247 байта повишава скоростта на 60–90 KB/s (с DLE и оптимален connection interval). Това е особено важно за приложения, пренасящи изображения, аудио фрагменти или логове.
Производителността на BLE преноса зависи от три фактора: MTU (колко данни в една ATT заявка), connection interval (колко често се случват събитията на размяна) и DLE (колко данни в един Link Layer пакет). Оптималната конфигурация за максимална скорост: MTU = 247, DLE = 251, connection interval = 7.5 ms (минимална стойност).
Според данните на Bluetooth SIG White Paper (2023), увеличаването на MTU от 23 на 247 байта при connection interval от 30 ms увеличава пропускателната способност от 8 KB/s на 42 KB/s — 5-кратен растеж. При connection interval от 7.5 ms пропускателната способност достига 88 KB/s. За приложения, които не изискват висока скорост (температурни сензори, BLE маяци), стандартният MTU от 23 байта остава достатъчен.
iOS Core Bluetooth автоматично съгласява MTU при свързване с Peripheral. Разработчикът може да провери текущия MTU чрез maximumWriteValueLength, но не може да го настрои ръчно. iOS използва MTU до 512 байта за BLE 5.0 устройства и до 247 за BLE 4.2. За запис на големи обеми от данни използвайте writeType: .withResponse за гарантирано доставяне.
// Изискване на MTU в Android (Kotlin)
val bluetoothGatt: BluetoothGatt = ...
// Изискване на MTU 517 байта
bluetoothGatt.requestMtu(517)
// Обработка на резултата в callback
override fun onMtuChanged(
gatt: BluetoothGatt,
mtu: Int,
status: Int
) {
if (status == BluetoothGatt.GATT_SUCCESS) {
println("MTU negotiated: $mtu")
}
}
Android предоставя BluetoothGatt.requestMtu(int), който позволява да изискате всякаква MTU до 517 байта. Действителният MTU се определя от периферийното устройство — ако то поддържа само 23 байта, Android ще върне MTU 23. За определяне на текущия MTU използвайте gatt.requestMtu(0) — това върща текущата стойност без опит за промяна. Android 12+ поддържа автоматично съгласяване на MTU при свързване чрез TRANSPORT_LE.
Кросплатформените фреймуъркове (Flutter, React Native) обикновено предоставят API за requestMTU. В библиотеката FlutterBlue Plus MTU се задава като параметър за свързване. В RxAndroidBle — чрез метода requestMtu. Препоръчва се винаги да съгласявате максималния MTU веднага след откриване на услугите, преди започване на преноса на данни, за да се избегне фрагментация на ниво приложение.
OTA (Over-The-Air) обновления на фирмуера — най-изисквателният сценарий по отношение на MTU в BLE. Типичният размер на фирмуера на IoT устройство е 100–500 KB. При MTU от 23 байта и connection interval от 30 ms, преносът на 100 KB отнима около 2–3 минути. При MTU от 247 байта и DLE от 251 байта — 20–40 секунди. А при MTU от 512 байта (iOS) — 10–15 секунди.
Процесът на OTA обновление обикновено включва: фрагментация на фирмуера на пакети с големина ≤ MTU, последователно изпращане чрез Notify/Write, проверка на контролната сума на всеки пакет и потвърждаване на приема. Ако някой пакет се загуби, устройството изисква повторно изпращане. Надеждността на OTA критично зависи от правилния избор на MTU и connection interval.
Препоръки за OTA: съгласете максималния MTU (247–512 байта), настройте connection interval на 7.5–15 ms (ако устройството поддържа), използвайте DLE (Data Length Extension) за увеличаване на физическия пакет до 251 байта. За устройства с ограничена буферна памет (напр. BLE модули на база nRF52) проверете максималния MTU в спецификацията на чипа.
Често задавани въпроси
Връзката ще използва подразбирания MTU — 23 байта. За повечето IoT сценарии (пренос на показания от сензори) това е достатъчно. За пренос на големи обеми от данни, скоростта ще бъде 5–10 пъти по-ниска от тази със съгласуван MTU от 247 байта.
Не, MTU се съгласява един път след свързване и не може да бъде променен без прекъсване и повторно свързване. Поради това се препоръчва да съгласявате MTU веднага след откриване на услугите, преди започване на активния пренос на данни.
Това са исторически установени емпирични максимуми за всяка подредица. Действителният ATT MTU е все пак ограничен до 257 байта според спецификацията. Подредиците автоматично фрагментират данни, по-големи от 251 байта, в няколко пакета, така че разликата между 512 и 517 е пренебрежима.
MTU — размер на GATT заявката на ниво ATT. DLE — размер на физическия пакет на ниво Link Layer. Без DLE всяка GATT заявка (до 247 байта) се фрагментира на пакети по 27 байта. С DLE — се пренася в един пакет. За максимална скорост и двата параметъра трябва да бъдат съгласувани.
За фитнес трекер, който пренася пулс и кръчки, стандартният MTU от 23 байта е достатъчен. Ако трябва да пренасяте история на тренировки (обем 10–50 KB) — съгласете MTU от 247 байта за да ускорите синхронизацията на данните при свързване с смартфона.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също