MQ Telemetry Transport

improve this page | report issue

Overview

IBM MQ Telemetry Transport (MQTT) is a lightweight messaging protocol that is designed for Internet of Things (IoT) and mobule connectivity.

Jump to:

Getting started with MQ Telemetry Transport

MQ Telemetry Transport provides:

  • Reliable message delivery over unreliable connections
  • Secure message delivery to the enterprise
  • One-to-many message delivery (publish/subscribe)
  • New real-time push of data from server (no polling)
  • Minimal footprint on-the-wire (only 2-byte header)
  • Reduced battery usage

MQ Telemetry Transport enables real-time data push from server to mobile devices, which makes it ideal for dynamic mobile applications.

Examples:

  • Stock ticker
  • Chat application
  • Collaboration apps (Whiteboard)
  • Real-time emergency alerts
  • Live match score updates
missing_alt

MQTT client libraries are available in JavaTM, C, JavaScriptTM, C++, Python, Objective-C, and many other programming languages.

The Eclipse Paho project (http://www.eclipse.org/paho/) provides many open source MQTT clients (http://www.eclipse.org/paho/).

IBM provides MQTT clients in a Mobile Messaging & M2M Client Pack, available from the IBM Messaging community on developerWorks.

This tutorial uses the Eclipse Paho JavaScript MQTT client for publish/subscribe messaging in MobileFirst Platform® application.

The MQTT clients have a simple API for publish/subscribe messaging.

The following examples use the Eclipse Paho JavaScript MQTT client to Connect to an MQTT broker, Subscribe to an MQTT topic, Receive and process messages from the broker, and Publish a message on an MQTT topic.

Connect

1
2
3
4
5
6
function connect() {
   client = new Messaging.Client(hostname, port, clientId);
   client.onMessageArrived = onMsgCallback;
   client.onConnectionLost = onConnLostCallback;
   client.connect({ onSuccess: onSuccessCallback });
}

Publish

1
2
3
4
5
function publish(topic, data) {
   var msg = new Messaging.Message(data);
   msg.destinationName = topic;
   client.send(msg);
}

Subscribe

1
2
3
function subscribe(topic) {
   client.subscribe(topic);
}

Receive

1
2
3
4
5
function onMsgCallback(msg) {
   var topic = msg.destinationName;
   var data = msg.payloadString;
   console.log(topic, data);
}

Building a collaborative application (Whiteboard)

In this tutorial, you build a dynamic application (Whiteboard) with MobileFirst and MQ Telemetry Transport that lets users draw on a shared canvas in real time. Create this application in two steps:

  • Build the MobileFirst application
    • Implement the "single-user" mode (run the sample without any MQTT publishes).
    • The application captures touch/click events, and you can paint on the canvas.
  • Implement collaboration by using an MQTT client and server
    • Add a JavaScript MQTT client to the Whiteboard application that communicates with other clients through an MQTT server.
    • The MQTT server options are covered in a subsequent slide.
    • Note: MQTT data does not use the MobileFirst Platform security and authentication mechanism.

The Whiteboard application usesMQTT messaging to prived a shared canvas for all users.

Each Whiteboard publishes all the drawing actions as MQTT messages on a topic that is uniqte to the application session.

Each Whiteboard also subscribes to the set of all the drawing topics, and draws the actions of the others that are based on this data.

With MQTT publish/subscribe messaging capabilities, the real-time collaborative experience can scale to many connected applications.

This scenario cannot be efficiently implemented by using traditional polling (HTTP) or mobile push notifications.

  • To provide a real-time experience, drawing actions should be reflected on other canvasses within milliseconds.
  • HTTP polling is high bandwidth (each request requires a now client connection) and result in poor latency
  • Push notifications minimize bandwith, but are inappropriate for small in-application updates.
  • MQTT publish/subscribe messaging minimizes bandwidth and latency: an MQTT connections is established once from client to server, and messages are pushed directly to the application with low latency.

Whiteboard - Create Project

Create a WhiteboardProject project with a Hybrid Application named Whiteboard. Add the jQuery Mobile 1.3.1 library, obtained separately.

  • For more information, see the Working with UI frameworks tutorial

Add a header, a canvas, and a button to clear the canvas.

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE HTML>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Whiteboard</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0"> <link rel="shortcut icon" href="images/favicon.png">
        <link rel="apple-touch-icon" href="images/apple-touch-icon.png"> <link href="jqueryMobile/jquery.mobile-1.3.1.css" rel="stylesheet">
        <link rel="stylesheet" href="css/main.css">
        <script>window.$ = window.jQuery = WLJQ;</script>
        <script src="jqueryMobile/jquery.mobile-1.3.1.js"></script>
</head>
<body style="display: none;">
    <div data-role="page" id="page">
        <div data-role="header" id="header" data-position="fixed">
            <h3>MQTT Whiteboard</h3>
            <a onclick="app.clear()" class="ui-btn-left" data- role="button" data-icon="delete" data-theme="b">Clear</a>
        </div>
        <canvas id="whiteboard"></canvas> </div>
        <script src="js/initOptions.js"></script> <script src="js/main.js"></script> <script src="js/Whiteboard.js"></script> <script src="js/messages.js"></script>
  </body>
</html>
main.css
1
2
3
4
5
6
7
8
9
10
11
/* Reset CSS */
a, abbr, address, article, aside, ......... {
    margin: 0;
    padding: 0;
}
body {
    margin: 0 auto;
}
canvas {
    position: absolute;
}
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function wlCommonInit(){
    window.app = new WhiteboardApp();
    $("#whiteboard").on("vmousemove", function(event) {
        if (app.drawOn) {
            var x = event.pageX;
            var y = event.pageY - $("canvas").offset().top; app.draw(x, y, app.size, app.color);
        }
        event.preventDefault();
    });
    $("#whiteboard").on("vmousedown", function(event) {
        var x = event.pageX;
        var y = event.pageY - $("canvas").offset().top;
        app.draw(x, y, app.size, app.color);
        app.drawOn = true;
    });
    $("#whiteboard").on("vmouseup", function(event) {
        app.drawOn = false;
    });
    $("#whiteboard").bind("tap", function(event) {
        event.preventDefault();
    });
    $(window).resize(function() { resize(); });
    resize();
}
var resize = function() {
    var winSize = {
        width: window.innerWidth || document.body.clientWidth,
        height: window.innerHeight || document.body.clientHeight
    };
    // make canvas fill space under header
    $("canvas").css("top", $("#header").innerHeight() + "px"); $("canvas")[0].width = winSize.width;
    $("canvas")[0].height = winSize.height - $("#header").innerHeight();
}
Whiteboard.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var Colors = [
    "rgb(255,0,0)", "rgb(0,170,0)", "rgb(0,0,255)",
    "rgb(0,0,0)", "rgb(0,255,255)", "rgb(127,255,212)",
    "rgb(139,69,19)"];
function WhiteboardApp() {
    this.size = 8;
    this.color = Colors[Math.floor(Math.random() * Colors.length)]; this.drawOn = false;
    this.canvas = $("canvas")[0];
}
WhiteboardApp.prototype.draw = function(x, y, size, color) {
    var context = this.canvas.getContext("2d");
    for (var i = 1; i <= size; i+=2) {
        context.save();
        context.beginPath();
        var alpha = 1.0 - Math.pow(i/size, 2);
        context.globalAlpha = alpha;
        context.strokeStyle = color;
        context.arc(x, y, i, 0, 2*Math.PI);
        context.stroke();
        context.restore();
    }
}
WhiteboardApp.prototype.clear = function() {
    var context = this.canvas.getContext("2d");
    context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}

Whiteboard - Run the Application

Before you add collaboration through MQTT messaging, test the application by deploying it to your local MobileFirst Platform Server.

  • Select Run As > Run on MobileFirst Development Server
  • Right click the project and select "Open MobileFirst Console"
  • Click Applications -> WhiteBoard -> Preview (Common Resources)
  • Click/tap to draw on the canvas
missing_alt

Whiteboard - Adding Collaboration

You can now add collaborative features to the application with publish/subscribe MQTT messaging. Add an MQTT client to the Whiteboard application and connect to an MQTT broker when the application loads.

To create a shared canvas, each Whiteboard client publishes draw and clear actions on a topic that is unique to the client. The type of action and options are described in the MQTT message payload as JSON data.

Example: draw

  • Topic: whiteboard/<cleintId>
  • Payload: {"type" : "draw", "x" : "127", "y" : "53", "color": "rgb(255,0,0)"}

Example: clear

  • Topic: whiteboard/<cleintId>
  • Payload: {"type" : "clear" }

When another Whiteboard client receives this message, WhiteboardApp.draw or WhiteboardApp.clear() is called with the parameters from the JSON message.

Whiteboard - Add MQTT client

Add Eclipse Paho JavaScript MQTT client to the project:

  • WhiteboardProject/apps/Whiteboard/common/js/mqttws31.js

Load the .js file in index.html:

1
2
3
4
5
6
7
8
9
10
&<html>
    <head>
        ...
    </head>
<body style="display: none;">
    ...
    <script src="js/initOptions.js"></script>
    <script src="js/main.js"></script>
    <script src="js/mqttws31.js"></script>
    ...

On application load, invoke connect the client:

1
2
3
4
function wlCommonInit(){
    window.app = new WhiteboardApp();
    app.connect();
    ...
When you initialize and connect the MQTT client, specify the following configuration parameters and connection options. missing_alt

If you do not have an MQTT broker available, see Connecting to an MQTT broker later in this tutorial for details about how to find your own broker.

Whiteboard.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function WhiteboardApp() {
    ...
    this.host = "<My MQTT broker IP>";
    this.port = "<My MQTT broker port>";
    // generate a 6-character alpha-num unique ID
    this.uuid = Math.random().toString(36).slice(2).substring(0, 6);
    this.clientId = "whiteboard-"+this.uuid;
    this.client = new Messaging.Client(this.host, this.port, this.clientId);
}
WhiteboardApp.prototype.connect = function() {
    this.client.onMessageArrived = (function(self) {
        return function(msg) { self.onMsg(msg); }
    })(this);
    this.client.onConnectionLost = function() {
        alert("Connection lost!");
    };
    var connectOptions = new Object();
    // extend keep-alive to one hour
    connectOptions.keepAliveInterval = 3600;
    connectOptions.onSuccess = (function(self) {
    return function() {
        self.onConn;
    } }) (this);
    connectOptions.onFailure = function() {
        alert("Failed to connect!");
    };
    this.client.connect(connectOptions);
}

Whiteboard - Add callbacks

Next, implement the onMesg and onConn callbacks.

When the MQTT connection succeeds, subscribe to the wildcard topic of all Whiteboard applications: whiteboard/+

You must make the difference between the draw and clear actions that come from other Whiteboards from the ones that your Whiteboard initiates.

For the actions that you initiate, publish an MQTT message. If you receive the action from an MQTT message, do not republish this action as a new message.

Whiteboard.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
WhiteboardApp.prototype.onConn = function() {
    this.client.subscribe("whiteboard/+");
}
hiteboardApp.prototype.onMsg = function(msg) {
    var topic = msg.destinationName;
    var payload = msg.payloadString;
    // make sure the topic matches whiteboard/*
    if (topic.indexOf("whiteboard/") == 0) {
        var sourceUUID = topic.split("/")[1];
        // do not process own actions
        if (sourceUUID == this.uuid) { return; }
        var data = JSON.parse(payload);
        if (data.type == "draw") {
            this.draw( data.x, data.y, this.size, data.color, true);
        } else if (data.type == "clear") {
            this.clear(true);
        }
    }
}
WhiteboardApp.prototype.draw = function(x, y, size, color, fromOutside) {
    ...
    if (!fromOutside) {
        this.publishDraw(x, y, color); }
    }
    WhiteboardApp.prototype.clear = function(fromOutside) {
    ...
    if (!fromOutside) {
        this.publishClear();
    }
}
WhiteboardApp.prototype.publishDraw = function(x, y, color) {
    var topic = "whiteboard/" + this.uuid;
    var data = JSON.stringify({
        type: "draw",
        x: x,
        y: y,
        color: color,
    });
    var msg = new Messaging.Message(data);
    msg.destinationName = topic;
    msg.qos = 0;
    msg.retained = false;
    this.client.send(msg);
}

MQ Telemetry Transport provides three qualities of service to deliver messages between clients and servers:

QoS 0 = "at most once"
QoS 1 = "at least once"
QoS 2 = "exactly once"

A retained message is retained on the MQTT server and transmitted to new subscribers to the message topic.

1
2
3
4
5
6
7
8
9
WhiteboardApp.prototype.publishClear = function() {
    var topic = "whiteboard/" + this.uuid;
    var data = JSON.stringify({type: "clear"});
    var msg = new Messaging.Message(data);
    msg.destinationName = topic;
    msg.qos = 0;
    msg.retained = false;
    this.client.send(msg);
}

Run the sample

Deploy to the MobileFirst development server again, and open the application in two (or more) windows.

Draw in one Whiteboard, and MQTT messages are published to all the other subscribing Whiteboard applications.

missing_alt

Extending the collaboration scenario This collaboration scenario can be modified and extended to build other types of real-time applications:

missing_alt
missing_alt
missing_alt
  • Stock ticker: clients subscribe to trade data for an exchange (for example, MarketData/NYSE/IBM) and update in real time.
  • Real-time emergency alerts: clients subscribe to a topic for their own geographic location, and the emergency services publish alerts onto these same topics (for example, emergency/<X>/<Y>/alert).
  • Chat application: clients publish and subscribe on a topic for a particular chat room (for example, chat/room123/user1).

Connecting to an MQTT broker

An MQTT server is required to broker messages between MQTT clients. To support JavaScript MQTT clients (such as Eclipse Paho), the MQTT server must implement the WebSocket transport.

Several MQTT servers are available, both open source and commercial.

  • Development MQTT servers:
    • Mosquitto (open source, multi-platform)
    • IBM Message Sight for Developers (virtual appliance image)
  • Enterprise MQTT servers:
    • IBM MessageSight (appliance)

Mosquitto

Mosquitto is an open source, lightweight implementation of MQ Telemetry Transport V3.1, part of the Eclipse Paho messaging project.

The Mosquitto broker is available for many different platforms (Windows, OS X, Linux distributions).

For more information go to:

Download Mosquitto:

IBM MessageSight

IBM MessageSight for Developers is a virtual IBM MessageSight appliance image.

IBM MessageSight is a low-latency, reliable, and scalable messaging server with strong security and easy management.

The developer image can be run with virtualization software such as VMWare, Oracle VirtualBox, and KVM.

For more information go to:

Sample application

Click to download the Studio project.

Last modified on December 02, 2015