Eclipse Tahu est l'implémentation de référence open source de la spécification Sparkplug, avec des bibliothèques et des exemples en Java, Python et C. Dans ce guide, vous verrez le rôle de chaque partie du dépôt Tahu, comment le compiler, les pièges qui font trébucher lors d'une première utilisation, et comment connecter un edge node basé sur Tahu à un vrai broker MQTT pour voir arriver ses births et ses données.
Ce qu'est Eclipse Tahu, et ce qu'il n'est pas
Sparkplug est gouverné au sein de la Fondation Eclipse, et Tahu est le projet qui transforme la spécification en code fonctionnel. Il fournit trois choses :
- La définition Protobuf des payloads Sparkplug B,
sparkplug_b.proto, ainsi que le code généré à partir d'elle pour chaque langage. - Des bibliothèques utilitaires qui construisent et analysent les payloads : création des payloads BIRTH et DEATH, ajout de métriques avec les bons types de données, gestion des numéros de séquence.
- Des exemples et des outils de compatibilité qui présentent un edge node et une application hôte minimaux, et aident les éditeurs à vérifier leurs implémentations par rapport à la spécification.
Ce qu'Eclipse Tahu n'est pas : ce n'est ni un broker MQTT, ni un système SCADA, ni un produit de passerelle. Chaque exemple Tahu se connecte comme un client MQTT ordinaire à un broker que vous fournissez. Cette séparation est tout l'intérêt de Sparkplug. L'edge node et l'hôte parlent Sparkplug, et le broker MQTT au milieu doit seulement être un serveur MQTT conforme.
Tahu est aussi du code de référence. Il est écrit pour être clair et correct plutôt que pour être intégré tel quel dans une passerelle de production. Beaucoup d'équipes utilisent directement les définitions Protobuf et les utilitaires de payload, et écrivent leur propre gestion de session autour, ce que nous allons justement faire ci-dessous.
Visite du dépôt
Les sources se trouvent dans le dépôt Eclipse Tahu sur GitHub. Clonez-le pour l'explorer :
git clone https://github.com/eclipse-tahu/tahu.git
cd tahu
ls
L'arborescence est organisée par langage. Les noms de dossiers ont changé d'une version à l'autre : considérez ce tableau comme une carte plutôt qu'un listing exact, et consultez le README de la branche que vous clonez.
| Zone | Contenu | Usage typique |
|---|---|---|
sparkplug_b (proto) |
La définition .proto des payloads Sparkplug B |
Générer des bindings pour n'importe quel langage |
java |
Bibliothèque principale, constructeurs et décodeurs de payloads, exemples edge et hôte, tests de compatibilité | Passerelles et applications hôtes sur JVM |
python |
core avec les utilitaires sparkplug_b.py et le sparkplug_b_pb2.py généré, plus des exemples |
Scripts, simulateurs, outils de test |
c |
Encodage de payload de base reposant sur nanopb, plus un client d'exemple | Passerelles embarquées et équipements contraints |
javascript |
Utilitaires d'encodage de payload pour Node.js | Outils basés sur Node et flows de type Node-RED |
Java
L'implémentation Java est la plus complète. Elle contient des classes de modèle pour les payloads et les métriques, des encodeurs et décodeurs, ainsi que des exemples de plus haut niveau d'edge node et d'hôte. Elle se compile avec Maven :
cd java
mvn clean install -DskipTests
Les artefacts obtenus peuvent être utilisés depuis votre propre projet Maven ou Gradle. Java est le choix naturel si vous écrivez une application hôte ou intégrez un SCADA ou un MES basé sur la JVM.
Python
Le dossier Python contient deux fichiers que vous utiliserez en permanence. sparkplug_b_pb2.py est le module Protobuf généré, et sparkplug_b.py ajoute des utilitaires comme getNodeBirthPayload, getDeviceBirthPayload, getDdataPayload, getNodeDeathPayload et addMetric, ainsi qu'une énumération MetricDataType. Le dossier d'exemples présente un edge node simple qui publie ses births, envoie des données et répond aux commandes.
C
L'implémentation C encode et décode les payloads Sparkplug à l'aide de nanopb, un petit runtime Protobuf conçu pour les microcontrôleurs. C'est le point de départ si vous avez besoin de Sparkplug sur une passerelle Linux embarquée ou un firmware à mémoire limitée. Le client d'exemple associe l'encodeur à une bibliothèque MQTT ; vous le compilez avec le Makefile fourni après avoir installé les en-têtes de développement de cette bibliothèque.
Pièges courants d'Eclipse Tahu
La plupart des problèmes rencontrés le premier jour avec Tahu relèvent de l'environnement plutôt que de Sparkplug.
- paho-mqtt 2.x casse les anciens exemples Python. Les exemples Python de Tahu ont été écrits pour paho-mqtt 1.x. Avec paho-mqtt 2.x,
mqtt.Client()exige une version d'API de callbacks comme premier argument. Fixez soitpip install "paho-mqtt<2"pour les exemples, soit créez le client avecmqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id=...)pour conserver les anciennes signatures de callbacks. - Incompatibilité du runtime Protobuf. Un
sparkplug_b_pb2.pygénéré par un ancienprotocpeut échouer avec un paquetprotobufrécent, avec le message « Descriptors cannot be created directly ». Régénérez-le avecprotoc --python_out=. sparkplug_b.protoà l'aide d'un compilateur à jour. - Chemins d'import. Les exemples importent les utilitaires principaux via une insertion de chemin relatif. Si vous copiez un exemple ailleurs, copiez
sparkplug_b.pyetsparkplug_b_pb2.pyà côté. - Paramètres de connexion codés en dur. Les exemples pointent par défaut vers
localhost. Modifiez l'hôte et le port du broker, le group ID, l'edge node ID et les identifiants en haut du fichier. - Group ID partagés sur les brokers publics. Les topics Sparkplug commencent toujours par
spBv1.0: sur un broker public, utilisez donc un group ID aléatoire pour éviter les collisions avec les tests d'autres personnes.
Connecter un edge node Tahu à un broker MQTT
Le script suivant utilise les utilitaires Python de Tahu avec paho-mqtt 2.x. Copiez sparkplug_b.py et sparkplug_b_pb2.py depuis le dossier Python core de Tahu dans un répertoire vide, ajoutez ce fichier à côté, et installez les dépendances avec pip install "paho-mqtt>=2.0" protobuf.
import random
import time
import paho.mqtt.client as mqtt
from sparkplug_b import (
MetricDataType,
addMetric,
getDdataPayload,
getDeviceBirthPayload,
getNodeBirthPayload,
getNodeDeathPayload,
)
BROKER = "broker.connectmq.com"
PORT = 1883
GROUP = "tahu-demo-5mz8" # group ID aléatoire pour le broker public
NODE = "tahu-edge-01"
DEVICE = "pump-01"
CLIENT_ID = f"tahu-edge-{random.randint(1000, 9999)}"
def t(msg_type, device=None):
base = f"spBv1.0/{GROUP}/{msg_type}/{NODE}"
return f"{base}/{device}" if device else base
def publish_births(client):
nbirth = getNodeBirthPayload()
addMetric(nbirth, "Node Control/Rebirth", None, MetricDataType.Boolean, False)
client.publish(t("NBIRTH"), bytearray(nbirth.SerializeToString()), 0, False)
dbirth = getDeviceBirthPayload()
addMetric(dbirth, "Flow", None, MetricDataType.Float, 12.5)
addMetric(dbirth, "Pressure", None, MetricDataType.Float, 3.1)
addMetric(dbirth, "Running", None, MetricDataType.Boolean, True)
client.publish(t("DBIRTH", DEVICE), bytearray(dbirth.SerializeToString()), 0, False)
print("NBIRTH and DBIRTH published")
def on_connect(client, userdata, flags, reason_code, properties):
print("connected:", reason_code)
client.subscribe(t("NCMD"))
publish_births(client)
def on_message(client, userdata, msg):
print("command received on", msg.topic)
publish_births(client) # dans cette démo, tout NCMD est traité comme une demande de rebirth
# Le payload de death doit être construit avant le birth pour que les deux portent le même bdSeq
death = getNodeDeathPayload()
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.on_connect = on_connect
client.on_message = on_message
client.will_set(t("NDEATH"), bytearray(death.SerializeToString()), 1, False)
client.connect(BROKER, PORT, 60)
client.loop_start()
try:
while True:
time.sleep(3)
ddata = getDdataPayload()
addMetric(ddata, "Flow", None, MetricDataType.Float, round(random.uniform(11, 14), 2))
addMetric(ddata, "Pressure", None, MetricDataType.Float, round(random.uniform(2.8, 3.4), 2))
client.publish(t("DDATA", DEVICE), bytearray(ddata.SerializeToString()), 0, False)
print("DDATA published")
except KeyboardInterrupt:
client.loop_stop()
client.disconnect()
L'ordre de getNodeDeathPayload() et getNodeBirthPayload() est important, car les utilitaires de Tahu gèrent le compteur bdSeq en interne, et le NDEATH enregistré comme will doit porter la même valeur que le NBIRTH qui suit. Si votre copie des utilitaires se comporte différemment, inspectez la métrique bdSeq dans les deux payloads et ajustez.
Lancez le script et abonnez-vous au groupe dans un autre terminal :
mosquitto_sub -h broker.connectmq.com -p 1883 -i tahu-watch-5mz8 -t "spBv1.0/tahu-demo-5mz8/#" -v
Vous verrez arriver les topics avec des payloads binaires. Pour lire les métriques, ouvrez le trafic dans un portail ConnectMQ : l'explorateur de topics en direct décode les payloads Sparkplug B, en Protobuf comme en JSON, en métriques nommées avec leurs types et valeurs. Vous confirmez ainsi rapidement que Tahu a produit ce que vous attendiez avant d'impliquer un hôte SCADA. Le broker que vous venez d'utiliser est le serveur MQTT public gratuit ; il est lisible par tous, n'y mettez donc ni vrais noms de tags ni vraies valeurs.
Du code de référence à un vrai edge node
Une fois l'exemple fonctionnel, un edge node de production a besoin de plus que ce que Tahu fournit d'origine :
- bdSeq persistant. Stockez le compteur sur disque pour qu'il s'incrémente d'un redémarrage du processus à l'autre.
- Report by exception. Ne publiez que les valeurs modifiées, avec des bandes mortes pour les signaux analogiques bruités.
- Store and forward. Mettez les données en tampon pendant les pannes du broker et rejouez-les avec les indicateurs historiques.
- Alias. Activez les alias de métriques Sparkplug sur les liaisons contraintes.
- Prise en compte de l'hôte primaire. Dans Sparkplug 3.0, les edge nodes peuvent attendre le message STATE de l'hôte primaire avant de publier leurs births.
- TLS et identifiants. Passez au port 8883 avec des identifiants propres à chaque client.
Si vous voulez un script entièrement autonome sans les utilitaires de Tahu, notre simulateur d'edge node Sparkplug B construit les payloads directement à partir du module Protobuf généré et gère explicitement numéros de séquence et rebirths. Pour le fonctionnement interne des payloads, consultez les types de données Sparkplug B. La spécification elle-même est publiée par le groupe de travail Eclipse Sparkplug.
En production, connectez les nœuds basés sur Tahu à un broker privé. Sur ConnectMQ, créez un broker dans le portail, copiez les YOUR_USERNAME, YOUR_PASSWORD et YOUR_CLIENT_ID générés, renseignez le client ID dans le script, ajoutez client.username_pw_set(...) et client.tls_set(), et connectez-vous au port 8883. ConnectMQ peut alors republier les données Sparkplug B décodées dans des topics ISA-95 comme connectmq/factory1/production/line1/cnc1/telemetry, que des consommateurs non Sparkplug peuvent lire comme des données ordinaires. L'architecture d'ensemble est traitée dans notre guide de l'IoT industriel avec MQTT.
Connecter Eclipse Tahu à ConnectMQ
Tahu vous donne des payloads corrects ; il vous faut encore un broker fiable entre le terrain et l'hôte. ConnectMQ est un broker MQTT managé avec MQTT 3.1.1 et 5.0, TLS sur le port 8883, décodage Sparkplug B et republication ISA-95. Créez un broker avec l'offre Serverless gratuite sur app.connectmq.com, sans carte bancaire, et pointez votre edge node Tahu vers lui en quelques minutes.
Questions fréquentes
Eclipse Tahu est-il un broker ?
Non. Eclipse Tahu fournit des bibliothèques et des exemples Sparkplug. Les edge nodes et les hôtes construits avec lui se connectent comme clients MQTT à n'importe quel broker MQTT conforme.
Quel langage Tahu choisir ?
Java pour les applications hôtes et les passerelles JVM, Python pour les scripts, simulateurs et tests, et C pour les passerelles embarquées aux budgets mémoire serrés.
Pourquoi les exemples Python de Tahu échouent-ils avec paho-mqtt 2.x ?
paho-mqtt 2.x exige une version d'API de callbacks lors de la création du client. Fixez paho-mqtt sous la version 2.0 pour les exemples, ou passez mqtt.CallbackAPIVersion.VERSION1 pour conserver leurs signatures de callbacks.
Tahu est-il prêt pour la production ?
C'est du code de référence axé sur l'exactitude. Beaucoup d'équipes utilisent ses définitions Protobuf et ses utilitaires de payload en production, en y ajoutant leur propre gestion de session, mise en tampon et sécurité.



