iBeacons with ProximityKit and Rubymotion

Chris Hale by Chris Hale, 07 Feb 2014

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.

iBeacon Hardware

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!

Phone Hardware

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:

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:

Software

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 resources folder.

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[177] <Warning>: did sync
Feb  7 13:02:28 Chriss-iPhone proximity-motion[177] <Warning>: entered region <PKIBeacon: 0x146571b0>
Feb  7 13:02:28 Chriss-iPhone proximity-motion[177] <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

comments powered by Disqus