Beacon Testing and Configuration Using BlackBerry 10

Cascades

minecraft pic

Image derived from: http://www.minecraftforum.net/topic/1034324-my-lighthouse-legit/

Introduction

A few weeks ago, John Murray (@jcmrim) published a blog post entitled “Where’s My Beacon?” This was the first of several we plan to share, relating to work we’ve been doing together on the subject of Bluetooth™ beacons. You can find that post here and if you’re new to beacons and haven’t read it yet, you should check it out before diving into this article. John did a great job of introducing the topic and explaining the key technicalities.

In this article, I want to continue where John left off and talk about the practicalities of developing beacon applications, share information about the tools I’ve been using to assist me, the issues I’ve encountered, and other important points.

Testing Beacon Applications

One of the key issues for beacon application developers is testing. Imagine your application is targeted to the customers of a retailer with hundreds of large stores up and down the country. Each store is to have a number of beacons deployed in it, and your application will need to respond to the proximity of each distinct beacon in a unique way. For example, it could notify the user of special offers relating to products in that department of that particular store. So ideally, you need to test your application with a wide range of relevant beacon UUID, major and minor attribute value combinations.

This raises the question: how exactly can you set the values of these attributes?

Setting Beacon Attribute Values

There does not appear to be a standard defining the way in which a beacon might expose configuration settings and allow them to be updated.

So you may ask, “how is it done with the Estimote beacons which John talked about in the first article of the series?”

Estimote beacons include a form of authentication to prevent unauthorized attempts to change attribute values, an important measure in the context of real world applications. They’ve not yet published details of how to work directly with this aspect of their product however, and the only way to use it right now is via their SDK. The SDK is not currently available for BlackBerry but, we are working with the Estimote team regarding the possibility of a BlackBerry version becoming available in the future.

Texas Instruments SensorTag

In support of my work, I’ve also been making extensive use of a great Bluetooth developer tool from Texas Instruments (TI): the SensorTag. There’s a lot that could be written about this flexible bit of kit, but first of all: SensorTag is not a beacon! In fact, it’s a small hardware device that has a whole range of sensors dotted about its surface, various IO pins and a Bluetooth Low Energy (BLE) “system on a chip”. The sensors include an infra-red temperature sensor, a barometric pressure sensor, a humidity sensor, an accelerometer, a magnetometer, a gyroscope and just for good measure an ambient temperature sensor. BLE GATT services make this data available to your application. One of the cool things about SensorTag is that in the most recent firmware update, it is now able to switch into “beacon mode”, where those other services are disabled and instead the device starts to emit advertising packets containing the beacon data that John previously explained, including a UUID, major and minor attribute through which to identify a specific beacon.

 sensor tagFigure 1 – My 2 SensorTags side by side and out of their plastic case

Furthermore, a new GATT service was added, the iBeacon service, and this exposes the beacon attributes as writable GATT characteristics[1].

I’ve made some changes to the WheresMyBeacon application that John introduced in the last article, and this includes a feature that lets me modify the beacon attributes that SensorTag includes in advertising packets and a couple of other attributes concerned with beacon operation.

Naming Beacons

Before I get to the good stuff, let me mention one change I implemented in WheresMyBeacon V2.0.0 that made life easier but, is not quite in line with this article’s main point. I made it possible to associate a human readable name with a beacon, keyed on its MAC address. This simple idea made it so much easier to know which beacon was which as they popped up on the UI of WheresMyBeacon. To use it, just select any beacon listed in the main screen showing iBeacon advertising and a new screen will open up, allowing you to name and indicate the type of beacon. Check the code and you’ll see I used the QSettings class to persist this data.

where's my beacon

Figure 2 – Naming your beacons in WheresMyBeacon V2.0.0

Managing SensorTag Beacon Attributes

As mentioned, the TI SensorTag can be in one of two modes; either it’s exposing a variety of GATT services or it’s in “beacon mode” and advertising with iBeacon packets. To toggle between the two modes, you hold down the side button on the SensorTag for a couple of seconds.

I pointed another of my TI tools, “BLE Device Monitor” at the SensorTag whilst it was in “non-beacon mode” and here are the GATT services that are evident:

where's my beacon 2

Figure 3 – SensorTag GATT services and characteristics

As you can see, there’s an “iBeacon Service” with UUID 0xF000BCC0-0451-4000-B000-000000000000. This service exposes six writable characteristics, four of which contain attributes whose value will appear in advertising packets when in “beacon mode”. These are the Beacon UUID, Beacon Major, Beacon Minor and Beacon Power attributes. The other two are the Beacon Interval, which control how often advertising packets are sent (and this can be important as it impacts battery life) and Beacon PIN, which according to the TI documentation is “not currently used” but, which I assume will be used for authentication purposes in the future.

Updating these values is easy and no different to the way you’d write to any GATT characteristics for which write access is permitted.

The device must first be paired via the BlackBerry 10 Bluetooth Settings page. After this has been done, your application will find it by scanning, and then connect to its iBeacon Service. Having done so you need to establish the handle values of those attributes you wish to update and use these values when updating them via an API call[2].

Let’s look at some code!

Code Review

Step 1 – Define some useful constants

// SensorTag service UUID
staticconstchar* SENSORTAG_IBEACON_SERVICE_UUID = "0xF000BCC0-0451-4000-B000-000000000000";
 
// Characteristic UUIDs
staticconstchar* SENSORTAG_BEACON_UUID_UUID = "0xF000BCC1-0451-4000-B000
000000000000";
staticconstchar* SENSORTAG_BEACON_MAJOR_UUID = "0xF000BCC2-0451-4000-B000-000000000000";
staticconstchar* SENSORTAG_BEACON_MINOR_UUID = "0xF000BCC3-0451-4000-B000-000000000000";
staticconstchar* SENSORTAG_BEACON_POWER_UUID = "0xF000BCC4-0451-4000-B000-000000000000";
staticconstchar* SENSORTAG_BEACON_INTERVAL_UUID = "0xF000BCC5-0451-4000-B000-000000000000";
staticconstchar* SENSORTAG_BEACON_PIN_UUID = "0xF000BCC6-0451-4000-B000-000000000000";

Constants defining UUIDs of the iBeacon Service and its characteristics

Step 2 – Scan for devices that have the SensorTag iBeacon Service

voidApplicationUI::startScanning()
{
    bt_remote_device_t **remoteDeviceArray;
    bt_remote_device_t *nextRemoteDevice = 0;
    if (!_bt_initialised) {
        initBluetooth();
    }
    // look for SensorTag devices
   remoteDeviceArray = bt_disc_retrieve_devices(BT_DISCOVERY_ALL, 0);
    if (remoteDeviceArray) {
        for (int i = 0; (nextRemoteDevice = remoteDeviceArray[i]); ++i) {
            char **servicesArray = bt_rdev_get_services_gatt(remoteDeviceArray[i]);
            if (servicesArray) {
                for (int i = 0; servicesArray[i]; i++) {
                    if (strcasecmp(servicesArray[i], SENSORTAG_IBEACON_SERVICE_UUID) == 0) {
                        QVariantMap map;
                        char buffer[128];
                        constint bufferSize = sizeof(buffer);
                        bt_rdev_get_friendly_name(nextRemoteDevice, buffer, bufferSize);
                        map["DEVICE_NAME"] = QString::fromLatin1(buffer);
                        bt_rdev_get_address(nextRemoteDevice, buffer);
                        map["MAC"] = QString::fromLatin1(buffer);
                        _config_model->insert(map);
                        break;
                    }
                }
                bt_rdev_free_services(servicesArray);
            }
        }
        bt_rdev_free_array(remoteDeviceArray);
    }
}

Scanning for SensorTag devices with the iBeacon Service (code simplified for blog)

Step 3 – Connect to the iBeacon GATT Service

    bt_gatt_init(&gatt_callbacks);

    bt_gatt_connect_service(_mac.toAscii().constData(), SENSORTAG_IBEACON_SERVICE_UUID, NULL, &conParm, this);

Connecting to the SensorTag iBeacon Service (code simplified for blog)

Step 4 – Receive call back indicating GATT service connection established

voidgatt_service_connected(constchar *bdaddr, constchar *service, int instance, int err, uint16_t connInt, uint16_t latency, uint16_t superTimeout, void *userData)
{
    // we’ve either connected so we can read attributes or so we can write to them
    if (!_connect_to_write) {
        _beacon_attributes_available = false;
        _beacon_attributes_available = readBeaconAttributes(instance);
    } else {
        writeBeaconAttributes(instance);
    }
}

Connected to the iBeacon Service either to read or write attributes (code simplified for blog)

Step 5 – Determine the handle values for the iBeacon Attributes

boolestablishHandles(int service_instance)
{
    int num_characteristics = bt_gatt_characteristics_count(service_instance);
    if (num_characteristics > -1) {
        bt_gatt_characteristic_t *characteristicList;
        characteristicList = (bt_gatt_characteristic_t*) malloc(num_characteristics * sizeof(bt_gatt_characteristic_t));
        number = bt_gatt_characteristics(service_instance, characteristicList, num_characteristics);
        int characteristicListSize = number;
        for (int i = 0; i < characteristicListSize; i++) {
            // Is this a Beacon UUID characteristic?
            if (strcmp(characteristicList[i].uuid, SENSORTAG_BEACON_UUID_UUID) == 0) {
                _beacon_uuid_handle = characteristicList[i].handle;
                _beacon_uuid_value_handle = characteristicList[i].value_handle;
                continue;
            }
            // other similar IF statements for the other beacon attribute UUIDs follow
            ......
        }
    }
    returntrue;
}

Determining the handles for the beacon attributes(code simplified for blog)

Step 6 – Update the iBeacon Attribute values

boolwriteBeaconAttributes(int service_instance)
{
    if (_beacon_uuid.compare(_new_beacon_uuid) != 0) {
        uint8_t *uuid_bytes;
        int uuid_len = _new_beacon_uuid.length() / 2;
        uuid_bytes = (uint8_t*) calloc(uuid_len, sizeof(uint8_t));
        hexToIntArray(_new_beacon_uuid,uuid_bytes);
        // update the attribute value here
        bt_gatt_write_value(service_instance, _beacon_uuid_value_handle, 0, uuid_bytes , uuid_len);             
        _beacon_uuid = _new_beacon_uuid;
    } else {
        qDebug() << "XXXX writeBeaconAttributes - UUID has not been changed";
    }
    // similar blocks for the other beacon attributes
    ....
    returntrue;
}

Using bt_gatt_write_value to update a beacon attribute (code simplified for blog)

Using WheresMyBeacon to Modify SensorTag Beacon Attributes

WheresMyBeacon 2.0.0 includes a new pull-down menu. Selecting the Configure action takes you to the “Configurable Beacons” screen. Selecting “Scan” will cause all previously paired SensorTag devices to be listed. Note that they need to be in “non-beacon mode” to be configurable. Select a beacon by touching the item in the list and you’ll be presented with a screen where you can modify and save beacon attribute values back to the selected SensorTag. Figure 4 shows this:

beacon testing 3

Figure 4 – Changing Beacon Attribute Values with WheresMyBeacon 2.0.0

Useful BLE Tools for Developers

During any development project, you’re bound to hit a problem or two and need to investigate. Aside from standard debugging techniques that might be used for any application, I often use additional BLE tools to help troubleshoot problems. These are useful for any BLE application, not just those relating to beacons.

I’ve already mentioned one of these tools, the TI BLE Device Monitor. This is a user-friendly tool, used in conjunction with a BLE dongle that plugs into my laptop and allows me to query and explore the GATT services and characteristics. Figure 3 shows a screen shot taken from this tool. Note that if you need more control (e.g. you want to send specific Attribute Protocol commands), TI have another tool called “btool” that I also use quite a lot.

Sometimes you really need to see what’s being transmitted and received “over the air”. This can be particularly true with beacons where being able to see the content of advertising packets can be a big help sometimes. To that end, I use the same TI dongle, loaded with alternative firmware which turns it into a “sniffer” plus a TI PC tool called Smart RF Packet Sniffer. Figure 5 shows three iBeacon advertising packets broadcast by one of my SensorTag devices. I’ve highlighted the four iBeacon fields which are (in order from left to right), the UUID, major, minor and “calibrated power” values.

beacon testing 4Figure 5 – TI Smart TF Packet Sniffer showing iBeacon advertising packets

Summary

We’ve released V2.0.0 of the WheresMyBeacon application containing the features described in this article and, so you can download, review and reuse the full source code, you can find the URL in the “Resources” section below. I hope this has been interesting and will help set you on your way developing beacon applications for Blackberry 10.

Watch out for more from myself and John Murray on this topic right here in the BlackBerry Developer Blog.

Please feel free to contact either myself (@mdwrim) or John (@jcmrim) via Twitter if you need any help on anything Bluetooth Low Energy related.

Resources

BlackBerry Bluetooth LE Developer Resource Index Page

WheresMyBeacon Application Project on GitHub

Contacts

Martin Woolley – @mdwrim

John Murray – @jcmrim

[1] If you’re unfamiliar with this term, take a look at our Bluetooth Low Energy Primer for BlackBerry Developers

[2] Think of a Characteristic as being a type which is identified by a UUID whereas an Attribute is a concrete instance of that type and it’s identified by a handle value

 

About mdwrim

My name’s Martin Woolley and I work in BlackBerry's Developer Relations team as a Senior Application Development Consultant. I’ve been with BlackBerry since 2009 but have worked in software development in various capacities for 30 years in a whole range of industry sectors and on numerous computing platforms small and large. These days I specialise in areas such as Bluetooth Low Energy, NFC, Internet of Things (Iot) and wearable technologies amongst other things.

Join the conversation

Show comments Hide comments
+ -
blog comments powered by Disqus