IoT industrial

MQTT sobre Rede Celular (LTE-M, NB-IoT): Dicas de Projeto para Consumo de Dados, Keep Alive e TLS

Links celulares mudam as regras do MQTT. Aprenda a estimar o consumo mensal de dados, escolher valores de keep alive que sobrevivem ao NAT da operadora, reduzir o custo do handshake TLS e escolher entre LTE-M e NB-IoT.

Estação de bombeamento remota enviando telemetria com MQTT sobre rede celular por um modem LTE-M para um broker na nuvem
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

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:

  1. Cada byte é cobrado, incluindo cabeçalhos TCP/IP, registros TLS, confirmações e pings de keep alive, não apenas o seu payload.
  2. 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.
  3. 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:

  1. Mantenha as conexões abertas quando os relatórios são frequentes, para que o handshake aconteça raramente.
  2. 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.
  3. Prefira ECDHE com ECDSA quando os dois lados suportarem; chaves e assinaturas de curvas elípticas são menores que as equivalentes RSA.
  4. 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.
  5. 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.

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

  1. Escolha LTE-M para MQTT sobre TCP/TLS e comandos interativos; considere NB-IoT para dispositivos estacionários com relatórios pouco frequentes.
  2. Meça o timeout de ociosidade do NAT da operadora e configure o keep alive abaixo dele.
  3. Mantenha o TLS, mas minimize os handshakes e use retomada de sessão quando disponível.
  4. Encurte os topics ou use topic aliases do MQTT 5; compacte e agrupe os payloads.
  5. Aplique report by exception na borda.
  6. Faça buffer dos dados de saída no dispositivo durante as quedas.
  7. Use backoff exponencial com jitter nas reconexões.
  8. 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.

Artigos relacionados

Cliente MQTT no CODESYS: Publicando Variáveis do CLP em um Broker

Configure a biblioteca IIoT MQTT Client do CODESYS para publicar variáveis do CLP em JSON, verifique-as no servidor MQTT público broker.connectmq.com e depois migre para um broker privado com credenciais e TLS.

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.