1

I am using the example project from google (BluetoothLeGatt) to receive data from a BLE device and trying to read a specific byte within it's scanRecord obtained by the onLeScan method.

My problem is that there is missmatch between the data I am observing in the network and what I see on logs.

This is on Android 4.3 and using a Samsung Galaxy S4 to test it. To verify that the scanRecord logs are correct on Android, I am using TI's Packet Sniffer to observe the byte stream being broadcasted by the device, and here it is: enter image description here

That is 31 bytes of data being broadcasted by the device to the network, and there are no other working devices around.

02 01 1A 1A FF 4C 00 02 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0C C6 64

On the other hand, Android logs claim that the data being received has the length of 62 bytes and it matches the data until the 29th[0-indexed] byte, having 0s for the rest of the data.

02-12 15:34:09.548: D/DEBUG(26801): len: 62 data:02011a1aff4c000215000000000000000000000000000000000000000cc60000000000000000000000000000000000000000000000000000000000000000

And this is the code piece I used in order to obtain the logs within the LeScanCallback method:

int len = scanRecord.length;
String scanHex = bytesToHex(scanRecord);
Log.d("DEBUG", "len: " + len + " data:" + scanHex);

The method used to convert byte array to hex representation:

private static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        int v;
        for ( int j = 0; j < bytes.length; j++ ) {
            v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    } 

I used a few other example projects including Dave Smith's example and RadiusNetworks' Android iBeacon Library and I ended up with the same results. I can't possibly understand why do I receive 62 bytes of data when "Packet Sniffer" shows (and I also know) that it should be 31 bytes. This would not be my main concern if I was able to read the data in the last byte correctly (I get 00 instead of 64 from Android's BluetoothAdapter). But that is not the case either.

I would appreciate any suggestions about what might potentially be the reason for this missmatch for both the data(last byte only) and the data size between what Android receives and what is actually on the network.

Kerem
  • 2,867
  • 24
  • 35

1 Answers1

2

Your transmission is malformed, containing 31 bytes of payload data (PDU length of 37) when its internal length fields indicate it should in total contain only 30 bytes (PDU length 36).

Let's take a look at your data

02 01 1a

This is a length (2) of type codes - 01 and 1a, and good so far

1a ff 4c ...

Now we have a problem - the 1a is a length code for this field (manufacturer specific data), value of 26. Yet 27 bytes of data follow it in your case, instead of the proper 26 you have indicated you will provide.

Now, if you have a properly formed packet, you will still get a larger buffer padded with meaningless (likely uninitialized) values following the proper content, but you can simply ignore that by parsing the buffer in accordance with the field-length values and ignoring anything not accounted for in the proclaimed lengths.

But with your current malformed packet, the copying of packet data to the buffer stops at the proclaimed content size, and the unannounced extra byte never makes it into the buffer your program receives - so you see instead something random there, as with the rest of the unused length.

Probably, when you made up your all-zeroes "region UUID" (might want to rethink that) you simply typed an extra byte...

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117
  • There are no extra bytes, in fact there is an extra byte but it was placed on purpose by the manufacturer at the end of the stream. The length indeed was the issue here, when we changed 1A to 1B, exactly 27 bytes were being grabbed by the buffer and it solved the problem. Thanks a lot for pointing that out. After your recommendation, with the help of @davidgyoung's answer here:http://stackoverflow.com/a/19040616/1505341, I have read up the related sections in the Core Bluetooth spec, it clarified a lot of things. I'll edit my question to reflect my observations for other people who might need. – Kerem Feb 13 '14 at 20:08
  • I guess that a properly formatted (self-consistent) longer packet may work as long as it's your own code in both peripheral and central, and it's possible it may sometimes interoperate with other implementations, but I'd be cautious about going down that route unless you intend to build a closed system using only customizable components, and not (for example) ones where the decoding of this sort of packet might be performed by the operating system rather than by code you provide or can change. – Chris Stratton Feb 13 '14 at 20:58
  • I think my main concern about it would be to lose compatibility with iBeacon one day, I mean if they decide to include the length control for their iBeacon packets then any device not operating with the same data length as iBeacons will become incompatible with iOS devices. At least for now, it looks like only the 16 bit reserved UUID is what's making this stream compatible with Apple standard: https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers. But who knows when or if they will decide to add extra control for their packets. – Kerem Feb 13 '14 at 21:13