Dispositivos em redes instáveis raramente têm a chance de se despedir. Baterias acabam, o Wi-Fi cai, processos travam. O Last Will and Testament (LWT) do MQTT permite que um cliente registre antecipadamente uma mensagem que o broker publica em seu nome caso o cliente desapareça de forma inesperada. É o bloco de construção padrão para detecção de presença e alertas em sistemas MQTT.
Como o Last Will funciona
O will é declarado no pacote CONNECT. Ele tem as mesmas partes de uma publicação normal:
| Campo | Significado |
|---|---|
| Will Topic | Onde o broker vai publicar, por exemplo acme/sensor-17/status |
| Will Payload | O corpo da mensagem, por exemplo offline |
| Will QoS | 0, 1 ou 2 — veja níveis de QoS |
| Will Retain | Se o will é armazenado como mensagem retida |
| Will Properties (MQTT 5) | Will Delay Interval, Message Expiry, Content Type, User Properties… |
O broker guarda o will junto com a sessão e não faz nada com ele enquanto o cliente está conectado. O que acontece depois depende de como a conexão termina.
Quando o will é publicado?
O broker publica o will quando a conexão de rede é encerrada sem uma desconexão normal, inclusive quando:
- o broker detecta um erro de I/O ou uma falha de rede;
- o cliente não se comunica dentro do período de keep-alive — o broker espera até 1,5 × o intervalo de keep-alive antes de considerar a conexão morta;
- o cliente fecha a conexão TCP/WebSocket sem enviar
DISCONNECT; - o broker fecha a conexão por causa de um erro de protocolo.
O will não é publicado quando o cliente envia um DISCONNECT normal; um encerramento limpo o apaga. O MQTT 5 adiciona uma exceção: um cliente pode se desconectar com o reason code 0x04 (Disconnect with Will Message) para encerrar de forma limpa e ainda assim ter o will enviado.
Will Delay Interval (MQTT 5)
No MQTT 3.1.1, o will dispara imediatamente. Isso gera ruído para dispositivos que se reconectam rápido após uma breve oscilação de rede: os assinantes veem offline e, um segundo depois, online. O MQTT 5 adiciona a propriedade Will Delay Interval (em segundos):
- O broker espera o atraso antes de publicar o will.
- Se o cliente se reconectar com o mesmo client ID dentro desse atraso, o will não é enviado.
- O will é publicado quando o atraso expira ou quando a sessão termina, o que acontecer primeiro — então um will delay maior que o
Session Expiry Intervalfica, na prática, limitado por ele.
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 },
},
});O padrão de presença: status online/offline
O uso mais comum do LWT é combiná-lo com mensagens retidas (retained) para que qualquer cliente saiba, a qualquer momento, se um dispositivo está online:
- Conecte com um will: tópico
acme/sensor-17/status, payloadoffline, QoS 1, retain = true. - Logo após o CONNACK, publique
onlineno mesmo tópico, QoS 1, retain = true. Isso sobrescreve qualquerofflineantigo que tenha ficado da última vez. - No encerramento normal, publique você mesmo
offline(retido) e depois envieDISCONNECT. Como o will é descartado em uma desconexão limpa, é essa publicação explícita que mantém o status correto. - Em caso de falha, o broker publica o will
offlineretido por você.
Os dashboards então assinam acme/+/status e recebem imediatamente o status atual de cada dispositivo, graças à retenção.
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());
});Armadilhas comuns
- Colisões de client ID. Se um segundo cliente se conecta com o mesmo client ID, o broker desconecta o primeiro — e publica o will dele. Duas instâncias disputando um mesmo ID produzem um status que fica alternando entre online e offline.
- Bibliotecas que sempre se desconectam de forma limpa. Alguns SDKs enviam
DISCONNECTao encerrar o processo, e o will nunca dispara. Teste matando o processo ou cortando a rede. - Esquecer o retain. Um will não retido só é visto pelos clientes inscritos naquele momento.
- Autorização. O will é publicado com as permissões do cliente. Se o cliente não tiver permissão para publicar no tópico do will, o broker pode rejeitar a conexão ou descartar o will silenciosamente. Veja erros de conexão MQTT.
Definindo um will pela linha de comando
Os clientes do Mosquitto aceitam opções de will diretamente, o que facilita experimentos rápidos. Inicie um assinante em um terminal, depois conecte um segundo cliente com um will e mate-o com Ctrl+C ou fechando o 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-retainDependendo de como o processo termina, o cliente pode ou não conseguir enviar o DISCONNECT. A forma mais confiável de ver o will é cortar a rede (por exemplo, desativando o Wi-Fi) e esperar o keep-alive expirar — exatamente o tipo de falha para o qual o LWT foi criado.
Como testar o Last Will
- Em uma aba do cliente MQTT online, assine
testmqtt/lwt-demo/#. - Em uma segunda aba, conecte com um will em
testmqtt/lwt-demo/statuse um keep-alive curto. - Feche a segunda aba sem desconectar. Dentro da janela de keep-alive, a primeira aba recebe o will.
Perguntas frequentes
Por que o meu Last Will do MQTT não está sendo enviado?
O broker só publica o will quando um cliente se desconecta de forma abrupta. Se a sua biblioteca cliente envia um pacote DISCONNECT ao fechar, o will é descartado. Verifique também o keep-alive: o broker pode esperar até 1,5 vez o intervalo de keep-alive antes de perceber uma conexão morta.
Posso alterar o Last Will depois de conectar?
Não. O will faz parte do pacote CONNECT e não pode ser modificado durante a sessão. Para alterá-lo, desconecte e conecte de novo com um novo will.
A mensagem de Last Will deve ser retida?
Para tópicos de presença e status, sim. Um will offline retido faz com que clientes que assinam depois ainda vejam o dispositivo como offline, em vez de não verem nada ou verem uma mensagem online antiga.