El nodo switch de Node-RED es la forma más sencilla de enviar cada mensaje MQTT por el camino correcto: las temperaturas a una rama, la humedad a otra y los valores fuera de rango a una alerta. En este tutorial combinarás el nodo switch con el nodo change para enrutar mensajes por topic y por valor, remodelar payloads sin escribir JavaScript y republicar alertas limpias en un broker. Terminarás con un flujo importable que puedes probar en dos minutos.
Por qué enrutar mensajes MQTT dentro de Node-RED
Un único nodo mqtt in suscrito a un comodín como sensors/# recibe todo lo que hay por debajo de ese nivel. Es cómodo, porque una suscripción sustituye a decenas, pero implica que cada nodo posterior ve todos los mensajes. Sin enrutamiento acabas escribiendo un gran nodo function lleno de sentencias if que nadie quiere mantener.
El nodo switch lo resuelve de forma declarativa. Evalúa una propiedad del mensaje frente a una lista de reglas y envía el mensaje por el puerto que coincide. Después, el nodo change edita el mensaje en cada rama: asigna un nuevo topic, mueve un campo, elimina ruido o calcula un valor con una expresión JSONata. Juntos cubren la mayoría de las tareas de enrutamiento, y la lógica queda visible en el editor, donde un compañero puede leerla de un vistazo.
Si eres nuevo en el propio editor, empieza por el tutorial de Node-RED MQTT y vuelve aquí cuando tengas funcionando una conexión con el broker.
Cómo funciona el nodo switch de Node-RED
Abre un nodo switch y verás tres ajustes importantes.
- Property. El valor que se comprueba. Por defecto es
msg.payload, pero puede sermsg.topic, un campo anidado comomsg.payload.value, una variable de contexto flow o global, o una expresión JSONata. - Rules. Cada regla crea un puerto de salida. Las reglas se evalúan en orden.
- Modo de comprobación. "Checking all rules" envía el mensaje por todos los puertos que coinciden. "Stopping after first match" lo envía solo por la primera coincidencia. Para enrutar casi siempre querrás la segunda opción, para que un valor nunca acabe por accidente en dos ramas.
Los tipos de regla que más usarás se enumeran a continuación.
| Regla | Qué comprueba | Uso típico en MQTT |
|---|---|---|
==, != |
Igualdad exacta | Estado de un dispositivo, como ON u OFF |
<, <=, >, >= |
Comparación numérica | Alertas por umbral |
| is between | Rango inclusivo | Banda de funcionamiento normal |
| contains | Subcadena | El topic contiene /alarm/ |
| matches regex | Expresión regular | El topic termina en /temperature |
| is true / is false | Booleano | Indicadores de puerta abierta |
| is null / is not null | Valores ausentes | Descartar lecturas incompletas |
| is of type | string, number, object, buffer... | Rechazar payloads mal formados |
| has key | El objeto tiene una propiedad | Campos opcionales |
| JSONata exp | Cualquier expresión que devuelva true | Condiciones con varios campos |
| otherwise | No coincidió nada más | Cajón de sastre y registro |
Añade siempre una regla otherwise al final. No cuesta nada y es el primer sitio donde mirarás cuando un mensaje parezca desaparecer.
Cómo funciona el nodo change
El nodo change aplica una lista de operaciones al mensaje, en orden:
- Set: asigna a una propiedad una cadena, un número, un booleano, JSON, otra propiedad del mensaje, un valor de contexto, una marca de tiempo o una expresión JSONata.
- Change: modifica parte de una cadena, con texto literal o una expresión regular, algo muy útil para reescribir topics.
- Delete: elimina una propiedad, por ejemplo un campo de depuración que un dispositivo incluye en cada mensaje.
- Move: mueve una propiedad a una nueva ubicación, como subir
msg.payload.valueamsg.payload.
JSONata es lo que hace potente al nodo change. Dentro de una expresión, payload y topic se refieren a msg.payload y msg.topic, así que $round(payload.value * 9 / 5 + 32, 1) convierte Celsius a Fahrenheit y $split(topic, "/")[4] extrae el quinto nivel del topic. Obtienes valores calculados sin un nodo function y sin salir del editor visual.
El flujo de ejemplo: enruta por topic y después por valor
El flujo que vas a importar hace lo siguiente:
- Se suscribe a
connectmq/demo/a7f3k2/sensors/#en el servidor MQTT público gratuito con el tipo de payload configurado como JSON analizado. - Un primer nodo switch de Node-RED enruta por
msg.topic: temperatura, humedad o cualquier otra cosa. - Un segundo nodo switch divide las temperaturas en tres bandas según
msg.payload.value. - Las bandas baja y alta pasan por un nodo change que construye el topic y el payload de la alerta, y después un nodo
mqtt outla publica. - Las lecturas normales, la humedad y los topics desconocidos van a nodos debug.
Sustituye a7f3k2 por tu propia cadena aleatoria en todas partes antes de desplegar. Cualquiera puede leer el broker público, así que un prefijo único mantiene separado tu tráfico de prueba, y nunca deberías enviar allí datos sensibles. El client ID también debe ser único y no vacío.
[
{"id":"cmq_broker","type":"mqtt-broker","name":"ConnectMQ public","broker":"broker.connectmq.com","port":"1883","clientid":"nr-switch-a7f3k2","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true},
{"id":"in_all","type":"mqtt in","name":"all sensors","topic":"connectmq/demo/a7f3k2/sensors/#","qos":"1","datatype":"json","broker":"cmq_broker","nl":false,"rap":true,"rh":0,"inputs":0,"x":140,"y":160,"wires":[["sw_topic"]]},
{"id":"sw_topic","type":"switch","name":"by measurement","property":"topic","propertyType":"msg","rules":[{"t":"regex","v":"/temperature$","vt":"str","case":false},{"t":"regex","v":"/humidity$","vt":"str","case":false},{"t":"else"}],"checkall":"false","repair":false,"outputs":3,"x":350,"y":160,"wires":[["sw_temp"],["dbg_hum"],["dbg_other"]]},
{"id":"sw_temp","type":"switch","name":"temperature band","property":"payload.value","propertyType":"msg","rules":[{"t":"lt","v":"5","vt":"num"},{"t":"btwn","v":"5","vt":"num","v2":"30","v2t":"num"},{"t":"gt","v":"30","vt":"num"},{"t":"else"}],"checkall":"false","repair":false,"outputs":4,"x":560,"y":100,"wires":[["chg_alert"],["dbg_ok"],["chg_alert"],["dbg_other"]]},
{"id":"chg_alert","type":"change","name":"build alert","rules":[{"t":"delete","p":"payload.debug","pt":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{\"room\": $split(topic, \"/\")[4], \"value\": payload.value, \"level\": payload.value > 30 ? \"high\" : \"low\", \"fahrenheit\": $round(payload.value * 9 / 5 + 32, 1)}","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"\"connectmq/demo/a7f3k2/alerts/\" & payload.room","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":790,"y":60,"wires":[["out_alert","dbg_alert"]]},
{"id":"out_alert","type":"mqtt out","name":"publish alert","topic":"","qos":"1","retain":"false","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"cmq_broker","x":1000,"y":40,"wires":[]},
{"id":"dbg_alert","type":"debug","name":"alert","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":990,"y":90,"wires":[]},
{"id":"dbg_ok","type":"debug","name":"normal temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":800,"y":120,"wires":[]},
{"id":"dbg_hum","type":"debug","name":"humidity","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":560,"y":200,"wires":[]},
{"id":"dbg_other","type":"debug","name":"unrouted","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":800,"y":240,"wires":[]}
]
Impórtalo con Menu → Import, pega el JSON y haz clic en Deploy. En pocos segundos, el nodo mqtt in debería mostrar debajo el estado "connected" en verde.
Fíjate en dos detalles del nodo change. Primero se reconstruye el payload, y después la regla del topic lee payload.room del nuevo payload. El orden de las reglas importa: cada regla ve el mensaje tal como lo dejó la anterior. Fíjate también en que el nodo mqtt out tiene el campo topic vacío, así que publica en el msg.topic que haya fijado el nodo change. Si rellenas el campo topic en el nodo, sobrescribe msg.topic y tu enrutamiento dinámico deja de funcionar sin avisar.
Prueba el enrutamiento desde la línea de comandos
Publica algunos mensajes de prueba con los clientes de Mosquitto. Cada comando usa su propio client ID.
# Temperatura normal -> salida de depuración "normal temperature"
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-a7f3k2-1 \
-t connectmq/demo/a7f3k2/sensors/room1/temperature -m '{"value": 22.5}'
# Temperatura alta -> alerta publicada en connectmq/demo/a7f3k2/alerts/room1
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-a7f3k2-2 \
-t connectmq/demo/a7f3k2/sensors/room1/temperature -m '{"value": 34.2, "debug": "fw-1.2"}'
# Humedad -> salida de depuración "humidity"
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-a7f3k2-3 \
-t connectmq/demo/a7f3k2/sensors/room1/humidity -m '{"value": 48}'
# Medida desconocida -> salida de depuración "unrouted"
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-a7f3k2-4 \
-t connectmq/demo/a7f3k2/sensors/room1/co2 -m '{"value": 640}'
En una segunda terminal, vigila el topic de alertas para confirmar que el nodo change construyó el mensaje que esperabas:
mosquitto_sub -h broker.connectmq.com -p 1883 -i sub-a7f3k2 -v \
-t 'connectmq/demo/a7f3k2/alerts/#'
Deberías ver {"room":"room1","value":34.2,"level":"high","fahrenheit":93.6}, sin el campo debug. Si no tienes claro qué efecto tiene cada ajuste de QoS sobre la entrega en esta prueba, la guía de niveles de QoS de MQTT explica por qué el flujo usa QoS 1 para las alertas.
Patrones de enrutamiento que vale la pena reutilizar
Cuando el flujo básico funcione, estos patrones cubren la mayoría de los proyectos reales:
- Enrutar por tipo de dispositivo con un nivel del topic. En lugar de una regex, configura la propiedad del switch con la expresión JSONata
$split(topic, "/")[3]y compárala con reglas==. Es más fácil de leer que una regex cuando los topics siguen una jerarquía estricta. - Validar antes de enrutar. Coloca un nodo switch justo después de
mqtt incon una regla "is of type: object". Los payloads mal formados van al puertootherwise, donde puedes registrarlos en lugar de dejar que hagan fallar un nodo function más adelante. - Eliminar cambios de estado duplicados. Combina el nodo switch con un nodo filter (modo report-by-exception) para que un sensor de puerta que publica
opencada segundo solo active tu rama cuando cambie el valor. - Normalizar unidades pronto. Usa un nodo change justo después de enrutar para convertir unidades y renombrar campos, de modo que todo lo posterior vea un único esquema.
- Enriquecer con contexto. Un nodo change puede asignar
msg.payload.limitdesdeflow.limits[room], y el siguiente nodo switch puede comparar conmsg.payload.limiten lugar de con un número fijo. Así los umbrales viven en un único sitio.
Cuando las condiciones superan unas pocas reglas o necesitan bucles y estado, un nodo function es la mejor herramienta. La guía del nodo function de Node-RED cubre ese paso, y el tutorial del nodo JSON explica cómo interactúan los payloads de cadena y de objeto con estas reglas de enrutamiento.
Solución de problemas de los nodos switch y change
| Síntoma | Causa probable | Solución |
|---|---|---|
| No sale nada del nodo switch | El payload es una cadena, no un objeto | Configura la salida de mqtt in como "a parsed JSON object" o añade un nodo JSON |
| La regla numérica nunca coincide | El valor llega como "34.2" (cadena) |
Conviértelo con un nodo change: $number(payload.value) |
| El mensaje aparece en dos ramas | Está seleccionado "Checking all rules" | Cambia a "stopping after first match" |
| Las alertas van al topic equivocado | El campo topic está relleno en mqtt out |
Déjalo vacío para que se use msg.topic |
| Error de JSONata en la barra de depuración | La expresión hace referencia a msg.payload |
Dentro de JSONata, usa payload, no msg.payload |
| La regex coincide con demasiado | Falta el ancla | Termina los patrones con $, por ejemplo /temperature$ |
Un hábito útil: da a cada nodo switch y change un nombre descriptivo. La barra lateral de depuración muestra el nombre del nodo, y "temperature band" es mucho más fácil de rastrear que "switch".
Lleva el flujo a un broker privado
El broker público es ideal para aprender, pero los flujos de enrutamiento en producción deben ejecutarse contra tu propio broker, con credenciales y TLS. Crea un broker en el portal de ConnectMQ y edita el nodo de configuración mqtt-broker:
- Server: el host que muestra el portal, puerto
8883, con Use TLS activado. - Pestaña Security:
YOUR_USERNAMEyYOUR_PASSWORD. - Client ID:
YOUR_CLIENT_ID, porque ConnectMQ vincula los client IDs a las credenciales que emite.
Todos los nodos mqtt in y mqtt out comparten ese nodo de configuración, así que la lógica de enrutamiento no cambia. Después puedes eliminar el prefijo connectmq/demo/a7f3k2 y usar una jerarquía adecuada como site/area/line/device/measurement. Ejecutarlo en un broker MQTT gestionado también significa que no tienes que parchear y supervisar un proceso de broker junto a Node-RED.
Ejecuta tus flujos de Node-RED en ConnectMQ
Tus nodos switch y change merecen un broker que siga en pie mientras iteras. Regístrate en app.connectmq.com, elige el plan Serverless gratuito (sin tarjeta de crédito), crea un broker y pega el usuario, la contraseña y el client ID generados en tu nodo de configuración de Node-RED. El explorador de topics en directo del portal muestra cómo llegan tus topics de alerta en tiempo real, lo que acelera mucho la comprobación de la lógica de enrutamiento.
Preguntas frecuentes
¿Cuál es la diferencia entre el nodo switch y el nodo change en Node-RED?
El nodo switch decide adónde va un mensaje comprobando una propiedad frente a unas reglas y eligiendo un puerto de salida. El nodo change modifica el propio mensaje asignando, cambiando, eliminando o moviendo propiedades.
¿Puede el nodo switch de Node-RED enrutar según msg.topic?
Sí. Configura la propiedad como msg.topic y usa reglas "matches regex", "contains" o ==. Es la forma estándar de dividir el tráfico de una única suscripción MQTT con comodín.
¿Por qué mi regla numérica del switch no coincide con los valores MQTT?
Los payloads MQTT llegan como texto salvo que el nodo mqtt in los analice. Asegúrate de que el nodo emite un objeto JSON analizado y convierte los campos de tipo cadena con $number() en un nodo change antes de comparar.
¿Debería usar un nodo function en lugar de los nodos switch y change?
Usa los nodos switch y change para el enrutamiento y las transformaciones sencillas, porque son más fáciles de leer y revisar. Pasa a un nodo function cuando necesites bucles, estado complejo o lógica que requeriría más de unas pocas reglas.



