Taxonomy Icon

IoT

IBM Watson IoT Platform provides simple, but powerful, services capable of interconnecting different kinds of devices and applications all over the world. What makes this possible? The secret behind Watson IoT Platform is MQTT, the Message Queue Telemetry Transport, a lightweight and flexible network protocol. In this tutorial, you’ll see how MQTT works and how you can easily build applications using the IoT service.

In general terms, Watson IoT Platform acts as the MQTT broker, and is thus responsible for distributing messages to connected clients (devices and applications). Devices include machines that publish information they detect, and applications are the programs that consume the information received from those devices. Devices and applications communicate with the MQTT broker using the MQTT protocol, as shown in Figure 1.

Figure 1. IBM Cloud (formerly IBM Bluemix) services and MQTT clients
Bluemix IoT Service (MQTT broker) subscribes commands on the device side (MQTT client) and events on the application side (MQQT client).

An app using Watson IoT Platform usually consists of three parts:

  • Watson IoT Platform service configuration (device and application registration)
  • Device-side programming
  • Application-side programming

Ready to give it a try?

What you’ll need to build your application

1

Set up the Watson IoT Platform service

In this step, you’ll register devices and applications with Watson IoT Platform. Before connecting devices and utilizing data, first register for an IBM Cloud account and then create an instance of the Watson IoT Platform service in your IBM Cloud organization.

Create an app on the IBM Cloud dashboard

  1. Log in to IBM Cloud.
  2. From the top menu, click Catalog.
  3. To create a new service, under the Platform category click Internet of Things, and then click the Internet of Things Platform service tile.
    screen shot
  4. In the Service name field, specify a unique name of your service. For this tutorial, I’ve usedIoT-article-demo.
    screen shot
  5. Click Create.

Launch the IoT service console

You set up and configure your Watson IoT Platform service from the dashboard.

  1. On the IoT-article-demo service page, click Launch.
    screen shot Your board dashboard opens. It should look similar to this. screen shot
  2. Use the menu pane on the left to navigate the service.
    screen shot

Note: After you have created the service console, you can visit it directly from the Watson IoT Platform website. After logging in, you can see all the service consoles you created from the drop-down menu in the upper right of the window.

screen shot

Register the device

Each device that is connected to Watson IoT Platform must be associated with a device type. Device types are groups of devices that share common characteristics. When you add your first device to your Watson IoT Platform service, no device types are available in the Device type menu. You must first create a device type.

  1. Click Devices, and then click the Device Types tab.
    screen shot
  2. Click Add Device Type.
    screen shot
  3. For the device Name, use Java_Client.
    Note: You can use any value you want.
    screen shot
  4. Click Next, Done, and then Cancel.
  5. Click the Browse tab, and then click Add Device.
    screen shot
  6. For the Select Existing Device Type field, select the device type you created: Java_Client.
    screen shot
  7. In the Device ID field enter a unique ID, for example, 314159. You can input your own identifier.
  8. Click Next.
  9. Click the Security tab. Auto-generate the security credentials. Click Next, and then click Done.
    screen shot
  10. Write down the Authentication Token or copy and paste to a text editor for future use.
    screen shot

Repeat steps 5 to 10 to add all of your devices. You can see them on the Devices dashboard.

screen shot

After you register a device with Watson IoT Platform, you can use the registration information to connect the device and start receiving device data.

Register the application

To connect your application to Watson IoT Platform, you must connect by using API keys and tokens or binding your application directly to Watson IoT Platform in IBM Cloud. You use the access dashboard to grant access.

  1. In the Watson IoT Platform dashboard, from the left menu pane, click Apps, and then click Generate API Key.
    screen shot
  2. Copy and save the API Key and Authentication Token information to a text editor for future use.
    screen shot
  3. Click Generate.
    screen shot

Repeat these steps to register more applications, if you like.

2

Create a device-side program

Device-side programming consists of three parts:

  • Connecting to the IoT service (MQTT broker).
  • Publishing events to applications.
  • Subscribing commands from applications.

In this section, you’ll build a simple device-side program using the Java Client library in the ibm-watson-iot GitHub repo. For more information, see the source code.

Connect to the IoT service

The code here shows the main thread of the MQTT device-side program. It connects to one of the Watson IoT Platform devices we created in the dashboard. The connection parameters are passed in using the command line to execute the program. This allows us to run multiple instances of the device, each corresponding to a device registered in Watson IoT Platform. In the real world, however, the physical sensor device implements its own MQTT program using its own SDK.


public static void main(String[] args) throws Exception {
  Properties options = new Properties();
  options.put("org", args[0]);
  options.put("type", args[1]);
  options.put("id", args[2]);
  options.setProperty("auth‑method", "token");
  options.setProperty("auth‑token", args[3]);

  try {
    myClient = new DeviceClient(options);
  } catch (Exception e) {
    e.printStackTrace();
  }

  // More code to handle commands from apps 
  myClient.connect();

  // More code to send events to apps
}

The command line arguments for our sample device are as follows.

  • args[0] is the org parameter: 7z5mnk
  • args[1] is the device type: Java_Client
  • args[2] is the id of the device: 314159
  • args[3] is the access token (secret) for the device: jiw0cK1j84*e_dDjWd

Publish events

The main function of our device is to start a counter, and send the current count to Watson IoT Platform every 5 seconds as an event. Watson IoT Platform is responsible for broadcasting the event to all applications that listens for device events.


// More code to send events to apps
Runnable countRunnable = new Runnable() {
  public void run() {
    JsonObject event = new JsonObject();
    event.addProperty("count", count);
    myClient.publishEvent("status", event);
    count++;
  }
};
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(countRunnable, 0, 5, TimeUnit.SECONDS);

Subscribe commands

After connection to the device on Watson IoT Platform, our device is now ready to receive commands from an application registered in the same Watson IoT Platform service (that is, the IoT-article-demo service we created before).

You need to implement the Command Callback interface, and register the callback with the Device Client you created. In our callback implementation, we push the commands into a queue, and then use a separate thread to read and process commands from the queue. This design prevents blocking of the command handler thread, and allows all commands to be handled in the sequence they are received.

In the command handler thread, the device parses the command from the app. If the command is restart-counter, the device would restart its own counter.


public static void main(String[] args) throws Exception {
  // ... ...

  // More code to handle commands from apps
  AppCommandHandler handler = new AppCommandHandler();
  myClient.setCommandCallback(handler);
  myClient.connect();

  // Run the event processing thread
  Thread thread = new Thread(handler);
  thread.start();
}

class AppCommandHandler implements CommandCallback, Runnable {

  // A queue to hold and process the Events 
  // for smooth handling of MQTT messages
  // as some commands may take a long time to process
  private BlockingQueue<Command> cmdQueue = new LinkedBlockingQueue<Command>();

  @Override
  public void processCommand(Command c) {
    try {
      cmdQueue.put(c);
    } catch (InterruptedException e1) {
      e1.printStackTrace();
    }
  }

  @Override
  public void run() {
    while(true) {
      Command c = null;
      try {
        c = cmdQueue.take();

        JsonParser jsonParser = new JsonParser();
        JsonElement ele = jsonParser.parse(c.getPayload());

        if ("restart‑counter".equalsIgnoreCase(ele.getAsJsonObject().get("name").getAsString())) {
          SampleDevice.count = 0;
        }
      } catch (InterruptedException e1) {
        continue;
      }
    }
  }
}

Note: The device-side program is written in Java for illustration purposes. Your device needs a full JVM to run the program. You can always use your laptop as the device, but a full JVM-capable computer is not a realistic IoT device (like a NodeMCU board, which I used in my previous tutorial that used MQTT from Watson IoT Platform). To write a real-world device-side program that is embedded in a sensor device, you can use one of the appropriate ibm-watson-iot client libraries (for example, embedded C++).

3

Create an application-side program

As with device-side programming, application-side programming consists of three parts:

  • Connecting to the IoT service (MQTT broker).
  • Subscribing to events from devices or from the MQTT broker.
  • Publishing commands to devices.

In this section, you’ll build a simple application-side program using the ibm-watson-iot Java Client library. For more information, see the source code.

Connect to the IoT service

The code here shows the main thread of the MQTT application. It connects to the Watson IoT Platform app we created in the dashboard. The connection parameters are passed in using the command line to execute the application.


public static void main(String[] args) throws Exception {
  Properties options = new Properties();
  options.put("org", args[0]);
  options.put("id", args[1]);
  options.put("Authentication‑Method","apikey");
  options.put("API‑Key", args[2]);
  options.put("Authentication‑Token", args[3]);

  ApplicationClient myClient = new ApplicationClient(options);
  myClient.connect();

  // More code to handle events from devices
}

The command line arguments for our sample project are as follows.

  • args[0] is the org parameter: 7z5mnk
  • args[1] is the id parameter for the app: dw-sample-app
  • args[2] is the API key for the app: a-7z5mnk-3ail3qwogk
  • args[3] is the API token (secret) for the app: j-T56vZHOjFdTz3iXQ

Subscribe events

After connection to the app on Watson IoT Platform, our application is now ready to receive events from devices registered in the same Watson IoT Platform service (that is, the IoT-article-demo service we created before).

You need to implement the EventCallback interface, and register the callback with the ApplicationClient you created. In our callback implementation, we push the events into a queue, and then use a separate thread to read events from the queue. This design prevents blocking of the event handler thread, and allows all events to be handled in the sequence they are received.

In the event handler thread, the application parses the count value from the device event. If it is greater than 4, the application sends back a command to the device to restart the count.


public static void main(String[] args) throws Exception {
  // ... ...

  ApplicationClient myClient = new ApplicationClient(options);
  myClient.connect();

  DeviceEventHandler handler = new DeviceEventHandler();
  handler.setClient(myClient);

  myClient.setEventCallback(handler);
  myClient.subscribeToDeviceEvents();

  // Run the event processing thread
  Thread thread = new Thread(handler);
  thread.start();
}

class DeviceEventHandler implements EventCallback, Runnable {

  private ApplicationClient client;

  // A queue to hold and process the Events 
  // for smooth handling of MQTT messages
  // as some events may take a long time to process
  private BlockingQueue<Event> evtQueue = new LinkedBlockingQueue<Event>();

  public void processEvent(Event e) {
    try {
      evtQueue.put(e);
    } catch (InterruptedException e1) {
      e1.printStackTrace();
    }

  }

  @Override
  public void processCommand(Command cmd) {
    System.out.println("Command received:: " + cmd);
  }

  @Override
  public void run() {
    while(true) {
      Event e = null;
      try {
        e = evtQueue.take();

        // Check count value
        JsonParser jsonParser = new JsonParser();
        JsonElement ele = jsonParser.parse(e.getPayload());

        int count = ele.getAsJsonObject().get("count").getAsInt();

        if (count >= 4) {
          // Send "restart" command back to this device
          // ... ...
        }
      } catch (InterruptedException e1) {
        continue;
      }
    }
  }

  public ApplicationClient getClient() {
    return client;
  }
  public void setClient(ApplicationClient client) {
    this.client = client;
  }
}

Publish commands

To send the restart count command back the device, we use the publishCommand method, and pass in the device information, as well as a JSON message.


if (count >= 4) {
  // Send "restart" command back to this device
  JsonObject data = new JsonObject();
  data.addProperty("name", "restart‑counter");
  data.addProperty("time", new SimpleDateFormat("yyyy‑MM‑dd HH:mm:ss").format(new Date()));
  client.publishCommand(e.getDeviceType(), e.getDeviceId(), "restart", data);
}

4

Run the app

Both the device-side and application-side programs are built as Java applications. We set up the sample source code projects to be Maven projects, and configured Maven to build executable JAR files. This way, you can run the programs directly from the command line after building.

Build the project

To build the project, run the following command in both the device and application directories.


$ mvn clean package

The command creates application-1.0.jar and device-1.0.jar files in the target directory.

Run the application-side program

You can run the application-side program as follows.


$ java ‑jar target/application‑1.0.jar 7z5mnk dw‑sample‑app a‑7z5mnk‑3ail3qwogk j‑T56vZHOjFdTz3iXQ
Nov 05, 2017 2:26:34 AM com.ibm.iotf.client.AbstractClient createClient
INFO: main: Org ID    = 7z5mnk
         Client ID    = a:7z5mnk:dw‑sample‑app
Nov 05, 2017 2:26:35 AM com.ibm.iotf.client.AbstractClient connect
INFO: main: Initiating Token based authentication
Nov 05, 2017 2:26:35 AM com.ibm.iotf.client.AbstractClient connect
INFO: main: Connecting client a:7z5mnk:dw‑sample‑app to ssl://7z5mnk.messaging.internetofthings.ibmcloud.com:8883 (attempt #1)...
Nov 05, 2017 2:26:35 AM com.ibm.iotf.client.AbstractClient connect
INFO: main: Successfully connected to the IBM Watson IoT Platform

Now it is waiting for events from the devices.

Run the device-side program

After you start the device-side program, it starts to send count events to Watson IoT Platform every 5 seconds. And, you can see that it restarts the counter after the count hits 4, in response to the restart-counter command from the application-side program.

Again, note that the device-side program presented here is an illustration that runs on a full JVM device. To run the application on an embedded device, you need to use a different Watson IoT Platform client library for that device.


$ java ‑jar target/device‑1.0.jar 7z5mnk Java_Client  314159  jiw0cK1j84*e_dDjWd
Starting IoT device
Nov 05, 2017 2:26:46 AM com.ibm.iotf.client.AbstractClient createClient
INFO: main: Org ID    = 7z5mnk
         Client ID    = d:7z5mnk:Java_Client:314159
Nov 05, 2017 2:26:46 AM com.ibm.iotf.client.AbstractClient connect
INFO: main: Initiating Token based authentication
Nov 05, 2017 2:26:46 AM com.ibm.iotf.client.AbstractClient connect
INFO: main: Connecting client d:7z5mnk:Java_Client:314159 to ssl://7z5mnk.messaging.internetofthings.ibmcloud.com:8883 (attempt #1)...
Nov 05, 2017 2:26:47 AM com.ibm.iotf.client.AbstractClient connect
INFO: main: Successfully connected to the IBM Watson IoT Platform
Posted event {"count":0}
Posted event {"count":1}
Posted event {"count":2}
Posted event {"count":3}
Posted event {"count":4}
Command:: restart:{"name":"restart‑counter","time":"2017‑11‑05 02:27:07"}
Posted event {"count":0}
Posted event {"count":1}
Posted event {"count":2}
Posted event {"count":3}

After the device-side program starts, you can also see output from the application-side program console.


Event received:: Event [2017‑11‑05T02:26:47.438‑06:00] Java_Client:314159 ‑ status: {"count":0}
Event received:: Event [2017‑11‑05T02:26:52.374‑06:00] Java_Client:314159 ‑ status: {"count":1}
Event received:: Event [2017‑11‑05T02:26:57.377‑06:00] Java_Client:314159 ‑ status: {"count":2}
Event received:: Event [2017‑11‑05T02:27:02.374‑06:00] Java_Client:314159 ‑ status: {"count":3}
Event received:: Event [2017‑11‑05T02:27:07.377‑06:00] Java_Client:314159 ‑ status: {"count":4}
Event received:: Event [2017‑11‑05T02:27:12.376‑06:00] Java_Client:314159 ‑ status: {"count":0}
Event received:: Event [2017‑11‑05T02:27:17.372‑06:00] Java_Client:314159 ‑ status: {"count":1}
Event received:: Event [2017‑11‑05T02:27:22.371‑06:00] Java_Client:314159 ‑ status: {"count":2}
Event received:: Event [2017‑11‑05T02:27:27.375‑06:00] Java_Client:314159 ‑ status: {"count":3}

Check running applications

From the Watson IoT Platform console, you can also review the events log for individual devices. That makes debugging easy.

screen shot

Conclusion and next steps

By following these steps, you can build an app using the Watson IoT Platform service using the MQTT protocol. If you are familiar with MQTT client programming, you might find there are no significant differences, except that when using the Watson IoT Platform service you must make properties – such as the MQTT connection options, publishing and subscription subjects form, and so on – conform to the correct format.

It is easy to build solutions using the Watson IoT Platform service when they are based on an existing MQTT client library. The good news is that there are quite a number of open source MQTT client libraries for different platforms, such as C, C++, Java, JavaScript, Ruby, Go, and more. There are also several client libraries specific to Watson IoT Platform, as the Java library we used in this tutorial.

Watson IoT Platform services support a variety of connected smart devices, such as Arduino Uno, Raspberry Pi, and so on. There are several sample code projects in the documentation section of the web portal you can study. The previously discussed MQTT mechanism should help you understand and modify the source code. If your device is not covered in the sample code, don’t worry. Just as we implemented the device-side program in Java in this sample app, you can easily build your own program using an MQTT client library.

We implemented this application-side program in Java, but you might choose another programming language, such as Node.js or Ruby. To ease the application-side programming, you can use the browser-based flow editor Node-RED instead of coding it locally. Whether you are building it yourself or using Node-RED, the MQTT flow under the Watson IoT Platform service works the same way.

Acknowledgements

This article was originally written by Chun Bin Tang and published on February 18, 2015.