owned this note
owned this note
Published
Linked with GitHub
# 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!
:::