MQTT

  1. General Information
    1. What is MQTT?
    2. Communication Architecture
  2. API Overview
  3. Implementation
    1. Setup
    2. Setting up MQTT resources
    3. Setting up variable topic-signals
    4. Publishing on a Topic
    5. Subscribing to a Topic
    6. Settings
      1. Clean Session
      2. Keep Alive Interval
  4. Full Code Example

General Information

What is MQTT?

Note: The code snippets in this article are intended for Mita version 1a1ed7881e2220895ec60ce4f657972538c43195 and XDK-Workbench versions 3.4.0 and higher.

Initially developed by IBM to create a protocol for minimal battery loss and bandwidth, connecting oil pipelines via satellite connection, it is now an open standard. Gaining great acceptance in the IoT environment MQTT is persevering its initial goals like quality of service data delivery, continuous session awareness, simple implementation with a lightweight protocol stack especially useful on embedded devices with limited capacities.

As the following picture shows, the MQTT protocol is based on TCP/IP, and all clients and the broker need to have a TCP/IP Stack.

Image

Although MQTT is widely associated with the term Message Queuing Telemetry Transport it is not the correct meaning of the abbreviation: The name MQTT comes from an IBM product called MQseries and has nothing to do with traditional message queues. In general MQTT can be seen as a publish/subscribe messaging protocol based on TCP/IP using the client/server model.

Communication Architecture

The communication architecture is based on the client-server model where clients and servers are responsible for specific tasks. In general the roles are defined as the following:

  • Server: awaits incoming connection requests by clients and provides resources or services
  • Client: initiates the communication and requests the server’s content and functionalities

In MQTT there are two kinds of client types:

  • Subscriber client: is interested in a special set of data from other publishers and registers as a potential recipient of data whenever it is published to the server
  • Publisher client: provides data that can be interesting to subscribers by pushing data to the server whenever the data is changed or needs to be updated

The clients, either subscriber, publisher or both, do not communicate directly with and do not know about each other but rather exchange data with the help of a common central server in the communication architecture, called the broker. This principle is described as the clients being decoupled from each other. Decoupling happens on three stages:

  • Space decoupling: publisher and subscriber do not need to know each other (e.g. IP/port)
  • Time decoupling: publisher and subscriber do not need to run at the same time
  • Synchronization decoupling: operations on both sides are not halted during publishing / receiving

A MQTT client can be any device from a microcontroller up to a full-blown server with a MQTT library running and is connecting to an MQTT broker over any kind of network. MQTT libraries are available for a huge variety of programming languages (e.g. C, C++, C#, Go, iOS, Java, JavaScript, .NET).

Each client that wants to talk to other clients needs to be connected to the same broker. The broker needs to receive and filter all incoming messages, check which clients apply as interested, connected and available recipients and distribute the updated message according to the subscriptions. It is also an important task of the broker to provide the authentication and authorization of clients since the broker is exposed and accessible by many communication partners (e.g. via the internet). Whereas the MQTT client can be deployed on a great variety of devices with flexible performance and capabilities it is essential that the MQTT server can handle various client connections and data transmission between the publishers and subscribers.

As a premise for the communication architecture both clients, publisher and subscriber, initiate a connect message to the same broker which responds with an acknowledgement including a status code. Once the connection is established, the broker will keep it active as long as the client doesn’t perform a disconnect or the connection is lost.

API Overview

Mita provides the possibility to create MQTT resources. If the configuration and implementation provided by the Mita implementation are insufficient for a certain purpose, it is recommended to make adapting changes in the generated C code.

The MQTT implementation in Mita is based on the corresponding ServalStack C Library, which is included in the XDK SDK. It contains modules for a range of application layer protocols that are used on embedded systems.

This section will demonstrate the Mita MQTT API. In Mita, MQTT is defined as a many resource. That means, multiple instances of this resource can exist, and each is given a unique name by the developer. All possible configuration items and signals for the MQTT resource are listed below. The use of the configuration items and signals will be explained in subsequent chapters.

connectivity many MQTT {
    generator "org.eclipse.mita.platform.xdk110.connectivity.MqttGenerator"
    validator "org.eclipse.mita.platform.xdk110.connectivity.MqttValidator"

    /**
     * The underlying transport connectivity we use to send the data out. In the future we might also
     * support LoRa here.
     */
    required configuration-item transport : WLAN

    /**
     * The URL pointing to the MQTT broker, for example: mqtt://does-not.exist:8000
     */
    required configuration-item url : string

    /**
     * The client identifier (here: clientID) is a identifier of each MQTT client
     * connecting to a MQTT broker. It needs to be unique for the broker to
     * know the state of the client.
     */
    required configuration-item clientId : string

    /**
     * The clean session flag indicates to the broker whether the client wants
     * to establish a clean session or a persistent session where all
     * subscriptions and messages (QoS 1 & 2) are stored for the client.
     */
    configuration-item cleanSession : bool = false

    /**
     * The keep alive interval (in seconds) is the time the client commits to for
     * when sending regular pings to the broker. The broker responds to the
     * pings enabling both sides to determine if the other one is still alive and
     * reachable.
     */
    configuration-item keepAliveInterval : uint32 = 60

    /**
     * Publishes a message to a particular topic.
     */
    signal topic(name : string, qos : uint32 = 0) : string

}

Implementation

Setup

MQTT requires a network connection to the destination server, to which the MQTT requests are sent. With the XDK, this network is usually established using Wi-Fi. The following code can be used to create a WLAN resource for use with MQTT:

NOTE: Between version 3.4 and 3.5 the syntax spelling has been corrected from authentification to authentication

setup wifi : WLAN {
    authentication = Personal(psk='myPassword');
    ssid = 'mySSID';
}

For a Wi-Fi configuration that goes beyond a simple WPA connection, please visit the Wi-Fi guide.

Setting up MQTT resources

All MQTT resources are generally set up with the required configuration-items url, clientId and transport. The first configuration-item is a URL, pointing to the desired MQTT broker, such as mqtt://my-broker.com:1883. The configuration-item clientId will identify the XDK. The configuration-item transport is the Wi-Fi resource, through which the MQTT messages are sent.

The following code can be used to create an MQTT resource:

setup hivemq : MQTT {
    transport = wifi;
    url = 'mqtt://broker.hivemq.com:1883';
    clientId = 'myXdk';
    var temperature = topic('XDK110/myXdk/temperature');
}

Please note: The endpoint URL must be a fully qualified address, including the protocol (For MQTT, it should always be mqtt://) and the port, as shown above.

Setting up variable topic-signals

In the above example, temperature is a variable of type topic. This variable is a so-called signal, an MQTT instance can have multiple topic signals. For example, if it is desired to have one topic for temperature and one for light, the following code would initialize an MQTT resource with topics for light and temperature:

setup hivemq : MQTT {
    transport = wifi;
    url = 'mqtt://broker.hivemq.com:1883';
    clientId = 'myXdk';
    var light = topic('XDK110/myXdk/light');
    var temperature = topic('XDK110/myXdk/temperature');
}

Every read/write operation on one of the signals will only send or receive MQTT messages to the broker on the associated topics.

So far, the topic-signals have been initialized with default settings (apart from the endpoint). They have the following optional parameter (and default values):

  • qos, of type uint32. This defines the Quality of Service for all messages sent and received on the topic. Per default, this is 0 (representing At Most Once). Otherwise, it can be either 1 (At Least Once) or 2 (Exactly Once)2

The following code demonstrates how the optiomal parameter can be set:

setup hivemq : MQTT {
    transport = wifi;
    url = 'mqtt://broker.hivemq.com:1883';
    clientId = 'myXdk';
    var temperature = topic('XDK110/myXdk/temperature', 0);
}

Publishing on a Topic

Assuming that the following MQTT resource has been previously set up:

setup hivemq : MQTT {
    transport = wifi;
    url = 'mqtt://broker.hivemq.com:1883';
    clientId = 'myXdk';
    var helloWorld = topic('hello/world');
}

Then the following code will publish a message on the topic hello/world at the broker broker.hivemq.com every 5 seconds, with a JSON payload.

every 5 seconds {
  hivemq.helloWorld.write('{"hello": "world"}');
}

The input must always be a string.

Subscribing to a Topic

This functionality is not implemented currently.

Settings

Clean Session

Every MQTT resource can be further configured using the configuration-item cleanSession of type bool.

This defines whether the client (i.e. the XDK) wants to establish a clean session. That means, previous interaction between broker and XDK will be ignored.

The default value for this configuration-item is false.

Keep Alive Interval

Every MQTT resource can be further configured using the configuration-item keepAliveInterval of type uint32.

This defines how long the destination broker will keep the session between Broker and XDK alive. The keep alive timer is reset every time the XDK sends a Ping Message or Control Packets. If the keep alive period times out, the broker will stop the session.

The default value for this configuration-item is 60.

Full Code Example

package main;
import platforms.xdk110;

setup wifi : WLAN {
    authentication = Personal(psk='myPassword');
    ssid = 'mySSID';
}

setup hivemq : MQTT {
    transport = wifi;
    url = 'mqtt://broker.hivemq.com:1883';
    clientId = 'myXdk';
    var helloWorld = topic('hello/world');
}

every 5 seconds {
  hivemq.helloWorld.write('{"hello": "world"}');
}