Maximum data size when sending data via BTLE on iOS

BlackWolf picture BlackWolf · Jun 22, 2014 · Viewed 9.2k times · Source

I am currently implementing an iOS application that uses CoreBluetooth to transfer data between 2 devices. For example, to send data from the central to the peripheral, I use this code:

NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:nil];
NSLog(@"Writing data of length %d", [data length]);
[peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];

This works absolutely fine, but the thing is that I have read multiple times now that characteristics can transfer a maximum of 20 bytes at once. Also, when I look at Apple's BTLE Example Code they implement a mechanism that splits the data into chunks of 20 bytes. But the above code prints something like Writing data of length 124 - the data arrives fine at the other device, though.

So: Why is this working at all? And even more so, I am afraid that this could break at some point, especially when non-iOS devices come into play.

Answer

Peter Kämpf picture Peter Kämpf · Mar 23, 2016

The BLE standard requires 23 bytes as the minimum ATT_MTU (Attribute Protocol Maximum Transmission Unit) which all BLE devices must support. The maximum ATT_MTU is 255 bytes, however, and has been doubled again for BLE 4.2.

BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part A]:

All L2CAP implementations shall support a minimum MTU of […] 23 octets over the LE-U logical link; however, some protocols and profiles explicitly require support for a larger MTU.

When establishing a connection, both devices will exchange their ATT_MTU size, and the smaller of both values is used. When Apple started with BLE, they would only support the minimum, but have since expanded the possible size. That is why your 124 bytes work, but the older documentation and sample code uses a much smaller ATT_MTU.