ESP32学习笔记 MQTT协议

这篇具有很好参考价值的文章主要介绍了ESP32学习笔记 MQTT协议。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),信息传输的对象我分为客户端消息发布者(pub)、服务器(server)、客户端消息订阅者(sub),一个客户端可以同时为发布者和订阅者。服务器,服务器为信息传输的枢纽有传递数据、管理客户端、数据保真等作用。

主题

MQTT的通信方式为pub向server发布一个主题并且向这个主题中发布数据,sub如果订阅了这个主题就可以接收到这个主题下的消息。

打个比喻,我们用户观看互联网视频平台上的视频,如果我们想观看一名UP的视频,那么我们用户就一定要关注这名UP的频道,而这名UP会不定时得向他自己的频道发布视频供我们用户观看。而平台就负责了视频、用户、UP的管理,并提供了视频传输的服务。

连接MQTT服务器

客户端连接服务器分为两步:1、客户端向服务器发送连接请求。2、服务器向客户端发送连接确认。

客户端向服务器发送连接请求

客户端向服务器发送一个CONNECT报文
报文内容包括:
clientId——客户端的ID,不能出现重名的客户端
cleanSession——清除会话,在消息的重发中用到
username——连接客户端时输入的用户名,没有可以不输入
password——连接客户端时输入的密码,没有可以不输入
lastWillQos——遗言的Qos
lastWillMessage——遗言的消息内容
lastWillRetain——遗言是否保留
keepAlive——心跳时间间隔,用于服务器判断此客户端是否意外断线

服务器向客户端发送连接确认

服务器向客户端发送一个CONNACK报文
报文内容包括:
sessionPresent——当前会话,配合cleanSession清除会话使用,用于查看是否有保留消息
returnCode——连接返回码,用0到5来表示连接的状态

发布、订阅和取消订阅

发布操作包括1、pub向server发布消息。2、server向订阅了主题的sub发布消息。每次pub更新了主题内的数据,server都会向sub发布消息。
订阅则简单得多,当sub订阅了一个主题后,关于这个主题的操作就只有等着接收数据和取消订阅了。
当每次发布与订阅时就会创建相对应的主题,不需要什么专门操作。
这里有个问题,如果pub不更新数据,那么sub是不能接收到数据的,为了解决这个问题pub发布的消息可以选择为保留状态,这样sub一订阅这个主题就会收到这个保留消息。
这些操作同样是通过报文交互完成。

发布

pub向server或者server向订阅了该主题的sub发送一个PUBLISH报文
报文内容包括:
packetId——报文标识符,用于标识数据包,只有当qos为非0时才为非0的数字序列
topicName——主题名
qos——服务质量等级,分为0,1,2三档次
retainFlag——保留标志,标识消息是否需要设置为保留消息
payload——有效载荷,消息的实际内容
dupFlag——重发标志,标识消息是否可以重发,只有当qos为非0才能为true

订阅

sub向server发送一个SUBSCRIBE报文
报文包括qos与多个订阅主题名,即一个SUBSCRIBE报文可以用于订阅一个或者多个主题。
qos——服务质量等级,在发布与订阅中都要设置。
topic——主题名,可为多个

在sever接收到SUBSCRIBE报文后,server向sub发送一个SUBACK报文
报文包括“订阅返回码”和“报文标识符”这两个信息。
packetId——报文标识符
returnCode —— 订阅返回码,服务端会针对SUBSCRIBE报文中的所有订阅主题来逐一回复给客户端一个返回码。

取消订阅

sub向server发送一个UNSUBSCRIBE报文
报文内容:
packetId——报文标识符
topic——主题名,可为多个

当server接收到UNSUBSCRIBE报文后,会向sub发送取消订阅确认报文 – UNSUBACK报文
该报文含有客户端所发送的“取消订阅报文标识符”。

MQTT主题

主题基本形式

主题的最基本形式就是一个字符串。
主题是区分大小写的。
主题可以使用空格,但不建议。
大部分MQTT服务端不支持中文主题。

主题分级

MQTT主题各个级别之间可以使用”/”来分隔
列如 username/myTopic/1
分别是第1级 username、第2级 myTopic、第3级 1

主题通配符

当客户端订阅主题时,可以使用通配符同时订阅多个主题。通配符只能在订阅主题时使用,下面我们将介绍两种通配符:单级通配符和多级通配符。
单级通配符: +
单级通配符可以代替一个主题级别。

多级通配符 : #
单级通配符仅可代替一个主题级别,而多级通配符”#”可以涵盖任意数量的主题级别。

主题应用注意事项

以$开始的主题是MQTT服务端系统保留的特殊主题,我们不能随意订阅或者向其发布信息。
不要用 “/” 作为主题开头,这没有意义。
主题中不要使用空格,难以阅读且容易忽略。
保持主题简洁明了。
主题中尽量使用ASCII字符。
在主题中嵌入客户端ID。

Qos 服务质量等级

什么是服务质量

MQTT服务质量(Quality of Service 缩写 QoS)正是用于告知物联网系统,哪些信息是重要信息需要准确无误的传输,而哪些信息不那么重要,即使丢失也没有问题。

MQTT协议有三种服务质量级别:

QoS = 0 – 最多发一次
QoS = 1 – 最少发一次
QoS = 2 – 保证收一次

设置QoS

发布消息
客户端发布信息时,PUBLISH数据包中专有一个信息为qos。该信息正是用于设置客户端发布MQTT消息的QoS等级。

订阅消息
同样的,在客户端订阅MQTT主题时,SUBSCRIBE数据包中也同样有一个信息用于设置订阅主题的QoS级别。客户端正是通过该主题来设置订阅主题的QoS级别的。

接收端连接服务端
另外,要想实现QoS>0的MQTT通讯,客户端在连接服务端时必须要将cleanSession设置为false。如果这一步没有实现,那么客户端是无法实现QoS>0的MQTT通讯。

服务质量降级

假如客户端A发布到主题1的消息是采用QoS = 2,然而客户端B订阅主题1采用QoS = 1。那么服务端该如何来应对这一情况呢?
答案是服务端会选择Qos等级低的一方为准。

保留消息

保留消息的作用

默认情况下只有当pub发布了一条新的数据时,sub才会接收到数据。
那么一种情况:
pub要隔很久才会更新一次消息。
sub在pub更新消息的间隙订阅了主题。
那么在pub更新前sub是接收不到消息的,这情况下pub将会有很长的时间是没有信息的状态。

为了避免这种情况,我们把一条pub发布的消息设置为保留消息,当sub订阅了主题时能马上接收到保留消息,而不需要白白等待pub更新。

发布保留消息的方法

MQTT设备发布的保留消息的流程与发布普通消息的流程十分类似。唯一区别是,在发布保留消息时,MQTT设备需要将PUBLISH报文中retainFlag设置为true。

修改保留消息的方法

每一个主题只能有一个“保留消息”,如果客户端想要更新“保留消息”,就需要向该主题发送一条新的“保留消息”,这样服务端会将新的“保留消息”覆盖旧的“保留消息”。当有客户端订阅该主题时,服务端就会将最新的“保留消息”发送给订阅客户端了。

删除保留消息的方法

如果要删除主题的“保留消息”,可以通过向该主题发布一条空的“保留消息”,也就是发送一条0字节payload的“保留消息”。

心跳机制

有些客户端并不经常发送消息给服务端。对于这种客户端,服务端可以使用类似心跳检测的方法,来判断客户端是否在线。

让客户端在没有向服务端发送信息时,可以定时向服务端发送一条消息。这条用于心跳机制的消息也被称作心跳请求(PINGREQ)。心跳请求的作用正是用于告知服务端,当前客户端依然在线。服务端在收到客户端的心跳请求后,会回复一条消息。这条回复消息被称作心跳响应(PINGRESP)。
由于心跳请求是客户端定时发送的,一旦服务端发现客户端停止发送请求信息,那么服务端就会知道,这台客户端已经断开了连接。

在客户端连接服务端时,会将心跳时间间隔信息放入CONNECT报文。
keepAlive正是用于告知服务端心跳时间间隔的。

假如客户端的心跳间隔时间是60秒,那么服务端是不是每隔60秒就检查一次客户端是否发来心跳请求呢?
如果客户端在心跳时间间隔内发布了消息给服务端,那么服务端不需要客户端发送心跳请求也可以确定该客户端肯定在线。
但是当客户端在心跳间隔内没有发布消息给服务端,这时客户端会主动发送一个心跳请求消息给服务端。以表明自己仍让在线。
在实际运行中,如果服务端没有在1.5倍心跳时间间隔内收到客户端发布消息(PUBLISH)或发来心跳请求(PINGREQ),那么服务端就会认为这个客户端已经掉线。
另外,心跳机制不仅仅用于服务端判断客户端是否在线。客户端也可以利用这一机制来判断自己是否与服务端仍保持连接。如果客户端发送了心跳请求(PINGREQ)给服务端一段时间后,仍然没有收到服务端回复的心跳确认。那么客户端也会认为自己已经断开了与服务端的连接。

MQTT遗嘱

当客户端正常断开连接时,会向服务端发送DISCONNECT报文,服务端接收到该报文后,就知道,客户端是正常断开连接,而并非意外断开连接。
然而,当服务端在没有收到DISCONNECT报文的情况下,发现客户端“心跳”停止了,这时服务端就知道客户端是意外断线了。
当客户端意外断线时server会向订阅了此客户端遗嘱的sub发布遗嘱。

客户端如何将遗嘱消息发送给服务端

MQTT客户端要想连接服务端,首先要向服务端发送CONNECT报文,遗嘱相关的内容就在CONNECT报文中。
lastWillTopic —— 遗嘱主题
lastWillMessage —— 遗嘱消息
lastWillQoS —— 遗嘱QoS
lastWillRetain —— 遗嘱保留

遗嘱和一般主题类似,可以对这个遗嘱主题进行发布消息等操作,不同点为要在CONNECT报文中也就是连接服务器过程中将遗嘱内容发给服务器,并且在客户端意外离线时服务器会对订阅了此客户端的遗嘱主题的客户端发布遗嘱消息。

pub与sub代码

pub

#include <WiFi.h>
#include "WiFiClient.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"


#define WLAN_SSID "xxx_wifi"
#define WLAN_PASS "xxx_password"

#define MQTT_SERVER "xxx_server"

#define MQTT_SERVERPORT 1883

WiFiClient client;
Adafruit_MQTT_Client mqtt(&client,MQTT_SERVER,MQTT_SERVERPORT);
Adafruit_MQTT_Publish pub = Adafruit_MQTT_Publish(&mqtt,"my_test_topic/1");
void setup() {
  Serial.begin(115200);
  WiFi.begin(WLAN_SSID,WLAN_PASS);
  delay(2000);
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

}

void loop() {
  MQTT_connect();
  Serial.print(F("\nSendinf val"));
  if(!pub.publish("Hello World")){
    Serial.println(F("Failed"));
  }else{
    Serial.println(F("OK!"));
  }
  delay(2000);

}

void MQTT_connect(){
  int8_t ret;
  if(mqtt.connected()){
    return;
  }
  Serial.print("Connecting to MQTT...");
  uint8_t retries = 3;
  while((ret = mqtt.connect()) !=0){
    Serial.println(mqtt.connectErrorString(ret));
    Serial.println("Retrying MQTT connection in 5 seconds...");
    mqtt.disconnect();
    delay(5000);
    retries--;
    if(retries == 0){
      while(1);
    }
  }
  Serial.println("MQTT Connected!");

}

sub文章来源地址https://www.toymoban.com/news/detail-472786.html

#include <WiFi.h>
#include "WiFiClient.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"


#define WLAN_SSID "xxx_wifi"
#define WLAN_PASS "xxx_password"

#define MQTT_SERVER "xxx_server"

#define MQTT_SERVERPORT 1883

WiFiClient client;
Adafruit_MQTT_Client mqtt(&client,MQTT_SERVER,MQTT_SERVERPORT);
Adafruit_MQTT_Subscribe sub = Adafruit_MQTT_Subscribe(&mqtt,"my_test_topic/1");
void setup() {
  Serial.begin(115200);
  WiFi.begin(WLAN_SSID,WLAN_PASS);
  delay(2000);
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  mqtt.subscribe(&sub);
}

void loop() {
  MQTT_connect();
  Adafruit_MQTT_Subscribe *subscription;
  while((subscription = mqtt.readSubscription(1000))){
    if (subscription == &sub) {
      Serial.print("Got: ");
      Serial.println((char *)sub.lastread);
    }
  }
}

void MQTT_connect(){
  int8_t ret;
  if(mqtt.connected()){
    return;
  }
  Serial.print("Connecting to MQTT...");
  uint8_t retries = 3;
  while((ret = mqtt.connect()) !=0){
    Serial.println(mqtt.connectErrorString(ret));
    Serial.println("Retrying MQTT connection in 5 seconds...");
    mqtt.disconnect();
    delay(5000);
    retries--;
    if(retries == 0){
      while(1);
    }
  }
  Serial.println("MQTT Connected!");

}

到了这里,关于ESP32学习笔记 MQTT协议的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 + ESP32(AT固件 MQTT协议) + MQTTX(桌面终端) + (EMQX消息服务器)

    翻出老物件,搭建一个简单的 IOT 开发环境,也算是废物利用了 ,接下来加传感器。 1. STM32  采集数据:      RTOS。      资源相对比较丰富,可以根据项目需求定制。 2. ESP32  网络传输(AT固件 MQTT协议) :     AT:封装好的接口,扩展性不是那么好,业务简单的话将就可以

    2024年02月08日
    浏览(78)
  • STM32+ESP8266+DHT11通过MQTT协议连接新版ONENET云平台上传数据

    项目讲解视频 新版 云平台搭建视频演示 单片机代码修改演示视频 APP参数修改 实物演示 前段时间ONENET云平台进行了升级更新,此前平台的多协议接入(包含旧版MQTT、HTTP、EDP、Modbus、TCP透传等)接口已经隐藏,后续应该会下架,为了能够后续继续使用ONENET云平台,就需要学

    2024年02月09日
    浏览(44)
  • STM32+ESP-01s+EMQX实现单片机MQTT协议传输数据上云(二)STM32F103与ESP-01s的Usart通信,实现STM32连接上网上云

    单片机:STM32F103c8t6 WiFi模块:ESP8266-01s EMQX:自身服务器上搭载emq服务器或者借用emqx window 版本  USB TO TTL模块:CH340 因为CH340不能给ESP-01s供3.3V的电,所以测试时需要外加供电           本章中涉及到的技术原理主要为ESP01S wfi模块的AT指令通信,我在上一篇文章给大家提到了

    2024年02月16日
    浏览(56)
  • STM32进阶学习(1)-ESP01-S的AT指令测试、MQTT原理

    如图,不多解释了。 参数: 这里注意的是,频谱范围是2.4GHZ,所以连接WIFI时只支持2.4HGZ的频段,不支持5Ghz频段。另外,供电是3.3V,这里让单片机给其供电即可。 电路图: 拿到手的ESP01S,首先要验证其功能是否正常,这里我用ESP01S连接USB转串口模块,并与电脑上的串口调试

    2024年02月09日
    浏览(51)
  • 【Microsoft Message Queuing远程代码执行漏洞(CVE-2023-21554)漏洞修复】

    Windows 消息队列服务是一个Windows组件,需要系统启用该组件才能利用此漏洞,该组件可以通过控制面板添加。Microsoft Message Queuing中存在远程代码执行漏洞,未经身份验证的远程攻击者通过向MSMQ服务器发送特制的恶意MSMQ数据包触发此漏洞,最终实现在服务器端远程代码执行,

    2024年02月15日
    浏览(45)
  • Microsoft Message Queuing Denial-of-Service Vulnerability

    近期官方公布了一个MSMQ的拒绝服务漏洞,可能因为网络安全设备的更新,影响业务,值得大家关注。 Name: Microsoft Message Queuing Denial-of-Service Vulnerability Description: Microsoft Message Queuing is prone to a denial-of-service vulnerability while parsing certain crafted MSMQ requests. The vulnerability is due to the

    2024年02月14日
    浏览(39)
  • ESP8266学习笔记一 互联网通讯协议

    协议作用简单来说 就是规范不同的语言; 包含的协议有 TCP/IP实际上是一个协议组   不同的协议处于不同的层次上 (由下到上) 链路层WIFI 网络层IP 传输层TCP/UDP 应用层 HTTP 链路层: WIFI Ethernet 就是实实在在的进行数据传输的物理连接层 ESP32的三种模式: 链路层 数据帧 1,

    2023年04月27日
    浏览(51)
  • 【ESP32最全学习笔记(基础篇)——9.ESP32 深度睡眠模式】

    关于本教程: 1.ESP32简介                                                                 2.ESP32 Arduino 集成开发环境 3.VS 代码和 PlatformIO 4.ESP32 引脚 5.ESP32 输入输出 6.ESP32 脉宽调制 7.ESP32 模拟输入 8.ESP32 中断定时器 9.ESP32 深度睡眠 ☑

    2024年02月05日
    浏览(67)
  • 【ESP32最全学习笔记(基础篇)——4.ESP32 引脚介绍】

    关于本教程: 1.ESP32简介                                                                 2.ESP32 Arduino 集成开发环境 3.VS 代码和 PlatformIO 4.ESP32 引脚 ☑  5.ESP32 输入输出 6.ESP32 脉宽调制 7.ESP32 模拟输入 8.ESP32 中断定时器 9.ESP32 深度睡眠 ESP32 网络

    2024年02月03日
    浏览(51)
  • 【ESP32最全学习笔记(基础篇)——8.ESP32 中断定时器】

    关于本教程: 1.ESP32简介                                                                 2.ESP32 Arduino 集成开发环境 3.VS 代码和 PlatformIO 4.ESP32 引脚 5.ESP32 输入输出 6.ESP32 脉宽调制 7.ESP32 模拟输入 8.ESP32 中断定时器 ☑ 9 .ESP32 深度睡眠 ESP32 网络

    2024年02月06日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包