I and my team are working on a beacon that we need to talk to an app on the user's iPhone. Since we need the app to detect the beacon and execute code to talk to our API even when killed, we cannot use CoreBluetooth and need to operate as a beacon.
We're attempting to make a custom beacon on a BCM20737S BLE module. Is it possible to have this custom beacon talk to an app on an iPhone as a beacon? (CoreLocation framework)
Thanks!
As long as your packet is broadcasting a packet with the iBeacon protocol, then corelocation can detect it and your app will wake based on detection of this signal. An iBeacon protocol packet is a 25 byte payload set as the manufacturer data field in the BLE advertisement.
The company ID is 2 bytes (0x004C)
The type is 1 byte (0x02)
Data Length is 1 byte (0x015)
Proximity UUID is a 16 byte Hex String
Major is 2 bytes uint16_t
Minor is 2 bytes uint16_t
Measured Power is 1 byte int8_t
This stack thread might be of some use to you.
What is the iBeacon Bluetooth Profile
But essentially corelocation is only configured for ibeacons, if you want to transmit a different protocol packet youre going to need to use CoreBluetooth on iOS, then once you receive the packet, translate it somehow for use with your app.
The CoreLocation framework will only detect iBeacons, which means beacons that meet the iBeacon byte format. You can certainly build your own, and while it does not have to be an official Apple certified iBeacon, but it does have to match the byte pattern. This pattern is widely available on the internet, even if you do not sign up for Apple's certification program that earns you the right to see the spec.
Be careful, however, that you make no changes to rhe byte pattern. Some vendors have built beacon transmissions that tack extra bytes on to the end to send the battery level. While these transmissions are detected, they are detected much more slowly because the header has a different length field, which does not match the hardware filter used for rapid detection in the background.
If you want to customize your beacon format, you must use CoreBluetooth for detections. I have written some open source iOS beacon tools that help do this, using the open source AltBeacon and Eddystone-UID formats as examples. While detections in the background are slower as you say, you can make your beacon transmit both an iBeacon signal (to wake up your app quickly) and a custom beacon signal (to send whatever custom fields you want) to be detected as soon as it is awoken. This way you get fast detection even if you define your own custom beacon format.
Related
I work on iOS application which is using BLE for communication with our custom made BLE unit.
We want to send specific commands via BLE to the unit automatically.
When user is near unit and specific criteria are met, the app should connect to the unit, "login" the user, send command via BLE and disconnect right away.
These specific criteria are based on manufacturer data from advertisement (i.e. the unit is in "available to login" state when manufacturer data has last byte 0x01, when it's "NOT available to login", last byte is 0x00).
In foreground, this mechanism works flawlessly.
We want to do this even when app is in background or terminated (swipe up in dashboard on iPhone).
The mechanism we have implemented:
the unit has capability of acting as iBeacon
when unit is NOT available for login, the iBeacon is OFF
when it IS available for login, the iBeacon will turn ON and wakes up application, upon that the BLE scan will start in background mode
background mode setting is bluetooth-central
Problem here is that no matter what I tried, the advertisement:
sometimes it's not discovered at all (looks like it's timing issue?)
when it's discovered, it does NOT contain manufacturer data
Did anyone come across something similar?
Any help is appreciated and have a nice day!
An app simply cannot read raw BLE manufacturer advertisement data when in the background on iOS -- the operating system prohibits it.
Two exceptions to this rule:
iBeacon, which itself is implemented as a specific type of manufacturer advertisement. An app can detect iBeacons in the background on iOS, although only four bytes of readable data (encoded in the major and minor fields) are fully usable. If you can modify your device to send information this way, it will do what you want. However you must use CoreLocation APIs to detect iBeacon, as CoreBluetooth does not allow reading manufacturer data from iBeacon advertisements. If you do use CoreLocation, you cannot use the detections to establish a Bluetooth connection with CoreBluetooth as the two APIs are sandboxed.
Overflow Area advertisements. Backgrounded iOS apps can read these special types of manufacturer advertisements when in the background but only if the screen is turned on. (It is often possible to force the screen on at specific times by sending a local notification.) See my blog post here for more info: http://www.davidgyoungtech.com/2020/05/07/hacking-the-overflow-area
An alternative to detecting manufacturer advertisements is to use BLE Service advertisements with attached data. For this to work, you'd need to define a 16 bit or 128 bit GATT Service UUID and send out an advert with attached data bytes. Eddystone beacon formats work this way, and allow detection in the background on iOS. This is probably the best approach if you can alter the BLE hardware.
I have played around with Airlocate and two iPhones. Also between a Linux /hcitool beacon transmitter and Airlocate ranging. I see that the set of proximity UUIDs to be tracked are hardcoded in the Airlocate source code.
Is it possible for an iOS app to get a more generic call back , when it is in the vicinity of any iBeacon (any proximity UUID) and let that app decide how to go about behaving the way it wants.
I understand that this should definitely be possible from the OS perspective, as I see a 9 byte iBeacon prefix in the start of the PDU, which is independent of the proximity UUID.
Another query - I view hardcoding the proximity UUID in the APP as some sort of pairing . How is general bluetooth pairing different from this.
My aim in asking these questions is to understand the feasibility of using beacons to beam (broadcast) data, so that all recipients in the vicinity can receive it. If I choose to go with a specific 16 byte proximity UUID, then I am left with only 5 bytes (Major/minor/power) to beam data. Otherwise I get 21 bytes
By "more generic call back", it seems like you are trying to listen to iBeacons that are not deployed by you. The answer to this is NO, you can't do that.
According to this post:http://beekn.net/2013/10/ibeacons-can-my-ios-app-find-beacons-that-arent-mine/ , in order to listen to an iBeacon, you must know its proximityUUID first.
Unfortunately Apple decides to limited your ability to do that. CoreBluetooth framework can detect iBeacon nearby but since it only returns the device UUID, not the proximityUUID, you cannot add callback to them.
And Android can read the proximityUUID of any iBeacon without any problem.
I'm looking to create a BLE Beacon which does not follow Apples iBeacon specification. The reason being that the "beacon" will be an arduino device which the app should also be able to communicate to to instruct it to do things. Is this supported on iOS? I've heard rumours of iOS 8 locking down on generic device advertising via Bluetooth.
Thanks in advance.
Yes, you can do this using the CoreBluetooth APIs, but there are a few restrictions depending on what type of Bluetooth LE advertisement you use.
1. Manufacturer Advertisement
You can read all the bytes of the manufacturer advertisement (up to 24 bytes) using CoreBluetooth, but only when an app is in the foreground. In the background, you will get no callbacks. This is often paired with a second iBeacon advertisement that wakes the app up in the background on iOS. For an example of this type of advertisement, see the AltBeacon specification.
2. GATT Service Advertisement
A GATT service advertisement detection will be sent to an app by CoreBluetooth even when the app is in the background, provided that the app is specifically looking for the GATT service UUID of the beacon. The disadvantage of this approach is that the data payload is generally limited to only 18 bytes after the 2-byte service UUID.
Other Details
In the case of both advertisement types, you can connect to the device using GATT, and read and write data. Note, however, that once you connect the device will generally stop advertising as a beacon.
Both of the above work as described with iOS 8. It's hard to predict the future, but it seems unlikely that Apple will lock down on the above two use cases as they are widely used for Bluetooth LE applications aside from Beacons.
You can see the basic steps to read these advertisements in this blog post. While the post is specifically about how Apple filters out iBeacon advertisements, if you make your own custom manufacturer advertisement, it will allow you to read the bytes as described in the post.
For the sake of completeness, both of the advertisement types above can be picked up by Android devices both in the foreground and the background.
Is it possible to send only 1 iBeacon packet? I have tried using CBPeripheralManager,but since there are only 2 method to start and stop advertising, so I can't control how many packet is being broadcast.
What I want to try to do is use an iBeacon packet as a command, instead of just a broadcasting some ID. So I could send 1 iBeacon packet, and if the receiver got the message, it can send back Acknowledgement with another iBeacon packet. The intention is to avoid the pairing of bluetooth to send very simple data. The information will be linked to UUID, major, and minor of the packet.
Or are there better ways to do this than using iBeacon.
Yes, you can use iBeacon technology to send information back and forth between two iOS devices without pairing. If you have two devices, Device A and Device B, you set both of them up to range for beacons with a common ProximityUUID, say, E2C56DB5-DFFB-48D2-B060-D0F5A71096E0. And then you can exchange information in the two byte major and minor fields.
What you can't do is control the transmitter enough to send only a single iBeacon advertisement. The transmitter in iOS sends out 10 advertisement packets per second, so the best you could do is start the transmitter then stop it on a timer about 100ms later. (You probably shouldn't do this, because there is no guarantee that a single iBeacon advertising packet will be received successfully by the other device -- it may be lost due to a CRC error in the radio noise. You are probably better off letting the packet continue to transmit until you can confirm from a response from the other device that it was received.)
You can see an example of starting and stopping a transmitter on a timer in my answer here.
Of course, there may be easier and more robust ways of accomplishing what you want with built-in Bluetooth data exchange mechanisms. But that doesn't change the fact that what you propose is certainly possible.
No you can't since iBeacon is uni-direction device
I am working on a project where I first wanted to advertise a device as an iBeacon and make it possible to connect to that device via Core Bluetooth at the same time. Besides the fact that this is not easily doable (a device cannot advertise as an iBeacon and CB device at the same time), I noticed that the iBeacon part seems unnecessary - discovering peripherals with Core Bluetooth seems to be basically the same as discovering iBeacons.
My first Question: Am I right in assuming this? Or does iBeacon provide anything that central/peripherals in CB do not? Especially in regard to background advertisement/searching?
The only issue I can see right now is that the CLBeacon gives me both an rssi and an accuracy (and from this, the approximated proximity is calculated). With Core Bluetooth, centralManager:didDiscoverPeripheral:advertisementData:RSSI: gives me only an RSSI. Is there any way to retrieve the accuracy here so I can calculate a proximity? This is important for me and I guess relying on RSSI only for the proximity will give me less accurate results?
My second Question: Can I get the accuracy that I get with iBeacon in Core Bluetooth or a similar measure to calculate the proximity?
You can calculate your own distance estimate with RSSI using an algorithm like the one I posted here:
https://stackoverflow.com/a/20434019/1461050
The trick is that you will need as many RSSI measurements as possible averaged over a time window of 20 seconds or so to reduce the noise on the estimate.
The main advantages of using CoreLocation APIs to detect standard iBeacons vs. using CoreBluetooth to detect custom beacons are:
A variety of cheap off-the shelf hardware is available for the iBeacon standard.
CoreLocation can scan for iBeacons in the background (likely using hardware assist on iPhone 5+) in a way that can automatically launch your app relatively quickly, even if the user did not manually launch it since boot. As of iOS 7.1, even if the user kills the app from the task switcher, CoreLocation can re-launch it into the background if an iBeacon is detected. I do not believe all this is possible with CoreBluetooth.
The iBeacon transmission allows you to easily read the UUID/major/minor identifier combination in iOS without pairing. This 20 bytes of data (with the major and minor fields able to be set to arbitrary values) is more than you can get from a 16 byte Bluetooth Service UUID.
You don't have to roll your own software for distance estimation.