RisalDash RisalDash

Guide · MQTT · IoT

MQTT on ESP32, from zero to Home Assistant

When one sensor needs to reach three apps at once, wiring each pair by hand falls apart fast. MQTT flips it: a device publishes to a topic, and everything that cares subscribes — with a broker in the middle. Here’s why it fits IoT, the three words you actually need (topic, QoS, retain), and the ESP32 code to talk to Home Assistant.

MQTTHome AssistantPubSubClientESP32IoT
MQTT pub/sub: an ESP32 publishes home/temp to a Mosquitto broker; Home Assistant, a phone app and a logger subscribe
Publish once to a topic; every subscriber that cares gets it — no polling, no pairwise wiring.

Why MQTT beats HTTP polling

With plain HTTP, a dashboard asks the device “any news?” on a timer — wasteful, laggy, and it doesn’t scale past a couple of clients. MQTT inverts the flow: the device pushes a value the instant it changes, and the broker fans it out to every subscriber. It’s built for many small messages over flaky, low-power links — exactly IoT. If you’re choosing a transport at all, see Wi-Fi vs the rest first; MQTT rides on top of Wi-Fi here.

Topics, QoS and retain — in plain words

A topic is just a path like home/livingroom/temp; publishers and subscribers rendezvous on it (subscribe with wildcards: home/+/temp). QoS is the delivery guarantee, and retain tells the broker to keep the last value so a new subscriber gets it immediately instead of waiting for the next update.

ConceptWhat it meansUse it for
QoS 0at most once (fire & forget)frequent sensor readings
QoS 1at least once (may duplicate)commands, state changes
QoS 2exactly once (slowest)rarely — critical, one-shot
Retainbroker keeps the last messagecurrent state on connect
Last Willbroker posts if you drop off“offline” detection

A broker in five minutes

MQTT needs a broker in the middle — the post office. The default is Mosquitto: install it on a Raspberry Pi, a NAS, or the same box as Home Assistant (which ships it as a one-click add-on), and you’re done. A hosted broker (HiveMQ, EMQX Cloud) works too if you want nothing local. Point every device at the broker’s IP and port 1883 and they find each other.

The ESP32 side: PubSubClient

On the device, the PubSubClient library is the classic choice. The shape is always the same — connect, subscribe to what you control, publish what you sense, and reconnect when Wi-Fi blips:

connect:    client.connect("esp32-kitchen")        // to the broker
subscribe:  client.subscribe("home/relay/set")     // broker pushes commands here
publish:    client.publish("home/temp", "24.1")    // fire it; subscribers get it
callback:   on message  →  switch the relay        // react without polling

Keep a small reconnect loop in loop() so a dropped link heals itself, and publish sensor values only when they actually change to keep the traffic (and power) low — the same discipline as deep sleep if you’re on a battery.

Home Assistant, without hand-configuring

The magic trick is MQTT discovery: publish one small JSON to a special homeassistant/…/config topic (retained), and Home Assistant creates the entity by itself — no YAML editing, the sensor or switch just appears. Publish your readings to the state topic and control comes back on the command topic. From there it’s dashboards, automations and voice, all for free. Prefer no code at all? ESPHome does MQTT/discovery from YAML.

Want the device to serve its own UI too? A full dashboard from a few lines of C++.