Esp8266 Connecting To MQTT Broker

 

Aelius Venture News   •   Jun 15, 2018

 

The objective of this post is to explain how to connect the ESP8266 to a MQTT broker, hosted on CloudMQTT.

The code

First, we start by including the libraries needed for all the functionality. We need the ESP8266WiFi library, in order to be able to connect the ESP8266 to a WiFi network, and the PubSubClient library, which allows us to connect to a MQTT broker and publish/subscribe messages in topics.

1
2
#include
#include

Then, we will declare some global variables for our connections. Naturally, we need the WiFi credentials, to connect to the WiFi network.

1
2
const char* ssid = "YourNetworkName";
const char* password =  "YourNetworkPassword";

We will also need the information and credentials of the MQTT server. As explained in the introduction, you will need to know the server address, the port, the username and the password. Use your values in the variables bellow.

const char* mqttServer = "m11.cloudmqtt.com";
const int mqttPort = 12948;
const char* mqttUser = "YourMqttUser";
const char* mqttPassword = "YourMqttUserPassword";

After that, we will declare an object of class WiFiClient, which allows to establish a connection to a specific IP and port [1]. We will also declare an object of class PubSubClient, which receives as input of the constructor the previously defined WiFiClient.

The constructor of this class can receive other number of arguments.

1
2
WiFiClient espClient;
PubSubClient client(espClient);

Now, moving for the setup function, we open a serial connection, so we can output the result of our program. We also connect to the WiFi network.

Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");

Next, we need to specify the address and the port of the MQTT server.  To do so, we call the setServer method on the PubSubClient object, passing as first argument the address and as second the port.  These variables were defined before, in constant strings.

1
client.setServer(mqttServer, mqttPort);

Then, we use the setCallback method on the same object to specify a handling function that is executed when a MQTT message is received. We will analyse the code for this function latter.

1
client.setCallback(callback);

Now, we will connect to the MQTT server, still in the setup function. As we did in the connection to the WiFi network, we connect to the server in a loop until we get success.

So, we do a while loop based on the output of the connected method called on the PubSubClient, which will return true if the connection is established or false otherwise.

To do the actual connection, we call the connect method, which receives as input the unique identifier of our client, which we will call “ESP8266Client”, and the authentication username and password, which we defined early. This will return true on connection success and false otherwise

Check bellow the whole connecting loop.

while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected"); 
    } else {
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
}

To finalize the setup function, we will publish a message on a topic. To do so, we call the publish method, which receives as input arguments the topic and the message. In this case, we will publish a “Hello from ESP8266” message on the “esp/test” topic.

1
client.publish("esp/test", "Hello from ESP8266");

Then, we will subscribe to that same topic, so we can receive messages from other publishers.

1
client.subscribe("esp/test");

Check the full setup function bellow.

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected"); 
    } else {
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
  }
  client.publish("esp/test", "Hello from ESP8266");
  client.subscribe("esp/test");
}


The callback function

After the initialization, we need to specify the callback function, which will handle the incoming messages for the topics subscribed.

The arguments of this function are the name of the topic, the payload (in bytes) and the length of the message. It should return void.

In this function, we will first print the topic name to the serial port, and then print each byte of the message received. Since we also have the length of the message as argument of the function, this can be easily done in a loop.

Check bellow the whole function code.

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

 

The main loop

In the main loop function, we will just call the loop method of the PubSubClient. This function should be called regularly to allow the client to process incoming messages and maintain its connection to the server.

1
2
3
void loop() {
  client.loop();
}

Check the full code bellow

#include
#include
const char* ssid = "YourNetworkName";
const char* password =  "YourNetworkPassword";
const char* mqttServer = "m11.cloudmqtt.com";
const int mqttPort = 12948;
const char* mqttUser = "YourMqttUser";
const char* mqttPassword = "YourMqttUserPassword";
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected"); 
    } else {
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
  }
  client.publish("esp/test", "Hello from ESP8266");
  client.subscribe("esp/test");
}
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  Serial.println("-----------------------");
}
void loop() {
  client.loop();
}