← Back to Garden
evergreen ·
mqtt iot networking

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/#"

Resources