BLE: Advertising local name and service UUID from background iOS - ios

According to iOS documentation, when an iOS application that utilizes BLE as a peripheral moves to background mode, peripheral name is not advertised and all service UUIDs are placed in a special ‘overflow’ area, they can be discovered only by an iOS device which is explicitly scanning for them.
I sniffed the BLE packets sent over the air when application is in background. There is no local name and service UUID data. There is an 'overflow' area which encodes the service UUID. A brief discussion can be found here: https://github.com/crownstone/bluenet-ios-basic-localization/blob/master/BROADCASTING_AS_BEACON.md
I wish to know if there is any way we can determine the actual service UUID being advertised from the data in 'overflow' area. iOS documentation states that when an app is advertising as BLE peripheral in background, another iOS app can find it by explicitly specifying the service UUIDs to scan for. So, there must be a way to figure out the actual UUID from overflow data.
Any pointers on this would be helpful.

No. The data in the overflow area is hashed (sending several 128-bit UUIDs would be much too large for an advertising packet). I don't believe the hash is documented, but I strongly suspect that it's based on a Bloom filter, so that Apple can probabilistically pack a unlimited number of UUIDs into the very limited space of an advertising packet.
The upside of all of this is that it means the data isn't there in the advertising packet (and really can't be). You will need to connect to the device to discover its services.

Related

How to send service UUID

We are developing an app which needs to scan for beacons in the background. This requires us for iOS to specify a service UUID while scanning. See Apple documentation:
Apps that have specified the bluetooth-central background mode are allowed to scan while in the background. That said, they must explicitly scan for one or more services by specifying them in the serviceUUIDs parameter. The CBCentralManagerOptionShowPowerAlertKey scan option is ignored while scanning in the background.
We are using a Raspberry Pi with a bluetooth adapter to send a beacon signal (conforming the AltBeacon spec). Unfortunately we are not able to find out how the service UUID should be set in the BLE Advertising PDU, is it part of the Bluetooth specification or part of the Manufacturer specific data structure? We did find examples for setting the service UUID for when you use an iOS device as beacon, but since we are using a generic bluetooth adapter we cannot use that.
Could anyone clarify us how and where the service UUID should be set in the beacon transmission?
is it part of the Bluetooth specification or part of the Manufacturer specific data structure?
the later.
generally when you setting the advertising parameters, you can set the UUID(or name, tx power, etc) to it.

scanForPeripheralsWithServices on iOS not finding devices by service UUID

I am using scanForPeripheralsWithServices to scan for devices by service UUID. When I use some of the standard service UUID values it will work sometimes.
When I try to use custom service UUIDs it often won't find any devices, but if I use nil for the service UUID list it will find those same devices that it doesn't find when I use their service UUID.
What is going on? Could it be because the advertising packet for the devices can only advertise some of its services?
The set of services advertised by a peripheral is typically smaller than the services it offers. This is because there is limited space in the advertisement so it makes sense to advertise only the "primary" service.
From the Apple Core Bluetooth Programming Guide -
There are also limits as to how much space you can use when advertising
data. When your app is in the foreground, it can use up to 28 bytes of
space in the initial advertisement data for any combination of the two
supported advertising data keys. If this space is used up, there are
an additional 10 bytes of space in the scan response that can be used
only for the local name. Any service UUIDs that do not fit in the
allotted space are added to a special “overflow” area; they can be
discovered only by an iOS device that is explicitly scanning for them.
While your app is in the background, the local name is not advertised
and all service UUIDs are place in the overflow area.
To help you stay within these space constraints, limit the service
UUIDs you advertise to those that identify your primary services.
As an example, a Heart rate device may offer the heart rate service, the device information service, the battery service and more, but it will only advertise the heart rate service as this is service that other devices will be "interested in" as it distinguishes this device from other classes of device.
Once the device has been identified and a connection established the other services can be discovered if required.

Identify iOS peripheral advertising in background

I work on iOS application with acts as Bluetooth peripheral. I need to implement a searching for my iOS peripheral from non iOS centrals. I’m faced with a problem while my iOS application advertising in background mode. When it is advertising in foreground, my central can read primary service UUID from advertising data, but when it is advertising in background, I can’t see the name or the UUID of peripheral – there is only Apple manufacturer data in advertising packet.
The essence of the problem lies in the fact that my non iOS central can’t determinate – is it advertising my peripheral in background or any other peripheral in background. I have to connect every iOS device with advertising in background, enumerate its services to look for my service UUID.
The documentation says that during background advertising all service UUIDs go to special “overflow” area and only iOS devices can read it specifying service in CBCentralManager’s scanForPeripherialWithServices method. It looks like Apple have an ability to check background advertising packet data for service UUID.
After searching on SO I found some interesting information about service hashed UUID. Background mode advertising packet always contains Apple manufacturer data (14 FF 4c 00 01) and undocumented 128 bit value, where one of these 128 bits equals 1. I tried to change my service UUID several times and found out than this 128 bit value after Apple manufacturer data changes too.
I’d like to use this value to filter peripherals around and reduce
connections to wrong (not mine) peripherals. Can anyone give any
information how this value depends on service UUID? Is there any
hash function that is used on specified service UUID in
scanForPeripherialWithServices method?
Can I be sure that the background advertising packet will always be the same for the immutable service UUID which will never change?
Is there any other way to send my custom information while
advertising in background mode? Maybe I can add my data into BLE
SCAN RESPONSE packet?
Best Regards,
Dezmond

Changing CBAdvertisementDataManufacturerDataKey from peripheral

Is there any way to modify CBAdvertisementDataManufacturerDataKey from CBPeripheralManager? I understand I can get the CBAdvertisementDataManufacturerDataKey from CBCentralManager.
The reason I want to do this is because I want the peripheral to advertise a 10-byte value without resorting to having the central connect to it, discover services, and then reading a characteristic which would contain the 10-byte value.
No, this is currently not possible as of iOS 7. The Manufacturer Data is reserved by Apple and is unmodifiable (at least on non-jailbroken devices). If you were writing the firmware for your own peripheral, this would not be a problem. But since the CoreBluetooth api is a layer above Apple's actual implementation of the iOS ble firmware, we face the limitations of what they actually expose. You may consider advertising you own custom service and displaying the same value you would have put in the manufacturer data, however.

Core Bluetooth: Transmit specific data in background as advertiser

I'm trying to use an iOS BLE device as BLE peripheral which also advertises in background.
I already figured out how to advertise in background and got it detected by another device looking for the specific bluetooth UUDID.
Unfortunately the advertiser-info is not transmitted when the app is in background. Is there a way to send a short string or something else device specific when the app is in background? It would be ok if the app would be woken up for a short period (if this is possible).
The advertised services are removed from the advertisement packages when the app is backgrounded. Only foreground scanning iOS devices will be able to obtain the services.
The advertised services are arbitrary UUIDs. You can easily figure out some encoding to store characters in them. However, this has several caveats, like
the general scheme is usually that the scanner finds your peripheral by the service UUIDS. If the data can be anything, then this is tricky.
the peripheral will not be able to change the advertisement data while backgrounded.
I suggest you not try to trick around with the system. Rather plan for connecting to the peripheral for a short time and sending the data to the central during this interval.

Resources