Publicado

mrubiodev.blog / artículo

MQTT desde cero: protocolo, broker y cliente Python (Paho)

FECHA2018/04/20
CATEGORIAPROYECTOS
TAGS#mqtt #iot #python #paho #mosquitto #broker #automacion #domotica
TIEMPO_LECTURA5 MIN

MQTT desde cero: protocolo, broker y cliente Python (Paho)

Nota de actualización — 2026: Este artículo fusiona tres posts originales (2018–2020): Conociendo el protocolo MQTT, Primeros pasos en MQTT – Broker MQTT Online y MQTT 3. Python Librería PAHO. Se ha sustituido el broker online recomendado (CloudMQTT cerró el servicio en 2022) y se ha corregido la numeración de la serie original, que era inconsistente entre título y URL.


1. Qué es MQTT

MQTT (Message Queue Telemetry Transport) es un protocolo de comunicación machine-to-machine (M2M) diseñado para el Internet of Things. Está orientado a la comunicación entre sensores y actuadores con feedback, consume muy poco ancho de banda y tiene requisitos de hardware mínimos — por eso funciona bien en dispositivos con pocos recursos (microcontroladores, sensores de bajo consumo, etc.).

Arquitectura: topología de estrella centralizada. Un nodo central actúa como servidor o broker, con capacidad para miles de clientes simultáneos. El broker gestiona toda la red y transmite los mensajes; para mantener el canal activo, los clientes envían periódicamente un paquete PINGREQ y esperan PINGRESP del broker.

Modelo publicación/suscripción (pub/sub): funciona como un foro temático. Los clientes publican mensajes bajo un topic, y otros clientes se suscriben a esos topics para recibir la información.

Ejemplo:

  • Un dispositivo publica humedad en casa/salon/humedad.
  • Otro publica temperatura en casa/salon/temperatura.
  • Un tercer dispositivo suscrito a casa/salon/# recibe ambos.
  • El comodín # sustituye cualquier nivel restante del topic: suscribirse a casa/# recibe todo lo publicado en la casa.

Niveles de QoS (Quality of Service):

QoS Nombre Garantía
0 At most once El mensaje se envía sin confirmación de recepción. Puede perderse.
1 At least once El cliente reenvía hasta que el broker confirma. Puede duplicarse.
2 Exactly once Confirmación en dos fases entre emisor y broker. Más lento, sin duplicados ni pérdidas.

Especificación completa del protocolo: mqtt.org


2. Levantar un broker para pruebas

El broker es el corazón del sistema: gestiona el tráfico y las publicaciones. Hay dos caminos razonables para empezar sin montar infraestructura propia desde el primer día.

Opción A — Broker público de pruebas (cero configuración)

Para pruebas rápidas sin registro, existen brokers públicos como broker.hivemq.com o test.mosquitto.org. Nunca uses un broker público para nada con datos reales o sensibles — cualquiera puede leer y publicar en topics no protegidos.

Opción B — Broker propio en tu homelab (recomendado si vas en serio)

Dado que ya tienes Proxmox y Docker corriendo en zion, el camino con más sentido en 2026 no es un servicio SaaS gratuito (el CloudMQTT del post original ya no existe), sino levantar Eclipse Mosquitto en un contenedor:

# docker-compose.yml
services:
  mosquitto:
    image: eclipse-mosquitto:2
    container_name: mosquitto
    ports:
      - "1883:1883"   # MQTT estándar
      - "9001:9001"   # WebSockets (opcional)
    volumes:
      - ./config:/mosquitto/config
      - ./data:/mosquitto/data
      - ./log:/mosquitto/log
    restart: unless-stopped

Con un mosquitto.conf mínimo que exige autenticación:

listener 1883
allow_anonymous false
password_file /mosquitto/config/passwd

Usuarios se crean con:

docker exec -it mosquitto mosquitto_passwd -c /mosquitto/config/passwd <usuario>

Esto te da control total sobre ACLs por topic, persistencia y logs — justo lo que el post original dejaba como “para más adelante” con CloudMQTT, y que aquí resuelves desde el primer paso al ser tu propia infraestructura.

Si prefieres no montar nada aún: HiveMQ Cloud ofrece un plan gratuito con gestión por interfaz web, como alternativa más directa a lo que ofrecía CloudMQTT.


3. Cliente Python con la librería Paho

Paho-MQTT es la librería cliente MQTT de referencia en Python (también disponible para C++, Android, etc.). Es pura en Python, compatible con Python 3.x.

Instalación:

pip install paho-mqtt

Conectar

import paho.mqtt.client as paho

client = paho.Client(client_id="", clean_session=True, userdata=None)
client.connect(host="localhost", port=1883, keepalive=60)
  • client_id: identifica al cliente ante el broker; si se omite, se genera uno aleatorio.
  • clean_session: normalmente True.
  • userdata: cualquier valor propio que se pasará a todos los callbacks.

Con autenticación (recomendado siempre que el broker no sea de pruebas):

client.username_pw_set("usuario", "password")
client.connect("broker", 1883)

Con Last Will and Testament (mensaje que el broker publica automáticamente si el cliente se desconecta de forma anómala — muy útil para detectar sensores/dispositivos caídos):

client.will_set(topic, payload=None, qos=0, retain=False)
client.connect("broker")

Mantener la conexión activa

Método Comportamiento
client.loop_forever() Bloquea el flujo del programa; reconecta automáticamente. Ideal si el programa solo escucha.
client.loop_start() Lanza un hilo en segundo plano; no bloquea. Ideal si el programa hace otras tareas. Se detiene con client.loop_stop().
client.loop() Procesamiento manual, un solo ciclo. Solo para casos muy concretos — hay que gestionar la reconexión a mano.

Publicar

import paho.mqtt.client as paho
import time

def on_publish(client, userdata, result):
    print("Mensaje publicado")

client = paho.Client()
client.on_publish = on_publish
client.connect("broker", 1883)
client.loop_start()

while True:
    temperatura = leer_sensor()  # sustituir por la lectura real
    client.publish("salon/temperatura", str(temperatura))
    (rc, mid) = client.publish("cocina/temperatura", str(temperatura), qos=1)
    time.sleep(30)

publish() devuelve (código_retorno, id_mensaje). Para publicaciones puntuales sin mantener el cliente vivo:

import paho.mqtt.publish as publish

publish.single("salon/temperatura", payload="hot", hostname="localhost", port=1883)

Y para varios mensajes de una vez:

msgs = [
    {'topic': "salon/temperatura", 'payload': "22.5"},
    {'topic': "cocina/temperatura", 'payload': "24.0", 'qos': 1},
]
publish.multiple(msgs, hostname="localhost", port=1883)

Suscribirse

import paho.mqtt.client as paho

def on_subscribe(client, userdata, mid, granted_qos):
    print(f"Suscrito: {mid} {granted_qos}")

def on_message(client, userdata, msg):
    print(f"{msg.topic} {msg.qos} {msg.payload}")

client = paho.Client()
client.on_subscribe = on_subscribe
client.on_message = on_message
client.connect("broker", 1883)
client.subscribe("salon/#", qos=1)
client.loop_forever()

Recomendación práctica: coloca las llamadas a subscribe() dentro del callback on_connect, no justo después de connect(). Así la suscripción se renueva automáticamente en cada reconexión, algo que con un cliente no persistente se pierde si no se hace así.

Para callbacks específicos por sub-topic:

client.subscribe("cocina/#")
client.message_callback_add("cocina/temperatura/valor", on_message_temperatura)

Desconectar

client.disconnect()

Con callback asociado:

def on_disconnect(client, userdata, rc):
    print(f"Desconectado, código: {rc}")

client.on_disconnect = on_disconnect

TLS / seguridad en tránsito

Para cualquier despliegue fuera de tu red local, usa TLS:

client.tls_set(ca_certs="/ruta/a/ca.crt")
client.connect("broker", 8883)  # puerto TLS estándar

Recursos


Posts originales fusionados en esta guía: “Conociendo el protocolo MQTT” (abr. 2018), “Primeros pasos en MQTT – Broker MQTT Online” (may. 2018), “MQTT 3. Python Librería PAHO” (abr. 2020).