5. Exercise: practical application
An exercise is proposed to communicate two ESP32s in an MQTT netword. One of them acts as publisher while the other as subscriber. The one that has the role of publisher has a button connected and, when the button is pressed (or released), it publishes in a topic that the button has been pressed. The other ESP32 will have a LED connected and will subscribe to the topic in which the ESP32 publisher publishes. Then, each time it receives a message in the topic, it changes the state of the LED.
To test the application you can open two tabs in the browser and check that it works as follows:
Try to solve the problem before seeing the solution below.
Show publisher diagram.json
diagram.json
{
"version": 1,
"author": "Juan M. Gandarias",
"editor": "wokwi",
"parts": [
{
"type": "board-esp32-devkit-c-v4",
"id": "esp",
"top": -124.8,
"left": -187.16,
"attrs": {}
},
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": -3.4,
"left": -326.4,
"attrs": { "color": "green", "bounce": "0" }
}
],
"connections": [
[ "esp:TX", "$serialMonitor:RX", "", [] ],
[ "esp:RX", "$serialMonitor:TX", "", [] ],
[ "btn1:1.r", "esp:14", "green", [ "v0" ] ],
[ "btn1:2.r", "esp:GND.1", "black", [ "h0" ] ]
],
"dependencies": {}
}
Show publisher code
mqtt_publisher_button.ino
#include <WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
# define BUTTON_PIN 14
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
#define WIFI_CHANNEL 6
const char *MQTT_BROKER_ADRESS = "mqtt.eclipseprojects.io";
const uint16_t MQTT_PORT = 1883;
const char *MQTT_CLIENT_NAME = "ESP32_test_pub";
WiFiClient espClient;
PubSubClient mqttClient(espClient);
String payload;
volatile bool button_released = false;
void IRAM_ATTR buttonReleased(){
button_released = true;
}
void ConnectWiFi()
{
WiFi.begin(WIFI_SSID, WIFI_PASSWORD, WIFI_CHANNEL);
Serial.print("Connecting to WiFi ");
Serial.print(WIFI_SSID);
while (WiFi.status() != WL_CONNECTED)
{
delay(100);
Serial.print(".");
}
Serial.println(" Connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void InitMqtt()
{
mqttClient.setServer(MQTT_BROKER_ADRESS, MQTT_PORT);
}
void ConnectMqtt()
{
while (!mqttClient.connected())
{
Serial.print("Starting MQTT connection...");
if (mqttClient.connect(MQTT_CLIENT_NAME))
{
Serial.print("Client connected");
}
else
{
Serial.print("Failed MQTT connection, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void HandleMqtt()
{
if (!mqttClient.connected())
{
ConnectMqtt();
}
mqttClient.loop();
}
void PublishMqtt(bool data)
{
payload = "";
payload = String(data);
mqttClient.publish("/button_released", (char *)payload.c_str());
}
void setup(void)
{
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt((BUTTON_PIN)), buttonReleased, FALLING);
ConnectWiFi();
InitMqtt();
}
void loop()
{
HandleMqtt();
if (button_released){
PublishMqtt(true);
Serial.println("Publishing button data");
button_released = false;
}
delay(10);
}
Show subscriber diagram.json
diagram.json
{
"version": 1,
"author": "Juanma Gandarias",
"editor": "wokwi",
"parts": [
{ "type": "board-esp32-devkit-c-v4", "id": "esp", "top": -38.4, "left": -158.36, "attrs": {} },
{
"type": "wokwi-led",
"id": "led1",
"top": -42,
"left": -274.6,
"attrs": { "color": "green" }
},
{
"type": "wokwi-resistor",
"id": "r1",
"top": 41.8,
"left": -288.85,
"rotate": 270,
"attrs": { "value": "1000" }
}
],
"connections": [
[ "esp:TX", "$serialMonitor:RX", "", [] ],
[ "esp:RX", "$serialMonitor:TX", "", [] ],
[ "led1:C", "r1:2", "black", [ "v0" ] ],
[ "r1:1", "esp:GND.1", "black", [ "v38.4", "h105.45" ] ],
[ "led1:A", "esp:26", "green", [ "v0" ] ]
],
"dependencies": {}
}
Show subscriber code
mqtt_subscriber_LED.ino
#include <WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#define LED_PIN 26
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
#define WIFI_CHANNEL 6
const char *MQTT_BROKER_ADRESS = "mqtt.eclipseprojects.io";
const uint16_t MQTT_PORT = 1883;
const char *MQTT_CLIENT_NAME = "ESP32_test_sub";
WiFiClient espClient;
PubSubClient mqttClient(espClient);
String payload;
String content = "";
void ConnectWiFi()
{
WiFi.begin(WIFI_SSID, WIFI_PASSWORD, WIFI_CHANNEL);
Serial.print("Connecting to WiFi ");
Serial.print(WIFI_SSID);
while (WiFi.status() != WL_CONNECTED)
{
delay(100);
Serial.print(".");
}
Serial.println(" Connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void InitMqtt()
{
mqttClient.setServer(MQTT_BROKER_ADRESS, MQTT_PORT);
SuscribeMqtt();
mqttClient.setCallback(OnMqttReceived);
}
void ConnectMqtt()
{
while (!mqttClient.connected())
{
Serial.print("Starting MQTT connection...");
if (mqttClient.connect(MQTT_CLIENT_NAME))
{
Serial.println("Client connected!");
SuscribeMqtt();
}
else
{
Serial.print("Failed MQTT connection, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void HandleMqtt()
{
if (!mqttClient.connected())
{
ConnectMqtt();
}
mqttClient.loop();
}
void SuscribeMqtt()
{
mqttClient.subscribe("/button_released");
}
void OnMqttReceived(char *topic, byte *payload, unsigned int length)
{
Serial.print("Received on ");
Serial.print(topic);
Serial.print(": ");
content = "";
for (size_t i = 0; i < length; i++)
{
content.concat((char)payload[i]);
}
Serial.print(content);
Serial.println();
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
void setup(void)
{
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
ConnectWiFi();
InitMqtt();
}
void loop()
{
HandleMqtt();
delay(10);
}