IoT industrial

Siemens S7 MQTT: publicar datos de PLC S7-1200 y S7-1500 en un broker

Dos formas probadas de sacar datos de un S7-1200 o S7-1500 por MQTT: la librería LMQTT nativa del PLC y un gateway externo en Python con python-snap7, con TLS, topics ISA-95 y report by exception.

PLC Siemens S7-1500 en un carril DIN enviando valores de tags a un broker en la nube, ilustrando la conectividad Siemens S7 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

La integración Siemens S7 MQTT permite que un S7-1200 o un S7-1500 publique sus datos de proceso directamente en dashboards, historiadores y aplicaciones en la nube sin un servidor SCADA de por medio. En este tutorial compararás los dos enfoques prácticos, la librería LMQTT nativa del PLC y un gateway externo, y después construirás un gateway funcional en Python que lee un bloque de datos y lo publica en un broker MQTT con TLS. Terminarás con una estructura de topics probada y una lista de comprobación para llevarlo a producción.

Dos formas de hacer Siemens S7 MQTT

Los PLC S7 no hablan MQTT de serie como hablan comunicación S7, PROFINET u OPC UA. Tienes dos opciones realistas.

Opción 1: cliente MQTT dentro del PLC. Siemens ofrece una librería gratuita para TIA Portal, conocida normalmente como LMQTT, que implementa un cliente MQTT 3.1.1 sobre los bloques de comunicación abierta (TCON, TSEND, TRCV). El propio PLC abre una conexión TCP o TLS con el broker y publica. También existen variantes de este enfoque en procesadores de comunicaciones y dispositivos edge de Siemens.

Opción 2: gateway externo. Un pequeño PC industrial, dispositivo edge o contenedor lee tags del PLC mediante comunicación S7 (PUT/GET) o el servidor OPC UA del PLC y los publica por MQTT. El programa del PLC no cambia, o cambia muy poco.

Criterio LMQTT en el PLC Gateway externo
Hardware adicional Ninguno PC industrial, dispositivo edge o VM
Cambios en el programa del PLC Sí: llamadas a FB, buffers, construcción de JSON Ninguno o mínimos
Impacto en el tiempo de ciclo del PLC Pequeño pero real; el manejo de strings es costoso Ninguno
TLS Admitido en firmware reciente con certificados en TIA Portal Lo gestionan el sistema operativo y la librería del gateway
Formato del payload Se construye en SCL, con herramientas de strings limitadas Cualquier formato, JSON o Sparkplug sin esfuerzo
Store-and-forward Limitado por la memoria del PLC Buffer en disco en el gateway
Quién lo mantiene El programador del PLC El equipo IT/OT o de software
Ideal para Pocas señales, sin posibilidad de añadir otro equipo Muchas señales, muchos PLC, lógica más rica

Si solo necesitas unas decenas de valores de un PLC y añadir hardware es complicado, LMQTT resulta atractiva. Si vas a conectar una línea o una planta, el enfoque con gateway escala mejor y mantiene al PLC centrado en el control. Las ventajas e inconvenientes de arquitectura se tratan de forma más amplia en conectividad de PLC a la nube.

Opción 1: la librería nativa LMQTT

El flujo de trabajo en TIA Portal es el siguiente:

  1. Descarga la librería LMQTT y su documentación desde Siemens Industry Online Support y añádela a tu proyecto como librería global.
  2. Arrastra el bloque de función del cliente a tu programa y crea un bloque de datos de instancia.
  3. Configura los parámetros de conexión: hostname del broker, puerto, client ID, usuario y contraseña, keep alive.
  4. Para TLS, importa el certificado raíz de la CA del broker en el gestor global de certificados de TIA Portal y asígnalo al PLC. Un broker con certificado de Let's Encrypt necesita el certificado ISRG Root X1. Consulta la documentación de la librería para conocer las versiones mínimas de firmware de la CPU que admiten comunicación abierta segura.
  5. Construye el payload en SCL como array de bytes o string y lanza una publicación en un flanco de subida con topic, QoS y flag de retained.
  6. Vigila las salidas de estado y de error; el bloque informa de fallos de conexión, timeouts y rechazos del broker.

Algunas lecciones aprendidas en campo:

  • Construye el JSON con cuidado. La concatenación de strings en SCL es verbosa y propensa a errores. Mantén los payloads pequeños y usa formatos fijos, o publica strings numéricos simples en topics separados.
  • Dispara al cambiar, no en cada ciclo. Publicar en cada ciclo del OB1 saturará el broker y los recursos de comunicación del PLC. Usa un temporizador o una comparación con banda muerta.
  • Cuidado con el client ID. Dos PLC con el mismo client ID se desconectarán mutuamente en bucle. En un broker MQTT gestionado que vincula los client ID a las credenciales, cada PLC necesita su propio juego de credenciales.
  • Usa TLS desde el primer día. Añadir certificados después de la puesta en marcha supone otra descarga y otra ventana de parada.

Opción 2: gateway en Python con python-snap7

El enfoque con gateway usa python-snap7 para leer un bloque de datos mediante comunicación S7 y paho-mqtt para publicar. Funciona en cualquier máquina Linux o Windows que alcance el PLC por el puerto TCP 102.

Preparar el PLC en TIA Portal

Las CPU S7-1200 y S7-1500 bloquean por defecto las lecturas S7 externas. Haz dos cambios y descarga:

  1. En las propiedades de la CPU, en Protección y seguridad, activa Permitir acceso vía comunicación PUT/GET del interlocutor remoto (Permit access with PUT/GET communication from remote partner).
  2. En las propiedades del bloque de datos que vas a leer, desmarca Acceso optimizado al bloque (Optimized block access) para que las variables tengan offsets de bytes fijos.

Después crea un bloque de datos, por ejemplo DB10, con esta estructura:

Offset Nombre Tipo
0.0 Temperature Real
4.0 Pressure Real
8.0 MotorSpeed Int
10.0 Running Bool

PUT/GET no tiene autenticación, así que actívalo solo en una red segmentada donde el gateway sea el único cliente. Si eso no es aceptable en tu planta, lee los mismos datos a través del servidor OPC UA del S7-1500, como se describe en el tutorial de gateway OPC UA a MQTT.

Instalar las librerías

python -m venv s7mqtt
source s7mqtt/bin/activate
pip install python-snap7 "paho-mqtt>=2.0"

El script del gateway

Este script lee el DB10 cada segundo, aplica una banda muerta y publica solo los cambios significativos. También mantiene un topic de estado retained con un Last Will para que los consumidores sepan cuándo se desconecta el gateway.

import json
import time
import uuid
from datetime import datetime, timezone

import snap7
from snap7.util import get_real, get_int, get_bool
import paho.mqtt.client as mqtt

PLC_IP = "192.168.0.10"
RACK, SLOT = 0, 1          # S7-1200 and S7-1500 CPUs use rack 0, slot 1
DB_NUMBER, DB_SIZE = 10, 12

# Test on the public broker first. Use a random prefix: the public area is readable by everyone.
BROKER = "broker.connectmq.com"
PORT = 1883
USE_TLS = False
USERNAME = None            # production: "YOUR_USERNAME"
PASSWORD = None            # production: "YOUR_PASSWORD"
CLIENT_ID = f"s7-gw-{uuid.uuid4().hex[:8]}"   # production: "YOUR_CLIENT_ID"
BASE = f"connectmq/demo/{uuid.uuid4().hex[:6]}/plant1/packaging/line2/filler"

DEADBANDS = {"temperature": 0.2, "pressure": 0.05, "motor_speed": 5}


def read_plc(plc):
    data = plc.db_read(DB_NUMBER, 0, DB_SIZE)
    return {
        "temperature": round(get_real(data, 0), 2),
        "pressure": round(get_real(data, 4), 3),
        "motor_speed": get_int(data, 8),
        "running": get_bool(data, 10, 0),
    }


def changed(name, new, last):
    if name not in last:
        return True
    if isinstance(new, bool):
        return new != last[name]
    return abs(new - last[name]) >= DEADBANDS.get(name, 0)


def on_connect(client, userdata, flags, reason_code, properties):
    print("MQTT connected:", reason_code)
    client.publish(f"{BASE}/status", "online", qos=1, retain=True)


def main():
    mq = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
    if USERNAME:
        mq.username_pw_set(USERNAME, PASSWORD)
    if USE_TLS:
        mq.tls_set()       # system CA store validates the Let's Encrypt certificate
    mq.will_set(f"{BASE}/status", "offline", qos=1, retain=True)
    mq.on_connect = on_connect
    mq.connect(BROKER, PORT, keepalive=30)
    mq.loop_start()

    plc = snap7.client.Client()
    last = {}
    last_full = 0.0
    print("Publishing under", BASE)

    while True:
        try:
            if not plc.get_connected():
                plc.connect(PLC_IP, RACK, SLOT)
            values = read_plc(plc)
            now = time.time()
            force = now - last_full > 300      # full refresh every 5 minutes
            ts = datetime.now(timezone.utc).isoformat(timespec="seconds")
            for name, value in values.items():
                if force or changed(name, value, last):
                    payload = json.dumps({"value": value, "ts": ts, "quality": "good"})
                    mq.publish(f"{BASE}/{name}", payload, qos=1)
                    last[name] = value
            if force:
                last_full = now
        except Exception as exc:              # PLC unreachable, wrong DB layout, etc.
            print("PLC read failed:", exc)
            mq.publish(f"{BASE}/quality", "bad", qos=1, retain=True)
            try:
                plc.disconnect()
            except Exception:
                pass
            time.sleep(5)
        time.sleep(1)


if __name__ == "__main__":
    main()

Ver llegar los datos

Ejecuta el script, anota el prefijo que imprime y suscríbete a él desde otro terminal:

mosquitto_sub -h broker.connectmq.com -p 1883 -i s7-watch-01 \
  -t 'connectmq/demo/+/plant1/packaging/line2/filler/#' -v

Cambia un valor en la tabla de observación del PLC y el topic correspondiente se actualizará en menos de un segundo. Los valores que se mueven menos que su banda muerta no se publican, que es justo el comportamiento que quieres en una red de planta con mucho tráfico. El servidor MQTT público gratuito sirve para esta prueba, pero nunca envíes allí datos reales de producción.

Pasar a un broker privado con TLS

Para producción, crea un broker privado y cambia tres ajustes: PORT = 8883, USE_TLS = True y el usuario, la contraseña y el client ID emitidos en el portal. Como ConnectMQ usa un certificado de Let's Encrypt, tls_set() con el almacén de CA del sistema lo valida sin necesidad de distribuir un archivo de CA propio. Quita el prefijo connectmq/demo/... y usa una ruta ISA-95 limpia como plant1/packaging/line2/filler/temperature; el portal de ConnectMQ reconoce los topics de estilo ISA-95 y muestra los dispositivos organizados por empresa, planta, área y línea.

Si estás decidiendo entre ejecutar tu propio broker junto a los PLC o usar un broker MQTT gestionado, piensa en quién lo parcheará, renovará los certificados y vigilará los límites de conexiones a las tres de la madrugada.

Lista de comprobación para producción

  1. Un juego de credenciales y un client ID único por PLC o gateway.
  2. TLS en el puerto 8883; nada de TCP sin cifrar fuera de la red de planta.
  3. PUT/GET activado solo en una red segmentada, o usar OPC UA en su lugar.
  4. Bandas muertas dimensionadas por señal con un refresco completo periódico.
  5. Topic de estado retained con un Last Will para el estado online y offline.
  6. QoS 1 para mediciones; QoS 0 solo para datos de alta frecuencia que puedas permitirte perder.
  7. El gateway se ejecuta como servicio con reinicio automático y registro.
  8. Los nombres de topic siguen una jerarquía ISA-95 acordada para todas las líneas.

Solución de problemas en conexiones Siemens S7 MQTT

  • Error de snap7 "CLI : function refused by CPU". PUT/GET no está activado, o no se ha descargado la CPU desde que lo cambiaste.
  • "Address out of range". El DB es más pequeño que los bytes solicitados, o sigue siendo optimizado. Revisa la columna de offsets en TIA Portal.
  • Los valores parecen basura. Los offsets son incorrectos. Recuerda que Real ocupa 4 bytes, Int 2, y Bool se empaqueta en bits.
  • Bucle de reconexión MQTT. Client ID duplicado, credenciales incorrectas o el gateway se conecta con TLS al puerto 1883.
  • LMQTT bloqueada en el estado de conexión. El DNS no está configurado en la CPU o falta el certificado de la CA en el almacén de certificados del PLC.

Para el resto del panorama industrial, incluidos Sparkplug B, los gateways de borde y el diseño del namespace, lee la guía de IoT industrial con MQTT. ¿También tienes hardware de Rockwell? El tutorial Allen-Bradley MQTT sigue el mismo patrón con EtherNet/IP.

Conecta tus PLC Siemens a ConnectMQ

Tu gateway S7 necesita un broker MQTT en la nube seguro en el que publicar. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, copia las credenciales generadas en el script y observa cómo aparecen los tags de tu PLC en el explorador de topics en vivo. Con esos mismos topics también puedes animar un gemelo digital 3D de la línea en el navegador.

Preguntas frecuentes

¿Puede un S7-1200 publicar MQTT directamente?

Sí. Con la librería LMQTT de Siemens, un S7-1200 o un S7-1500 puede actuar como cliente MQTT. Consulta la documentación de la librería para conocer las versiones de firmware admitidas, sobre todo si necesitas TLS.

¿Admite Siemens S7 MQTT la versión MQTT 5?

La librería nativa del PLC implementa MQTT 3.1.1. Si necesitas funciones de MQTT 5 como la caducidad de mensajes, usa un gateway externo con una librería como paho-mqtt.

¿Es seguro activar el acceso PUT/GET?

PUT/GET no tiene autenticación, así que actívalo solo en una red segmentada donde el gateway sea el único cliente. En el S7-1500, el servidor OPC UA del PLC con autenticación de usuarios es la alternativa más segura.

¿Qué QoS deberían usar los datos del PLC?

QoS 1 es un buen valor por defecto para mediciones y estados. Usa mensajes retained en los topics de estado para que los nuevos suscriptores reciban de inmediato el valor actual.

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.