A Real-Time IoT System with ESP32, MQTT & Node-RED
How a temperature and humidity sensor becomes a real-time IoT monitoring system using ESP32, MQTT, an MQTT broker, and Node-RED
In this article, we will build this system step by step and, more importantly, understand what is happening at each stage.
Introduction
What happens when a simple temperature sensor becomes part of an IoT system?
The sensor measures the temperature and humidity. An ESP32 collects that data, MQTT transports it across the network, an MQTT broker manages the communication, and Node-RED turns those raw values into a real-time dashboard.
Requirement
For this project, you need:
Hardware
1. ESP32 development board
2. DHT11/DHT22 sensor
3. Breadboard
4. Jumper wires
5. USB cable
6. Computer/Laptop
Software
1. Arduino IDE
2. ESP32 board support
3. DHT sensor library
4. PubSubClient MQTT library
5. MQTT broker such as Mosquitto
6. Node-RED
7. Node-RED Dashboard
But for ease we are working on simulation no physical hardware is required
Prerequisites
Before starting, you should have:
- Laptop
- Internet connection
- A modern web browser
- Basic knowledge of Arduino programming
- Basic understanding of MQTT
No physical ESP32 or DHT11/DHT22 is required for this project.
Lets Start With WOKWI Simulation
Now, its time to connect DHT sensor to ESP32 GPIO pin
To connect a DHT22 temperature and humidity sensor to an ESP32 in Wokwi, wire the pins as follows (pin numbering for DHT22 from left to right: Pin 1 to Pin 4):
Pin Connections
Connecting the DHT22 to ESP32
VCC ───────────────── 3.3V
DATA ───────────────── GPIO 4
GND ───────────────── GND
DHT22 Pin 1 (VCC): Connect to 3V3 (or 5V) on the ESP32.
DHT22 Pin 2 (SDA / Data): Connect to a digital GPIO pin on the ESP32 (commonly GPIO 15 or GPIO 4).
DHT22 Pin 3 (NC): Leave disconnected (Not Connected).
DHT22 Pin 4 (GND): Connect to any GND pin on the ESP32.
Wokwi Wiring Tip :
In the Wokwi simulator, click on a pin on the DHT22 and drag the wire directly to the corresponding pin on the ESP32.
First Test: Read the Sensor
Before adding Wi-Fi and MQTT, we should test the sensor.
This is an important development practice.
Don’t start with:
DHT11 + ESP32 + Wi-Fi + MQTT + Broker + Node-RED all at once.
Instead:
DHT11
↓
ESP32
↓
Serial Monitor
First make sure the hardware works.
Before Implementing Code
Install the Required Arduino Libraries
Our ESP32 program needs libraries to communicate with the DHT22 sensor and the MQTT broker.
We will use:
DHT Sensor Library, This library allows the ESP32 to read temperature and humidity.
PubSubClient, This library provides MQTT client functionality for Arduino-compatible boards.
In Wokwi, libraries can be added through the project’s library management interface.
The libraries required are:
- DHT sensor library
- PubSubClient
Depending on the Wokwi environment, the required library dependencies may also be installed automatically.
For Manually
Use the following Arduino code:
#include <DHT.h>
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
dht.begin();
}
void loop() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (isnan(temperature) || isnan(humidity)) {
Serial.println("Failed to read from DHT sensor!");
delay(2000);
return;
}
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" °C");
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println(" %");
delay(2000);
}In Short the Arduino Code Represents :
The core logic follows a straightforward read-validate-output sequence executing repeatedly inside loop():
- Read: Fetches the latest numerical readings for temperature and humidity from the sensor using dht.readTemperature() and dht.readHumidity().
- Validate: Uses isnan() to check if the sensor returned invalid (“Not a Number”) data. If the read failed, it skips the rest of the loop, waits 2 seconds, and tries again.
- Output: If valid, prints the values along with their units (°C and %) to the Serial Monitor, then pauses 2 seconds before repeating the cycle.
Somhow the UI of WOKWI looks like this after you run the simulation :
Connecting ESP32 to Wi-Fi
Now we introduce networking.
The ESP32 needs to connect to a Wi-Fi network before it can communicate with the MQTT broker.
A basic Wi-Fi connection looks like:
Note: You do not use your real home Wi-Fi name or password when running this in Wokwi.
Because Wokwi runs entirely inside your web browser in a simulated environment, it cannot access your physical home network or local Wi-Fi router. Instead, Wokwi provides a built-in virtual access point specifically for simulations.
#include <WiFi.h>
const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD"; //optional
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
void loop() {
}Now lets test in Simulation :
After connecting, the ESP32 may receive an address such as:
192.168.1.25
This IP address identifies the ESP32 on the local network.
Here in our simulation you see in image
After you click the simulation button you will see compiling message pop up and after that you will see the following image.
Understanding the MQTT Architecture
Before writing the code, it is important to understand how MQTT works.
MQTT follows a publish/subscribe architecture.
There are three important concepts:
- Publisher
The ESP32 acts as the publisher.
It publishes sensor readings.
2. Broker
HiveMQ acts as the broker.
It receives messages from publishers and forwards them to subscribers.
3. Subscriber
Node-RED acts as the subscriber.
It subscribes to the MQTT topic and receives messages.
The communication looks like this:
ESP32
Publisher
│ publish
▼
HiveMQ
MQTT Broker
│ subscribe
▼
Node-RED
Subscriber
The ESP32 does not need to communicate directly with Node-RED.
The broker handles the communication.
Understanding TLS
When communicating with a cloud MQTT broker, security is extremely important.
An insecure connection could expose:
- Username
- Password
- Sensor data
- MQTT messages
HiveMQ Cloud provides secure MQTT connections using TLS.
The architecture becomes:
ESP32
│
│ Secure MQTT/TLS
▼
HiveMQ Cloud
│
│ MQTT
▼
Node-RED
For learning purposes, the important concept is:
MQTT + TLS = Secure MQTT Communication
When implementing the Wokwi connection, configure the ESP32 MQTT client according to HiveMQ’s current TLS connection requirements.
Now for the next step,
Install Node.js
Now we need Node-RED.
Node-RED runs on Node.js, so Node.js needs to be installed first.
Download and install the appropriate LTS version of Node.js for your operating system.
After installation, verify it using:
node — version
and:
npm — version
If both commands return version numbers, Node.js is installed correctly.
Next Step :
Install Node-RED
Open your terminal or command prompt and install Node-RED.
Run:
Get Er. Sunil Thapa’s stories in your inbox
Join Medium for free to get updates from this writer.
npm install -g — unsafe-perm node-red
After installation, start Node-RED using:
node-red
You should see Node-RED starting in the terminal.
By default, the Node-RED editor is available at:
Open this address in your browser. You should now see the Node-RED flow editor.
You Will See in your terminal as like below :
As after “node-red” command you will see in terminal :
Now COPY and PASTE server address of the terminal “http://127.0.0.1:1880/” link in web browser then you will see Node-RED flow editor.
Now You can change the name of flow with double click on the flow, Here I set custom flow name named as MQTT_ESP_FLOW
Now its time to add MQTT in our flow so make a search in PALETTE section as shown in the image below and then insert MQTT IN and MQTT OUT accordingly as you have to drag and grop the plugs for shown MQTT and then make a custom configuration as given in the image.
With Double Click on MQTT you will get the UI like given image below to setup custom configuration.
Inorder to fillup required information about the MQTT first check the given link :
https://www.hivemq.com/mqtt/public-mqtt-broker/
and then select for Public as shown in given figure below.
Now you will get MQTT connection Settings as shown in the image, these information are need to filled in the NODE-RED MQTT Configuration.
Now next,
Next
From the above image Name field in Node-RED is optional and purely for your own organizational convenience.
Default Behavior:
If left blank, Node-RED will automatically display the server address and port (e.g, broker.hivemq.com:1883) to identify this connection.
Custom Label:
You can type any friendly, descriptive name that helps you easily identify this specific MQTT broker configuration in your flow (e.g, Public HiveMQ Broker, Local Mosquitto, or Home Assistant MQTT).
It does not affect the connection settings or functionality — use whatever makes your workflow easiest to read.
Here the name is custom named as : “HiveMQ Public Broker”
You Can Edit and Make Custom Configuration By Clicking PEN sign in server section.
Then
Then
Then
Then
The two tools serve fundamentally different roles in an MQTT setup: one is the central router, and the other is a user interface for testing.
The Differences
HiveMQ Public Broker (broker.hivemq.com):
Role: The Server (Router).
Function: It sits in the cloud and acts as the middleman. It receives messages sent from publishers (e.g., your Node-RED flow, sensors, or apps) and routes them to subscribers who want that data.
Interface: None. It runs headlessly in the background without a visual dashboard.
HiveMQ MQTT Browser Client:
Role: A Client (Tool/Testing UI).
Function: It is a web app running in your web browser that uses WebSockets to connect to an MQTT broker.
Interface: A visual UI with buttons, text fields, and logs that allows you to manually send (Publish) and receive (Subscribe) messages.
Why Both Are Necessary
MQTT operates strictly on a Publish/Subscribe architecture. Clients never talk directly to each other; they can only talk through a central broker.
Now Click on : https://www.hivemq.com/mqtt/public-mqtt-broker/
You will see like :
Here with clicking the connect button ,
As you update the required document with the exact topic that you have configured before in mqtt configuration.
Note : The topic name must match.
If the ESP32 publishes to:
iot/esp32/dht22
but Node-RED subscribes to:
iot/dht11
Node-RED will not receive the message.
As soon as you publish with the detail it will automatically seen in NODE-RED debug section as shown below :
Till now we CHECKED the flow process now it time to show in the node-red dashboard that has been published from WOKWI platform.
For that create new project, here project is created as “ESP32-MQTT”
Here is the code
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
// Fixed topic strings for easy Node-RED integration
String temperatureTopic = "iot/esp32/dht22/temperature";
String humidityTopic = "iot/esp32/dht22/humidity";
WiFiClient espClient;
PubSubClient mqttClient(espClient);
unsigned long lastSensorRead = 0;
const unsigned long sensorInterval = 5000;
void setupWiFi() {
Serial.println();
Serial.println("Connecting to Wi-Fi...");
Serial.print("SSID: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
unsigned long startTime = millis();
// Wait maximum 15 seconds for Wi-Fi connection
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 15000) {
delay(500);
Serial.print(".");
}
Serial.println();
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Wi-Fi connected!");
Serial.print("ESP32 IP Address: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("Wi-Fi connection failed! Restarting ESP32...");
delay(2000);
ESP.restart();
}
}
void reconnectMQTT() {
while (!mqttClient.connected()) {
Serial.println();
Serial.println("Connecting to MQTT broker...");
// Create unique client ID so broker connection doesn't conflict
String clientId = "ESP32-Wokwi-" + String((uint32_t)ESP.getEfuseMac(), HEX);
Serial.print("Client ID: ");
Serial.println(clientId);
if (mqttClient.connect(clientId.c_str())) {
Serial.println("MQTT connected!");
} else {
Serial.print("MQTT connection failed. Error code: ");
Serial.println(mqttClient.state());
Serial.println("Retrying in 5 seconds...");
delay(5000);
}
}
}
void readAndPublishSensorData() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
// Check if sensor reading failed
if (isnan(temperature) || isnan(humidity)) {
Serial.println();
Serial.println("ERROR: Failed to read DHT22!");
return;
}
// Convert float values to string format
char temperatureString[10];
char humidityString[10];
dtostrf(temperature, 1, 2, temperatureString);
dtostrf(humidity, 1, 2, humidityString);
// Publish to HiveMQ broker
bool temperaturePublished = mqttClient.publish(temperatureTopic.c_str(), temperatureString);
bool humidityPublished = mqttClient.publish(humidityTopic.c_str(), humidityString);
Serial.println();
Serial.println("--- SENSOR READINGS ---");
Serial.print("Temperature: "); Serial.print(temperature, 2); Serial.println(" °C");
Serial.print("Humidity: "); Serial.print(humidity, 2); Serial.println(" %");
Serial.println("--- MQTT PUBLISH STATUS ---");
Serial.print("Temperature: "); Serial.println(temperaturePublished ? "SUCCESS" : "FAILED");
Serial.print("Humidity: "); Serial.println(humidityPublished ? "SUCCESS" : "FAILED");
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println();
Serial.println("ESP32 IoT MQTT PROJECT (Wokwi)");
// Initialize DHT22
dht.begin();
Serial.println("DHT22 initialized.");
// Connect to Wi-Fi
setupWiFi();
// Configure MQTT broker
mqttClient.setServer(mqtt_server, mqtt_port);
Serial.println();
Serial.println("Target MQTT Topics:");
Serial.print("Temperature: "); Serial.println(temperatureTopic);
Serial.print("Humidity: "); Serial.println(humidityTopic);
Serial.println("ESP32 setup completed!");
}
void loop() {
// Ensure Wi-Fi remains connected
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Wi-Fi disconnected!");
setupWiFi();
}
// Ensure MQTT connection remains active
if (!mqttClient.connected()) {
reconnectMQTT();
}
// Process incoming MQTT network packets
mqttClient.loop();
// Non-blocking timer to read sensor every 5 seconds
unsigned long currentMillis = millis();
if (currentMillis - lastSensorRead >= sensorInterval) {
lastSensorRead = currentMillis;
readAndPublishSensorData();
}
}Try to Play Button for the Simulation , while if its longer time to compile and shows a message like this,
You can follow the link for solution : Please Click Here
If simulation start working you will see the output at the terminal of VS Code
For the UI in NODE RED instead of Application
Install Dashboard in order to get the GAUGE and CHART in UI
Look for manage palette as shown below,
then install DASHBOARD
After that you will be able to access GAUGE and CHART and many other data visualization tool
For Configiuration double click on mqtt
To fillup the required value look for
After clicking Connect You Will See Details for
Add these detail to
Also you can change the name as
NEXT
Now TOPIC has been changed according to Humidity and Temperature
NEXT , you look for the data in the debug option as for the visualization
The most important lesson from this project is not simply how to connect a DHT11 sensor.
It is understanding how different components work together to form an IoT system.
We started with a simulated sensor: DHT22
Connected it to: ESP32
Used: MQTT to transport the data.
Used: HiveMQ Cloud as the communication broker.
Used: Node-RED to process the data.
And finally created a: Real-Time Dashboard to visualize the information.
The complete architecture can be summarized as:
Sense → Process → Publish → Broker → Subscribe → Visualize
And the best part is that the entire system can be developed and tested using simulation before purchasing physical hardware.
This makes the project a useful starting point for anyone learning IoT, MQTT, ESP32, Node-RED, and cloud-based sensor communication.
Project Architecture at a Glance
┌──────────────┐
│ DHT22 │
│ Temperature │
│ Humidity │
└──────┬───────┘
│
▼
┌──────────────┐
│ ESP32 │
│ Wokwi │
└──────┬───────┘
│
│ MQTT
▼
┌──────────────┐
│ HiveMQ │
│ MQTT Broker │
└──────┬───────┘
│
│ MQTT
▼
┌──────────────┐
│ Node-RED │
│ Data Process │
└──────┬───────┘
│
▼
┌──────────────┐
│ Dashboard │
│ │
│ Temperature │
│ Humidity │
│ Charts │
└──────────────┘No physical hardware. No complicated backend. Just a simulated ESP32, MQTT, a cloud broker, and Node-RED working together to create a complete IoT system.










