ESP32/Messages on the network/56. MQTT and a broker
No board required

This one is about the wire, not the chip. Nothing below changes with the board you picked, which is why the chip and language switches are not on it. They come back on the ESP32 pages this one sits underneath.

Messages on the network · 56 of 81

MQTT and a broker

The board does not send a message to your phone. It publishes a name to a broker, and the broker works out who cares — which is why you can add a second sensor, or a dashboard, without changing a line of firmware.

/esp32/mqtt-and-a-broker · any board · 12 min read

Publish one message and watch who gets a copy. The board is told nothing about any of them.

Publish once, and see who hears it
home/kitchen/temp
boardbrokerno memoryPhone apphome/kitchen/tempHome Assistanthome/#Logger+/+/temp
Publish tohome/kitchen/temp
3 of three subscribers get a copy. The board sent one message and named a topic. Matching subscribers to it is the broker's job — # takes everything below a level, + takes exactly one level, and the board is told about none of it.

The one idea

With HTTP the board needs an address, a path, and a server that is awake. With MQTT it needs a broker and a topic — a name like home/kitchen/temp. Everybody connects to the broker; nobody connects to anybody else.

That single indirection buys three things:

  • Publishers don't know their subscribers. Add a dashboard, a logger and a phone. The sensor firmware never changes.
  • Nobody has to be awake at the same time. A subscriber that connects an hour later gets the next message — or the last one, with retain.
  • One connection carries everything. Handshake once at boot, then send 30-byte messages for a month.

Topics are a path, not a folder

There is nothing to create. The first publish to home/kitchen/temp makes it exist, and a topic nobody subscribes to costs nothing.

Subscribers use two wildcards:

FilterMatchesDoes not match
home/kitchen/tempexactly thatanything else
home/+/temphome/kitchen/temp, home/garage/temphome/kitchen/oven/temp
home/#everything under homeoffice/desk/temp

+ is exactly one level. # is the rest, and only at the end. The trap in the middle row is that + never matches nothing — a subscriber to home/+/temp will not hear home/temp.

Name topics the way you would name folders, most general first: house/floor/room/device/measurement. You will want to subscribe to a whole floor eventually, and you cannot if the room is the last level.

Retain: the difference between a number and a dash

A broker forgets a message the moment it has delivered it. Publish with the retain flag and it keeps the last one per topic and hands it to anything that subscribes later. Turn it on in the figure and press a dashboard connects now.

Retain state, not events. home/kitchen/temp — yes, a new dashboard should know it is 21.4°. home/doorbell/pressed — no, or every dashboard that opens tomorrow announces yesterday's visitor.

QoS, in one table

QoSPromiseCostUse it for
0at most once, fire and forget1 messageTemperature every 30 s
1at least once, may duplicate2 messagesA command that matters
2exactly once4 messagesAlmost nothing

QoS 0 is the right default for sensors: if a reading is lost, another one is along in thirty seconds. QoS 1 is for the things where losing one is not fine — turning a heater off. Handle the duplicate rather than reaching for QoS 2; make the command idempotent (set/heater = off, not toggle/heater).

What the code looks like

client.setServer("192.168.1.10", 1883);
client.setWill("home/kitchen/status", "offline", true, 1);  // retained
client.connect("kitchen-esp32", user, pass);
client.publish("home/kitchen/status", "online", true);
client.subscribe("home/kitchen/heater/set", 1);

// then, every 30 seconds:
client.publish("home/kitchen/temp", "21.4");   // QoS 0, not retained

client.loop() has to run often. It is not decoration: it is what answers the broker's keepalive pings, and a board that stops answering is dropped in about ninety seconds — after which your publishes go nowhere and no error says so.

Running the broker

Mosquitto on a Raspberry Pi or any always-on box, one apt install and a config file. Two settings are worth doing on day one:

  • Turn off anonymous access. Default Mosquitto lets anything on the network publish anything, including to your heater/set topic.
  • Keep it off the internet. If you need to reach it from outside, use a VPN or a hosted broker with TLS — not a forwarded port.

When MQTT is not the answer

One board and one server that already speaks HTTP: use HTTP, there is nothing to run. A browser page that needs to feel instant: the browser cannot speak MQTT without extra parts, and WebSocket is the shorter road.

Edit this page — content/esp32/mqtt-and-a-broker.mdx

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse ESP32 on the forum