Sparkplug B
Sparkplug B es MQTT — no sustituye al MQTT del CMS, es una especificación que corre sobre él (MQTT 3.1.1) y llena lo que el MQTT deja abierto:
MQTT puro (MQTT_TOPIC_SUBSCRIBER) | Sparkplug B (SPARKPLUG_SUBSCRIBER) | |
|---|---|---|
| Tópico | usted lo escribe (fabrica/linea1/horno/temp) | namespace fijo spBv1.0/{grupo}/{tipo}/{edge}/{device} |
| Payload | lo que mande el origen (JSON, texto, número) | protobuf, con tipo y timestamp por métrica |
| Descubrir tags | alguien documenta y usted registra | vienen en el BIRTH, cuando el dispositivo conecta |
| Dispositivo caído | silencio, indistinguible de “nada cambió” | DEATH publicado por el broker, al instante |
| Mensaje perdido | invisible | hueco en el número de secuencia (seq) |
| Escribir de vuelta | publicar en un tópico acordado | NCMD/DCMD estandarizados |
Use Sparkplug cuando el otro lado habla Sparkplug — Ignition, HiveMQ Edge, Kepware, Cirrus Link, Opto 22. Un sensor que publica JSON en un tópico sigue siendo un caso de MQTT puro.
Conexión
Ninguna conexión nueva: use la misma Conexión Externa MQTT del broker (host, puerto, credenciales). Hay solo un campo más, opcional:
Primary Host ID — si se completa, el CMS se anuncia como Host Application del namespace:
publica spBv1.0/STATE/{hostId} como ONLINE al conectar y registra OFFLINE como Last Will. Varios
gateways usan esa señal para activar store-and-forward cuando el host se cae.
Complete el Primary Host ID solo si ningún otro host (un Ignition, por ejemplo) ya ejerce ese rol con el mismo ID en su namespace. En blanco, el CMS es solo un suscriptor más y no interfiere.
Recolección — SPARKPLUG_SUBSCRIBER
La Recolección apunta a un recorte del namespace, no a un tópico:
| Campo | Rol |
|---|---|
| Group ID | agrupa los edge nodes de una planta/área |
| Edge Node ID | el gateway |
| Device ID | opcional — en blanco, recolecta de todos los devices del nodo |
| Incluir métricas del edge node | trae también NBIRTH/NDATA (CPU, uptime del gateway) |
| Solicitar Rebirth | al conectar, pide que el nodo vuelva a anunciar sus métricas |
Cada NDATA/DDATA se convierte en un mensaje con las métricas que cambiaron (report by
exception, como la propia spec):
{ "grupo": "Fabrica01", "edgeNode": "GW_L1", "device": "Forno_A", "tipo": "DDATA", "seq": 42,
"timestamp": "2026-08-21T19:00:00.000Z", "recebidoEm": "2026-08-21T19:00:03.120Z",
"metricas": { "Temperatura": 812.5, "Status": "RUN" } }timestamp es la marca del origen (cuándo midió el dispositivo), no la de la llegada — es una
de las razones de existir de Sparkplug, y lo que permite ordenar correctamente datos que se
atrasaron en la red.
Descubrir tags
El botón Descubrir tags en la pantalla de la Recolección muestra el catálogo de métricas de cada device: nombre, tipo de dato y el último valor anunciado. El catálogo queda guardado, así que la pantalla abre con él incluso si el dispositivo está offline; el botón publica un Rebirth y actualiza.
Rebirth y orden
Después del BIRTH, las métricas viajan solo con el alias numérico — quien no tiene el catálogo
no sabe qué es alias 7. Por eso el CMS pide Rebirth cuando conecta, cuando recibe datos de un nodo
sin BIRTH conocido y cuando el seq salta (señal de mensaje perdido). Los pedidos están limitados a
uno cada 30 s por nodo.
La caída de un edge node (NDEATH) o de un device (DDEATH) marca la recolección como desconectada
y dispara la alerta Dispositivo Sparkplug Offline — distinta de Conexión MQTT Perdida, que es
la caída del broker.
Float en Sparkplug es de 32 bits: un valor 33,3 vuelve como 33.29999923706055. Para precisión
decimal exacta use métricas Double en el gateway.
Entrega — SPARKPLUG_CMD
Escribe métricas en el dispositivo publicando DCMD (Device ID completado) o NCMD (en blanco). El
mapeo es el mismo de las Tags de Escritura OPC UA: cada línea liga un alias esperado en el
payload a una métrica del dispositivo, con el tipo de dato usado en la codificación.
| Campo de la línea | Rol |
|---|---|
| Alias | clave en el payload del mensaje |
| Métrica | nombre en el dispositivo (destino del comando) |
| Tipo | Boolean, Int32, Int64, Float, Double, String o DateTime |
| Valor predeterminado | usado cuando el mensaje no trae el alias |
| Obligatorio | sin valor (y sin predeterminado), la entrega falla y nada se publica |
Los alias se resuelven contra el payload ya transformado — si hay un Transformador en la definición o en el reenvío, vale su salida. (Las Tags de Escritura OPC UA/Modbus hacen lo contrario: leen el payload original.)
El retorno grabado es {"topico": "spBv1.0/.../DCMD/...", "metricas": N}.
Probar sin gateway real
El repositorio trae un simulador de edge node que publica un ciclo de vida completo y responde a comandos:
docker compose -f docker-compose.test.yml up -d mosquitto # broker local (opcional)
node tools/sparkplug-simulador/edge-node.mjs --broker mqtt://localhost:18830
node tools/sparkplug-simulador/edge-node.mjs --morrer 30 # publica NDEATH tras 30 s