Los dispositivos en redes poco fiables rara vez tienen ocasión de despedirse. Las baterías se agotan, el Wi-Fi se cae, los procesos fallan. El Last Will and Testament (LWT, «última voluntad») de MQTT permite a un cliente registrar por adelantado un mensaje que el broker publicará en su nombre si el cliente desaparece de forma inesperada. Es la pieza estándar para detectar presencia y generar alertas en sistemas MQTT.
Cómo funciona el Last Will
El will se declara en el paquete CONNECT. Tiene las mismas partes que una publicación normal:
| Campo | Significado |
|---|---|
| Will Topic | Dónde publicará el broker, p. ej. acme/sensor-17/status |
| Will Payload | El cuerpo del mensaje, p. ej. offline |
| Will QoS | 0, 1 o 2; consulta los niveles de QoS |
| Will Retain | Si el will se guarda como mensaje retenido |
| Will Properties (MQTT 5) | Will Delay Interval, Message Expiry, Content Type, User Properties… |
El broker guarda el will junto con la sesión y no hace nada con él mientras el cliente está conectado. Lo que ocurre después depende de cómo termine la conexión.
¿Cuándo se publica el will?
El broker publica el will cuando la conexión de red se cierra sin una desconexión normal, por ejemplo cuando:
- el broker detecta un error de E/S o un fallo de red;
- el cliente no se comunica dentro del periodo de keep-alive: el broker espera hasta 1,5 × el intervalo de keep-alive antes de dar la conexión por muerta;
- el cliente cierra la conexión TCP/WebSocket sin enviar
DISCONNECT; - el broker cierra la conexión por un error de protocolo.
El will no se publica cuando el cliente envía un DISCONNECT normal; un cierre ordenado lo elimina. MQTT 5 añade una excepción: un cliente puede desconectarse con el reason code 0x04 (Disconnect with Will Message) para cerrar limpiamente y que aun así se envíe el will.
Will Delay Interval (MQTT 5)
En MQTT 3.1.1 el will se dispara de inmediato. Eso genera ruido con dispositivos que se reconectan rápido tras un breve corte de red: los suscriptores ven offline y, un segundo después, online. MQTT 5 añade la propiedad Will Delay Interval (en segundos):
- El broker espera ese retardo antes de publicar el will.
- Si el cliente se reconecta con el mismo client ID dentro de ese plazo, el will no se envía.
- El will se publica cuando vence el retardo o cuando termina la sesión, lo que ocurra primero; por eso, un will delay mayor que el
Session Expiry Intervalqueda limitado en la práctica por este.
const client = mqtt.connect('wss://broker.emqx.io:8084/mqtt', {
protocolVersion: 5,
clientId: 'sensor-17',
properties: { sessionExpiryInterval: 300 },
will: {
topic: 'acme/sensor-17/status',
payload: 'offline',
qos: 1,
retain: true,
properties: { willDelayInterval: 30 },
},
});El patrón de presencia: estado online/offline
El uso más habitual del LWT lo combina con los mensajes retenidos (retained) para que cualquier cliente pueda saber en todo momento si un dispositivo está online:
- Conéctate con un will: topic
acme/sensor-17/status, payloadoffline, QoS 1, retain = true. - Justo después del CONNACK, publica
onlineen el mismo topic, QoS 1, retain = true. Esto sobrescribe cualquierofflineobsoleto que quedara de la vez anterior. - En un apagado ordenado, publica tú mismo
offline(retenido) y después envíaDISCONNECT. Como el will se descarta en una desconexión limpia, esta publicación explícita es lo que mantiene el estado correcto. - Si el cliente falla, el broker publica por ti el will
offlineretenido.
Después, los dashboards se suscriben a acme/+/status y, gracias a la retención, reciben al instante el estado actual de todos los dispositivos.
import mqtt from 'mqtt';
const statusTopic = 'acme/sensor-17/status';
const client = mqtt.connect('wss://broker.hivemq.com:8884/mqtt', {
clientId: 'sensor-17',
keepalive: 30,
will: { topic: statusTopic, payload: 'offline', qos: 1, retain: true },
});
client.on('connect', () => {
client.publish(statusTopic, 'online', { qos: 1, retain: true });
});
process.on('SIGINT', () => {
client.publish(statusTopic, 'offline', { qos: 1, retain: true }, () => client.end());
});Errores habituales
- Colisiones de client ID. Si un segundo cliente se conecta con el mismo client ID, el broker desconecta al primero y publica su will. Dos instancias peleándose por un mismo ID producen un estado online/offline que no para de oscilar.
- Librerías que siempre se desconectan limpiamente. Algunos SDK envían
DISCONNECTal salir el proceso, así que el will nunca se dispara. Pruébalo matando el proceso o cortando la red. - Olvidar el retain. Un will no retenido solo lo ven los clientes suscritos en ese momento.
- Autorización. El will se publica con los permisos del cliente. Si el cliente no tiene permiso para publicar en el topic del will, el broker puede rechazar la conexión o descartar el will sin avisar. Consulta errores de conexión MQTT.
Configurar un will desde la línea de comandos
Los clientes de Mosquitto aceptan directamente las opciones del will, lo que facilita experimentar. Arranca un suscriptor en un terminal, conecta un segundo cliente con un will y mátalo con Ctrl+C o cerrando el terminal:
# terminal 1 — watch the status topic
mosquitto_sub -h test.mosquitto.org -t 'testmqtt/lwt-demo/#' -v
# terminal 2 — connect with a retained will and a 10 s keep-alive
mosquitto_sub -h test.mosquitto.org -t 'testmqtt/lwt-demo/cmd' -k 10 \
--will-topic 'testmqtt/lwt-demo/status' --will-payload 'offline' \
--will-qos 1 --will-retainSegún cómo termine el proceso, el cliente puede llegar o no a enviar DISCONNECT. La forma más fiable de ver el will es cortar la red (por ejemplo, desactivando el Wi-Fi) y esperar a que venza el keep-alive: exactamente el fallo para el que está pensado el LWT.
Cómo probar el Last Will
- En una pestaña del cliente MQTT online, suscríbete a
testmqtt/lwt-demo/#. - En una segunda pestaña, conéctate con un will en
testmqtt/lwt-demo/statusy un keep-alive corto. - Cierra la segunda pestaña sin desconectarte. Dentro de la ventana de keep-alive, la primera pestaña recibe el will.
Pruébalo en el cliente MQTT online
Preguntas frecuentes
¿Por qué no se envía mi Last Will de MQTT?
El broker solo publica el will cuando un cliente se desconecta de forma no ordenada. Si tu librería cliente envía un paquete DISCONNECT al cerrarse, el will se descarta. Revisa también el keep-alive: el broker puede esperar hasta 1,5 veces el intervalo de keep-alive antes de detectar una conexión muerta.
¿Puedo cambiar el Last Will después de conectarme?
No. El will forma parte del paquete CONNECT y no se puede modificar durante la sesión. Para cambiarlo, desconéctate y vuelve a conectarte con un nuevo will.
¿El mensaje Last Will debe ser retenido?
Para topics de presencia y estado, sí. Un will offline retenido hace que los clientes que se suscriban más tarde sigan viendo el dispositivo como offline, en lugar de no ver nada o un antiguo mensaje online.