Tutoriels

Passerelle OPC UA vers MQTT pour les données industrielles

Reliez des tags OPC UA à des topics MQTT : abonnez-vous aux changements avec Python asyncua, mappez les nœuds dans un arbre UNS et testez avec un client MQTT.

Mis à jour · 9 min de lecture

Passerelle OPC UA vers MQTT pour les données industrielles

Une passerelle OPC UA vers MQTT se connecte à un serveur OPC UA en tant que client, s'abonne aux tags qui vous intéressent et republie chaque changement de donnée sous forme de message MQTT sur un topic bien nommé. L'usine garde OPC UA là où il excelle — modèles riches, sécurité, intégration machine — pendant que tableaux de bord, historiens et services cloud reçoivent un flux publish/subscribe léger qu'ils peuvent faire évoluer librement.

Ce tutoriel construit une telle passerelle en Python avec asyncua et paho-mqtt, mappe les node ids OPC UA vers un arbre de topics de type Unified Namespace et montre comment la tester avec un serveur OPC UA simulé.

Pourquoi une passerelle plutôt qu'une connexion directe

OPC UA est client/serveur : chaque consommateur ouvre une session vers chaque serveur dont il a besoin. Avec cinq consommateurs et vingt serveurs, cela fait cent sessions, chacune avec ses subscriptions, ses certificats et sa charge sur le serveur. Une passerelle en fait un hub :

OPC UA directPasserelle OPC UA → MQTT
Sessions par serveurUne par consommateurUne (la passerelle)
Ajouter un consommateurReconfigurer certificats et node idsS'abonner à un topic
Modèle de donnéesModèle d'information OPC UA completTopics aplatis + payloads JSON
Sens du pare-feuEntrant vers les serveurs OTSortant de la passerelle vers le broker
Idéal pourContrôle machine à machine, navigation, méthodesDiffusion des valeurs vers l'IT et le cloud

Par défaut, la passerelle est à sens unique : OPC UA en entrée, MQTT en sortie. Le côté OT reste protégé pendant que l'IT reçoit les données. Pour une comparaison plus large des deux protocoles, lisez MQTT vs OPC UA.

1. Lancer un serveur OPC UA de test

Ne développez pas contre un serveur de production. Le simulateur open source OPC PLC de Microsoft tourne dans Docker et expose des valeurs qui changent :

Lancer un serveur OPC UA simulé
docker run --rm -p 50000:50000 mcr.microsoft.com/iotedge/opc-plc:latest \
  --pn=50000 --autoaccept --unsecuretransport

L'endpoint est opc.tcp://localhost:50000. Parcourez-le avec un client graphique comme UaExpert, ou avec la commande uals fournie avec asyncua, et notez les node ids à relayer. Le simulateur expose des nœuds comme StepUp, AlternatingBoolean et RandomSignedInt32 dans son propre namespace ; vérifiez l'index de namespace dans votre navigateur, car il peut varier selon les versions.

2. Mapper les nœuds vers des topics

Le mapping est le vrai travail de conception. Un topic doit dire où vit la valeur dans l'usine, pas quel serveur ou quel node id la fournit aujourd'hui. Gardez la table dans la configuration :

nodes.py
BASE = "testmqtt/acme/plant1/packaging/line1"

NODES = {
    "ns=3;s=StepUp":             f"{BASE}/filler/counter",
    "ns=3;s=AlternatingBoolean": f"{BASE}/filler/running",
    "ns=3;s=RandomSignedInt32":  f"{BASE}/capper/torque",
}

Quand vous remplacerez plus tard le serveur simulé par le vrai — ou déplacerez un tag vers un autre automate — seul le côté gauche de la table change. Tous les abonnés continuent de fonctionner. C'est l'idée centrale d'un Unified Namespace : l'arbre de topics est le contrat, les sources sont des détails d'implémentation.

3. La passerelle

L'API de subscriptions d'asyncua appelle un handler à chaque changement d'un monitored item. Le handler publie la valeur, sa qualité OPC UA et l'horodatage source :

opcua_mqtt_bridge.py
import asyncio, json, os
import paho.mqtt.client as mqtt
from asyncua import Client
from nodes import BASE, NODES

OPC_URL = os.getenv("OPC_URL", "opc.tcp://localhost:50000")
STATUS = f"{BASE}/_bridge/status"

mq = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="opcua-bridge-line1")
mq.username_pw_set(os.getenv("MQTT_USER"), os.getenv("MQTT_PASS"))
mq.tls_set()
mq.will_set(STATUS, "offline", qos=1, retain=True)
mq.connect("broker.connectmq.com", 8883, keepalive=30)
mq.loop_start()

class Handler:
    def datachange_notification(self, node, val, data):
        dv = data.monitored_item.Value
        ts = dv.SourceTimestamp or dv.ServerTimestamp
        payload = {
            "v": val,
            "good": dv.StatusCode.is_good(),
            "ts": ts.isoformat() if ts else None,
        }
        topic = NODES[node.nodeid.to_string()]
        mq.publish(topic, json.dumps(payload, default=str), qos=1, retain=True)

async def run():
    while True:
        try:
            async with Client(url=OPC_URL, timeout=10) as opc:
                nodes = [opc.get_node(nid) for nid in NODES]
                sub = await opc.create_subscription(500, Handler())   # intervalle de publication de 500 ms
                await sub.subscribe_data_change(nodes)
                mq.publish(STATUS, "online", qos=1, retain=True)
                print("passerelle active pour", len(nodes), "nœuds")
                while True:
                    await asyncio.sleep(5)
                    await opc.check_connection()
        except Exception as exc:          # connexion perdue, redémarrage serveur, node id invalide
            print("Erreur OPC UA :", exc)
            mq.publish(STATUS, "opcua-unreachable", qos=1, retain=True)
            await asyncio.sleep(5)

asyncio.run(run())
Installer et lancer
pip install "asyncua>=1.1" "paho-mqtt>=2.0"
python opcua_mqtt_bridge.py

Ce que cette conception vous apporte :

  • Un trafic piloté par les changements. OPC UA n'envoie des notifications que lorsque les valeurs changent, le côté MQTT ne transporte donc aucun échantillon redondant. Ajustez l'intervalle de publication (500 ms ici) et l'intervalle d'échantillonnage par item à votre procédé.
  • La qualité voyage avec la valeur. Un status code OPC UA mauvais ou incertain est une information ; gardez-le dans le payload au lieu de jeter le message en silence.
  • Horodatage source. Les historiens doivent stocker le moment où la valeur a changé à la source, pas celui où la passerelle l'a relayée.
  • Valeurs retenues et topic de statut. Les nouveaux abonnés voient l'état courant immédiatement, et le Last Will passe le statut de la passerelle à offline si le processus meurt. Plus de détails dans messages retenus.
  • Reprise automatique. Si le serveur OPC UA redémarre, la boucle externe se reconnecte et recrée la subscription. paho se reconnecte seul au broker après loop_start().

4. Tester la passerelle

  1. Lancez le simulateur et la passerelle. La passerelle doit afficher le nombre de nœuds relayés.
  2. Ouvrez le client MQTT en ligne, connectez-vous à broker.connectmq.com et abonnez-vous à testmqtt/acme/plant1/#. filler/counter doit augmenter, filler/running basculer et _bridge/status afficher online.
  3. Arrêtez le conteneur du simulateur. En quelques secondes, le statut doit passer à opcua-unreachable ; relancez-le et les valeurs doivent reprendre sans redémarrer la passerelle.
  4. Tuez la passerelle avec kill -9. Après le timeout du keep-alive, le broker publie le Last Will : offline.

Suivre les tags OPC UA relayés dans le navigateur

Vérifiez avec le topic matcher que les filtres des consommateurs correspondent à ce que publie la passerelle, et pensez aux grosses valeurs structurées (tableaux, extension objects) : le calculateur de taille de paquet aide à estimer le coût d'une notification sur le réseau.

Autres façons de relier OPC UA et MQTT

Une petite passerelle Python est idéale pour apprendre, pour quelques serveurs et pour garder un contrôle total du mapping. Pour des parcs plus importants, envisagez :

OptionRemarques
Node-RED avec un paquet de nœuds OPC UAFlux visuels, adapté aux prototypes et petits sites ; voir Node-RED et MQTT
Telegraf (inputs.opcua + outputs.mqtt)Uniquement de la configuration, convient aux équipes qui utilisent déjà la stack TICK
Plateformes de connectivité industrielleDe nombreux produits SCADA et DataOps incluent des clients OPC UA et des publieurs MQTT avec des outils de modélisation
OPC UA PubSub sur MQTT (partie 14)Le serveur publie lui-même vers le broker, s'il le supporte ; les payloads suivent les encodages OPC UA JSON ou UADP
Edge node Sparkplug BAjoute les certificats birth/death et une gestion d'état standard ; voir Sparkplug B

Quel que soit l'outil, les règles restent les mêmes : les topics décrivent l'usine, les payloads portent valeur + qualité + horodatage, la passerelle annonce sa propre santé, et les écritures vers OPC UA passent par un chemin séparé et volontairement sécurisé.

Checklist de production

  • Utilisez la sécurité OPC UA (Basic256Sha256 avec signature et chiffrement) et un certificat d'application dédié pour la passerelle sur les vrais serveurs ; le mode non sécurisé du simulateur est réservé aux tests locaux.
  • Consultez les limites du serveur en monitored items par subscription et répartissez les grandes listes de tags sur plusieurs subscriptions.
  • Déployez une passerelle par zone ou par ligne pour qu'une panne reste locale.
  • Versionnez la table nœud→topic et relisez-la comme du code.
  • Surveillez le topic de statut de la passerelle et alertez quand il n'est pas online.

Une passerelle OPC UA vers MQTT vous permet de garder OPC UA pour ce qu'il fait de mieux tout en donnant à tous les autres systèmes un flux simple et évolutif. Mappez les nœuds vers des topics à l'image de l'usine, publiez les notifications de changement avec qualité et horodatage, testez contre un simulateur et le client en ligne, et vos données OT deviennent quelque chose à quoi toute l'entreprise peut s'abonner.

Questions fréquentes

Pourquoi relier OPC UA à MQTT plutôt que laisser chaque application utiliser OPC UA ?

OPC UA est un modèle client/serveur riche : chaque consommateur ouvre sa propre session vers chaque serveur. MQTT les découple : la passerelle lit chaque serveur une fois et un nombre quelconque de tableaux de bord, d'historiens et de services cloud s'abonnent au broker sans charger les automates ni les serveurs SCADA.

Faut-il interroger les nœuds OPC UA en boucle ou utiliser des subscriptions ?

Utilisez les subscriptions OPC UA avec des monitored items. Le serveur échantillonne les valeurs et n'envoie que les changements, ce qui est plus efficace et plus précis qu'une lecture en boucle. Le polling n'est qu'un repli pour les serveurs dont les subscriptions sont défaillantes.

Et OPC UA PubSub sur MQTT ?

La partie 14 d'OPC UA définit PubSub avec un transport MQTT et un encodage JSON ou UADP. Si vos serveurs le supportent, ils peuvent publier directement vers un broker. Beaucoup de serveurs installés ne le font pas, c'est pourquoi une passerelle côté client reste l'approche la plus courante.