MQTT gerenciado na nuvem

Rastreamento de Veículos com MQTT: Tópicos, Payloads e Mapa da Frota ao Vivo

Monte um rastreamento de veículos com MQTT que funciona em redes celulares instáveis: design de tópicos, payloads GPS compactos, ajuste de keep alive, detecção de veículos offline e um mapa web ao vivo.

Ilustração de rastreamento de veículos com MQTT mostrando vans de entrega enviando posições GPS via rede celular a um broker na nuvem e a um mapa da frota ao vivo
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 rastreamento de veículos com MQTT funciona bem porque o protocolo foi criado exatamente para esse tipo de enlace: dispositivos pequenos enviando mensagens pequenas e frequentes por redes instáveis e tarifadas por consumo. Neste guia você vai projetar uma estrutura de tópicos para uma frota, escolher payloads GPS compactos, ajustar keep alive e sessões para rastreadores celulares, detectar veículos offline e construir um mapa ao vivo no navegador que se atualiza diretamente a partir de assinaturas MQTT no ConnectMQ.

Por que o MQTT combina com telemetria de frotas

Um rastreador celular instalado em uma van passa a vida trocando de célula, entrando em túneis e perdendo sinal em estacionamentos. Cada reconexão custa tempo, energia e dados. O MQTT ajuda de várias formas:

  • Uma única conexão persistente em vez de uma nova requisição HTTP para cada posição, de modo que cabeçalhos e handshakes são pagos uma só vez.
  • Overhead fixo pequeno por mensagem, o que faz diferença quando cada kilobyte é cobrado.
  • Keep alive e Last Will dão ao servidor um sinal claro quando um veículo fica em silêncio.
  • QoS 1 com sessões persistentes permite que comandos cheguem a um veículo que perdeu o sinal por alguns instantes.
  • Distribuição por assinaturas: a mesma posição alimenta o mapa do despachante, um serviço de geofencing e um gravador de histórico sem que o rastreador faça nada a mais.

Para relembrar as garantias de entrega, veja níveis de QoS do MQTT explicados.

Design de tópicos para rastreamento de veículos

Comece com uma hierarquia que reflita como as pessoas consultam os dados: por frota, depois por veículo, depois por tipo de dado.

fleet/{fleetId}/vehicle/{vehicleId}/position     live GPS fixes
fleet/{fleetId}/vehicle/{vehicleId}/status       online/offline (retained)
fleet/{fleetId}/vehicle/{vehicleId}/event        ignition, harsh braking, door open
fleet/{fleetId}/vehicle/{vehicleId}/diag         battery voltage, signal quality
fleet/{fleetId}/vehicle/{vehicleId}/cmd          commands to the tracker

Assim, o mapa do despachante pode assinar fleet/north/vehicle/+/position, um serviço de alertas fleet/+/vehicle/+/event e um painel de operações fleet/+/vehicle/+/status. Mantenha os identificadores curtos e estáveis: um ID de veículo como v0142, e não a placa completa com espaços. Evite colocar dados pessoais identificáveis, como o nome do motorista, nos nomes dos tópicos.

Design do payload

As mensagens de posição são a maior parte do seu tráfego, então merecem atenção.

Campo Chave Exemplo Observações
Timestamp t 1792137600 Segundos Unix da hora GNSS, não a hora de recebimento no servidor
Latitude la 41.01224 5 casas decimais equivalem a cerca de um metro
Longitude lo 28.97601 Mesma precisão
Velocidade s 48 km/h, inteiro
Direção h 270 Graus, inteiro
Qualidade do fix q 3 0 = nenhum, 2 = 2D, 3 = 3D
Satélites n 9 Útil para filtrar fixes ruins

O payload resultante tem cerca de 90 bytes:

{"t":1792137600,"la":41.01224,"lo":28.97601,"s":48,"h":270,"q":3,"n":9}

Regras práticas:

  1. Sempre inclua o timestamp do dispositivo. Mensagens armazenadas durante uma falha de cobertura chegam atrasadas; o mapa e o histórico precisam ordenar pela hora do fix.
  2. Agrupe ao bufferizar. Depois de um túnel, publique uma única mensagem com um array dos fixes armazenados, em vez de centenas de mensagens individuais.
  3. Reporte de forma adaptativa. A cada 5 a 15 segundos em movimento, a cada poucos minutos quando estacionado e imediatamente em mudanças significativas de direção.
  4. Descarte fixes ruins no próprio dispositivo. Se a qualidade do fix for 0, não publique a posição.

Keep alive, sessões e QoS em enlaces celulares

  • Keep alive: 60 a 120 segundos é um ponto de partida razoável em rede celular. Valores menores detectam quedas mais rápido, mas mantêm o modem acordado; os timeouts de NAT da operadora também podem derrubar silenciosamente conexões ociosas, então não use um valor tão longo que o mapeamento NAT expire antes.
  • QoS: QoS 0 é aceitável para posições de alta frequência, em que o próximo fix substitui o anterior; QoS 1 para eventos e comandos que não podem ser perdidos.
  • Sessões persistentes: conecte com clean start igual a false e um session expiry (MQTT 5), por exemplo de 10 a 30 minutos, para que comandos enviados durante uma interrupção curta sejam entregues na reconexão.
  • Expiração de mensagens: defina uma expiração em comandos como "destravar portas", para que um veículo que volte uma hora depois não execute uma instrução antiga.
  • Last Will: registre um will offline retido no tópico de status e publique um online retido após conectar.

Simulando um rastreador em Python

Antes de o hardware chegar, simule um veículo. Este script percorre uma trajetória, usa um Last Will e publica posições com paho-mqtt 2.x. Ele usa o servidor MQTT público, feito para testes, para que você possa executá-lo imediatamente; troque para suas próprias credenciais e a porta 8883 em uso real.

import json
import math
import time
import uuid

import paho.mqtt.client as mqtt

HOST = "broker.connectmq.com"
PORT = 1883
PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:6]}"
VEHICLE = "v0142"
BASE = f"{PREFIX}/fleet/north/vehicle/{VEHICLE}"

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=f"sim-{VEHICLE}-{uuid.uuid4().hex[:6]}",
                     protocol=mqtt.MQTTv5)
client.will_set(f"{BASE}/status", "offline", qos=1, retain=True)


def on_connect(client, userdata, flags, reason_code, properties):
    print("Connected:", reason_code, "| topic prefix:", PREFIX)
    client.publish(f"{BASE}/status", "online", qos=1, retain=True)


client.on_connect = on_connect
client.connect(HOST, PORT, keepalive=90)
client.loop_start()

lat, lon, heading = 41.0100, 28.9700, 45.0
try:
    while True:
        lat += 0.0003 * math.cos(math.radians(heading))
        lon += 0.0003 * math.sin(math.radians(heading))
        heading = (heading + 3) % 360
        fix = {"t": int(time.time()), "la": round(lat, 5), "lo": round(lon, 5),
               "s": 42, "h": int(heading), "q": 3, "n": 9}
        client.publish(f"{BASE}/position", json.dumps(fix), qos=0)
        time.sleep(5)
except KeyboardInterrupt:
    client.publish(f"{BASE}/status", "offline", qos=1, retain=True).wait_for_publish()
    client.loop_stop()
    client.disconnect()

Anote o prefixo impresso; você vai precisar dele para o mapa. O servidor MQTT público permite 10 mensagens por segundo por cliente e 8 níveis de tópico, então o tópico completo connectmq/demo/xxxxxx/fleet/north/vehicle/v0142/position (8 níveis) cabe no limite. Encurte a hierarquia se adicionar mais níveis. Lembre-se de que a área pública pode ser lida por qualquer pessoa: use apenas coordenadas simuladas.

Um mapa da frota ao vivo a partir de assinaturas

O mapa é simplesmente um cliente MQTT no navegador que assina as posições e move os marcadores. Esta página usa MQTT.js sobre Secure WebSocket e Leaflet.

// map.js - carregue Leaflet e MQTT.js na página e adicione um elemento contêiner com id "map"
const PREFIX = "connectmq/demo/REPLACE_WITH_PREFIX";
const map = L.map("map").setView([41.01, 28.97], 13);
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
  attribution: "OpenStreetMap contributors",
}).addTo(map);

const markers = new Map();
const client = mqtt.connect("wss://broker.connectmq.com:8084/mqtt", {
  clientId: "fleet-map-" + Math.random().toString(16).slice(2, 10),
  protocolVersion: 5,
});

client.on("connect", () => {
  client.subscribe(`${PREFIX}/fleet/+/vehicle/+/position`);
  client.subscribe(`${PREFIX}/fleet/+/vehicle/+/status`);
});

client.on("message", (topic, payload) => {
  const parts = topic.split("/");
  const vehicleId = parts[parts.length - 2];
  const kind = parts[parts.length - 1];

  if (kind === "position") {
    const fix = JSON.parse(payload.toString());
    let m = markers.get(vehicleId);
    if (!m) {
      m = L.marker([fix.la, fix.lo]).addTo(map).bindTooltip(vehicleId);
      markers.set(vehicleId, m);
    }
    m.setLatLng([fix.la, fix.lo]);
    m.setTooltipContent(`${vehicleId} - ${fix.s} km/h`);
  } else if (kind === "status") {
    const m = markers.get(vehicleId);
    if (m) m.setOpacity(payload.toString() === "online" ? 1 : 0.4);
  }
});

Em produção, autentique o mapa com credenciais emitidas pelo seu backend em vez de embutir uma senha compartilhada na página e, se muitas pessoas abrirem o mapa ao mesmo tempo, considere um pequeno backend que assine uma única vez e entregue as posições aos navegadores.

Armazenamento de histórico e geofencing

O ConnectMQ é o broker, não um banco de dados, então histórico e geofencing rodam como clientes MQTT seus. Um serviço em Python ou Node.js que assine fleet/+/vehicle/+/position pode gravar em PostgreSQL com PostGIS ou em um banco de séries temporais, e um segundo serviço pode testar cada fix contra polígonos de geofence e publicar no tópico de eventos. A partir do Serverless (Paid), shared subscriptions como $share/geo/fleet/+/vehicle/+/position permitem que várias instâncias dividam a carga. As regras de alerta por limite do portal também são úteis para verificações simples, como a tensão da bateria nos diagnósticos caindo abaixo de um valor.

Lidando com falhas de cobertura no dispositivo

Rastreadores passam um bom tempo sem cobertura, então o firmware precisa de um plano para isso. Mantenha um buffer circular dos fixes recentes em flash ou RAM, dimensionado para a maior falha que você espera, por exemplo uma hora de fixes em taxa reduzida. Quando a conexão voltar, publique primeiro a posição atual para que o mapa ao vivo se atualize imediatamente e, em seguida, esvazie o buffer em lotes com os timestamps originais. Os consumidores que gravam histórico devem fazer upsert por veículo e timestamp, para que um lote entregue duas vezes com QoS 1 não gere pontos duplicados.

Checklist de produção

  1. Credenciais e client ID exclusivos por rastreador, TLS na porta 8883.
  2. Timestamp do dispositivo em cada fix; envio em lotes após interrupções.
  3. Intervalo de reporte adaptativo.
  4. Status retido com Last Will.
  5. Sessões persistentes e expiração de mensagens para comandos.
  6. Nenhum dado pessoal nos nomes de tópicos.
  7. Backoff de reconexão com jitter para toda a frota.

O lado ESP32 de um rastreador é abordado em rastreador GPS com ESP32 e MQTT, e MQTT para aplicativos móveis trata de apps para motoristas ou despachantes. Para opções de hospedagem, veja o guia de broker MQTT na nuvem.

Rastreie sua frota com o ConnectMQ

Crie um broker Serverless gratuito em app.connectmq.com sem cartão de crédito, aponte seus rastreadores ou o simulador para ele via TLS e acompanhe as posições chegando no explorador de tópicos ao vivo. O ConnectMQ é um broker MQTT gerenciado, com planos Serverless (Paid) e Dedicated conforme sua frota cresce.

Perguntas frequentes

Com que frequência um rastreador veicular deve publicar sua posição via MQTT?

A cada 5 a 15 segundos em movimento e a cada poucos minutos quando estacionado é um ponto de partida comum. Ajuste conforme o seu caso de uso e o seu plano de dados.

Qual QoS devo usar para posições GPS?

QoS 0 costuma bastar para posições frequentes, porque o próximo fix substitui o anterior. Use QoS 1 para eventos e comandos que precisam chegar.

Como sei quando um veículo fica offline?

Registre um Last Will retido com offline no tópico de status do veículo e publique um online retido após conectar.

O ConnectMQ pode armazenar o histórico de localização?

Não, o broker roteia mensagens. Execute seu próprio serviço assinante para gravar as posições em um banco de dados como PostgreSQL com PostGIS.

Artigos relacionados

Broker MQTT BYOC: Bring Your Own Cloud Explicado

Um broker MQTT BYOC roda na sua conta de nuvem, mas é operado por um provedor. Entenda como o modelo funciona, a divisão de responsabilidades e como preparar a sua conta para ele.

9 min de leitura

Alternativa ao Google Cloud IoT Core: Opções e Migração Após o Encerramento

O Google desativou o Cloud IoT Core em agosto de 2023. Este guia compara as alternativas realistas, mapeia os conceitos do IoT Core para MQTT puro e mostra como mover dispositivos para um broker MQTT gerenciado mantendo os dados fluindo para o Google Cloud.

9 min de leitura

Mensagens MQTT por Segundo: Como Estimar e Medir a Vazão

O planejamento de vazão em MQTT se resume a algumas fórmulas e a uma medição honesta. Aprenda a estimar mensagens de entrada e saída por segundo, considerar os picos e associar o resultado a um plano de broker.

8 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.