Este tutorial MQTT te lleva de cero a un sistema de publicación/suscripción funcionando en una sola sesión. Aprenderás el puñado de conceptos que hacen funcionar MQTT y después ejecutarás cada paso de verdad contra el servidor MQTT público gratuito broker.connectmq.com usando la línea de comandos, Python y un navegador. Al terminar sabrás diseñar topics, elegir un nivel de QoS, usar retained messages y Last Will, y cuándo pasar a un broker privado.
¿Qué es MQTT y por qué aprenderlo?
MQTT es un protocolo de mensajería ligero de publicación/suscripción que funciona sobre TCP. Se diseñó para redes poco fiables y dispositivos pequeños, y por eso es hoy el idioma por defecto del IoT: sensores, gateways, adaptadores de PLC, apps móviles y servicios de backend lo hablan. Las versiones actuales son MQTT 3.1.1 y MQTT 5.0, ambas estandarizadas por OASIS (el texto completo está publicado en mqtt.org).
Tres propiedades explican su popularidad:
- Sobrecarga mínima. La cabecera fija de un paquete puede ocupar solo dos bytes, así que MQTT funciona sobre enlaces móviles, satélite y redes Wi-Fi saturadas.
- Desacoplamiento. Los publicadores nunca hablan directamente con los suscriptores. No necesitan conocer sus direcciones IP y ni siquiera tienen que estar conectados al mismo tiempo.
- Push, no polling. En cuanto un cliente se suscribe, los datos llegan en el momento en que se publican. No hay un bucle de peticiones gastando batería y ancho de banda.
Si quieres ver con más detalle el flujo de paquetes antes de ponerte manos a la obra, lee cómo funciona MQTT por dentro. Si no, sigue adelante: los conceptos siguientes bastan para construir sistemas reales.
Los conceptos clave en cinco minutos
Broker
El broker es el servidor que está en medio. Cada cliente abre con él una conexión TCP de larga duración, y el broker enruta cada mensaje publicado a todos los clientes cuya suscripción coincide. Además, gestiona las sesiones, guarda los retained messages y dispara los mensajes de Last Will. Para una explicación completa de qué hace un broker MQTT, incluida su diferencia con una cola de mensajes, consulta nuestra guía específica.
Clientes
Todo lo que se conecta al broker es un cliente: un ESP32, un script de Python, un flujo de Node-RED, un dashboard en un navegador. Un cliente puede publicar, suscribirse o ambas cosas. Cada conexión lleva un client ID, que el broker usa para identificar la sesión. Dos clientes con el mismo ID se expulsan mutuamente, así que asegúrate siempre de que sea único.
Topics
Un topic es una cadena UTF-8 con niveles separados por barras, por ejemplo factory1/line2/press3/temperature. Los topics no se crean de antemano; existen en el momento en que alguien publica en ellos. Un buen diseño de topics es la decisión más importante de un proyecto MQTT, por eso lo tratamos en detalle en convenciones de nombres de topics MQTT.
Publicar y suscribirse
Un publicador envía un mensaje a un topic. Un suscriptor registra su interés en un filtro de topics. El broker los empareja. Este es el modelo de publicación/suscripción, y es lo que te permite añadir un nuevo dashboard o un nuevo proceso que escriba en la base de datos sin tocar ni un solo dispositivo.
Comodines
Los suscriptores pueden usar dos comodines:
+coincide exactamente con un nivel:factory1/+/press3/temperature#coincide con todos los niveles restantes y debe ir al final:factory1/#
Los publicadores nunca pueden usar comodines. Las reglas completas de coincidencia, incluidos los casos límite de los topics $SYS, están en nuestra guía de comodines MQTT.
Paso 1: elige un broker para este tutorial MQTT
Necesitas un broker con el que hablar. Instalar uno en local funciona, pero añade a tu primera hora la gestión del firewall, los puertos y el servicio. El camino más rápido es un servidor público de pruebas. En este tutorial usamos broker.connectmq.com, el servidor MQTT público gratuito que opera ConnectMQ, pensado para pruebas y prototipos, no para datos de producción. Acepta conexiones anónimas en todos los puertos estándar:
| Transporte | Puerto | URL | Úsalo para |
|---|---|---|---|
| MQTT sobre TCP | 1883 | mqtt://broker.connectmq.com:1883 | Herramientas CLI, pruebas rápidas |
| MQTT sobre TLS | 8883 | mqtts://broker.connectmq.com:8883 | Conexiones cifradas de dispositivos y servidores |
| WebSocket | 8083 | ws://broker.connectmq.com:8083/mqtt | Experimentos web en local |
| WebSocket seguro | 8084 | wss://broker.connectmq.com:8084/mqtt | Navegadores y páginas HTTPS |
Reglas que conviene conocer antes de empezar:
- Usa un client ID único y no vacío en cada conexión.
- Añade a todos tus topics un prefijo que nadie más vaya a usar, como
connectmq/demo/<random-id>/. Elige ahora tu ID aleatorio, por ejemploa7k2q9. - Todo lo que hay en el área pública puede leerlo cualquiera. Nunca publiques contraseñas, datos personales ni nada sensible.
- El broker público tiene límites: 64 KB por mensaje, 10 mensajes por segundo por cliente, 10 suscripciones por cliente, hasta 8 niveles de topic y sesiones que caducan como máximo a los 30 minutos. Son generosos para aprender e intencionadamente demasiado pequeños para producción.
Si quieres entender por qué existen esos cuatro puertos y cuál elegir detrás de un firewall corporativo, lee los puertos MQTT explicados.
Paso 2: tu primer publish y subscribe desde la línea de comandos
Los clientes de línea de comandos de Mosquitto son la forma más sencilla de ver MQTT en acción. Instálalos con tu gestor de paquetes:
# Debian / Ubuntu / Raspberry Pi OS
sudo apt install mosquitto-clients
# macOS (Homebrew)
brew install mosquitto
En Windows, el instalador del proyecto Mosquitto incluye mosquitto_pub.exe y mosquitto_sub.exe.
Abre un terminal y suscríbete a todo lo que cuelgue de tu prefijo. La opción -v imprime el topic junto a cada payload:
mosquitto_sub -h broker.connectmq.com -p 1883 -i sub-a7k2q9 \
-t "connectmq/demo/a7k2q9/#" -v
Abre un segundo terminal y publica:
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-a7k2q9 \
-t "connectmq/demo/a7k2q9/room1/temperature" -m "21.5"
El primer terminal imprime connectmq/demo/a7k2q9/room1/temperature 21.5 al instante. Ese es todo el ciclo de MQTT: conectar, suscribirse, publicar, recibir.
Ahora prueba el puerto cifrado. Como broker.connectmq.com usa un certificado de Let's Encrypt, el paquete de CA de tu sistema puede verificarlo:
mosquitto_pub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
-i pub-tls-a7k2q9 -t "connectmq/demo/a7k2q9/room1/humidity" -m "48"
En macOS o Windows, apunta --cafile a un archivo de paquete de CA en lugar de usar --capath.
Paso 3: QoS, retained messages y Last Will
Estas tres funciones son las que distinguen MQTT de un simple socket. Pruébalas ahora una por una.
Calidad de servicio (QoS)
Cada publicación y cada suscripción llevan un nivel de QoS:
| QoS | Garantía | Flujo de paquetes | Uso típico |
|---|---|---|---|
| 0 | Como máximo una vez | PUBLISH | Telemetría de alta frecuencia en la que perder una muestra no importa |
| 1 | Al menos una vez | PUBLISH, PUBACK | La mayoría de datos y comandos IoT; puede haber duplicados |
| 2 | Exactamente una vez | PUBLISH, PUBREC, PUBREL, PUBCOMP | Eventos de facturación, contadores, todo lo que no deba duplicarse |
La QoS efectiva para un suscriptor es la menor entre la QoS de publicación y la de suscripción. Publica con -q 1 y suscríbete con -q 1 para ver una entrega confirmada. Nuestra guía para elegir entre QoS 0, 1 y 2 repasa las ventajas e inconvenientes con escenarios de fallo reales.
Retained messages
Un retained message es un mensaje que el broker guarda como el "último valor conocido" de un topic y que entrega al instante a cualquier suscriptor nuevo. Publica uno:
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-a7k2q9 -r \
-t "connectmq/demo/a7k2q9/room1/setpoint" -m "22"
Ahora arranca un suscriptor nuevo. Recibe 22 inmediatamente, aunque no se haya publicado nada después de que se conectara. Para borrar un retained message, publica un payload vacío con el flag de retención: -r -n. Encontrarás más patrones, incluido cuándo los retained messages generan confusión, en retained messages en MQTT.
Last Will and Testament
Cuando un cliente se conecta, puede registrar un mensaje de "testamento" (will). Si el cliente desaparece sin una desconexión limpia (corte de corriente, caída de red, fallo del programa), el broker publica el will en su nombre. Combínalo con un mensaje retenido de "online" y obtendrás una detección fiable de presencia de dispositivos:
mosquitto_sub -h broker.connectmq.com -p 1883 -i dev-a7k2q9 \
-t "connectmq/demo/a7k2q9/room1/cmd" \
--will-topic "connectmq/demo/a7k2q9/room1/status" \
--will-payload "offline" --will-retain --will-qos 1 -k 10
Mata ese proceso con el botón de cerrar del terminal (no con Ctrl+C, que en algunas compilaciones aún envía una desconexión limpia) y observa cómo llega offline a tu suscriptor con comodín al cabo de aproximadamente un intervalo y medio de keep-alive.
Paso 4: el mismo tutorial MQTT en Python
La línea de comandos es estupenda para explorar; los proyectos reales usan una librería. Instala paho-mqtt 2.x:
pip install "paho-mqtt>=2.0"
Este script se conecta con MQTT 5, se suscribe a su propio topic de comandos, publica una lectura cada cinco segundos y anuncia su presencia con un estado retenido más un Last Will:
import json
import random
import time
import uuid
import paho.mqtt.client as mqtt
BROKER = "broker.connectmq.com"
PREFIX = "connectmq/demo/a7k2q9"
CLIENT_ID = f"tutorial-py-{uuid.uuid4().hex[:8]}"
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print(f"Connect failed: {reason_code}")
return
print("Connected as", CLIENT_ID)
client.publish(f"{PREFIX}/room1/status", "online", qos=1, retain=True)
client.subscribe(f"{PREFIX}/room1/cmd", qos=1)
def on_message(client, userdata, msg):
print(f"Command on {msg.topic}: {msg.payload.decode()}")
def on_disconnect(client, userdata, flags, reason_code, properties):
print(f"Disconnected: {reason_code}")
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id=CLIENT_ID,
protocol=mqtt.MQTTv5,
)
client.will_set(f"{PREFIX}/room1/status", "offline", qos=1, retain=True)
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
client.tls_set() # verifica el certificado de Let's Encrypt con las CA del sistema
client.connect(BROKER, 8883, keepalive=30)
client.loop_start()
try:
while True:
reading = {"temperature": round(random.uniform(19, 24), 2), "ts": int(time.time())}
client.publish(f"{PREFIX}/room1/telemetry", json.dumps(reading), qos=1)
time.sleep(5)
except KeyboardInterrupt:
client.publish(f"{PREFIX}/room1/status", "offline", qos=1, retain=True).wait_for_publish()
client.disconnect()
client.loop_stop()
Deja abierto tu terminal con mosquitto_sub y verás llegar la telemetría. Envía un comando de vuelta con mosquitto_pub -t "connectmq/demo/a7k2q9/room1/cmd" -m "reboot" y el script lo imprimirá. Fíjate en los detalles de paho 2.x: CallbackAPIVersion.VERSION2 es obligatorio y los callbacks reciben los argumentos reason_code y properties. Mezclar ejemplos antiguos de la versión 1.x es la causa de errores más habitual en este punto.
Paso 5: MQTT en el navegador con WebSocket
Los navegadores no pueden abrir sockets TCP en bruto, así que hablan MQTT sobre WebSocket. Guarda esto como index.html y ábrelo en cualquier navegador moderno:
// Carga primero MQTT.js desde un CDN en tu HTML:
// <script src="https://unpkg.com/mqtt@5.10.1/dist/mqtt.min.js"></script>
const clientId = "tutorial-web-" + Math.random().toString(16).slice(2, 10);
const prefix = "connectmq/demo/a7k2q9";
const client = mqtt.connect("wss://broker.connectmq.com:8084/mqtt", {
clientId,
protocolVersion: 5,
clean: true,
reconnectPeriod: 2000,
});
client.on("connect", () => {
console.log("Connected", clientId);
client.subscribe(`${prefix}/#`, { qos: 1 });
client.publish(`${prefix}/room1/cmd`, "hello from the browser", { qos: 1 });
});
client.on("message", (topic, payload) => {
console.log(topic, payload.toString());
});
client.on("error", (err) => console.error("MQTT error", err.message));
Abre la consola de desarrollador y verás la telemetría de Python, el setpoint y el estado retenidos y tu propio comando devuelto. El puerto 8084 con la ruta /mqtt es el que debes usar desde páginas HTTPS, porque los navegadores bloquean las conexiones WebSocket inseguras desde orígenes seguros. Nuestra guía de MQTT sobre WebSocket cubre proxies, frameworks y autenticación en el navegador.
Diseñar topics y payloads que escalen
Una vez que los mensajes fluyen, el diseño decide si el sistema seguirá siendo mantenible. Algunas reglas que funcionan en la práctica:
- Ve de lo general a lo específico.
site/area/line/device/measurementte permite suscribirte a toda una línea con un solo comodín. - No empieces con una barra.
/factory/line1crea un primer nivel vacío que complica todos los filtros. - Mantén estables los identificadores. Usa IDs de dispositivo, no nombres legibles que acabarán cambiando.
- Separa los datos de los comandos.
.../telemetry,.../statusy.../cmddeben ser topics distintos para que los permisos y la QoS puedan diferir. - Elige un único formato de payload. JSON es legible y fácil de depurar; los formatos binarios como Protobuf ahorran ancho de banda en enlaces limitados. Elijas lo que elijas, incluye una marca de tiempo y las unidades.
- Evita un topic por lectura. Publicar diez valores en diez topics cada segundo multiplica la sobrecarga de paquetes; un pequeño objeto JSON suele ser mejor.
En los sistemas industriales, una jerarquía alineada con ISA-95 (empresa, planta, área, línea, celda) se ha convertido en una convención habitual, y es la base del patrón Unified Namespace que explicamos en Sparkplug B y el Unified Namespace.
Errores típicos de principiante y cómo corregirlos
| Síntoma | Causa probable | Solución |
|---|---|---|
| Dos clientes se desconectan el uno al otro continuamente | Se usa dos veces el mismo client ID | Genera un ID único por proceso; consulta las reglas del client ID en MQTT |
| El suscriptor no recibe nada | Errata en el topic o diferencia de mayúsculas | Los topics distinguen mayúsculas y minúsculas; suscríbete a prefix/# para ver qué llega realmente |
| Los mensajes llegan dos veces | Reenvío de QoS 1 tras una reconexión | Haz que los consumidores sean idempotentes o usa QoS 2 donde los duplicados importen |
| Conexión rechazada en el puerto 8883 | TLS no configurado en el cliente | Activa TLS (tls_set(), mqtts://) o usa el puerto 1883 para pruebas sin cifrar |
| El navegador no puede conectarse | Uso de ws:// desde una página HTTPS o falta la ruta /mqtt |
Usa wss://broker.connectmq.com:8084/mqtt |
| Sigue apareciendo un valor retenido antiguo | El retained message sigue almacenado | Publica un payload retenido vacío para borrarlo |
| Errores de firma en los callbacks de Python | Código de ejemplo 1.x con paho 2.x | Pasa CallbackAPIVersion.VERSION2 y usa las firmas v2 |
Del tutorial a producción
Un servidor público es ideal para aprender y nada más. Antes de que entren en servicio dispositivos reales necesitas credenciales privadas, TLS en todas partes, aislamiento respecto a otros usuarios y límites dimensionados para tu flota. Puedes operar tu propio broker, pero entonces te encargas tú de los parches, los certificados, la monitorización y la planificación de capacidad. Un broker MQTT gestionado traslada ese trabajo al proveedor.
Con ConnectMQ, el cambio es casi solo una cuestión de configuración. Regístrate, elige un plan, crea un broker y el portal te dará un nombre de usuario, una contraseña y un client ID generados. El mismo código de este tutorial funciona en cuanto añades las credenciales:
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()
client.connect("broker.connectmq.com", 8883, keepalive=30)
El portal incluye además un cliente MQTT en el navegador y un explorador de topics en tiempo real, así que puedes repetir cada paso de este tutorial en tu broker privado sin instalar nada. Para comparar opciones de despliegue, desde un nivel serverless compartido hasta un clúster dedicado o tu propia cuenta en la nube, lee nuestra guía para elegir un broker MQTT en la nube. Después repasa las buenas prácticas de seguridad en MQTT antes de conectar el primer dispositivo en campo.
Tu ruta de aprendizaje después de este tutorial
| Siguiente tema | Por qué importa |
|---|---|
| Funciones de MQTT 5 | Caducidad de mensajes, suscripciones compartidas, reason codes y user properties |
| Tutorial ESP32 MQTT | Lleva MQTT a hardware real |
| Sesiones persistentes en MQTT | Recibe los mensajes que llegan mientras un cliente está desconectado |
| Intervalo keep alive en MQTT | Ajusta la rapidez con la que el broker detecta una conexión caída |
| MQTT vs HTTP | Saber cuándo MQTT es la herramienta adecuada y cuándo no |
Empieza con ConnectMQ
Acabas de usar todas las funciones básicas de MQTT en un broker público. Cuando estés listo para topics privados y dispositivos reales, crea un broker gratuito en app.connectmq.com. El plan Serverless gratuito no requiere tarjeta de crédito, admite MQTT 3.1.1 y 5.0 sobre TCP, TLS y WebSocket, y te da hasta 25 conexiones para construir tu primer proyecto. Tus credenciales de ConnectMQ encajan directamente en el código anterior.
Preguntas frecuentes
¿Es difícil aprender MQTT?
No. El modelo básico se reduce a clientes, un broker, topics y publicación/suscripción, y puedes enviar tu primer mensaje en menos de cinco minutos con la CLI. La profundidad llega después, con las sesiones, las ventajas e inconvenientes de cada QoS y el diseño de topics.
¿Necesito instalar un broker para seguir este tutorial MQTT?
No. Todos los pasos se ejecutan contra broker.connectmq.com, que acepta conexiones anónimas. Solo necesitas las herramientas cliente de Mosquitto, Python o un navegador.
¿Debo aprender MQTT 3.1.1 o MQTT 5?
Aprende los conceptos una sola vez; son los mismos en ambas versiones. Usa MQTT 5 en los proyectos nuevos porque añade reason codes, caducidad de mensajes, suscripciones compartidas y user properties, y sigue siendo compatible con brokers que admiten las dos versiones.
¿Es seguro el broker público para datos reales?
No. Cualquiera puede leer lo que hay en el área pública, así que úsalo solo para pruebas y demos. Los datos reales deben ir a un broker privado con credenciales y TLS.
¿Qué debería construir después de este tutorial?
Conecta un sensor real con un ESP32 o una Raspberry Pi, guarda las lecturas en una base de datos con un pequeño script suscriptor y crea un dashboard sobre WebSocket. Cada uno de esos pasos reutiliza exactamente lo que has aprendido aquí.



