Mqtt Will Message(遗嘱消息)

LWT 全称为 Last Will and Testament,也就是我们在连接到 Broker 时提到的遗嘱,包括遗嘱Topic、遗嘱 QoS、遗嘱消息等。

顾名思义,当 Broker 检测到 Client 非正常地断开连接的时候,就会向遗嘱Topic里面发布一条消息。遗嘱相关的设置是在建立连接的时候,在 CONNECT 数据包里面的 Variable header(可变头与) Payload(有效载荷) 中 指定的。

  • Will Flag:是1否0使用 LWT
  • Will Topic:遗嘱主题名,不可使用通配符(在 CONNECT报文中的 有效载荷 中 设置)
  • Will Qos:发布遗嘱消息时使用的 QoS 等级,如果遗嘱标志(Will Flag)被设置为0,遗嘱QoS也必须设置为0(0x00)
  • Will Retain:遗嘱消息的 Retain 标识
  • Will Message:遗嘱消息内容(在 CONNECT报文中的 有效载荷 中 设置)

Broker 在以下情况下认为 Client 是非正常断开连接的:

  • Broker 检测到底层的 I/O 异常;
  • Client 未能在 Keep Alive 的间隔内和 Broker 之间有消息交互;
  • Client 在关闭底层 TCP 连接前没有发送 DISCONNECT 数据包;
  • Broker 因为协议错误关闭和 Client 的连接,比如 Client 发送了一个格式错误的 MQTT 数据包。

如果 Client 通过发布 DISCONNECT 数据包断开连接,这个属于正常断开连接,不会触发 LWT 的机制,同时,Broker 还会丢弃掉这个 Client 在连接时指定的 LWT 参数。

使用场景

在客户端 A 进行连接时候,遗嘱消息设定为”offline“,客户端 B 订阅这个遗嘱主题。当 A 异常断开时,客户端 B 会收到这个”offline“的遗嘱消息,从而知道客户端 A 离线了。

Connect Flag 报文字段

Bit7654210
 User Name FlagPassword FlagWill RetainWill QoSWill FlagClean StartReserved
byte 8XXXXXXX

遗嘱消息在客户端正常调用 disconnect 方法之后并不会被发送。

Will Flag 作用

简而言之,就是客户端预先定义好,在自己异常断开的情况下,所留下的最后遗愿(Last Will),也称之为遗嘱(Testament)。这个遗嘱就是一个由客户端预先定义好的主题和对应消息,附加在CONNECT的可变报文头部中,在客户端连接出现异常的情况下,由服务器主动发布此消息。

当Will Flag位为1时,Will QoS和Will Retain才会被读取,此时消息体中要出现Will Topic和Will Message具体内容,否则Will QoS和Will Retain值会被忽略掉。

当Will Flag位为0时,则Will Qos和Will Retain无效。

命令行示例

下面是一个Will Message的示例:

  1. Sub端clientid=sub预定义遗嘱消息:

    mosquitto_sub --will-topic test --will-payload die --will-qos 2 -t topic -i sub -h 192.168.1.1
    
  2. 客户端 clientid=alive 在 192.168.1.1(EMQ服务器) 订阅遗嘱主题

    mosquitto_sub -t test -i alive -q 2 -h 192.168.1.1
    
  3. 异常断开Sub端与Server端(EMQ服务器)连接,Pub端收到Will Message 。

根据遗嘱的属性和触发机制,我们不难看出,遗嘱常用于获取设备的连接状态。

注意,设置好遗嘱以后还不够(因为你只要订阅者一启动就会收到遗嘱消息,如果此时发布者已经在线,会导致不准确),
所以,还需要在设备成功连接MQTT的时候主动发个消息,发送的主题必须和遗嘱的主题相同,设置好消息的 retain 属性,让其自动纠正过来。

最佳使用:

我想让我的APP或者上位机或者网页一登录的时候获取设备的状态   在线还是离线

设备端只需要这样设置

注意:MQTT本身有遗嘱设置

所以大家可以设置遗嘱 ,注意哈,发布的主题自己随意哈,假设是aaaaa  假设设置的遗嘱是   {data:state,state:offline}   注意遗嘱的retain 必须设置为1 ,即让服务器保留这个消息

如果这样设置了,那么只要 设备掉线了,服务器就会向订阅aaaaa主题的APP或者上位机或者网页发送{data:state,state:offline} 

但是只这样设置还不行,因为你会发现每次APP或者上位机或者网页只要一启动就会收到{data:state,state:offline} 

所以需要下一步

在设备成功连接MQTT的时候主动发个消息,发送的主题必须和上面一样哈aaaaa  假设消息是 {data:state,state:online}  注意消息的retain 必须设置为1 ,即让服务器保留这个消息

 

### ESP32 使用 MQTT 协议设置遗嘱消息 在使用 ESP32 实现 MQTT 客户端连接时,可以配置遗嘱消息Will Message)。这是一条客户端断开连接时发送的消息。通过这种方式,在设备意外掉线的情况下,服务器或其他订阅者能够及时收到通知。 下面是一个简单的代码示例来展示如何利用 PubSubClient 库为 ESP32 设置遗嘱消息: ```cpp #include <WiFi.h> #include <PubSubClient.h> // WiFi 和 MQTT 服务参数 const char* ssid = "your_SSID"; const char* password = "your_PASSWORD"; const char* mqtt_server = "broker_address"; WiFiClient espClient; PubSubClient client(espClient); void setup_wifi() { delay(10); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } randomSeed(micros()); Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void callback(char* topic, byte* payload, unsigned int length) { // 处理接收到的信息... } void reconnect() { // 循环直到重新连接上MQTT Broker while (!client.connected()) { Serial.print("Attempting MQTT connection..."); if (client.connect("ESP32Client", "willTopic", 0, true, "Device offline")) { // 配置遗嘱消息 Serial.println("connected"); // ... 订阅主题 ... } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } } void setup() { pinMode(LED_BUILTIN, OUTPUT); // 初始化内置LED引脚 Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); // 发布数据到指定的主题... } ``` 上述代码展示了如何创建一个带有遗嘱消息MQTT 连接[^1]。当 `client.connect` 方法被调用时,传递给它的第三个参数指定了遗嘱消息发布的主题名称,第四个参数表示 QoS 级别,第五个参数则是实际要发布的内容字符串。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值