Bluetooth Low Energy has got us all excited at Strobe, and over the last week I've been experimenting with iBeacons. Before reading this article, I would suggest watching Rich Kilmer's talk on Controlling the Real World with RubyMotion if you haven't already. It's a great explanation of Bluetooth Low Energy, and should give you a good idea of what is acheivable.
So what are iBeacons?
iBeacons are a standard thought up by Apple, that a built on top of Bluetooth 4 (Low Energy). They are to be used as purley location based devices that do no more that broadcast three pieces of information via Bluetooth. Those three things are: a UUID, a major value and a minor value. It is then up to you to write code in your app that: monitors for those beacons and reacts to those beacons in the event that your phone finds or loses the beacon. There are some common misconceptions about iBeacons, outlined in this article which I also suggest you read.
There are quite a few Kickstarted projects that are now selling iBeacon hardware. Typically bundled with a nice user friendly SDK, they are a great way to dive into working with iBeacons. Noteable ones include:
Unfortunatly they seem pretty hard to come by in the UK, without paying hefty postage and import duties from the US. Luckily we found some on eBay. They're not the best looking beacons on the market but they do the job!
You will need an iOS device with Bluetooth 4, so in our case I was using an iPhone 5. But at the time of writing, any of these devices should work:
- iPhone 4S, iPhone 5, iPhone 5C, iPhone 5S
- iPad (3rd generation and later)
- iPad Mini (1st generation and later)
- iPod Touch (5th generation)
Unfortunatly even if your very expensive, modern, fantastic Mac has Bluetooth 4 built in — you will not be able to use this in the simulator.
To do this, you will need to buy a Bluetooth 4 USB dongle. One caveat with this, it will need to have a different chipset to the Broadcom chip that is used in your Mac (I'm not sure why). I've not had a chance to try this yet, but I've ordered a Cirago BTA8000 on the advice of Rich Kilmer.
UPDATE: Turns out in Apple's infinite wisdom, they have chosen to remove support for Bluetooth in the iOS7 Simulator. So to test any Bluetooth interaction in iOS7 you will need to deploy to a provisioned device and test it there. [Source]
It is important also that you configure your iPhone to have the following settings:
- Settings > Bluetooth > Blutooth = ON (obviously!)
- Settings > Privacy > Location Services > Location Services = ON
- Settings > General > Background App Refresh > Background App Refresh = ON
As mentioned, some iBeacon development kits you can buy come with an SDK which can make this process a little easier. But by far my favourite is ProximityKit by Radius Networks. It works with any iBeacons, not just their own. This also allows you to use Geofencing in a similar way to iBeacons which is also pretty cool.
First you will need to sign up for an account (their developer account is free): http://proximitykit.com/plans.
Once your signed up / logged in, you will need to create your first kit. Each kit has a name and you can add Geofences and iBeacons for each kit. Once you have added your iBeacons UUID's, major and minor values - you will need to download the SDK and config file.
Click on the Download SDK button for your kit you have just created and you should see a link under "Option 2: manual download" to download the framework. Unzip that and put it in your app's
vendor folder (you might need to create that manually).
You will also need to download your config file for the kit (this can be found on the same page as the SDK download link). This will download a
ProximityKit.plist file, you will need to put that in your app's
To include the framework in your app, you will need to add the following to your Rakefile:
Motion::Project::App.setup do |app| ... app.frameworks += %w(CoreLocation) app.info_plist['UIBackgroundModes'] = ['fetch'] app.vendor_project('vendor/ProximityKit.framework', :static, :products => ['ProximityKit'], :headers_dir => 'Headers') ... end
Next in your AppDelegate you will need to add the following:
class AppDelegate attr_accessor :proximityKitManager def application(application, didFinishLaunchingWithOptions:launchOptions) @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) @window.rootViewController = UIViewController.new @window.makeKeyAndVisible self.proximityKitManager = PKManager.managerWithDelegate self self.proximityKitManager.start true end def application(application, performFetchWithCompletionHandler:completionHandler) self.proximityKitManager(syncWithCompletionHandler: completionHandler) end def proximityKit(manager, didEnter:region) NSLog "entered region %@", region end def proximityKit(manager, didExit:region) NSLog "exited region %@", region end def proximityKit(manager, didFailWithError: error) NSLog "failed with errored %@", error end def proximityKit(manager, didDetermineState: state, forRegion: region) NSLog "determined state %@, %@", state, region end def proximityKit(manager, didRangeBeacons: beacons, inRegion: region) NSLog "did range beacons %@, %@", beacons, region end def proximityKitDidSync(manager) NSLog "did sync" end end
And believe it or not that is it! If you run
rake device with your iPhone plugged in (presuming you've provisioned your device etc), you should see in the log something similar to:
Feb 7 13:02:10 Chriss-iPhone proximity-motion <Warning>: did sync Feb 7 13:02:28 Chriss-iPhone proximity-motion <Warning>: entered region <PKIBeacon: 0x146571b0> Feb 7 13:02:28 Chriss-iPhone proximity-motion <Warning>: determined state 1, <PKIBeacon: 0x146571b0>
I've put the code above on GitHub if you want to give it a try: https://github.com/chrishale/proximity-motion