Un payload Sparkplug B est un message encodé en Protobuf qui transporte un horodatage, un numéro de séquence et une liste de métriques typées. À la fin de ce guide, vous saurez ce que signifie chaque champ, pourquoi les octets bruts semblent illisibles dans un client MQTT ordinaire, et comment inspecter rapidement les payloads lorsque vous mettez en service ou déboguez un edge node.
Pourquoi les payloads Sparkplug B ressemblent à du charabia
Si vous vous abonnez à spBv1.0/# avec un outil générique comme mosquitto_sub, vous verrez des noms de tags lisibles entourés de caractères étranges. Il ne s'agit pas d'une corruption. Sparkplug B utilise Google Protocol Buffers, un format de sérialisation binaire : les numéros de champ, les longueurs et les valeurs numériques sont écrits sous forme de varints compacts et d'octets à largeur fixe plutôt qu'en texte.
Ce compromis est délibéré. Les réseaux industriels passent souvent par des liaisons cellulaires, des liaisons satellites ou un Ethernet d'usine saturé, et une passerelle peut publier des milliers de tags. Un encodage binaire garde des messages petits, préserve les types numériques exacts (un compteur non signé 64 bits reste un compteur non signé 64 bits) et donne le même schéma à tous les consommateurs. La contrepartie : il vous faut le schéma, le fichier sparkplug_b.proto, pour retransformer les octets en quelque chose de lisible.
Essayez vous-même avec un abonné générique :
mosquitto_sub -h broker.connectmq.com -p 1883 -i payload-viewer-7f3a -t "spBv1.0/demo-7f3a/#" -v
Tout ce qu'un edge node Sparkplug publie dans ce groupe s'affichera sous forme de texte partiellement binaire. Pour lui donner du sens, il faut comprendre la structure sous-jacente.
La structure du payload Sparkplug B
Le schéma se trouve dans le projet Eclipse Tahu, sous le nom sparkplug_b.proto. Au niveau supérieur, il n'y a qu'un seul message Payload :
message Payload {
optional uint64 timestamp = 1; // ms depuis l'epoch Unix, UTC
repeated Metric metrics = 2; // les données proprement dites
optional uint64 seq = 3; // 0-255, reboucle
optional string uuid = 4; // identifiant de schéma optionnel
optional bytes body = 5; // octets opaques optionnels
}
| Champ | Type | Rôle | Remarques |
|---|---|---|---|
| timestamp | uint64 | Heure de création du payload | Millisecondes depuis l'epoch, en UTC |
| metrics | repeated Metric | Les valeurs de tags transmises | Peut contenir une métrique ou des milliers |
| seq | uint64 | Numéro de séquence du message | De 0 à 255, puis retour à 0 |
| uuid | string | Identifiant optionnel du schéma du payload | Rarement utilisé en pratique |
| body | bytes | Octets optionnels propres à l'application | Non interprétés par Sparkplug |
C'est le champ seq qui permet à une application hôte de détecter des messages perdus. Le NBIRTH commence à 0 et chaque message suivant du même edge node l'incrémente de un. Un trou signifie qu'un message a été manqué, ce qui déclenche généralement une demande de rebirth. Ce mécanisme de récupération s'appelle un rebirth.
À l'intérieur d'une métrique
L'essentiel des données intéressantes se trouve dans le message Metric. Chaque métrique est une valeur nommée unique, accompagnée de métadonnées optionnelles :
message Metric {
optional string name = 1;
optional uint64 alias = 2;
optional uint64 timestamp = 3;
optional uint32 datatype = 4;
optional bool is_historical = 5;
optional bool is_transient = 6;
optional bool is_null = 7;
optional MetaData metadata = 8;
optional PropertySet properties = 9;
oneof value {
uint32 int_value = 10;
uint64 long_value = 11;
float float_value = 12;
double double_value = 13;
bool boolean_value = 14;
string string_value = 15;
bytes bytes_value = 16;
DataSet dataset_value = 17;
Template template_value = 18;
MetricValueExtension extension_value = 19;
}
}
Quelques points qui piègent souvent :
- Nom ou alias. Les messages de birth doivent inclure le nom complet de la métrique, par exemple
Line1/Spindle/Speed. Si l'edge node attribue un alias, les messages NDATA et DDATA suivants peuvent n'envoyer que l'alias numérique pour économiser des octets. Un décodeur qui n'a pas vu le birth ne peut pas retrouver le nom à partir de l'alias. - datatype est un nombre. Le champ
datatypeest un code entier, par exemple 3 pour Int32, 9 pour Float ou 12 pour String. Il indique comment interpréter l'emplacement de la valeur. La liste complète figure dans notre référence des types de données Sparkplug B. - L'emplacement de la valeur dépend du type. Les types Int8 à UInt32 voyagent dans
int_value, Int64, UInt64 et DateTime danslong_value. Les valeurs signées stockées dans un champ non signé sont encodées en complément à deux : un décodeur doit donc consulterdatatypepour retrouver correctement un nombre négatif. - is_null est explicite. Une métrique peut exister sans valeur courante. Au lieu d'envoyer zéro, le nœud met
is_nullà true, ce qui compte pour les consommateurs attentifs à la qualité des données. - is_historical et is_transient. Les métriques historiques transportent des données rattrapées a posteriori qui ne doivent pas écraser la valeur en direct. Les métriques transitoires doivent être affichées mais pas stockées par un historian.
Un exemple décodé
Voici à quoi ressemble un payload DDATA typique provenant d'une machine CNC une fois décodé, présenté en JSON pour plus de lisibilité :
{
"timestamp": 1792137600123,
"seq": 42,
"metrics": [
{ "alias": 3, "timestamp": 1792137600120, "datatype": 9, "floatValue": 1487.5 },
{ "alias": 4, "timestamp": 1792137600120, "datatype": 11, "booleanValue": true },
{ "alias": 7, "timestamp": 1792137600121, "datatype": 3, "intValue": 4294967291 }
]
}
Remarquez deux détails. D'abord, les métriques ont des alias mais pas de noms : il vous faut le DBIRTH pour savoir que l'alias 3 correspond à la vitesse de broche. Ensuite, la métrique Int32 affiche 4294967291 dans le champ brut non signé. Interprétée comme un entier signé 32 bits, elle vaut -5. C'est exactement le genre d'erreur que commet un décodeur naïf.
Le DBIRTH correspondant contiendrait les définitions complètes :
{
"timestamp": 1792137590000,
"seq": 1,
"metrics": [
{ "name": "Spindle/Speed", "alias": 3, "datatype": 9, "floatValue": 0.0 },
{ "name": "Spindle/Running", "alias": 4, "datatype": 11, "booleanValue": false },
{ "name": "Axis/X/Offset", "alias": 7, "datatype": 3, "intValue": 0 }
]
}
Propriétés, DataSets et templates
Au-delà des scalaires simples, le payload Sparkplug B peut transporter des structures plus riches :
- PropertySet. Une liste de clés et de valeurs typées rattachée à une métrique. La propriété bien connue
Qualityutilise 192 pour bonne, 0 pour mauvaise et 500 pour périmée. Unités d'ingénierie, plages et descriptions peuvent aussi être attachées sous forme de propriétés. - DataSet. Un petit tableau avec des noms de colonnes, des types de colonnes et des lignes. Pratique pour des paramètres de recette ou un lot de mesures.
- Template. Un type défini par l'utilisateur, comparable à un UDT dans un automate. Une définition de template est déclarée une seule fois dans le NBIRTH et les instances y font référence. C'est avec les templates que Sparkplug modélise pompes, moteurs et autres équipements répétés.
- MetaData. Des informations pour les métriques de type octets et fichier, comme le type de contenu, la taille, le MD5 et le nom de fichier.
La plupart des systèmes de production utilisent des scalaires accompagnés d'une propriété Quality. Les DataSets et les templates sont puissants mais ajoutent de la complexité : ne les introduisez que lorsqu'une liste plate de métriques devient difficile à gérer.
Lire les payloads Sparkplug B en pratique
Vous disposez de trois options concrètes pour transformer des données Sparkplug binaires en quelque chose de lisible.
Décoder avec votre propre code
Compilez sparkplug_b.proto pour votre langage et analysez chaque message. C'est le bon choix pour des consommateurs en production, et cela ne demande que quelques lignes en Python. Notre tutoriel pour décoder Sparkplug B en Python présente un abonné complet, avec la résolution des alias et la gestion des entiers signés.
Utiliser les bibliothèques de référence Tahu
Le projet Eclipse Tahu fournit le fichier proto canonique et des implémentations de référence dans plusieurs langages. C'est un bon point de départ lorsque vous développez un edge node ou une application hôte et que vous voulez un comportement conforme à la spécification.
Utiliser un broker qui décode pour vous
Pendant la mise en service, vous ne voulez pas écrire du code simplement pour vérifier qu'un tag publie bien. ConnectMQ détecte les topics Sparkplug B, décode les payloads Protobuf (et Sparkplug encodé en JSON) et les affiche sous forme lisible dans l'explorateur de topics du portail. Il peut aussi republier les données Sparkplug dans des topics ISA-95 : spBv1.0/factory1/DDATA/line1/cnc1 devient ainsi disponible sous connectmq/factory1/production/line1/cnc1/telemetry pour les outils qui ne parlent pas Protobuf. Si vous hébergez votre propre broker, il vous faudrait un service de décodage distinct pour obtenir la même vue.
Pièges courants liés au payload
| Symptôme | Cause probable | Solution |
|---|---|---|
| Les métriques affichent des nombres au lieu de noms | Le décodeur a manqué le message de birth | Demander un rebirth ou démarrer le consommateur avant le nœud |
| Les valeurs négatives apparaissent comme d'énormes nombres | Type signé lu depuis un champ non signé | Appliquer le complément à deux en fonction de datatype |
| Les horodatages semblent dater de l'an 50000 | Confusion entre secondes et millisecondes | Les horodatages Sparkplug sont toujours en millisecondes |
| DecodeError dans le parseur | Le payload n'est pas du Sparkplug B, ou mauvaise version du proto | Vérifier que le topic commence par spBv1.0 et utiliser le proto Tahu |
| Seq fait des sauts inattendus | Messages perdus ou deux nœuds avec le même ID | Garantir des ID d'edge node uniques et choisir la QoS adaptée |
La plupart de ces problèmes apparaissent pendant la mise en service. Garder une vue décodée en direct ouverte pendant que vous démarrez une nouvelle passerelle évite bien des tâtonnements.
La place du payload dans l'ensemble
Le payload n'est que la moitié de Sparkplug. L'autre moitié, c'est l'espace de noms des topics Sparkplug et les règles d'état construites autour des certificats de birth et de death. Ensemble, ils rendent les données autodescriptives et conscientes de leur état, ce qui explique la popularité de Sparkplug comme transport d'un Unified Namespace. Pour la vue architecturale, lisez MQTT, Sparkplug B et le Unified Namespace ainsi que notre guide de référence sur l'IoT industriel avec MQTT.
N'importe quel broker MQTT conforme aux standards peut transporter du Sparkplug B, car le broker n'a jamais besoin d'analyser le payload pour le router. Ce qu'apporte un broker compatible Sparkplug, c'est la visibilité : vues décodées, republication lisible et détection de la structure des topics, qui rendent les données binaires accessibles à toute l'équipe.
Démarrer avec ConnectMQ
Pointez un edge node Sparkplug ou un simulateur vers le serveur MQTT public gratuit avec un group ID unique, puis passez à votre propre broker MQTT managé lorsque vous avez besoin d'identifiants et d'isolation. Créez un broker Serverless gratuit sur app.connectmq.com, sans carte bancaire, et observez vos payloads Sparkplug B décodés en direct dans l'explorateur de topics de ConnectMQ.
Questions fréquentes
Un payload Sparkplug B est-il toujours en Protobuf ?
La spécification définit Protobuf comme l'encodage de Sparkplug B. Certains outils produisent aussi une représentation JSON de la même structure pour le débogage ou les passerelles, et ConnectMQ sait décoder les deux formes.
Pourquoi mes métriques ont-elles des alias mais pas de noms ?
L'edge node n'a envoyé les noms complets que dans son certificat de birth et utilise ensuite des alias numériques pour économiser de la bande passante. Votre consommateur doit conserver la correspondance nom-alias issue du NBIRTH ou du DBIRTH, ou demander un rebirth pour l'obtenir à nouveau.
Quelle est la taille maximale d'un payload Sparkplug B ?
Sparkplug lui-même ne fixe pas de limite basse, mais votre broker, si. Sur le serveur MQTT public gratuit de ConnectMQ, les messages sont limités à 64 Ko, et les offres Serverless autorisent 256 Ko (gratuit) ou 1 Mo (payant).
Ai-je besoin du fichier proto pour lire des données Sparkplug ?
Oui, sauf si un outil les décode pour vous. Le fichier sparkplug_b.proto d'Eclipse Tahu est le schéma canonique, et tous les décodeurs Sparkplug reposent sur lui.



