视频链接:http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-tuttorial/mqtt-tutorial/esp8266-last-will/
资料链接:http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-tuttorial/mqtt-tutorial/esp8266-last-will/

示例1:MQTT 遗嘱基本应用

本示例程序将实现 ESP8266 的最基本 MQTT 遗嘱应用。程序使用 connect 函数对遗嘱消息实现设置。

/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : last_will_no_retain
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 20201223
程序目的/Purpose          :
本程序旨在演示如何设置客户端遗嘱机制。客户端在连接服务器时,设置遗嘱的主题和信息。MQTT服务器会定时检查客户端是否仍然与服务器连接。为了实现这一检查,服务器将会根据以下
内容进行检查.
1. 客户端连接时会提供心跳时间间隔(Keep Alive)。
2. 如果在心跳时间间隔时长内,客户端向服务器发布了消息,则服务器会认为客户端与服务器保持连接无误。
3. 如果在心跳时间间隔时长内,客户端没有向服务端发布消息,客户端会向服务端发送pingreq信息。此信息由PubSubClient库自动发送。
4. 我们可以通过setKeepAlive函数控制心跳时间间隔时长,或者可以通过PubSubClient.h的#define MQTT_KEEPALIVE 15来设置心跳时间间隔时长。
4. 在心跳时间间隔的1.5倍时长内,如果服务端没有收到客户端信息也没有pingreq。那么服务端将会执行客户端遗嘱机制。默认情况下,设备的心跳时间间隔时长为15秒。这是在PubSubClient.h中通过以下语句定义的:
#define MQTT_KEEPALIVE 15若要修改keep-alive时间,可修改以上头文件,或者使用setKeepAlive函数实现。对于PubSubClient,遗嘱QoS允许使用0,1。
-----------------------------------------------------------------------
本示例程序为太极创客团队制作的《零基础入门学用物联网》中示例程序。
该教程为对物联网开发感兴趣的朋友所设计和制作。如需了解更多该教程的信息,请参考以下网页:
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/
***********************************************************************/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>// 设置wifi接入信息(请根据您的WiFi信息进行修改)
const char* ssid = "FAST_153C80";
const char* password = "123456798";
const char* mqttServer = "test.ranye-iot.net";
// 如以上MQTT服务器无法正常连接,请前往以下页面寻找解决方案
// http://www.taichi-maker.com/public-mqtt-broker/WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);// 遗嘱设置
const char* willMsg = "CLIENT-OFFLINE"; // 遗嘱消息内容
const int willQoS = 0;                   // 遗嘱QoS
const bool willRetain = false;           // 遗嘱保留void setup() {Serial.begin(9600);               // 启动串口通讯//设置ESP8266工作模式为无线终端模式WiFi.mode(WIFI_STA);// 连接WiFiconnectWifi();// 设置MQTT服务器和端口号mqttClient.setServer(mqttServer, 1883);mqttClient.setKeepAlive(10); // 设置心跳间隔时间// 连接MQTT服务器connectMQTTserver();
}void loop() {// 如果开发板未能成功连接服务器,则尝试连接服务器if (!mqttClient.connected()) {connectMQTTserver();}// 处理信息以及心跳mqttClient.loop();
}// 连接MQTT服务器并订阅信息
void connectMQTTserver(){// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)String clientId = "esp8266-" + WiFi.macAddress();// 建立遗嘱主题。主题名称以Taichi-Maker-为前缀,后面添加设备的MAC地址,最后// 以“-Will”结尾,这是为确保不同ESP8266客户端的遗嘱主题名称各不相同。String willString = "Taichi-Maker-" + WiFi.macAddress() + "-Will";char willTopic[willString.length() + 1];  strcpy(willTopic, willString.c_str());// 连接MQTT服务器,在连接过程中提供以下参数:// 客户端ID,遗嘱主题,遗嘱QoS,遗嘱保留,遗嘱信息if (mqttClient.connect(clientId.c_str(), willTopic, willQoS, willRetain, willMsg)){ Serial.println("MQTT Server Connected.");Serial.print("Server Address: ");Serial.println(mqttServer);Serial.print("ClientId: ");Serial.println(clientId);Serial.print("Will Topic: ");Serial.println(willTopic);    } else {Serial.print("MQTT Server Connect Failed. Client State:");Serial.println(mqttClient.state());delay(5000);}
}// ESP8266连接wifi
void connectWifi(){WiFi.begin(ssid, password);//等待WiFi连接,成功连接后输出成功信息while (WiFi.status() != WL_CONNECTED) {delay(1000);Serial.print(".");}Serial.println("");Serial.println("WiFi Connected!");  Serial.println("");
}

下面,来看下程序代码中的重要内容。

1、首先是遗嘱设置,

// 遗嘱设置
const char* willMsg = "CLIENT-OFFLINE";  // 遗嘱消息内容
const int willQoS = 0;                   // 遗嘱QoS
const bool willRetain = false;           // 遗嘱信息保留标志

2、设置心跳间隔时间,单位为 秒

mqttClient.setKeepAlive(10); // 设置心跳间隔时间

3、连接MQTT服务器 connectMQTTserver();看下该函数的具体内容。

// 连接MQTT服务器并订阅信息
void connectMQTTserver(){// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)String clientId = "esp8266-" + WiFi.macAddress();// 建立遗嘱主题。主题名称以Taichi-Maker-为前缀,后面添加设备的MAC地址,最后// 以“-Will”结尾,这是为确保不同ESP8266客户端的遗嘱主题名称各不相同。String willString = "Taichi-Maker-" + WiFi.macAddress() + "-Will";char willTopic[willString.length() + 1];  strcpy(willTopic, willString.c_str());// 连接MQTT服务器,在连接过程中提供以下参数:// 客户端ID,遗嘱主题,遗嘱QoS,遗嘱保留,遗嘱信息if (mqttClient.connect(clientId.c_str(), willTopic, willQoS, willRetain, willMsg)){ Serial.println("MQTT Server Connected.");Serial.print("Server Address: ");Serial.println(mqttServer);Serial.print("ClientId: ");Serial.println(clientId);Serial.print("Will Topic: ");Serial.println(willTopic);    } else {Serial.print("MQTT Server Connect Failed. Client State:");Serial.println(mqttClient.state());delay(5000);}
}

下面再来看下程序的运行结果,打开串口监视器。

接下来,打开 MQTT.fx 这个软件来订阅下该主题。

接下来,断开 ESP8266 开发板的电源,造成意外断开 MQTT 服务器连接的现象。

过了大概有几秒中的时间后, 接收到遗嘱信息。

示例2:利用 MQTT 遗嘱实现设备在线状态发布

本示例将实现 2-6 MQTT 遗嘱这节课中的 “MQTT遗嘱使用建议” 示例。通过以下程序,ESP8266客户端可以利用遗嘱机制来实时的将当前在线与否状态通过服务端进行发布。也就是说,其它客户端只要订阅ESP8266客户端的遗嘱主题就可以马上了解该客户端是否在线。

/**********************************************************************
项目名称/Project          : 零基础入门学用物联网
程序名称/Program name     : last_will_retain
团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
作者/Author              : CYNO朔
日期/Date(YYYYMMDD)     : 20201223
程序目的/Purpose          :
本程序旨在演示如何设置客户端遗嘱机制。客户端在连接服务器时,设置遗嘱的主题和信息。
本客户端所发布的遗嘱消息为保留消息。其它客户端可通过订阅本客户端的遗嘱主题获取本
客户端是否在线的状态信息。
-----------------------------------------------------------------------
本示例程序为太极创客团队制作的《零基础入门学用物联网》中示例程序。
该教程为对物联网开发感兴趣的朋友所设计和制作。如需了解更多该教程的信息,请参考以下网页:
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/
***********************************************************************/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>// 设置wifi接入信息(请根据您的WiFi信息进行修改)
const char* ssid = "FAST_153C80";
const char* password = "123456798";
const char* mqttServer = "test.ranye-iot.net";
// 如以上MQTT服务器无法正常连接,请前往以下页面寻找解决方案
// http://www.taichi-maker.com/public-mqtt-broker/WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);// 遗嘱设置
const char* willMsg = "CLIENT-OFFLINE"; // 遗嘱消息内容
const int willQoS = 0;                   // 遗嘱QoS
const bool willRetain = true;           // 遗嘱保留void setup() {Serial.begin(9600);               // 启动串口通讯//设置ESP8266工作模式为无线终端模式WiFi.mode(WIFI_STA);// 连接WiFiconnectWifi();// 设置MQTT服务器和端口号mqttClient.setServer(mqttServer, 1883);mqttClient.setKeepAlive(10); // 设置心跳间隔时间// 连接MQTT服务器connectMQTTserver();
}void loop() {// 如果开发板未能成功连接服务器,则尝试连接服务器if (!mqttClient.connected()) {connectMQTTserver();}// 处理信息以及心跳mqttClient.loop();
}// 连接MQTT服务器并订阅信息
void connectMQTTserver(){// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)String clientId = "esp8266-" + WiFi.macAddress();// 建立遗嘱主题。主题名称以Taichi-Maker-为前缀,后面添加设备的MAC地址,最后// 以“-Will”结尾,这是为确保不同ESP8266客户端的遗嘱主题名称各不相同。String willString = "Taichi-Maker-" + WiFi.macAddress() + "-Will";char willTopic[willString.length() + 1];  strcpy(willTopic, willString.c_str());// 连接MQTT服务器,在连接过程中提供以下参数:// 客户端ID,遗嘱主题,遗嘱QoS,遗嘱保留,遗嘱信息if (mqttClient.connect(clientId.c_str(), willTopic, willQoS, willRetain, willMsg)){ Serial.println("MQTT Server Connected.");Serial.print("Server Address: ");Serial.println(mqttServer);Serial.print("ClientId: ");Serial.println(clientId);Serial.print("Will Topic: ");Serial.println(willTopic);    publishOnlineStatus();     //发布在线状态} else {Serial.print("MQTT Server Connect Failed. Client State:");Serial.println(mqttClient.state());delay(5000);}
}// 发布信息
void publishOnlineStatus(){// 建立遗嘱主题。主题名称以Taichi-Maker-为前缀,后面添加设备的MAC地址,最后// 以“-Will”结尾,这是为确保不同ESP8266客户端的遗嘱主题名称各不相同。String willString = "Taichi-Maker-" + WiFi.macAddress() + "-Will";char willTopic[willString.length() + 1];  strcpy(willTopic, willString.c_str());// 建立设备在线的消息。此信息将以保留形式向遗嘱主题发布String onlineMessageString = "CLIENT-ONLINE"; char onlineMsg[onlineMessageString.length() + 1];   strcpy(onlineMsg, onlineMessageString.c_str());// 向遗嘱主题发布设备在线消息if(mqttClient.publish(willTopic, onlineMsg, true)){Serial.print("Published Online Message: ");Serial.println(onlineMsg);    } else {Serial.println("Online Message Publish Failed."); }
}// ESP8266连接wifi
void connectWifi(){WiFi.begin(ssid, password);//等待WiFi连接,成功连接后输出成功信息while (WiFi.status() != WL_CONNECTED) {delay(1000);Serial.print(".");}Serial.println("");Serial.println("WiFi Connected!");  Serial.println("");
}

首先,来看下程序的运行效果,通过串口监视器输出结果如下,

之后,打开 MQTT.fx 软件,

刚一订阅该主题,就接收到信息。

下面,尝试让客户端意外断线(ESP8266 开发板断电),过个几秒钟之后,收到断线的消息。

接着,再将开发板通上电,当开发板重新连接到 MQTT 服务器后,订阅该主题的客户端就立刻收到了消息。

从而,我们就可以通过订阅遗嘱主题达到实时监控发布(客户)端在线状态情况。

我们下面再来看看程序,看看其究竟是如何实现的?

1、遗嘱设置 —— 保留标志位设置为 true

// 遗嘱设置
const char* willMsg = "CLIENT-OFFLINE"; // 遗嘱消息内容
const int willQoS = 0;                  // 遗嘱QoS
const bool willRetain = true;           // 遗嘱保留

2、设置心跳间隔时间,没有必要发送过于频繁,过于频繁会耗费网络资源,这里为了演示能够尽快的出来效果,所以设置的时间比较小。

 mqttClient.setKeepAlive(10);

3、连接 MQTT 服务器的函数 connectMQTTserver

// 连接MQTT服务器并订阅信息
void connectMQTTserver(){// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)String clientId = "esp8266-" + WiFi.macAddress();// 建立遗嘱主题。主题名称以Taichi-Maker-为前缀,后面添加设备的MAC地址,最后// 以“-Will”结尾,这是为确保不同ESP8266客户端的遗嘱主题名称各不相同。String willString = "Taichi-Maker-" + WiFi.macAddress() + "-Will";char willTopic[willString.length() + 1];  strcpy(willTopic, willString.c_str());// 连接MQTT服务器,在连接过程中提供以下参数:// 客户端ID,遗嘱主题,遗嘱QoS,遗嘱保留,遗嘱信息if (mqttClient.connect(clientId.c_str(), willTopic, willQoS, willRetain, willMsg)){ Serial.println("MQTT Server Connected.");Serial.print("Server Address: ");Serial.println(mqttServer);Serial.print("ClientId: ");Serial.println(clientId);Serial.print("Will Topic: ");Serial.println(willTopic);    publishOnlineStatus();     //发布在线状态} else {Serial.print("MQTT Server Connect Failed. Client State:");Serial.println(mqttClient.state());delay(5000);}
}

当 ESP8266 开发板连接 MQTT 服务器成功之后,就会通过串口打印输出 “客户端ID,遗嘱主题,遗嘱QoS,遗嘱保留,遗嘱信息” 等一系列信息,然后通过 publishOnlineStatus() 函数发布在线状态。

publishOnlineStatus函数的内容如下,

// 发布信息
void publishOnlineStatus(){// 建立遗嘱主题。主题名称以Taichi-Maker-为前缀,后面添加设备的MAC地址,最后// 以“-Will”结尾,这是为确保不同ESP8266客户端的遗嘱主题名称各不相同。String willString = "Taichi-Maker-" + WiFi.macAddress() + "-Will";char willTopic[willString.length() + 1];  strcpy(willTopic, willString.c_str());// 建立设备在线的消息。此信息将以保留形式向遗嘱主题发布String onlineMessageString = "CLIENT-ONLINE"; char onlineMsg[onlineMessageString.length() + 1];   strcpy(onlineMsg, onlineMessageString.c_str());// 向遗嘱主题发布设备在线消息if(mqttClient.publish(willTopic, onlineMsg, true)){Serial.print("Published Online Message: ");Serial.println(onlineMsg);    } else {Serial.println("Online Message Publish Failed."); }
}

重点是将遗嘱信息以保留的形式发布,只有这样,客户端(ESP8266 开发板)一连接到 MQTT 服务器就能将设备在线消息给发送出去。

注意:遗嘱消息和 MQTT 消息都被设置为了保留消息。遗嘱消息和 MQTT 消息的主题是同一个

遗嘱消息被设置为保留消息的目的是,当 ESP8266 开发板(客户端)不在线时,当有客户端订阅该遗嘱主题时,可以立刻接收到遗嘱信息,并且当 ESP8266 开发板(客户端)意外离线时,也会向订阅该主题的客户端发送不在线的信息。

MQTT 消息被设置为保留消息的目的是,当有客户端刚订阅该主题时就能够立即收到 MQTT 消息。

学习太极创客 — MQTT 第二章(七)ESP8266 MQTT 遗嘱应用相关推荐

  1. 学习太极创客 — MQTT(八)ESP8266订阅MQTT主题

    视频链接:https://www.bilibili.com/video/BV1Wz4y1k7Fs/?spm_id_from=333.788.recommend_more_video.-1&vd ...

  2. 学习太极创客 — MQTT(四)服务端连接操作

    视频链接:https://www.bilibili.com/video/BV1T54y1k7MQ/?spm_id_from=trigger_reload&vd_source=b91967c49 ...

  3. 学习太极创客 — ESP8226 (十二)ESP8266 多任务处理

    视频链接:https://www.bilibili.com/video/BV1L7411c7jw?p=22&spm_id_from=333.851.header_right.history_l ...

  4. 学习太极创客 — ESP8226 (七)JSON 数据通讯 一

    视频链接:https://www.bilibili.com/video/BV1L7411c7jw?p=16&vd_source=b91967c499b23106586d7aa35af46413 ...

  5. 学习太极创客 — ESP8226 (十)HTTP API 应用

    视频链接:https://www.bilibili.com/video/BV1L7411c7jw?p=19&vd_source=b91967c499b23106586d7aa35af46413 ...

  6. 学习太极创客 — ESP8226 (九)JSON 数据通讯 三

    视频链接:https://www.bilibili.com/video/BV1L7411c7jw?p=18&vd_source=b91967c499b23106586d7aa35af46413 ...

  7. python从入门到实践学习笔记_Python编程从入门到实践:学习笔记1(第二章)

    开通博客我用的理由是:读书学习时记笔记,一方面为了回顾,一方面为了督促自己.fighting! 学习Python,我买了Python编程从入门到实践. 我将从第二章开始记录我认为我以后会忘记以及重要的 ...

  8. 组队学习-动手学数据分析-第二章第2、3节

    复习:在前面我们已经学习了Pandas基础,第二章我们开始进入数据分析的业务部分,在第二章第一节的内容中,我们学习了数据的清洗,这一部分十分重要,只有数据变得相对干净,我们之后对数据的分析才可以更有力 ...

  9. C Primer Plus 学习打卡之第二章(含课后编程答案)

    知识概要 本章主要介绍了C程序的主要构成,学习了printf()函数,教了我们怎么编写一个简单的程序.本章所要求的简程序需要头文件,main()函数,自定义函数,以及声明变量.注释.printf()函 ...

最新文章

  1. 研发管理101军规#003 实战规模化敏捷:从8人到百人的敏捷之路
  2. 微信公众平台:反正公众号的一切操作都从这里入手!
  3. Optimize Slow VBA Code
  4. wxWidgets:wxRichMessageDialog类用法
  5. vb.net获取服务器中所有数据库名称显示在list,vb listview显示数据库内容,该怎么解决...
  6. step1.day12 Linux下使用C语言编程基础总结
  7. linux db2创建存储过程语法,EF基础一-db2存储过程中循环语句while do...-oracle 创建DBLINK_169IT.COM...
  8. 电脑微信不用手机确认_不用安装第三方软件,手机投屏到电脑就这么简单
  9. Android studio之导入project出现SDK location not found. Define location with sdk.dir in the local.proper
  10. JVM 调优系列之图解垃圾回收
  11. 大文件分片上传前端框架_无插件实现大文件分片上传,断点续传
  12. 【网络安全工程师面试合集】—DNS 域名系统 到底是怎么回事?
  13. C# Window Form解决播放amr格式音乐问题
  14. nacos实现配置中心,对比config
  15. Microsoft Visio-Microsoft Visio下载
  16. Openv-python学习1--图片加载
  17. i9x系列是服务器CPU吗,Intel推出全新酷睿X系列CPU:i9处理器亮相
  18. 构造常数函数解决抽象函数导数小题
  19. 概率论 —— 泊松分布和指数分布
  20. jena mysql_使用Jena将本体存入MySQL

热门文章

  1. python爬虫4.1模拟登录古诗词网并通过Cookie处理获取个人信息
  2. n代表二进制数字的长度,m代表二进制数字中1的个数,返回所有符合条件的数
  3. HDU - 4966 GGS-DDU (最小树形图)
  4. LeetCode149. 直线上最多的点数: 给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。
  5. 《学Unity的猫》——第十二章:使用Unity制作背包,皮皮的梦想背包
  6. 阿里云服务器的优势,为何选择阿里云服务器?
  7. edward_mj退役经验帖(浙大final队员-陈伟杰)
  8. 蓝桥杯算法训练 无聊的逗(状态压缩搜索)
  9. [极客大挑战 2019]HardSQL
  10. 电力电子simulink练习01:单相_半波_整流