MQTT值订阅

前言

记忆不太好的时候,只能翻看以前的文章/笔记重新温习一遍,但找不到MQTT协议有关订阅部分的描述,好不容易从Evernote中找到贴出来,这样整个MQTT协议笔记,就比较齐全了。

SUBSCRIBE

一般来讲,客户端在成功建立TCP连接之后,发送CONNECT消息,在得到服务器端授权允许建立彼此连接的CONNACK消息之后,客户端会发送SUBSCRIBE消息,订阅感兴趣的Topic主题列表(至少一个主题),一个完整示范如下:


Description 7 6 5 4 3 2 1 0
Fixed header/固定头部
byte 1  Message Type(8)DUP flag QoS levelRETAIN
  1000001x
byte 2 Remaining Length
Variable header/可变头部
Message Identifier
byte 1Message ID MSB (0)00000000
byte 2Message ID LSB (10)00001010
Playload/消息体
Topic name
byte 1Length MSB (0)00000000
byte 2Length LSB (3)00000011
byte 3'a' (0x61)01100001
byte 4'/' (0x2F)00101111
byte 5'b' (0x62)01100010
Requested QoS
byte 6Requested QoS (1)xxxxxx01
Topic Name
byte 7Length MSB (0)00000000
byte 8Length LSB (3)00000011
byte 9'c' (0x63)01100011
byte 10'/' (0x2F)00101111
byte 11'd' (0x64)01100100
Requested QoS
byte 12Requested QoS (2)xxxxxx10
固定头部

Qos Level,可根据实际情况进行调整为0/1/2等。一般设为0表示最多一次。客户端可设置OoS Level值。 DUP flag,值为0表示第一次发送。

可变头部

因为上面示范QoS level值为1,因此需要客户端传递消息ID,16位,无符号的short类型。

消息体

订阅的主题名称采用修改版UTF-8编码,然后紧跟着对应的QoS值。下面的次序,可能更为形象:

Topic name"a/b"
Requested QoS1
Topic name"c/d"
Requested QoS2

订阅者的Topic name支持通配符#和+ :

  1. #支持一个主题内任意级别话题
  2. +只匹配一个主题级别的通配符

eg:

finance/stock/#
finance/sotkc/ibm/+

都是有效,更具体规则,请参阅协议附加部分。

在服务器接收处理时,按照顺序读取即可:

String topicName = readUTF();
int qosVal = read();

服务器可以发送QoS不大于客户端设置OoS的消息,尤其是服务器不提供良好的持久化机制的时候。

SUBACK

服务器会对发出SUBSCRIBE的消息返回一个确认消息。


Description 7 6 5 4 3 2 1 0
Fixed header/固定头部
byte 1  Message type (9)DUP flag QoS flagsRETAIN
  1001xxxx
byte 2  Remaining Length
Variable header/可变头部
Message Identifier
byte 1Message ID MSB (0)00000000
byte 2Message ID LSB (10)00001010
Playload/消息体
byte 1Granted QoS (0)xxxxxx00
byte 1Granted QoS (2)xxxxxx10
可变头部

Message Identifier,服务器需要附加,客户端需要处理。

消息体

QoS,为服务器根据实际情况授予的QoS级别列表,和客户端发送的SUBSCRIBE的订阅Topic Name顺序完全一致。

客户端订阅几个TOPIC,服务器端一一给出各个TOPIC的QoS具体值。

UNSUBSCRIBE

服务器需要支持客户端取消订阅功能,UNSUBSCRIBE消息格式和SUBSCRIBE消息格式差不多,除了消息类型不同,消息体中没有了QoS字节,其它没有区别。


Description 7 6 5 4 3 2 1 0
Fixed header/固定头部
byte 1  Message Type(10)DUP flag QoS levelRETAIN
  1010001x
byte 2 Remaining Length
Variable header/可变头部
Message Identifier
byte 1Message ID MSB (0)00000000
byte 2Message ID LSB (10)00001010
Playload/消息体
Topic name
byte 1Length MSB (0)00000000
byte 2Length LSB (3)00000011
byte 3'a' (0x61)01100001
byte 4'/' (0x2F)00101111
byte 5'b' (0x62)01100010
Topic Name
byte 6Length MSB (0)00000000
byte 7Length LSB (3)00000011
byte 8'c' (0x63)01100011
byte 9'/' (0x2F)00101111
byte 10'd' (0x64)01100100

可变头部的消息ID的出现还是由固定头部的QoS Level(1)决定是否存在。

一般来讲,客户端发布退订,服务器端需要返回退订确认。

MQTT没讲是否允许客户端退订所有TOPIC。

UNSUBACK

服务器返回的UNSUBSCRIBE消息UNSUBACK相应很简单,没有消息体。


Description 7 6 5 4 3 2 1 0
Fixed header/固定头部
byte 1  Message type (9)DUP flag QoS flagsRETAIN
  1011xxxx
byte 2  Remaining length (2)
  00000010
Variable header/可变头部
Message Identifier
byte 1Message ID MSB (0)00000000
byte 2Message ID LSB (10)00001010

小结

订阅部分,共有四个消息,分别一一对应。

命令响应备注建议
SUBSCRIBESUBACK协议没有涉及最多运行订阅TOPIC数目,隐藏的隐患建议至多10个
UNSUBSCRIBEUNSUBACK是否可以退订所有订阅,不详建议保留至少一个Topic

原文地址:http://www.blogjava.net/yongboy/category/54835.html

### ESP8266 使用 MQTT 实现消息发布与订阅 为了使ESP8266能够通过MQTT协议发送和接收数据,需先完成必要的库安装以及网络配置工作。具体而言,在Arduino IDE环境中操作时,应当引入`PubSubClient.h`用于处理MQTT通信逻辑,并加载Wi-Fi连接所需的库文件[^2]。 下面是一份完整的代码实例,展示了如何利用ESP8266执行基本的消息发布与订阅: ```cpp #include <ESP8266WiFi.h> #include <PubSubClient.h> // WiFi参数定义 const char* ssid = "yourSSID"; // 替换成自己的WiFi名称 const char* password = "yourPASSWORD"; // 替换成对应的WiFi密码 // MQTT服务器信息设定 const char* mqtt_server = "yourMQTTServer"; const int mqtt_port = 1883; // 默认端口号为1883, 如果不同则修改此 const char* topic_subscribe = "your/topic/subscribe"; // 订阅的主题名 const char* topic_publish = "your/topic/publish"; // 发布的主题名 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 reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); if (client.connect("ESP8266Client")){ // 尝试连接到MQTT代理服务 Serial.println("connected"); // 成功后的提示 // Once connected, subscribe to our topic client.subscribe(topic_subscribe); // 进行主题订阅动作 } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i=0;i<length;i++) { Serial.print((char)payload[i]); } Serial.println(); // Switch on the LED if an incoming message matches the condition. // This is just a simple example of how you can handle received messages. } void setup() { pinMode(LED_BUILTIN, OUTPUT); // 设置内置LED引脚模式 Serial.begin(115200); setup_wifi(); // 初始化并连接WiFi client.setServer(mqtt_server, mqtt_port); // 配置MQTT服务器地址及端口 client.setCallback(callback); // 注册回调函数以响应接收到的数据包事件 } void loop() { if (!client.connected()){ reconnect(); // 若断开,则重新连接MQTT服务器 } client.loop(); // 处理来自MQTT代理的服务端通知 long now = millis(); if(now % 5000 == 0){ // 每隔五秒向特定主题推送一次状态更新报告 String msg = "{\"status\":\"online\",\"time\":" + String(now) + "}"; Serial.print("Publish message: "); Serial.println(msg); client.publish(topic_publish,msg.c_str()); // 执行消息发布的API调用 } } ``` 这段程序实现了如下几个核心功能: - 完成对指定Wi-Fi热点的身份验证过程; - 建立起通往远程MQTT Broker的安全通道; - 对预设好的Topic实施监听(即订阅),以便及时获取其他设备分享的信息流; - 向外界广播自定义的内容片段(比如传感器读数或是简单的在线心跳信号);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值