Using the Arduino PubSub MQTT Client

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 PubSub client.



pubsubclient-arduino

The documentation for the client API is available here.

About This Tutorial

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. Two working Demo scripts are available for download at the end.

Client Basics

Like most most MQTT clients you follow 4 basic steps

  • Create a Client Object
  • Create a Connection to a Broker
  • Publish and/or subscribe
  • Process received Messages

The first step is to create an Instance of the client object the API lists several constructors they are:

  • PubSubClient ()
  • PubSubClient (client)
  • PubSubClient (server, port, [callback], client, [stream])

where

client= client transport object instance EthernetClient
server=broker name or IP address
port = broker port default is 1883
callback= a function to process received messages
stream= instance of a message stream to store received messages

The one I will Illustrate here is PubSubClient (client)

Example code Using Ethernet:

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);

Now our client is called mqttClient

Now we need to create a connection to a broker.

First we need to use the setServer method which requires a broker address and port (optional)

setServer(server, port)

example Code:

mqttClient.setServer("192.168.1.68", 1883);

Now if we want to receive messages we also need to create a callback function and set it using setCallback(callback) method;.

Example Code:

mqttClient.setCallback(callback_function);

However we will skip that step here and continue.

So now we need to connect using the connect (clientID) function. Here clientID is the name of the client and must be unique:

Example code:

mqttClient.connect("arduino-1")

Now we are connected we can subscribe and publish.

To subscribe to a topic use the subscribe function

subscribe(topic,qos)

This requires a topic and an option QOS (1 or 0)  defaults to 0

Example code:

mqttClient.subscribe("test")

We can Publish using the publish method. .There are four options all return an Integer, 1 for success (true) and 0 for fail(false).

These two use a character array for the payload:

  • publish (topic, payload)
  • publish (topic, payload, retained)

These two use a Byte Array for the payload:

  • publish (topic, payload, length)
  • publish (topic, payload, length, retained)

Example code using character string:

boolean rc = mqttClient.publish("test", "This is a test message");

Example code using bytes:

byte outmsg[]={0xff,0xfe};
boolean rc = mqttClient.publish("test", outmsg,2);

Return Codes

Most functions return a value which indicates success or fail.

Important ones to be aware of are the connect function which provides a boolean true/false for success or fail.

So it is usual to test for a successful connection before proceeding as you cannot publish or subscribe until you are connected.

The code below tests the connection and if successful goes ahead and subscribes.

  if (mqttClient.connect("arduino-1")) {
    // connection succeeded
    Serial.println("Connected now subscribing");
    boolean r= mqttClient.subscribe("test");

  } 
  else {
    // connection failed
    // mqttClient.state() will provide more information
    // on why it failed.
    Serial.println("Connection failed ");
  }

You should also note the comment in the else statement regarding using the state() function to get more detail on the connection.

I recommend you look at the docs for detailed information regarding the return codes and their meaning.

The Loop Function

The loop function is responsible for processing the message queues and is required in the script and is placed inside a while loop so that it is called frequently.

The idea behind this function is basically the same as the one used in the Python client which I described in detail here.

Example Code:

The example code publishes a string and a byte message every second. It also subscribes to a topic bit doesn’t have a callback function to process the received.

messages.

Receiving Messages

We have already seen how to subscribe which we did as part of the setup and now we need to ensure that we add the callback using the setcallback() function.

The function takes the name of the function to call.

  mqttClient.setServer("192.168.1.68", 1883);
  mqttClient.setCallback(callback);

We now need to create the callback function to process the received message.

The callback function needs to accept various arguments. The structure is

void callback(const char[] topic, byte* payload, unsigned int length)

Note: length is the length of the payload.

Example code:
The code prints the received topic and message.

  void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i=0;i<length;i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

Example Demo Code includes receiving Messages

Question

If you run demo code for example2 you only receive messages for the string message as shown in the screen shot below. Why is that? Answer at the end.

arduino-test-1

Related Tutorials

Using the Python MQTT Client.

Answer to question

This is because the bytes published on a different topic and so you need to subscribe to that topic as well.

Please rate? And use Comments to let me know more
[Total: 2   Average: 5/5]

2 comments

  1. Hi,

    the callback function is never called , im using the same code and subscription is shown in the server but I’m not able to receive the message when it comes to the topic, any idea ?

Leave a Reply

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