Quick guide to writing mobile iBeacon applications in JavaScript

Mikael KindborgBlogs, Tutorials

Tweet about this on TwitterShare on FacebookShare on LinkedInShare on Google+

New: Updated for Evothings Studio 2.0. It can take some effort to create an iBeacon app, especially if you want it to be available on both iOS and Android. This tutorial shows how to quickly create an iBeacon mobile application using Evothings Studio.

What are iBeacons?

iBeacons

iBeacons are like very small lighthouses sending out signals that can be detected by a mobile application. The app can sense if a particular beacon is near or far away. iBeacons are typically small battery powered devices. Applications include notifications based on position/range, for example security information, commercial offerings, ads, tourist information, museum applications, etc.

iBeacon is Apple’s beacon technology brand name and implementation. It is based on the Bluetooth Low Energy (BLE) wireless communication standard.

The BLE standard specifies an advertising mode, which is what iBeacons use. When a BLE device is in advertisement mode it repeatedly broadcasts packets over radio. The advertisement packet contains the name of the device and a scan record that can hold a limited amount of data. Apple uses the scan record to send out a UUID that uniquely identifies the beacon.

There are several companies that make iBeacons, like Estimote, Punch Through Design, Kontakt, and Roximity. Numerous additional offerings exist. The beekn website/blog presents an iBeacon guide.

iBeacon APIs for mobile platforms

iOS has an iBeacon API that you must use when scanning for beacons. Notably, the CoreBuetooth API cannot be used to detect beacons, as scan records that contain iBeacon headers are blocked by Apple.

Android and other platforms that support BLE can scan for iBeacons without any restrictions.

There are several iBeacon plugins for Cordova/PhoneGap, for example the plugin by Peter Metz.

While Apple place restrictions on how their own APIs can be used on iOS, other platforms can implement iBeacon libraries and applications without these restrictions. In addition, Apple does not manufacture iBeacon devices, they are a third party product. The openness of the BLE standard and the diversity of iBeacon hardware devices open up for lots or innovative beacon applications.

Example app – iBeacons that make you relax

relaxing-ibeacons-screen1relaxing-ibeacons-screen2relaxing-ibeacons-screen3relaxing-ibeacons-screen4

In a previous blogpost on “DIY” beacon technology we made an example app about ways to relax. Different relaxation techniques are shown depending on which beacon is closest to your mobile phone.

Here we will implement the same application, but this time we will use Apple’s iBeacon technology.

The app has four pages. When you are close to a beacon, an information page presenting a relaxation technique is shown. When no beacons are near, a default page is shown. This type of application could be used in a museum or library, at a university, or at some other public location where visitors can be given time to relax.

Implementation overview

Source code for the app is on GitHub.

The app is developed in HTML/JavaScript. For iBeacon functionality the cordova-ibeacon plugin is used (documentation is found by following the link). To deploy the app you can either use Evothings Viewer or build a native app that you publish on the app stores.

File index.html contains HTML data for the info pages of the application.

The JavaScript code that contains the iBeacon setup and logic is in file app.js.

Tracking iBeacons

To track iBeacons, you specify regions for the beacons for which you want to get notifications. Here is the code that defines the regions for the pages, the id is used to identify the page associated with a beacon:

// Regions that define which page to show for each beacon.
app.beaconRegions =
[
    {
        id: 'page-feet',
        uuid:'A4950001-C5B1-4B44-B512-1370F02D74DE',
        major: 1,
        minor: 1
    },
    {
        id: 'page-shoulders',
        uuid:'A4950001-C5B1-4B44-B512-1370F02D74DE',
        major: 1,
        minor: 2
    },
    {
        id: 'page-face',
        uuid:'A4950001-C5B1-4B44-B512-1370F02D74DE',
        major: 1,
        minor: 3
    }
]

Note that you need to know the UUID of the beacons you wish to track. Same UIID can be shared by multiple beacons, in which case you can use the major and minor integer numbers to uniquely identify a beacon. It is however not mandatory to specify the major/minor numbers when tracking for beacons.

Different iBeacon vendors have different method for how to find/specify the UUID and major/minor numbers. When testing the relaxation app, we used the LightBlue Bean, which is straightforward to configure over BLE.

Ranging vs. monitoring

Next we will look a the code for tracking beacons. Note that two types of tracking are used for iBeacons. Monitoring, which is enabled by startMonitoringForRegion, tracks the entering and exiting regions. Monitoring can be run both when the app is in the foreground and in the background, may have a low update rate, and does not contain proximity information. Ranging, enabled by startRangingBeaconsInRegion, works only in the foreground, has a fast update rate, and has proximity information (ProximityImmediate, ProximityNear, ProximityFar). For further details regarding iBeacons and background vs foreground modes, explore this report from Radius Networks.

iBeacon Plugin API

The main entry point in the iBeacon plugin is the object cordova.plugins.locationManager.

In the example code, we create a shorter global variable named locationManager to refer to this object. See this function, which is called when Cordova is initialized and ready. Here we also call the function that starts ranging beacons:

app.onDeviceReady = function()
{
    // Specify a shortcut for the location manager that
    // has the iBeacon functions.
    window.locationManager = cordova.plugins.locationManager

    // Start tracking beacons!
    app.startScanForBeacons()
}

Responding to iBeacon events

To listen for ranging and monitoring events, a delegate object with callback functions is used, as is shown in the following code snippet:

// The delegate object contains iBeacon callback functions.
var delegate = new cordova.plugins.locationManager.Delegate()

delegate.didDetermineStateForRegion = function(pluginResult)
{
    //console.log('didDetermineStateForRegion: ' + JSON.stringify(pluginResult))
}

delegate.didStartMonitoringForRegion = function(pluginResult)
{
    //console.log('didStartMonitoringForRegion:' + JSON.stringify(pluginResult))
}

delegate.didRangeBeaconsInRegion = function(pluginResult)
{
    //console.log('didRangeBeaconsInRegion: ' + JSON.stringify(pluginResult))
    app.didRangeBeaconsInRegion(pluginResult)
}

// Set the delegate object to use.
locationManager.setDelegate(delegate)

The pluginResult object contains information about ranged beacon(s). Examine the code in file app.js for further details. To enable logging, uncomment the console.log calls. Log output will be shown in the “Tools” window of Evothings Workbench.

As mentioned above, the example app uses ranging, but monitoring is also supplied for educational purposes.

Start ranging and monitoring

The example app uses ranging to determine proximity of the relaxation beacons. However, the code also enables monitoring of beacons for demonstrational purposes. The following piece of code iterates over the regions and enables monitoring and ranging for each region:

// Start monitoring and ranging our beacons.
for (var r in app.beaconRegions)
{
    var region = app.beaconRegions[r]

    var beaconRegion = new locationManager.BeaconRegion(
        region.id, region.uuid, region.major, region.minor)

    // Start monitoring.
    locationManager.startMonitoringForRegion(beaconRegion)
        .fail(console.error)
        .done()

    // Start ranging.
    locationManager.startRangingBeaconsInRegion(beaconRegion)
        .fail(console.error)
        .done()
}

Running the example app

To run the example app, do as follows:

  • Download the source code from GitHub
  • Start Evothings Workbench on a desktop machine
  • Launch the Evothings Viewer app on a mobile device and connect to the Workbench
  • Drag the index.html file of the example into the Workbench window – it is added to “My Apps”
  • Edit file app.js to contain the UUIDs and major/minor numbers of your iBeacons (alternatively configure your iBeacons with the values used in the example)
  • Click the RUN button on the app in the Workbench
  • When the app has loaded onto the mobile device, move it close to the beacons to see the different relaxation pages

Note that you can try out the example even if you have only one iBeacon. In this case, the page associated with the beacon will display when you are close to it. The default page will be shown when the beacon is out of range or turned off.

You can create your own iBeacon using a computer that supports BLE. For example, here is how to turn a Raspberry Pi into an iBeacon. For a specification of the iBeacon advertisement format, see for instance here and here.

To create a native app, follow the build instructions in the Evothings Studio documentation.

Do your own iBeacon app

Download Evothings Studio and start experimenting with building your own iBeacon apps. It is easy to get started!