Node-RED

Suscripción MQTT dinámica en Node-RED: cambia topics en tiempo de ejecución

Aprende cómo funciona el modo de suscripción dinámica del nodo mqtt in, cómo suscribirte y cancelar suscripciones con msg.action, cómo restaurarlas tras un reinicio y cómo controlarlo desde un panel o una lista de dispositivos.

Flujo de Node-RED que envía acciones subscribe y unsubscribe a un nodo mqtt in en una configuración de suscripción MQTT dinámica
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

El modo de suscripción MQTT dinámica de Node-RED permite que un flujo decida qué topics escuchar mientras se está ejecutando, en lugar de fijar un único topic en el nodo mqtt in. En este tutorial configurarás un suscriptor dinámico, añadirás y eliminarás topics con msg.action, listarás las suscripciones activas, las restaurarás tras un reinicio y controlarás todo desde una sencilla lista de dispositivos.

Cuándo necesitas suscripciones dinámicas

Un nodo mqtt in normal se suscribe a un filtro de topic fijo en el momento del despliegue. Eso cubre la mayoría de los flujos, sobre todo cuando un comodín como site/+/telemetry ya abarca todos los dispositivos. Las suscripciones dinámicas compensan el cableado adicional cuando:

  • Un operador elige desde un panel qué máquina vigilar y solo quieres que fluyan los datos de esa máquina.
  • La lista de dispositivos está en una base de datos o en un topic de configuración y cambia sin necesidad de volver a desplegar.
  • Un comodín traería mucho más tráfico del que necesitas, por ejemplo # en una planta con mucha actividad.
  • Quieres seguir temporalmente un topic de depuración mientras resuelves un problema y después abandonarlo.
  • Estás cerca del límite de suscripciones del broker y debes ser selectivo.

El último punto importa en infraestructuras compartidas. El servidor MQTT público gratuito en broker.connectmq.com, por ejemplo, permite 10 suscripciones por cliente, así que suscribirse bajo demanda es una forma práctica de no salirse del presupuesto.

Configura el nodo mqtt in en modo dinámico

Las suscripciones dinámicas llegaron en Node-RED 2.2 y forman parte de todas las versiones actuales. Para activarlas:

  1. Arrastra un nodo mqtt in al lienzo y ábrelo.
  2. Selecciona o crea un nodo de configuración de broker. Para pruebas, usa el servidor broker.connectmq.com, el puerto 1883 y un client ID único y no vacío, como nr-dyn-91c4.
  3. Cambia Action de "Subscribe to single topic" a Dynamic subscription.
  4. Configura Output como "auto-detect" o "a parsed JSON object", como de costumbre.
  5. Despliega.

Ahora el nodo tiene un puerto de entrada y su estado muestra "connected", pero todavía no está suscrito a nada. A partir de aquí todo se controla con los mensajes que envíes a esa entrada.

También verás la opción Connect automatically en el nodo de configuración del broker. Déjala marcada salvo que quieras controlar también la propia conexión con las acciones connect y disconnect, que se explican más adelante.

Acciones de suscripción MQTT dinámica en Node-RED

El nodo reacciona a msg.action y msg.topic:

msg.action msg.topic Resultado
subscribe "a/b/c" Se suscribe a un topic con el QoS predeterminado del nodo
subscribe ["a/+", "b/#"] Se suscribe a varios filtros de topic
subscribe { "topic": "a/b", "qos": 1 } Se suscribe con opciones explícitas
unsubscribe "a/b/c" o un array Elimina esas suscripciones
unsubscribe true Elimina todas las suscripciones de este nodo
getSubscriptions no es necesario Emite la lista actual en msg.payload
connect / disconnect no es necesario Abre o cierra la conexión con el broker

La forma de objeto también acepta opciones de suscripción de MQTT 5, como nl (no local), rap (retain as published) y rh (retain handling), cuando el nodo broker usa la versión 5 del protocolo.

Los mensajes recibidos en topics añadidos dinámicamente salen por la misma salida que una suscripción normal, con msg.topic igual al topic real, así que el resto de tu flujo no cambia.

Un ejemplo funcional en el broker público

Inicia un publicador que simule tres máquinas. Sustituye 91c4 por tu propia cadena aleatoria para que tus topics sean únicos:

for i in $(seq 1 300); do
  for m in cnc1 cnc2 press1; do
    mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-dyn-pub-91c4 \
      -t "connectmq/demo/91c4/line1/$m/telemetry" \
      -m "{\"machine\":\"$m\",\"load\":$((RANDOM % 100))}"
  done
  sleep 3
done

Ahora importa el flujo siguiente. Tiene nodos inject que se suscriben a cnc1, añaden press1, listan las suscripciones y cancelan todas.

[
  {"id":"tabd","type":"tab","label":"Dynamic subscribe"},
  {"id":"brkd","type":"mqtt-broker","name":"ConnectMQ public","broker":"broker.connectmq.com","port":"1883","clientid":"nr-dyn-91c4","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true},
  {"id":"i1","type":"inject","z":"tabd","name":"watch cnc1","props":[{"p":"action","v":"subscribe","vt":"str"},{"p":"topic","v":"connectmq/demo/91c4/line1/cnc1/telemetry","vt":"str"}],"repeat":"","once":false,"x":130,"y":60,"wires":[["dyn"]]},
  {"id":"i2","type":"inject","z":"tabd","name":"add press1 (QoS 1)","props":[{"p":"action","v":"subscribe","vt":"str"},{"p":"topic","v":"{\"topic\":\"connectmq/demo/91c4/line1/press1/telemetry\",\"qos\":1}","vt":"json"}],"repeat":"","once":false,"x":150,"y":110,"wires":[["dyn"]]},
  {"id":"i3","type":"inject","z":"tabd","name":"list","props":[{"p":"action","v":"getSubscriptions","vt":"str"}],"repeat":"","once":false,"x":110,"y":160,"wires":[["dyn"]]},
  {"id":"i4","type":"inject","z":"tabd","name":"unsubscribe all","props":[{"p":"action","v":"unsubscribe","vt":"str"},{"p":"topic","v":"true","vt":"bool"}],"repeat":"","once":false,"x":140,"y":210,"wires":[["dyn"]]},
  {"id":"dyn","type":"mqtt in","z":"tabd","name":"dynamic","topic":"","qos":"0","datatype":"auto-detect","broker":"brkd","inputs":1,"x":380,"y":130,"wires":[["dbgd"]]},
  {"id":"dbgd","type":"debug","z":"tabd","name":"received","active":true,"complete":"true","x":560,"y":130,"wires":[]}
]

Haz clic en "watch cnc1" y en la barra lateral de depuración aparecerán solo los datos de cnc1. Haz clic en "add press1" y se mostrarán ambas máquinas. "list" emite las suscripciones activas y "unsubscribe all" detiene el flujo de datos sin volver a desplegar.

Restaura las suscripciones tras un reinicio

Esta es la parte que casi todo el mundo pasa por alto: las suscripciones dinámicas viven en memoria. Cuando vuelves a desplegar el nodo, reinicias Node-RED o la conexión con el broker se cae y se restablece con una sesión limpia, el nodo puede volver sin ninguna suscripción. Tenlo en cuenta desde el principio.

Un patrón fiable es guardar la lista deseada en un contexto persistente y volver a aplicarla al arrancar:

// Nodo function "apply subscriptions"
// Entrada: msg.payload = array de IDs de máquina, p. ej. ["cnc1", "press1"]
const prefix = "connectmq/demo/91c4/line1/";
const wanted = Array.isArray(msg.payload) ? msg.payload : [];

global.set("watchedMachines", wanted, "file");   // requiere un almacén de contexto en archivo

// Dos mensajes, en orden, desde una única salida
return [[
    { action: "unsubscribe", topic: true },
    { action: "subscribe", topic: wanted.map(m => ({ topic: prefix + m + "/telemetry", qos: 1 })) }
]];

Los dobles corchetes envían ambos mensajes en secuencia desde la única salida, de modo que la cancelación siempre llega antes de la nueva suscripción. Después añade un nodo inject configurado para dispararse una vez al cabo de unos segundos, con su payload igual a la propiedad global #:(file)::watchedMachines (la sintaxis que usa Node-RED para leer de un almacén de contexto con nombre), y conéctalo a la misma función. La configuración del almacenamiento en archivo se explica en nuestra guía sobre el contexto en Node-RED.

Borrarlo todo antes de volver a suscribirse mantiene el estado del nodo predecible: lo que guardaste es exactamente lo que obtienes.

Controla las suscripciones desde un panel o un topic de configuración

Como la entrada es simplemente un mensaje, cualquier cosa puede controlarla:

  • Desplegable de un panel. Un desplegable de Dashboard 2.0 emite la máquina seleccionada; un nodo Change construye msg.action = "subscribe" y el topic. Envía antes una cancelación para la selección anterior.
  • Topic de configuración. Publica una lista JSON retenida de máquinas en un topic como connectmq/demo/91c4/config/watchlist. Un nodo mqtt in normal la lee y alimenta la función anterior, de modo que al cambiar el mensaje retenido se reconfiguran todas las instancias de Node-RED que lo escuchan.
  • Endpoint HTTP. Un nodo http in puede aceptar una lista desde otro sistema y aplicarla de la misma forma.

El topic de configuración retenido es especialmente elegante: el broker entrega la lista más reciente a Node-RED en cuanto se suscribe, lo que también resuelve el problema del reinicio sin almacenamiento en archivo. Si más adelante necesitas borrar esa lista, consulta nuestra nota sobre cómo borrar mensajes retenidos.

Conexiones dinámicas con el broker

El mismo mecanismo controla las conexiones. Enviar msg.action = "disconnect" cierra la conexión con el broker y connect la vuelve a abrir. Con connect también puedes pasar msg.broker con propiedades como broker, port, clientid, username y password para sobrescribir el nodo de configuración en tiempo de ejecución. Es útil para cambiar entre un broker de pruebas y el de producción, pero mantén las credenciales fuera de los flujos: léelas de variables de entorno en un nodo function en lugar de escribirlas en nodos inject.

Lista de errores frecuentes

  1. Sin cable de entrada no hay suscripciones. Un nodo dinámico no se suscribe a nada hasta que recibe un mensaje.
  2. Client IDs duplicados. Dos instancias de Node-RED con el mismo client ID se expulsarán mutuamente del broker; cada instancia necesita su propio ID.
  3. Filtros solapados. Suscribirse a la vez a line1/# y line1/cnc1/telemetry puede entregar el mismo mensaje dos veces. Mantén los filtros disjuntos.
  4. Límites. Respeta los límites de suscripciones y de profundidad de topics del broker; el broker público limita los topics a 8 niveles.
  5. Estado perdido. Guarda la lista deseada y vuelve a aplicarla al arrancar, como se mostró antes.
  6. Salida equivocada para el topic equivocado. Todos los topics dinámicos comparten una salida, así que enruta con un nodo Switch sobre msg.topic si necesitan un tratamiento distinto.

Si algo directamente no conecta, revisa Node-RED MQTT no conecta antes de depurar la lógica de suscripción. Los detalles completos de las propiedades de entrada del nodo están en la documentación oficial de los nodos MQTT de Node-RED y en el panel de ayuda integrado del nodo.

Usa suscripciones dinámicas con ConnectMQ

En un broker privado tienes margen para crecer: ConnectMQ es un broker MQTT gestionado compatible con MQTT 3.1.1 y 5.0, así que las opciones de suscripción de MQTT 5 en la forma de objeto funcionan como se espera. Su portal incluye un explorador de topics en directo, que facilita confirmar qué topics publican realmente los dispositivos antes de crear una lista de vigilancia. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, pega las credenciales en tu nodo broker con TLS en el puerto 8883 y tu flujo dinámico funcionará sin cambios. Para conocer las opciones de alojamiento, lee sobre cómo ejecutar un broker MQTT en la nube, o empieza por el tutorial de Node-RED MQTT si eres nuevo con estos nodos.

Preguntas frecuentes

¿Qué versión de Node-RED admite suscripciones MQTT dinámicas?

Node-RED 2.2 y posteriores. Si tu nodo mqtt in no tiene la opción "Dynamic subscription", actualiza Node-RED.

¿Sobreviven las suscripciones dinámicas a un nuevo despliegue?

No. Se mantienen en memoria, así que guarda la lista que quieras en un contexto persistente o en un topic de configuración retenido y vuelve a aplicarla cuando arranque el flujo.

¿Puedo definir el QoS por topic con suscripciones dinámicas?

Sí. Envía un objeto como { "topic": "a/b", "qos": 1 }, o un array de esos objetos, como msg.topic con msg.action igual a subscribe.

¿Cómo veo a qué está suscrito el nodo?

Envía un mensaje con msg.action igual a getSubscriptions. El nodo emite la lista de suscripciones actual en msg.payload.

Artículos relacionados

Cliente OPC UA en Node-RED hacia MQTT con topics ISA-95

Usa node-red-contrib-opcua para suscribirte a variables OPC UA de un PLC o de un servidor de simulación, asignar los node IDs a topics MQTT de estilo ISA-95 y publicar los valores con calidad y marcas de tiempo.

10 min de lectura

Node-RED Dashboard 2.0 con MQTT: indicadores, gráficos y controles

Un tutorial práctico de Node-RED Dashboard 2.0: suscríbete a telemetría MQTT en directo, muéstrala en indicadores y en un gráfico de líneas, y controla un dispositivo con un interruptor que publica comandos y refleja el estado real.

9 min de lectura

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.