Day 2 of 5
⏱ ~60 minutes
IoT in 5 Days — Day 2

MQTT and Protocols

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 Concepts

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 Messages and LWT

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 Setup

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).

python
# 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.")
💡
Topic naming conventions matter. Use a hierarchy: 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.
📝 Day 2 Exercise
Build a Multi-Device MQTT Network
  1. Install Mosquitto locally: sudo apt install mosquitto mosquitto-clients.
  2. Run the publisher script pointing to localhost. In a second terminal, subscribe: mosquitto_sub -h localhost -t '#' -v.
  3. Add authentication: create a password file, configure mosquitto.conf to require passwords, test that unauthenticated connections fail.
  4. Implement a command subscriber: subscribe to device/commands, parse JSON like {"led":"on"}, and print the command.
  5. Add TLS: generate a self-signed CA and server certificate with openssl, configure Mosquitto to use them, test with --cafile option.

Day 2 Summary

  • MQTT: pub/sub, topics are hierarchical strings, broker routes between publishers and subscribers
  • QoS 1 (at-least-once with ACK) is the right choice for sensor data — QoS 0 loses messages, QoS 2 is slow
  • Retained messages and LWT enable device state tracking without extra heartbeat logic
  • Authenticate your broker in production — public brokers are for development only
Challenge

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.

Finished this lesson?