Publish using MQTT

Overview

Publish/Subscribe model

MQTT is a lightweight publish/subscribe messaging protocol designed for machine to machine telemetry in low bandwidth environments. It is useful for use with low power sensors, but is applicable to many scenarios. The MQTT protocol is based on the principle of publishing messages and subscribing to topics. Multiple clients connect to a server often termed as a "broker". The broker is a central communication point that transmits the messages between senders and the clients who subscribed to receive the messages on a certain topic. Clients include the topic in the message, when publishing to the broker. The topic is the routing information for the broker. The broker delivers all the messages on a specific topic to the client, if the client has subscribed to it. The broker and MQTT act as a simple, common interface for everything to connect to. The data producers and the data consumers are independant of each other.

Figure 1

Subscription to MQTT topics

Messages in MQTT are published on topics. There is no need to configure a topic, publishing on it is enough. Topics are simple strings treated as a hierarchy, using a slash (/) as a separator.

Clients can receive messages by subscribing to a topic.

In figure 1, we see client 1 (a temperature sensor) sending temperature to the broker. client 2 and client 3 subscribed to the topic and will receive all the messages on that topic. In this case, a sample topic for sending temperature of room A in HiveColab building could be HiveColab/roomA/temp.

Figure 2

A subscription can be to an exact topic, in which case the client will receive all the messages on that exact topic, or it may include wildcards. Two wildcards are available, + or #. The + sign can be used as a wildcard for a single level of hierarchy. The subscription to HiveColab/+/temp would result in all the messages sent to HiveColab/roomA/temp as well as any topic with an arbitrary value in the place of roomA, for example, HiveColab/roomB/temp. A detailed example is shown in figure 2.

Multiple applications have been developed on MQTT which include Amazon Web Services, EVERYTHING IoT platform, Facebook Messenger and many others which are available on PlayStore for Android and AppStore for iOS. An example of Google PlayStore is shown in figure 3 below.

Figure 3

Further documentation on MQTT is available on their official website mqtt.org.

Brief description of the code

We will briefly explain the steps used in the example below to use the MQTT protocol.

Include the publish/subscribe library

 
#include <PubSubClient.h>

Test parameters for MQTT: topic, temperature and MQTT server address

 
char *topicin = "UPPA/test"; 
char *topicout = "UPPA/test"; 
char *msgTemp  = "22.5"; 
char* mqtt_server = "test.mosquitto.org";

Define the publish/subscribe client

WiFiClient espClient; 
PubSubClient client(espClient);

Define a function callback() to process incoming message from a given subscribed topic. This is not needed if you only publish, which is more typical of an end-device.

 
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]);
  }

Define a function reconnect() to keep trying to connect to the MQTT broket until it is successful. Here the client id can be random because the MQTT broker we use does not require authentication.

 
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");

    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
    // Wait 5 seconds before retrying  
      delay(5000);
    }
  }
}

In function setup(), setup the MQTT server

 
client.setServer(mqtt_server, 1883);

In function loop(), check if client is connected, if not then reconnect

 
void loop() {

  if (!client.connected()) {
    reconnect();
  }

At the end, publish the message on specified topic

   
  int e=client.publish(topicout, msgTemp);

Complete working example

  
    
// if you have an ESP8266 based board
#define ESP8266

#if defined ESP8266 || defined ARDUINO_ESP8266_ESP01
include <ESP8266WiFi.h>
#else
#include <WiFi.h>
#endif

#include <PubSubClient.h>

// Update these with values suitable for your network.

char* ssid = "iPhoneD";
char* password = "345hello";

char *topicin = "UPPA/test"; 
char *topicout = "UPPA/test"; 
char *msgTemp  = "22.5"; 
char* mqtt_server = "test.mosquitto.org";

WiFiClient espClient;
PubSubClient client(espClient);

int WiFi_status = WL_IDLE_STATUS;

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

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();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");

    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
    // Wait 5 seconds before retrying  
      delay(5000);
    }
  }
}

void setup() {
  delay(3000);
  Serial.begin(38400);

// Print a start message  
  Serial.println(F("Simple MQTT demo")); 
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  //client.setCallback(callback);
}

void loop() {

  if (!client.connected()) {
    reconnect();
  }
  
  //client.loop();  
  WiFi_status = WiFi.status();
  
  if ( WiFi_status != WL_CONNECTED) {
  while ( WiFi_status != WL_CONNECTED) {
      Serial.print("Attempting to connect to WPA SSID: ");
      Serial.println(ssid);
      // Connect to WPA/WPA2 network
      WiFi_status = WiFiWiFi.begin(ssid, password);
      delay(500);
    }
    Serial.println("Connected to AP");   
  } 
  Serial.print("Publishing: status=");

  int e=client.publish(topicout, msgTemp);
  Serial.println(e); 
  delay(7500);   
 }                 

The raw source of the sketch example is visible here.

Enjoy!