17

I'm creating an app that gets the UUID of all BLE devices within range. I've gotten it working fine in Android, where it gives me the advertisement data as a byte array. Now I'm trying to do the same in iOS.

I'm running a scan and it's detecting the device, and in the callback there's an NSDictionary called advertisementData. But the only information in it is as follows:

kCBAdvDataChannel = 39;
kCBAdvDataIsConnectable = 1;
kCBAdvDataLocalName = jaalee;
kCBAdvDataTxPowerLevel = 0;

Am I right in thinking I should be getting the entirety of the advertising packet? If not, how can I get it?

user2564511
  • 257
  • 1
  • 6
  • 14
  • You can't, except if the BLE device explicitly add others info in its advertisement data. `Core-Bluetooth` provides a high-level implementation. What other information do you want? – Larme Apr 03 '14 at 09:42
  • Corebluetooth provides the CBPeripheral object. The `identity` property provides the UUID, which is equivalent to, but is not, the MAC address. The UUID can also change periodically, particularly if the peripheral is an iOS device – Paulw11 Apr 03 '14 at 10:03
  • 1
    Also, I notice that you tagged your question [ibeacon] - Are you trying to gather BLE peripherals or iBeacons - on iOS the former are handled by the CoreBluetooth framework and the latter by the CoreLocation framework – Paulw11 Apr 03 '14 at 10:04
  • This is meant for all BLE devices, including iBeacons. The CBPeripheral object doesn't have an identity property- it has an identifier property, but that's just a temporary identifier internal to iOS. I need what the BLE device is broadcasting in it's advertisement. – user2564511 Apr 03 '14 at 11:20
  • 2
    Basically, on iOS you can't do "all BLE devices, including iBeacons" - you have to use different APIs for generic connectable devices with services vs. advertise-only iBeacons. – Chris Stratton Apr 03 '14 at 15:46

2 Answers2

19

Unfortunately, iOS does not allow you to access the raw advertisement data. I wrote a blog post demonstrating this. While the post is specifically about iBeacons, it applies to any BLE advertisement.

EDIT: To clarify, you can read the raw manufacturer data bytes or service data bytes of non-iBeacon advertisements. It is only the iBeacon advertisements that have their manufacturer data bytes hidden by CoreLocation. See here: Obtaining Bluetooth LE scan response data with iOS

The equivalent MacOS CoreLocation methods do allow this, so it is probably an intentional security or power saving restriction on iOS.

davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • 1
    I actually was just looking at that blog post. And everything that I see agrees with you except the fact that other apps on my devices do this. One called Locate iB shows a BLE device's UUID among other information. So I'm erring on the side of "it can be done because others do it". – user2564511 Apr 03 '14 at 12:55
  • It's possible that other apps just use characteristics to get this information, assuming they'll be in place, so I'm gonna accept your answer since it seems the most likely at this point. – user2564511 Apr 03 '14 at 13:48
  • 1
    I'm actually the author of the Locate IB app you mention. The way it gets the iBeacon Proximity UUID is from the CoreLocation's didRangeBeaconsInRegion callback, which relies on OS-level code to parse the raw advertisement data and only give you certain fields out of it, in this case the iBeacon Proximity UUID, Major and Minor. – davidgyoung Apr 03 '14 at 16:49
  • It sounds like that's what I need to do then. Thanks for the help. – user2564511 Apr 04 '14 at 07:42
  • 1
    This seems like a lack of major feature. Even though it does not allow to read raw advertisement, it should allow to read at least some bytes of custom data. The only thing that I can modify in firmware is `kCBAdvDataLocalName` but sending lets say temperature in that does not makes sense. –  Oct 15 '14 at 09:13
18

Based on official documentation from Apple iOS and my personal experience:

YES, iOS does not allow you to access the RAW advertisement data.

BUT

If your intention is to put information in advertising packet and read them from the iOS app without connect with the peripheral, this is possible to do. Here is described how:

1) in the peripheral firmware you have to insert your manufacturer specifica data in the advertising packet, with the data type GAP_ADTYPE_MANUFACTURER_SPECIFIC (0xFF) Remember that in the Manufacturer Specific Data, first 2 octets contain the Company Identifier Code followed by the additional manufacturer specific data

2) in the iOS

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

You can see the manufacturer specific data in advertisementData dictionary with key:

CBAdvertisementDataManufacturerDataKey

3) if you want that in your App receive a callback notification every advertising packet sent by peripheral to iOS, remember to change the scan option to YES. Look at this post about that: Core Bluetooth - constant RSSI updates of in-range devices

In my blog post will be soon a tutorial: http://www.megabri.com/

Community
  • 1
  • 1
megabri
  • 881
  • 8
  • 11