IMONT SDK and the TI SensorTag: a step-by-step guide

Romanas Sonkinas
IMONT Technologies
Published in
7 min readMay 30, 2017

We’re going to explore, step-by-step, how to integrate one of the most popular prototyping devices out there — the Texas Instruments CC2650 SensorTag with the IMONT SDK. We’re going to use the Bluetooth Low Energy (BLE) connectivity on the SensorTag to connect it to a Raspberry Pi 3, which will be running an instance of the SDK, and we’ll show you how to connect that to an Android phone running another instance — and how the two will exchange information directly without any intermediaries.

Pre-Requisites

This article assumes you have a working knowledge of Java and the development ecosystem around it — specifically, how to use Gradle/Maven to manage a project and it’s dependencies. Basic JavaScript is useful to work on the SensorTag device driver.

Step 1: Prepare your Pi

Install Java8 — either OpenJDK or OracleJDK will work:

$ sudo apt-get install oracle-java8-jdk

Now we need to get the latest version of Bluez — Linux’ Bluetooth library. The one bundled with Raspbian tends to be fairly out of date (5.23 at the time of writing) and does not support BLE very well, so we’ll want to get the latest and greatest — which (again, at the time of writing) is 5.45. Bluez can be downloaded from the official site here. Full instructions on setting up BlueZ can be found in this nice article from Adafruit, but in a nutshell:

$ wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.45.tar.xz
$ tar Jxf bluez-5.45.tar.xz && cd bluez-5.45/
$ sudo apt-get install -y libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
$ ./configure
$ make
$ sudo make install
$ sudo reboot

To simplify things and avoid the need for running the app as root, add the default pi user to the ‘bluetooth’ group, which can be done like this:

sudo usermod -a -G bluetooth pi

Then edit the D-Bus configuration file /etc/dbus-1/system.d/bluetooth.conf and add the following policy to allow the bluetooth group to access BlueZ:

<policy group="bluetooth">
<allow send_destination="org.bluez"/>
<allow send_interface="org.bluez.Agent1"/>
<allow send_interface="org.bluez.MediaEndpoint1"/>
<allow send_interface="org.bluez.MediaPlayer1"/>
<allow send_interface="org.bluez.ThermometerWatcher1"/>
<allow send_interface="org.bluez.AlertAgent1"/>
<allow send_interface="org.bluez.Profile1"/>
<allow send_interface="org.bluez.HeartRateWatcher1"/>
<allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
<allow send_interface="org.bluez.GattCharacteristic1"/>
<allow send_interface="org.bluez.GattDescriptor1"/>
<allow send_interface="org.freedesktop.DBus.ObjectManager"/>
<allow send_interface="org.freedesktop.DBus.Properties"/>
</policy>

Step 2: Get the SDK

Go to https://sdk.imont.io, register with your favourite identity provider and you’ll be able to access the SDK. The SDK is not an application in itself, but a set of libraries — it’s up to you to build the app that would start it. Don’t worry — we provide an example. Follow the instructions on the SDK site to set up Gradle (or Maven if you prefer).

Step 3: Get the example Command Line app

Available on GitHub: https://github.com/imont/sdk-example-cli-app. The app comes pre-configured for Bluetooth on the Pi and the SensorTag driver pre-loaded.

The basic dependencies that the app declares are on the SDK, the Bluetooth/BlueZ Network layer and logback for logging:

dependencies {
compile 'io.imont.lion:lion-client:0.7.1'
compile 'io.imont.bluetooth:bluetooth-bluez-integration:0.4'
compile 'ch.qos.logback:logback-classic:1.1.7'
}

Now just build the project with Gradle:

./gradlew clean build

And copy build/distributions/sdk-example-cli-app-0.1-SNAPSHOT.zip to your pi. After unzipping it, you should be able to run the app by typing.

./bin/sdk-example-cli-app

Provided there were no errors, you are ready to go to the next step.

Step 4: Pairing an Android app with the Raspberry Pi

Available on GitHub: https://github.com/imont/sdk-example-android-app

Now that the CLI app is running on the Pi, we are ready to start our phone app and pair the two SDK instances together. Open the app in Android Studio and install it to your phone (Note: using an emulator which is effectively behind a NAT, will prevent the two instances from seeing each other). After starting the example Android app, you will be greeted with a simple screen that shows two options: either creating a new network, or joining an existing one. Since we are starting from scratch, we’ll want to create a new one:

We’ll be greeted with a screen showing the instance of the SDK running on the Pi:

If we click on the discovered instance, the phone and the Pi will pair, and you should now see a new screen showing the two devices in your network (drag down to refresh if the Pi does not appear):

Step 5: Adding the SensorTag as a bridged device

Since the SensorTag is an embedded device and is thus unable to run an instance of the IMONT SDK, we’ll need to add it as a bridged device — and we want the Raspberry Pi to do the bridging. Fortunately we’ve already set everything up on the Pi, so all we need to do is click on the Pi in the app, and then select “Find Bridged Device”

The SDK on the Pi will now scan the surrounding Bluetooth spectrum and see what devices we’ve got available — you’ll most likely find quite a few here. Once the SensorTag is discovered, click “Acquire” and the Pi will connect to the device for you and pair (this might take up to 15s, you’ll be notified when it’s done).

Click “Finish” once that is done, and you will see the Sensor Tag as a bridged device in the main device list:

If you click on the SensorTag device now, you’ll be taken to a screen showing all of the available sensors and their current state, including things like temperature, atmospheric pressure and light intensity. By default, the driver re-reads all the values every two minutes, but you can configure that to be done at a higher interval in the driver itself.

Leave the device running for some time and observe how those values change.

Appendix: The actual JavaScript driver

The default driver for the SensorTag is bundled together with the example CLI application that you have used previously. It can be found in src/main/resources/drivers/ti-cc2650-sensortag.js. Let’s take a look at some of the basic features that are used in the driver, and how that can be adopted for other Bluetooth Low Energy devices.

First, any driver in the SDK must declare some metadata, telling the SDK what sort of device it is meant for. The metadata for the SensorTag is fairly simple:

function metadata() {
return {
"network": "BLE",
"manufacturer": "Texas Instruments",
"model": "CC2650 SensorTag",
"hardwareVersion": "PCB 1.2/1.3",
"primaryFeature": 'TEMPERATURE' // arbitrary
}
}

When a device is added to the SDK, the first thing that happens is the onLoad function is called. In our case, we set up callbacks to report the various sensor values every once in a while, depending on how often the value is likely to change — feel free to experiment on the exact timings. More frequent polling = higher battery usage and a larger database in the SDK.

function onLoad() {
reportIO(); // Report the status of the LED
context.scheduler.callback("readLux", 0, 120000);
context.scheduler.callback("readTemperature", 0, 300000);
context.scheduler.callback("readHumidity", 0, 300000);
context.scheduler.callback("readBarometer", 0, 300000);
context.scheduler.callback("readBattery", 0, 3600000 );
}

By default, none of the sensors are actually switched on, so we make sure they are whenever we do the polling.

When those readings are taken, they are written to the internal database within the SDK — called Mole — which handles replication of data between the various peer instances in our network (the Android app in this case). In the driver, this is done in the reportIfChanged function, which, as the name implies, only saves new readings if it differs from the previous one:

reportIfChanged = function(id, key, value, metadata) {
var currentValue = context.cache.get(key);
if (currentValue != value) {
framework.db.raiseEvent(id, key, value, metadata);
context.cache.put(key, value);
}
}

To do the actual reading from Bluetooth, we rely on the bluetooth network layer, and the various primitives that it provides. To anyone who has worked with Bluetooth Low Energy before, they should be the quite familiar concepts of readAttribute and writeAttribute, which are provided in the framework.ble namespace, i.e.:

var rawLux = framework.ble.readCharacteristic(
context.id,
luxometer_service_uuid,
luxometer_data_uuid
);

The SensorTag also has a buzzer and a couple of LEDs which we can control — that is done in onRequestEvent which is invoked automatically by the SDK whenever one of the peers raises a request event — read more about those in the SDK docs. In the simple implementation given in this driver, we just write a characteristic to the sensor tag whenever we receive such an event:

function onRequestEvent(evt) {
if (evt.key == 'ON_OFF>ON_OFF') {
if (evt.value == 1) {
var data = 7
} else if (evt.value == 0) {
var data = 0
} else {
return;
}
switchOnIOActuator();
framework.ble.writeCharacteristic(context.id, io_service_uuid, io_data_uuid, [ data ]);
framework.db.raiseEvent(context.id, 'ON_OFF>ON_OFF', "" + evt.value, null);
}
}

You can view this in action in the app, by clicking on the ON_OFF>ON_OFF attribute in the SensorTag device view.

Resources

IMONT SDK: https://sdk.imont.io
TI SensorTag: http://www.ti.com/ww/en/wireless_connectivity/sensortag/
Example Raspberry Pi app: https://github.com/imont/sdk-example-cli-app
Example Android app: https://github.com/imont/sdk-example-android-app

--

--