Using the ArduinoMQTT Client Library

arduinoThere are several  MQTT clients available for Arduino and we are going to use the PubSub MQTT client.

Before you can use this client you need to install it into the Arduino Library.

Go to the Library manager and so a search for MQTT. You will find quite a few listings scroll down the select the ArduinoMQTT client.

The documentation for the library is here, but I did not find it particularly helpful.

There are also code examples on the Github page here.

About This Tutorial

In this tutorial we will look at using the ArduinoMQTT Client Library with code examples for Arduino Uno (Ethernet), ESP8266 and ESP32 boards.

We will start by going through the basic functions available and how and in what order they are used.

We will see how you connect to a broker,subscribe to topics and publish messages and finally how we receive incoming messages. Working Demo scripts are available for download at the end.

MQTT Client Basics

For any MQTT client we have 4 distinct stages

  1. Connect
  2. Subscribe
  3. Publish
  4. Disconnect

Steps 2 and 3 are optional.

Before we connect we need to create a client object.

This client object is tied to the underlying physical connection i.e. (Ethernet or Wi-Fi).

For Wi-FI you will see something similar to this near the top of the code

WiFiClient espClient;
MqttClient mqttClient(espClient);

All MQTT clients are required to have a unique client id .

and for Ethernet we have

EthernetClient ethClient;
MqttClient mqttClient(ethClient);

You need to set this before connecting along with any other connection parameters like clean session, username/password etc.
To set the client id use:

mqttClient.setId("esp32-1");

were esp32-1 is the client name.

Some Other commands are :

  • MqttClient.setKeepAliveInterval(unsigned long interval)
  • MqttClient.setCleanSession(bool cleanSession)
  • void MqttClient.setUsernamePassword(const char* username, const char* password)

Once you have set the client options you can then connect to the broker using the mqttClient.connect(broker,port)  call as shown below:

const char broker[] = "192.168.1.33";
int        port     = 1883;
mqttClient.connect(broker,port);

The call returns true if successful and false if not, and so it is normal to put this call in a while and if loop the psuedo code is:

while not connected
try and connect

Actual code is below and uses the mqttClient.connected() function call to test the connection (0=connected,1=not connected).

  
void reconnect() {
while (mqttClient.connected()==0) {
      mqttClient.setId("esp32-1");
      Serial.print("Attempting to connect to the MQTT broker: ");
      Serial.println(broker);

  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());
         Serial.print("failed, rc=");
      Serial.println(" try again in 5 seconds");
      delay(5000);
   }
 else {
  
  Serial.println("Connected to the MQTT broker!");
  Serial.println();
 Serial.println("connected so subscribe");
 mqttClient.subscribe(topic);
    }
  }//end while
} //end function

In many online scripts this code is placed in the setup, but if you do this the client will not reconnect so I place it inside a function and call the function from the loop. You can see this in the code above.

Receiving Messages

In order to receive messages you will need to:

  • subscribe to a topic or topics
  • configure a callback to handle the received message

To subscribe to a topic or topics use mqttClient.subscribe(topic) function.

You should note that you can use wild cards when subscribing see Understanding MQTT topics for details.

The subscribe code is paled in the connect loop and you can see it in the code above– mqttClient.subscribe(topic).

The call back consists of a callback function and a set up. Sample call back function is shown below:

void onMqttMessage(int messageSize) {
  // we received a message, print out the topic and contents
  Serial.println("Received a message with topic '");
  Serial.print(mqttClient.messageTopic());
  Serial.print("', length ");
  Serial.print(messageSize);
  Serial.println(" bytes:");

  // use the Stream interface to print the contents


  while (mqttClient.available()) {
   Serial.print((char)mqttClient.read());
  }
  Serial.println();

}

In the setup you need to register this callback using

 mqttClient.onMessage(onMqttMessage); //callback

mqttClient.poll() Function

This function needs to be called on a regular basis and it processes the receive buffer.

Without this function you want see any incoming messages including control messages like puback,pingresp.

I did a tutorial on the loop in relation to python but it is applicable to all MQTT clients.

The arduino client is single threaded and so it must be placed in the loop.

In addition the loop should not  have any delays . Here is my loop example:

void loop() {
  // call poll() regularly to allow the library to send MQTT keep alives which
  // avoids being disconnected by the broker
  mqttClient.poll();
 if (mqttClient.connected()==0) {
    reconnect();
  }
  // to avoid having delays in loop, we'll use the strategy from BlinkWithoutDelay
  // see: File -> Examples -> 02.Digital -> BlinkWithoutDelay for more info
      unsigned long now = millis();
     if (now - lastMsg > 5000) {
    lastMsg = now;
    Serial.print("Publishing message: ");
    Serial.println(msg);
    publish_msg(topic, msg);
    //Serial.printf("RSSI: %d dBm\n", WiFi.RSSI());
    WiFi.printDiag(Serial);
 
     }
    
}

Notice we do not use delay(5000) to control the print as this would cause a delay.
Also notice that the connection is tested and if it has failed the reconnect function is called.

Publishing Messages

This is done with the calls to three functions
beginMessage(),print() and end. Actual code is shown below:

    mqttClient.beginMessage(topic);
    mqttClient.print(msg);
    mqttClient.endMessage();

The begin message function can also take the retain flag and QOS,
e.g to publish with a QOS or 1 and retain flag set use:

mqttClient.beginMessage(topic,true,1);

User names and Passwords

If the broker requires authentication you can set the username and password the you can set this before you connect using

mqttClient.setUsernamePassword(“username”, “password”);

Last Will Message

The last will message and topic need to be set before connecting and use the same format as the publish as shown in the code below.

   char willTopic[]        = "connected/esp-32";
  char willPayload[] = "not connected";
  bool willRetain = true;
  int willQos = 1;

  mqttClient.beginWill(willTopic, willRetain, willQos);
  mqttClient.print(willPayload);
  mqttClient.endWill();

Code Examples

The example code will subscribe to a topic and publish a message on the same  topic every 5 seconds.

It also sets a will message and uses authentication.

The code for all three boards -arduino, ESP32 and ESP8266 is virtually identical and only differs in the libraries.

At the top of the ESP code you will see:

#include <ArduinoMqttClient.h>
#include <ESP8266WiFi.h> //use this for ESP8266
//#include <WiFi.h> //use this and comment out above when using ESP32 boards
//#include "arduino_secrets.h"
//#include "arduino_secrets.h"
//#include "arduino_secrets.h"
//#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = "Akehurst";    // your network SSID (name)
char pass[] = "akehurst122012";    // your network password (use for WPA, or use as key for WEP)

WiFiClient espClient;
MqttClient mqttClient(espClient);

for esp8266 we use:

#include <ESP8266WiFi.h>

and for ESP32 we use

#include <WiFi.h>

Arduino Ethernet

For the arduino board with Ethernet we have:

#include <ArduinoMqttClient.h>
#include <Ethernet.h>

// Update these with values suitable for your network.
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 89); //address of client
EthernetClient ethClient;
MqttClient mqttClient(ethClient);

Full Demo code

download

Related Tutorials and Resources:

Please rate? And use Comments to let me know more

Leave a Reply

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