Node-RED

Switch Node e Change Node do Node-RED para roteamento MQTT

Use o switch node do Node-RED para dividir o tráfego MQTT por topic e valor e depois ajuste cada ramo com o change node antes de republicar. Inclui um fluxo importável e um plano de testes em um broker gratuito.

Switch node do Node-RED dividindo mensagens MQTT em três saídas que alimentam change nodes e um nó MQTT out
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

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.

  1. Property. O valor a ser testado. O padrão é msg.payload, mas pode ser msg.topic, um campo aninhado como msg.payload.value, uma variável de contexto de fluxo ou global, ou uma expressão JSONata.
  2. Regras. Cada regra cria uma porta de saída. As regras são avaliadas em ordem.
  3. 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.value para msg.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:

  1. Assina connectmq/demo/a7f3k2/sensors/# no servidor MQTT público com o tipo de payload definido como JSON parseado.
  2. Um primeiro switch node do Node-RED roteia por msg.topic: temperatura, umidade ou qualquer outra coisa.
  3. Um segundo switch node divide as temperaturas em três faixas com base em msg.payload.value.
  4. 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 out o publica.
  5. 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 in com uma regra "is of type: object". Payloads malformados vão para a porta otherwise, 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 open a 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.limit a partir de flow.limits[room], e o switch node seguinte pode comparar com msg.payload.limit em 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_USERNAME e YOUR_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.

Artigos relacionados

Node-RED Dashboard 2.0 com MQTT: gauges, gráficos e controles

Um tutorial prático do Node-RED Dashboard 2.0: assine telemetria MQTT ao vivo, exiba-a em gauges e em um gráfico de linha e controle um dispositivo com um switch que publica comandos e reflete o estado real.

9 min de leitura

Cliente OPC UA no Node-RED para MQTT com topics ISA-95

Use o node-red-contrib-opcua para assinar variáveis OPC UA em um CLP ou servidor de simulação, mapear node IDs para topics MQTT no estilo ISA-95 e publicar os valores com qualidade e timestamps.

10 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.