Sitemap

A Real-Time IoT System with ESP32, MQTT & Node-RED

14 min readSep 15, 2026

--

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.

Press enter or click to view image in full size
IoT Temperature & Humidity Monitoring System using MQTT

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:

  1. Laptop
  2. Internet connection
  3. A modern web browser
  4. Basic knowledge of Arduino programming
  5. Basic understanding of MQTT

No physical ESP32 or DHT11/DHT22 is required for this project.

Lets Start With WOKWI Simulation

Press enter or click to view image in full size
Select ESP32 in WOKWI
Press enter or click to view image in full size
Select ESP32
Press enter or click to view image in full size
WOKWI will show the given display.
Press enter or click to view image in full size
Click Add Button to Add DHT Sensor
Press enter or click to view image in full size
Now, Search for DHT sensor
Press enter or click to view image in full size
Sensor Selection

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.

Press enter or click to view image in full size
Circuit Diagram For ESP32 and DHT22 Sensor

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:

  1. DHT sensor library
  2. PubSubClient

Depending on the Wokwi environment, the required library dependencies may also be installed automatically.

For Manually

Press enter or click to view image in full size

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 :

Press enter or click to view image in full size
Press enter or click to view image in full size

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.

Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
This IP address identifies the ESP32 on the local network.

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:

  1. 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:

  1. Username
  2. Password
  3. Sensor data
  4. 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:

http://localhost:1880

Open this address in your browser. You should now see the Node-RED flow editor.

You Will See in your terminal as like below :

Press enter or click to view image in full size

As after “node-red” command you will see in terminal :

Press enter or click to view image in full size

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.

Press enter or click to view image in full size

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

Press enter or click to view image in full size

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.

Press enter or click to view image in full size

With Double Click on MQTT you will get the UI like given image below to setup custom configuration.

Press enter or click to view image in full size

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.

Press enter or click to view image in full size
Press enter or click to view image in full size

Now you will get MQTT connection Settings as shown in the image, these information are need to filled in the NODE-RED MQTT Configuration.

Press enter or click to view image in full size

Now next,

Press enter or click to view image in full size

Next

Press enter or click to view image in full size

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”

Press enter or click to view image in full size
Press enter or click to view image in full size

You Can Edit and Make Custom Configuration By Clicking PEN sign in server section.

Press enter or click to view image in full size

Then

Press enter or click to view image in full size

Then

Press enter or click to view image in full size

Then

Press enter or click to view image in full size

Then

Press enter or click to view image in full size
Connected Sign Must be seen after you deploy.

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/

Press enter or click to view image in full size

You will see like :

Press enter or click to view image in full size
Press enter or click to view image in full size

Here with clicking the connect button ,

Press enter or click to view image in full size

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 :

Press enter or click to view image in full size

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”

Press enter or click to view image in full size

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,

Press enter or click to view image in full size

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

Press enter or click to view image in full size

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,

Press enter or click to view image in full size

then install DASHBOARD

Press enter or click to view image in full size

After that you will be able to access GAUGE and CHART and many other data visualization tool

Press enter or click to view image in full size
Press enter or click to view image in full size

For Configiuration double click on mqtt

Press enter or click to view image in full size

To fillup the required value look for

Press enter or click to view image in full size
Press enter or click to view image in full size

After clicking Connect You Will See Details for

Press enter or click to view image in full size

Add these detail to

Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size

Also you can change the name as

NEXT

Press enter or click to view image in full size

Now TOPIC has been changed according to Humidity and Temperature

Press enter or click to view image in full size
Press enter or click to view image in full size

NEXT , you look for the data in the debug option as for the visualization

Press enter or click to view image in full size

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.

--

--

Written by Er. Sunil Thapa

.NET Engineer | HRMS & FinTech | Robotics & Electronics | Lecturer