El soporte de Sparkplug B en Node-RED permite que un flujo low-code se comporte como un auténtico edge node industrial: anuncia sus métricas con certificados de birth, publica datos Protobuf compactos, informa de su death cuando se desconecta y acepta comandos. En este tutorial construirás un edge node Sparkplug B para una máquina CNC simulada, consumirás y decodificarás los datos en un segundo flujo y comprobarás el resultado en un broker que entiende Sparkplug. Por el camino aprenderás qué detalles de la especificación dan más problemas.
Sparkplug B en pocas palabras
Sparkplug B es una especificación de la Eclipse Foundation que funciona sobre MQTT. MQTT por sí solo no dice nada sobre la estructura de los topics ni sobre el formato del payload; Sparkplug define ambas cosas, además del estado de sesión, para que equipos de distintos fabricantes interoperen de serie con aplicaciones SCADA y MES.
Las ideas clave:
- Namespace de topics:
spBv1.0/<group_id>/<message_type>/<edge_node_id>/[<device_id>]. - Payload: Google Protocol Buffers con una lista de métricas, cada una con nombre, tipo de dato, valor y marca de tiempo.
- Conciencia de sesión: un edge node publica
NBIRTHal conectarse y registra unNDEATHcomo su Last Will de MQTT. Los dispositivos que hay detrás publicanDBIRTHyDDEATH. - Report by exception: tras el birth, los mensajes
DDATAsolo contienen las métricas que han cambiado. - Comandos: las aplicaciones envían mensajes
NCMDyDCMD, incluida una petición de "Rebirth".
| Mensaje | Dirección | Significado |
|---|---|---|
| NBIRTH / DBIRTH | Del edge al broker | Lista completa de métricas con tipos y valores actuales |
| NDATA / DDATA | Del edge al broker | Solo las métricas modificadas |
| NDEATH / DDEATH | Del edge al broker (NDEATH vía Last Will) | Nodo o dispositivo fuera de línea |
| NCMD / DCMD | De la aplicación al edge | Escribir una métrica o pedir un rebirth |
| STATE | Primary host application | Si la aplicación host está en línea |
Para la gramática completa de los topics, consulta la guía del namespace de topics de Sparkplug, y para ver cómo los births y deaths mantienen la coherencia del estado, lee certificados de birth y death en Sparkplug.
Instala los nodos Sparkplug
La implementación de Sparkplug más completa para Node-RED es node-red-contrib-mqtt-sparkplug-plus. Instálala desde el gestor de paleta o desde la línea de comandos:
cd ~/.node-red
npm install node-red-contrib-mqtt-sparkplug-plus
# restart Node-RED afterwards
Añade tres nodos y un nodo de configuración:
- mqtt sparkplug device: representa un dispositivo detrás del edge node. Gestiona por ti DBIRTH, DDATA, DDEATH y DCMD.
- mqtt sparkplug in: se suscribe a topics Sparkplug y decodifica el payload Protobuf en un objeto JavaScript.
- mqtt sparkplug out: publica mensajes Sparkplug en bruto cuando necesitas control total.
- Sparkplug broker config: la conexión MQTT más el Group ID y el Edge Node ID de Sparkplug. Publica NBIRTH y registra NDEATH automáticamente.
Construye un edge node Sparkplug B en Node-RED
Paso 1: configura el broker y la identidad
Añade un nodo mqtt sparkplug device y crea una nueva configuración de broker:
- Servidor:
broker.connectmq.com, puerto1883, con un client ID único. Es el servidor MQTT público gratuito, así que todo lo que publiques puede leerlo cualquiera; usa solo datos simulados. - Group ID:
demo-a7f3k2. Los topics Sparkplug deben empezar porspBv1.0, así que aquí no puedes usar el prefijo habitualconnectmq/demo/.... En su lugar, haz que el group ID sea único sustituyendoa7f3k2por tu propia cadena aleatoria. - Edge Node ID:
line1.
Después pon cnc1 como nombre del dispositivo en el nodo device. El dispositivo publicará en spBv1.0/demo-a7f3k2/DDATA/line1/cnc1.
Paso 2: define las métricas
En el nodo device, añade métricas con nombres y tipos de dato Sparkplug:
| Nombre de la métrica | Tipo de dato | Significado |
|---|---|---|
spindle/speed |
Int32 | Velocidad del husillo en rpm |
spindle/load |
Float | Carga del husillo en porcentaje |
coolant/temperature |
Float | Temperatura del refrigerante en °C |
running |
Boolean | Máquina en marcha |
partCount |
Int64 | Contador acumulado de piezas |
Declarar los tipos importa: el DBIRTH indica a cada consumidor qué esperar, y una aplicación host rechazará o malinterpretará datos que cambien de tipo más adelante. Por defecto el nodo espera a que todas las métricas hayan recibido un valor antes de publicar el DBIRTH, lo que evita un certificado de birth lleno de valores vacíos.
Paso 3: aliméntalo con datos
Un nodo inject que se repite cada 2 segundos alimenta un nodo function que simula la máquina. El nodo device espera msg.payload.metrics como un array de pares nombre-valor:
// Function node "simulate cnc1" -> mqtt sparkplug device
let parts = context.get("parts") || 0;
const running = Math.random() > 0.1;
if (running) {
parts += 1;
}
context.set("parts", parts);
msg.payload = {
metrics: [
{ name: "spindle/speed", value: running ? Math.round(11800 + Math.random() * 400) : 0 },
{ name: "spindle/load", value: running ? Math.round(450 + Math.random() * 200) / 10 : 0 },
{ name: "coolant/temperature", value: Math.round((21 + Math.random() * 3) * 10) / 10 },
{ name: "running", value: running },
{ name: "partCount", value: parts }
]
};
return msg;
Despliega. La configuración del broker publica el NBIRTH de line1, el dispositivo publica el DBIRTH de cnc1 y, a partir de ahí, solo salen las métricas modificadas en mensajes DDATA.
Paso 4: gestiona los comandos
Cuando una aplicación envía un DCMD a spBv1.0/demo-a7f3k2/DCMD/line1/cnc1, el nodo device lo emite por su salida como un mensaje con las métricas solicitadas. Conecta la salida a un nodo function que valide la petición y actúe en consecuencia, por ejemplo reiniciando el contador de piezas:
// Function node "handle DCMD" (wired from the device node output)
const metrics = (msg.payload && msg.payload.metrics) || [];
for (const m of metrics) {
if (m.name === "partCount" && Number(m.value) === 0) {
flow.set("cnc1_reset_requested", true);
node.warn("Part counter reset requested");
} else {
node.warn("Ignored command for metric " + m.name);
}
}
return null;
Para que el simulador respete el reinicio, lee cnc1_reset_requested del contexto del flujo en el simulador y vuelve a poner parts a cero. Las peticiones de rebirth las gestiona el propio nodo, que vuelve a publicar los certificados de birth.
Consume y decodifica Sparkplug B en Node-RED
Los payloads Sparkplug son binarios. Un nodo mqtt in normal sobre spBv1.0/# te daría un Buffer lleno de bytes Protobuf. El nodo mqtt sparkplug in los decodifica:
- Añade un nodo mqtt sparkplug in que use una configuración de broker aparte, con su propio client ID único.
- Suscríbete a
spBv1.0/demo-a7f3k2/+/line1/#. - Conéctalo a un nodo debug configurado para mostrar el mensaje completo.
Verás objetos con un timestamp, un número seq y un array metrics. Para que los datos sean útiles a consumidores que no hablan Sparkplug, aplánalos en un topic MQTT sencillo por métrica:
// Function node "sparkplug to plain topics"
// msg.topic: spBv1.0/<group>/<type>/<edge>/<device>
const t = msg.topic.split("/");
const type = t[2];
if (type !== "DDATA" && type !== "DBIRTH") {
return null;
}
const group = t[1];
const edge = t[3];
const device = t[4];
const out = [];
for (const m of msg.payload.metrics || []) {
// Sparkplug allows "/" in metric names; keep each metric to one topic level
const metric = String(m.name).replace(/\//g, "_");
let value = m.value;
if (value !== null && typeof value === "object" && typeof value.toNumber === "function") {
value = value.toNumber(); // 64-bit integers may arrive as Long objects
}
out.push({
topic: `connectmq/demo/a7f3k2/${group}/${edge}/${device}/${metric}`,
payload: { value: value, ts: Number(m.timestamp) || Date.now() },
retain: true
});
}
return [out];
Conéctalo a un nodo mqtt out con los campos de topic y retain vacíos. Ahora un panel, un script o una hoja de cálculo pueden suscribirse a connectmq/demo/a7f3k2/demo-a7f3k2/line1/cnc1/spindle_speed sin saber nada de Protobuf. Es la misma idea que la arquitectura Sparkplug más UNS descrita en Sparkplug B y el Unified Namespace.
Comprueba los datos en un broker que entiende Sparkplug
Los nodos debug demuestran que Node-RED puede decodificar sus propios mensajes, pero vale la pena comprobarlo con una herramienta independiente. ConnectMQ decodifica payloads Sparkplug B, tanto Protobuf como JSON, así que en el portal ves las métricas de cada mensaje DBIRTH y DDATA en lugar de bytes en bruto. También puede republicar los datos Sparkplug en topics ISA-95; por ejemplo, spBv1.0/factory1/DDATA/line1/cnc1 se convierte en connectmq/factory1/production/line1/cnc1/telemetry, lo que te da el paso de aplanado anterior sin tener que mantener tú el nodo function.
Para probarlo, crea un broker gratuito en el portal de ConnectMQ y cambia la configuración del broker Sparkplug en Node-RED al host de ese broker, puerto 8883 con TLS, y al usuario, la contraseña y el client ID generados. Después abre el explorador de topics en vivo y observa cómo llegan decodificados los births y los datos.
Errores habituales con Sparkplug
- Reutilizar client IDs. Dos edge nodes con el mismo client ID de MQTT se expulsan mutuamente una y otra vez, y cada reconexión produce un nuevo NDEATH y NBIRTH. Cada edge node necesita un client ID único.
- Cambiar el tipo de las métricas. Una métrica declarada como Int32 no debe transportar más tarde un float. Corrige la definición y fuerza un rebirth.
- Consumidores sin births. Un consumidor que arranca después del birth solo ve DDATA con las métricas modificadas. Debería enviar un NCMD de Rebirth, o leer el estado retenido en otro lugar, antes de fiarse de su visión.
- Ignorar los números de secuencia. El campo
seqva de 0 a 255 y vuelve a empezar. Un hueco significa que se perdió un mensaje y que conviene pedir un rebirth. - Niveles de topic. Los IDs de grupo, edge y dispositivo son niveles de topic individuales y no deben contener
/,+ni#. - Expectativas de QoS. Los mensajes de datos suelen usar QoS 0, mientras que NDEATH y STATE usan QoS 1. Asegúrate de que el plan de tu broker admite QoS 1.
Del piloto a producción
Una arquitectura Sparkplug concentra en el broker todos los edge nodes, aplicaciones host e historiadores, de modo que el broker se convierte en infraestructura crítica. Usa conexiones autenticadas sobre TLS, client IDs únicos vinculados a credenciales y un broker que siga siendo accesible tanto desde la planta como desde la nube. Un broker MQTT en la nube se adapta a despliegues multiplanta, por ejemplo en Querétaro, Santiago y Bilbao, y un broker MQTT gestionado elimina la carga operativa de mantenerlo tú mismo. Para alimentar Sparkplug desde controladores existentes, combina este flujo con Node-RED y OPC UA como fuente de datos. Si eres nuevo con los nodos MQTT, empieza por el tutorial de Node-RED y MQTT.
Ejecuta tus edge nodes Sparkplug en ConnectMQ
Regístrate en app.connectmq.com con el plan gratuito Serverless, sin tarjeta de crédito. Crea un broker, apunta a él tu configuración Sparkplug de Node-RED con las credenciales generadas e inspecciona en el portal, en cuestión de minutos, los births, los datos y los deaths decodificados.
Preguntas frecuentes
¿Qué paquete de Node-RED admite Sparkplug B?
node-red-contrib-mqtt-sparkplug-plus es la opción más completa. Gestiona por ti los births, los deaths, los números de secuencia, las peticiones de rebirth y la codificación y decodificación Protobuf.
¿Puedo leer mensajes Sparkplug B con un nodo mqtt in normal?
Recibirás los bytes Protobuf en bruto como un Buffer. Usa el nodo mqtt sparkplug in, o un decodificador Protobuf en un nodo function, para convertirlos en métricas legibles.
¿Envía Node-RED el NDEATH automáticamente?
Sí. La configuración del broker Sparkplug registra el NDEATH como Last Will de MQTT al conectarse, de modo que el broker lo publica si el edge node se desconecta de forma inesperada.
¿Por qué solo aparecen algunas métricas en mis mensajes DDATA?
Sparkplug informa por excepción: DDATA solo lleva las métricas que han cambiado. La lista completa y los valores actuales están en el DBIRTH, así que los consumidores deben conservar el birth para interpretar los datos posteriores.



