Ad

Our DNA is written in Swift
Jump

Can you Smell the iBeacon?

iBeacons are one of the hot new topics introduced with iOS 7, though I have not seen any actual real life use case for it.

Last week I received my Developer Preview Kit from Estimote and also I have begun to research iBeacons for inclusion in the book I am currently working on. Here are my findings.

There are two words that you should know to understand the difference between the two modes of operation:

  • Monitoring – this refers to a low-power region-monitoring, you get didEnterRegion: and didExitRegion: delegate messages
  • Ranging – this means a higher-power activity where you get the signal strength from individual iBeacons and can estimate distance to them from this

Even before iOS 7 Apple gave us the ability to monitor if a device would enter or exit certain geographic regions, the center stone being CLRegion. This spans a circle around a geolocation and when your device enters or exits this location you can have something happen. Better yet, if you specify in the info.plist that the app should receive background location updates then the system can launch your app on the crossing of the region boundary.

iOS 7 adds CLBeaconRegion which inherits from CLRegion. Here you are defined to be “inside” the region as long as any iBeacon is seen by iOS, however weak its signal might be. During testing this often drove me nuts because iOS claimed me being inside the region even though I had covered all my Estimote beacons in aluminum foil.

An iBeacon is identified by 3 values: proximityUUID, Major and Minor. The first being a UUID and the two latter being two 16 bin integers. You can construct a CLBeaconRegion in 3 levels: only UUID, UUID plus Major, UUID plus Major plus Minor. For example you might want to use one UUID for an entire company and then have Major be the individual stores. Minor could specify individual shelves inside each store.

Let’s Advertise

Normal BTLE peripherals are advertising multiple services, iBeacon is different. iBeacon uses the advertising information itself and has no need for an actual Bluetooth connection because all necessary information is already present in the iBeacon advertisement.

Here’s a bare bones example to start

@implementation ViewController
{
   CBPeripheralManager *_peripheralManager;
   BOOL _isAdvertising;
}
 
- (void)_startAdvertising
{
   NSUUID *estimoteUUID = [[NSUUID alloc] initWithUUIDString:@"B9407F30-F5F8-466E-AFF9-25556B57FE6D"];
 
   CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:estimoteUUID
                                                                    major:2
                                                                    minor:1
                                                               identifier:@"SimEstimote"];
   NSDictionary *beaconPeripheralData = [region peripheralDataWithMeasuredPower:nil];
 
   [_peripheralManager startAdvertising:beaconPeripheralData];
}
 
- (void)_updateEmitterForDesiredState
{
   if (_peripheralManager.state == CBPeripheralManagerStatePoweredOn)
   {
      // only issue commands when powered on
 
      if (_isAdvertising)
      {
         if (!_peripheralManager.isAdvertising)
         {
            [self _startAdvertising];
         }
      }
      else
      {
         if (_peripheralManager.isAdvertising)
         {
            [_peripheralManager stopAdvertising];
         }
      }
   }
}
 
#pragma mark - CBPeripheralManagerDelegate
 
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
   [self _updateEmitterForDesiredState];
}
 
#pragma mark - Actions
 
- (IBAction)advertisingSwitch:(UISwitch *)sender
{
   _isAdvertising = sender.isOn;
 
   [self _updateEmitterForDesiredState];
}
 
@end

This example would have a UISwitch which toggles the soft-beacon. There are some gotchas in there. First it takes a few milliseconds for the BT system to power on. You should only send the CBPeripheralManager if it is powered on. As soon as it does that you get a peripheralManagerDidUpdateState: delegate callback and if the power is on in there, then you can start to advertise the beacon.

Stopping the iBeacon is much simpler, it only takes a single command. If the CBPeripheralManager is powered off then also all advertisements are stopped. This happens if the app goes in to the background if you don’t tell iOS to keep the BT service running. If I remember correctly then all services are resumed as soon as the app comes back to foreground.

Estimote

It is of no consequence what kind of device you have for performing the function of being an iBeacon. You can make any iOS device (>= iPhone 4S) and any Mac (>= late 2011) sporting a BTLE chip into an iBeacon. Also there are a number of hardware companies which are offering dedicated hardware beacons.

Hardware beacons are ideal for conditions where you don’t want to glue an actual iOS device to the wall. Not everybody can put iPads all around the store for being kiosks. The typical price point of hardware iBeacons is at $99 for 3. This is also what I paid for my 3 Estimote beacons.

Estimote Developer Preview Kit

Estimote did a wonderful job in providing a pleasant unboxing experience. Besides of the 3 differently colored iBeacons you get a button, a sticker, a business card of Estimote’s CEO and Co-Founder Jakub Krzych, and some warning text – spiced up with hand written pieces – informing you that these beacons have still been hand-assembled and might contain firmware bugs.

The first thing you do when receiving the beacons is to download the Estimote demo app which lets you experiment with Monitoring and Ranging as explained above. It also allows you to connect to individual Estimote devices to see their battery level, firmware version and the configured values for UUID, Major and Minor.

At this point I was astonished to learn that Estimote uses a “burned in” UUID. The official statement that this is by design to prevent hackers from hijacking devices and spoofing some other location from these.

The UUID, plainly visible in the app, but also posted on several blogs is:

B9407F30-F5F8-466E-AFF9-25556B57FE6D

This is also the UUID I used in the above example, indeed this creates a simulated Estimote beacon.

Estimote beacons are fully enclosed in rubber and thus there is no physical hardware port, like for a USB plug. Instead all configuration has to happen over Bluetooth and the internal services that Estimote exposes. In a future version of the official Estimote SDK supposedly there will be an encrypted method to hide the UUID for people who still fear for the security of their beacons.

They also would you rather use their wrapper around Core Location and Core Bluetooth instead of using standard iOS methods. Personally I abhor using third-party SDKs for activities that the system provides just as well. The best workaround for potential issue with your neighbor using the same UUID is to use a random Major value to monitor in combination with the UUID. Then when the range is found you would do extra sanity checks – possibly against geo-location – if you are indeed inside your own store.

Monitoring for an iBeacon Range

Provided that you have an Estimote next to you, or created a soft-beacon as shown above, the counter part is to monitor this region. What follows is a minimally viable sample for updating a label and sending a local notification when you cross the region boundary, this goes in the app delegate.

@implementation AppDelegate
{
   CLLocationManager *_locationManager;
   BOOL _isInsideRegion; // flag to prevent duplicate sending of notification
}
 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)options
{
   // create a location manager
   _locationManager = [[CLLocationManager alloc] init];
 
   // set delegate, not the angle brackets
   _locationManager.delegate = self;
 
   NSUUID *estimoteUUID = [[NSUUID alloc] initWithUUIDString:@"B9407F30-F5F8-466E-AFF9-25556B57FE6D"];
   CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:estimoteUUID 
                                                               identifier:@"Estimote Range"];
 
   // launch app when display is turned on and inside region
   region.notifyEntryStateOnDisplay = YES;
 
   if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
   {
      [_locationManager startMonitoringForRegion:region];
 
      // get status update right away for UI
      [_locationManager requestStateForRegion:region];
   }
   else
   {
      NSLog(@"This device does not support monitoring beacon regions");
   }
 
    // Override point for customization after application launch.
    return YES;
}
 
- (void)_sendEnterLocalNotification
{
   if (!_isInsideRegion)
   {
      UILocalNotification *notice = [[UILocalNotification alloc] init];
 
      notice.alertBody = @"Inside Estimote beacon region!";
      notice.alertAction = @"Open";
 
      [[UIApplication sharedApplication] scheduleLocalNotification:notice];
   }
 
   _isInsideRegion = YES;
}
 
- (void)_sendExitLocalNotification
{
   if (_isInsideRegion)
   {
      UILocalNotification *notice = [[UILocalNotification alloc] init];
 
      notice.alertBody = @"Left Estimote beacon region!";
      notice.alertAction = @"Open";
 
      [[UIApplication sharedApplication] scheduleLocalNotification:notice];
   }
 
   _isInsideRegion = NO;
}
 
- (void)_updateUIForState:(CLRegionState)state
{
   ViewController *vc = (ViewController *)self.window.rootViewController;
 
   if (state == CLRegionStateInside)
   {
      vc.label.text = @"Inside";
   }
   else if (state == CLRegionStateOutside)
   {
      vc.label.text = @"Outside";
   }
   else
   {
      vc.label.text = @"Unknown";
   }
}
 
#pragma mark - CLLocationManagerDelegate
 
- (void)locationManager:(CLLocationManager *)manager
	  didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
   // always update UI
   [self _updateUIForState:state];
 
   if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
   {
      // don't send any notifications
      return;
   }
 
   if (state == CLRegionStateInside)
   {
      [self _sendEnterLocalNotification];
   }
   else
   {
      [self _sendExitLocalNotification];
   }
}
 
@end

Essentially you just create a CLBeaconRegion and instruct your instance of CLLocationManager to monitor for it. For some devices beacon monitoring might not be possible, e.g. if they lack a BT4 chip, so you should inquire about isMonitoringAvailableForClass:.

Note that the didDetermineState: is always called after a region boundary crossing as well as following requestStateForRegion:. So you can do all the monitoring in there and/or implement the didEnterRegion: and didExitRegion: just make sure that you don’t bother the user too much.

The rest of the code takes care of sending local push notifications if the app is running in background and preventing sending multiple messages with the same status in succession.

In my tests I would always get the didEnterRegion: message right away after turning on the soft beacon from the first example on my iPad. When I turned the beacon off I would get the didExit message with a delay of 43 seconds. So iOS does some internal filtering that prevents a rapid flip-flop.

In Background

You will find that the above code works nicely while the app is in the foreground but will remain sending/monitoring if it goes into the background, e.g. via pressing the home button.

For monitoring regions in the background you need the “Location updates” background mode enabled in the info.plist. To have the soft beacon persist you need the “Acts as Bluetooth LE accessory”. Xcode provides a nice UI for adding these keys to the info.plist file.

Enabling iBeacon background modes

Changes you make here end up in the UIBackgroundModes key of your info.plist.

Adding the accessory setting also asks the user for authorization of Bluetooth File Sharing. Be aware that the user might deny or turn off this authorization in the device’s privacy settings.

Macs which sport a BT4-compatible chipset are also able to emit a soft-beacon. As of OS X 10.9 CoreBluetooth is also available on the Mac. Late-2011 Macs generally have the chips it takes. The only thing missing is CLBeaconRegion, but if you construct the dictionary for advertising the iBeacon yourself you can work around this. Then the only other thing you need to know is that CoreBluetooth.framework is hidden inside the IOBluetooth.framework on Mac.

Matthew Robinson has created the BeaconOSX sample app that does exactly that.

Competition

At the time of this writing Apple has not yet published the official specification for iBeacon. When I asked the responsible Apple evangelist about this he told me that he’ll let me know when they publish something. So there is still hope that they will do, eventually. In the meantime some smart people still went ahead and reverse-engineered the spec.

Several hardware iBeacons are coming to market and Estimote soon will feel their competition. Other companies I found at a cursory search were:

  • RedBearLab sells a plug in board (aka “shield”) for Arduino 2.0 for $29, they have an iBeacon profile for it.
  • Kontakt.io has beacons running on normal – user-replaceable – batteries. They sell 3 for $99, 5 for $149, 10 for $279.
  • GeoHopper has USB-powered micro-plugs acting as iBeacons: The sell 1 for $39.99, 3 for $89.99, 5 for $192.99.
  • You can also use a Raspberry Pi and Bluetooth LE dongle to roll your own, cost would be around $40 for the device and $10 for the dongle

Of those company which are already shipping Estimote appears to have the best offering.

Having USB-power or user-replacable batteries is much less of a necessity if it turns out that with the lower power consumption of BTLE Estimotes are said to last for 2 years. The waterproof rubber casing and the built-in sticker lets you easily stick them anywhere without having to fear theft or damage.

But the competition does not sleep and as ever more companies are pushing into the hot new field of context and micro-location prices surely will be half or even less next year. We hope that Estimote keep competing on price and reduce it once they are able to churn out boatloads of factory-produced beacons.

The only two negatives I found that personally I think that an custom SDK should not be used as an USP to lock in the customer and that they don’t plan to offer the ability to customize the UUID, however securely. Maybe they will see the light there eventually as well. At this moment these items can easily be worked around and the rest of the “package” is great value.

Conclusion

There is little to prevent us from leveraging the iBeacon technology everywhere to make apps and services aware of the user’s context. If anything then maybe the simple fear that Apple might update their – still secret – iBeacon advertising packets to include other values. But all the hardware devices I mentioned can be updated to adjust the advertised values.

The only problem might be lack of imagination and an inherent slow speed of adoption rate in the sales and corporate markets. iBeacons promise to make it interesting again to enter brick-and-mortar stores. As such any company that still has these is well advised to quickly adopt iBeacons as a means to hook and reel their customers into the physical points of sale.

Small stores can enable an iBeacon running on the Mac or iPad they use for their POS system at no extra cost. This allows Passbook-based vouchers or customer-cards to automatically pop up when next to the cashier’s desk.

Do you know of any innovative uses for iBeacon that you have seen in real life? Or ideas you had during reading this article? Let us know in the comments.


Categories: Recipes

15 Comments »

  1. Fantastic post.

    I agree on the ‘lock’ – if beacon suppliers are merely providing a beacon then there’s no way you should build a solution on top of an SDK where you remain locked in. Companies come and go. If beacon providers build robust back-ends, then fine – you’re buying a solution not just a beacon.

    We’ve used GeLo and Kontakt – great beacons and are ‘heavier’ and more robust than Estimote – and waaaay easier to change the battery (Estimote you need to cut them open and then glue them back together)…although the theory is that in 2 years you’ll just throw the little turtles out.

    Right now, we’re big fans of Kontakt. Great signal strength and a nice RESTful API – although we’re back at the question of ‘lock’.

    Love the tutorial. Some things I’m curious about:

    – How do you handle rapid ‘toggling’ between beacons? We’ve been trying a timer so that you don’t repeat proximity zone changes every time a user sways back and forth
    – Have you resolved the “lag” you can get in localNotification? Using Estimote sample apps as an example, we’re seeing variations from 10 seconds to 2 minutes in how long a notification takes to trigger
    – And finally, and I know there’s no answer, but I’d love a way to figure out how to prompt a user to turn an app “on” that’s off….getting it at least into background.

    Closest idea we’ve come up with is using a standard push notice based on some kind of predictive model – “this is the time you usually get coffee, open our app for a coupon” – once the app is on, they later go to the store and hopefully have the app still in background!

    Thanks for your contribution to understanding iBeacon!

  2. Hi Oliver,

    thank you so much for the post and your opinions. Please let me comment on few concerns you mentioned.

    First of all, our motes are iBeacon-compatible. There is no final spec from Apple yet, but there will be for sure. And not only from Apple, but also other major vendors. If you think about it – most of the phones and other smart devices (Google Glass, Jawbone, FitBit, etc) would work better if they got context and micro-location.
    Estimote Beacons will provide the context trough a generic SDK, so you don’t have to implement it differently for all the platforms.

    Please also note that our beacons consist of other sensors like acceloremeter, temperature sensor and more to come. The more sensors the better context you can deliver to phone and other smart device, thus the better user experience. That’s why we had to wrap it into our SDK.

    And the last argument is privacy and security. As you know data broadcasted by beacons are public, so anyone can pickup the signal and implement into the app. Retailers and other venue owners don’t want third-party apps to trigger actions on consumer phones once they are in their stores. You also don’t want other people to fake your home beacons to trigger reminders or other actions you designed. That’s why there is a way to encrypt the communication and make it secure. In order to use one must implement our SDK because part of the solution is a sophisicated cloud service that introuces another layer of abstraction for UUIDs, location and context.

    And I agree with Doug and his comments above that hardware is not enough. We are pushing really hard about robust software component and will announce something really great soon : ) Will keep you posted!

  3. Jakub/others – I would love to understand something: I’ve heard it mentioned numerous times that Apple hasn’t released its spec. But what will the spec contain that isn’t in, say, their current Bluetooth accessory specification?

    https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf

    What is it exactly that everyone’s waiting for? A beacon doesn’t transmit a heck of a lot – so is it that they’ll specify power ranges or something? Have been mystified by this question for some time.

    And Jakub – have said this elsewhere – but the “cloud” you’re heading towards launching is key to getting the real “power” out of an Estimote. Can’t wait to see it! That’s where the real value will lie in “beacon producers” IMHO so we anxiously await!

  4. Very good post and I concur with a few of your concerns, including Doug’s. Having gone through too many “latest greatest” moments in the industry I know it will flush itself out over time. Just hope it doesn’t fragment from an implementation standpoint. Keep up the awesome work and to Doug, love beekn.

  5. Can you post the full sample app code? I tried the bit you posted but am missing something.
    Thanks

  6. Great writeup. One small correction: You transposed the digits in the cost of the “USB-powered micro-plugs” for the 5 pack. It is $129, not $192. The beacons themselves are called Bleu Stations and there is a direct link here: http://bleu.io. Geohopper is an iOS app that is beacon-enabled but not directly related to bleu stations. We have a free setup app in the app store that is called Bleu Setup that allows you to easily configure the beacons over Bluetooth.

    Our solution is focusing on providing flexible hardware and great integration code and tools to make mass deployment easy. We don’t provide a server based solution to manage the beacons, but rather use our tools and code to make zero touch deployment of beacons possible.

    Again, nice write up.

    timothy perfitt
    twocanoes software

  7. Is there any way to modify the distance or range at which the CLRegionStateInside or CLRegionStateOutside will fire on an iBeacon or Estimote beacon? Perhaps a broadcast power setting we could tap into?

    We’d like to simulate the experience of sending a user a local notification with the screen turned off and the app in background to greet a customer when they have actually entered the store.

  8. Thanks for the nice writeup.

    One correction though: the RedBearLab BLE shield cannot be used as an iBeacon. The Nordic nRF8001 chip it uses doesn’t have enough user-definable bytes in its advertisements. I’ve confirmed this with RedBearLab personally and also saw a forum posting from a Nordic employee confirming the same. The firmware you link to is for another device that RedBearLab sells that is iBeacon-specific.

    You might want to update the article so others don’t waste $30 on the shield in hopes of creating an iBeacon.

  9. It’s the RedBear Labs BLE Mini that can either a) with an attached Battery/power supply act as an iBeacon or b) attach to an Arduino so as to communicate with the Arduino via BT. http://redbearlab.com/blemini/