Learning Goals 5 min
Arduino IoT Cloud was easy because it hid everything. Underneath, IoT Cloud (and almost every commercial smart-home product) speaks MQTT — a tiny, fast, reliable pub/sub protocol that runs on top of TCP/IP. Today you learn its four concepts before wiring up a real broker tomorrow. By the end of this lesson you will:
- Define the four MQTT concepts: broker, client, topic, message.
- Explain QoS levels 0, 1, 2 and pick the right one for "sensor stream" vs "turn off the pump".
- Describe retained messages and last-will, the two features that make MQTT pleasant for IoT.
Warm-Up 10 min
No hardware today — just the model. Tomorrow we publish from an ESP to a real broker.
The pub/sub pattern in everyday terms
HTTP is request/response: client asks, server answers, both wait around. MQTT is publish/subscribe: clients drop messages into "mailboxes" (topics), and any other client subscribing to that mailbox automatically receives a copy. The middleman is the broker — a small server, often free or self-hosted, that fan-outs messages.
Why IoT loves it
- Tiny on-the-wire footprint (~2-byte header).
- Stays connected over hours/days (one TCP socket per device).
- One device can listen to thousands of topics or publish to one.
- No client needs to know about another client — broker decouples everyone.
New Concept · The four pieces 25 min
1. The broker
A small server program. The most popular open source one is Mosquitto. Free public brokers include test.mosquitto.org, broker.hivemq.com — fine for school projects, not production.
Brokers run on:
- Your laptop (install Mosquitto for testing).
- A Raspberry Pi on your home network (the standard Home Assistant setup).
- A cloud service (HiveMQ Cloud, AWS IoT Core, Adafruit IO).
2. The client
Any device that connects to a broker. Each client has a unique client ID (a string, like a username). Clients can both publish and subscribe.
Your ESP is a client. Home Assistant is a client. Your phone app might be a client. They never talk to each other directly — all messages flow through the broker.
3. The topic
A slash-separated label that names a kind of message. Examples:
home/livingroom/temperature home/garage/door sensors/plant1/moisture robot/wheels/left/speed
Topics are hierarchical. Wildcards:
+matches one level:home/+/temperaturematcheshome/livingroom/temperatureandhome/bedroom/temperaturebut NOThome/livingroom/temp/raw.#matches everything below (multi-level):home/#matches every topic underhome/.
4. The message
The payload sent under a topic. MQTT doesn't care about content — bytes are bytes. By convention, smart-home products send JSON payloads ({"temp": 22.5}) or plain text (22.5 or ON).
Quality of Service (QoS)
| QoS | Guarantee | Use |
|---|---|---|
| 0 (at most once) | Fire and forget. Message may be lost on a flaky network. | Sensor streams where losing one update is fine. |
| 1 (at least once) | Broker acknowledges. May arrive twice on retry. | Most cases. Default for commands. |
| 2 (exactly once) | Two-step handshake guarantees one delivery. | Critical commands (e.g. payment, irreversible actions). Slowest. |
Pick the lowest QoS that's safe. Sensor streams at QoS 0; commands at QoS 1; rare critical things at QoS 2.
Retained messages
Normally, if a subscriber connects AFTER a publisher sent a message, the subscriber missed it. With the retain flag, the broker keeps the last message on each topic; new subscribers receive it immediately on subscribe.
Use case: sensor reports temperature once a minute (retained). Phone opens dashboard → broker delivers the most recent reading instantly, no waiting for the next push.
Last Will and Testament (LWT)
When a client connects, it can register a "will": "if I disconnect ungracefully (no proper goodbye), publish this message on this topic."
Use case: ESP-based sensor sets LWT = "offline" on topic home/plant1/status. On boot it publishes "online" (retained). If WiFi drops, the broker auto-publishes "offline" after a timeout. Dashboards see the device's connection state in real time.
The mental picture
Think of MQTT like a school bulletin board:
- The bulletin board = broker.
- Anyone reading = subscriber.
- Anyone posting = publisher.
- The categorised sections (Sports, Drama, Lost Property) = topics.
- The actual notes = messages.
- "Last seen Tuesday: closed" = retained message.
- "If I'm absent without notice, post that I'm sick" = last will.
Worked Example · Trace a smart-home message 20 min
Imagine your home Mosquitto broker running on a Raspberry Pi. Three devices:
- ESP-A: living-room temperature sensor.
- ESP-B: kitchen light switch.
- Home Assistant (Raspberry Pi dashboard).
Scenario 1 — Sensor publishes a reading
- ESP-A reads temperature → 22.5 °C.
- ESP-A publishes
{"value": 22.5}to topichome/livingroom/tempwith QoS 0 and retain=true. - Broker stores it as the retained message for that topic.
- Home Assistant is subscribed to
home/+/temp→ receives the message → updates its dashboard.
Scenario 2 — Phone toggles a light
- User taps a button in Home Assistant's app.
- Home Assistant publishes
ONtohome/kitchen/light/setwith QoS 1. - Broker receives, ACKs to Home Assistant, fans out to subscribers.
- ESP-B (subscribed to
home/kitchen/light/set) receives → switches the relay. - ESP-B publishes
ONtohome/kitchen/light/stateto confirm. Home Assistant's UI shows it as on.
Scenario 3 — ESP-A loses WiFi
- ESP-A registered LWT on connect: topic
home/livingroom/temp/status, messageoffline, retain=true. - WiFi drops. Broker waits ~30 s (keep-alive timeout).
- Broker publishes
offlinetohome/livingroom/temp/statuson its own. - Home Assistant's "living room sensor" indicator turns red.
- When ESP-A comes back, it publishes
online→ indicator goes green.
Why this is so much nicer than HTTP polling
- ESP-A pushes once per minute, not every second.
- ESP-B receives commands in < 100 ms.
- Connection state visible to all parties without polling.
- One broker can handle hundreds of devices.
- One TCP socket per device, kept alive — no reconnect overhead per message.
Try It Yourself · Paper exercises 15 min
Subscriber pattern: home/+/light/state. Which of these messages would it receive?
home/kitchen/light/statehome/garage/light/statehome/kitchen/light/dimmer/stateoffice/light/state
Reveal
Receives: kitchen/light/state and garage/light/state. NOT the dimmer (extra level). NOT office (doesn't match home/+).
A doorbell publishes "pressed" on a topic. What QoS?
Reveal
QoS 1 (at least once). Losing a doorbell event is bad; receiving it twice is OK (the dashboard / phone shows two notifications — annoying but recoverable). QoS 2 is overkill.
Do you publish a temperature reading with retain=true or retain=false?
Reveal
retain=true. New dashboards opening should see the current value without waiting for the next push. The opposite case (an event like a button press) should NOT retain — a dashboard opening shouldn't trigger past events.
Your plant monitor goes offline when batteries die. Design the topic + payload for its LWT.
Reveal
Topic: home/plants/garden/status. Payload: offline. Retain: true. Then on connect, publish online (retained) to the same topic. The dashboard shows the current value of that topic; subscribed Home Assistant alerts on transitions.
Design a topic structure for a fridge / freezer combo with two compartments, each reporting temperature and door state.
Reveal
Many good answers. One:
home/kitchen/fridge/main/temperature home/kitchen/fridge/main/door home/kitchen/fridge/freezer/temperature home/kitchen/fridge/freezer/door home/kitchen/fridge/status (online/offline)
Same shape for any room / appliance pair. A subscriber listening to home/+/fridge/+/temperature sees every compartment of every fridge. Consistent naming = clean MQTT.
Mini-Challenge · Sketch the topology 10 min
- Draw a square in the middle = Broker.
- Draw three circles around it = three IoT devices.
- Label each device's "publishes" and "subscribes" topics.
- Draw arrows showing the message flow for a typical scenario (e.g. user toggles light).
This diagram is the "system architecture" of any smart home. Tape it next to your wiring diagram.
Recap 5 min
MQTT = pub/sub through a broker. Four pieces: broker, client, topic, message. Wildcards + and #. QoS 0 / 1 / 2 trade reliability for speed. Retain = "keep the last one for new subscribers". LWT = "auto-publish this if I die without saying goodbye". Tomorrow we'll connect a real ESP to a public broker and publish our first message.
- MQTT
- Message Queuing Telemetry Transport — lightweight pub/sub protocol designed for IoT. Tiny header, runs over TCP, used by Home Assistant, AWS IoT, Adafruit IO, and most commercial smart-home gear.
- Broker
- Server that receives published messages and fans them out to subscribers. Mosquitto is the open-source standard.
- Client
- Any device connected to a broker. Identified by a unique client ID.
- Topic
- Slash-separated label naming a message channel. Hierarchical, case-sensitive.
- Wildcards
+= single level,#= multi-level (rest of the tree). Only allowed in subscribe topics, not publish.- QoS (Quality of Service)
- 0 = at most once, 1 = at least once, 2 = exactly once. Higher = more reliable, slower.
- Retain
- Broker keeps the last message on each retained topic; new subscribers get it on subscribe.
- Last Will and Testament (LWT)
- A message the broker auto-publishes if a client disconnects without a clean goodbye. The IoT "heartbeat" pattern.
- Keep-alive
- Interval at which clients send a ping to confirm they're alive. Broker triggers LWT after a missed ping.
- Mosquitto
- The most popular open-source MQTT broker. Runs on Raspberry Pi, laptops, cloud VMs. Free.
Homework 5 min
- Install MQTT Explorer (free desktop app — Mac/Win/Linux). Connect to
test.mosquitto.orgon port 1883. - Subscribe to
#. Watch the firehose of public test traffic. - Publish your own message to
advaslearning/<your-name>/hello. Take a screenshot. - Read ahead to ARD-L04-14 (PubSubClient Library). Tomorrow we publish from an ESP.