MQTT — le protocole publish/subscribe de l'IoT¶
Léger, asynchrone et conçu pour les liens instables : MQTT est devenu le standard de facto de la communication applicative IoT, du capteur embarqué aux plateformes cloud à des millions de connexions.
Modèle publish/subscribe¶
MQTT repose sur un découplage total entre producteurs et consommateurs de données via un broker central. Un client publie un message sur un topic ; tous les clients abonnés à ce topic reçoivent le message. Ni le publisher ni les subscribers ne se connaissent directement.
graph LR
S1[Capteur température] -- publish\nusine/zone-a/temp --> B((Broker\nMQTT))
S2[Capteur humidité] -- publish\nusine/zone-a/hum --> B
B -- subscribe\nusine/zone-a/# --> D1[Dashboard SCADA]
B -- subscribe\nusine/+/temp --> D2[Alarme thermique]
B -- subscribe\n# --> D3[Archiveur données] Topics hiérarchiques¶
Les topics sont des chaînes UTF-8 séparées par /. La hiérarchie est libre et conventionnelle :
Wildcards¶
| Wildcard | Symbole | Niveau | Exemple |
|---|---|---|---|
| Un seul niveau | + | Unique | usine/+/temp → zone-a, zone-b… |
| Tous les niveaux suivants | # | Terminal | usine/# → tout ce qui commence par usine/ |
Le # ne peut apparaître qu'en fin de pattern. Un abonnement # seul récupère tous les messages du broker.
Niveaux de QoS¶
MQTT définit trois niveaux de garantie de livraison. Le choix impacte directement la fiabilité, la consommation réseau et la charge du broker.
QoS 0 — At most once (fire and forget)¶
sequenceDiagram
participant P as Publisher
participant B as Broker
participant S as Subscriber
P->>B: PUBLISH (QoS 0)
B->>S: PUBLISH (QoS 0)
Note over P,S: Aucun accusé. Message peut être perdu. Usage : télémetrie haute fréquence où une perte occasionnelle est acceptable (température toutes les 5 s, GPS).
QoS 1 — At least once¶
sequenceDiagram
participant P as Publisher
participant B as Broker
participant S as Subscriber
P->>B: PUBLISH (QoS 1, PacketID=42)
B->>P: PUBACK (PacketID=42)
B->>S: PUBLISH (QoS 1, PacketID=42)
S->>B: PUBACK (PacketID=42)
Note over P,S: Garanti livré ≥1 fois. Doublons possibles. Usage : alertes, commandes où la perte est inacceptable mais le doublon gérable.
QoS 2 — Exactly once¶
sequenceDiagram
participant P as Publisher
participant B as Broker
participant S as Subscriber
P->>B: PUBLISH (QoS 2, PacketID=7)
B->>P: PUBREC (PacketID=7)
P->>B: PUBREL (PacketID=7)
B->>P: PUBCOMP (PacketID=7)
B->>S: PUBLISH (QoS 2, PacketID=7)
S->>B: PUBREC (PacketID=7)
B->>S: PUBREL (PacketID=7)
S->>B: PUBCOMP (PacketID=7)
Note over P,S: 4 échanges par message. Exactement une livraison. Usage : transactions financières, commandes d'actionneurs critiques, ordres de production.
| QoS | Livraisons | Échanges réseau | Latence | Cas d'usage |
|---|---|---|---|---|
| 0 | 0 ou 1 | 1 | Minimale | Télémetrie fréquente |
| 1 | ≥ 1 | 2 | Faible | Alertes, commandes |
| 2 | Exactement 1 | 4 | Plus élevée | Transactions critiques |
Retain et Last Will and Testament¶
Retain messages¶
Un message publié avec le flag retain=true est conservé par le broker sur ce topic. Tout nouveau subscriber reçoit immédiatement ce dernier message retenu, même s'il s'abonne après la publication.
Cas d'usage typique : état courant d'un device (online/offline, dernière valeur connue d'un capteur) disponible à tout nouvel abonné sans attendre la prochaine publication.
Last Will and Testament (LWT)¶
À la connexion, un client peut déclarer un message de «testament» : topic, payload, QoS et retain. Si la connexion est rompue de façon anormale (timeout keepalive, coupure réseau), le broker publie automatiquement ce message.
# Exemple de LWT
Topic : fleet/camion-17/status
Payload : {"state": "offline", "reason": "connection_lost"}
QoS : 1
Retain : true
Ce mécanisme est fondamental pour la détection de déconnexion involontaire dans les flottes IoT.
Brokers MQTT — comparatif¶
| Broker | Licence | Mémoire | Clustering | Auth/TLS | MQTT 5 | Points forts |
|---|---|---|---|---|---|---|
| Mosquitto | EPL 2.0 | < 2 Mo | Non (bridge) | Oui | Oui (≥2.0) | Ultra-léger, embarqué, Raspberry Pi |
| EMQX | Apache 2 / Commercial | ~50 Mo | Oui (Erlang) | Oui | Oui | 100M+ connexions, plugins Kafka/DB |
| VerneMQ | Apache 2 | ~30 Mo | Oui (Erlang) | Oui | Partiel | Erlang OTP, écriture plugins Lua |
| HiveMQ | Commercial | ~200 Mo | Oui | Oui | Oui | Certifié industries, extensions Java |
| NanoMQ | MIT | < 1 Mo | Non | Oui | Oui | Edge ultra-léger, multi-thread |
Mosquitto s'impose sur les gateways embarquées (OpenWRT, Raspberry Pi) grâce à son empreinte mémoire inférieure à 2 Mo. EMQX cible les déploiements cloud à très haute disponibilité avec son cluster Erlang.
MQTT 5.0 — nouvelles fonctionnalités clés¶
La version 5.0 (2019) apporte des fonctionnalités manquantes en 3.1.1, notamment pour les déploiements industriels à grande échelle.
Shared subscriptions¶
Plusieurs consommateurs partagent la charge d'un topic sans recevoir de doublons :
Le broker distribue chaque message à un seul membre du groupe (round-robin ou aléatoire). Permet le scaling horizontal des consommateurs.
Flow control¶
Le client annonce son Receive Maximum à la connexion : nombre maximum de messages QoS 1/2 en vol simultanément. Évite la saturation des clients lents.
Topic alias¶
Remplace un topic long par un entier court pour réduire le overhead sur les liens contraints. L'alias est négocié à la connexion.
Reason codes¶
Chaque ACK inclut un code de raison détaillé (succès, non autorisé, topic invalide…). En 3.1.1, les SUBACK se limitaient à 0x00/0x80.
User properties¶
Paires clé/valeur arbitraires dans les headers : métadonnées, corrélation, traçabilité sans toucher au payload.
| Fonctionnalité | MQTT 3.1.1 | MQTT 5.0 |
|---|---|---|
| Shared subscriptions | Non | Oui |
| Reason codes détaillés | Non | Oui (45 codes) |
| Topic alias | Non | Oui |
| Flow control | Non | Oui |
| User properties | Non | Oui |
| Message expiry | Non | Oui |
| Session expiry configurable | Non | Oui |
| Request/Response natif | Non | Oui |
Sparkplug B — MQTT industriel¶
Sparkplug B (spécification Cirrus Link / Eclipse Foundation) définit un namespace et un encodage au-dessus de MQTT 3.1.1 pour les environnements SCADA/IIoT.
Namespace¶
Exemples :
spBv1.0/Usine-A/NBIRTH/PLC-01
spBv1.0/Usine-A/DDATA/PLC-01/Capteur-Temp
spBv1.0/Usine-A/NDEATH/PLC-01
Types de messages¶
| Type | Signification |
|---|---|
| NBIRTH | Nœud edge en ligne, publie toutes ses metrics |
| NDEATH | Nœud edge hors ligne (LWT) |
| DBIRTH | Device connecté au nœud, metrics initiales |
| DDEATH | Device déconnecté |
| NDATA | Données télémétriques du nœud (delta) |
| DDATA | Données télémétriques du device (delta) |
| NCMD | Commande vers un nœud |
| DCMD | Commande vers un device |
Encodage Protobuf¶
Le payload est sérialisé en Protocol Buffers (binaire compact) avec un schéma Sparkplug défini. Chaque metric inclut : nom, type, valeur, timestamp, qualité. Les BIRTH publient toutes les metrics ; les DATA publient uniquement les deltas (valeurs modifiées).
Birth/Death certificates¶
Le mécanisme BIRTH/DEATH reconstruit l'état complet de l'infrastructure à tout moment : un nouveau subscriber peut rejoindre et connaître immédiatement l'état de tous les équipements. C'est la principale limite de MQTT 3.1.1 vanilla (pas de modèle d'état natif) que Sparkplug résout.
Ce qu'il faut retenir¶
- MQTT est asynchrone et découplé : publisher et subscriber ne se connaissent pas, le broker est l'intermédiaire unique.
- Le choix du QoS (0/1/2) équilibre fiabilité, overhead et latence — QoS 2 n'est justifié que pour des transactions réellement critiques.
- LWT + retain forment le mécanisme de base pour suivre l'état de connexion des devices.
- MQTT 5.0 apporte les shared subscriptions, le flow control et les reason codes essentiels pour les déploiements à grande échelle.
- Sparkplug B ajoute un namespace et un modèle d'état complet (BIRTH/DEATH/DATA) pour les cas SCADA/IIoT.
Chapitre suivant : CoAP & protocoles contraints — REST sur UDP pour les microcontrôleurs les plus limités en ressources.