IoT Industrial con MQTT y AWS: Tutorial Completo para Enviar Datos de Planta a la Nube
Aprende a conectar sensores industriales a AWS IoT Core con MQTT. Tutorial paso a paso con código Python, arquitectura IIoT y buenas prácticas de seguridad.
IoT Industrial con MQTT y AWS: Tutorial Completo para Enviar Datos de Planta a la Nube
Tienes sensores en planta que generan datos cada segundo. Temperaturas, presiones, estados de máquinas, contadores de producción. Esos datos viven atrapados en tu red OT, visibles solo desde el SCADA local. La pregunta que muchos ingenieros industriales se hacen es clara: ¿cómo llevo esos datos a la nube de forma segura, fiable y sin comprometer la red de producción?
Este tutorial de IoT industrial con MQTT y AWS te lleva desde cero hasta tener una arquitectura IIoT funcional. Vas a conectar sensores industriales a AWS IoT Core usando el protocolo MQTT, procesar los datos en la nube y almacenarlos para análisis. Con código Python real, no diagramas bonitos que se quedan en la teoría.
Por Qué MQTT Es el Protocolo Estrella del IoT Industrial
Si vienes del mundo industrial, probablemente conoces Modbus, OPC-UA y PROFINET. Todos cumplen su función dentro de la red de planta. Pero cuando necesitas sacar datos hacia la nube, MQTT gana por goleada. Y hay razones técnicas sólidas detrás.
MQTT consume muy poco ancho de banda. Un mensaje MQTT típico ocupa entre 2 y 100 bytes de cabecera. Compara eso con HTTP, donde cada petición arrastra cabeceras de cientos de bytes. En una planta con 500 sensores publicando cada 5 segundos, esa diferencia es brutal.
Funciona sobre conexiones inestables. El protocolo fue diseñado originalmente para comunicaciones satelitales — redes con alta latencia y pérdida de paquetes. Si tu planta tiene zonas con conectividad intermitente (y la tiene, seamos honestos), MQTT gestiona reconexiones y colas de mensajes de forma nativa.
El modelo publicador/suscriptor desacopla emisor y receptor. Un sensor publica en un topic como planta/linea-1/temperatura y no necesita saber quién consume ese dato. Puede ser AWS, un dashboard local, una regla de alarmas o los tres a la vez. Si ya trabajas con MQTT en entornos industriales, en nuestro artículo de MQTT industrial con ejemplos prácticos cubrimos los patrones básicos.
Tres niveles de calidad de servicio (QoS). QoS 0 dispara y olvida — perfecto para telemetría que llega cada segundo. QoS 1 garantiza al menos una entrega. QoS 2 garantiza exactamente una. Para datos industriales críticos, QoS 1 suele ser el punto óptimo entre fiabilidad y rendimiento.
Arquitectura IIoT: De la Planta a AWS IoT Core
Antes de tocar código, necesitas entender la arquitectura. Saltarse este paso es la razón por la que muchos proyectos IIoT fracasan en producción tras funcionar en el laboratorio.
Capa 1: Sensores y PLCs (Red OT)
Aquí viven tus dispositivos de campo. PLCs Siemens, Allen-Bradley, Schneider. Sensores de temperatura, presión, vibración. Todos conectados a tu red industrial (normalmente aislada y con razón).
No conectes un PLC directamente a internet. Esto debería ser obvio, pero se sigue haciendo. La red OT y la red IT deben estar separadas por un firewall industrial o una DMZ.
Capa 2: Gateway IoT (El Puente)
Un gateway IoT actúa como traductor y puente seguro. Lee datos de la red OT (vía Modbus TCP, OPC-UA o el protocolo que uses) y los publica en MQTT hacia la nube.
Opciones habituales para el gateway:
- Raspberry Pi / Mini PC industrial con Python y un cliente MQTT — económico y flexible.
- AWS IoT Greengrass — el edge runtime de Amazon, permite ejecutar funciones Lambda en local.
- Gateways comerciales como Moxa, HMS Ewon o Siemens IOT2050 — robustos pero más caros.
Para este tutorial usaremos un gateway basado en Python, que es la opción más accesible y la que mejor te ayuda a entender qué ocurre debajo.
Capa 3: AWS IoT Core (La Nube)
AWS IoT Core es un broker MQTT gestionado. No necesitas montar ni mantener un servidor Mosquitto en EC2 — AWS se encarga del escalado, la disponibilidad y la seguridad TLS.
El flujo completo queda así:
[Sensor/PLC] → Modbus/OPC-UA → [Gateway Python] → MQTT+TLS → [AWS IoT Core]
↓
[IoT Rules Engine]
↓ ↓
[DynamoDB] [S3 / Timestream]
↓
[Dashboard / Alertas]
Configurar AWS IoT Core Paso a Paso
Vamos al grano. Necesitas una cuenta de AWS. Si no la tienes, la capa gratuita incluye 250.000 mensajes MQTT al mes durante 12 meses — más que suficiente para una prueba de concepto industrial.
Paso 1: Crear un Thing (Dispositivo)
En la terminología de AWS IoT, cada dispositivo es un “Thing”. Piensa en ello como el registro de un sensor o gateway en la nube.
- Ve a la consola de AWS IoT Core → Manage → Things.
- Crea un Thing con nombre descriptivo:
gateway-planta-madrid-linea1. - Asígnale un Thing Type si tienes varios gateways:
gateway-industrial.
Convención de nombres que funciona:
{tipo}-{ubicación}-{línea/zona}
Ejemplos: gateway-planta-bcn-zona3, sensor-temperatura-horno-01.
Paso 2: Crear Certificados X.509
AWS IoT Core usa autenticación mutua TLS con certificados X.509. Cada dispositivo tiene su propio certificado. No hay usuario/contraseña — esto es mucho más seguro.
- En la consola, ve a Security → Certificates.
- Crea un certificado auto-firmado por AWS (opción recomendada para empezar).
- Descarga los tres archivos — certificado del dispositivo, clave privada y el certificado raíz de Amazon (Amazon Root CA 1).
- Activa el certificado.
Guarda estos archivos como si fueran las llaves de tu planta. Si alguien los obtiene, puede publicar datos falsos en tu broker.
Paso 3: Crear una Política de Acceso
Las políticas definen qué puede hacer cada dispositivo. El principio de mínimo privilegio es obligatorio aquí.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:eu-west-1:123456789:client/gateway-planta-madrid-*"
},
{
"Effect": "Allow",
"Action": "iot:Publish",
"Resource": "arn:aws:iot:eu-west-1:123456789:topic/planta/madrid/*"
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": "arn:aws:iot:eu-west-1:123456789:topicfilter/planta/madrid/+/comandos"
},
{
"Effect": "Allow",
"Action": "iot:Receive",
"Resource": "arn:aws:iot:eu-west-1:123456789:topic/planta/madrid/+/comandos"
}
]
}
Fíjate: el gateway solo puede publicar en topics bajo planta/madrid/* y solo puede suscribirse a topics de comandos. No puede leer datos de otras plantas ni de otros topics. Si alguien compromete ese gateway, el daño está contenido.
Paso 4: Vincular Certificado, Política y Thing
Asocia el certificado a la política y al Thing. Este paso es el que más gente olvida y luego se pregunta por qué el dispositivo no conecta.
En la consola:
- Ve al certificado que creaste.
- Adjunta la política (
Attach policy). - Adjunta el Thing (
Attach thing).
Paso 5: Obtener Tu Endpoint
Cada cuenta de AWS tiene un endpoint MQTT único. Lo necesitas para configurar el cliente.
aws iot describe-endpoint --endpoint-type iot:Data-ATS
Te dará algo como: a1b2c3d4e5f6g7-ats.iot.eu-west-1.amazonaws.com. Apunta este valor.
Código Python: Gateway IoT Industrial con MQTT y AWS
Ahora la parte interesante. Vamos a escribir un gateway en Python que simula la lectura de datos industriales y los publica en AWS IoT Core.
Instalar Dependencias
pip install awsiotsdk pymodbus
El SDK oficial de AWS (awsiotsdk) maneja la conexión MQTT con TLS de forma nativa. pymodbus te permite leer datos de PLCs vía Modbus TCP si tienes dispositivos reales.
El Gateway Completo
import json
import time
import random
from datetime import datetime, timezone
from awscrt import mqtt
from awsiot import mqtt_connection_builder
# === CONFIGURACIÓN ===
ENDPOINT = "a1b2c3d4e5f6g7-ats.iot.eu-west-1.amazonaws.com"
CLIENT_ID = "gateway-planta-madrid-linea1"
CERT_PATH = "./certs/device-certificate.pem.crt"
KEY_PATH = "./certs/private.pem.key"
CA_PATH = "./certs/AmazonRootCA1.pem"
TOPIC_BASE = "planta/madrid/linea1"
PUBLISH_INTERVAL = 10 # segundos
def crear_conexion_mqtt():
"""Crea la conexión MQTT con autenticación TLS mutua."""
conexion = mqtt_connection_builder.mtls_from_path(
endpoint=ENDPOINT,
cert_filepath=CERT_PATH,
pri_key_filepath=KEY_PATH,
ca_filepath=CA_PATH,
client_id=CLIENT_ID,
clean_session=False,
keep_alive_secs=30
)
future = conexion.connect()
future.result() # Espera a que conecte
print(f"Conectado a AWS IoT Core como {CLIENT_ID}")
return conexion
def leer_datos_sensores():
"""
Simula lectura de sensores industriales.
En producción, aquí usarías pymodbus para leer de un PLC real:
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient('192.168.1.10', port=502)
resultado = client.read_holding_registers(0, 10, slave=1)
"""
return {
"timestamp": datetime.now(timezone.utc).isoformat(),
"temperatura_horno": round(random.uniform(180.0, 220.0), 2),
"presion_bar": round(random.uniform(2.5, 4.0), 2),
"velocidad_rpm": round(random.uniform(1400, 1600), 1),
"estado_maquina": random.choice(["RUN", "RUN", "RUN", "IDLE"]),
"contador_piezas": random.randint(10000, 50000),
"vibracion_mm_s": round(random.uniform(0.5, 8.0), 3)
}
def publicar_datos(conexion, datos):
"""Publica datos en el topic MQTT de la línea."""
topic = f"{TOPIC_BASE}/telemetria"
payload = json.dumps(datos)
conexion.publish(
topic=topic,
payload=payload,
qos=mqtt.QoS.AT_LEAST_ONCE # QoS 1
)
print(f"Publicado en {topic}: {payload[:80]}...")
def publicar_alerta(conexion, tipo, mensaje, valor):
"""Publica alertas en un topic separado para procesamiento inmediato."""
topic = f"{TOPIC_BASE}/alertas"
alerta = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"tipo": tipo,
"mensaje": mensaje,
"valor": valor,
"severidad": "warning" if tipo == "temperatura_alta" else "critical"
}
conexion.publish(
topic=topic,
payload=json.dumps(alerta),
qos=mqtt.QoS.AT_LEAST_ONCE
)
print(f"⚠️ ALERTA: {mensaje}")
def main():
conexion = crear_conexion_mqtt()
try:
while True:
datos = leer_datos_sensores()
publicar_datos(conexion, datos)
# Verificar umbrales y generar alertas
if datos["temperatura_horno"] > 215.0:
publicar_alerta(
conexion, "temperatura_alta",
f"Temperatura del horno en {datos['temperatura_horno']}°C",
datos["temperatura_horno"]
)
if datos["vibracion_mm_s"] > 7.0:
publicar_alerta(
conexion, "vibracion_excesiva",
f"Vibración en {datos['vibracion_mm_s']} mm/s",
datos["vibracion_mm_s"]
)
time.sleep(PUBLISH_INTERVAL)
except KeyboardInterrupt:
print("Desconectando...")
conexion.disconnect().result()
if __name__ == "__main__":
main()
Desglose del Código
Conexión TLS mutua. La función crear_conexion_mqtt() establece una conexión cifrada donde tanto el servidor (AWS) como el cliente (tu gateway) se autentican con certificados. No hay credenciales en texto plano viajando por la red.
Estructura de topics. Usamos un patrón jerárquico: planta/madrid/linea1/telemetria y planta/madrid/linea1/alertas. Esto facilita las reglas de enrutamiento en AWS y permite suscripciones con wildcards (planta/madrid/+/alertas para recibir alertas de todas las líneas).
QoS 1 (AT_LEAST_ONCE). Cada mensaje se confirma. Si la conexión se corta durante el envío, MQTT reintenta automáticamente. Para telemetría industrial donde perder un dato afecta a la trazabilidad, QoS 1 es lo mínimo aceptable.
Separación telemetría / alertas. Los datos normales van a un topic, las alertas a otro. En AWS podrás crear reglas diferentes: la telemetría se almacena en Timestream o DynamoDB para análisis histórico; las alertas disparan notificaciones SNS inmediatas.
Procesar Datos en AWS: IoT Rules Engine
Los datos llegan a AWS IoT Core. Ahora necesitas hacer algo con ellos. El Rules Engine es el motor de reglas que enruta mensajes MQTT a otros servicios de AWS sin escribir código adicional.
Regla 1: Almacenar Telemetría en DynamoDB
SELECT * FROM 'planta/madrid/+/telemetria'
Acción: insertar en tabla DynamoDB telemetria-industrial con partición por linea y ordenación por timestamp.
Cada mensaje que llegue a cualquier topic de telemetría se almacena automáticamente. DynamoDB escala sin intervención y soporta millones de escrituras por segundo.
Regla 2: Alertas por SNS
SELECT * FROM 'planta/madrid/+/alertas' WHERE severidad = 'critical'
Acción: enviar notificación SNS al topic alertas-produccion. Puedes configurar suscriptores por email, SMS o incluso un webhook que dispare un workflow en n8n.
Solo las alertas críticas generan notificación. Las warnings se almacenan para revisión pero no despiertan a nadie a las 3 de la madrugada.
Regla 3: Archivar en S3 para Análisis a Largo Plazo
SELECT * FROM 'planta/+/+/telemetria'
Acción: escribir en un bucket S3 con particionado por fecha (s3://datos-planta/2026/09/10/linea1/). Desde ahí puedes usar Athena para consultas SQL sobre los datos históricos sin levantar infraestructura adicional.
Seguridad: No Negociable en IoT Industrial
Si estás conectando una planta industrial a la nube, la seguridad no es un capítulo opcional que leer después. Es lo primero que diseñas.
Certificados Rotativos
Los certificados X.509 no son eternos. Define una política de rotación — cada 12 meses como mínimo. AWS IoT tiene APIs para registrar certificados nuevos y revocar los antiguos sin downtime.
Aislamiento de Red
Tu gateway IoT debería estar en una DMZ entre la red OT y la red IT. El tráfico permitido es:
- Desde el gateway hacia AWS (puerto 8883, MQTT sobre TLS) — permitido.
- Desde AWS hacia el gateway — solo respuestas a conexiones iniciadas por el gateway.
- Desde internet hacia la red OT — bloqueado sin excepciones.
Si quieres profundizar en seguridad OT, nuestro artículo sobre ciberseguridad industrial OT cubre los fundamentos que necesitas.
Monitorización de Anomalías
AWS IoT Device Defender analiza el comportamiento de tus dispositivos y detecta anomalías. Si un gateway que normalmente publica 6 mensajes por minuto de repente empieza a publicar 600, algo va mal. Configura alertas para:
- Cambios en el volumen de mensajes.
- Conexiones desde IPs no habituales.
- Intentos de publicar en topics no autorizados.
Cifrado Extremo a Extremo
MQTT sobre TLS cifra el canal de comunicación. Pero si necesitas proteger los datos incluso dentro de AWS (defense in depth), cifra el payload antes de publicar:
from cryptography.fernet import Fernet
key = Fernet.generate_key() # Almacenar en AWS Secrets Manager
cipher = Fernet(key)
payload_cifrado = cipher.encrypt(json.dumps(datos).encode())
conexion.publish(topic=topic, payload=payload_cifrado, qos=mqtt.QoS.AT_LEAST_ONCE)
Diseño de Topics MQTT para Entornos Industriales
La estructura de topics parece un detalle menor, pero una jerarquía mal pensada te hará la vida imposible cuando escales a múltiples plantas.
Patrón Recomendado
{empresa}/{planta}/{zona}/{tipo_dato}
Ejemplos reales:
acme/madrid/linea1/telemetria
acme/madrid/linea1/alertas
acme/madrid/linea1/comandos
acme/barcelona/zona3/telemetria
acme/barcelona/zona3/estado
Por Qué Esta Estructura Funciona
- Wildcards potentes:
acme/+/+/alertascaptura alertas de todas las plantas y zonas. - Políticas granulares: puedes dar acceso a un operador solo a
acme/madrid/#sin que vea datos de Barcelona. - Escalable: añadir una planta nueva no requiere cambiar la arquitectura.
Errores Comunes que Debes Evitar
- Topics planos como
sensor1,sensor2— imposible de gestionar con más de 10 dispositivos. - Datos en el nombre del topic como
planta/madrid/temperatura/22.5— la temperatura va en el payload, no en el topic. - Topics demasiado profundos con 8+ niveles — dificulta las suscripciones con wildcards.
Escalado: De Prueba de Concepto a Producción
Tu PoC funciona en el escritorio. Ahora toca llevarlo a producción. Estos son los puntos que marcan la diferencia.
Gestión de Reconexiones
Las redes industriales no son estables. Tu gateway debe gestionar desconexiones de forma elegante:
def on_connection_interrupted(connection, error, **kwargs):
print(f"Conexión interrumpida: {error}. Reconectando...")
def on_connection_resumed(connection, return_code, session_present, **kwargs):
print(f"Conexión restaurada. Sesión persistente: {session_present}")
if not session_present:
# Re-suscribirse a topics de comandos
connection.subscribe("planta/madrid/linea1/comandos", mqtt.QoS.AT_LEAST_ONCE)
Con clean_session=False y sesiones persistentes, MQTT guarda los mensajes pendientes mientras el gateway está desconectado y los entrega cuando vuelve.
Buffer Local
Si la conexión a AWS cae durante horas (corte de internet en la planta), necesitas un buffer local que almacene los datos y los envíe cuando la conectividad se restaure. SQLite funciona perfectamente para esto:
import sqlite3
def guardar_buffer_local(datos):
conn = sqlite3.connect("buffer_iot.db")
conn.execute(
"INSERT INTO pendientes (timestamp, payload) VALUES (?, ?)",
(datos["timestamp"], json.dumps(datos))
)
conn.commit()
conn.close()
def enviar_pendientes(conexion_mqtt):
conn = sqlite3.connect("buffer_iot.db")
pendientes = conn.execute(
"SELECT id, payload FROM pendientes ORDER BY timestamp LIMIT 100"
).fetchall()
for id_msg, payload in pendientes:
conexion_mqtt.publish(
topic=f"{TOPIC_BASE}/telemetria",
payload=payload,
qos=mqtt.QoS.AT_LEAST_ONCE
)
conn.execute("DELETE FROM pendientes WHERE id = ?", (id_msg,))
conn.commit()
conn.close()
Monitorización del Gateway
Tu gateway es un punto crítico. Si deja de funcionar, pierdes visibilidad de toda la línea. Implementa:
- Heartbeat MQTT: publica cada 60 segundos en
planta/madrid/linea1/heartbeat. Si AWS deja de recibir el heartbeat, dispara una alerta. - Métricas del sistema: publica CPU, RAM y espacio en disco del gateway junto con la telemetría.
- Logs remotos: envía los logs del gateway a CloudWatch para diagnóstico remoto.
Costes: ¿Cuánto Cuesta Esto en AWS?
Pregunta obligatoria. AWS IoT Core factura por mensajes y por minutos de conexión.
Ejemplo real para una línea de producción:
- 10 sensores publicando cada 10 segundos = 86.400 mensajes/día.
- Con el precio actual de AWS IoT Core (aproximadamente 1€ por millón de mensajes en la región EU-West-1), eso son unos 2,60€/mes en mensajes.
- El coste de conexión (0,08€ por millón de minutos) es prácticamente despreciable con un solo gateway.
- DynamoDB en modo bajo demanda para almacenar la telemetría: entre 1€ y 5€/mes dependiendo del volumen.
Total estimado: 5-10€/mes por línea de producción. Compara eso con el coste de una licencia de software SCADA cloud comercial y la diferencia es obscena.
Para proyectos más grandes (múltiples plantas, miles de sensores), los costes escalan de forma lineal. 50 líneas de producción rondarían los 250-500€/mes — sigue siendo competitivo frente a alternativas comerciales.
Alternativas a AWS: ¿Cuándo Considerar Otra Nube?
AWS IoT Core no es la única opción. Dependiendo de tu contexto, estas alternativas merecen evaluación:
- Azure IoT Hub: si tu empresa ya está en el ecosistema Microsoft. Integración nativa con Power BI para dashboards.
- Google Cloud IoT (descontinuado en 2023, migrado a terceros): no recomendable para proyectos nuevos.
- EMQX Cloud o HiveMQ Cloud: brokers MQTT gestionados sin atarte a un cloud provider específico. Buena opción si quieres evitar vendor lock-in.
- Mosquitto auto-gestionado en VPS: máximo control, mínimo coste, pero tú gestionas la alta disponibilidad y la seguridad.
Para entornos industriales donde ya existe relación con AWS, IoT Core es la opción más integrada. Pero si tu principal necesidad es OPC-UA, echa un vistazo a nuestro tutorial de OPC-UA con Python para automatización industrial que cubre el protocolo nativo de la industria.
Conclusión y Próximos Pasos
Conectar una planta industrial a la nube con MQTT y AWS IoT Core no es ciencia ficción ni requiere un presupuesto de multinacional. Con un gateway Python, certificados X.509 y una arquitectura bien pensada, puedes tener datos de producción en la nube en una tarde.
Lo que has aprendido en este tutorial:
- MQTT como protocolo ideal para IoT industrial por su ligereza y fiabilidad.
- AWS IoT Core como broker gestionado que escala sin que tú gestiones infraestructura.
- Seguridad con TLS mutuo, políticas de mínimo privilegio y aislamiento de red.
- Código real en Python para un gateway industrial funcional.
- Reglas de enrutamiento para almacenar, alertar y archivar datos automáticamente.
- Costes reales — desde 5€/mes por línea de producción.
El siguiente paso lógico es montar un dashboard de producción en tiempo real con esos datos. Si quieres hacerlo con Python puro, tenemos un tutorial de dashboards industriales con Flask que encaja perfectamente como siguiente fase.
¿Necesitas ayuda para diseñar tu arquitectura IIoT o conectar tu planta a la nube? En automatizatodo.com ayudamos a empresas industriales a dar ese salto. Contacta con nosotros y hablamos de tu caso concreto.