Cómo habla MQTT Captia Connect
En MQTT nadie habla con nadie: todos hablan con el broker. Por eso la primera pregunta de una integración no es qué equipo publica, sino dónde está el broker y de quién es. Connect ocupa dos posiciones distintas según la respuesta, y conviene tenerlas separadas porque el trabajo, los riesgos y la conversación con el cliente cambian por completo.
Connect como cliente suscriptor de un broker que ya existe. Es el caso más frecuente en retrofit. La planta ya tiene un broker montado por el integrador de la sensórica, por el fabricante de la máquina o por el equipo de sistemas, y Connect entra como un cliente más: abre la sesión, se suscribe a los topics que le corresponden y no publica nada. Aquí el trabajo es de acuerdo, no de despliegue: qué credenciales, qué filtros de suscripción y qué se hace cuando alguien cambia la jerarquía sin avisar.
Connect junto a un broker en el edge. Cuando no hay broker, o cuando el que hay está en una cloud del fabricante y la planta no quiere depender de esa salida, el broker se levanta en el propio nodo edge, en contenedor Docker igual que el resto de la capa de adquisición. Los equipos publican contra una dirección de la red local, el tráfico de telemetría no sale de planta y lo que cruza hacia la plataforma es la serie ya normalizada. Qué exigirle a ese broker, cómo dimensionarlo y qué modelo de alta disponibilidad tiene sentido en industria es la discusión del recurso de broker MQTT industrial, y ahí está desarrollada.
Sesión, puerto y transporte
Connect abre una conexión TCP saliente contra el broker y sobre ella negocia la sesión MQTT. El puerto es 1883 cuando el tráfico va en claro y 8883 cuando va sobre TLS, que es el registrado para MQTT seguro y el único que se plantea en una instalación nueva. Cuando el broker solo es accesible por WebSocket, que ocurre con plataformas de fabricante detrás de un proxy corporativo, la sesión viaja encapsulada sobre HTTPS por el 443. La conexión es siempre saliente desde el nodo: MQTT no obliga a abrir ningún puerto entrante hacia el edge ni hacia la máquina que publica.
En el CONNECT se deciden cuatro cosas que después explican la mitad de los incidentes. El identificador de cliente debe ser estable y único: si dos clientes se presentan con el mismo identificador, el broker expulsa al anterior, y el síntoma clásico es un par de clientes reconectando en bucle cada pocos segundos con los datos llegando a trozos. El keep alive fija cada cuánto se envía un latido y, con él, en cuánto tiempo detecta el broker que el cliente ha desaparecido: el corte se declara a la vez y media de ese intervalo, así que un keep alive de 60 segundos significa que una desconexión sucia tarda hasta 90 segundos en notarse. La sesión persistente determina si el broker guarda las suscripciones y los mensajes pendientes de QoS 1 y 2 mientras el cliente no está, en lugar de empezar de cero en cada reconexión. Y las credenciales identifican al cliente frente al servicio de autenticación del broker.
Connect trabaja con sesión persistente en las suscripciones que llevan QoS 1, porque es lo que permite que una reconexión de treinta segundos no deje un hueco de treinta segundos en el histórico. A cambio, esa decisión obliga a lo anterior: identificador de cliente estable, porque la sesión se recupera por identificador. Si el identificador se genera aleatorio en cada arranque, la sesión persistente no sirve para nada.
Suscripción: filtros, comodines y volumen
Connect no se suscribe señal a señal. Se suscribe con filtros de topic, que admiten un comodín de un nivel, +, y un comodín multinivel, #, que solo puede ir al final. Un filtro como planta1/+/energia/# recoge la energía de todas las líneas sin enumerarlas, y esa es exactamente la propiedad que hace que añadir un equipo nuevo no exija reconfigurar la adquisición: si el equipo publica en el sitio correcto de la jerarquía, aparece solo.
Esa misma propiedad es un riesgo si se usa mal. Suscribirse a # desde la raíz recoge todo lo que pase por el broker, incluidos topics de control, de aplicaciones ajenas y de diagnóstico del propio broker, y convierte la ingesta en un vertedero que alguien tendrá que limpiar aguas abajo. El criterio de partida es el opuesto: filtros tan específicos como permita la jerarquía, comodín solo en el nivel donde de verdad se espera que crezca el parque.
Cuando el volumen de un topic muy poblado supera lo que conviene procesar en un solo cliente, el broker moderno ofrece suscripciones compartidas (los filtros con prefijo $share/), que reparten los mensajes entre varios suscriptores del mismo grupo en lugar de entregar una copia a cada uno. Es la vía correcta para escalar la ingesta sin duplicar dato, y depende del broker, no del cliente.
QoS: qué garantiza cada nivel y qué cuesta
El nivel de calidad de servicio se negocia dos veces, y esto es lo que más confusión genera en obra: el publicador elige el QoS con el que entrega el mensaje al broker, y el suscriptor elige el QoS máximo con el que quiere recibirlo. El nivel efectivo de una entrega es el menor de los dos. Un sensor que publica en QoS 1 contra un cliente suscrito en QoS 0 produce entrega QoS 0, y la garantía se pierde en el tramo que importa sin que nadie haya configurado nada mal a la vista.
Connect no aplica el mismo nivel a toda la instalación. Lo decide por naturaleza del dato, con una regla corta: si la muestra siguiente reemplaza a la anterior, QoS 0 basta; si la muestra es un hecho que no se repite, QoS 1; QoS 2 solo cuando duplicar el mensaje tenga consecuencias contables o legales.
| Nivel | Qué garantiza | Coste real | Cuándo lo usa Connect |
|---|---|---|---|
| QoS 0 | Entrega como mucho una vez. El mensaje se envía y no se confirma: si el TCP se rompe a mitad, ese valor se pierde y nadie se entera | Un solo paquete por mensaje y ninguna memoria de sesión en el broker | Magnitudes continuas muestreadas con periodo corto, donde la lectura siguiente reemplaza a la anterior: temperatura, presión, potencia instantánea |
| QoS 1 | Entrega al menos una vez. El emisor reintenta hasta recibir confirmación, así que el mensaje puede llegar duplicado pero no se pierde | Dos paquetes por mensaje y cola de pendientes en el broker mientras el cliente no confirma | Datos que no admiten hueco: contadores de energía, estados de máquina, arranques y paradas, alarmas de proceso |
| QoS 2 | Entrega exactamente una vez. Un intercambio en cuatro fases descarta el duplicado antes de entregarlo a la aplicación | Cuatro paquetes por mensaje y estado por mensaje en ambos extremos, con latencia sensiblemente mayor | Solo cuando el duplicado tiene consecuencias: eventos de facturación, registros de lote, trazabilidad con valor legal |
Hay una consecuencia práctica que conviene decir en voz alta: QoS 1 y QoS 2 son garantías de transporte, no de captura. Si el sensor no publica porque se ha quedado sin batería, ningún nivel de QoS inventa el dato. Lo que garantiza QoS 1 es que lo que se publicó llegó; lo que garantiza el last will es que se sabe que el sensor dejó de publicar. Son cosas distintas y hacen falta las dos.
Retained y last will: el estado que MQTT no tiene por defecto
MQTT es un protocolo de flujo, no de estado. Un cliente que se suscribe a un topic no recibe nada hasta que alguien publica de nuevo, y en una planta eso significa que tras un reinicio del nodo la consigna de una máquina que solo se publica cuando cambia puede tardar días en aparecer. El mecanismo que lo resuelve es la marca de retenido: el broker conserva el último mensaje publicado con esa marca en cada topic y se lo entrega de inmediato a todo el que se suscriba después.
Connect se apoya en el retenido para el arranque en frío. Al reconectar, la primera oleada de mensajes retenidos le da el estado actual de todo lo que está modelado como estado (consignas, receta activa, modo de operación) sin esperar al siguiente cambio. La contrapartida que hay que vigilar es que un mensaje retenido no caduca: si un equipo se retira sin borrar su topic, ese valor sigue ahí meses después y aparenta ser actual. Por eso el retenido se reserva a lo que de verdad es estado y no se usa como sustituto de un histórico.
El last will es la otra mitad. Es un mensaje que el cliente entrega al broker en el momento de conectarse con la instrucción de publicarlo si la sesión se corta de forma sucia, es decir sin un DISCONNECT ordenado. Cuando el sensor se cuelga, pierde alimentación o queda sin cobertura, el broker publica ese mensaje y todos los suscriptores se enteran de que ese punto ha dejado de estar vivo. Combinado con retenido en el topic de estado del dispositivo, es el mecanismo estándar para distinguir un valor estable de un valor congelado, que es la diferencia entre una planta tranquila y una planta con un sensor muerto que nadie ha notado.
Connect trata esos avisos como señal de primera clase: la desconexión de un publicador se registra en el histórico como evento, con su instante, de modo que un hueco en una serie tiene explicación y no queda como un misterio. La convención completa de nacimiento y muerte de dispositivo, con secuencia y estado de sesión, es la que formaliza Sparkplug B.
TLS y credenciales
MQTT no lleva seguridad dentro del protocolo: la delega en TLS por debajo y en el servicio de autenticación del broker por encima. Esa es su diferencia estructural con OPC UA y la razón por la que un broker mal configurado es uno de los hallazgos más habituales en una auditoría de red industrial: el puerto 1883 abierto, sin usuario y con acceso anónimo permitido, es la configuración de fábrica de más de un despliegue improvisado.
El criterio de Connect es de tres capas. Canal: TLS contra el 8883 con verificación del certificado del broker, incluida la validación del nombre, porque un TLS que acepta cualquier certificado protege del observador pasivo pero no del suplantador. Identidad: credencial dedicada para el cliente Connect, nunca la del integrador ni una compartida con el SCADA, y cuando el broker lo soporta, autenticación mutua con certificado de cliente en lugar de usuario y contraseña. Autorización: lista de control de acceso que otorga a esa credencial permiso de suscripción sobre su rama de la jerarquía y nada más. Connect adquiere; no necesita permiso de publicación sobre los topics de proceso y no debe tenerlo.
Buffering local: por qué una caída del broker no es una pérdida de dato
Aquí es donde la posición de Connect en la arquitectura cambia la respuesta, y conviene separar tres cortes que la gente suele meter en el mismo saco.
Corte entre el nodo Connect y la plataforma. Es el caso benigno y el que cubre el buffering local. La adquisición no se detiene: Connect sigue recibiendo del broker, normaliza y persiste en la base de datos de series temporales del propio nodo, y sincroniza cuando la conectividad vuelve. Como cada muestra conserva su marca de tiempo, el bloque atrasado se coloca donde le toca en el histórico en lugar de comprimirse contra el instante de llegada.
Corte entre Connect y el broker. Connect reconecta y, con sesión persistente y QoS 1, el broker le entrega lo que quedó encolado durante la ausencia. Lo que llevaba QoS 0 en ese intervalo no se recupera, porque nunca se guardó: es la decisión que se tomó al elegir el nivel y por eso QoS 0 se reserva a magnitudes que se vuelven a muestrear enseguida.
Corte entre el publicador y el broker. Este es el que no cubre nadie desde el lado del suscriptor. Si el sensor no llega al broker, el dato depende de que el propio dispositivo tenga cola interna, y muchos equipos de campo no la tienen. Es el argumento técnico que más pesa a favor de poner el broker en el edge, en el mismo dominio de red que los publicadores: acorta el tramo frágil hasta dejarlo dentro de la planta, donde el enlace es cable y no depende de un operador móvil.
| Dónde se corta | Qué pasa con la adquisición | Qué se recupera al volver |
|---|---|---|
| Nodo Connect hacia la plataforma | No se detiene. Connect sigue recibiendo del broker, normaliza y persiste en local | Todo el intervalo, con la marca de tiempo original de cada muestra |
| Connect hacia el broker | Se interrumpe la recepción. Connect reintenta la conexión de forma continua | Lo publicado con QoS 1 o 2 sobre suscripciones de sesión persistente. Lo de QoS 0 del intervalo no existe |
| Publicador hacia el broker | El topic deja de actualizarse. El last will del equipo avisa de la caída | Solo lo que el propio dispositivo haya podido encolar. La caída queda registrada como evento |
| Caída del proceso del broker | Se interrumpe toda la ingesta MQTT de esa rama, con independencia del QoS | Los mensajes retenidos y las sesiones persistentes si el broker tiene su almacén en disco y no solo en memoria |
Qué publica por MQTT en una instalación
MQTT no aparece en planta porque alguien lo eligiera sobre un plano: aparece porque los equipos que llegaron después de 2015 vienen hablándolo. Se encuentra en cuatro familias, y el trabajo de integración es distinto en cada una.
La primera es la sensórica añadida en retrofit: sondas de temperatura y humedad, medidores de vibración, caudalímetros y contadores de pulsos instalados sobre equipos que no tenían instrumentación. Suelen ser dispositivos alimentados por batería que llegan por radio hasta una pasarela, y esa pasarela es la que habla MQTT. Publican con periodo largo y, cuando el fabricante lo permite, se les ajusta el topic; cuando no, publican donde el firmware decide y el trabajo se traslada al mapeo.
La segunda son las pasarelas y concentradores de campo, que es el caso más frecuente en instalaciones mixtas. Un gateway lee por Modbus a los analizadores de red, variadores y contadores del cuadro, y publica el resultado por MQTT. Desde el punto de vista de Connect el origen del dato es MQTT, pero conviene saber que detrás hay un sondeo: el periodo real de la señal lo fija el gateway, no el intervalo con el que llegan los mensajes, y esa distinción evita creer que se tiene una resolución que no se tiene.
La tercera son los equipos de fabricante con conector nativo: máquinas de proceso reciente, compresores, enfriadoras, inversores fotovoltaicos y cargadores. Publican un conjunto cerrado de variables en la jerarquía que el fabricante ha decidido, casi siempre con el número de serie como raíz. No hay margen para renombrar en origen, así que la normalización se hace entera en el edge.
La cuarta es el propio SCADA o el sistema de supervisión, cuando se le ha añadido un módulo de publicación MQTT. Es un punto de toma cómodo porque las señales ya vienen agregadas y con nombre de operación, con la contrapartida habitual: el dato llega con la granularidad que el SCADA aplica, no con la del proceso.
Y una advertencia de campo que ahorra reuniones: que un equipo tenga MQTT en la ficha técnica no significa que se pueda apuntar al broker de la planta. Buena parte de los equipos conectados de gran consumo industrial solo publican contra la cloud de su fabricante, con la dirección del broker fijada en firmware. En esos casos la vía no es MQTT sino la API que esa cloud expone, que entra por las integraciones estándar.
De mensaje MQTT a serie temporal
Un mensaje MQTT son dos cosas: un topic y una carga útil de bytes. El protocolo no dice nada de lo que hay dentro, no declara tipos, no declara unidades y no obliga a incluir una marca de tiempo. Esa indiferencia es lo que lo hace ligero y lo que traslada al edge todo el trabajo que en OPC UA viene resuelto por el modelo de información. La normalización, en MQTT, no es un remate: es la mitad del proyecto.
El topic es la identidad, y por eso la jerarquía hipoteca la plataforma
En MQTT la identidad de la señal vive en el topic. Es la única pista estable que trae el mensaje, y por eso una jerarquía mal diseñada se paga durante años. Los tres modos de fallo que se ven una y otra vez son siempre los mismos.
Poner en el topic lo que cambia. Una raíz basada en el número de serie del equipo, o en la dirección de la pasarela, convierte la sustitución de un sensor averiado en una ruptura de la serie histórica: el equipo nuevo publica en otro sitio y lo que era una señal continua se parte en dos. El topic debe identificar el punto de medida por su lugar en la planta, no el hardware que lo ocupa hoy.
Aplanar la jerarquía. Cuando todo cuelga de un nivel único con nombres compuestos del tipo planta1_linea2_prensa_temp, los comodines dejan de servir: no hay forma de suscribirse a la línea 2 entera ni de recoger todas las temperaturas de la planta sin enumerarlas una a una. Cada equipo nuevo pasa a exigir un cambio de configuración en la adquisición, y eso es exactamente lo que MQTT venía a evitar.
Mezclar el dato con lo demás. Telemetría, comandos, configuración y diagnóstico bajo la misma rama impiden dar a Connect un permiso de solo lectura limpio, y obligan a filtrar por contenido lo que debería filtrarse por topic.
El patrón que Connect propone cuando puede intervenir en el diseño va de lo estable a lo volátil, con el sitio primero y la naturaleza del dato al final: empresa/planta/area/linea/activo/tipo/senal. Con esa forma, un filtro por área recoge todo lo de esa área, un filtro por tipo recoge toda la energía de la planta, y cambiar un sensor no rompe nada. Cuando el broker es ajeno y la jerarquía viene impuesta, esa traducción se hace en el edge: Connect mantiene la correspondencia entre el topic de origen y la identidad canónica de la señal, de modo que la nomenclatura del fabricante no se propaga al histórico. El diseño completo de la jerarquía, con sus criterios de gobierno, se trata en la guía de broker MQTT industrial y en la idea de unified namespace.
El payload y la marca de tiempo
En la carga útil se encuentran tres formas y a las tres hay que responder. El valor escalar en texto plano, un topic por señal con un número dentro, es lo que publican los dispositivos más simples: no trae tipo, no trae unidad y no trae instante. El objeto JSON con varias señales es lo habitual en pasarelas y equipos de fabricante: agrupa medidas y a menudo incluye su propio campo de tiempo, con el formato y el huso que el firmware haya decidido. Y el binario compacto, propio de enlaces de radio con carga limitada, exige conocer la estructura del fabricante para desempaquetarlo.
La regla de Connect sobre el tiempo es la misma que en el resto de protocolos y es la que sostiene el buffering: si el payload trae una marca de tiempo de origen creíble, esa manda. Solo cuando no la trae se sella la muestra en el momento de la recepción en el edge. La diferencia se nota justo cuando importa: al recuperarse un corte, un lote de mensajes encolados llega en ráfaga, y fechado por hora de llegada aplastaría media hora de proceso en dos segundos de gráfica. Sobre el adjetivo creíble no hay margen: un dispositivo sin reloj sincronizado que arranca en 1970 tras cada corte de alimentación entrega marcas peores que la del edge, y esa comprobación se hace en la puesta en marcha, no después.
| Lo que llega en el mensaje | Qué hace Connect con ello | Qué problema evita |
|---|---|---|
| Topic de publicación | Se traduce a la identidad canónica de la señal, asociada a activo, línea y área | Que la nomenclatura del fabricante o el número de serie acaben siendo el nombre de la señal en el histórico |
| Payload sin tipo declarado | Se fija tipo y unidad por señal en la configuración de ingesta, una sola vez | Contadores tratados como texto, booleanos que llegan como cero y uno y agregados que no cuadran |
| Marca de tiempo dentro del payload | Se usa como instante de la muestra si el dispositivo tiene reloj fiable, con el huso normalizado | Que una ráfaga de mensajes encolados se apile en el instante de recepción y falsee la dinámica |
| Mensaje sin marca de tiempo | Se sella en el edge en el momento de la recepción, dejando constancia de que el origen no la aportó | Suponer una precisión temporal que el dispositivo nunca dio |
| Objeto JSON con varias medidas | Se desdobla en una serie por medida, cada una con su unidad y su nombre estable | Un histórico de documentos opaco, imposible de agregar y de comparar entre equipos |
| Aviso de last will del publicador | Se registra como evento de desconexión en el instante en que el broker lo emite | Huecos en la serie sin explicación y valores congelados que aparentan estar vivos |
Con eso hecho, la señal entra en el mismo modelo que las adquiridas por cualquier otra vía y el resto de la plataforma no necesita saber de dónde vino. El encuadre general de ese trabajo está en la guía de sistema de adquisición de datos.
Cuándo MQTT no es la vía adecuada
MQTT resuelve muy bien un problema concreto, y precisamente por eso se le pide con frecuencia lo que no puede dar. Estos son los seis escenarios en los que insistir cuesta dinero.
El equipo no publica y hay que preguntarle. Es el límite estructural: MQTT es pub/sub y necesita un publicador. Un autómata antiguo, un analizador de red o un contador con puerto serie no van a empujar nada hacia ningún sitio. Para leerlos hay que sondearlos, y eso es Modbus, por TCP o por RTU sobre RS-485. Añadir MQTT ahí significa meter una pasarela que sondea y republica: tiene sentido si esa pasarela ya existe o si va a concentrar muchos equipos, y no lo tiene si es un cacharro nuevo entre Connect y un equipo que Connect ya lee directamente.
Se necesita el modelo de información, no solo el valor. Cuando lo que se quiere es descubrir qué expone una máquina, con nombres legibles, tipos declarados y calidad por lectura, MQTT no lo tiene: el broker mueve bytes y no sabe qué transporta. La respuesta del ecosistema a esa carencia es Sparkplug B, que impone tipo, secuencia y estado de dispositivo por encima de MQTT. Si el equipo ya trae servidor OPC UA, ese modelo ya está resuelto y montar una capa MQTT encima solo para tenerlo es trabajo duplicado. Qué arquitectura conviene en un diseño nuevo se discute en el recurso OPC UA frente a MQTT.
El lazo es de control y tiene requisito de tiempo. MQTT viaja sobre TCP y su latencia depende del broker, de la cola y de la red; ni el protocolo ni el broker ofrecen garantía de plazo. Para un enclavamiento, una parada de emergencia o cualquier lazo cerrado, la vía es el sistema de automatización de la planta, con su bus determinista. Connect adquiere para decidir y para el histórico; no cierra lazos y no debe estar en el camino crítico de una seguridad.
Hay que recuperar el pasado. Un broker no es un histórico. Guarda el último mensaje retenido por topic y las colas pendientes de las sesiones vivas, y nada más. Quien se conecta hoy no puede pedir la semana pasada, porque la semana pasada no está ahí. Esa es exactamente la función del almacenamiento de series temporales del edge y de la plataforma, y confundir las dos capas lleva a la conversación incómoda de descubrir, tras un incidente, que no hay dato con el que reconstruirlo.
El dato vive fuera de la planta. Órdenes de fabricación en el ERP, resultados de laboratorio, precios horarios de la energía o partes de mantenimiento no van a aparecer en ningún broker. La vía son las integraciones estándar por API REST, webhooks o CSV.
No hay quien gobierne la jerarquía de topics. Este es un límite de organización y es el que más proyectos estropea. MQTT no impone estructura, así que si tres integradores publican a su aire durante dos años el broker acaba siendo un conjunto de topics incompatibles con la misma magnitud escrita de cuatro formas. El protocolo no lo va a arreglar, y la traducción en el edge tapa el síntoma pero no la causa. Ese trabajo es de contexto y de gobierno del dato, y es el que describe el recurso de contextualización de datos industriales.
Convivencia con el resto de la instalación
La planta normal no habla un protocolo, habla los que le fueron cayendo. Connect adquiere en paralelo por todas las vías disponibles y las lleva al mismo modelo de series temporales, de modo que en el histórico una vibración publicada por MQTT desde una pasarela, una señal de proceso leída por OPC UA al PLC y un consumo tomado a un contador por IEC 870-5-102 quedan al mismo nivel. Nadie tiene que saber de qué protocolo vino un dato para poder usarlo.
El reparto que se repite en las plantas mixtas es simple: MQTT cubre lo que se ha añadido y OPC UA cubre lo que ya estaba. La sensórica de retrofit, las pasarelas y los equipos conectados publican; la maquinaria con controlador y el SCADA se leen como cliente. No compiten y no hay que elegir. Cuál conviene como arquitectura de partida en un diseño nuevo, y con qué criterio se decide, es la discusión del recurso OPC UA frente a MQTT, que es donde está desarrollada.
La migración que sí se ve con frecuencia no es de protocolo sino de dueño del broker. Muchas instalaciones empiezan publicando contra la cloud del fabricante de la sensórica porque es lo que venía en la caja, y en algún momento la planta quiere el dato en su casa, quiere sumar equipos de otro proveedor o quiere dejar de depender de un enlace a internet para ver su propia temperatura. El movimiento entonces es traer el broker al edge y reapuntar los publicadores, lo que se hace equipo a equipo y sin parar la producción: el broker nuevo convive con el antiguo mientras dure la transición, porque un publicador reapuntado deja de mandar al viejo y empieza a mandar al nuevo sin que nada más se entere. Los equipos con la dirección fijada en firmware son la excepción y se quedan por la API de su cloud.
Cuando el parque MQTT crece y empieza a haber varias aplicaciones consumiendo, la evolución natural es dar semántica a la jerarquía: convención única de topics, tipos declarados en el payload y estado explícito de cada dispositivo. Ese destino tiene nombre, unified namespace, y una especificación que lo aterriza, Sparkplug B. Connect no exige llegar ahí para funcionar, pero cuanto más ordenada esté la jerarquía, menos traducción hay que mantener en el edge.
Sobre esa base ya trabajan los módulos de la plataforma, y el proyecto de ingeniería que la implanta es la integración MQTT.