iosbluetoothbluetooth-lowenergycore-bluetoothios-bluetooth

iOS determine data length of CBCharacteristic


Is there any way to dynamically sniff out the data length of a CBCharacteristic?

I'm evolving the characteristic API on a gadget I have, and I want to change the field width of one of the characteristics. If I make the change in the iOS side so that it writes a value of 9 bytes instead of 7 bytes, a device that has the old API (characteristic field width of 7) on it causes the following to occur when I attempt to write the value:

Error Domain=CBATTErrorDomain Code=13 "The value's length is invalid." UserInfo={NSLocalizedDescription=The value's length is invalid.}

What I'd like to determine is whether or not I can catch that error, and then somehow query the CBCharacteristic what its current field width is. Obviously at some point, it determined that 9 > 7 and caused the error to bubble up. I've tried reading the descriptor associated with the characteristic, but there's just one descriptor (<CBDescriptor: 0x2830cbe40, UUID = Client Characteristic Configuration, value = 2>) which doesn't tell me much.


Solution

  • This is a standard ATT protocol error that's generated by the peripheral, not iOS. It means you sent a value and the peripheral responded that the value was the wrong length. Characteristics do not necessarily have specific lengths. The correct length might be context dependent. For example, a characteristic might accept 2 bytes, 4 bytes, or 8 bytes. If you write 7 bytes, it could return this error. Or the first byte might be a command selector, and the rest might be the payload that needs to be of a specific length for that command. There's no simple "what's the length of this characteristic" for these designs.

    There's no general way to know what a remote service wants. You need to know that through API documentation. This is the equivalent of getting back a 405 Method not allowed error from an HTTP server. It's up to you to know what methods are allowed. A particular system might give you a way to query it, and it might not. It's not part of the HTTP spec to provide that, and similarly it's not part of the BLE spec.