IoT industrial

SCADA MQTT: modernizar la telemetría con report by exception

Cómo cambia MQTT la telemetría SCADA: report by exception en lugar de sondeo, un broker como nodo central entre RTU y hosts SCADA, conocimiento del estado con Last Will y Sparkplug B, y una ruta de migración paso a paso.

RTU remotas publicando telemetría en un broker central que alimenta servidores SCADA y dashboards, ilustrando una arquitectura SCADA MQTT
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

Las arquitecturas SCADA MQTT sustituyen el modelo clásico en el que el maestro sondea cada RTU por dispositivos que informan por excepción (report by exception) a un broker central y hosts SCADA que se suscriben a lo que necesitan. Esta guía explica por qué ese cambio ahorra ancho de banda y simplifica la integración, cómo se conoce el estado de los dispositivos cuando nadie sondea y cómo migrar paso a paso un sistema existente. Además construirás un pequeño host en Python que detecta RTU desconectadas o con datos obsoletos, la habilidad central de cualquier SCADA basado en MQTT.

Cómo funciona la telemetría SCADA tradicional

En un sistema SCADA clásico, la estación maestra controla la conversación. Sondea por turnos cada RTU o PLC mediante Modbus, DNP3 o un protocolo propietario, pidiendo los mismos registros en cada ciclo, haya cambiado algo o no. El modelo tiene puntos fuertes reales: el maestro siempre sabe si un dispositivo ha respondido y la temporización es predecible.

También tiene costes bien conocidos:

  • Ancho de banda gastado en datos sin cambios. Un nivel de depósito que se mueve dos veces por hora se sigue leyendo cada pocos segundos.
  • El tiempo de escaneo crece con la red. En enlaces de radio o satélite, como los de un oleoducto o una operación minera en los Andes, añadir RTU alarga el ciclo de sondeo para todos.
  • Acoplamiento estrecho. Cada nuevo consumidor (un historiador, una herramienta de analítica, una segunda sala de control) o vuelve a sondear los dispositivos o depende de las interfaces del servidor SCADA.
  • Direcciones de dispositivo por todas partes. Los mapas de registros y los detalles del protocolo se filtran a todos los sistemas que necesitan los datos.

Qué cambia con SCADA MQTT

Con MQTT, la RTU o el gateway de borde abre una conexión saliente con un broker y publica los valores cuando cambian de forma significativa. Los hosts SCADA, historiadores y dashboards son suscriptores. El broker se sitúa en medio y reparte los mensajes.

Aspecto SCADA de sondeo-respuesta SCADA MQTT
Quién inicia El maestro sondea cada dispositivo El dispositivo publica, los hosts se suscriben
Tráfico Cada punto, en cada escaneo Solo cambios, más latidos
Añadir un consumidor Nuevos sondeos o interfaz SCADA Nueva suscripción, sin tocar los dispositivos
Sentido de la conexión Del maestro al dispositivo (entrante en campo) Del dispositivo al broker (saliente desde campo)
Salud del dispositivo Implícita: sin respuesta hay problema Explícita: Last Will, mensajes de birth/death
Contexto de los datos Direcciones de registros Topics con nombre, a menudo ISA-95 o Sparkplug
Eficiencia del enlace Mala en enlaces de alta latencia Buena: sesión persistente, paquetes pequeños

El mayor cambio conceptual es el report by exception (RBE). En lugar de preguntar, el campo informa. Una banda muerta en cada valor analógico y la publicación inmediata de cada cambio de estado digital mantienen los datos al día con una fracción del tráfico. La guía de report by exception explica en detalle cómo dimensionar la banda muerta.

El broker como nodo central del SCADA

En un diseño SCADA MQTT, el broker se convierte en el sistema nervioso central. Los dispositivos de campo no saben ni les importa cuántos hosts consumen sus datos, y los hosts no necesitan conocer las direcciones de los dispositivos. Este desacoplamiento permite patrones que resultan incómodos con el sondeo:

  • Hosts SCADA redundantes se suscriben a los mismos topics sin duplicar el tráfico de campo.
  • Consumidores de IT, como historiadores, analítica o un gemelo digital 3D de la instalación, se suscriben en paralelo sin tocar el sistema de control.
  • Migraciones por fases pueden ejecutar el SCADA antiguo y el nuevo en paralelo sobre los mismos datos en vivo.

Entender qué hace un broker MQTT es la base: enruta mensajes, guarda valores retained y el estado de las sesiones, y controla quién puede conectarse.

Conocer el estado sin sondear

La objeción más habitual a SCADA MQTT es: «Si dejo de sondear, ¿cómo sé que una RTU está viva?». MQTT responde a esto en dos niveles.

Keep alive y Last Will. Cada cliente declara un intervalo de keep alive. Si el broker no recibe nada durante 1,5 veces ese intervalo, cierra la sesión y publica el mensaje Last Will del cliente, por ejemplo un offline retained en el topic de estado de la RTU. Cuando la RTU se reconecta, publica un online retained. Todos los suscriptores, incluidos los que arranquen más tarde, ven el estado actual.

Sparkplug B. La especificación Sparkplug formaliza esto para SCADA: los edge nodes publican mensajes NBIRTH y DBIRTH con todas las métricas al conectarse, NDEATH como Last Will, y un primary host publica su propio STATE para que los edge nodes sepan si hay un host SCADA escuchando. Los hosts pueden solicitar un rebirth cuando detectan un hueco. Ignition y muchos gateways de borde lo implementan de forma nativa; consulta aplicaciones Sparkplug primary host para el lado del host.

Incluso con topics JSON simples, deberías detectar también los datos obsoletos: un dispositivo que sigue conectado pero cuyos valores han dejado de actualizarse, por ejemplo porque han fallado sus E/S de campo.

Ejemplo: un host SCADA MQTT mínimo en Python

Este host se suscribe al estado y la telemetría de las RTU, sigue el estado de conexión a partir de los mensajes Last Will retained y marca cualquier RTU cuyos datos no hayan cambiado ni se hayan refrescado dentro de su latido esperado. Ejecútalo contra el servidor MQTT público gratuito con un simulador y después apúntalo a tu propio broker.

import json
import time
import uuid
import threading

import paho.mqtt.client as mqtt

BROKER, PORT = "broker.connectmq.com", 1883
PREFIX = "connectmq/demo/scada-7h2k"          # random prefix: public data is readable by all
STALE_AFTER = 120                             # seconds; heartbeat is 60 s

rtus = {}   # rtu_id -> {"online": bool, "last_seen": float, "values": dict}
lock = threading.Lock()


def on_connect(client, userdata, flags, reason_code, properties):
    print("Connected:", reason_code)
    client.subscribe(f"{PREFIX}/+/status", qos=1)
    client.subscribe(f"{PREFIX}/+/telemetry/#", qos=1)


def on_message(client, userdata, msg):
    parts = msg.topic.split("/")
    rtu_id = parts[3]
    with lock:
        rtu = rtus.setdefault(rtu_id, {"online": False, "last_seen": 0.0, "values": {}})
        if parts[4] == "status":
            rtu["online"] = msg.payload.decode() == "online"
            print(f"[STATE] {rtu_id} is {'ONLINE' if rtu['online'] else 'OFFLINE'}")
        else:
            point = "/".join(parts[5:])
            rtu["values"][point] = json.loads(msg.payload)
            rtu["last_seen"] = time.time()


def watchdog():
    while True:
        time.sleep(10)
        now = time.time()
        with lock:
            for rtu_id, rtu in rtus.items():
                if rtu["online"] and now - rtu["last_seen"] > STALE_AFTER:
                    print(f"[STALE] {rtu_id}: no data for {int(now - rtu['last_seen'])} s")


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"scada-host-{uuid.uuid4().hex[:6]}")
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, PORT, keepalive=30)
threading.Thread(target=watchdog, daemon=True).start()
client.loop_forever()

Simula una RTU en otro terminal publicando un estado retained y un valor de telemetría:

mosquitto_pub -h broker.connectmq.com -p 1883 -i rtu-sim-7h2k \
  -t 'connectmq/demo/scada-7h2k/rtu07/status' -m online -r -q 1
mosquitto_pub -h broker.connectmq.com -p 1883 -i rtu-sim2-7h2k \
  -t 'connectmq/demo/scada-7h2k/rtu07/telemetry/tank1/level' -m '{"value":3.42,"unit":"m"}' -q 1

Para un simulador de larga duración con un Last Will real, usa mosquitto_sub o un script con --will-topic connectmq/demo/scada-7h2k/rtu07/status --will-payload offline --will-retain y mátalo para ver cómo reacciona el host. Usa el servidor público solo con valores simulados como estos; no está pensado para datos de producción.

Migrar un sistema SCADA existente

Rara vez hace falta una sustitución de golpe. Una ruta por fases mantiene la operación segura:

  1. Primero, replica. Añade un publicador MQTT junto al maestro existente, ya sea un módulo SCADA que reenvía tags o un gateway de borde que lee las mismas RTU en modo solo escucha. No cambia nada en el control.
  2. Define el namespace. Acuerda la estructura de topics (rutas ISA-95 o group y node ID de Sparkplug) y el formato de payload antes de que existan muchas fuentes.
  3. Conecta los consumidores de solo lectura. Historiadores, dashboards y analítica pasan al broker. Valida los valores con las pantallas del SCADA.
  4. Convierte las instalaciones a RBE. Sustituye el sondeo de una instalación o tipo de enlace cada vez por RTU o gateways de borde con capacidad RBE. Compara el ancho de banda y la frescura de los datos.
  5. Traslada el control con cuidado. Los comandos por MQTT necesitan patrones de confirmación, timeouts y enclavamientos. Los mensajes de comando de Sparkplug o el request/response de MQTT 5 con response topics ayudan a estructurarlo.
  6. Retira el sondeo heredado solo cuando todos los consumidores se hayan trasladado y se haya verificado el comportamiento de las alarmas.

Errores de diseño

  • Sin latido. Un RBE puro sin refresco periódico hace que un valor congelado no se distinga de uno tranquilo.
  • Marcas de tiempo del reloj del dispositivo sin sincronizar. El análisis de secuencia de eventos se rompe si los relojes de las RTU derivan. Usa hora NTP o GPS en el origen.
  • QoS 2 en todas partes. Añade viajes de ida y vuelta en enlaces lentos. QoS 1 con consumidores idempotentes es la opción habitual para telemetría.
  • Retener todo. Retén el estado y los últimos valores, no los flujos de alta frecuencia.
  • Topics planos. rtu07/ai3 no escala; nombra por instalación y activo.

Dónde encaja ConnectMQ

Un broker que actúe como nodo central del SCADA necesita TLS, credenciales por dispositivo y protección frente a clientes que se comportan mal. ConnectMQ ofrece MQTT 3.1.1 y 5.0 con TLS, vincula cada client ID a sus credenciales emitidas y aplica protección contra avalanchas de mensajes y bloqueo de IP tras inicios de sesión fallidos repetidos. El portal decodifica payloads Sparkplug B, puede republicar datos Sparkplug en topics ISA-95 legibles y ofrece reglas de alerta por umbral con un registro de alertas, útil como vista rápida de operaciones junto a tu host SCADA. El software SCADA, los historiadores y los scripts se conectan como clientes MQTT corrientes. Si prefieres no mantener infraestructura de broker en cada centro de control, merece la pena evaluar un broker MQTT gestionado; para detalles de implementación con un paquete SCADA concreto, consulta Ignition con MQTT y, para el contexto general, la guía de IoT industrial con MQTT.

Moderniza tu telemetría SCADA con ConnectMQ

Empieza con una instalación o un tipo de RTU. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, conecta un gateway y tu host SCADA, y compara los datos en paralelo con tu sondeo actual.

Preguntas frecuentes

¿Puede MQTT sustituir a DNP3 o Modbus en SCADA?

MQTT suele sustituir el transporte entre las instalaciones de campo y el centro de control, mientras que Modbus o DNP3 pueden seguir usándose localmente entre un gateway de borde y los dispositivos de campo.

¿Cómo sabe un host SCADA MQTT que un dispositivo está desconectado?

Mediante el mensaje Last Will del dispositivo, que el broker publica cuando expira el keep alive, o mediante mensajes NDEATH de Sparkplug. Añade detección de datos obsoletos para los dispositivos que siguen conectados pero dejan de actualizarse.

¿Es obligatorio Sparkplug B para SCADA MQTT?

No, pero normaliza los mensajes de birth y death, las definiciones de métricas y el estado del host, lo que facilita mucho la interoperabilidad entre hosts SCADA y dispositivos de borde.

¿Qué QoS debería usar la telemetría SCADA?

QoS 1 es la opción habitual, combinada con topics de estado retained. QoS 0 encaja con datos de alta frecuencia en los que la siguiente muestra sustituye a una perdida.

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.