This article is more than 1 year old
Build your OWN Apple iBeacon with a Raspberry Pi
DIY Bluetooth LE zone tracking
Building a beacon monitor app
If you’d just like to cut to the chase and start coding iBeacon support into apps, Radius is selling pre-configured Pis as iBeacon development kits with one or two on-board dongles. Prices start at $100 (£61).
With the Pi running as a beacon, the next stage is to create an app that will look for it and notify you when you’re there. I chose to work up an iOS app - I’m exploring Apple’s iBeacon, after all - but it should be possible to code it up in Android 4.3, which added Bluetooth LE support to the Google OS.
Apple added it to iOS 7, released back in September. iOS’s existing CoreLocation framwork defines a CLLocationManager
class that provides an interface for detecting iBeacons and a mechanism for dealing with events triggered by moving into and out a beacon’s zone of coverage, an extension of CLLocationManager
’s already available ability to work with geographical regions.
CLLocationManager
also defines methods for checking whether the device the app is running on has an OS and hardware able to handle Bluetooth LE: [CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]
returns a Boolean true if the device is beacon savvy.
Pass that test and a well-behaved app will then double-check that iOS’ Location Services have been enabled and that the app has permission to access them. It can then start looking for beacons with the Proximity UUID, Major and Minor values punched into the Pi earlier:
{ ... CLBeaconRegion *beaconRegion; NSUUID *beaconUUID; NSString *beaconIdent; ... beaconUUID = [[NSUUID alloc] initWithUUIDString:@"9277830A-B2EB-490F-A1DD-7FE38C492EDE"]; beaconIdent = @"Vulture.Zone.1"; beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:beaconUUID major:0 minor:0 identifier:beaconIdent]; ... [appLocationManager startMonitoringForRegion:beaconRegion]; ... }
CoreLocation provides two handy delegate methods for dealing with events triggered by the beacon monitor: - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
and - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
. The object that owns the CLLocationManager
must adhere to the CLLocationManagerDelegate
protocol if it’s to receive these messages.
These two methods provide an easy way to alert the user he or she has entered the zone and to trigger actions accordingly. My test app, for instance, grabs a block of HTML code from El Reg’s server and presents it in a UIWebView
: “Special Offer! The Editor will buy you a pint if you present this code...”, that kind of thing.
Running the app: We’re too far away (left) but then...
iOS scans for regions even when the app that initiated the monitoring isn’t running. The app is automatically run in the background if the beacon is detected in those circumstances. Likewise, it’s woken from sleep if it is merely napping. You can control whether messages triggered when beacon region boundaries are crossed are delayed while the iDevice’s screen is off: the CLBeaconRegion
object created above has a Boolean property, notifyEntryStateOnDisplay
, you can use to enable this behaviour. It also has a Boolean property called notifyOnEntry
, inherited from CLBeaconRegion
’s superclass CLRegion
, which you’ll need to set to NO in this case.
Once the phone knows it’s inside a beacon’s sphere of influence, the app can call the - (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
method to get a list of nearby beacons and from each entry, a beacon’s UUID, Major and Minor values to help identify which they are and, thanks to each beacon’s proximity
property, roughly how close it is.
To keep things tidy, I added an switch to disable beacon scanning. By way of inter-object notifications, it calls [appLocationManager stopMonitoringForRegion:beaconRegion]
to take the currently defined beacon off the system-wide monitoring list.
...and here’s a message from our (nearby) sponsor
Once all this is up and running, and the Pi-hosted iBeacon is operating in the background, it’s easy to test the system by walking out of range of the beacon and then turning round and coming back.
Android users keen to try this out without coding their own beacon detector can check out Radius Networks’ iBeacon Locate app in Google Play. There’s an iOS version in iTunes too. Radius also has an open-source library of iBeacon compatibility code for Android if you want to incorporate iBeacon support into an app of your own. ®