Get advertisement data for BLE in iOS - ios

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?

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.

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/

Related

The background advertised peripheral to be scanned from other BLE devices either in foreground/background

I'm working on with BLE of iOS where in i could able to establish a peripheral advertisement and scanning at the same time.
I have 2 devices where in both would scan advertise at the same time, it works fine when the devices are in foreground.
Now the issue is: The device is in background meaning the advertisement is not working(not able to show the Local Name and UUID as it will mask as per Apple) because as per Apple Docs:
advertisement key are placed in a special “overflow” area; they can be discovered only by an iOS device that is explicitly scanning for them.
Now my question how can i scan for this overflow area?
Also note when a device is advertising in background i do not get a call back in below delegate too:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI;
Any possible way i can do this approach, which would really helpful.
The Solution to the above scenario is as per #Paulw11 said.
We just need to scan for specific Peripheral Id.
Thanks Paulw11

Unique identifier for peripheral BLE device

So I have peripheral BLE device and I need some identifier for it to later share with another iPhone. Example I connect with iPhone 'A' to peripheral. iPhone 'A' saves peripheral's identifier to database and later I easily can take iPhone 'B' and connect to the peripheral found by this identifier.
Now there is UUID what changes for every iPhone-peripheral connection, but MAC
Address is not available. What could you suggest?
If you do not manufacture the peripheral yourself then you can not uniquely identify peripherals across different iOS devices. This is exactly how Apple wants it to be since it means that developers can't track user's locations or movement patterns based on device addresses. It would be a privacy concern.
If you manufacture the peripheral yourself then you can do pretty much whatever you want. For example: Use a custom Service uuid, add uuid to manufacturer data in advertisement, set unique advertisement names, etc etc.. But if the core purpose of all this is to track your user then I would guess that Apple might deny your submission.
I have a similar problem and many thread like this say you cannot obtain MAC address by CoreBluetooth. I want to connect to a BLE peripheral (I mean open and connectable peripheral) and store some information on a database so that a different iPhone can read the same database and use the informations when it connects to the same kind of BLE peripheral. For now I rely on the device name, obtained like this:
-(void)addDiscoveredDevice:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSString * name = [peripheral name];
}
because NSString * uuid = [[peripheral identifier] UUIDString]; gives me different results on different iOS devices.
Therefore, let's say my first problem is to know how many Apple Watch I have close to my iPhone, the second problem is to know if a given Apple Watch (e.g. John's Apple Watch) is close to my iPhone. Unfortunately this method doesn't work because users (e.g. John) or companies can change the name of their peripherals.
Yes I can rely on a combination of name + service uuid + characteristic uuid but for the same reasons, if the name changes it is useless.
Does anybody found a solution?

how to get public Bluetooth Device Address using core_bluetooth

We have one bluetooth devices.Bluetooth devices have one public bluetooth device address(BDA).In android they get bluetooth like (30:03:5B:00:15:12).I can get only device name and device UUID
like this
-(void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(#"Discovered peripheral %# (%#) (%#)",peripheral.name,peripheral.identifier.UUIDString); //PHARMACELL CAREOUSEL (0BEF07EA-7680-4223-2D5E-6CE159333F7E)
}
Please any one guide to us how to get BDA value
The simple answer is clearly: NO.
It is not possible (practically) to get the BDA from the seeds that generated a particular UUID. Provided that in fact the algorithm that generated your UUID did used the MAC Address of your device to generate it, and I guess you cannot guarantee that it is the case for the UUID generator you use, unless you have access to the UUID Generator code or algorithm.
As apple while generating UUID might use the MAC address of the device, other components like timestamps, hashing, UDID (iOS Devices) and also some other factors so its looks impossible to get it back from UDID also.
Android 6 has REMOVED ability to read own Device WIFI and BT MAC address, they will be hardcoded to 02:00:00:00:00:00.
This is "to protect user data" or more correctly "privacy". Too many big mall's have abused harvesting these addresses for getting user behavioral information.
On iOS it is not possible to get the MAC address of the device, it's abstracted by the CBPeripheral class and is identified internally in os by the identifier property. One way to get the MAC address, that's actually most popular, is to include the MAC address in the scan response. You could ask this feature from your BLE device manufacturer. Also the MAC address could be read from one of the GATT characteristics. Ask your BLE manufacturer for more details.

Obtaining Bluetooth LE scan response data with iOS

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?
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
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.

iOS CoreBluetooth reconnecting device with UUID

I have a Bluetooth 4.0 (BLE) device using the CC2541 chipset which I am interfacing with via the iOS Core Bluetooth Framework.
I can successfully make a connection to the device using Core Bluetooth when the device is in a discoverable/advertising mode and transfer data to and from the device without any problem.
I maintain a collection of device UUIDs that I have connected with and I am now attempting to connect to one of these devices again using:
CBCentralManager
- (void)retrievePeripherals:(NSArray *)peripheralUUIDs
Calling this function appears to work and I receive a callback to my implementation of the the following function:
CBCentralManagerDelegate
- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
The device I'm attempting to connect with is the one and only peripheral listed in the peripherals array that is passed to this function.
When I then attempt to connect to this device using my connect function (shown below) the connection will not initiate and I get no callbacks at all on either the CBCentralManagerDelegate or the CBPeripheralDelegate.
- (void) connectPeripheral:(CBPeripheral *)peripheral {
NSLog(#"Connecting to peripheral with UUID : %s\r\n",[self UUIDToString:peripheral.UUID]);
activePeripheral = peripheral;
activePeripheral.delegate = self;
[CM connectPeripheral:activePeripheral options:nil];
}
I can make the connection go through successfully, as described above, if I first place the device into discoverable/advertising mode, but this is not a workable solution. The device must allow reconnection without it being placed into discoverable mode.
I did note the answer given to this question CoreBluetooth: What is the lifetime of unique UUIDs suggests I need to pair/bond the BLE device with the iOS device but that this may be dependent on the BLE chipset, the device I'm using is the CC2541. Any advice on how to go about pairing with the device would be most useful, or indeed whether this is a necessary step. I have attempted to watch WWDC 2012: Advanced Core Bluetooth which might give me some assistance, but since Apple were hacked on Thursday I'm not able to access my acccount to watch the video.
Please let me know if any more details are required. The Bluetooth device is stable, but it is being developed internally. If changes may be required to the firmware to assist with the pairing process, I can pass this information along to the electronics team.
Why dont you try this?
It specifies first you need to send a request to a GATT characteristic that requires GATT_AUTHEN_READ permission. Then your CC2541 will respond with INVALID AUTHENTICATION. This will trigger Apple's internal Bonding mechanism and ask for a key. You can enter the passkey and then if the device and CC2541 are successfully paired, it will read the characteristic value and enter your callback.
NOTE: I'm not an iOS developer, but I have worked with CC2541. If you are using the default simplePEripheral example, then a characteristic in simpleProfile characteristic5 requires authentication to read. Take a look at profiles/SimpleProfile/simpleGATTprofile.c

Resources