MQTT in ESP32 Feather

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’

Here you can find information about the MQTT protocol and how it works.

You need the Arduino IDE installed. And the PubSubClient library.
If you don't know how to install libraries on the Arduino IDE here is a guide.

Code Example

Full Code
#include <WiFi.h> #include <PubSubClient.h> const char* ssid = "mdefAP"; const char* password = "mdefPassword"; WiFiClient wifiClient; const char* mqttBroker = "192.168.5.1"; const char* mqttClientName = "teamX"; const String mqttUser = ""; // MQTT User Authentification const String mqttPass = ""; // MQTT Password Authentification const char* topicToSub = "teamx/in"; const char* topicToPub = "teamx/out"; PubSubClient mqttClient(wifiClient); const int buttPin = 6; bool buttState; void mqttConnect() { while (!mqttClient.connected()) { Serial.print("Attempting MQTT connection..."); if (mqttClient.connect(mqttClientName, mqttUser, mqttPass)) { Serial.println("connected"); mqttClient.publish("hello", mqttClientName); // Topic(s) subscription mqttClient.subscribe(topicToSub); } else { Serial.print("failed, rc="); Serial.print(mqttClient.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } } void callback(char* topic, byte* message, unsigned int length) { String receivedMsg; for (int i = 0; i < length; i++) { receivedMsg += (char)message[i]; } Serial.print("Message arrived on topic: "); Serial.print(topic); Serial.print(". Message: "); Serial.println(receivedMsg); if (String(topic) == topicToSub) { // Add here the code to act on input -------------- // Arduino String obejct reference : // https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/ if (receivedMsg == ("1")) { Serial.println("on"); digitalWrite(LED_BUILTIN, HIGH); } else if (receivedMsg == "0") { Serial.println("off"); digitalWrite(LED_BUILTIN, LOW); } //------------------------------------------------- } } void setup() { Serial.begin(115200); // Connect to wifi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); // MQTT setup mqttClient.setServer(mqttBroker, 1883); mqttClient.setCallback(callback); // Led setup pinMode(LED_BUILTIN, OUTPUT); } unsigned long lastMsg = 0; char msg[50]; void loop() { // Check the current button state bool currentState = digitalRead(buttPin); // Check if we are still connected to the MQTT broker if (!mqttClient.connected()) { mqttConnect(); } // Let PubSubClient library do his magic mqttClient.loop(); // Add your publish code here -------------------- // OPTION 1 -- Publish based on events if (currentState != buttState) { buttState = currentState; snprintf (msg, 50, "%i", buttState); mqttClient.publish(topicToPub, msg); } // OPTION 2 -- Publish based on Timer // Only publish every 5 seconds unsigned long now = millis(); if (now - lastMsg > 5000) { lastMsg = now; snprintf (msg, 50, "%ld - hello again!", now); Serial.print("Publish message: "); Serial.println(msg); mqttClient.publish(topicToPub, msg); } //----------------------------------------------- }

Global setup

Include Libraries

#include <WiFi.h>
#include <PubSubClient.h>

Wifi

Change the WiFi ssid and password to fit your's.

const char* ssid = "mdefAP";
const char* password = "mdefPassword";
WiFiClient wifiClient;

MQTT

Set the IP address or name of your MQTT broker or the server name, the name that will identify your device and the names of a topic(s) to subscribe and/or publish, and the authentification (mqttUser and mqttPass)

const char* mqttBroker = "192.168.5.1";
const char* mqttUser = ""; // MQTT User Authentification
const char* mqttPass = ""; // MQTT Password Authentification
const char* mqttClientName = "teamX";
const char* topicToSub = "teamx/in";
const char* topicToPub = "teamx/out";
PubSubClient mqttClient(wifiClient);

Adding variables for topic names is optional but in this way if you need to change them you can do it in one point instead of tracking all the places where they are used.

Helper functions

MQTT connect function

This function is called on the main loop, it checks if the connection with the MQTT broker is alive and reconnects if necessary.
Here we subscribe to the topics we want to receive.

void mqttConnect() {
  
  while (!mqttClient.connected()) {
  
    Serial.print("Attempting MQTT connection...");
  
    if (mqttClient.connect(mqttClientName, mqttUser, mqttPass)) {
  
      Serial.println("connected");
      mqttClient.publish("hello", mqttClientName);
      
      // Topic(s) subscription
      mqttClient.subscribe(topicToSub);

  
    } else {
      
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    
    }
  }
}

Subscription callback

This function is executed every time a message is received. In this example if we receive the words on or off in a specific topic we change the led state.

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

  if (String(topic) == topicToSub) {
  
    if (receivedMsg == ("1")) {
    
      Serial.println("on");
      digitalWrite(LED_BUILTIN, HIGH);
    
    } else if (receivedMsg == "0") {
      
      Serial.println("off");
      digitalWrite(LED_BUILTIN, LOW);
    
    }
  } // Here you can check for other subscribed topics
}

Subscribing to a new topic is done in three points of the code:

  1. Near the top create a variable with the topic name you want to subscribe to.
  2. In the mqttConnect() function add a line subscribing to the new topic: mqttClient.subscribe(newName)
  3. In the callback() function check if the new topic is receiving something, evaluate the message and take some actions!

Main functions

Setup

Start Serial communication, WiFi, MQTT and the pin to control internal led.

void setup() {
  
  Serial.begin(115200);

  // Connect to wifi
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  
  // MQTT setup
  mqttClient.setServer(mqttBroker, 1883);
  mqttClient.setCallback(callback);

  // Led setup
  pinMode(LED_BUILTIN, OUTPUT);
}

Loop

In the main loop we check if the MQTT connection is still alive and call the mqttConnect() function if needed.
We need to call the mqttClient.loop() function every cycle so the PubSubClient library has time to do his inner works.

// Declare needed variables
unsigned long lastMsg = 0;
char msg[50];

void loop() {
// Check the current button state
  bool currentState = digitalRead(buttPin);

  // Check if we are still connected to the MQTT broker
  if (!mqttClient.connected()) {
    mqttConnect();
  }

  // Let PubSubClient library do his magic
  mqttClient.loop();

  // Publish based on events
  if (currentState != buttState) {
      buttState = currentState;
      
      snprintf (msg, 50, "%i", buttState);      
      mqttClient.publish(topicToPub, msg);
  }   
}

Now make sure your broker is running and it is on the right address and power your feather!

Publishing a MQTT message can be done just adding a call to the publish(topic, message) function of the MQTT client.

Troubleshooting

  • Check the output of the Feather Serial port

    • Is WiFi connection successfull?
    • Is your Feather finding the MQTT broker?
  • To interact with MQTT from your computer you can use
    mosquitto software.

    • Try sending a MQTT message to a subscribed topic and check if the feather receives it.
    • Subscribe to a topic whre your Feather is posting and check if you receive something.
  • Log in your Raspberry Pi MQTT broker.

    • Check the logs of the Mosquitto broker (/var/log/mosquitto/mosquitto.log)
    • Stop the broker sudo systemctl stop mosquitto and run it manually (just type mosquitto and hit enter) to see the the console output.

Printing debug messages to the Serial port can make your code big and more complicated, but when something doesn't work you will be gratefull of those lines!