I’m trying to read characteristics from a service on a Bluetooth LE device. For some reason, for some characteristics, after calling -[CBPeripheralManager discoverCharacteristics:forService]
, the peripheral:didDiscoverServices:
callback is getting 0 characteristics. Are there any workarounds to allow me to read the characteristics of this service?
When installing Hardware IO Tools for Xcode and running PacketLogger, it is apparent that the discoverServices call is causing a 0x08 Read By Type request (Bluetooth® Core Specification Volume 3, Part F, Section 3.4.4.1) with Starting Handle=0x1a, Ending Handle=0x1a, Attribute Type=0x2803.
Also, by defining the following class extensions to read the protected fields, it is apparent that the service that I’m interested in, 0x180a=Device Information, also has ATT handles too close to comfort: _startHandle=0x1a and _endHandle=0x1a.
@implementation CBService(ProtectedProps)
- (NSNumber*) startHandle {
return self->_startHandle;
}
- (NSNumber*) endHandle {
return self->_endHandle;
}
@end
@implementation CBCharacteristic(ProtectedProps)
- (NSNumber*) descriptorHandle {
return self->_handle;
}
- (NSNumber*) valueHandle {
return self->_valueHandle;
}
@end
By the way, when I read the device from LightBlue on an iPhone 4S, the service works fine, and I can read the 3 characteristics of this service.
I’m testing this on OSX 10.9 Mavericks with Apple Bluetooth Software Version: 4.2.0f6 12982. The device that I’m testing is a Livescribe 3.
Here is a table of the actual GATT handles, CBService handles, and UUIDs. It looks like having a 16-bit UUID after a 128-bit UUID messed up the table. Bluetooth 4.0 section 3.1 states that 16-bit UUID services “should” be grouped together for performance, but I don’t think they must.
- 0001–0004 0001–0004 uuid:1801
- 0005–0009 0005–0009 uuid:1800
- 0010–0019 0010–0019 uuid:128 bit UUID
- 001A–0020 001A–001A uuid:180a
- 0021–0023 missing uuid:180f
- 0024–002A 0021–0027 uuid:128 bit UUID
- 002E–0031 002B–002E uuid:128 bit UUID
The bug in reading 16-bit UUIDs interleaved with 128-bit UUIDs was probably fixed in OSX 10.9.1. However, the bad values were still cached because the computer was still bonded with the peripheral. So if you previously connected to the peripheral, the bug will still manifest itself no matter how many times you reconnect or restart because of the bad cached GATT values.
I had to erase the bonding cache /Library/Preferences/com.apple.Bluetooth.plist and kill blued. See my other question Does blued cache ATT values, and how to clear the cache? for more details.