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.
When you write data to the characteristic of remote device by
func writeValue(_ data: Data, for characteristic: CBCharacteristic, type: CBCharacteristicWriteType) https://developer.apple.com/documentation/corebluetooth/cbperipheral/1518747-writevalue
you should use
func maximumWriteValueLength(for type: CBCharacteristicWriteType) -> Int https://developer.apple.com/documentation/corebluetooth/cbperipheral/1620312-maximumwritevaluelength
to figure out the size of chunks to split your data into.
On iOS 9+ you can use this method on each subscribed CBCentral to determine how much data to send per chunk:
[central maximumUpdateValueLength];
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.
I'm using iOS 7.1.1 and have also found that I can send as much as 132 bytes reliably from an iPhone to an iPad using BLE. I also heard that 20 bytes was the max but it sure doesn't seem like it is
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With