Node-RED

Node-RED Modbus para MQTT: faça polling de dispositivos e publique os valores

Monte um gateway Node-RED Modbus: faça polling de holding registers e coils com node-red-contrib-modbus, decodifique escalas e floats de 32 bits, publique JSON no MQTT por exceção e aceite comandos de escrita com segurança.

Flow Node-RED Modbus fazendo polling de holding registers de um controlador de bomba e publicando valores JSON no MQTT
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

Flows Node-RED Modbus são uma das formas mais rápidas de tirar dados de medidores, inversores e CLPs que só falam Modbus e levá-los ao MQTT, onde dashboards, historiadores e ferramentas na nuvem podem usá-los. Neste tutorial você vai fazer polling de holding registers e coils com node-red-contrib-modbus, decodificar corretamente inteiros com escala e floats de 32 bits e publicar JSON limpo em um broker apenas quando os valores mudarem. Você também vai ver como tratar comandos de escrita com segurança e como testar tudo sem hardware real.

Por que fazer a ponte de Modbus para MQTT com o Node-RED

O Modbus é um protocolo de requisição/resposta de 1979: um cliente (mestre) pede a um servidor (escravo) um bloco de registradores e recebe de volta números brutos de 16 bits. Não há unidades, nomes, timestamps nem envio espontâneo. Cada consumidor que quer os dados precisa consultar o dispositivo por conta própria, e muitos dispositivos aceitam apenas poucas conexões simultâneas.

O MQTT inverte isso. Um gateway consulta o dispositivo, dá significado aos números e os publica uma única vez em um broker. Qualquer número de assinantes recebe então valores nomeados e com escala no momento em que mudam. O Node-RED é um gateway natural porque polling, decodificação, filtragem e publicação são, cada um, um node, e a lógica fica visível para a equipe de manutenção, seja em uma estação de saneamento ou em uma planta industrial. Para a visão arquitetural mais ampla, o guia de Modbus TCP para MQTT compara o Node-RED com outras opções de gateway.

Instale o node-red-contrib-modbus

Instale o pacote em Manage palette → Install ou pela linha de comando:

cd ~/.node-red
npm install node-red-contrib-modbus
# reinicie o Node-RED em seguida

Ele fornece, entre outros, estes nodes:

Node Função
Modbus Read Faz polling de um bloco fixo de registradores em intervalos regulares
Modbus Getter Lê sob demanda quando chega uma mensagem
Modbus Flex Getter Lê o que a mensagem de entrada especificar
Modbus Write Escreve coils ou registradores
Modbus Server Um servidor Modbus TCP simples para testes
Modbus Client (config) Conexão TCP ou serial compartilhada pelos nodes

Entenda primeiro o mapa de registradores

Todo projeto Modbus começa pelo mapa de registradores do dispositivo. Para este tutorial, imagine um controlador de bomba com este mapa:

Dado Tipo Endereço (base 0) Notação clássica Escala
Temperatura Holding register, 16 bits com sinal 0 40001 valor / 10, °C
Pressão Holding register, 16 bits sem sinal 1 40002 valor / 100, bar
Vazão Holding registers, float de 32 bits, big-endian 2-3 40003-40004 nenhuma, m³/h
Bomba ligada Coil 0 00001 booleano

O erro mais comum em Node-RED Modbus é o endereço. Datasheets costumam usar a notação "40001", que começa em um e inclui um prefixo de tipo. O endereço do protocolo, que é o que você digita no Node-RED, começa em zero e não tem prefixo: 40001 vira o holding register de endereço 0. Se seus valores parecem deslocados em um registrador, é por isso.

Teste sem hardware: um servidor Modbus local

Você pode seguir o tutorial inteiro sem nenhum dispositivo rodando um servidor Modbus dentro do próprio Node-RED.

  1. Arraste um node Modbus Server para uma aba separada. Configure-o para escutar em 0.0.0.0, porta 10502 (não privilegiada, então não precisa de root). Faça o deploy.
  2. Crie um node de configuração Modbus Client: tipo TCP, host 127.0.0.1, porta 10502, unit ID 1.
  3. Adicione um inject node repetindo a cada 2 segundos, um function node que gera valores simulados de registradores e um node Modbus Write usando esse cliente com function code 16 (preset multiple registers), endereço 0, quantidade 4.

A função do simulador:

// Function node "simulate pump registers" -> Modbus Write (FC16, endereço 0, quantidade 4)
const temperature = 40 + Math.random() * 5;           // °C
const pressure = 3.2 + Math.random() * 0.3;           // bar
const flowRate = 12 + Math.random() * 2;              // m³/h

const buf = Buffer.alloc(4);
buf.writeFloatBE(flowRate, 0);

msg.payload = [
    Math.round(temperature * 10),      // registrador 0
    Math.round(pressure * 100),        // registrador 1
    buf.readUInt16BE(0),               // registrador 2: palavra alta do float
    buf.readUInt16BE(2)                // registrador 3: palavra baixa do float
];
return msg;

Adicione um segundo node de escrita para o coil: function code 5 (force single coil), endereço 0, alimentado com true a partir de um inject node. Seu controlador de bomba simulado já está funcionando.

Monte o flow de polling Node-RED Modbus

Passo 1: faça polling dos registradores

Adicione um node Modbus Read com o mesmo cliente:

  • FC: 3, Read Holding Registers
  • Endereço: 0, Quantidade: 4
  • Taxa de polling: 2 segundos

A primeira saída emite msg.payload como um array de quatro números brutos, por exemplo [423, 334, 16708, 26214]. A segunda saída traz o buffer bruto e os detalhes da resposta, o que é útil para depurar a ordem dos bytes.

Para o coil, adicione um segundo node Modbus Read com FC 1 (Read Coil Status), endereço 0, quantidade 1 e um polling mais lento, de 5 segundos.

Passo 2: decodifique os registradores brutos em valores de engenharia

// Function node "decode pump registers"
const r = msg.payload;
if (!Array.isArray(r) || r.length < 4) {
    node.warn("Unexpected register block");
    return null;
}

// Conversão para 16 bits com sinal da temperatura
const int16 = v => (v > 32767 ? v - 65536 : v);

// Float de 32 bits a partir de dois registradores, ordem de palavras big-endian
const buf = Buffer.alloc(4);
buf.writeUInt16BE(r[2], 0);
buf.writeUInt16BE(r[3], 2);
const flowRate = buf.readFloatBE(0);

const values = {
    temperature: Math.round(int16(r[0])) / 10,
    pressure: Math.round(r[1]) / 100,
    flow: Math.round(flowRate * 100) / 100
};

// Guarda para combinar com a leitura do coil
flow.set("pump1_values", values);

msg.topic = "connectmq/demo/a7f3k2/plant1/utilities/pump1/telemetry";
msg.payload = {
    ...values,
    running: flow.get("pump1_running") === true
};
return msg;

Ligue a leitura do coil a uma pequena função que guarda o estado: flow.set("pump1_running", msg.payload[0] === true); return null;. Muitos dispositivos usam floats com "palavras invertidas", em que a palavra baixa vem primeiro. Se o valor da vazão parecer absurdo, como 1.2e-38 ou -4.5e+12, troque r[2] e r[3] de lugar e tente de novo.

Passo 3: publique apenas quando algo mudar

Fazer polling a cada 2 segundos e publicar todos os resultados desperdiça banda e enche os assinantes de dados duplicados. Insira um node filter (antes chamado RBE) configurado como "block unless value changes" em msg.payload, ou use uma versão com banda morta em valores individuais se eles oscilarem. O filtro compara o objeto inteiro, e é por isso que a função de decodificação não adiciona timestamp. Depois do filtro, adicione um change node que define msg.payload.ts com um timestamp. Reportar por exceção é um padrão central do MQTT, mas ainda vale adicionar um heartbeat periódico para valores que mudam pouco, para que os assinantes consigam distinguir um dispositivo quieto de um dispositivo morto.

Passo 4: publique no MQTT

Adicione um node mqtt out com o topic vazio para que msg.topic seja usado. Para testes, configure o broker como broker.connectmq.com, porta 1883, com um client ID único, que é o servidor MQTT público. Substitua a7f3k2 por uma string sua. Depois acompanhe a saída:

mosquitto_sub -h broker.connectmq.com -p 1883 -i sub-modbus-a7f3k2 -v \
  -t 'connectmq/demo/a7f3k2/plant1/#'

Você deve ver mensagens como {"temperature":42.3,"pressure":3.34,"flow":12.81,"running":true,"ts":...}. Não envie dados reais da planta para o servidor público: qualquer pessoa pode assiná-lo, e ele serve apenas para testes e protótipos.

Escrevendo no Modbus a partir do MQTT, com segurança

Ler tem baixo risco; escrever em uma bomba, não. Se você aceitar comandos via MQTT, coloque proteções no flow:

  1. Assine um topic de comando dedicado, como .../pump1/cmd, nunca um wildcard.
  2. Valide o payload em um function node contra uma lista de ações permitidas e faixas de valores.
  3. Associe cada ação a um registrador ou coil fixo. Nunca deixe a mensagem escolher o endereço.
  4. Publique o resultado em um topic .../pump1/cmd/ack para que o remetente saiba se a escrita aconteceu.
  5. Use um broker privado com autenticação para qualquer topic que possa mudar o estado de um equipamento.
// Function node "validate pump command" -> Modbus Write (FC5, coil 0)
const cmd = String(msg.payload).trim().toUpperCase();
if (cmd !== "START" && cmd !== "STOP") {
    node.warn("Rejected command: " + cmd);
    return null;
}
msg.payload = cmd === "START";
return msg;

Modbus RTU sobre RS-485

Para dispositivos seriais, mude apenas a configuração do cliente: tipo Serial, porta como /dev/ttyUSB0, baud rate, paridade e stop bits iguais aos do dispositivo (9600 8N1 é comum) e o tipo serial RTU. Cada dispositivo no barramento tem seu próprio unit ID. Mantenha as taxas de polling conservadoras, porque um barramento RS-485 atende todos os dispositivos em sequência, e um timeout em um dispositivo atrasa os outros. O guia de Modbus RTU para MQTT aborda ligação e terminação.

Solução de problemas em flows Node-RED Modbus

Sintoma Causa provável Correção
Erros de timeout IP, porta ou unit ID errados; firewall Teste antes com uma ferramenta Modbus de desktop
Illegal data address (exceção 2) Endereço deslocado em um ou function code errado Use endereços base 0; holding vs input registers
Valores deslocados em um registrador Notação 40001 digitada literalmente Subtraia o deslocamento
Valores de float absurdos Ordem de palavras diferente Troque os dois registradores
Números negativos aparecem como 65.000+ Valor com sinal lido como sem sinal Aplique a conversão int16
O dispositivo para de responder sob carga Clientes demais ou polling rápido demais Um gateway, polling mais lento, leituras agrupadas em blocos

Do gateway à produção

Quando os valores estão fluindo, o gateway é tão útil quanto o broker em que publica. Em um site com vários gateways Node-RED, um cliente SCADA e um historiador, todos devem compartilhar um único broker autenticado, acessível tanto pela rede da planta quanto pela rede do escritório. Um broker MQTT na nuvem é uma forma simples de conseguir isso, porque cada gateway se conecta de saída pela porta 8883 e nenhuma porta de entrada é aberta para a rede de OT. O ConnectMQ também reconhece topics no estilo ISA-95, como plant1/utilities/pump1/telemetry, e mostra os dispositivos por esses níveis no portal. Se você prefere não rodar nenhuma infraestrutura de broker, um broker MQTT gerenciado tira os patches e o monitoramento das suas mãos.

Outros protocolos industriais seguem o mesmo padrão: veja Node-RED OPC UA para MQTT para controladores modernos e Node-RED com Siemens S7 para CLPs S7. Para configurar o broker no Node-RED, o tutorial Node-RED MQTT traz o básico.

Conecte seu gateway Modbus ao ConnectMQ

Cadastre-se em app.connectmq.com no plano Serverless gratuito, sem cartão de crédito. Crie um broker, cole o username, o password e o client ID gerados no node de configuração do Node-RED, ative o TLS na porta 8883 e seus valores Modbus passam a ser publicados de forma privada e criptografada. Use o explorador de topics ao vivo do ConnectMQ para conferir cada registrador que você decodificou.

Perguntas frequentes

O node-red-contrib-modbus suporta Modbus TCP e RTU?

Sim. O node de configuração Modbus Client suporta conexões TCP e seriais, incluindo RTU por adaptadores RS-485. Os nodes de leitura e escrita funcionam da mesma forma nos dois casos.

Por que meu endereço Modbus está deslocado em um no Node-RED?

Datasheets costumam usar a numeração no estilo 40001, que começa em um, enquanto o Node-RED usa endereços de protocolo que começam em zero. O holding register 40001 é o endereço 0 no node Modbus Read.

Como leio um float de 32 bits do Modbus no Node-RED?

Leia dois registradores consecutivos, escreva-os em um buffer de 4 bytes e chame readFloatBE. Se o resultado parecer errado, troque as duas palavras de lugar, porque alguns dispositivos usam a ordem de palavras oposta.

Com que frequência o Node-RED deve fazer polling em um dispositivo Modbus?

Faça polling tão devagar quanto o seu caso de uso permitir, muitas vezes de 1 a 10 segundos para monitoramento. Agrupe registradores em blocos e publique por exceção para manter o dispositivo e o broker com carga leve.

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.