Implementing MQTT Client using C++ with libmosquitto

From Neuromeka Wiki
Jump to: navigation, search


Introduction

This is a simple example of the C++ library mosquittopp. It is a client that read data from a local shared memory and then publish all information to the message topic IGoT/sensors via MQTT.

Prerequisites

  • MQTT Broker host:
    • IP Address: 192.168.0.12.
    • Port: 1883.
  • MQTT Client:
    • libmosquitto C++ library
    • Platform: BeagleBone Black with Ubuntu (precise)

C++ Code Explanation

This example's source code is organized as an Eclipse project which includes main code and a wrapper class as below.

  • main.cpp
  • NRMKMqttWrapper.h and NRMKMqttWrapper.cpp


MQTT Wrapper

Fundamentally, the libmosquitto was developed in C programming language so that we should implement a wrapper class which covers all API in C and exposes C++ methods for easy to use. Fortunately, in the libmosquitto package, there is mosquittopp which is C++ base wrapper class for us to inherit and customize our wrapper as desired.

The below code snippet is the prototype of NRMKMqttWrapper class in this example. The wrapper class consists of a constructor to create and initialize libmosquitto library and other three methods to handle Mqtt communication.

#include <mosquittopp.h>

class NRMKMqttWrapper : public mosqpp::mosquittopp
{
public:
	NRMKMqttWrapper(const char *id, const char *host, int port);
	~NRMKMqttWrapper();

	void on_connect(int rc);
	void on_message(const struct mosquitto_message *message);
	void on_subcribe(int mid, int qos_count, const int *granted_qos);
};


  • First of all is the implementation of wrapper's constructor. Al shown below, it uses ID argument as its unique ID of MQTT Client. Then, it initializes libmosquitto and try to connect to the Broker via the host and port argument.
NRMKMqttWrapper::NRMKMqttWrapper(const char *id, const char *host, int port) : mosquittopp(id)
{
	mosqpp::lib_init();			// Initialize libmosquitto

	int keepalive = 120; // seconds
	connect(host, port, keepalive);		// Connect to MQTT Broker
}


  • Next, the on_connect() method is called after the connection to Broker is established. In this case, it simply prints a message on console and subscribes to a MQTT message topic (command/IGoT).
void NRMKMqttWrapper::on_connect(int rc)
{
	printf("Connected with code %d. \n", rc);

	if (rc == 0)
	{
		subscribe(NULL, "command/IGot");
	}
}
  • Finally, if we successfully subscribe to a message topic, libmosquittopp will call on_subscribe() method which only prints a success message to console.
void NRMKMqttWrapper::on_subcribe(int mid, int qos_count, const int *granted_qos)
{
	printf("Subscription succeeded. \n");
}


Main

In main() function, we firstly create and initialize an object of NRMKMqttWrapper with its own ID (Neuromeka IGoT) and Broker information (192.168.0.12:1883).

NRMKMqttWrapper * mqttHdl;
mqttHdl = new NRMKMqttWrapper("Neuromeka IGot", "192.168.0.12", 1883);

Later, we scan the shared memory for newest information so that we can publish it as a message to the topic IGoT/sensors.

while(1)
{
	fd	= open (NRMK_SMEM_NAME, O_RDWR, S_IRUSR | S_IWUSR);	// Open Shared Memory
	res	= read(fd, tstr, FILE_LENGTH);

	for (i=0; i<FILE_LENGTH; ++i)					// Read data from shared memory
	{
		if ((tstr[i]==':') && (i<100))
		{
			strncpy(strCounter, tstr, i);
			Counter = atol(strCounter);
			break;
		}

	}

	if (Counter != preCounter)					// Check whether this data is new
	{
		printf ("%s", tstr);
		preCounter=Counter;

		mqttHdl->publish(NULL, "IGoT/sensors", strlen(tstr), tstr);	// Publish the data to MQTT topic "IGoT/sensors"
	}

	close (fd);

	res = mqttHdl->loop();						// Keep MQTT connection		
	if (res)
		mqttHdl->reconnect();
	usleep(1e5);
}
  • You may not that we call mqttHdl->loop() repeatedly. Actually, this function should be called frequently in order to keep communications between the client and broker working.
    • If incoming data is present it will then be processed.
    • The loop() will also attempt to send any remaining outgoing messages