# MQTT in ESP32 Feather ![](https://hackaday.com/wp-content/uploads/2016/05/mqtt_dash.png =200x) ![](https://2.bp.blogspot.com/-p2fCwjQl2Ag/XHm2_Lz7EhI/AAAAAAAAI8Q/mQnXwIv0B7YTcVkV6m-ibOX172AaQUeNgCLcBGAs/s1600/adafruithuzzah32pin.jpg =200x) [Here]() you can find information about the MQTT protocol and how it works. You need the [Arduino IDE](https://www.arduino.cc/en/software) installed. And the [PubSubClient](https://github.com/knolleary/pubsubclient) library. If you don't know how to install libraries on the Arduino IDE here is a [guide](https://www.arduino.cc/en/guide/libraries). ## Code Example :::spoiler Full Code ~~~c= #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 ~~~c #include <WiFi.h> #include <PubSubClient.h> ~~~ ### Wifi Change the WiFi **ssid** and **password** to fit your's. ~~~c 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`) ~~~c 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); ~~~ :::info 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.** ~~~c 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. ~~~c 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 } ~~~ :::info 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. ~~~c 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. ~~~c // 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! :::info **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](https://mosquitto.org/) 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. :::info 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! :::