MQTT and Node-RED on Raspberry Pi: Visual Automation for ESP32 Sensor Networks
If you've built more than one or two ESP32 sensor nodes, you've probably hit the same wall: each one talks to the world a different way, some post to a spreadsheet, some blink an LED, none of them talk to each other. MQTT and Node-RED fix that by giving every device a common language and a visual place to wire them together. This guide sets up a Mosquitto MQTT broker and Node-RED on a Raspberry Pi, connects an ESP32 sensor node to it, and builds a simple automation flow — the same pattern scales from one sensor to dozens of ESP32 nodes, a Flipper Zero, or any other device on the network.
Why MQTT Instead of Direct HTTP Requests
Most beginner ESP32 tutorials have the device POST directly to a server or cloud API. That works for one device doing one thing, but it doesn't scale — every device needs to know the destination's address, every change requires reflashing firmware, and there's no clean way for multiple things to react to the same event. MQTT solves this with a publish/subscribe model: devices publish small messages to named "topics" on a central broker, and anything interested in that topic subscribes to it without the publisher needing to know who's listening. An ESP32 publishing to home/greenhouse/soil-moisture doesn't care whether that's read by a dashboard, a watering system, or a phone notification — all of them can subscribe independently.
Part 1: Install Mosquitto (the MQTT Broker)
- On a Raspberry Pi running Raspberry Pi OS (headless is fine — see our headless Pi setup guide if you haven't configured SSH access yet), install Mosquitto: sudo apt update && sudo apt install -y mosquitto mosquitto-clients
- Enable it to start on boot: sudo systemctl enable mosquitto
- By default Mosquitto only listens on localhost — for other devices to connect, create /etc/mosquitto/conf.d/local.conf with: listener 1883 allow_anonymous false password_file /etc/mosquitto/passwd
- Create a login: sudo mosquitto_passwd -c /etc/mosquitto/passwd pi (set a password when prompted), then restart: sudo systemctl restart mosquitto
- Test it from the Pi itself in two terminals — subscribe in one: mosquitto_sub -h localhost -u pi -P yourpassword -t test/topic, then publish from the other: mosquitto_pub -h localhost -u pi -P yourpassword -t test/topic -m "hello". You should see "hello" appear in the subscriber terminal.
Never leave allow_anonymous true on a broker reachable outside your LAN — an open broker lets anyone on the network publish fake sensor data or, worse, trigger anything you've wired up to react to a topic.
Part 2: Install Node-RED
- Raspberry Pi OS ships with an official install script: bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
- Enable it on boot: sudo systemctl enable nodered.service, then start it: sudo systemctl start nodered
- Open the editor from another machine on your network at http://<pi-ip>:1880
- From the palette manager (menu → Manage palette → Install), add node-red-dashboard for a simple web dashboard, and confirm node-red-node-mqtt nodes appear by default in the left-hand palette (they're bundled with Node-RED)
Part 3: Get an ESP32 Publishing Sensor Data
Using the Arduino IDE with the PubSubClient library, a minimal ESP32 sketch publishing a temperature reading looks like this:
#include <WiFi.h> #include <PubSubClient.h> const char* ssid = "your-wifi"; const char* password = "your-password"; const char* mqtt_server = "192.168.1.X"; // your Pi's IP WiFiClient espClient; PubSubClient client(espClient); void setup() { WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) delay(500); client.setServer(mqtt_server, 1883); } void loop() { if (!client.connected()) { client.connect("esp32-greenhouse", "pi", "yourpassword"); } float temp = readTemperature(); // your sensor read char payload[8]; dtostrf(temp, 4, 1, payload); client.publish("home/greenhouse/temperature", payload); client.loop(); delay(60000); // publish once a minute }For battery-powered nodes, combine this with deep sleep between publishes rather than a fixed delay loop — see our ESP32 deep sleep guide for the pattern.
Part 4: Build a Node-RED Flow
In the Node-RED editor, drag an mqtt in node onto the canvas, double-click it, and set the server to your Pi's own address with the topic home/greenhouse/temperature. Wire its output to a debug node first to confirm messages are arriving in the sidebar, then build out from there:
- Wire the mqtt-in node to a gauge or chart node from the dashboard palette to get a live web dashboard at http://<pi-ip>:1880/ui with zero front-end code
- Add a switch node to branch on the payload value (e.g., "if temperature > 85, continue") feeding into an mqtt out node that publishes to a topic like home/greenhouse/fan, which a second ESP32 subscribes to and uses to switch a relay
- Add a notification flow using an email or Pushover node so you get an alert if a sensor stops reporting for too long (use a trigger node set to fire if no message arrives within a timeout window)
A Simple, Genuinely Useful Flow: Cross-Device Automation
This is where the pattern earns its keep: with Home Assistant, a Frigate NVR, or a Flipper Zero's sub-GHz output all capable of publishing to or being triggered by MQTT, a single Node-RED flow can react across all of them without any device needing to know about the others. A common example — a soil moisture ESP32 node publishes to garden/soil, Node-RED watches for the value dropping below a threshold, publishes to garden/pump to run a second ESP32's relay-driven water pump for a fixed duration, and separately posts a summary to a dashboard chart. No cloud service, no per-device coding beyond the initial publish/subscribe, and adding a third or fourth node later is just another wire in the flow editor.
Troubleshooting
SymptomLikely Cause ESP32 can't connect to brokerWrong IP/port, or Mosquitto still bound to localhost only — check listener 1883 is present in the conf.d file mqtt-in node shows "connecting" indefinitely in Node-REDBroker credentials not entered on the node's Security tab, or allow_anonymous false with no username/password configured Messages published but nothing in debug sidebarTopic mismatch — MQTT topics are case-sensitive and exact-match unless using wildcards (+ and #) Node-RED dashboard blank at /uinode-red-dashboard not installed, or no widget nodes deployed to the flow yetOnce the broker and Node-RED are running, this becomes the connective tissue for every future ESP32 project — new sensor nodes just need a broker IP and a topic name, and new automations are a few dragged-and-wired nodes rather than new firmware.
Related Guides
- Tying It Together: Pi + ESP32 + Flipper Home Automation Hub
- Homebridge on Raspberry Pi: Bringing Non-HomeKit Devices and DIY ESP32 Sensors into Apple Home
- Build a Wall-Mounted Maker Dashboard: Aggregating Your Print Farm, Security, and Home Server on One CYD Panel
- Scaling Up: A Multi-Node LoRa Sensor Network with a Raspberry Pi Gateway
- Build a Wired ESP32 IoT Sensor Node with W5500 Ethernet for Reliable Uptime
- Automated Plant Watering System with Raspberry Pi
- Running Home Assistant on a Raspberry Pi 4
- Auto-Backup Your Raspberry Pi SD Card to a Network Share