MQTT sobre red celular es la forma en que la mayoría de los activos remotos (estaciones de bombeo, depósitos, plantas solares, vehículos, monitores ambientales) llegan a la nube, pero las reglas de diseño son distintas de las de Wi-Fi o Ethernet. Los bytes se facturan, los enlaces se caen más a menudo y las redes de los operadores cierran en silencio las conexiones inactivas. Esta guía te muestra cómo estimar un presupuesto de datos, elegir valores de keep alive, reducir la sobrecarga de TLS y decidir entre LTE-M y NB-IoT para que tus dispositivos sigan conectados sin facturas sorpresa.
Por qué la red celular cambia el diseño de MQTT
MQTT se diseñó originalmente para enlaces poco fiables y de bajo ancho de banda, así que ya encaja bien: una cabecera fija de 2 bytes, conexiones TCP persistentes y un modelo publicación-suscripción que evita el sondeo. Pero tres realidades de la red celular determinan los detalles:
- Se factura cada byte, incluidas las cabeceras TCP/IP, los registros TLS, las confirmaciones y los pings de keep alive, no solo tu payload.
- El NAT de nivel de operador (CGNAT) se sitúa entre la mayoría de los dispositivos e internet y elimina las asignaciones TCP inactivas tras un timeout que depende de cada operador. Si MQTT permanece en silencio más tiempo que eso, la conexión muere sin que ninguno de los dos extremos lo note de inmediato.
- El estado de la radio cuesta energía. Cada transmisión despierta el módem, que permanece un rato en un estado de alto consumo. Muchos envíos pequeños agotan las baterías más rápido que unos pocos agrupados.
LTE-M vs NB-IoT para MQTT
| LTE-M (Cat-M1) | NB-IoT (Cat-NB1/NB2) | |
|---|---|---|
| Rendimiento | Mayor, holgado para MQTT sobre TLS | Muy bajo; los handshakes grandes tardan mucho |
| Latencia | Comparable a LTE normal, lo bastante baja para comandos interactivos | Alta y variable, a veces de segundos |
| Movilidad | Admite traspaso entre celdas | Diseñado para dispositivos fijos |
| Idoneidad para TCP/TLS | Buena | Posible, pero a menudo se combina con protocolos basados en UDP |
| Ahorro de energía | Admite PSM y eDRX | Admite PSM y eDRX, consumo en reposo muy bajo |
| Cobertura | Buena, mejorada respecto a LTE normal | Excelente en interiores profundos y ubicaciones subterráneas |
Para MQTT sobre TCP y TLS, LTE-M suele ser la opción pragmática: los handshakes TLS se completan de forma fiable y los comandos llegan rápido al dispositivo. NB-IoT destaca en dispositivos fijos que envían informes pequeños y poco frecuentes desde lugares de difícil acceso; ahí, muchos equipos usan MQTT-SN u otro protocolo basado en UDP, o aceptan un establecimiento de conexión lento con MQTT sobre TCP. Comprueba qué tecnologías admite tu operador en la región de despliegue antes de elegir el hardware; algunos módems admiten ambas y cambian de una a otra automáticamente.
Estimar el presupuesto de datos de MQTT sobre red celular
El tamaño del payload suele ser la parte más pequeña de la factura. Ten en cuenta:
- Las cabeceras TCP/IP de cada paquete (unos 40 bytes en IPv4 sin opciones, más con opciones o con IPv6), además de las confirmaciones TCP.
- La sobrecarga de los registros TLS por mensaje, unas pocas decenas de bytes para la cabecera, el nonce y la etiqueta de autenticación.
- La sobrecarga de MQTT: cabecera fija, nombre del topic (a menudo la parte más grande de un mensaje pequeño) y un PUBACK con QoS 1.
- Los pings de keep alive: un PINGREQ y un PINGRESP ocupan solo 2 bytes cada uno, pero con TLS, cabeceras TCP/IP y ACK, cada ida y vuelta cuesta mucho más en la red.
- El establecimiento de la conexión: un handshake TLS completo, con la cadena de certificados del servidor, suele ocupar varios kilobytes. Las reconexiones frecuentes pueden dominar el presupuesto.
El script siguiente da una estimación aproximada. Las cifras por paquete son suposiciones deliberadamente conservadoras; sustitúyelas por valores medidos en tu módem (la mayoría de los módems informan de los bytes enviados y recibidos).
# Estimación aproximada de datos mensuales para un dispositivo celular con MQTT sobre TLS.
# Las cifras de sobrecarga son suposiciones: mide tu propio enlace y ajústalas.
PAYLOAD_BYTES = 60 # p. ej. JSON compacto
TOPIC_BYTES = 40 # longitud de la cadena del topic
MSGS_PER_HOUR = 12 # una lectura cada 5 minutos
QOS = 1 # QoS 1 añade un PUBACK
KEEPALIVE_S = 240 # los pings solo cuentan cuando el enlace está inactivo
RECONNECTS_PER_DAY = 2 # cada una paga un handshake TLS completo
TLS_HANDSHAKE_BYTES = 6000 # suposición: domina la cadena de certificados
TCP_IP_PER_PACKET = 52 # IPv4 + TCP con la opción de timestamps
TLS_PER_RECORD = 29 # sobrecarga de registro TLS 1.2 AES-GCM
TCP_ACK = 52 # paquete 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 + nuestro 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 necesarios entre mensajes
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")
Al ejecutarlo verás el mismo patrón que encontrarás sobre el terreno: el total en la red es varias veces el payload en bruto, y la longitud del topic, las confirmaciones y las reconexiones importan tanto como los propios datos. Por eso las optimizaciones siguientes se centran en la sobrecarga.
Keep alive frente a los timeouts NAT del operador
El intervalo de keep alive de MQTT indica al broker cuánto tiempo puede permanecer en silencio el cliente. Si no se envía nada más, el cliente envía un PINGREQ antes de que venza el intervalo. En la red celular, el keep alive tiene una segunda función: mantener viva la asignación NAT del operador.
- Si el keep alive es más largo que el timeout de inactividad del NAT, la asignación se elimina en silencio. El dispositivo sigue creyendo que está conectado; la siguiente publicación desaparece y la conexión solo se detecta como muerta tras un timeout TCP. Mientras tanto, los comandos desde la nube nunca llegan.
- Si el keep alive es mucho más corto de lo necesario, pagas pings que no necesitas y mantienes la radio despierta.
Los timeouts NAT varían entre operadores y pueden ser de solo unos minutos. Mide el tuyo: conéctate con un keep alive largo, espera cada vez más tiempo entre publicaciones y anota cuándo dejan de llegar los mensajes desde la nube. Después fija el keep alive holgadamente por debajo de ese valor. Si el dispositivo solo envía datos y no necesita recibir comandos, una alternativa es conectar, publicar y desconectar, aceptando el coste del handshake cada vez, lo que puede salir más barato cuando los informes están separados por horas.
Reducir el coste de TLS sin renunciar a TLS
Nunca envíes MQTT en texto plano por una red celular pública. En su lugar, abarata TLS:
- Mantén las conexiones abiertas cuando los informes sean frecuentes, para que el handshake ocurra rara vez.
- Usa la reanudación de sesión TLS si tu módem o tu librería TLS admiten session IDs o session tickets. Un handshake reanudado se salta el intercambio de certificados y ahorra bytes y tiempo.
- Prefiere ECDHE con ECDSA cuando ambos lados lo admitan; las claves y firmas de curva elíptica son más pequeñas que sus equivalentes RSA.
- Confía solo en la raíz que necesitas (por ejemplo ISRG Root X1 para certificados de Let's Encrypt) para que el dispositivo almacene y valide una cadena mínima.
- Evita las tormentas de reconexión. Usa backoff exponencial con jitter para que una caída de la celda no desencadene cientos de handshakes seguidos.
Reduce cada mensaje
- Topics cortos. Un topic como
t/pump7/pes mucho más barato en cada publicación que una larga jerarquía descriptiva. Con MQTT 5, los topic aliases permiten al cliente enviar el topic completo una vez y después referirse a él con un entero pequeño, conservando topics legibles sin el coste por mensaje. - Payloads compactos. Claves JSON cortas, enteros con escalado implícito o un formato binario como Protobuf (el que usa Sparkplug B).
- Agrupa las lecturas. Envía diez lecturas en un mensaje cada diez minutos en lugar de una por minuto; las cabeceras se pagan una sola vez.
- Report by exception. Envía solo los cambios significativos más un heartbeat; consulta report by exception.
- Elección de QoS. QoS 1 añade un PUBACK por mensaje. Úsalo donde importe la entrega, y QoS 0 para valores de alta frecuencia en los que la siguiente lectura sustituye a la anterior.
Ajustes de sesión de MQTT 5 para enlaces intermitentes
Una sesión persistente permite al broker conservar las suscripciones y encolar mensajes QoS 1 para el dispositivo mientras está brevemente desconectado, de modo que los comandos enviados durante un corte no se pierden. Con 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() # almacén de CA del sistema
client.reconnect_delay_set(min_delay=2, max_delay=300)
props = Properties(PacketTypes.CONNECT)
props.SessionExpiryInterval = 3600 # conserva la sesión 1 h tras una caída
client.connect("YOUR_BROKER_HOST", 8883, keepalive=240,
clean_start=False, properties=props)
client.loop_forever()
Combínalo con un búfer local para los datos salientes, porque una sesión solo protege los mensajes que el broker ha recibido. La guía de store and forward MQTT muestra una cola respaldada en disco precisamente para eso.
Checklist de diseño para red celular
- Elige LTE-M para MQTT sobre TCP/TLS y comandos interactivos; considera NB-IoT para dispositivos fijos que informan con poca frecuencia.
- Mide el timeout de inactividad del NAT del operador y fija el keep alive por debajo.
- Mantén TLS, pero minimiza los handshakes y usa la reanudación de sesión cuando esté disponible.
- Acorta los topics o usa topic aliases de MQTT 5; compacta y agrupa los payloads.
- Aplica report by exception en el edge.
- Guarda en un búfer del dispositivo los datos salientes durante las caídas.
- Usa backoff exponencial con jitter para las reconexiones.
- Vigila los bytes por dispositivo y día para que las anomalías aparezcan antes que la factura.
Para un ejemplo práctico con módem, consulta SIM7600 MQTT. Para la arquitectura a nivel de gateway, lee sobre el gateway edge IIoT y la guía de IoT industrial con MQTT.
Prueba antes de pagar por los datos
Valida primero la estructura de topics y el formato del payload por Wi-Fi o Ethernet, usando el servidor MQTT público gratuito con un prefijo único como connectmq/demo/cell-4f8a/.... Después pasa el dispositivo a la red celular con credenciales de producción en un broker MQTT gestionado como ConnectMQ, que ofrece endpoints TLS y funciones de MQTT 5 sin que tengas que operar servidores. ¿Comparando opciones de alojamiento? La guía del broker MQTT en la nube explica qué buscar.
Conecta tu flota celular a ConnectMQ
ConnectMQ admite MQTT 3.1.1 y 5.0 sobre TLS en el puerto 8883, con expiración de sesión, topic aliases y expiración de mensajes para enlaces intermitentes. Su topic $SYS/broker/connection/{clientId}/state y las vistas de dispositivos del portal te ayudan a ver qué dispositivos remotos están conectados. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito.
Preguntas frecuentes
¿Cuántos datos consume MQTT sobre red celular?
Depende mucho más de la sobrecarga que del payload: cabeceras TCP/IP y TLS, confirmaciones, pings de keep alive y handshakes de reconexión. Haz una estimación con un modelo como el script anterior y verifícala después con los contadores de bytes de tu módem.
¿Qué keep alive debo usar en LTE-M?
Uno más corto que el timeout de inactividad del NAT de tu operador, que deberías medir. Unos pocos minutos es un punto de partida habitual; ajústalo después de probar.
¿Es NB-IoT adecuado para MQTT?
Puede funcionar para mensajes pequeños y poco frecuentes de dispositivos fijos, pero la alta latencia y el bajo rendimiento hacen que los handshakes TCP y TLS sean lentos. LTE-M encaja más fácilmente con MQTT estándar sobre TLS.
¿Deben los dispositivos celulares desconectarse entre informes?
Si los informes están separados por horas y no hace falta que lleguen comandos al dispositivo, conectar-publicar-desconectar puede salir más barato. Para informes frecuentes o control remoto, mantén la conexión abierta con un keep alive ajustado.



