Skip to content

MQTT en lo que necesitas ​

Todo el invernadero habla MQTT: los sensores publican sus lecturas, la bomba y el ventilador reciben órdenes y tu Node-RED escucha y manda. Esta página resume del protocolo solo lo que usarás en el módulo, con ejemplos del invernadero y dónde está cada cosa en Node-RED. Las sesiones lo aplican; vuelve aquí cuando necesites el porqué.

Publicación y suscripción ​

En MQTT nadie envía un mensaje a otro. Cada programa es un cliente que se conecta a un servidor central, el broker, y hace una de dos cosas:

  • Publicar un mensaje en un topic (un nombre, como invernadero/suelo/humedad).
  • Suscribirse a uno o varios topics para recibir lo que otros publiquen en ellos.

El broker entrega una copia de cada mensaje a todos los clientes suscritos a su topic. Quien publica no sabe quién lo recibe, ni cuántos son, ni si hay alguien escuchando.

El sensor de suelo publica 42.5 en invernadero/suelo/humedad y el broker lo entrega a Node-RED, suscrito a invernadero/+/+, y a mosquitto_sub, suscrito a invernadero/#. En sentido contrario, Node-RED publica on en el topic de comando del Shelly y el broker se lo entrega al Shelly, suscrito a ese topic

Un mismo cliente puede publicar y suscribirse a la vez: tu Node-RED recibe las lecturas y publica los comandos de la bomba. Por eso es tan fácil añadir piezas: el panel, la base de datos o un mosquitto_sub para depurar son solo suscriptores más, y los sensores no se enteran.

En el curso, el broker es Mosquitto: el contenedor mosquitto de tu entorno, donde publica el simulador. En Node-RED, la conexión con el broker es el nodo de configuración Broker invernadero; mqtt in se suscribe y mqtt out publica.

Topics y comodines ​

Un topic es una cadena con niveles separados por /. En el invernadero siguen el patrón invernadero/<nodo>/<magnitud>:

text
invernadero/dht22/temperatura
invernadero/suelo/humedad
invernadero/shelly/shellyplug-s-SIM001/relay/0

Reglas que conviene recordar:

  • Distingue mayúsculas y minúsculas: invernadero/Suelo/humedad es otro topic, y no recibirás nada.
  • No hay que crearlos: un topic existe en cuanto alguien publica en él.
  • Sin / al principio ni al final: /invernadero/suelo tiene un primer nivel vacío y no es el mismo topic.

Al suscribirte (nunca al publicar) puedes usar dos comodines:

ComodínSignificadoEjemploRecibeNo recibe
+Exactamente un nivel cualquierainvernadero/+/temperaturainvernadero/dht11/temperatura, invernadero/dht22/temperaturainvernadero/suelo/humedad
#Cualquier número de niveles, incluido ninguno. Solo al finalinvernadero/shelly/#todo lo que cuelga de invernadero/shellyinvernadero/suelo/humedad

invernadero/+/+ recibe todas las magnitudes de los nodos (tres niveles exactos) pero no los topics de los Shelly, que tienen más. # solo lo recibe todo: útil para explorar, demasiado para un flujo.

En Node-RED, cuando un mensaje llega por un mqtt in con comodines, msg.topic trae el topic concreto en el que se publicó. Así sabes de qué sensor viene.

El payload ​

El contenido del mensaje, el payload, son bytes: el broker no los interpreta. Qué significan lo decide quien publica. En el invernadero:

  • Las lecturas son números en texto: "42.5". En el mqtt in, Output a String lo entrega como texto y tú lo conviertes a número.
  • Los comandos y estados de los Shelly son palabras: on, off.

El curso pide a String y convierte de forma explícita para que la conversión quede a la vista y puedas tratar los valores que no son números.

QoS: la garantía de entrega ​

Cada mensaje viaja con un nivel de QoS (Quality of Service) que fija qué hacen emisor y receptor para asegurar que llega:

Intercambio de paquetes en cada nivel: QoS 0 envía PUBLISH sin respuesta; QoS 1 envía PUBLISH y espera PUBACK, repitiendo si no llega; QoS 2 intercambia PUBLISH, PUBREC, PUBREL y PUBCOMP

QoSGarantíaCosteEn el invernadero
0Como mucho una vez: puede perderseUn paqueteLecturas periódicas: si se pierde una, llega otra en 5 s
1Al menos una vez: puede llegar repetidoDos paquetes y reenvíosEstados y comandos
2Exactamente una vezCuatro paquetesNo se usa

Dos detalles importantes:

  • El QoS se aplica en cada tramo, no de extremo a extremo: emisor → broker y broker → suscriptor son entregas distintas. El suscriptor recibe con el menor de los dos QoS: el del mensaje publicado y el de su suscripción. Si publicas con QoS 1 y te suscribes con QoS 0, recibes con QoS 0.
  • QoS 1 puede entregar el mismo mensaje dos veces. Para un comando como on da igual: encender algo que ya está encendido no cambia nada. Por eso los comandos idempotentes (que repetidos dan el mismo resultado) son buena práctica.

El QoS asegura la entrega al siguiente tramo, no que la orden se haya cumplido. La única prueba de que la bomba se ha encendido es el estado que publica el propio Shelly (sesión 3).

En Node-RED: campo QoS del mqtt in (el de la suscripción) y del mqtt out (el de publicación), o msg.qos si en el mqtt out lo dejas vacío.

Retain: el último valor conocido ​

Normalmente, el broker no guarda nada: si nadie está suscrito cuando llega un mensaje, se pierde. Un mensaje publicado con el indicador retain es distinto: el broker guarda el último de cada topic y se lo entrega a todo cliente que se suscriba después, nada más suscribirse.

  • Sirve para que quien se conecta sepa al instante el estado actual: la última lectura de cada sensor o si la bomba está encendida, sin esperar a la siguiente publicación.
  • Es el último valor conocido, no el actual: puede ser de hace una hora, o de un sensor que ya no funciona. En Node-RED, msg.retain vale true en los mensajes retenidos que entrega el broker al suscribirte.
  • Por eso, al desplegar, tus flujos reciben de golpe un mensaje por topic retenido, antes de que ningún sensor publique. Si un nodo depende de algo que se carga al arrancar, puede que aún no esté listo (la condición de carrera de la sesión 1).
  • Para borrar un mensaje retenido, se publica en su topic un payload vacío con retain.

Un comando nunca se publica con retain. El broker se lo volvería a entregar al Shelly cada vez que este se reconectara: una bomba que se enciende sola tras un corte de red.

Tipo de mensajeQoSRetain
Lectura periódica0Sí
Estado (relay/0, online)1Sí
Comando (…/command)1Nunca

En Node-RED: casilla Retain del mqtt out, o msg.retain si la dejas vacía.

La conexión: Client ID, keep alive y sesión ​

Al conectarse, cada cliente se identifica ante el broker. Estos datos de la conexión afectan al curso:

  • Client ID. Identifica al cliente y debe ser único: si dos clientes se conectan con el mismo, el broker desconecta al primero, este reconecta y desconecta al segundo, y así en bucle. En Node-RED, déjalo vacío y se generará uno aleatorio.
  • Usuario y contraseña. El broker del curso exige usuario (alumno) y, con una lista de control de acceso (ACL), decide en qué topics puede publicar y suscribirse cada uno.
  • Keep alive. Si el cliente no envía nada en ese tiempo, manda un pequeño ping. Si el broker no oye al cliente en vez y media ese tiempo, da la conexión por perdida. Es lo que permite detectar que un cliente se ha caído sin despedirse.
  • Sesión limpia (clean session). Con ella, al desconectarte el broker olvida tus suscripciones. Sin ella, las recuerda y te guarda los mensajes QoS 1 y 2 que lleguen mientras no estés (necesita un Client ID fijo). En el curso se usa sesión limpia.

En Node-RED, todo esto está en el nodo Broker invernadero: pestaña Connection (Client ID, Keep Alive, Use clean session) y pestaña Security (usuario y contraseña).

Saber quién está conectado: will y birth ​

Un cliente puede dejar al broker, al conectarse, un testamento (Last Will and Testament, LWT o will): un mensaje con su topic y payload que el broker publicará en su nombre si la conexión se corta sin despedirse (corte de red, proceso que muere, keep alive agotado). Si el cliente se desconecta de forma ordenada, el will no se publica.

Combinado con un mensaje de nacimiento (birth) que el propio cliente publica al conectarse, y ambos con retain, cualquiera puede saber si un dispositivo está conectado leyendo un solo topic:

MomentoQuién publicaPayload
Al conectarseEl cliente (birth)online
Al desconectarse ordenadamenteEl cliente (close, propio de Node-RED)offline
Al perder la conexiónEl broker (will)offline

Así funcionan los topics invernadero/shelly/<id>/online de los Shelly. En la sesión 3 configurarás lo mismo para tu Node-RED, en la pestaña Messages del nodo Broker invernadero.

Probar desde la terminal ​

El contenedor del broker trae los clientes de línea de comandos de Mosquitto, que vienen bien para ver qué está pasando sin tocar tus flujos. Ejecútalos desde una terminal en tu carpeta docker:

bash
docker compose exec mosquitto mosquitto_sub -u alumno -P alumno -v -t "invernadero/#"
bash
docker compose exec mosquitto mosquitto_pub -u alumno -P alumno -t invernadero/shelly/shellyplug-s-SIM002/relay/0/command -m on
OpciónSignificado
-u, -PUsuario y contraseña (la de MQTT_ALUMNO_PASS en tu .env)
-tTopic. En mosquitto_sub admite comodines; entre comillas para que la terminal no interprete #
-v(mosquitto_sub) Escribe el topic delante de cada mensaje
-m(mosquitto_pub) El payload
-qQoS (0 por defecto)
-r(mosquitto_pub) Publica con retain
-hHost del broker. Sin él, el del propio contenedor

mosquitto_sub se queda esperando mensajes hasta que pulses Ctrl+C: ábrelo en una terminal aparte. Si prefieres una interfaz gráfica, MQTT Explorer muestra el árbol de topics con sus valores; conéctalo a localhost, puerto 1883, usuario alumno.

Para saber más ​