MQTT sobre rede celular é a forma como a maioria dos ativos remotos (estações de bombeamento, tanques, usinas solares, veículos, monitores ambientais) chega à nuvem, mas as regras de projeto são diferentes das de Wi-Fi ou Ethernet. Os bytes são tarifados, os links caem com mais frequência e as redes das operadoras fecham silenciosamente conexões ociosas. Este guia mostra como estimar o consumo de dados, escolher valores de keep alive, reduzir o overhead do TLS e decidir entre LTE-M e NB-IoT para que seus dispositivos fiquem conectados sem contas surpresa.
Por Que a Rede Celular Muda o Projeto MQTT
O MQTT foi originalmente pensado para links instáveis e de baixa banda, então já se encaixa bem: cabeçalho fixo de 2 bytes, conexões TCP persistentes e publish-subscribe que evita polling. Mas três realidades da rede celular definem os detalhes:
- Cada byte é cobrado, incluindo cabeçalhos TCP/IP, registros TLS, confirmações e pings de keep alive, não apenas o seu payload.
- O NAT de nível de operadora (CGNAT) fica entre a maioria dos dispositivos e a internet e descarta mapeamentos TCP ociosos após um timeout específico de cada operadora. Se o MQTT ficar em silêncio por mais tempo que isso, a conexão morre sem que nenhum dos lados perceba de imediato.
- O estado do rádio custa energia. Cada transmissão acorda o modem, que permanece em estado de alto consumo por um tempo depois. Muitos envios pequenos drenam baterias mais rápido do que alguns envios agrupados.
LTE-M vs NB-IoT para MQTT
| LTE-M (Cat-M1) | NB-IoT (Cat-NB1/NB2) | |
|---|---|---|
| Vazão | Maior, confortável para MQTT sobre TLS | Muito baixa; handshakes grandes demoram muito |
| Latência | Comparável à do LTE comum, baixa o suficiente para comandos interativos | Alta e variável, às vezes segundos |
| Mobilidade | Suporta handover entre células | Pensado para dispositivos estacionários |
| Adequação a TCP/TLS | Boa | Possível, mas muitas vezes combinado com protocolos baseados em UDP |
| Economia de energia | Suporta PSM e eDRX | Suporta PSM e eDRX, consumo ocioso muito baixo |
| Cobertura | Boa, melhor que a do LTE comum | Excelente em ambientes internos profundos e subterrâneos |
Para MQTT sobre TCP e TLS, o LTE-M costuma ser a escolha pragmática: os handshakes TLS terminam de forma confiável e os comandos chegam rápido ao dispositivo. O NB-IoT se destaca em dispositivos estacionários que enviam relatórios pequenos e pouco frequentes de lugares de difícil acesso; nesses casos, muitas equipes usam MQTT-SN ou outro protocolo baseado em UDP, ou aceitam uma conexão lenta com MQTT sobre TCP. Verifique quais tecnologias a sua operadora suporta na região de implantação antes de escolher o hardware; alguns modems suportam as duas e alternam automaticamente.
Estimando o Consumo de Dados do MQTT sobre Rede Celular
O tamanho do payload costuma ser a menor parte da conta. Considere:
- Cabeçalhos TCP/IP em cada pacote (cerca de 40 bytes em IPv4 sem opções, mais com opções ou IPv6), além das confirmações TCP.
- Overhead dos registros TLS por mensagem, algumas dezenas de bytes para cabeçalho, nonce e tag de autenticação.
- Overhead do MQTT: cabeçalho fixo, nome do topic (muitas vezes a maior parte de uma mensagem pequena) e um PUBACK no QoS 1.
- Pings de keep alive: PINGREQ e PINGRESP têm apenas 2 bytes cada, mas com TLS, cabeçalhos TCP/IP e ACKs, cada ida e volta custa bem mais na rede.
- Estabelecimento da conexão: um handshake TLS completo, incluindo a cadeia de certificados do servidor, costuma ter vários kilobytes. Reconexões frequentes podem dominar o consumo.
O script abaixo dá uma estimativa aproximada. Os valores por pacote são suposições deliberadamente conservadoras; substitua-os por valores medidos no seu modem (a maioria dos modems informa bytes enviados e recebidos).
# Estimativa aproximada de dados mensais para um dispositivo celular com MQTT sobre TLS.
# Os valores de overhead são suposições - meça o seu próprio link e ajuste.
PAYLOAD_BYTES = 60 # ex.: JSON compacto
TOPIC_BYTES = 40 # tamanho da string do topic
MSGS_PER_HOUR = 12 # uma leitura a cada 5 minutos
QOS = 1 # QoS 1 acrescenta um PUBACK
KEEPALIVE_S = 240 # pings só contam quando o link está ocioso
RECONNECTS_PER_DAY = 2 # cada uma paga um handshake TLS completo
TLS_HANDSHAKE_BYTES = 6000 # suposição: a cadeia de certificados domina
TCP_IP_PER_PACKET = 52 # IPv4 + TCP com a opção de timestamps
TLS_PER_RECORD = 29 # overhead de registro TLS 1.2 AES-GCM
TCP_ACK = 52 # pacote de ACK puro
def bytes_per_publish():
mqtt = 2 + 2 + TOPIC_BYTES + (2 if QOS > 0 else 0) + PAYLOAD_BYTES
out = mqtt + TLS_PER_RECORD + TCP_IP_PER_PACKET
back = TCP_ACK
if QOS > 0:
back = 4 + TLS_PER_RECORD + TCP_IP_PER_PACKET + TCP_ACK # PUBACK + o nosso ACK
return out + back
def bytes_per_ping():
one_way = 2 + TLS_PER_RECORD + TCP_IP_PER_PACKET
return 2 * one_way + 2 * TCP_ACK
msgs = MSGS_PER_HOUR * 24 * 30
gap = 3600 / MSGS_PER_HOUR
pings_per_gap = int(gap // KEEPALIVE_S) # pings necessários entre mensagens
pings = pings_per_gap * msgs
total = (msgs * bytes_per_publish()
+ pings * bytes_per_ping()
+ RECONNECTS_PER_DAY * 30 * TLS_HANDSHAKE_BYTES)
print(f"messages/month: {msgs}")
print(f"payload only: {msgs * PAYLOAD_BYTES / 1e6:.2f} MB")
print(f"estimated total: {total / 1e6:.2f} MB")
Ao rodá-lo, você vê o padrão que vai encontrar em campo: o total na rede é várias vezes o payload bruto, e o tamanho do topic, as confirmações e as reconexões pesam tanto quanto os próprios dados. É por isso que as otimizações abaixo focam no overhead.
Keep Alive vs Timeouts de NAT da Operadora
O intervalo de keep alive do MQTT diz ao broker por quanto tempo o cliente pode ficar em silêncio. Se nada mais for enviado, o cliente manda um PINGREQ antes de o intervalo expirar. Na rede celular, o keep alive tem uma segunda função: manter vivo o mapeamento de NAT da operadora.
- Se o keep alive for maior que o timeout de ociosidade do NAT, o mapeamento é descartado silenciosamente. O dispositivo continua achando que está conectado; a próxima publicação some, e a conexão só é detectada como morta depois de um timeout TCP. Enquanto isso, comandos vindos da nuvem nunca chegam.
- Se o keep alive for muito menor que o necessário, você paga por pings desnecessários e mantém o rádio acordado.
Os timeouts de NAT variam entre operadoras e podem ser de apenas alguns minutos. Meça o seu: conecte com um keep alive longo, aumente progressivamente o intervalo entre publicações e anote quando as mensagens vindas da nuvem param de chegar. Depois, configure o keep alive com folga abaixo desse valor. Se o dispositivo só envia dados e não precisa receber comandos, uma alternativa é conectar, publicar e desconectar, aceitando o custo do handshake a cada vez, o que pode sair mais barato quando os relatórios têm horas de intervalo.
Reduza o Custo do TLS Sem Abrir Mão do TLS
Nunca envie MQTT em texto puro por uma rede celular pública. Em vez disso, torne o TLS mais barato:
- Mantenha as conexões abertas quando os relatórios são frequentes, para que o handshake aconteça raramente.
- Use retomada de sessão TLS se o seu modem ou biblioteca TLS suportar session IDs ou session tickets. Um handshake retomado pula a troca de certificados e economiza bytes e tempo.
- Prefira ECDHE com ECDSA quando os dois lados suportarem; chaves e assinaturas de curvas elípticas são menores que as equivalentes RSA.
- Confie apenas na raiz necessária (por exemplo, ISRG Root X1 para certificados Let's Encrypt), para que o dispositivo armazene e valide uma cadeia mínima.
- Evite tempestades de reconexão. Use backoff exponencial com jitter, para que uma queda da célula não dispare centenas de handshakes seguidos.
Encolha Cada Mensagem
- Topics curtos. Um topic como
t/pump7/pé muito mais barato a cada publicação do que uma hierarquia longa e descritiva. Com o MQTT 5, os topic aliases permitem que o cliente envie o topic completo uma vez e depois se refira a ele por um pequeno inteiro, mantendo topics legíveis sem o custo por mensagem. - Payloads compactos. Chaves JSON curtas, inteiros com escala implícita ou um formato binário como Protobuf (como o Sparkplug B usa).
- Agrupe leituras. Envie dez leituras em uma mensagem a cada dez minutos em vez de uma por minuto; os cabeçalhos são pagos uma vez só.
- Report by exception. Envie apenas as mudanças significativas mais um heartbeat; veja report by exception.
- Escolha do QoS. O QoS 1 acrescenta um PUBACK por mensagem. Use-o onde a entrega importa, e QoS 0 para valores de alta frequência em que a próxima leitura substitui a anterior.
Configurações de Sessão do MQTT 5 para Links Intermitentes
Uma sessão persistente permite que o broker mantenha as assinaturas e enfileire mensagens QoS 1 para o dispositivo enquanto ele fica brevemente offline, para que comandos enviados durante uma queda não se percam. Com paho-mqtt 2.x:
import paho.mqtt.client as mqtt
from paho.mqtt.packettypes import PacketTypes
from paho.mqtt.properties import Properties
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id="YOUR_CLIENT_ID", protocol=mqtt.MQTTv5)
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set() # repositório de CAs do sistema
client.reconnect_delay_set(min_delay=2, max_delay=300)
props = Properties(PacketTypes.CONNECT)
props.SessionExpiryInterval = 3600 # mantém a sessão por 1 h após uma queda
client.connect("YOUR_BROKER_HOST", 8883, keepalive=240,
clean_start=False, properties=props)
client.loop_forever()
Combine isso com um buffer local para os dados de saída, porque a sessão só protege mensagens que o broker já recebeu. O guia de store and forward MQTT mostra uma fila em disco exatamente para isso.
Checklist de Projeto para Rede Celular
- Escolha LTE-M para MQTT sobre TCP/TLS e comandos interativos; considere NB-IoT para dispositivos estacionários com relatórios pouco frequentes.
- Meça o timeout de ociosidade do NAT da operadora e configure o keep alive abaixo dele.
- Mantenha o TLS, mas minimize os handshakes e use retomada de sessão quando disponível.
- Encurte os topics ou use topic aliases do MQTT 5; compacte e agrupe os payloads.
- Aplique report by exception na borda.
- Faça buffer dos dados de saída no dispositivo durante as quedas.
- Use backoff exponencial com jitter nas reconexões.
- Monitore os bytes por dispositivo por dia para que anomalias apareçam antes da fatura.
Para um exemplo prático com modem, veja SIM7600 com MQTT. Para a arquitetura no nível do gateway, leia sobre o gateway de borda IIoT e o guia de IoT industrial com MQTT.
Teste Antes de Pagar pelos Dados
Valide primeiro a estrutura de topics e o formato do payload em Wi-Fi ou Ethernet, usando o servidor MQTT público (gratuito), pensado para testes, com um prefixo único como connectmq/demo/cell-4f8a/.... Depois, passe o dispositivo para a rede celular com credenciais de produção em um broker MQTT gerenciado como a ConnectMQ, que oferece endpoints TLS e recursos do MQTT 5 sem que você precise operar servidores. Comparando opções de hospedagem? O guia de broker MQTT na nuvem mostra o que observar.
Conecte a Sua Frota Celular à ConnectMQ
A ConnectMQ suporta MQTT 3.1.1 e 5.0 sobre TLS na porta 8883, com session expiry, topic aliases e message expiry para links intermitentes. O topic $SYS/broker/connection/{clientId}/state e as visões de dispositivos do portal ajudam a ver quais dispositivos remotos estão online. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito.
Perguntas frequentes
Quantos dados o MQTT consome em rede celular?
Depende muito mais do overhead do que do payload: cabeçalhos TCP/IP e TLS, confirmações, pings de keep alive e handshakes de reconexão. Estime com um modelo como o script acima e depois confira com os contadores de bytes do seu modem.
Que keep alive devo usar em LTE-M?
Menor que o timeout de ociosidade do NAT da sua operadora, que você deve medir. Valores de alguns minutos são pontos de partida comuns; ajuste após os testes.
O NB-IoT serve para MQTT?
Pode funcionar para mensagens pequenas e pouco frequentes de dispositivos estacionários, mas a alta latência e a baixa vazão tornam lentos os handshakes TCP e TLS. O LTE-M se encaixa com mais facilidade no MQTT padrão sobre TLS.
Dispositivos celulares devem desconectar entre os relatórios?
Se os relatórios têm horas de intervalo e nenhum comando precisa chegar ao dispositivo, conectar-publicar-desconectar pode sair mais barato. Para relatórios frequentes ou controle remoto, mantenha a conexão aberta com um keep alive ajustado.



