Using CoreBluetooth I am trying to detect a BLE peripheral which is transmitting the advertisement and scan response packets.
Packet sniffer is able to find the advertisement as well as scan response data but iPhone only detects the scan response. So looks like iOS is rejecting the advertising data.
I am able to receive advertising data from other devices properly.
Any possible debug starting points ?
Note: The periferal device spec indicates that it does not set the 3 optional BLE packet bytes while transmitting the advertising data.
Advertising packets are used only to notify periodically any possible Central devices of the BLE device presence. The Advertising packet can contain information if the device can be connected to or not, and a few other data. Scan response should be the place where you should focus to pack important data.
On iOS you should rely on scan response to deliver the important identification data. On Android you have more flexibility, such as accessing both advertising packet and scan responses. Just to make sure you play along well with both platforms, keep the advertising simple so just the device is visible by any central, and store your data in scan response.
Related
When an iOS BLE peripheral enters the background state, the advertising packets are not emitted in the regular manner and they are placed in a special “overflow” area which is only detectable by another iOS device explicitly looking for this device.
The bluetooth-peripheral Background Execution Mode
That said, you should be aware that advertising while your app is in the background operates differently than when your app is in the foreground. In particular, when your app is advertising while in the background:
• The CBAdvertisementDataLocalNameKey advertisement key is ignored, and the local name of peripheral is not advertised.
• All service UUIDs contained in the value of the CBAdvertisementDataServiceUUIDsKey advertisement key are placed in a special “overflow” area; they can be discovered only by an iOS device that is explicitly scanning for them.
Is there any way an Android central (scanner) can detect any advertised custom UUID without having to connect to the iOS peripheral?
With "overflow" area I guess they mean Scan Response Data. To get that data, a device must perform an active scan, rather than a passive scan. In an active scan, the scanner sends a scan request packet immediately after it detects an advertisement packet. The advertising device will only broadcast the scan response data if it detected a scan request.
Android devices only perform active scans, so you should be fine.
EDIT: the answer above is not correct. See http://www.davidgyoungtech.com/2020/05/07/hacking-the-overflow-area for correct information.
I have a custom BLE peripheral that can send a notification data packet to a central. The device sends packets of 200 bytes at a time, and the central is expected to register for notification of characteristic updates on the device. Note this device was not designed for read operations and only supports streaming notifications to central.
In android 7 The central software just works with no problems and the phone (central) receives 200 bytes in a single notify event. - this works just fine.
I am porting the code for use on Apple devices using swift. I am using an iPad with iOS 9.3 and core blue tooth to test my software.
The iPad is programmed as a central, to receive notifications, but when the callback didUpdateValueForCharacteristic fires I only ever see the length of the data from the characteristic.value as being 155bytes. This means that 45 bytes are lost somewhere. BTW - The same code was also tested on a mac book air, and in that case the data received by the central was only 101bytes not 200 bytes either.
I dont see any mention in the corebluetooth API documents of a 155byte limitation anywhere. Am I supposed to call some extra function, or should I have set up the notifications a special way to do something to get the remainder of the bytes? If so does anyone know what?
I'd like to ask whether it is possible to access the raw advertisement data from a custom BLE device built using a Raspberry Pi from the Core Bluetooth API?
The use case is to broadcast constantly changed data from the Raspberry Pi to multiple iOS devices in the proximity and consume them in an iOS app. See the topology description in this article.
I already found out that the iBeacon advertisements are filtered out from the Core Bluetooth API and are only accessible from the Core Location API only, which requires the knowledge of the UUID. Due to the constantly changed data a custom iBeacon wouldn't work for this particular use case anyway. But I am unsure whether I could achieve that with Core Bluetooth?
You can do what you want if you change the Raspberry Pi to transmit a non-iBeacon format. CoreBluetooth only filters out the raw bytes of advertisements if they are iBeacon advertisements. See here: Obtaining Bluetooth LE scan response data with iOS
A simple solution is to change your iBeacon advertisement to an open-source AltBeacon advertisement. CoreLocation will no longer pick it up, but CoreBluetooth will.
Here's an example of what you get in the advertisementData NSDictionary in the CoreBluetooth centralManager:didDiscoverPeripheral:advertisementData:RSSI: callback. This example is the result of 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. Note that the above are the actual contents of the NSDictionary for a detected advertisement on iOS8 that were printed to the console using an NSLog statement.
Quick answer is "there is no direct way".
Why:
Because CoreBluetooth filters out advertisement data, except kCBAdvDataServiceUUIDs, kCBAdvDataLocalName, so there is now way to pass custom data from peripheral to central via advertising.
How can we workaround:
Peripheral
1) Holds some custom service (let's name it 'BeaconService').
2) BeaconService contains Beacon's UUID, major, minor characteristics.
3) Advertises BeaconService UUID (via kCBAdvDataServiceUUIDs key).
Central
1) Scans for peripherals that have BeaconService UUID.
2) Found peripherals are queued.
3) Connection is opened to queued peripherals, and the iBeacon information is read from BeaconService.
4) Read values can be used to start CoreLocation beacon monitoring/ranging.
So by this way you can make bridge from CoreBluetooth to CoreLocation.
I would like to configure my Bluetooth Low Energy peripheral devices as iBeacons and send additional data without connecting. Scan response is the correct way to do this, but including my custom scan response is causing the iOS iBeacon callback not to trigger within my iOS app
This post clearly outlines how to format the advertising packet: http://e2e.ti.com/support/wireless_connectivity/f/538/p/293551/1023580.aspx#1023580
I know iBeacons made by Estimote do have scan responses, so it is possible, but I can't find any good documentation for iBeacons.
What are acceptable scan responses for iBeacons?
You can see an example of a scan request/response sequence here:
http://processors.wiki.ti.com/index.php/BLE_sniffer_guide
I doubt that making a custom scan response from your beacon is stopping detections. I think it is more likely that when you added the scan response you somehow altered your advertisement so that iOS no longer sees it.
Even if you get this working, I don't believe there is any way to make iOS be able to see the data from a scan response that came from an iBeacon. If you want this data for use by other platforms then this may be fine.
I was including the data type "manufacturer data" in the scan response. I had a different company code than the code given in Apples preamble for iBeacon advertising packets. Removing this data made iOS recognize my device as an iBeacon and receive the scan response packet
We need in our project to detect the proximity of an iPhone that is running a custom APP that is using Bluetooth LE.
The detector (Scanner, Central...) will be implemented using a BLE Integrated Circuit (from Texas or Nordic). I mean that the scanner is not another IOS device... running Core Bluetooth as a Central..
For the detector to guess the proximity, the idea is very simple, just advertise a service with an UUID proprietary.
While in foreground all works OK, and the UUID and a Local name are advertised (The UUID in the main advertise packet, and the Local Name in the SCAN Response packet....), and our scanner is able to decide if this iOS device is running our App.
The problem arises when going to background .....
The iOS stops broadcasting UUID and Local Name. (As the documentation of Core Bluetooth Explains... I Know...)
At this moment (Background), IOS begin to broadcast a SPECIAL MANUFACTURER DATA in the main advertise packet, and nothing in the SCAN Response packet)
The data packet we see using a Bluetooth Sniffer is :
0x14 (length of packet not including this byte).
0xFF (Manufacturer specific data AD Type).
And then :
0x4C, 0x00 (this data is the manufacturer identifier, if the packet is compliant with BLE 4.0 specification).
0x01, 0x00,0x00, 0x00, 0x00,0x00,0x80, and ten 0x00 more....
I know Apple says that while in background ONLY ANOTHER IOS DEVICE SEARCHING FOR A SPECIFIC SERVICE CAN DISCOVER IT. (Really I do not know how they can achieve that, unless they connect to the peripheral and retrieve the services, or if the peripheral knows about other IOS device is scanning because of it´s Address in the SCAN REQUEST and then changes the advertisement data in background).
The main questions are :
Is there any documentation or knowledge of what this manufacturer data means....Perhaps it would be possible to the scanner to know based on this info that this is an iOS device advertising in background and then connect to look if the custom service is there. (Not a quick and clean solution...but I do not see any other workaround....)
Does anybody worked with this scenario...and found a clean solution .....
I have heard from people that forces the application not to go to background.
This limitation, will stop a lot of possible projects.