IoT industriel

Exemples de structure de topics UNS pour les industriels

Des exemples prêts à l'emploi de structure de topics UNS pour la fabrication discrète et les industries de process, avec les règles de nommage, les conventions de payload et la validation qui gardent un Unified Namespace exploitable à mesure qu'il grandit.

Diagramme en arbre d'une structure de topics UNS, de l'entreprise et du site jusqu'aux lignes et aux machines
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

Une bonne structure des topics UNS est ce qui rend un Unified Namespace navigable : quiconque connaît l'usine peut deviner où se trouve une valeur sans ouvrir la documentation. Ce guide vous fournit des arborescences de topics prêtes à l'emploi pour la fabrication discrète et les industries de process, les règles de nommage et de payload qui les gardent propres, et un petit validateur à exécuter en CI ou sur la passerelle pour bloquer les mauvais topics avant qu'ils n'atteignent le broker.

Les principes d'une structure de topics UNS

Tous les exemples de cet article suivent les cinq mêmes principes. Si vous adaptez les arborescences, conservez les principes.

  1. Modéliser l'usine, pas la technologie. Les topics décrivent où se trouve un élément et ce qu'il est, pas le protocole ou la marque de PLC qui l'a produit. opcua/ et s7/ n'ont rien à faire dans le chemin.
  2. La hiérarchie d'abord, l'ISA-95 comme colonne vertébrale. Entreprise, site, zone, ligne ou cellule, et équipement forment une structure que l'exploitation comprend déjà. Le guide sur la hiérarchie des équipements ISA-95 explique chaque niveau.
  3. Une profondeur fixe quand c'est possible. Lorsque chaque machine se trouve au même niveau, des abonnements avec wildcards comme +/+/+/+/telemetry fonctionnent sur toute l'entreprise.
  4. Un petit ensemble de types de feuilles. Terminez chaque branche d'équipement par un ensemble prévisible d'espaces comme telemetry, state, alarms, events et cmd.
  5. Des identifiants stables. Des noms courts, en minuscules et avec tirets, qui survivent aux réorganisations. Les numéros d'actifs valent souvent mieux que des noms descriptifs qui changent.

Exemple 1 : fabrication discrète

Une usine discrète avec des lignes d'assemblage, des cellules d'usinage et des utilités partagées :

acme/                                     entreprise
  dallas/                                 site
    machining/                            zone
      cell-03/                            cellule de travail
        cnc-01/                           équipement
          telemetry                       {"spindle_rpm":..., "load_pct":..., "ts":...}
          state                           "running" | "idle" | "down" (retenu)
          alarms                          liste des alarmes actives (retenue)
          events/cycle-complete           un message par pièce terminée
          cmd/                            commandes, requête/réponse
        robot-01/
          telemetry
          state
    assembly/
      line-02/                            ligne de production
        station-10/
          telemetry
          events/part-scanned
        station-20/
          telemetry
      line-02/kpi/oee                     valeurs calculées au niveau de la ligne
    utilities/
      compressors/
        comp-01/telemetry

Remarquez la branche kpi au niveau de la ligne. Les valeurs calculées comme l'OEE (TRS) ou le débit appartiennent au niveau qu'elles décrivent et sont publiées par l'application qui les calcule. Les données brutes des machines et les données dérivées restent ainsi clairement séparées tout en vivant dans la même arborescence.

Exemple 2 : industrie de process

Les usines de process raisonnent en cellules de process et en unités plutôt qu'en lignes et en postes. L'ISA-95 couvre les deux cas : l'arborescence change de vocabulaire, pas de forme.

acme/
  izmir/                                  site
    brewing/                              zone
      brewhouse-1/                        cellule de process
        mash-tun/                         unité
          telemetry                       {"temp_c":..., "level_pct":..., "ts":...}
          state                           "heating" | "resting" | "transferring"
          batch                           id de lot et recette en cours (retenu)
        lauter-tun/
          telemetry
      fermentation/
        fv-07/
          telemetry
          batch
    utilities/
      boiler-1/telemetry
      water-treatment/ro-1/telemetry

La feuille batch est l'équivalent, en industrie de process, d'un ordre de fabrication : retenue, légère et mise à jour quand le lot change. Les consommateurs associent le contexte du lot à la télémétrie via le chemin du topic, sans consultation d'une base de données séparée.

Exemple 3 : entreprise multisite avec services partagés

Lorsque plusieurs sites partagent un broker ou un namespace relié par bridge, ajoutez une branche de premier niveau pour les systèmes d'entreprise, afin que les données MES, ERP et qualité aient leur place sans se faire passer pour des équipements :

acme/dallas/...                           arborescences de site comme ci-dessus
acme/izmir/...
acme/_enterprise/erp/work-orders/dallas   ordres de fabrication par site (retenus)
acme/_enterprise/quality/spc/dallas/line-02
acme/_enterprise/mes/schedule/izmir

Le tiret bas initial classe la branche à part des noms de sites et indique clairement qu'il ne s'agit pas d'un lieu physique.

La place de Sparkplug B dans une structure de topics UNS

Sparkplug B utilise son propre format de topic fixe, spBv1.0/<group>/<message type>/<edge node>/<device>. Ce format est optimisé pour la gestion d'état entre edge nodes et applications hôtes, pas pour la navigation selon la hiérarchie de l'usine. Notre article sur le namespace des topics Sparkplug l'explique en détail.

Vous n'avez pas à choisir. Un modèle courant conserve Sparkplug pour le trafic edge-vers-hôte et republie les valeurs dans l'arborescence ISA-95 pour tous les autres. ConnectMQ le fait automatiquement pour le trafic Sparkplug B : il décode le payload Protobuf ou JSON et le republie dans des topics ISA-95, si bien que spBv1.0/factory1/DDATA/line1/cnc1 devient connectmq/factory1/production/line1/cnc1/telemetry. Les tableaux de bord et les historians s'abonnent à du JSON lisible dans l'arborescence ISA-95, tandis que les hôtes SCADA continuent d'utiliser Sparkplug natif.

Règles de nommage et de payload

Règle Correct À éviter
Minuscules uniquement line-02 Line_02, LINE02
Tirets, pas d'espaces mash-tun mash tun, mash%20tun
Pas de slash initial ni final acme/dallas/... /acme/dallas/
Pas de wildcard ni de $ dans les noms cnc-01 cnc#1, $cnc
Unités dans les noms de champs temp_c, speed_bpm temp, speed
Horodatage dans les payloads "ts": "2026-10-16T08:00:00Z" Se fier à l'heure d'arrivée
Retenir l'état courant state, batch, alarms Retenir des flux d'événements
Versionner les payloads "v": 2 Changements cassants silencieux

Le slash initial est une erreur classique : il crée un premier niveau vide, si bien que /acme/# et acme/# sont deux abonnements différents. La casse mixte en est une autre : les topics MQTT sont sensibles à la casse, et Line-02 et line-02 deviennent deux branches distinctes qui scindent discrètement vos données.

Valider les topics avant qu'ils n'atteignent le broker

Le script ci-dessous vérifie les topics par rapport aux règles ci-dessus et à la structure d'équipement à cinq niveaux. Utilisez-le dans une passerelle, dans un test CI sur votre fichier de mapping de tags, ou comme abonné de supervision qui signale les violations.

import re

LEVEL = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$")
LEAVES = {"telemetry", "state", "alarms", "batch", "events", "cmd", "kpi"}

def validate(topic: str, depth: int = 5) -> list[str]:
    """Return a list of problems; an empty list means the topic is valid."""
    problems = []
    if topic.startswith("/") or topic.endswith("/"):
        problems.append("leading or trailing slash")
    levels = topic.strip("/").split("/")
    if any(ch in topic for ch in "+#$"):
        problems.append("wildcard or $ character in topic name")
    if any(" " in level for level in levels):
        problems.append("space in topic level")
    if len(levels) < depth + 1:
        problems.append(f"expected at least {depth + 1} levels, got {len(levels)}")
        return problems
    for level in levels[:depth]:
        if not (LEVEL.match(level) or level.startswith("_")):
            problems.append(f"level '{level}' is not lowercase-hyphenated")
    if levels[depth] not in LEAVES:
        problems.append(f"leaf '{levels[depth]}' not in {sorted(LEAVES)}")
    return problems

if __name__ == "__main__":
    tests = [
        "acme/dallas/machining/cell-03/cnc-01/telemetry",
        "acme/dallas/machining/cell-03/CNC_01/telemetry",
        "/acme/dallas/assembly/line-02/station-10/telemetry",
        "acme/dallas/assembly/line-02/station-10/temperature",
    ]
    for t in tests:
        result = validate(t)
        print("OK  " if not result else "FAIL", t, "" if not result else result)

Exécutez-le avec python validate_topics.py et ajustez LEAVES et depth selon votre norme.

Faire évoluer la structure sans casser les consommateurs

Aucune structure de topics ne sort indemne de la confrontation avec une vraie usine. Des lignes sont reconstruites, des machines changent de cellule, un nouveau site est racheté avec ses propres habitudes de nommage. L'objectif n'est pas d'éviter le changement, mais de le rendre sûr.

  1. Ajouter, ne jamais renommer sur place. Lorsqu'une branche doit changer, publiez en parallèle sur le nouveau et l'ancien chemin pendant une période définie, puis retirez l'ancien. Annoncez la date de fin à chaque responsable de consommateur.
  2. Effacer les retained messages lors du retrait. Une branche retirée renvoie toujours ses valeurs retenues aux nouveaux abonnés. Publiez un retained message vide sur chaque ancien topic d'état pour le supprimer.
  3. Tenir un registre. Un simple fichier sous contrôle de version listant chaque branche, son responsable, ses types de feuilles et la version de son schéma de payload suffit. Le validateur ci-dessus peut lire ses règles depuis ce fichier.
  4. Versionner les payloads, pas les topics. Ajoutez un champ v dans le payload quand le schéma change. Les topics contenant /v2/ dans le chemin ont tendance à se multiplier et à semer la confusion dans les abonnements avec wildcards.
  5. Relire les nouvelles branches. Une courte revue par le responsable du namespace avant la mise en service d'une passerelle détecte la plupart des problèmes tant qu'ils sont encore peu coûteux à corriger.

Traitez la structure comme une API dont dépend toute l'usine, car c'est exactement ce qu'elle devient dès que des tableaux de bord, des historians, des intégrations MES ou un jumeau numérique s'y abonnent.

Tester la structure sur un broker en direct

Avant de déployer une structure, publiez quelques messages d'exemple et parcourez-les. Sur le serveur MQTT public gratuit broker.connectmq.com, vous pouvez le faire sans compte, à condition d'utiliser un préfixe unique et de garder à l'esprit que l'espace public est lisible par tous et réservé aux tests. Le serveur public autorise 8 niveaux de topic : connectmq/demo/<id>/ plus l'arborescence à cinq niveaux et une feuille tiennent donc exactement si vous retirez le niveau entreprise :

mosquitto_pub -h broker.connectmq.com -p 1883 -i uns-test-pub-q7 -r \
  -t "connectmq/demo/q7w2/dallas/machining/cell-03/cnc-01/state" -m "running"

mosquitto_sub -h broker.connectmq.com -p 1883 -i uns-test-sub-q7 \
  -t "connectmq/demo/q7w2/dallas/+/+/+/state" -v

Sur un broker ConnectMQ privé, vous pouvez utiliser l'arborescence complète sans le préfixe de démo, et l'explorateur de topics en direct ainsi que la vue des appareils ISA-95 du portail montrent d'un coup d'œil si les appareils arrivent dans la bonne entreprise, le bon site, la bonne zone et la bonne ligne. Pour les règles d'encodage étape par étape, poursuivez avec les topics MQTT ISA-95, et pour le processus de construction complet, consultez comment construire un Unified Namespace. La vue d'ensemble se trouve dans notre guide MQTT pour l'IoT industriel.

Déployez votre structure de topics UNS sur ConnectMQ

Une structure de topics ne vaut que par le broker qui la transporte et la visibilité dont vous disposez sur elle. ConnectMQ est un broker MQTT managé qui détecte les topics ISA-95 et Unified Namespace, décode Sparkplug B et le republie dans votre arborescence ISA-95. Créez un broker avec l'offre gratuite Serverless sur app.connectmq.com, sans carte bancaire, et publiez votre première branche de namespace en quelques minutes.

Questions fréquentes

Combien de niveaux doit compter une structure de topics UNS ?

La plupart des usines en utilisent cinq ou six : entreprise, site, zone, ligne ou cellule, équipement, et une feuille comme telemetry ou state. Une profondeur fixe garde les abonnements avec wildcards simples.

Chaque mesure doit-elle avoir son propre topic ?

Les deux approches fonctionnent. Un objet JSON par topic de télémétrie d'équipement est plus simple et moins coûteux ; un topic par mesure convient aux outils qui associent directement les topics à des tags. Choisissez une approche par type de feuille et appliquez-la de manière cohérente.

Où placer les KPI calculés ?

Au niveau qu'ils décrivent, publiés par l'application qui les calcule, par exemple dans une branche kpi/oee sous la ligne.

Les topics Sparkplug B peuvent-ils faire partie d'un UNS ?

Oui, mais ils ne sont pas organisés selon la hiérarchie de l'usine. Republiez les valeurs Sparkplug dans des topics ISA-95 pour que tous les consommateurs puissent parcourir une seule arborescence.

Articles liés

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.