A full end-to-end IoT project that reads temperature and humidity from a DHT22 sensor connected to an ESP32, shows them on an OLED screen, publishes them over MQTT, and visualizes everything in a real-time React dashboard with live readings, charts, 7-day predictions, a heat map, and CSV/PDF/Excel export.
Built as a learning project covering the whole stack: hardware → firmware → broker → backend → UI.
ESP32 + DHT22 + OLED
│ publishes JSON {"temperature","humidity"} to topic "iot/dht22" every 2s
▼
MQTT broker (broker.hivemq.com, public)
│ backend subscribes to the same topic
▼
Node.js / Express backend REST :3001 + WebSocket :8080
│ REST: /api/sensor, /api/predictions, /api/humidityPredictions
│ WebSocket: streams the latest reading to the dashboard
▼
React dashboard :3000 (live cards, charts, predictions, heat map, exports)
.
├── primerProyectoIoT.ino # ESP32 firmware (Arduino)
├── conexiones_esp32_dht22_pantallaOled.txt # Wiring reference
└── mqtt-dashboard/
├── backend/ # Express + MQTT + WebSocket server
└── frontend/ # React dashboard (Create React App + Tailwind)
- ESP32 dev board
- DHT22 temperature/humidity sensor
- SSD1306 OLED display (128×64, I²C, address 0x3C)
- Breadboard + jumper wires
| Component | Pin | Connects to |
|---|---|---|
| ESP32 | 3.3V | 3.3V rail on breadboard |
| ESP32 | GND | GND rail on breadboard |
| DHT22 | VCC (+) | 3.3V rail |
| DHT22 | GND (−) | GND rail |
| DHT22 | OUT | GPIO 15 |
| OLED | VCC | 3.3V rail |
| OLED | GND | GND rail |
| OLED | SDA | GPIO 21 |
| OLED | SCL | GPIO 22 |
Reads the DHT22 every 2 seconds, prints the values to the serial monitor, shows
them on the OLED, and publishes them as JSON to the MQTT topic iot/dht22. It
auto-reconnects to both Wi-Fi and the MQTT broker if the connection drops.
Before flashing, open the sketch and set your network credentials:
const char* ssid = "TU_RED_WIFI"; // your Wi-Fi network
const char* password = ""; // your Wi-Fi passwordArduino libraries required: WiFi, DHT sensor library (Adafruit),
Adafruit SSD1306, Adafruit GFX, PubSubClient.
You need Node.js installed. Open two terminals.
cd mqtt-dashboard/backend
npm install
npm start # REST on :3001, WebSocket on :8080cd mqtt-dashboard/frontend
npm install # an .npmrc sets legacy-peer-deps automatically
npm start # opens http://localhost:3000The frontend includes an
.npmrcwithlegacy-peer-deps=truebecause one of the Leaflet heat-map packages declares a React 17 peer dependency while the app runs React 18. The mismatch is harmless; this flag lets npm install cleanly.
You don't need the hardware to try the UI: the prediction charts have a "Ver datos ficticios" button that generates sample data, and the header shows a live WebSocket connection indicator (Conectado / Conectando / Desconectado).
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/sensor |
Latest temperature and humidity |
| GET | /api/predictions |
7-day temperature forecast (linear regression) |
| GET | /api/humidityPredictions |
7-day humidity forecast (linear regression) |
The prediction endpoints return an error object (not an array) until at least two readings have been received. The dashboard guards against this, so it never crashes while waiting for data.
- Sensor history is stored in memory on the backend, so it resets on restart. Adding SQLite or MongoDB would persist it.
- API URLs are hard-coded to
localhost. Move them to an environment variable (REACT_APP_API_URL) before deploying. - The MQTT broker is a free public one; for production use your own broker with authentication.
- The heat map could use real confidence bounds (
upper/lower) computed on the backend instead of placeholders.
ESP32 / Arduino · MQTT (PubSubClient + HiveMQ) · Node.js · Express · ws · React · Tailwind CSS · Chart.js · Recharts · Leaflet · regression-js