Um navegador de tópicos MQTT mostra cada topic que passa por um broker como uma árvore viva e expansível, com o payload mais recente ao lado de cada nó. Neste tutorial você vai gerar uma hierarquia de topics realista, explorá-la no explorador de topics ao vivo da ConnectMQ e na linha de comando, e aprender os padrões que revelam em segundos erros de nomenclatura, retained messages desatualizadas e payloads malformados.
O Que um Navegador de Tópicos MQTT Faz
O MQTT não tem um comando nativo de "listar topics". Topics não são criados nem registrados; eles existem apenas porque alguém publica neles. Um navegador de tópicos contorna isso assinando um curinga amplo como # (ou a raiz de um projeto, como factory1/#) e montando uma árvore a partir das strings de topic que recebe. Cada barra vira um nível, cada nível vira uma pasta, e o payload mais recente aparece na folha.
Essa ideia simples é surpreendentemente poderosa. Um fluxo plano de mensagens do mosquitto_sub fica difícil de ler quando você tem mais de uma dúzia de dispositivos. Uma árvore mostra de relance:
- Quais ramos existem e quais não deveriam existir.
- Quais folhas estão atualizando agora e quais pararam há horas.
- Quais valores são retidos, ou seja, um novo assinante os receberá imediatamente.
- Qual o tamanho dos payloads e se estão bem formados.
Se a estrutura de topics é novidade para você, vale entender o que um broker MQTT faz com topics e assinaturas antes de começar.
Gere uma Árvore de Topics para Explorar
Você precisa de tráfego para navegar. O script abaixo publica uma pequena hierarquia de fábrica, como a de uma planta de usinagem em Joinville, no servidor MQTT público (gratuito) em broker.connectmq.com, que serve apenas para testes e protótipos. Ele inclui de propósito três erros comuns para que você os encontre no navegador. Instale o client com pip install "paho-mqtt>=2.0".
import json
import random
import time
import uuid
import paho.mqtt.client as mqtt
RUN_ID = uuid.uuid4().hex[:6]
ROOT = f"connectmq/demo/{RUN_ID}"
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id=f"tree-gen-{RUN_ID}",
)
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_start()
print(f"Publishing under {ROOT}/ (subscribe to {ROOT}/#)")
# Metadados retidos dos dispositivos
for line in ("line1", "line2"):
for machine in ("cnc1", "cnc2"):
meta = {"vendor": "demo", "model": "X200", "line": line}
client.publish(f"{ROOT}/factory1/{line}/{machine}/meta",
json.dumps(meta), qos=1, retain=True)
# Erro 1: maiúsculas/minúsculas inconsistentes criam um ramo paralelo
client.publish(f"{ROOT}/factory1/Line1/cnc1/meta", "{}", qos=1, retain=True)
# Erro 2: barra final cria um último nível vazio
client.publish(f"{ROOT}/factory1/line2/cnc2/telemetry/", "42", qos=0)
try:
while True:
for line in ("line1", "line2"):
for machine in ("cnc1", "cnc2"):
payload = {
"spindle_rpm": random.randint(9000, 12000),
"temperature": round(random.uniform(35, 60), 1),
"ts": int(time.time()),
}
client.publish(f"{ROOT}/factory1/{line}/{machine}/telemetry",
json.dumps(payload), qos=0)
# Erro 3: um payload que não é JSON válido
client.publish(f"{ROOT}/factory1/line1/cnc2/telemetry",
"temp=48.2;rpm=10100", qos=0)
time.sleep(2)
except KeyboardInterrupt:
client.loop_stop()
client.disconnect()
O script publica quatro mensagens por ciclo, mais a malformada, o que o mantém com folga dentro do limite do servidor MQTT público de 10 mensagens por segundo por client. Deixe-o rodando e anote a raiz impressa.
Explore a Árvore no Explorador de Topics da ConnectMQ
No seu próprio broker, o explorador de topics ao vivo do portal ConnectMQ é o navegador de tópicos integrado. Para acompanhar, crie um broker gratuito no portal e aponte o script acima para ele, mudando para a porta 8883 com TLS e adicionando as credenciais que o portal gerou (YOUR_USERNAME, YOUR_PASSWORD, YOUR_CLIENT_ID). Para dar uma olhada rápida no servidor MQTT público, qualquer explorador MQTT com suporte a WebSockets pode se conectar a wss://broker.connectmq.com:8084/mqtt e assinar a sua raiz connectmq/demo/<run-id>/#.
À medida que as mensagens chegam, percorra a árvore de cima para baixo:
- Expanda a raiz. Você deve ver
factory1e, abaixo dele,line1,line2e um inesperadoLine1. Topics diferenciam maiúsculas de minúsculas, entãoLine1é um ramo separado que nenhum assinante deline1/#jamais receberá. - Abra
line2/cnc2. Sobtelemetryhá um filho com nome vazio. É a barra final:telemetry/tem um nível a mais quetelemetry, e uma assinatura de.../cnc2/telemetrynão vai corresponder a ele. - Abra
line1/cnc2/telemetry. O valor alterna entre JSON etemp=48.2;rpm=10100. Qualquer consumidor que faça parse de JSON vai lançar um erro a cada duas mensagens. - Observe as folhas
meta. Elas carregam a flag de retenção. Desconecte e reconecte, e elas aparecem imediatamente, enquanto a telemetria só surge quando chega a próxima mensagem.
O portal ConnectMQ também oferece uma visão de dispositivos organizada pelos níveis ISA-95 (empresa, planta, área, linha, célula). Se os seus topics seguem um layout de Unified Namespace, essa visão agrupa os mesmos dados pela hierarquia da planta em vez de strings brutas, o que faz dispositivos fora do lugar se destacarem. Nosso artigo sobre Sparkplug B e o Unified Namespace explica essa estrutura.
Navegue pelos Topics na Linha de Comando
Nem sempre há um navegador gráfico à mão. O mosquitto_sub com a flag -v imprime o topic antes de cada payload, e algumas flags extras o transformam em um navegador leve:
# Todos os topics sob a sua raiz, com os nomes dos topics
mosquitto_sub -h broker.connectmq.com -p 1883 -i browse-$RANDOM \
-t 'connectmq/demo/RUN_ID/#' -v
# Somente retained messages: conecta, imprime o que está retido e sai após 3 s
mosquitto_sub -h broker.connectmq.com -p 1883 -i retained-$RANDOM \
-t 'connectmq/demo/RUN_ID/#' -v --retained-only -W 3
# Nomes de topics únicos vistos em 30 segundos
timeout 30 mosquitto_sub -h broker.connectmq.com -p 1883 -i list-$RANDOM \
-t 'connectmq/demo/RUN_ID/#' -F '%t' | sort -u
Substitua RUN_ID pelo valor que o script imprimiu. O último comando é o mais próximo que o MQTT tem de "listar topics" e é uma forma rápida de comparar os topics que você espera com os que realmente existem. Mais receitas estão nos nossos exemplos de mosquitto_pub e mosquitto_sub.
Padrões de Depuração que um Navegador de Tópicos Revela
Quando você se acostuma a ler uma árvore, a maioria dos problemas de topics cai em um pequeno número de padrões.
| O que você vê na árvore | O que significa | Correção |
|---|---|---|
| Dois ramos que diferem apenas em maiúsculas/minúsculas | Nomenclatura inconsistente no firmware ou na configuração | Padronize em minúsculas e exija isso na revisão de código |
| Uma folha com nome vazio | Barra final no topic de publicação | Remova barras finais antes de publicar |
| Um primeiro nível com nome vazio | Barra inicial (/factory1/...) |
Remova a barra inicial; ela adiciona um nível inútil |
| Uma folha cujo valor nunca muda | O dispositivo parou de publicar ou o valor é um dado retido desatualizado | Verifique o dispositivo; limpe a retained message se estiver obsoleta |
| Valores alternando entre formatos | Duas versões de firmware ou dois publicadores no mesmo topic | Versione o payload ou separe os topics |
| Centenas de folhas irmãs com IDs no nome | IDs únicos colocados alto demais na hierarquia | Mova os IDs para o nível do dispositivo |
| Ramos muito profundos | Topics estruturados em excesso | Achate; o servidor MQTT público permite 8 níveis |
Limpando Retained Messages Desatualizadas
Valores retidos permanecem no broker até serem substituídos. Por isso, um dispositivo desativado pode continuar exibindo um valor "atual" em todos os dashboards. Para remover uma retained message, publique um payload retido vazio no topic exato:
mosquitto_pub -h broker.connectmq.com -p 1883 -i clear-$RANDOM \
-t 'connectmq/demo/RUN_ID/factory1/Line1/cnc1/meta' -r -n
A flag -n envia um payload de tamanho zero e -r define a flag de retenção. Atualize o navegador de tópicos e o ramo Line1 desaparece assim que não tiver outros filhos.
Usando Bem um Navegador de Tópicos em Produção
Um navegador que assina # em um broker de produção movimentado recebe todas as mensagens, o que consome banda e pode esbarrar em cotas de assinatura ou de conexão. Alguns hábitos o mantêm útil:
- Assine a raiz mais estreita que responde à sua pergunta, como
factory1/line2/#, em vez de#. - Use uma credencial dedicada para ferramentas de depuração, para que uma sessão do navegador nunca use o client ID de um dispositivo e o derrube.
- Verifique o estado da conexão além dos dados. O topic
$SYS/broker/connection/{clientId}/stateno seu broker ConnectMQ informa se um client específico está conectado, o que separa "dispositivo offline" de "dispositivo online, mas em silêncio". - Documente suas regras de nomenclatura e compare a árvore com elas após cada release de firmware.
Para fluxos de trabalho centrados no editor, a extensão ConnectMQ para VS Code e o explorador MQTT ConnectMQ Desktop oferecem a mesma navegação em árvore fora do portal. Se você testa apenas pelo navegador, nosso guia sobre usar um cliente web MQTT online combina bem com este, e monitoramento de broker MQTT cobre as métricas que um navegador de tópicos não mostra.
Explore Seus Próprios Topics na ConnectMQ
Crie um broker gratuito em app.connectmq.com no plano Serverless (Free), sem cartão de crédito. O portal inclui o explorador de topics ao vivo, o client no navegador e a visão de dispositivos ISA-95 usados neste guia. Saiba mais sobre a ConnectMQ como um broker MQTT gerenciado ou leia o guia mais amplo para escolher um broker MQTT na nuvem.
Perguntas frequentes
Posso listar todos os topics de um broker MQTT?
Não diretamente; o MQTT não tem um registro de topics. Um navegador de tópicos assina um curinga e mostra os topics que recebem mensagens, além de todos os topics retidos, o que é o equivalente prático.
Por que meu navegador de tópicos não mostra um topic que eu sei que existe?
Ou nada foi publicado nele desde que você assinou e ele não guarda nenhuma retained message, ou o seu curinga não o cobre. Verifique maiúsculas/minúsculas, barras iniciais ou finais e a raiz da assinatura.
Assinar # é seguro em um broker de produção?
Funciona, mas recebe todas as mensagens, o que pode ser pesado. Assine a raiz mais estreita que responde à sua pergunta e use uma credencial dedicada para depuração.
Como apago um topic da árvore?
Topics desaparecem quando nada os mantém. Limpe uma retained message publicando um payload retido vazio naquele topic exato e pare o publicador que o cria.



