Beacons, CoreLocation, BLE, and "Geo-Fencing" - definition of terms? - ios

I was hoping someone could spell out the relationship between iBeacon recognition, CoreLocation and CoreBluetooth, specifically in the context of what iOS considers "geo-fencing".
First off, I understand Apple's documentation on Using Regions to Monitor Boundary Crossings and have seen other discussions around the topic, like iOS - CoreLocation and geofencing while app is closed (especially pertinent to our app since this is a background operation). However, I'm having a hard time finding Apple's explicit definition of geofencing and exactly which frameworks get categorized as such.
Consider:
Beacons are based on BLE and yet they use the CoreLocation framework and not the CoreBluetooth framework. In fact, you do not need to add Bluetooth capabilities to the project settings in order to get them to work.
Detecting beacon regions uses the same object and method calls: to register a region, you call the ‘startMonitoringForRegion’ method of ‘CLLocationManager’ object.
It appears that once we added beacon recognition to our app, users have begun seeing "geo-fencing enabled" messages in their settings.
I thought geo-fencing was purely used in GPS- and Wifi-based location services? Not BLE services? The whole point of BLE beacons is to reduce the drain on the battery that geo-fencing produces.
On a higher level, is there any way to prove demonstrably that using beacon technology produces a much lower battery drain than other location-based geo-fencing? Using "geo-fencing" as an umbrella term for both (if that is indeed what is happening), muddies the waters significantly when making a business case for beacons.

Related

Detect other iPhones nearby using Swift

I am trying to build an app that is able to detect another iPhone with the same app within a certain proximity. I don't want to use location. Is this possible?
Assuming you're looking for devices pretty close to each other, generally on the order of a single room, maybe a bit further if you're lucky (sometimes quite a lot less if you're not), what you're looking for is Bluetooth LE (Low Energy).
Choose a service UUID (type uuidgen from the commandline; it'll make you one)
Using CBPeripheralManager, advertise your service ID (see startAdvertising)
Using CBCentralManager, search for the same service ID (see scanForPeripherals)
Register yourself as a background Bluetooth app, both as bluetooth-central and bluetooth-periphral (see Core Bluetooth Background Execution Modes for details)
With this setup, your app will advertise your service, and your app will automatically be launched anytime the phone sees something advertising the service.
See the Core Bluetooth Programming Guide for details. Bluetooth development is a bit finicky and there are lots of little corner cases you often need to deal with, but the basics are pretty straightforward, especially for this kind of use case.
If you just want to find people who are actively (in the foreground) using your app and communicate with them, take a look at GameKit. It's built on top of Core Bluetooth, but does a ton of the work for you. It's especially designed for getting people together to play games, but it can do a lot more than that.
One note: Do not confuse Bluetooth with Bluetooth LE. They are radically different and basically unrelated protocols. Bluetooth is used for things likes streaming music, and you have basically no access to it at all in iOS. BLE is used for exchanging small bits of data with low-power peripherals like heart rate monitors and the like. Core Bluetooth only deals with BLE.
You could also use iBeacons for this (An abstraction on top of BLE). iBeacons are a little easier to use than BLE, and like Core Bluetooth you can set up beacon region monitoring so your app will get launched if a beacon (or group of beacons) you are listening for comes into range. (But beacon monitoring uses the location manager)

CoreBluetooth and iBeacon: any conflicts?

I have got a chip that has a iBeacon service as well as a standard BLE service.
I would like to use the iBeacon service to trigger the app that I am developing when entering a BLE signal range.
Once active I'd like the app to scan for peripherals using CoreBluetooth and then connect to the chip.
Is this against Apple terms and conditions?
Apple has no known restrictions on this setup. In fact, this is how the RadBeacon configuration app works.
Using this technique, detecting a beacon in the background will only give your app 5 seconds of background running time, which generally is not enough time to reliably complete Bluetooth pairing and data exchange. Your best bet would be to present a local notification to the user on beacon detection, and then if the user brings the app to the foreground, do the pairing.
An alternative would be to extend background running time using a technique like described in my blog post here. That post shows how to range for beacons in the background, but the same technique will work for bluetooth communication tasks.

How to reduce the time interval for didRangeBeacons method

I am working on a project involving iBeacons. I am observing that the didRangeBeacons method is called in 1 second interval. Is there any way to reduce this time interval? My project requires low latency proximity detection and I was wondering how this could be achieved.
No, you cannot reduce this interval on iOS because it is baked in to the CoreLocation APIs. You can do so on Android, or you could do something similar with lower-level CoreBluetooth APIs on iOS, but using CoreBluetooth is a bigger roll-your-own project than can be answered here.
While I am unsure of your use case, you should consider that reducing the interval might not help. Beacons only send out advertisements at a certain frequency (typically 1-10Hz). If you are using a beacon transmitting at 10Hz, you could potentially get a detection in 1/10 of a second. But if you need a distance estimate, this fluctuates greatly with each packet, so you really need to average the measurements over many samples anyway.
Also, consider that a CoreBluetooth-based solution would only be able to do faster ranging when the app is in the foreground. Background processes on iOS have a whole different set of delay challenges.
Finally, any CoreBluetooth solution could not work with standard iBeacons because iOS sandboxes the ability to read iBeacon identifiers with anything other than CoreLocation. So you would need to build a custom beacon.

Use Core Bluetooth instead of iBeacon - Any Downsides?

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.

How can I tell if CLLocationManager is actively scanning for a beacon?

When you set up an iOS device as a beacon (peripheral role), you can query its state by calling CBPeripheralManager.isAdvertising. I can't find the equivalent to query whether a device is scanning for a beacon (central role) on CLLocationManager. Any ideas?
Update:
Given David's answer, I encapsulated the code setting up the CLBeaconRegion with the specific UUID and added a boolean variable which is changed when calling startMonitoringRegion and stopMonitoringRegion on CLLocationManager.
I do not believe there is any way this is possible. Even though CoreLocation's iBeacon APIs use Bluetooth LE and CoreBluetooth under the hood, Apple appears to have gone to some lengths to hide this implementation. There is no obvious way to see whether a Bluetooth LE scan is going on at a specific point in time.
Generally speaking, a Bluetooth LE scan is always going on when an app is ranging for iBeacons in the foreground. When an app is monitoring for iBeacons (either in the foreground or background) or ranging in the background, indirect evidence suggests that scans for beacons take place every few minutes, with the exact number ranging from 1-15 depending on phone model and state. I know of no way to programmatically detect the exact times when this starts and stops, although it can be inferred by iBeacon monitoring entry/exit times. If you look at the graph below, the blue dots show the inferred scan times for one particular test case. Details of how I inferred this are described in this blog post.

Resources