MQTT is the protocol that powers most IoT deployments. Today you'll master it — broker setup, pub/sub, QoS levels, retained messages, and last-will topics.
MQTT broker routes messages between publishers and subscribers. Topic: hierarchical string like home/living-room/temperature. Subscribe with wildcards: home/+/temperature (single level) or home/# (all below). QoS levels: 0 = fire and forget, 1 = at least once (ACK), 2 = exactly once (4-way handshake). QoS 1 is the sweet spot for sensor data.
Retained message: broker stores the last message on a topic. New subscribers immediately receive the latest value — useful for device state. Last Will and Testament (LWT): when a device disconnects unexpectedly, the broker publishes a predefined message to a specified topic. Use this to detect device offline events: subscribe to home/sensor-01/status and get 'offline' when the device loses power.
Mosquitto is the most widely-used open-source MQTT broker. Install: apt install mosquitto mosquitto-clients. Configure authentication: create a password file with mosquitto_passwd -c /etc/mosquitto/passwd username. Enable TLS by pointing Mosquitto to your certificates. Public test broker: broker.hivemq.com:1883 (no auth, for testing only — never production data).
# MQTT publisher and subscriber with paho-mqtt
# pip install paho-mqtt
import json, time, threading
import paho.mqtt.client as mqtt
BROKER = "broker.hivemq.com" # free public broker for testing
PORT = 1883
TOPIC_DATA = "precisionai/demo/sensors"
TOPIC_STATUS = "precisionai/demo/status"
CLIENT_ID = "demo-sensor-01"
# ── Subscriber (runs in background) ─────────────────────────
def on_connect(client, userdata, flags, rc):
print(f"Subscriber connected: {rc}")
client.subscribe(TOPIC_DATA, qos=1)
client.subscribe(TOPIC_STATUS, qos=1)
def on_message(client, userdata, msg):
try:
payload = json.loads(msg.payload.decode())
print(f" [{msg.topic}] temp={payload.get('temp')}°C")
except:
print(f" [{msg.topic}] {msg.payload.decode()}")
sub = mqtt.Client(client_id="demo-subscriber")
sub.on_connect = on_connect
sub.on_message = on_message
sub.connect(BROKER, PORT, keepalive=60)
sub.loop_start()
time.sleep(1)
# ── Publisher ────────────────────────────────────────────────
import random
pub = mqtt.Client(client_id=CLIENT_ID)
# Last Will: auto-publish 'offline' if we disconnect unexpectedly
pub.will_set(TOPIC_STATUS, payload=json.dumps({"status":"offline","id":CLIENT_ID}), qos=1, retain=True)
pub.connect(BROKER, PORT, keepalive=60)
pub.loop_start()
# Announce online (retained so new subscribers see current state)
pub.publish(TOPIC_STATUS, json.dumps({"status":"online","id":CLIENT_ID}), qos=1, retain=True)
print(f"Publishing to {BROKER}:{PORT}/{TOPIC_DATA}")
for i in range(5):
payload = json.dumps({
"device": CLIENT_ID,
"temp": round(22 + random.gauss(0, 1), 1),
"hum": round(50 + random.gauss(0, 5), 1),
"seq": i,
})
result = pub.publish(TOPIC_DATA, payload, qos=1)
result.wait_for_publish()
print(f"Published #{i}: {payload}")
time.sleep(2)
pub.loop_stop()
sub.loop_stop()
print("Done.")
org/location/device/sensor. Never use spaces or special characters except /. Keep topics consistent — automated tools parse them. A common convention: company/site/device-id/metric.sudo apt install mosquitto mosquitto-clients.mosquitto_sub -h localhost -t '#' -v.device/commands, parse JSON like {"led":"on"}, and print the command.--cafile option.Implement MQTT topic ACL (Access Control List). Create two users: 'sensor' that can only publish to 'home/sensors/#', and 'dashboard' that can only subscribe to 'home/#'. Test that sensor user cannot subscribe, and dashboard user cannot publish. Document the mosquitto.conf settings required.
The foundations from today carry directly into Day 3. In the next session the focus shifts to Day 3 — building directly on everything covered here.
Before moving on, verify you can answer these without looking:
Live Bootcamp
Learn this in person — 2 days, 5 cities
Thu–Fri sessions in Denver, Los Angeles, New York, Chicago, and Dallas. $1,490 per seat. June–October 2026.
Reserve Your Seat →