Un système de parking intelligent IoT indique aux conducteurs où se trouvent les places libres avant qu'ils ne tournent en rond, et montre aux exploitants comment leurs parkings sont réellement utilisés. Cet article présente une conception complète : choix des capteurs de place, structuration des topics MQTT, agrégation des places libres par zone et pilotage d'une carte en direct dans le navigateur, mise à jour à l'instant où une voiture s'en va.
Ce qu'un système de parking intelligent doit faire
Une fois le discours marketing mis de côté, un système de guidage de parking a quatre missions :
- Détecter si chaque place est occupée.
- Transporter ces changements d'état de manière fiable du terrain vers le back-end.
- Agréger les places individuelles en chiffres qui intéressent les gens : places libres par niveau, par zone, par parking.
- Afficher le résultat sur des panneaux, des applications et des cartes, en quasi temps réel.
MQTT s'intègre naturellement aux couches de transport et d'affichage. Chaque place est un topic d'état retenu, les agrégateurs s'abonnent avec des wildcards et les navigateurs s'abonnent via WebSocket pour recevoir les mises à jour en direct. La suite de l'article suit les données de l'asphalte jusqu'à l'écran.
Choisir les capteurs de place
| Type de capteur | Fonctionnement | Points forts | Points de vigilance |
|---|---|---|---|
| Magnétomètre (encastré ou palet en surface) | Détecte la variation du champ magnétique terrestre causée par une voiture | Grande autonomie, insensible à la lumière et à la météo | Interférences des places voisines, nécessite un étalonnage |
| Radar (combiné à un magnétomètre) | Réflexion à courte portée sur le dessous du véhicule | Moins de faux positifs qu'un magnétomètre seul | Coût et consommation plus élevés |
| Ultrasons (fixé au plafond) | Mesure la distance jusqu'au toit de la voiture | Simple, courant dans les parkings couverts, souvent avec voyant LED | Nécessite une alimentation secteur et un montage en intérieur |
| Caméra avec modèle de vision | Une caméra couvre de nombreuses places | Faible coût par place, peut lire les plaques | Règles de confidentialité, éclairage, traitement en edge |
Pour les parkings à ciel ouvert et le stationnement en voirie, les palets magnétomètres ou radar sur batterie en LoRaWAN ou NB-IoT sont le choix habituel. Les parkings couverts utilisent souvent des capteurs à ultrasons au plafond sur un bus filaire avec une passerelle locale. Les systèmes à caméra publient des résultats plutôt que de la vidéo : l'équipement edge exécute la détection et ne publie que occupied ou free par place.
Les chemins de connectivité vers le broker
La manière dont les capteurs atteignent le broker façonne l'architecture davantage que le type de capteur :
- LoRaWAN : les capteurs parlent aux passerelles, les passerelles transmettent à un serveur réseau comme The Things Stack ou ChirpStack, et ce serveur réseau, ou un petit service de pont, publie les données décodées vers votre broker. Des centaines de places deviennent une seule connexion MQTT. Consultez The Things Network avec MQTT pour l'étape de pont.
- NB-IoT ou LTE-M : chaque capteur peut se connecter directement en MQTT, ou remonter ses données via la plateforme de l'opérateur, que vous reliez ensuite.
- Bus filaire et passerelle : une passerelle intérieure interroge les capteurs à ultrasons et publie les changements.
- Caméra edge : un petit ordinateur exécute la détection et publie les résultats par place.
L'approche par passerelle est intéressante au-delà du coût. Elle limite le nombre de connexions, si bien que même une petite offre de broker gère un grand parking, et l'état des places reste un topic MQTT propre lorsqu'il atteint vos applications.
Conception des topics pour le parking intelligent IoT
Une hiérarchie qui reflète l'agencement physique transforme chaque requête en wildcard :
parking/<site>/<level>/<bay>/state retained: {"occupied":true,"ts":1760600000}
parking/<site>/<level>/<bay>/battery retained: 3.41
parking/<site>/<level>/summary retained: {"free":37,"total":120}
parking/<site>/summary retained: {"free":112,"total":420}
parking/<site>/<level>/<bay>/availability retained online/offline (gateway-reported)
parking/central/+/+/statecorrespond à toutes les places du parking central.parking/+/summaryest le chiffre clé de chaque site, et c'est tout ce dont un panneau à l'échelle de la ville a besoin.
En retenant à la fois les états des places et les synthèses, toute nouvelle application ou tout nouveau panneau affiche les bons chiffres dès la connexion. Incluez un horodatage dans le payload, car une place qui n'a rien remonté depuis une journée est « inconnue », pas « libre ».
Agréger les places libres par niveau
Un agrégateur s'abonne à tous les états de place, les conserve en mémoire et republie les synthèses à chaque changement. Cette version Python utilise paho-mqtt 2.x et le serveur MQTT public gratuit, réservé aux tests et jamais aux données de production :
import json
import time
from collections import defaultdict
import paho.mqtt.client as mqtt
PREFIX = "connectmq/demo/p3v6z8" # your own random prefix
SITE = "central"
STALE_AFTER = 6 * 3600 # seconds without a report = unknown
bays = {} # (level, bay) -> {"occupied": bool, "ts": float}
def publish_summaries(client):
now = time.time()
per_level = defaultdict(lambda: {"free": 0, "occupied": 0, "unknown": 0, "total": 0})
for (level, _), s in bays.items():
bucket = per_level[level]
bucket["total"] += 1
if now - s["ts"] > STALE_AFTER:
bucket["unknown"] += 1
elif s["occupied"]:
bucket["occupied"] += 1
else:
bucket["free"] += 1
site = {"free": 0, "occupied": 0, "unknown": 0, "total": 0}
for level, b in per_level.items():
client.publish(f"{PREFIX}/parking/{SITE}/{level}/summary", json.dumps(b), qos=1, retain=True)
for k in site:
site[k] += b[k]
client.publish(f"{PREFIX}/parking/{SITE}/summary", json.dumps(site), qos=1, retain=True)
def on_connect(client, userdata, flags, reason_code, properties):
client.subscribe(f"{PREFIX}/parking/{SITE}/+/+/state", qos=1)
def on_message(client, userdata, msg):
parts = msg.topic.split("/")
level, bay = parts[-3], parts[-2]
try:
data = json.loads(msg.payload)
bays[(level, bay)] = {"occupied": bool(data["occupied"]), "ts": float(data.get("ts", time.time()))}
except (ValueError, KeyError):
return
publish_summaries(client)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="parking-agg-p3v6z8")
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_forever()
Simulez quelques places depuis le terminal :
P=connectmq/demo/p3v6z8/parking/central
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-p3v6z8 -r -q 1 -t $P/l1/b001/state -m "{\"occupied\":true,\"ts\":$(date +%s)}"
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-p3v6z8 -r -q 1 -t $P/l1/b002/state -m "{\"occupied\":false,\"ts\":$(date +%s)}"
mosquitto_sub -h broker.connectmq.com -p 1883 -i view-p3v6z8 -t "$P/+/summary" -t "$P/summary" -v
Notez que le préfixe de démonstration ajoute des niveaux : le topic d'état de place ci-dessus compte huit niveaux, le maximum autorisé par le serveur MQTT public gratuit. Sur un broker privé, vous supprimeriez le préfixe pour commencer à parking/.
Pour un grand déploiement, publier chaque synthèse à chaque changement est un gaspillage. Regroupez les mises à jour toutes les une à deux secondes et, si un seul agrégateur ne suffit pas, les abonnements partagés MQTT 5 sur une offre payante permettent à plusieurs instances de se répartir la charge.
La carte de disponibilité en direct
Le navigateur se connecte via WebSocket sécurisé et s'abonne uniquement aux synthèses, ou aux états des places pour une vue détaillée d'un niveau. Avec MQTT.js :
import mqtt from "mqtt";
const PREFIX = "connectmq/demo/p3v6z8/parking/central";
const client = mqtt.connect("wss://broker.connectmq.com:8084/mqtt", {
clientId: "parking-map-" + Math.random().toString(16).slice(2, 8),
protocolVersion: 5,
});
client.on("connect", () => {
client.subscribe(`${PREFIX}/+/summary`, { qos: 1 });
client.subscribe(`${PREFIX}/l1/+/state`, { qos: 0 });
});
client.on("message", (topic, payload) => {
const data = JSON.parse(payload.toString());
const parts = topic.split("/");
if (topic.endsWith("/summary")) {
const level = parts[parts.length - 2];
const el = document.querySelector(`[data-level="${level}"] .free`);
if (el) el.textContent = `${data.free} free of ${data.total}`;
} else {
const bay = parts[parts.length - 2];
const cell = document.querySelector(`[data-bay="${bay}"]`);
if (cell) cell.className = data.occupied ? "bay occupied" : "bay free";
}
});
Avec une bibliothèque cartographique comme Leaflet, le même gestionnaire recolorerait un marqueur par site. Comme les synthèses sont retenues, la carte affiche la situation actuelle dès le chargement de la page. Notre guide sur MQTT over WebSocket détaille la connexion depuis le navigateur et la gestion des identifiants, un point important : une page web publique ne doit jamais embarquer d'identifiants capables de publier sur les topics des places.
Checklist de déploiement
- Choisissez les capteurs selon l'environnement : palets en extérieur, ultrasons en intérieur, caméras là où les règles de confidentialité le permettent.
- Reliez les réseaux LoRaWAN ou filaires via des passerelles pour limiter le nombre de connexions.
- Retenez les états des places et les synthèses ; incluez des horodatages.
- Traitez les capteurs silencieux comme inconnus et déclenchez une alerte en cas de batterie faible.
- Ne livrez jamais d'identifiants autorisés à publier aux clients de carte publics ; servez plutôt les synthèses via votre propre back-end.
- Utilisez TLS sur le port 8883 pour les passerelles et 8084 pour les navigateurs.
- Enregistrez les changements d'état dans une base de données avec un abonné distinct pour l'analyse de l'occupation.
Les pièges courants des déploiements de parking
Interférences entre places voisines. Une grande camionnette peut perturber le magnétomètre de la place d'à côté. Étalonnez les capteurs après installation et privilégiez les unités combinant magnétomètre et radar dans les agencements serrés.
Occupation fantôme. La neige, une flaque d'eau ou un objet métallique tombé au sol peuvent faire paraître une place occupée pendant des jours. Signalez les places dont l'état n'a pas changé depuis une durée anormalement longue et vérifiez-les.
Dérive d'horloge. Si les horodatages proviennent des capteurs, une horloge qui dérive fait paraître périmées des données fraîches. Laissez la passerelle ou le serveur réseau horodater les messages à leur arrivée.
Synthèses publiées trop souvent. Des centaines de panneaux et d'applications recevant une synthèse à chaque changement de place, c'est de la bande passante gaspillée. Limitez le débit des synthèses et ne publiez que lorsque les chiffres changent réellement.
Passer à l'échelle au-delà d'un seul parking
Dès que plusieurs sites publient sous parking/<site>/..., un panneau de guidage à l'échelle de la ville s'abonne à parking/+/summary et à rien d'autre. C'est le même schéma de messagerie que celui de l'architecture IoT de la ville intelligente, où stationnement, éclairage et qualité de l'air partagent un même broker tout en restant dans des sous-arborescences distinctes. La logistique sensible à la température utilise un schéma de flotte similaire, décrit dans la surveillance de la chaîne du froid.
Exploiter le broker vous-même implique correctifs, certificats et supervision pour un système sur lequel les conducteurs comptent chaque jour. Un broker MQTT managé comme ConnectMQ prend en charge TLS, les endpoints WebSocket et la gestion des connexions, tandis que l'explorateur de topics en direct du portail vous permet de voir arriver les états des places. Si vous comparez les modèles d'hébergement, notre présentation de l'approche broker MQTT cloud vous aidera, et le guide de l'automatisation IoT rassemble des projets connexes.
Lancez votre pilote de parking intelligent sur ConnectMQ
Pilotez un niveau avec quelques capteurs et une passerelle, publiez vers ConnectMQ et affichez la carte en direct sur un écran de test. Créez un broker Serverless gratuit sur app.connectmq.com, sans carte bancaire, et passez à une offre payante ou dédiée lorsque le nombre de places augmente.
Questions fréquentes
Combien de connexions MQTT un système de parking intelligent nécessite-t-il ?
Généralement bien moins que le nombre de places. Les serveurs réseau LoRaWAN et les passerelles intérieures publient pour de nombreux capteurs via une seule connexion ; le nombre de connexions dépend donc des passerelles et des applications, pas des places.
Quel capteur convient le mieux aux places de stationnement en extérieur ?
Les palets magnétomètres sur batterie, idéalement combinés à un radar pour réduire les fausses lectures, sont le choix courant en extérieur, car ils résistent aux intempéries et tiennent des années sur une batterie.
Comment éviter que la carte publique soit détournée ?
Faites transiter les données par votre propre back-end, par exemple un petit serveur qui s'abonne aux synthèses et les pousse vers la page. N'intégrez jamais dans une page publique des identifiants capables de publier sur les topics de places ou de synthèses.
Puis-je utiliser des caméras à la place des capteurs de place ?
Oui. Un équipement edge exécute la détection et ne publie que l'occupation par place, jamais de vidéo, ce qui limite la bande passante et facilite la conformité en matière de confidentialité.



