Sunday, October 22, 2017 12:00 am

MQTT: The Go-To Protocol for Distributed IoT and Tutorial

Written by 
Rate this item
(3 votes)

Imagine you have to deploy a dozen various devices throughout a factory floor. These consist of Linux PCs, low power embedded devices, a mobile phone app, simple sensors, and a remote database. Some devices are connected through Ethernet, while other more remote devices utilize a cell network to occasionally phone home. The problem you now have is, how do I get these devices communicating with each other in real time? MQTT is an ISO standard protocol used to solve this problem.

I. Intro

Message Queuing Telemetry Transport (MQTT) is a TCP/IP based protocol designed around the following:

  1. Asynchronous communication in near real-time between many different devices.
  2. Works on lossy and unreliable networks, such as a mobile connection
  3. Very low network overhead, functions over TCP/IP
  4. Follows a publish/subscribe paradigm, allowing a single unit to emit messages to many listeners
  5. Can encrypt data and send via TLS

These attributes make it ideal for (Machine to Machine) M2M and IoT applications. It’s especially useful where one is constrained by processing overhead, bandwidth limitations or intermittent network connections.

After a brief introduction to MQTT, this article will go over how to run an MQTT client application on your NetBurner device, and then we will create a simple application that will publish and listen for MQTT messages on a free cloud MQTT test server.

II. What is MQTT?

MQTT, at heart, consists of a publish/subscribe paradigm, so it is important to understand what this entails. A pub/sub model allows a single device to send data to all devices with a single packet. This is because the single device sends its data to a “broker”, which then distributes the data to all subscribers when they are available.

MQQT notional flow diagram

Fig. 1: Published data distributed to multiple subscribers via broker

To work within this model, a client should be able to execute five commands.

  1. Connect - Connect to a broker, utilize a keep alive if real time notification required
  2. Subscribe - Register yourself with the broker to listen for a message on a specific topic
  3. Publish - Post a message to a specific topic
  4. Unsubscribe - Remove your subscription to a specific topic
  5. Disconnect - Disconnect from a broker

III. What is Paho?

Instead of writing our own MQTT client, this example will utilize an open-source MQTT client library, called Paho. Paho consists of several MQTT clients written in a host of different languages to support the maximum number of devices. Language support includes Java, C/C++, GoLang, Python, and an Android Service. This article utilizes the embedded MQTT C/C++ library.

IV. How To: Building Paho on a NetBurner / Connecting to Eclipse Cloud and sending a test message.

Now that you understand what MQTT is, let's create a simple example that will publish to and subscribe to channels on a public MQTT testing server. Begin by downloading this example from the NetBurner repository. It includes the relevant source from the Eclipse Paho MQTT C/C++ library. Create a new project in NBEclipse, and import the source from the GitHub repository, using the method detailed in the getting started guide.

** important **

The Paho library was designed for a little-endian system. The NetBurner ColdFire modules are big-endian. To account for this, the Paho source must be built with the defined symbol "REVERSED". To do this, open the project properties by right clicking on the project and then selecting Properties. Under C/C++ Build->Settings, Select GNU C++ Compiler->Preprocessor and add "REVERSED" to the defined symbols list. Add it to the GNU C Compiler as well.

MQQT Paho library

The Paho library does not include some platform specific functionality that changes based on the Operating System. If you downloaded your code for this example from the NetBurner repository, it includes the platform specific functionality not provided by Paho. This includes opening and closing a network socket, handling timers, and generating logs.

Once the big-endian switch is made, you can load this example on to a NetBurner Ethernet device and it will begin sending its current uptime to the eclipse.org test MQTT server, located at www.iot.eclipse.org. It will also automatically subscribe to the same “topic” that it is sending the uptime to. So, you should see your post, and if any other devices are online and running this same example, you will see posts from them as well.

Let's go over a few lines of code and describe a little about how the Paho library works. This will focus on three of the five commands (connect, subscribe, publish) listed above. For a more in-depth API discussion, see the Paho Embedded C/C++ documentation, which can be found in the GitHub GitHub repository for the library.

1. Connect

NBMQTTSocket mqttSocket;

MQTT::Client client = MQTT::Client(mqttSocket);

MQTTPacket_connectData connectOptions = MQTTPacket_connectData_initializer;
connectOptions.MQTTVersion = 3;
connectOptions.keepAliveInterval = 60; // We must send a keep-alive within this interval
connectOptions.cleansession = 1;
connectOptions.clientID.cstring = name;

In the beginning, we must create the MQTT client object. Then, a few connection options are set. In particular, the client must have a unique name that is sent to the broker. In this example, the name is set to nb-(the last two bytes of the mac address). This would not be an ideal name in a large network, as you may find another device with the same ending mac address. But it is sufficient for this example's purposes. The keep alive interval is also set to 60 seconds. This tells the broker to disconnect us from the service if we have not sent anything in 60 seconds. In our example, we will be sending a keep-alive packet every 30 seconds.

2. Subscribe

client.subscribe("nbuptime", MQTT::QOS0, messageArrived);

void messageArrived(MQTT::MessageData& md)
{
    MQTT::Message &message = md.message;

    iprintf("Message %d arrived: qos %d, retained %d, dup %d, packetid %d\r\n\r\n",
        ++arrivedcount, message.qos, message.retained, message.dup, message.id);

    iprintf("Message %d arrived: qos %d, retained %d, dup %d, packetid %d\r\nPayload: %s\r\n",
    	++arrivedcount, message.qos, message.retained, message.dup, message.id,
        (char*)message.payload);
}

Subscribing is handled in a single function call. This subscribe call notifies the broker that we want to receive messages from topic "nbuptime". Then, we need to add a function handler for when a message comes in on this channel. This example will print out details of the incoming message.

3. Publish

MQTT::Message message;
char buf[100] = { 0 };
siprintf(buf, "Uptime: %lu", Secs);
siprintf(buf, "%s -> Uptime: %lu", name, Secs);
message.qos = MQTT::QOS0;
message.retained = false;
message.dup = false;
message.payload = (void*)buf;
message.payloadlen = strlen(buf)+1;

client.publish("nbuptime",message);
client.yield(100); // Issue keep-alive

Finally, the application will publish a message to the broker. After configuring the options for the message, a string containing the current uptime of the device is published. This will immediately send out the message, and any subscriber listening to the topic "nbuptime" will get the payload. Finally, we issue the keep-alive. A “publish” also can function as a keep-alive packet, so this location is rather redundant. It is included to demonstrate how to send a keep-alive.

Read 248 times Last modified on Thursday, October 26, 2017 7:30 am

Leave a comment

NetBurner Learn

The NetBurner Learn website is a place to learn faster ways to design, code, and build your NetBurner based product. Sign-up for our monthly newsletter!

Latest Articles