Automatisation IoT

Surveillance de la chaîne du froid avec l'IoT : télémétrie MQTT cellulaire et alertes de rupture de température

Maintenez les produits frais et surgelés dans leur plage de température du dépôt à la livraison. Ce guide conçoit un système de surveillance de la chaîne du froid avec des passerelles MQTT cellulaires, un tampon store-and-forward et des alertes de rupture basées sur la durée.

Schéma de surveillance de la chaîne du froid avec un camion frigorifique et un conteneur envoyant des données de température via MQTT cellulaire vers un tableau de bord d'alertes
Essayez-le sur votre propre broker MQTTObtenez un broker MQTT privé et managé avec l’offre Free et partez d’exemples de code prêts à l’emploi.
Essayer gratuitement Exemples de code Aucune carte bancaire requise

La surveillance de la chaîne du froid consiste à prouver que des denrées réfrigérées, des vaccins ou des produits biologiques ne sont jamais sortis de leur plage de température entre le dépôt et le client, et à réagir vite quand cela arrive. Dans cet article, vous allez concevoir un système de surveillance pour camions et conteneurs frigorifiques qui envoie les données de température via MQTT cellulaire, traverse les zones blanches sans perdre de mesures et déclenche des alertes de rupture en fonction de la durée de dépassement d'une limite plutôt qu'à chaque pic isolé.

Ce que la surveillance de la chaîne du froid doit prouver

L'enregistrement de la température pendant le transport s'adresse à deux publics. Les équipes d'exploitation ont besoin d'informations en direct pour qu'un chauffeur puisse refermer une porte entrouverte ou réagir à un groupe frigorifique défaillant avant que le chargement ne soit perdu. Les équipes qualité ont besoin d'un historique complet après le trajet, souvent pour satisfaire les clients et les exigences de bonnes pratiques de distribution, montrant chaque mesure avec son heure et sa position.

Ces deux besoins guident toute la conception :

Exigence Pourquoi c'est important Conséquence sur la conception
Visibilité en direct Intervenir avant que le produit soit endommagé Connectivité cellulaire, télémétrie MQTT toutes les quelques minutes
Aucun trou dans l'historique Une heure manquante peut invalider une expédition Tampon store-and-forward sur l'équipement
Horodatages fiables L'ordre et la durée des ruptures doivent être prouvables Horodatage au moment de la mesure, pas à l'arrivée
Contexte La porte était-elle ouverte ? Où se trouvait le camion ? Capteurs de porte et GPS en plus de la température
Alertes pertinentes Les cycles de dégivrage et les ouvertures de porte provoquent de brefs pics Règles de rupture basées sur la durée

Le matériel embarqué dans le véhicule

Une installation typique comporte trois éléments :

  1. Des sondes de température dans la zone de chargement, généralement deux ou plus : une près de l'évaporateur et une à l'arrière près des portes, là où l'air chaud entre. Les enregistreurs BLE sans fil sont courants pour le suivi au niveau de la palette ; les sondes filaires conviennent aux installations frigorifiques fixes.
  2. Une passerelle télématique avec un modem LTE-M, NB-IoT ou LTE et un GPS. Il peut s'agir d'un boîtier du commerce ou d'une petite carte Linux équipée d'un HAT cellulaire. Elle lit les sondes, met les données en tampon et publie en MQTT.
  3. Des capteurs d'ouverture de porte, pour corréler chaque hausse de température avec une ouverture.

La passerelle est le seul équipement qui parle au broker. Même une longue remorque remplie d'enregistreurs BLE sur palettes se résume à une seule connexion MQTT.

Conception des topics pour la surveillance de la chaîne du froid

Organisez par actif de la flotte plutôt que par trajet ; les trajets sont des métadonnées dans le payload :

coldchain/<fleet>/<asset-id>/telemetry        {"ts":1760600000,"t_front":3.8,"t_rear":4.6,"door":"closed","lat":41.01,"lon":28.97,"trip":"TR-8812"}
coldchain/<fleet>/<asset-id>/status           retained {"online":true,"fw":"1.4.2","battery_v":12.6}
coldchain/<fleet>/<asset-id>/alarm            {"type":"excursion","probe":"t_rear","max":9.4,"duration_s":1260,"trip":"TR-8812"}
coldchain/<fleet>/<asset-id>/config           retained {"min":2.0,"max":8.0,"grace_s":900}

Retenir le topic config est une astuce élégante. La passerelle s'y abonne à la connexion ; passer un chargement de frais à surgelé se fait donc par une seule publication retenue depuis le système de répartition, et une passerelle qui redémarre récupère immédiatement ses limites.

Code de la passerelle avec store-and-forward

La couverture cellulaire sur les autoroutes, dans les tunnels et dans les ports est inégale. La passerelle doit continuer à échantillonner hors ligne et tout envoyer au retour de la liaison. Le script Python ci-dessous utilise paho-mqtt 2.x, MQTT 5 et une file SQLite sur la passerelle. Il cible le serveur MQTT public gratuit pour que vous puissiez l'essayer sur n'importe quel ordinateur ; remplacez read_probes() par votre code capteur réel.

import json
import random
import sqlite3
import time
import paho.mqtt.client as mqtt

PREFIX = "connectmq/demo/f2q7b5"          # your own random prefix
ASSET = "TRK-104"
BASE = f"{PREFIX}/coldchain/fleet1/{ASSET}"
SAMPLE_EVERY = 60                          # seconds
db = sqlite3.connect("buffer.db")
db.execute("CREATE TABLE IF NOT EXISTS q (id INTEGER PRIMARY KEY, payload TEXT)")
connected = False
limits = {"min": 2.0, "max": 8.0, "grace_s": 900}

def read_probes():
    # replace with real sensors; values here simulate a chilled load
    return {"t_front": round(random.uniform(3, 5), 1), "t_rear": round(random.uniform(3.5, 6), 1),
            "door": "closed"}

def on_connect(client, userdata, flags, reason_code, properties):
    global connected
    connected = not reason_code.is_failure
    if connected:
        client.subscribe(f"{BASE}/config", qos=1)
        client.publish(f"{BASE}/status", json.dumps({"online": True}), qos=1, retain=True)

def on_disconnect(client, userdata, flags, reason_code, properties):
    global connected
    connected = False

def on_message(client, userdata, msg):
    limits.update(json.loads(msg.payload))

def flush(client, batch=50):
    rows = db.execute("SELECT id, payload FROM q ORDER BY id LIMIT ?", (batch,)).fetchall()
    for row_id, payload in rows:
        info = client.publish(f"{BASE}/telemetry", payload, qos=1)
        info.wait_for_publish(timeout=10)
        if not info.is_published():
            return                           # link dropped; keep remaining rows
        db.execute("DELETE FROM q WHERE id = ?", (row_id,))
        db.commit()

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"gw-{ASSET}-f2q7b5",
                     protocol=mqtt.MQTTv5)
client.will_set(f"{BASE}/status", json.dumps({"online": False}), qos=1, retain=True)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message
client.reconnect_delay_set(min_delay=2, max_delay=120)
client.connect_async("broker.connectmq.com", 1883, keepalive=120)
client.loop_start()

while True:
    reading = {"ts": int(time.time()), "trip": "TR-8812", **read_probes()}
    db.execute("INSERT INTO q (payload) VALUES (?)", (json.dumps(reading),))
    db.commit()
    if connected:
        flush(client)
    time.sleep(SAMPLE_EVERY)

Chaque mesure passe d'abord par la file et n'est supprimée qu'une fois acquittée par le broker en QoS 1. Le tampon devient ainsi la source de vérité : coupures de courant, redémarrages et longues zones blanches ne peuvent pas créer de trous, et le champ ts enregistre le moment de la mesure plutôt que celui de son arrivée. Pour en savoir plus sur les garanties de livraison, consultez les niveaux de QoS MQTT expliqués.

Des alertes de rupture qui ignorent le bruit

Une règle naïve du type « alerter si la température dépasse 8 °C » se déclenche à chaque ouverture des portes lors d'un arrêt de livraison ou à chaque dégivrage de l'évaporateur. Une véritable alerte de chaîne du froid tient compte de la durée : elle ne se déclenche que lorsqu'une sonde est restée hors plage plus longtemps qu'une période de grâce.

import json
import paho.mqtt.client as mqtt

PREFIX = "connectmq/demo/f2q7b5"
LIMITS = {"min": 2.0, "max": 8.0, "grace_s": 900}
state = {}   # (asset, probe) -> first out-of-range timestamp

def check(client, asset, probe, value, ts):
    key = (asset, probe)
    out = value < LIMITS["min"] or value > LIMITS["max"]
    if not out:
        state.pop(key, None)
        return
    start = state.setdefault(key, ts)
    if start is not None and ts - start >= LIMITS["grace_s"]:
        alarm = {"type": "excursion", "probe": probe, "value": value, "since": start,
                 "duration_s": ts - start}
        client.publish(f"{PREFIX}/coldchain/fleet1/{asset}/alarm", json.dumps(alarm), qos=1)
        state[key] = None   # alarm once per excursion; reset when back in range

def on_connect(client, userdata, flags, reason_code, properties):
    client.subscribe(f"{PREFIX}/coldchain/fleet1/+/telemetry", qos=1)

def on_message(client, userdata, msg):
    asset = msg.topic.split("/")[-2]
    r = json.loads(msg.payload)
    for probe in ("t_front", "t_rear"):
        if probe in r:
            check(client, asset, probe, r[probe], r["ts"])

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="excursion-f2q7b5")
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_forever()

Comme il s'appuie sur l'horodatage de mesure, le détecteur traite correctement les données mises en tampon : une rupture de vingt minutes survenue dans un tunnel est toujours reconnue comme durant vingt minutes lorsque l'arriéré arrive. Pour de simples limites fixes sur une valeur en direct, les règles d'alerte à seuil du portail permettent de démarrer rapidement ; une logique de durée comme celle-ci a sa place dans votre propre abonné ou dans Node-RED.

Surveiller la flotte

Abonnez-vous à tout pendant les tests :

mosquitto_sub -h broker.connectmq.com -p 1883 -i ops-f2q7b5 -t "connectmq/demo/f2q7b5/coldchain/#" -v

Le serveur MQTT public gratuit convient pour ce prototype, mais les données d'expédition et la position des clients ne doivent pas transiter par une zone lisible publiquement. Les passerelles de production doivent utiliser TLS sur le port 8883 et des identifiants générés dans le portail.

Conseils de connectivité cellulaire

  1. Gardez des payloads compacts. Des clés courtes et des échantillons toutes les minutes limitent la consommation de données ; regroupez plusieurs mesures par message si votre forfait facture au message.
  2. Choisissez un keep-alive généreux. Des valeurs de deux à cinq minutes réduisent les réveils radio sans trop retarder la détection de déconnexion.
  3. Utilisez l'expiration de session de MQTT 5 pour que les abonnements survivent aux coupures courtes ; voir les fonctionnalités de MQTT 5.
  4. Espacez les reconnexions. Des délais exponentiels évitent de saturer le réseau après un changement d'antenne.
  5. Surveillez le modem. Publiez la force du signal et le type de réseau dans status pour diagnostiquer les zones blanches.

Les pièges courants

Une sonde uniquement près de l'évaporateur. Cette sonde mesure l'air le plus froid du caisson et peut masquer une zone chaude près des portes. Mesurez là où le produit est le plus exposé.

Des horodatages côté serveur. Si vous horodatez les mesures à leur arrivée, un arriéré mis en tampon se tasse en une seule minute et les durées de rupture perdent tout sens. Horodatez toujours au moment de la mesure.

Des avalanches d'alarmes après reconnexion. Une passerelle qui vide une heure de données peut déclencher de nombreuses alertes à la fois. Ne déclenchez qu'une alarme par rupture, comme le détecteur ci-dessus, et marquez les alarmes tardives comme « historiques » pour que les répartiteurs sachent que l'événement est déjà terminé.

Des identifiants partagés par toute la flotte. Un seul identifiant divulgué expose alors tous les camions. Donnez à chaque passerelle ses propres identifiants et son propre client ID.

Checklist de déploiement

  1. Sondes placées aux points les plus chauds et les plus froids de l'espace de chargement, et étalonnées.
  2. Capteurs de porte installés et remontés dans chaque message de télémétrie.
  3. Passerelle avec tampon sur stockage non volatil, ne supprimant qu'après acquittement.
  4. Horodatages issus d'une horloge synchronisée (GPS ou NTP).
  5. Limites fournies sous forme de configuration retenue par actif.
  6. Règles de rupture basées sur la durée par catégorie de produit.
  7. Un abonné d'archivage durable qui écrit chaque mesure dans une base de données pour les rapports de trajet.
  8. TLS et identifiants uniques par passerelle.

Schémas connexes

La surveillance de flotte a beaucoup en commun avec d'autres systèmes IoT distribués. Le principe d'une passerelle par actif reprend les passerelles de terrain d'une architecture IoT de ville intelligente, et l'agrégation de nombreux actifs dans des vues d'état en direct est le même problème que celui résolu dans le parking intelligent IoT. Pour construire un modèle d'état retenu durable, notre projet de détection de fuite d'eau montre des alarmes retenues dans un contexte plus réduit, et le guide de l'automatisation IoT propose d'autres exemples.

Faites tourner votre télémétrie de chaîne du froid sur ConnectMQ

La télémétrie de flotte exige un broker joignable depuis tous les réseaux cellulaires, sécurisé par TLS et maintenu en permanence. ConnectMQ fournit un broker MQTT managé avec MQTT 5, TLS, des identifiants générés et un explorateur de topics en direct pour voir chaque camion remonter ses données. Commencez avec un broker Serverless gratuit sur app.connectmq.com, sans carte bancaire, et passez à une offre payante ou dédiée à mesure que la flotte grandit. Pour le contexte d'hébergement, lisez notre présentation de l'approche broker MQTT cloud.

Questions fréquentes

À quelle fréquence un camion frigorifique doit-il remonter sa température ?

Un échantillonnage toutes les une à cinq minutes est courant. Échantillonnez localement à ce rythme même hors ligne, et envoyez les mesures mises en tampon au retour de la couverture.

Que se passe-t-il si le camion n'a pas de signal ?

La passerelle stocke les mesures avec leur horodatage de mesure dans un stockage local et les publie dans l'ordre une fois connectée, en ne supprimant chacune qu'après l'acquittement du broker.

Pourquoi alerter sur une durée plutôt que sur une seule mesure élevée ?

Les ouvertures de porte et les cycles de dégivrage provoquent de brefs pics sans danger pour le produit. Une période de grâce les filtre tout en détectant les véritables ruptures.

ConnectMQ stocke-t-il l'historique des températures ?

Non. ConnectMQ délivre les messages en temps réel. Exécutez un abonné qui écrit chaque mesure dans votre propre base de données pour les rapports de trajet et les audits.

Articles liés

Guide d'installation de Zigbee2MQTT : du coordinateur au tableau de bord

Installez Zigbee2MQTT avec Docker, configurez le coordinateur et la connexion MQTT, appairez et renommez les appareils, pilotez-les via MQTT et affichez leurs états sur un tableau de bord, en testant d'abord sur le serveur MQTT public gratuit.

8 min de lecture

Tous les articles →

Votre broker MQTT privé, à quelques clics

Créez un compte, récupérez les identifiants de votre broker et connectez votre premier appareil — aucun serveur à installer, mettre à jour ou dimensionner.