MQTT Protocol
MQTT (Message Queuing Telemetry Transport) is a lightweight publish/subscribe messaging protocol designed for IoT and constrained devices.
Core Concepts
Publish/Subscribe Model
Unlike HTTP (request/response), MQTT uses pub/sub:
Publishers ──► Broker ──► Subscribers
(routes)
- Publishers send messages to topics
- Subscribers listen to topics
- Broker routes messages between them
Publishers don't know about subscribers and vice versa - they're decoupled.
Topics
Topics are hierarchical strings like file paths:
car/telemetry
car/errors
home/living-room/temperature
sensor/+/temperature <- + is single-level wildcard
sensor/# <- # is multi-level wildcard
Why MQTT for IoT?
| Feature | Benefit |
|---|---|
| Small packet size | Low bandwidth usage |
| Persistent connections | No reconnect overhead |
| QoS levels | Reliability guarantees |
| Retained messages | New subscribers get last value |
| Last Will | Detect disconnections |
| Lightweight | Runs on microcontrollers |
QoS Levels
| Level | Name | Guarantee |
|---|---|---|
| 0 | At most once | Fire and forget, may lose messages |
| 1 | At least once | Guaranteed delivery, may duplicate |
| 2 | Exactly once | Guaranteed single delivery (slowest) |
For car telemetry, QoS 1 is ideal - we want reliability but can tolerate occasional duplicates.
MQTT Packet Structure
A minimal MQTT PUBLISH packet:
Fixed Header (2 bytes)
├── Packet type (PUBLISH = 3)
├── QoS level
├── Retain flag
└── Remaining length
Variable Header
├── Topic name length (2 bytes)
├── Topic name (UTF-8)
└── Packet ID (for QoS > 0)
Payload
└── Message data
In Our Project
ESP32 as Publisher
// Connect to broker
mqttClient.connect("esp32-car", username, password);
// Publish telemetry
mqttClient.publish("car/telemetry", "{\"rpm\":2500,\"speed\":80}");
Telegraf as Subscriber
Telegraf subscribes to car/telemetry and writes to InfluxDB:
[[inputs.mqtt_consumer]]
servers = ["tcp://localhost:1883"]
topics = ["car/telemetry"]
data_format = "json"
Message Flow
ESP32 publishes to "car/telemetry"
│
▼
Mosquitto Broker
│
├──► Telegraf (writes to InfluxDB)
├──► Future: Mobile app
└──► Future: Alert service
Retained Messages
When a message is published with retain=true, the broker stores it. New subscribers immediately receive the last retained message.
Use case: If Grafana dashboard restarts, it immediately gets the last telemetry reading.
Last Will and Testament (LWT)
When connecting, a client can set a "will" message that the broker publishes if the client disconnects unexpectedly:
mqttClient.connect("esp32-car", username, password,
"car/status", // will topic
1, // will QoS
true, // will retain
"offline" // will message
);
When ESP32 disconnects (car turned off), broker publishes "offline" to car/status.
Mosquitto Commands
# Subscribe to all car topics
mosquitto_sub -h localhost -t "car/#" -v
# Publish a test message
mosquitto_pub -h localhost -t "car/test" -m "hello"
# Subscribe with username/password
mosquitto_sub -h localhost -u user -P pass -t "car/#"