How do Beacon Regions work?

Alright, so — a beacon region can be created using just a UUID. No more, no less. Now listen up, because here’s where things get complicated:

Beacons ship with three unique identifiers. A UUID, a Minor and a Major value.

If a region is initialised with just a UUID, the Minor and Major value will be wildcarded. That means that your app will hunt for all beacons with that UUID, regardless of their Minor or Major.

If a region is initialised with a UUID and a Minor value, the Major value will be wildcarded. Same applies if it’s initialised with a UUID and Major — the Minor value will be wildcarded.

As a real-life example, I bought four beacons. All of these beacons had the same UUID and Minor value, but the major value was different for each.

That means I needed to hunt for all beacons with the set UUID and Minor value, but the Major was wildcarded.

How can I start interacting with my beacon?

There are two ways iOS offers to interact with your beacons — through ranging and monitoring. These are both executed from a CLLocationManager instance (startRangingBeacons and startMonitoring respectively).

Ranging Beacons

Ranging is like pinging devices. It effectively surveys an area intermittently (in iOS’ case, every second), and comes back with an array of beacons that are within range.

You’ll receive a CLBeacon instance when you’re ranging. This has all the information you’d expect; UUID, Major, Minor and RSSI (signal strength).

instance when you’re ranging. This has all the information you’d expect; UUID, Major, Minor and RSSI (signal strength). You can do this with as many beacon regions as you wish!

Monitoring Regions

Monitoring is like registering a beacon to the device for later usage.

That means the device will persist regions you’ve told it to monitor after you’ve started monitoring!

Unlike ranging, you can only monitor 20 regions at a time per app.

Monitoring gives you the ability to detect when you enter or leave the range of a beacon (also known as transitioning).

Unlike ranging, instead of receiving CLBeacon instances in the delegate method, you’ll receive the CLBeaconRegion instead. This means you might need to do some additional digging to identify exactly which beacon has been discovered.

instances in the delegate method, you’ll receive the instead. This means you might need to do some additional digging to identify exactly which beacon has been discovered. However, and probably most excitingly of all, if you have your app closed and wake your device, your device will ping the monitored beacons to see if they’re within range. If they are, your app will open in the background for a few seconds to give you the opportunity to execute some code.

Executing code while the app’s closed/dropped out of memory/in background

A fairly common usage of beacons in iOS is to let the user know that they’re in range of a beacon without opening an app first. This is possible, but comes with its limitations.

First, we’ll need to ensure your CLLocationManager instance you use has the property allowsBackgroundLocationUpdates set to “true”.

Right. Now, we’re going to want to initialise a CLBeaconRegion you want to monitor, and set its notifyEntryStateOnDisplay property to true.

Finally, we’ll startMonitoring (not ranging!) this beacon region.

…And that’s it!

Wait; how did that work?

Remember how I said earlier how the device persists the monitored regions? Well, every single time you wake your iPhone/iPod/iPad (not even unlocking!) and Bluetooth is enabled, the device will do a quick pass to see if those monitored regions are within range.

If it finds one, it launches the app quickly in the background, and triggers the delegate method didDetermineState. Neat, right?

Keen to learn a bit more about how this works? We built a little app called Rumblr to test this behaviour out.

Psst: You can find a more exhaustive example over at the Rumblr iOS repo!

Now for the bad news; we can’t force our app to the foreground from this state.

Good news; we can get creative.

For example, we could let our user know that they’re in range of one of our beacons, and prompt them with a notification to open the app!

Gnarly.

Can I figure out how many meters away from this beacon I am?

Bleurgh. Hate to be the bearer of bad news, but there’s no hard-and-fast rule to seeing how many meters away you are. Like I said, beacon signals don’t travel through water or metal, and the distance is typically calculated through signal strength.

With that said, the best way to measure proximity is not from any proximity value — but by using the RSSI. Most beacon distributors will give an idea of what the strength should be at a meter away, depending on what your beacon is configured to. In my case, the manufacturer for the beacons I picked up, BlueCats have a pretty exhaustive list of the expected meter range at ranging signal strengths.

Again — we can get creative. The excellent humans at Wayfindr came up with the genius idea of sending the RSSI proximity trigger over the wire using models (which we ended up taking inspiration from for our own little Rumblr!).

Gotchas

Occasionally, a beacon will be ranged (picked up in the didRangeBeacons delegate method). However, the RSSI value is 0. From a few Stack Overflow searches, I’ve deduced that this is typically seen as an incomplete packet. As a result, I perform a check on didRangeBeacons to ensure the RSSI value is anything but 0.

delegate method). However, the RSSI value is 0. From a few Stack Overflow searches, I’ve deduced that this is typically seen as an incomplete packet. As a result, I perform a check on to ensure the RSSI value is anything but 0. Adequate authorisation will need to be given for background beacon-monitoring behaviour. To do this, you can use CLLocationManager’s requestAlwaysAuthorization method to prompt the user. Don’t forget to add the Privacy — Location Always Usage Description property in your Info.plist, too!

Closing thoughts

The next big challenge for Combo and beacon technology is understanding what the best way is to venture between different areas whilst the app is running in the background, as well as the foreground.

On notifyStateOnDisplay — I can totally understand why Apple have limited notifications to only display when the device is woken, rather than just accepting them intermittently in the background — a walk down the high street could end in an abundance of unwanted push notifications, for example. It’s still a touch frustrating — a simple delegate method that was set to ping every minute or so would be fairly discreet and harmless, and certain functionality could be limited to prevent abuse (see aforementioned notification overload).

I’m well excited for what comes next — looks like the people over at Estimote are already pushing the boat out with advanced triangulation, which looks killer.

Everything I’ve explored so far is all fairly simple stuff, but nonetheless, I’ve come away from this really exciting first dive into beacons and their capability.