O switch node do Node-RED é a forma mais simples de mandar cada mensagem MQTT pelo caminho certo: temperaturas para um ramo, umidade para outro, valores fora da faixa para um alerta. Neste tutorial você vai combinar o switch node com o change node para rotear mensagens por topic e por valor, remodelar payloads sem escrever JavaScript e republicar alertas limpos em um broker. Ao final, você terá um fluxo importável que pode testar em dois minutos.
Por que rotear mensagens MQTT dentro do Node-RED
Um único nó mqtt in assinando um wildcard como sensors/# recebe tudo abaixo daquele nível. Isso é conveniente, porque uma assinatura substitui dezenas, mas significa que todos os nós seguintes veem todas as mensagens. Sem roteamento, você acaba escrevendo um nó function enorme, cheio de if, que ninguém quer manter.
O switch node resolve isso de forma declarativa. Ele avalia uma propriedade da mensagem contra uma lista de regras e envia a mensagem pela porta correspondente. O change node então edita a mensagem em cada ramo: define um novo topic, move um campo, remove ruído ou calcula um valor com uma expressão JSONata. Juntos, eles cobrem a maior parte dos trabalhos de roteamento, e a lógica fica visível no editor, onde um colega consegue lê-la num relance.
Se você está começando com o próprio editor, comece pelo tutorial Node-RED MQTT e volte aqui quando tiver uma conexão com o broker funcionando.
Como funciona o switch node do Node-RED
Abra um switch node e você verá três configurações que importam.
- Property. O valor a ser testado. O padrão é
msg.payload, mas pode sermsg.topic, um campo aninhado comomsg.payload.value, uma variável de contexto de fluxo ou global, ou uma expressão JSONata. - Regras. Cada regra cria uma porta de saída. As regras são avaliadas em ordem.
- Modo de verificação. "Checking all rules" envia a mensagem por todas as portas correspondentes. "Stopping after first match" a envia apenas pela primeira correspondência. Para roteamento, você quase sempre quer a segunda opção, para que um valor nunca caia em dois ramos por acidente.
Os tipos de regra que você vai usar com mais frequência estão abaixo.
| Regra | O que verifica | Uso típico com MQTT |
|---|---|---|
==, != |
Igualdade exata | Estado do dispositivo, como ON ou OFF |
<, <=, >, >= |
Comparação numérica | Alertas por limite |
| is between | Faixa inclusiva | Faixa normal de operação |
| contains | Substring | O topic contém /alarm/ |
| matches regex | Expressão regular | O topic termina com /temperature |
| is true / is false | Booleano | Flags de porta aberta |
| is null / is not null | Valores ausentes | Descartar leituras incompletas |
| is of type | string, number, object, buffer... | Rejeitar payloads malformados |
| has key | O objeto tem uma propriedade | Campos opcionais |
| JSONata exp | Qualquer expressão que retorne true | Condições com vários campos |
| otherwise | Nada mais correspondeu | Captura geral e registro |
Sempre adicione uma regra otherwise no final. Ela não custa nada e é o primeiro lugar onde você vai olhar quando uma mensagem parecer desaparecer.
Como funciona o change node
O change node aplica uma lista de operações à mensagem, em ordem:
- Set define uma propriedade como string, número, booleano, JSON, outra propriedade da mensagem, um valor de contexto, um timestamp ou uma expressão JSONata.
- Change altera parte de uma string, com texto simples ou expressão regular, o que é útil para reescrever topics.
- Delete remove uma propriedade, por exemplo um campo de debug que um dispositivo inclui em toda mensagem.
- Move leva uma propriedade para outro local, como subir
msg.payload.valueparamsg.payload.
O JSONata é o que torna o change node poderoso. Dentro de uma expressão, payload e topic se referem a msg.payload e msg.topic, então $round(payload.value * 9 / 5 + 32, 1) converte Celsius para Fahrenheit e $split(topic, "/")[4] extrai o quinto nível do topic. Você obtém valores calculados sem um nó function e sem sair do editor visual.
O fluxo de exemplo: rotear por topic e depois por valor
O fluxo que você vai importar faz o seguinte:
- Assina
connectmq/demo/a7f3k2/sensors/#no servidor MQTT público com o tipo de payload definido como JSON parseado. - Um primeiro switch node do Node-RED roteia por
msg.topic: temperatura, umidade ou qualquer outra coisa. - Um segundo switch node divide as temperaturas em três faixas com base em
msg.payload.value. - As faixas baixa e alta passam por um change node que monta um topic e um payload de alerta, e então um nó
mqtt outo publica. - Leituras normais, umidade e topics desconhecidos vão para nós debug.
Substitua a7f3k2 por uma string aleatória sua em todos os lugares antes do deploy. O broker público pode ser lido por qualquer pessoa, então um prefixo único mantém o seu tráfego de teste separado, e você nunca deve enviar dados sensíveis para lá. O client ID também precisa ser único e não vazio.
[
{"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":[]}
]
Importe-o em Menu → Import, cole o JSON e clique em Deploy. O nó mqtt in deve mostrar um status verde "connected" abaixo dele em poucos segundos.
Repare em dois detalhes no change node. Primeiro o payload é reconstruído, e então a regra do topic lê payload.room do novo payload. A ordem das regras importa: cada regra vê a mensagem do jeito que a regra anterior a deixou. Repare também que o nó mqtt out tem o campo de topic vazio, então ele publica no msg.topic que o change node definiu. Se você preencher o campo de topic no nó, ele sobrescreve msg.topic e o seu roteamento dinâmico para de funcionar em silêncio.
Teste o roteamento pela linha de comando
Publique algumas mensagens de teste com os clientes Mosquitto. Cada comando usa o próprio client ID.
# Temperatura normal -> saída de debug "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 publicado em 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"}'
# Umidade -> saída de debug "humidity"
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-a7f3k2-3 \
-t connectmq/demo/a7f3k2/sensors/room1/humidity -m '{"value": 48}'
# Medição desconhecida -> saída de debug "unrouted"
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-a7f3k2-4 \
-t connectmq/demo/a7f3k2/sensors/room1/co2 -m '{"value": 640}'
Em um segundo terminal, acompanhe o topic de alertas para confirmar que o change node montou a mensagem esperada:
mosquitto_sub -h broker.connectmq.com -p 1883 -i sub-a7f3k2 -v \
-t 'connectmq/demo/a7f3k2/alerts/#'
Você deve ver {"room":"room1","value":34.2,"level":"high","fahrenheit":93.6}, sem o campo debug. Se não tiver certeza do que cada configuração de QoS faz com a entrega neste teste, o guia de níveis de QoS do MQTT explica por que o fluxo usa QoS 1 para os alertas.
Padrões de roteamento que vale reutilizar
Depois que o fluxo básico funcionar, estes padrões cobrem a maioria dos projetos reais:
- Rotear por tipo de dispositivo com um nível do topic. Em vez de uma regex, defina a propriedade do switch como a expressão JSONata
$split(topic, "/")[3]e compare com regras==. Isso é mais fácil de ler do que uma regex quando os topics seguem uma hierarquia rígida. - Validar antes de rotear. Coloque um switch node logo depois do
mqtt incom uma regra "is of type: object". Payloads malformados vão para a portaotherwise, onde você pode registrá-los em vez de deixar que derrubem um nó function mais adiante. - Eliminar mudanças de estado duplicadas. Combine o switch node com um nó filter (modo report-by-exception) para que um sensor de porta que publica
opena cada segundo só acione o seu ramo quando o valor mudar. - Normalizar unidades cedo. Use um change node logo após o roteamento para converter unidades e renomear campos, para que tudo depois dele veja um único schema.
- Enriquecer com contexto. Um change node pode definir
msg.payload.limita partir deflow.limits[room], e o switch node seguinte pode comparar commsg.payload.limitem vez de um número fixo. Assim os limites ficam em um só lugar.
Quando as condições passam de um punhado de regras ou precisam de loops e estado, um nó function é a ferramenta melhor. O guia do function node do Node-RED cobre esse passo, e o tutorial do JSON node explica como payloads em string e em objeto interagem com essas regras de roteamento.
Solução de problemas com switch e change nodes
| Sintoma | Causa provável | Correção |
|---|---|---|
| Nada sai do switch node | O payload é uma string, não um objeto | Configure a saída do mqtt in como "a parsed JSON object" ou adicione um JSON node |
| A regra numérica nunca corresponde | O valor chega como "34.2" (string) |
Converta com um change node: $number(payload.value) |
| A mensagem aparece em dois ramos | "Checking all rules" está selecionado | Mude para "stopping after first match" |
| Os alertas vão para o topic errado | O campo de topic está preenchido no mqtt out |
Deixe-o vazio para que msg.topic seja usado |
| Erro de JSONata na barra lateral de debug | A expressão referencia msg.payload |
Dentro do JSONata, use payload, e não msg.payload |
| A regex corresponde a coisas demais | Falta de âncora | Termine os padrões com $, por exemplo /temperature$ |
Um hábito útil: dê a cada switch e change node um nome descritivo. A barra lateral de debug mostra o nome do nó, e "temperature band" é muito mais fácil de rastrear do que "switch".
Levando o fluxo para um broker privado
O broker público é ideal para aprender, mas fluxos de roteamento em produção devem rodar no seu próprio broker, com credenciais e TLS. Crie um broker no portal da ConnectMQ e edite o nó de configuração mqtt-broker:
- Server: o host mostrado no portal, porta
8883, Use TLS ativado. - Aba Security:
YOUR_USERNAMEeYOUR_PASSWORD. - Client ID:
YOUR_CLIENT_ID, porque a ConnectMQ vincula os client IDs às credenciais que emite.
Todos os nós mqtt in e mqtt out compartilham esse nó de configuração, então a lógica de roteamento em si não muda. Você pode então remover o prefixo connectmq/demo/a7f3k2 e usar uma hierarquia adequada como site/area/line/device/measurement, por exemplo para uma planta em Campinas. Rodar tudo em um broker MQTT gerenciado também significa que você não precisa aplicar patches e monitorar um processo de broker ao lado do Node-RED.
Rode seus fluxos Node-RED na ConnectMQ
Seus switch e change nodes merecem um broker que continue no ar enquanto você itera. Cadastre-se em app.connectmq.com, escolha o plano Serverless gratuito (sem cartão de crédito), crie um broker e cole o nome de usuário, a senha e o client ID gerados no nó de configuração do Node-RED. O explorador de topics ao vivo do portal mostra seus topics de alerta chegando em tempo real, o que deixa a verificação da lógica de roteamento muito mais rápida.
Perguntas frequentes
Qual é a diferença entre o switch node e o change node no Node-RED?
O switch node decide para onde uma mensagem vai, testando uma propriedade contra regras e escolhendo uma porta de saída. O change node modifica a própria mensagem, definindo, alterando, removendo ou movendo propriedades.
O switch node do Node-RED consegue rotear por msg.topic?
Sim. Defina a propriedade como msg.topic e use regras "matches regex", "contains" ou ==. Essa é a forma padrão de dividir o tráfego de uma única assinatura MQTT com wildcard.
Por que minha regra numérica do switch não corresponde aos valores MQTT?
Os payloads MQTT chegam como texto, a menos que o nó mqtt in os interprete. Garanta que o nó gere um objeto JSON parseado e converta campos em string com $number() em um change node antes de comparar.
Devo usar um nó function em vez de switch e change nodes?
Use switch e change nodes para roteamento e transformações simples, porque são mais fáceis de ler e revisar. Passe para um nó function quando precisar de loops, estado complexo ou lógica que exigiria mais do que algumas regras.



