Un bot de Telegram es una de las formas más rápidas de tener un mando a distancia y un canal de alertas para dispositivos MQTT: obtienes una interfaz de chat gratuita y multiplataforma, notificaciones push y ninguna app que desarrollar. El bot se ejecuta como un pequeño servicio que hace dos cosas: publica comandos como ON en devices/lamp/set cuando escribes /on lamp, y se suscribe a topics de alertas y de estado para reenviarlos a tu chat.
Este tutorial construye ese puente en Python con python-telegram-bot y aiomqtt, lo restringe a tu propio chat ID y prueba cada camino con mosquitto_pub y mosquitto_sub antes de tocar hardware.
Arquitectura
You (Telegram app) ──/on lamp──▶ Telegram API ──▶ bot.py ──PUBLISH testmqtt/tgbot/lamp/set "ON"──▶ broker ──▶ device
device ──PUBLISH testmqtt/tgbot/lamp/state "ON" (retained)──▶ broker ──▶ bot.py (cache for /status)
device ──PUBLISH testmqtt/tgbot/greenhouse/alert "..."──▶ broker ──▶ bot.py ──▶ Telegram chatEl dispositivo nunca habla con Telegram. Solo habla MQTT, así que un ESP32 o una Raspberry Pi no necesitan token del bot ni cliente HTTPS, y más adelante puedes añadir un dashboard o Home Assistant como segundo controlador sobre los mismos topics. La estructura de topics sigue la separación habitual entre comando y estado descrita en comando y control con MQTT:
| Topic | Dirección | Payload | Retenido |
|---|---|---|---|
testmqtt/tgbot/<device>/set | bot → dispositivo | ON / OFF | no |
testmqtt/tgbot/<device>/state | dispositivo → bot | ON / OFF | sí |
testmqtt/tgbot/<device>/alert | dispositivo → bot | texto libre | no |
Crea el bot
- En Telegram, abre un chat con @BotFather, envía
/newboty elige un nombre y un username que termine enbot. - Copia el token que devuelve BotFather. Es un secreto: quien lo tenga puede suplantar a tu bot.
- Opcionalmente envía
/setcommandsa BotFather conon - switch a device on,off - switch a device off,status - show device states, para que los comandos aparezcan en el menú del chat.
Instala las dos librerías (Python 3.10+):
pip install "python-telegram-bot>=21" "aiomqtt>=2"Ambas son librerías asyncio, por eso encajan: el bucle de polling del bot y la conexión MQTT se ejecutan en el mismo event loop, y un handler de comando puede hacer await client.publish(...) directamente. Consulta MQTT asíncrono en Python con aiomqtt para saber más del cliente.
El bot
@@BOTCODE@@
Algunas decisiones de diseño que conviene destacar:
- Una sola conexión MQTT para todo el bot. El worker es dueño de la conexión y la guarda en
bot_data; los handlers la reutilizan en lugar de conectarse por cada comando. Si el broker se cae, el bucle se reconecta a los cinco segundos y mientras tanto los handlers responden "Broker not connected". - Los estados vienen de mensajes retenidos. Como los dispositivos publican
statecon el flag retain, el bot conoce el último estado de cada dispositivo justo después de suscribirse, incluso tras un reinicio. Consulta mensajes retenidos. - Los chats desconocidos reciben silencio. Solo
/whoamiresponde a todo el mundo, para que puedas averiguar tu chat ID. Todo comando que publica comprueba primero la allowlist. - Las alertas tienen debounce. De lo contrario, un sensor inestable alcanzaría los límites de Telegram y ahogaría las alertas reales.
Ejecuta y prueba sin hardware
Arranca el bot solo con TELEGRAM_TOKEN, envía /whoami en el chat y apunta el número. Reinícialo con la allowlist:
export TELEGRAM_TOKEN="123456:ABC..." # de BotFather
export ALLOWED_CHAT_IDS="111111111" # tu chat ID de /whoami
export MQTT_USER="username" MQTT_PASS="password" # si tu broker exige login
python bot.pyAhora haz tú de dispositivo. En una terminal, observa lo que publica el bot:
mosquitto_sub -h broker.connectmq.com -p 1883 -t 'testmqtt/tgbot/+/set' -vEnvía /on lamp en Telegram. La terminal 1 muestra testmqtt/tgbot/lamp/set ON. Informa del nuevo estado como lo haría un dispositivo y después lanza una alerta:
mosquitto_pub -h broker.connectmq.com -p 1883 -q 1 -r \
-t testmqtt/tgbot/lamp/state -m ON
mosquitto_pub -h broker.connectmq.com -p 1883 -q 1 \
-t testmqtt/tgbot/pump/alert -m 'Water level low (12 %)'/status debería mostrar ahora lamp: ON, y el chat recibe ⚠️ pump: Water level low (12 %). Publica la alerta otra vez en menos de 60 segundos y confirma que se suprime. También puedes hacer todo esto desde el cliente MQTT online en lugar de la terminal. Por último, borra el estado retenido para que no se quede ahí: mosquitto_pub -h broker.connectmq.com -t testmqtt/tgbot/lamp/state -r -n.
Observa los topics del bot en tu navegador
El lado del dispositivo
En hardware real, el dispositivo se suscribe a su topic set, conmuta la salida y publica el estado resultante con retain. En MicroPython con umqtt.simple el núcleo son unas pocas líneas:
@@DEVCODE@@
Publicar el estado después de actuar es lo que hace fiable a /status: el bot informa de lo que hizo el dispositivo, no de lo que pediste. Añade un Last Will sobre el estado o un topic availability para que el bot te avise cuando un dispositivo se desconecte.
Asegúralo
Cualquiera en Telegram puede llegar a un bot, así que trátalo como una API pública:
- Allowlist de chats, como se muestra. En grupos el chat ID es negativo; añádelo a la lista como cualquier otro.
- Mantén el token fuera del código: variables de entorno o un gestor de secretos, nunca un repositorio Git.
- Usa TLS hacia el broker. El ejemplo conecta en el puerto 8883; el 1883 en claro solo vale para experimentos locales.
- Restringe el usuario del bot en el broker. Necesita escritura en
.../sety lectura en.../statey.../alert, nada más. Verifica las reglas con una prueba de permisos ACL.
Alternativas sin código
Si prefieres una herramienta visual, el mismo puente funciona en n8n (MQTT Trigger → nodo Telegram, y Telegram Trigger → nodo MQTT; consulta automatizaciones MQTT con n8n) o en Node-RED con un nodo de Telegram de la comunidad. La versión en Python gana cuando quieres un único servicio pequeño con allowlist explícita, debounce y tests en tu propio repositorio.
| Opción | Ideal para | Contrapartida |
|---|---|---|
| Bot en Python (esta guía) | Control total, testeable, consumo mínimo | Mantienes tú el código |
| Workflow de n8n | Puesta en marcha rápida, muchas otras integraciones | Una ejecución por mensaje |
| Flujo de Node-RED | Ya tienes Node-RED en casa | La lógica vive en un editor de flujos |
Un bot de Telegram convierte MQTT en algo que controlas desde el bolsillo: los comandos salen como publish, el estado vuelve como mensajes retenidos y las alertas llegan como notificaciones push. Haz que el dispositivo solo hable MQTT, limita el bot a tu chat, aplica debounce a las alertas y prueba todo el ciclo con mosquitto antes de cablear un relé.
Preguntas frecuentes
¿El dispositivo debe hablar con Telegram directamente o a través de MQTT?
A través de MQTT. Así los dispositivos solo necesitan una conexión ligera con el broker, el token del bot se queda en un servidor y no en cada dispositivo, y puedes añadir otros controladores (dashboards, Home Assistant, n8n) sin tocar el firmware.
¿Cómo evito que desconocidos controlen mis dispositivos a través del bot?
Los bots de Telegram son públicos: cualquiera que encuentre el username puede enviar comandos. Comprueba update.effective_chat.id contra una allowlist antes de publicar nada y da al usuario del bot en el broker una ACL que solo permita los topics de comandos necesarios.
¿Por qué el bot deja de enviar alertas cuando muchos sensores se disparan?
Telegram limita la velocidad a la que un bot puede enviar mensajes, aproximadamente uno por segundo por chat y menos en grupos. Aplica debounce a las alertas por dispositivo, agrupa ráfagas en un solo mensaje y nunca reenvíes telemetría de alta frecuencia al chat.


