This guide shows how to use the ESP32 with the
PubSubClient library
to connect to an MQTT broker, publish sensor data, and subscribe to topics.
PubSubClient is a lightweight MQTT client for Arduino and ESP platforms. It supports MQTT v3.1.1,
making it ideal for IoT and embedded applications running on constrained devices like ESP32.
Before you begin, ensure you have:
In ESP32, connecting to MQTT involves:
void connectToWiFi() {
Serial.print("Connecting to WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" connected");
}
void connectToMQTT() {
while (!client.connected()) {
Serial.print("Connecting to MQTT...");
if (client.connect("SensorClient", mqtt_user, mqtt_password)) {
Serial.println(" connected");
} else {
Serial.print(" failed, rc=");
Serial.print(client.state());
Serial.println(" - retrying in 5 seconds");
delay(5000);
}
}
}
DynamicJsonDocument doc(256);
doc["value"] = 5;
String payload;
serializeJson(doc, payload);
client.publish("sensor/status", payload.c_str());
if (client.connect("SensorClient", mqtt_user, mqtt_password)) {
client.subscribe("sensor/control");
}
To unsubscribe:
client.unsubscribe("sensor/control");
Clean disconnection ensures the broker releases resources tied to the session and avoids lingering socket connections.
client.disconnect();
The provided sketch connects the ESP32 to Wi-Fi, then establishes an MQTT connection using the PubSubClient library. It continuously monitors a digital sensor on GPIO 33. Whenever the sensor value changes (e.g., 0 → 1 or 1 → 0), the ESP32 creates a JSON payload like {"value":1} and publishes it to the topic sensor/status.
The code also keeps the MQTT connection alive with client.loop() and automatically attempts to reconnect if the broker connection is lost.
<#include <Arduino.h>
<#include <WiFi.h>
<#include <PubSubClient.h>
<#include <ArduinoJson.h>
// WiFi credentials
const char* ssid = "xxxxxxxxxx";
const char* password = "xxxxxxxxxx";
// MQTT broker credentials
const char* mqtt_server = "xxxxxxxxxxxxx";
const char* mqtt_user = "xxxxxxxxxxxxx";
const char* mqtt_password = "xxxxxxxxxx";
// Pin connected to the digital sensor
const int sensorPin = 33;
WiFiClient espClient;
PubSubClient client(espClient);
// Store last known sensor value to detect changes
int lastSensorValue = -1;
void connectToWiFi() {
Serial.print("Connecting to WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" connected");
}
void connectToMQTT() {
while (!client.connected()) {
Serial.print("Connecting to MQTT...");
if (client.connect("SensorClient", mqtt_user, mqtt_password)) {
Serial.println(" connected");
} else {
Serial.print(" failed, rc=");
Serial.print(client.state());
Serial.println(" - retrying in 5 seconds");
delay(5000);
}
}
}
void publishSensorValue(int value) {
DynamicJsonDocument doc(256);
doc["value"] = value;
String payload;
serializeJson(doc, payload);
client.publish("sensor/status", payload.c_str());
Serial.println("Published on change: " + payload);
}
void setup() {
Serial.begin(115200);
pinMode(sensorPin, INPUT);
connectToWiFi();
client.setServer(mqtt_server, 1883);
connectToMQTT();
// Initialize with current state to avoid false first trigger
lastSensorValue = digitalRead(sensorPin);
}
void loop() {
if (!client.connected()) {
connectToMQTT();
}
client.loop(); // Maintain MQTT connection
int currentValue = digitalRead(sensorPin);
if (currentValue != lastSensorValue) {
lastSensorValue = currentValue;
publishSensorValue(currentValue); // Publish only if value has changed
}
delay(10); // Short delay to debounce noise, tweak if necessary
}