MQTT – Publishing Messages

One of the main fields of application for the RevPi is in the (I)IOT area. MQTT is almost always mentioned in this context. MQTT is a protocol for exchanging data. Its popularity does not stem from the fact that it is very extensive, but because it is so incredibly simple.

A MQTT system basically consists of a MQTT broker (server) and clients. The server is basically not much more than a postman. Clients can send and receive messages. Each message is grouped into a so-called topic. A message of a client always consists of a message text and the topic under which the message should be published. Other clients can subscribe to Topics and receive all messages of the respective topics from the MQTT-Server without being asked. For example, a thermometer could regularly publish the current measured values under the topic temperature. Another client could display the current temperature and yet another could, for example, save the data.

The topics can be arranged hierarchically. This then works in the same way as a directory tree. If, for example, there are several thermometers, one in the house and one outside, the measured values could be published under temperature/outside, temperature/inside. If a client wants to receive all temperature data, it can subscribe to temperature/# and will receive all published messages in temperature and below.

MQTT offers even more functions. There has already been enough written about this on the internet. Therefore I will focus on the actual topic.

Two more notes, MQTT is case sensitive. The topics test and Test are different Topics. Also important to know that MQTT does not know any data types. All messages are strings. The application must take care of the conversion.

Preparation

First of all I need a MQTT server. One of the probably most common is Mosquitto. Practically it is included in the archives of many Linux distributions. So before I harass my work computer, my private computer has to be used. Of course I can run the MQTT-Server on the RevPi. Mosquitto also comes with Raspian/RaspberryPi OS. But that would only be half as interesting if I send the messages on the RevPi in a circle. A second RevPi serves the same purpose.

Install the Mosquitto-Broker and the Mosquitto-Clients:
sudo apt-get update
sudo apt-get install mosquitto
sudo apt-get install mosquitto clients

After the installation a small test on the server computer.
In one with

mosquitto_sub -t test

a client is started, start listening to the topic “test”.
In another terminal window

mosquitto_put -t test -m hello

a message is sent for the topic. If everything works now, the message should appear in the first terminal window.

Next I check if the connection between RevPi and my computer works correctly. For this the Mosquitto-Clients must be installed on the RevPi:

sudo apt-get update
sudo apt-get install mosquitto clients

Now a message is to be sent from the RevPi to the MQTT server on the PC. For this we need to know the destination IP address, in my case the 192.168.178.49.

mosquitto_pub -h 192.168.178.49 -t test -m helloagain

Publish Messages

Now I want to integrate MQTT into my application. There are several open source libraries for this. I chose paho, because I found simple examples for this right away. The necessary headers for C do not seem to come with the current distribution on the RevPi. Therefore I take the data from GIT. Before the make-run I have to install the developer files for SSL.

git clone https://github.com/eclipse/paho.mqtt.c.git
cd org.eclipse.paho.mqtt.c.git
sudo aptitude install libssl-dev
make
sudo make install

Now paho is ready for my purposes. Based on the example on the Eclipse page I wrote a small program:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <MQTTClient.h>

using namespace std;

const char *ADDRESS = "tcp://192.168.178.49";
const char *TOPIC = "test";

int main(int argc, char* argv[]) {
    const char *MESSAGE_STRING = "Hello, this is a message from the RevPi";

    MQTTClient mqttClient;
    MQTTClient_connectOptions connectionOptions =     MQTTClient_connectOptions_initializer;
    MQTTClient_message message = MQTTClient_message_initializer;
    MQTTClient_deliveryToken deliveryToken;

    MQTTClient_create(&mqttClient, ADDRESS, "RevPi", 
    MQTTCLIENT_PERSISTENCE_NONE, NULL);

    connectionOptions.keepAliveInterval = 20;
    connectionOptions.cleansession = 1;

    if (MQTTClient_connect(mqttClient, &connectionOptions) != MQTTCLIENT_SUCCESS) {
        printf("Failed to connect\n");
        return (-1);
    }

     // Copy the message string to avoid compiler warnings
    char *s = new char[strlen(MESSAGE_STRING)+1];
    strcpy(s,MESSAGE_STRING);

    message.payload = s;
    message.payloadlen = strlen(s);
    message.qos = 0;
    message.retained = 0;

    MQTTClient_publishMessage(mqttClient, TOPIC, &message, &deliveryToken);
    MQTTClient_disconnect(mqttClient, 5000);
    MQTTClient_destroy(&mqttClient);

    return (0);
}

The IP address in the constant ADDRESS must be adapted to the corresponding server.

The library paho-mqtt3c must be given to the linker. How this is done in Netbeans is shown in the previous articles.

Make sure that the MQTT server is online and a client is subscribed to the topic. The result should look like this:

Screenshot of a terminal session showing mosquitto_sub running, subscribed to to topic "test"
Terminal session with mosquitto_sub

The demo project

Leave a Reply

Your email address will not be published. Required fields are marked *