As arquiteturas SCADA MQTT substituem o modelo clássico em que o mestre consulta cada RTU por dispositivos que reportam por exceção a um broker central e hosts SCADA que assinam o que precisam. Este guia explica por que essa mudança economiza largura de banda e simplifica a integração, como funciona a percepção de estado quando nada é consultado por polling e como migrar um sistema existente passo a passo. Você também vai construir um pequeno host em Python que detecta RTUs offline e com dados desatualizados, a habilidade central de qualquer SCADA baseado em MQTT.
Como funciona a telemetria SCADA tradicional
Em um sistema SCADA clássico, a estação mestre comanda a conversa. Ela faz polling de cada RTU ou CLP em sequência via Modbus, DNP3 ou um protocolo proprietário, pedindo os mesmos registradores a cada ciclo, tenha algo mudado ou não. O modelo tem pontos fortes reais: o mestre sempre sabe se um dispositivo respondeu, e a temporização é previsível.
Ele também tem custos conhecidos:
- Largura de banda gasta com dados inalterados. Um nível de reservatório de uma companhia de saneamento que muda duas vezes por hora continua sendo lido a cada poucos segundos.
- O tempo de varredura cresce com a rede. Em links de rádio ou satélite, adicionar RTUs alonga o ciclo de polling para todos.
- Acoplamento forte. Cada novo consumidor, seja um historiador, uma ferramenta de análise ou uma segunda sala de controle, consulta os dispositivos novamente ou depende das interfaces do servidor SCADA.
- Endereços de dispositivos por toda parte. Mapas de registradores e detalhes de protocolo vazam para todo sistema que precisa dos dados.
O que muda com o SCADA MQTT
Com MQTT, a RTU ou o gateway de borda abre uma conexão de saída com um broker e publica valores quando eles mudam de forma significativa. Hosts SCADA, historiadores e dashboards são assinantes. O broker fica no meio e distribui as mensagens.
| Aspecto | SCADA por polling | SCADA MQTT |
|---|---|---|
| Quem inicia | O mestre consulta cada dispositivo | O dispositivo publica, os hosts assinam |
| Tráfego | Todos os pontos, a cada varredura | Apenas mudanças, mais heartbeats |
| Adicionar um consumidor | Novos pollings ou interface do SCADA | Nova assinatura, dispositivos intocados |
| Direção da conexão | Do mestre ao dispositivo (entrada no campo) | Do dispositivo ao broker (saída do campo) |
| Saúde do dispositivo | Implícita: sem resposta significa problema | Explícita: Last Will, mensagens de nascimento/morte |
| Contexto dos dados | Endereços de registradores | Topics nomeados, muitas vezes ISA-95 ou Sparkplug |
| Eficiência do link | Ruim em links de alta latência | Boa: sessão persistente, pacotes pequenos |
A maior mudança conceitual é o report by exception (RBE). Em vez de perguntar, o campo informa. Uma banda morta em cada valor analógico e a publicação imediata de toda mudança de estado digital mantêm os dados atualizados com uma fração do tráfego. O guia de report by exception detalha o dimensionamento da banda morta.
O broker como hub do SCADA
Em um design SCADA MQTT, o broker se torna o sistema nervoso central. Os dispositivos de campo não sabem nem se importam com quantos hosts consomem seus dados, e os hosts não precisam conhecer endereços de dispositivos. Esse desacoplamento permite padrões que são complicados com polling:
- Hosts SCADA redundantes assinam os mesmos topics sem dobrar o tráfego de campo.
- Consumidores de TI, como historiadores e ferramentas de análise, assinam em paralelo sem mexer no sistema de controle.
- Migrações em fases podem rodar o SCADA antigo e o novo lado a lado com os mesmos dados ao vivo.
Entender o que um broker MQTT faz é a base aqui: ele roteia mensagens, guarda valores retidos e estado de sessão e controla quem pode se conectar.
Percepção de estado sem polling
A objeção mais comum ao SCADA MQTT é: "Se eu parar de fazer polling, como sei que uma RTU está viva?" O MQTT responde isso em dois níveis.
Keep alive e Last Will. Todo cliente declara um intervalo de keep alive. Se o broker não ouvir nada por 1,5 vez esse intervalo, ele encerra a sessão e publica a mensagem Last Will do cliente, por exemplo um offline retido no topic de status da RTU. Quando a RTU reconecta, publica um online retido. Todo assinante, inclusive os que iniciam depois, vê o estado atual.
Sparkplug B. A especificação Sparkplug formaliza isso para SCADA: os edge nodes publicam mensagens NBIRTH e DBIRTH com todas as métricas ao conectar, NDEATH como Last Will, e um host primário publica seu próprio STATE para que os edge nodes saibam se um host SCADA está escutando. Os hosts podem pedir um rebirth quando detectam uma lacuna. O Ignition e muitos gateways de borda implementam isso nativamente; veja aplicações Sparkplug primary host para o lado do host.
Mesmo com topics JSON simples, você também deve detectar dados desatualizados: um dispositivo que está conectado, mas cujos valores pararam de atualizar, por exemplo porque o I/O de campo falhou.
Exemplo: um host SCADA MQTT mínimo em Python
Este host assina o status e a telemetria das RTUs, acompanha o estado online a partir de mensagens Last Will retidas e sinaliza qualquer RTU cujos dados não mudaram nem foram atualizados dentro do heartbeat esperado. Rode-o no servidor MQTT público com um simulador e depois aponte-o para o seu próprio broker.
import json
import time
import uuid
import threading
import paho.mqtt.client as mqtt
BROKER, PORT = "broker.connectmq.com", 1883
PREFIX = "connectmq/demo/scada-7h2k" # prefixo aleatório: dados públicos podem ser lidos por todos
STALE_AFTER = 120 # segundos; o heartbeat é de 60 s
rtus = {} # rtu_id -> {"online": bool, "last_seen": float, "values": dict}
lock = threading.Lock()
def on_connect(client, userdata, flags, reason_code, properties):
print("Connected:", reason_code)
client.subscribe(f"{PREFIX}/+/status", qos=1)
client.subscribe(f"{PREFIX}/+/telemetry/#", qos=1)
def on_message(client, userdata, msg):
parts = msg.topic.split("/")
rtu_id = parts[3]
with lock:
rtu = rtus.setdefault(rtu_id, {"online": False, "last_seen": 0.0, "values": {}})
if parts[4] == "status":
rtu["online"] = msg.payload.decode() == "online"
print(f"[STATE] {rtu_id} is {'ONLINE' if rtu['online'] else 'OFFLINE'}")
else:
point = "/".join(parts[5:])
rtu["values"][point] = json.loads(msg.payload)
rtu["last_seen"] = time.time()
def watchdog():
while True:
time.sleep(10)
now = time.time()
with lock:
for rtu_id, rtu in rtus.items():
if rtu["online"] and now - rtu["last_seen"] > STALE_AFTER:
print(f"[STALE] {rtu_id}: no data for {int(now - rtu['last_seen'])} s")
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"scada-host-{uuid.uuid4().hex[:6]}")
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, PORT, keepalive=30)
threading.Thread(target=watchdog, daemon=True).start()
client.loop_forever()
Simule uma RTU em outro terminal publicando um status retido e um valor de telemetria:
mosquitto_pub -h broker.connectmq.com -p 1883 -i rtu-sim-7h2k \
-t 'connectmq/demo/scada-7h2k/rtu07/status' -m online -r -q 1
mosquitto_pub -h broker.connectmq.com -p 1883 -i rtu-sim2-7h2k \
-t 'connectmq/demo/scada-7h2k/rtu07/telemetry/tank1/level' -m '{"value":3.42,"unit":"m"}' -q 1
Para um simulador de longa duração com um Last Will real, use o mosquitto_sub ou um script com --will-topic connectmq/demo/scada-7h2k/rtu07/status --will-payload offline --will-retain e encerre-o à força para ver o host reagir. Use o servidor MQTT público (gratuito) apenas para valores simulados como estes.
Migrando um sistema SCADA existente
Uma substituição de uma vez só raramente é necessária. Um caminho em fases mantém a operação segura:
- Espelhe primeiro. Adicione um publicador MQTT ao lado do mestre existente, seja um módulo SCADA que encaminha tags ou um gateway de borda que lê as mesmas RTUs em modo somente escuta. Nada no controle muda.
- Defina o namespace. Acorde a estrutura de topics (caminhos ISA-95 ou group e node IDs do Sparkplug) e o formato do payload antes que existam muitas fontes.
- Conecte consumidores somente leitura. Historiadores, dashboards e ferramentas de análise passam para o broker. Valide os valores comparando com as telas do SCADA.
- Converta os sites para RBE. Substitua o polling em um site ou tipo de link de cada vez por RTUs ou gateways de borda com suporte a RBE. Compare largura de banda e atualidade dos dados.
- Mova o controle com cuidado. Comandos via MQTT precisam de padrões de confirmação, timeouts e intertravamentos. As mensagens de comando do Sparkplug ou o request/response do MQTT 5 com response topics ajudam a estruturar isso.
- Desative o polling legado apenas quando todos os consumidores tiverem migrado e o comportamento dos alarmes tiver sido verificado.
Armadilhas de design
- Sem heartbeat. RBE puro sem atualização periódica torna um valor congelado indistinguível de um valor estável.
- Timestamps do relógio do dispositivo sem sincronização. A análise de sequência de eventos quebra se os relógios das RTUs derivarem. Use NTP ou horário de GPS na origem.
- QoS 2 em tudo. Adiciona idas e voltas em links lentos. QoS 1 com consumidores idempotentes é a escolha usual para telemetria.
- Reter tudo. Retenha status e últimos valores, não fluxos de alta taxa.
- Topics planos.
rtu07/ai3não escala; nomeie por site e ativo.
Onde o ConnectMQ se encaixa
Um broker que atua como hub de SCADA precisa de TLS, credenciais por dispositivo e proteção contra clientes mal comportados. O ConnectMQ oferece MQTT 3.1.1 e 5.0 com TLS, vincula cada client ID às credenciais emitidas e aplica proteção contra inundação e bloqueio de IP após falhas repetidas de login. O portal decodifica payloads Sparkplug B, pode republicar dados Sparkplug em topics ISA-95 legíveis e oferece regras de alerta por limite com um log de alertas, útil para uma visão operacional rápida ao lado do seu host SCADA. Os mesmos topics retidos de status e telemetria também podem alimentar um gêmeo digital das estações remotas. Softwares SCADA, historiadores e scripts se conectam como clientes MQTT comuns. Se você prefere não operar infraestrutura de broker em cada centro de controle, vale avaliar um broker MQTT gerenciado; para detalhes de implementação com um pacote SCADA específico, veja Ignition com MQTT e, para o contexto mais amplo, o guia de IoT industrial com MQTT.
Modernize sua telemetria SCADA com o ConnectMQ
Comece com um site ou um tipo de RTU. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, conecte um gateway e o seu host SCADA e compare os dados lado a lado com o polling existente.
Perguntas frequentes
O MQTT pode substituir o DNP3 ou o Modbus no SCADA?
O MQTT muitas vezes substitui o transporte entre os sites de campo e o centro de controle, enquanto o Modbus ou o DNP3 podem continuar sendo usados localmente entre um gateway de borda e os dispositivos de campo.
Como um host SCADA MQTT sabe que um dispositivo está offline?
Pela mensagem Last Will do dispositivo, publicada pelo broker quando o keep alive expira, ou por mensagens NDEATH do Sparkplug. Adicione detecção de dados desatualizados para dispositivos que continuam conectados, mas param de atualizar.
O Sparkplug B é obrigatório para SCADA MQTT?
Não, mas ele padroniza mensagens de nascimento e morte, definições de métricas e o estado do host, o que facilita muito a interoperabilidade entre hosts SCADA e dispositivos de borda.
Qual QoS a telemetria SCADA deve usar?
QoS 1 é a escolha comum, combinada com topics de status retidos. QoS 0 serve para dados de alta taxa em que a próxima amostra substitui uma perdida.



