6

I am working with Bluetooth Low Energy devices, and I was wondering whether it is possible to read the Scan Response Data to an advertisement with iOS and Core Bluetooth without connecting.

I understand that after reading an advertisement packet, you can request additional data from the peripheral in the format of a 31 byte scan response. I know that Core Bluetooth suggests that if the ad packet is full, you can put the local name in the scan response packet, but does it allow you to see the whole packet?

ccpmark
  • 1,005
  • 1
  • 10
  • 11

2 Answers2

15

Yes, you can use CoreBluetooth to read the full manufacturer data or service data bytes of a BLE advertisement as long as it is NOT an iBeacon advertisement. If it is an iBeacon advertisement, CoreBluetooth will block your ability to see the bytes. The callback you use is as follows:

- (void)   centralManager:(CBCentralManager *)central
didDiscoverPeripheral:(CBPeripheral *)peripheral
    advertisementData:(NSDictionary *)advertisementData
                 RSSI:(NSNumber *)RSSI

The raw service data or manufacturer data bytes will be present inside the NSDictionary *advertisementData. But they key holding those data will be removed by the operating system for iBeacons.

Here's an example of what you get in the advertisementData NSDictionary in the callback. This example is for detecting an AltBeacon advertisement (an open-source beacon standard), with identifiers 2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6 1 2

{
    kCBAdvDataIsConnectable = 0;
    kCBAdvDataManufacturerData = <1801beac 2f234454 cf6d4a0f adf2f491 1ba9ffa6 00010002 be00>;
}

You can see how to decode the above bytes by looking at the AltBeacon spec here.

For more details about why you can't read iBeacon data along with additional code showing how you set this up, see here:

http://developer.radiusnetworks.com/2013/10/21/corebluetooth-doesnt-let-you-see-ibeacons.html

davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • I'm specifically concerned with the scan response data. Do you know if iOS automatically requests scan response data, or how to initiate the request? – ccpmark Aug 20 '14 at 15:10
  • The information above applies to the data in the broadcast advertisement itself. iOS certainly does **NOT** request scan response data automatically. I have not tried doing this, and at first glance, I do not see anything in `CBCentralManager` allowing you to do this... this probably should be a new question. – davidgyoung Aug 20 '14 at 16:36
  • @davidgyoung In your another post http://stackoverflow.com/a/22837799/670119 you're writing that accessing the raw advertisement data of any BLE advertisement isn't possible in iOS. I'd like to ask which answer is correct? – Lukáš Kubánek Nov 16 '14 at 12:15
  • My answer above is correct. When I wrote the earlier answer you reference, I had not yet tried reading the bytes of a non-ibeacon advert, so I did not know better. :) – davidgyoung Nov 16 '14 at 14:36
  • I have edited the other answer to reflect my current understanding. – davidgyoung Nov 16 '14 at 14:43
  • 4
    Core Bluetooth does automatically request scan response data when the app is in the foreground. It's not something you can request. didDiscoverPeripheral will generally be called twice. First without the scan response data, and the second time with. However, in the background, the second event with scan response data may not occur. – Marcus Adams Mar 16 '15 at 19:00
  • Does `CoreBluetooth` filter out all packets with the iBeacon indicator octets (`02 15`) prior to returning the `NSDictionary`? Does it mean packets without `02 15` will pass through? – Kar Oct 07 '15 at 06:47
  • Yes, advertisements with a byte sequence that is not recognized as an iBeacon will have their bytes populated under the kCBAdvDataManufacturerData key. – davidgyoung Oct 07 '15 at 11:12
  • @davidgyoung I strongly believe on what you have said there but is there any documentation that will prove it? Because, I need to show it to my boss so he would believe that it will not work if an advertisment is an iBeacon advertisment. – Jongers Aug 17 '16 at 08:11
  • Like lots of iOS limitations, this one is a black box without documentation. My blog post above is essentially an experimental proof, I'd show this to your boss. – davidgyoung Aug 17 '16 at 12:48
  • 6
    I believe this post is very much confused - the RAW ADVERTISEMENT bytes received by Core Bluetooth ARE NOT AVAILABLE. There are bytes yes, for Services and Manufacturer Data for example, but those fields have already been parsed. There is a lot of information filtered by iOS that we don't get - and I believe people reading this post are confusing the full raw bytes transmitted by a BLE device and received by iOS, from bytes available in the `advertisementData` parameter. If there is indeed a way to get the raw bytes, please let me know. – dinesharjani Dec 17 '18 at 10:20
  • 1
    @dinesharjani,you are correct that the raw bytes of the *full advertisement* are not available, but the *raw bytes* of the manufacturer data part of an advertisement absolutely are available for the BLE manufacturer advertisement type. Similarly, the raw bytes of the service data are available in a BLE service advertisement type. I have edited my answer to make that clearer. – davidgyoung May 10 '19 at 13:42
6

I am working with a peripheral that has some manufacturer data which I believe is transmitted in the scan response because there's no room for it in the initial advertisement with a 128-bit UUID plus channel, RSSI, and connectable flag. I am receiving two calls to didDiscoverPeripheral:... in quick succession (3ms apart including some handling time in my code). The first does not have the kCBAdvDataManufacturerData key in the dict, but the second does. I am assuming that the scan response is being requested automatically and the reply results in the second call.

eclux
  • 984
  • 1
  • 9
  • 12