This is a post by Simpleweb full-stack developer Adam Butler. You can follow Adam on Twitter @Labfoo.

I’ve been at Simpleweb for four years and sit barely 6ft away from the office pool table. I lost count of the amount of games I’ve played long ago. My only basis for guessing is the 14 months that I spent challenging my former colleague Christos to see who could get 100 wins first, in exchange for lunch. Sadly I was beaten and was left forking out a hefty sum for lunch…

These types of competition are common now at Simpleweb, alongside some of our more experimental pool tournaments such as pool snakes & ladders and most recently pool Frustration. Sometimes we try to hold a company wide tournament but, with so many of us, it’s always run stale before half of the games are played.

pool_frustration
Pool Frustration

A few weeks back I started to experiment with Beacons.

I thought about lots of different experiments we could run, such as controlling the central heating by looking at the who was in the room and setting the thermostat to the average temperature preferred by the people present.

A note on ethics: Theoretically, such a system could keep track of how much time people spent in the office, but that’s not something we’d want to encourage at Simpleweb.

This brings me nicely onto the pervasiveness of beacon technology. When we give our mobile applications permission to track us in the background, what are the consequences of doing so? And how can we be sure that we’re not being possibly monitored? Does my employer have stats on how often I visit the toilet?! This is where we felt we needed to draw the line.

Monitoring and Ranging

Beacons support two types of tracking: monitoring and ranging.

  • Monitoring can happen continuously in the background (given permission), but can only report on what region you’re in. For example, in the Simpleweb office, the whole office acts as one region.
  • Ranging technically can run in the background with some significant limitations, but usually runs in the foreground (when the application is open on the screen), and can provide detailed information about the beacons in range, such as their distance as well as Major and Minor values. These are values that can be used to distinguish one beacon from another.

Android and iOS unfortunately have very tight constraints on the permissions that you afford to an application. In iOS, for instance, you can register for Apple’s location framework, CoreLocation, which allows you to ask the user to give you access to location services in the foreground only or in the background too. For our application, we’ve chosen to do the former giving the users absolute peace of mind that they aren’t being passively tracked.

So… how does it all work then?

Beacons come in different shapes, sizes and even adhere to different specifications. The iBeacon standard created by Apple really kicked things off. The iBeacon essentially broadcasts a small payload every 100ms containing the UUID (Universally Unique Identifier), Major and Minor values of the beacon, and often other information such as temperature.

The most popular beacons on the market are made by Estimote. These small, battery powered, beacons can broadcast their signal up to 70 meters and can last a number of years depending on their configuration.

In 2015, Google released a competing standard called Eddystone which maintains compatibility with platforms that support iBeacon, such as iOS and Android, whilst extending the functionality and lifting some of the limitations that Apple applied (such as broadcasting frequency allowing for devices with longer battery life).

This standard has become well supported across beacon hardware with most devices are able to switch between protocols. As of today, iOS still does not support Eddystone. That’s not to say that Eddystone doesn’t work on iOS. The first of the three payloads that an Eddystone beacon broadcasts is indistinguishable from an iBeacon payload however this is then followed by two further broadcasts:

  • **URL** – A website address or could be used to identify a resource in an installed application.
  • **TLM** – Contains useful information for maintaining beacons such as it’s battery life and uptime.

The beacons themselves aren’t aware of any connection to a phone, nor are they connected to the internet. They simply sit there blindly telling their surroundings about their existence.

What makes them smart then? Well nothing really… it’s up to the device and your application to do anything useful with them.

Tracking movements in the office

To develop an application that keeps scores in pool tournaments, we needed to set up regions for the beacons. A beacon region is simply the collective name for all beacons with the same UUID. These beacons could be physically in the same room or spread across the globe. A major limitation that you’ll face on iOS, however, is that you can only monitor 20 of these regions, but that’s usually okay and I’ll explain why in a little while.

Once we set up monitoring for a region, we can track movements within that region. So every time we enter or exit the region, we can expect to see a callback fired to the 'didEnterRegion' and 'didExitRegion' methods respectively.

Let’s assume for a moment that we have three beacons: Alpha, Bravo and Charlie. Alpha and Bravo are both in the Simpleweb office and Charlie lives up out of range on the office roof.

Given that Alpha and Bravo overlap we’d only expect to receive a 'didEnterRegion' event when we enter the range of either of these two beacons. If we then proceed from Alpha to Bravo only leaving alpha *after* we have entered Bravo, no callback will be fired. It’s only once we leave the range of both of the beacons that we’ll be sent a 'didExitRegion' event. Charlie isn’t overlapping with any other beacon regions and does not exhibit this particular issue.

This leaves us with a problem. How do we know when a user enters Alpha and Bravo separately? The 'didEnterRegion' event doesn’t tell us anything about the beacon and we can’t at this point distinguish Alpha and Bravo from one another.

This is where ranging comes into force. When the 'didEnterRegion' event is fired, we can ask the system to start ranging by executing the 'startRangingBeaconsInRegion' method, providing the region supplied to us as an argument in the 'didEnterRegion callback. This will then start firing to the 'didRangeBeaconsInRegion' giving us a lot more information about the beacons in the region.

The callback provides us with a list of beacons each of which have a Major & Minor value. Using pre-programmed information about the region we can display relevant information. This is how a museum would display information about an exhibit when you are nearby.

Alternatively we can reach out to a web application and retrieve this information via an API giving us the ability to dynamically load our content instead of having to deploy a new version of the application.

Limitations of ranging

There are a few notable limitations to ranging. You can only range for beacons whilst the app is in the foreground or within the time constraints that iOS enforces whilst running in the background.

*However* if you’re working with less than 20 beacons, you can simply give each beacon its own region meaning that you are able to identify Alpha from Bravo without resorting to ranging. Complicated right? Let’s break this down into some facts:

  • You can only monitor for 20 regions in the background.
  • Ranging gives you visibility of the in-range beacons Major and Minor values which can be used to identify them.
  • Using monitoring you can only get events containing information on the region, not a beacon.
  • When ranging you can identify up to 4,294,836,225 different beacons by setting the Major and Minor values (that’s just for one region or your twenty region allowance).
  • Ranging comes with strict time background limitations.

The pool table leaderboard

With the beacons in the office, we monitored for a region, in this case the Simpleweb office, and started ranging to identify exact proximity to different areas. The 'didRangeBeaconsInRegion' event is being fired while the app is open and this returns a list of in-range beacons. With these beacons we can see our proximity for which the value is a string of –

'ProximityUnknown' – Out of range or unknown (i.e. perhaps you just turned Bluetooth off)
'ProximityFar' – Within range but more than about 30 meters away
'ProximityNear' – Within about 30 meters away
'ProximityImmediate' – Within about 40 centimetres away

Why are these only approximate? Well this is going to depend of the make, model and signal strength of your beacon.

We inspect each of the beacons and if we have a beacon with a proximity of 'ProximityImmediate' we know we’re tapping against it. With this in mind we set up two beacons:

– Pool table – Claim a win
– Pool Table – I lost 🙁

At this point, the beacon UUID, Major and Minor values get fired over to the server. We record this event as something we call a “Checkin” which allows us to look at the win / lose ratio of games of pool meaning we can have an ongoing limitless leaderboard ranking players not by their amount of games played but rather the percentage of the games that they have won over a lifetime or the last month.

This has been a great opportunity to experiment with location tracking through beacons and it’ll be really interesting to see future applications of them.

Related Stories