IoT industrial

Formato del payload Sparkplug B: métricas, tipos de datos y Protobuf

Los payloads Sparkplug B son mensajes Protobuf compactos, y por eso parecen un galimatías en un cliente MQTT normal. Esta guía recorre cada campo, muestra un ejemplo decodificado y explica cómo inspeccionar payloads en la práctica.

Diagrama de un payload Sparkplug B desglosado en marca de tiempo, número de secuencia y una lista de métricas tipadas
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

Un payload Sparkplug B es un mensaje codificado en Protobuf que transporta una marca de tiempo, un número de secuencia y una lista de métricas tipadas. Al terminar esta guía sabrás qué significa cada campo, por qué los bytes en bruto resultan ilegibles en un cliente MQTT corriente y cómo inspeccionar payloads rápidamente durante la puesta en marcha o la depuración de un edge node.

Por qué los payloads Sparkplug B parecen un galimatías

Si te suscribes a spBv1.0/# con una herramienta genérica como mosquitto_sub, verás nombres de tags legibles rodeados de caracteres extraños. No se trata de datos corruptos. Sparkplug B utiliza Google Protocol Buffers, un formato de serialización binario, de modo que los números de campo, las longitudes y los valores numéricos se escriben como varints compactos y bytes de ancho fijo en lugar de texto.

Es una decisión deliberada. Las redes industriales suelen funcionar sobre enlaces celulares, backhaul satelital o Ethernet de planta congestionada, y un gateway puede publicar miles de tags. Una codificación binaria mantiene los mensajes pequeños, conserva los tipos numéricos exactos (un contador sin signo de 64 bits sigue siendo un contador sin signo de 64 bits) y ofrece a todos los consumidores el mismo esquema. El precio es que necesitas el esquema, el archivo sparkplug_b.proto, para convertir los bytes de nuevo en algo legible.

Pruébalo tú mismo con un suscriptor genérico:

mosquitto_sub -h broker.connectmq.com -p 1883 -i payload-viewer-7f3a -t "spBv1.0/demo-7f3a/#" -v

Todo lo que publique un edge node Sparkplug en ese grupo se mostrará como texto parcialmente binario. Para interpretarlo, necesitas entender la estructura subyacente.

La estructura del payload Sparkplug B

El esquema se encuentra en el proyecto Eclipse Tahu como sparkplug_b.proto. En el nivel superior hay un único mensaje Payload:

message Payload {
    optional uint64 timestamp = 1;   // ms desde la época Unix, UTC
    repeated Metric metrics   = 2;   // los datos propiamente dichos
    optional uint64 seq       = 3;   // 0-255, vuelve a empezar
    optional string uuid      = 4;   // identificador de esquema opcional
    optional bytes  body      = 5;   // bytes opacos opcionales
}
Campo Tipo Finalidad Notas
timestamp uint64 Momento en que se creó el payload Milisegundos desde la época Unix en UTC
metrics repeated Metric Los valores de tags que se reportan Puede contener una métrica o miles
seq uint64 Número de secuencia del mensaje De 0 a 255 y luego vuelve a 0
uuid string Identificador opcional del esquema del payload Rara vez se usa en la práctica
body bytes Bytes opcionales específicos de la aplicación Sparkplug no los interpreta

El campo seq es lo que permite a una aplicación host detectar mensajes perdidos. El NBIRTH empieza en 0 y cada mensaje posterior del mismo edge node lo incrementa en uno. Un salto significa que algo se perdió, lo que normalmente desencadena una solicitud de rebirth. Ese flujo de recuperación se denomina rebirth.

Dentro de una métrica

La mayor parte de los datos interesantes está en el mensaje Metric. Cada métrica es un único valor con nombre y metadatos opcionales:

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;
    }
}

Algunos puntos que suelen confundir:

  • name frente a alias. Los mensajes de birth deben incluir el nombre completo de la métrica, como Line1/Spindle/Speed. Si el edge node asigna un alias, los mensajes NDATA y DDATA posteriores pueden enviar solo el alias numérico para ahorrar bytes. Un decodificador que no haya visto el birth no puede traducir el alias de vuelta a un nombre.
  • datatype es un número. El campo datatype es un código entero, como 3 para Int32, 9 para Float o 12 para String. Indica cómo interpretar el campo de valor. La lista completa está en nuestra referencia de tipos de datos de Sparkplug B.
  • El campo de valor depende del tipo. De Int8 a UInt32 viajan en int_value; Int64, UInt64 y DateTime en long_value. Los valores con signo en un campo sin signo se codifican en complemento a dos, así que un decodificador tiene que consultar datatype para recuperar correctamente un número negativo.
  • is_null es explícito. Una métrica puede existir sin valor actual. En lugar de enviar cero, el nodo pone is_null a true, algo importante para los consumidores que tienen en cuenta la calidad del dato.
  • is_historical e is_transient. Las métricas históricas transportan datos de relleno (backfill) que no deben sobrescribir el valor en vivo. Las métricas transitorias deben mostrarse, pero un historian no debe almacenarlas.

Un ejemplo decodificado

Así se ve un payload DDATA típico de una máquina CNC tras decodificarlo, representado como JSON para facilitar la lectura:

{
  "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 }
  ]
}

Fíjate en dos detalles. Primero, las métricas tienen alias pero no nombres, así que necesitas el DBIRTH para saber que el alias 3 es la velocidad del husillo. Segundo, la métrica Int32 muestra 4294967291 en el campo sin signo en bruto. Interpretado como entero de 32 bits con signo, es -5. Este es justo el tipo de cosa que un decodificador ingenuo interpreta mal.

El DBIRTH correspondiente contendría las definiciones completas:

{
  "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 }
  ]
}

Propiedades, DataSets y Templates

Más allá de los escalares simples, el payload Sparkplug B puede transportar estructuras más ricas:

  1. PropertySet. Una lista de claves y valores tipados asociada a una métrica. La conocida propiedad Quality usa 192 para bueno, 0 para malo y 500 para obsoleto (stale). También se pueden adjuntar como propiedades unidades de ingeniería, rangos y descripciones.
  2. DataSet. Una pequeña tabla con nombres de columna, tipos de columna y filas. Útil para parámetros de receta o un lote de lecturas.
  3. Template. Un tipo definido por el usuario, similar a un UDT en un PLC. La definición de un template se declara una vez en el NBIRTH y las instancias hacen referencia a ella. Los templates son la forma en que Sparkplug modela bombas, motores y otros equipos repetidos.
  4. MetaData. Información para métricas de bytes y de archivo, como tipo de contenido, tamaño, MD5 y nombre de archivo.

La mayoría de los sistemas en producción usan escalares con una propiedad Quality. Los DataSets y los templates son potentes pero añaden complejidad, así que introdúcelos solo cuando una lista plana de métricas se vuelva difícil de gestionar.

Cómo leer payloads Sparkplug B en la práctica

Tienes tres opciones prácticas para convertir datos binarios de Sparkplug en algo legible.

Decodificar con tu propio código

Compila sparkplug_b.proto para tu lenguaje y analiza cada mensaje. Es la opción adecuada para consumidores en producción, y en Python son apenas unas líneas. Nuestro tutorial sobre cómo decodificar Sparkplug B en Python recorre un suscriptor completo, incluida la resolución de alias y el tratamiento de enteros con signo.

Usar las bibliotecas de referencia de Tahu

El proyecto Eclipse Tahu ofrece el archivo proto canónico e implementaciones de referencia en varios lenguajes. Son un buen punto de partida cuando construyes un edge node o una aplicación host y quieres un comportamiento acorde con la especificación.

Usar un broker que decodifique por ti

Durante la puesta en marcha no quieres escribir código solo para comprobar si un tag está publicando. ConnectMQ detecta los topics Sparkplug B, decodifica payloads Protobuf (y Sparkplug codificado en JSON) y los muestra de forma legible en el explorador de topics del portal. También puede republicar datos Sparkplug en topics ISA-95, de modo que spBv1.0/factory1/DDATA/line1/cnc1 queda disponible como connectmq/factory1/production/line1/cnc1/telemetry para herramientas que no hablan Protobuf. Si alojas tu propio broker, necesitarías un servicio de decodificación aparte para obtener la misma vista.

Errores habituales con el payload

Síntoma Causa probable Solución
Las métricas muestran números en lugar de nombres El decodificador no recibió el mensaje de birth Solicita un rebirth o arranca el consumidor antes que el nodo
Los valores negativos aparecen como números enormes Tipo con signo leído desde un campo sin signo Aplica complemento a dos según datatype
Las marcas de tiempo parecen del año 50000 Confusión entre segundos y milisegundos Las marcas de tiempo de Sparkplug siempre están en milisegundos
DecodeError en el parser El payload no es Sparkplug B, o la versión del proto es incorrecta Comprueba que el topic empieza por spBv1.0 y usa el proto de Tahu
Seq salta de forma inesperada Mensajes perdidos o dos nodos con el mismo ID Asegura IDs de edge node únicos y usa el QoS adecuado

La mayoría de estos problemas aparecen durante la puesta en marcha. Tener abierta una vista decodificada en vivo mientras levantas un nuevo gateway ahorra muchas conjeturas.

Cómo encaja el payload en el panorama general

El payload es solo la mitad de Sparkplug. La otra mitad es el namespace de topics de Sparkplug y las reglas de estado construidas en torno a los certificados de birth y death. Juntos hacen que los datos sean autodescriptivos y conscientes del estado, y por eso Sparkplug es tan popular como transporte para un Unified Namespace. Para la visión de arquitectura, lee MQTT, Sparkplug B y el Unified Namespace y nuestra guía principal sobre IoT industrial con MQTT.

Cualquier broker MQTT que cumpla el estándar puede transportar Sparkplug B, porque el broker nunca necesita analizar el payload para enrutarlo. Lo que aporta un broker compatible con Sparkplug es visibilidad: vistas decodificadas, republicación legible y detección de la estructura de topics, que hacen los datos binarios accesibles para todo el equipo.

Empieza con ConnectMQ

Apunta un edge node o simulador Sparkplug al servidor MQTT público gratuito con un group ID único y pasa después a tu propio broker MQTT gestionado cuando necesites credenciales y aislamiento. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y observa tus payloads Sparkplug B decodificados en vivo en el explorador de topics de ConnectMQ.

Preguntas frecuentes

¿Un payload Sparkplug B es siempre Protobuf?

La especificación define Protobuf como la codificación de Sparkplug B. Algunas herramientas también generan una representación JSON de la misma estructura para depuración o integración, y ConnectMQ puede decodificar ambas formas.

¿Por qué mis métricas tienen alias pero no nombres?

El edge node envió los nombres completos solo en su certificado de birth y después usa alias numéricos para ahorrar ancho de banda. Tu consumidor debe guardar la correspondencia entre nombre y alias del NBIRTH o DBIRTH, o solicitar un rebirth para obtenerla de nuevo.

¿Cuál es el tamaño máximo de un payload Sparkplug B?

Sparkplug en sí no fija un límite pequeño, pero tu broker sí. En el broker público de ConnectMQ los mensajes están limitados a 64 KB, y los planes Serverless permiten 256 KB (gratuito) o 1 MB (de pago).

¿Necesito el archivo proto para leer datos Sparkplug?

Sí, salvo que una herramienta los decodifique por ti. El archivo sparkplug_b.proto de Eclipse Tahu es el esquema canónico, y todos los decodificadores de Sparkplug se basan en él.

Artículos relacionados

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.