文章目录
- MQTT知识点
- mqtt数据
- 固定报头
- 可变报头(连接请求)
- 有效载荷
- 阿里云MQTT测试
- 订阅Topic
- 下发数据给MQTT.fx
- MQTT.fx 发布消息给服务器
- 下载mqtt(C-嵌入式版)
- 我的W5500项目路径
- 使用Cat1连接阿里云平台
- AT指令串口连接
- 1. 开机联网
- 2. 激活内置SIM卡(贴片卡)
- 3. 我这里使用连接的是阿里云的物联网平台
- 4. (非必要)关闭MQTT连接
- 5. 总结:AT全部指令(简便式)
- STM32单片机连接Cat1实现用MQTT连接阿里云
MQTT知识点
MQTT协议是通过TCP/IP协议做的
- 连接与响应(主要, 带的数据会比较多复杂些)
- 订阅主题
- 发布与响应
- PING(心跳)
- 关闭
mqtt数据
- 因为MQTT协议是通过TCP/IP协议做的所以第一部分是TCP的报头
- 固定报头限制字节,但没限制长度。不同的消息类型会传不同的信息; 会影响后面的可变报头,有效载荷
- 可变报头(可以像PingPong一样没有可变报头)
固定报头
-
报文类型(可以组成1~15bit)
不同的消息类型会传不同的信息; 会影响后面的可变报头,有效载荷 -
3bit-重复: 只有在QOS>1时,才有可能用到。当第一次发布消息时,
置0,如果是重复发布的要置1。(标志位;发生信息后没有响应,就再发一次后此时QOS从0到1) -
[1~2bit]:
QOS=0时,“最多一次”,尽操作
环境所能提供的最大努力分发消息。消息
可能会丢失。例如,这个等级可用于环境
传感器数据,单次的数据丢失没关系,因
为不久之后会再次发送,
Q0S=1时,“至少一次”
保证消
息可以到达,但是可能会重复。
Q0S=2时,”仅一次”,保证消息
只到达一次。例如,这个等级可用在一个
计费系统中,这里如果消息重复或丢失会
导致不正确的收费,
- [0bit] :flag
当置1时,服务端将(发布者的信息)保留此条应用消息,分发给未来的订阅者。如果载荷为空(消息是空的,当前flag数据还置为1),相当于清空消息。
固定报头长度最高5个字节
[0~6bit] : 最大值是128,若超过128就用最后一位(7bit)来表示: 最后一位是0的话没有第三字节,最后一位是1就有第三字节(第三字节与第二字节一致最大是128;第5个字节最后一位必须是0,若1不是前面的数据全部就没有了)
可变报头(连接请求)
- 协议名(站6个字节,UTF-8格式),前面是字符串长度(高(MSB)低(LSB)位)
- 协议级别: 版本。图中显示的是4对应3.1.1版本,这个版本就没有(属性5.0)
- 连接标志: 尤其是初次连接(用户名,密码不可少)
遗嘱: 订阅者订阅的时候会有标志位信息,那遗嘱就是我关闭的时候也可以发送一段信息(连接后关闭的时候这个遗嘱就可以发布给其他订阅者了,或者取消订阅)
- 新开始(新连接): 最开始已经连接过了但是中断了,那再连接时(遗嘱标志)就不需要置1了(最开始的连接需要置1)
- 保留位: 对于遗嘱保留什么,这个保留没什么动作
- 保持连接: 就算是心跳。心跳也是有时间的,图中设置成60秒
有效载荷
- 遗嘱属性(不是mqtt5.0的是没有的)
- 遗嘱主题(不是mqtt5.0的是没有的)
- 遗嘱载荷(不是mqtt5.0的是没有的)
现在万物智联(物体要有智慧的话就需要以上操作)
- 客户端标识符(必须有),也是utf-8格式(高()MSB)低(LSB)位)若长度是18那第19位就到用户名那了。18个就是18个字符串后不用像写
\0或者\n这样
阿里云MQTT测试
参考文章
HMACSHA1 在线加密工具
迈向物联网第一步——MQTT理论知识详解
mqtt.fx-windows下载
至于密钥(适用于MQTT.fx(validUntil: 2040-10-18 03:13:04))
-----BEGIN CERTIFICATE-----
MIIG7jCCBNagAwIBAgIJAOiLlBQu/GDHMA0GCSqGSIb3DQEBDQUAMIGpMQswCQYD
VQQGEwJERTEQMA4GA1UECAwHQmF2YXJpYTERMA8GA1UEBwwIRXJsYW5nZW4xFzAV
BgNVBAoMDlNvZnRibGFkZSBHbWJIMRkwFwYDVQQLDBB3d3cuc29mdGJsYWRlLmRl
MRwwGgYDVQQDDBNTb2Z0YmxhZGUgUm9vdCBDQSAxMSMwIQYJKoZIhvcNAQkBFhRj
b250YWN0QHNvZnRibGFkZS5kZTAeFw0yMDEwMjIxOTEzMDRaFw00MDEwMTcxOTEz
MDRaMIGpMQswCQYDVQQGEwJERTEQMA4GA1UECAwHQmF2YXJpYTERMA8GA1UEBwwI
RXJsYW5nZW4xFzAVBgNVBAoMDlNvZnRibGFkZSBHbWJIMRkwFwYDVQQLDBB3d3cu
c29mdGJsYWRlLmRlMRwwGgYDVQQDDBNTb2Z0YmxhZGUgUm9vdCBDQSAxMSMwIQYJ
KoZIhvcNAQkBFhRjb250YWN0QHNvZnRibGFkZS5kZTCCAiIwDQYJKoZIhvcNAQEB
BQADggIPADCCAgoCggIBAMw3XhycExw0i5GtFgXJoQkYv4B7abAQgSvJoGB8qm9o
0zxr0mHtYBkH7VANQb/m49CEADEVMYVGLVEeBXJ8rEg11ckS4FMxwxzj+YPpvcwS
cqe453+tWC0pFbDkNsZF4Y1ATlSR3Ab7KiQtsgfrsft46oghFE8Oadp0gmwP5O1A
z7SZKBbNadTGfqOK67T5p2gR+TMrb2L2llsStspLfxmGoOZEzytW5goKWKXphio2
vtIuUTiQqAfr7utbY8ZAEjx/srdF9BbxQUpj4zFsqSJfSu1H+l/sN6zOsVAzqTpG
wU3mgttAzlxYlI/SMbhDN817LYHP4IEmg0hgqqk1oEBA1U3y8LWLUuNt4VREscSU
bvPwYdJjApi3CpTmp+YahMk4tqXeJ0bZA0WXpAzPAnCWMHOpGG4rzC2iUJu61klb
9jmmxkOzZV2p/RMKlCGEYuVBM3h7jx8oFZ19Hea9nBarSQyPSvkYt9q3gGgvxN6L
+RvHRmbkHkHsbImKCtNJGg/8wqVmO91GqqjJSuR0IAYta4aRVoNe7UnDMhM5A+jt
smfS4IDklqZrbw/NnVJL+FRnrBfcIHSVJbTs9IFdz6ZGjvCexEu/bgDTwBwvWu4o
YIKNdXMB+UBCifuQEuPEcn4ce2nL9UJcEIGDWjOnJNHhg8efxBenn3ENZNwRBD8P
AgMBAAGjggEVMIIBETAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRO6cF4TD6P
FCYoe+kyrhV335+BODCB3gYDVR0jBIHWMIHTgBRO6cF4TD6PFCYoe+kyrhV335+B
OKGBr6SBrDCBqTELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0JhdmFyaWExETAPBgNV
BAcMCEVybGFuZ2VuMRcwFQYDVQQKDA5Tb2Z0YmxhZGUgR21iSDEZMBcGA1UECwwQ
d3d3LnNvZnRibGFkZS5kZTEcMBoGA1UEAwwTU29mdGJsYWRlIFJvb3QgQ0EgMTEj
MCEGCSqGSIb3DQEJARYUY29udGFjdEBzb2Z0YmxhZGUuZGWCCQDoi5QULvxgxzAN
BgkqhkiG9w0BAQ0FAAOCAgEAda2ef3YTFI2euS2EjZXa5jgdSAvrCpPjX4HVrG0n
3Su+FjIAGam0PMX635wTqj7np9s7NKqZj7IWS7o8EhVL4RqnAHFBq+ta8PXIZQB3
xWf8qbKIBoSmdwUaJw44MeBdhc4nni5O6zho4RY00/FJddLf4kCtcBsXu6Zs8K3a
IW/frSU4I7kD91xnFZ6SQQEZH1UBAttZvK5pO1m2MFkgYqXIOWycNB3CsPqor8sT
zF296Fp4LbyhkI+9HkeoiTce7oZQGPl346FwVYw4ERuiH7C217gy5TMRK/bangxq
yDOoOXyrRbWfyfhYnmexAe8k/IFix5XzHU9yU7iWvc1Y1nj4tnqIUnas3oXK08TU
vesfK4iUXviJQdRYIWpIJ1g1bagzec2sijFVIdSG0qThBXWiQp98tojCi9Z7fm5U
Et5douMZMm17wc5ELyX2nx083b6+5xMBpEFYrES9iiefMFFD7hmHb5r8B17iOnW6
ujZi5U/9ZhpnuVvI3VGqSDQfne8p3ra814X1gOtKJPWQRU6i0/1tfo+Pxw+ATB1j
h4ZxMEGx9zGF3UAD6VATeKE6yepfwrKiXAHz3gyLeD5F7Di8IFtKs5yIpjK4/Jfp
IkolTm9gBMKDT723nlfOS7xVHHnfP5auH+Wmgmb9BlavBO/k5zcqxMA3VfWsqnIS
Ekc=
-----END CERTIFICATE-----
#此mqtt服务器在上海(华东2)
Broker Address: ProductKey.iot-as-mqtt.cn-shanghai.aliyuncs.com
#一般端口为1883
Broker Port:1883
Client ID: DeviceName|securemode=3,signmethod=hmacsha1|
User Name:DeviceName&ProductKey
#忽略空格,加密密钥是DeviceSecret值
#举例: clientIdwlan_wifi_testdeviceNamewlan_wifi_testproductKeya1mqeQuLw0k
Password: clientId DeviceName deviceName DeviceName productKey ProductKey的hmacsha1加密
订阅Topic
阿里云上就有1订阅1
下发数据给MQTT.fx
/sys/productKey/DeviceName/thing/service/property/set
{"method":"thing.service.property.set","id":"621799578","params":{"CurrentTemperature":30},"version":"1.0.0"}
MQTT.fx 发布消息给服务器
/sys/productKey/DeviceName/thing/event/property/post
将上一段响应复制下来
//{"method":"thing.service.property.set","id":"621799578","params":{"CurrentTemperature":30},"version":"1.0.0"}
//改动了方法、消息ID(ID可自行用户定义)、params里的值
{"method":"thing.event.property.post","id":"621799531","params":{"CurrentTemperature":35},"version":"1.0.0"}
Response Topic : 跟上面订阅一样,但可以不填
Correlation Data: 必填即便是1都可以
没有右侧边的mqtt.fx软件可以无视
//json案例
{"method":"thing.event.property.post","id": "82485025","version": "1.0","params": {"CurrentTemperature": 46}
}
咱们mqqtt能通了那就可以下一步用单片机
下载mqtt(C-嵌入式版)
前面了解了MQTT协议和使用MQTT工具去如何通讯,接下来就看怎么用单片机进行通讯了(使用的还是W5500网卡驱动芯片)
参考文章
Paho-MQTT C(嵌入式版)
git clone https://github.com/eclipse/paho.mqtt.embedded-c.git
下载不了,可以用管理员运行记事本,用记事本打开windows的C:\Windows\System32\drivers\etc文件里面添加
140.82.113.4 github.com
重启计算机后即可
最主要的
mqtt.h
文件
#ifndef __MQTT_H
#define __MQTT_H#ifdef __cplusplus
extern "C" {
#endif/* 包含必要的头文件 */
#include <stdint.h>
#include <stdbool.h>
#include "FreeRTOS.h"
#include "queue.h"/* 阿里云MQTT配置 (根据实际修改) */
#define PRODUCT_KEY "a1xxxxxx" // 替换为您的产品Key
#define DEVICE_NAME "device1" // 替换为您的设备名称
#define DEVICE_SECRET "your_secret" // 替换为设备密钥/* MQTT服务器配置 */
#define MQTT_SERVER PRODUCT_KEY ".iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define MQTT_PORT 1883
#define MQTT_KEEP_ALIVE 60 // 心跳间隔(秒)/* MQTT主题定义 */
#define TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post"
#define TOPIC_PROP_SET "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/service/property/set"
#define TOPIC_UPDATE "/" PRODUCT_KEY "/" DEVICE_NAME "/user/update"
#define TOPIC_GET "/" PRODUCT_KEY "/" DEVICE_NAME "/user/get"/* MQTT QoS级别 */
typedef enum {MQTT_QOS0 = 0, // 最多一次MQTT_QOS1 = 1, // 至少一次MQTT_QOS2 = 2 // 恰好一次
} mqtt_qos_t;/* MQTT消息结构 */
typedef struct {char topic[128]; // 主题char payload[256]; // 负载内容mqtt_qos_t qos; // QoS级别bool retained; // 保留标志
} mqtt_message_t;/* MQTT客户端状态 */
typedef enum {MQTT_STATE_DISCONNECTED,MQTT_STATE_CONNECTING,MQTT_STATE_CONNECTED,MQTT_STATE_DISCONNECTING,MQTT_STATE_ERROR
} mqtt_state_t;/* 函数声明 *//*** @brief 初始化MQTT客户端*/
void mqtt_client_init(void);/*** @brief 连接到MQTT服务器* @return 0成功,其他失败*/
int mqtt_connect(void);/*** @brief 断开MQTT连接*/
void mqtt_disconnect(void);/*** @brief 发布消息* @param topic 主题* @param payload 负载内容* @param qos QoS级别* @param retained 是否保留* @return 0成功,其他失败*/
int mqtt_publish(const char *topic, const char *payload, mqtt_qos_t qos, bool retained);/*** @brief 订阅主题* @param topic 主题* @param qos QoS级别* @return 0成功,其他失败*/
int mqtt_subscribe(const char *topic, mqtt_qos_t qos);/*** @brief 取消订阅* @param topic 主题* @return 0成功,其他失败*/
int mqtt_unsubscribe(const char *topic);/*** @brief 发送心跳包* @return 0成功,其他失败*/
int mqtt_ping(void);/*** @brief 获取当前状态* @return mqtt_state_t 状态值*/
mqtt_state_t mqtt_get_state(void);/*** @brief 设置MQTT回调函数* @param connect_cb 连接回调* @param message_cb 消息回调*/
void mqtt_set_callback(void (*connect_cb)(bool connected), void (*message_cb)(const char *topic, const char *payload));/*** @brief 获取发送队列(用于其他任务发送消息)* @return QueueHandle_t 消息队列句柄*/
QueueHandle_t mqtt_get_tx_queue(void);/*** @brief 获取接收队列(用于其他任务接收消息)* @return QueueHandle_t 消息队列句柄*/
QueueHandle_t mqtt_get_rx_queue(void);/*** @brief 生成阿里云MQTT密码* @param client_id 客户端ID* @param product_key 产品Key* @param device_name 设备名称* @param device_secret 设备密钥* @param password_out 输出的密码缓冲区(至少65字节)*/
void mqtt_generate_password(const char *client_id, const char *product_key, const char *device_name, const char *device_secret, char *password_out);#ifdef __cplusplus
}
#endif#endif /* __MQTT_H */
这个阿里云MQTT配置可查看填入
我的W5500项目路径
太麻烦了,可以看下一个。这里之后更新
使用Cat1连接阿里云平台
AT指令串口连接
以塔石Cat1为例E27-EVK(内置SIM卡)
1. 开机联网
将
PWKY
播到ON就可以正常使用AT指令,若没有拨到ON则会出现AT指令发送却收不到的现象
2. 激活内置SIM卡(贴片卡)
AT+CFUN=0 #注销网络
AT+QDSIM=1 #切卡SIM1内置贴片卡
AT+CFUN=1 #重新注册网络
之后就可以通过TCPIP连接还是UDP还是MQTT连接啦
3. 我这里使用连接的是阿里云的物联网平台
- 我们先学会使用串口发数据,那用单片机去执行也很快
- 打开MQTT
#举例: AT+QMTOPEN=0,"a1mqeQuLw0k.iot-as-mqtt.cn-shanghai.aliyuncs.com",1883
AT+QMTOPEN=0,"ProductKey.iot-as-mqtt.cn-shanghai.aliyuncs.com",1883
若出现说明连接成功
- 连接阿里云
#举例: AT+QMTCONN=0,"wlan_wifi_test|securemode=3,signmethod=hmacsha1|","wlan_wifi_test&a1mqeQuLw0k","751050e9cca6018089a5dc729a55933e0da6ab74"
AT+QMTCONN=0,"DeviceName|securemode=3,signmethod=hmacsha1|","DeviceName&ProductKey","(DeviceName+DeviceName+DeviceSecret)通过hmacsha1加密而得到的"
加密工具密钥是DeviceSecret
加密格式
阿里云MQTT配置
说明连接成功
查看物联网平台
若出现
没有输出用户名密码或者出现QMTCONN:0,0,4
的情况说明连接失败,请查看数据手册
出现QMTCONN:0,0,4
需重新AT+QMTOPEN
指令因为最后+QMTDISC: 0,0
(断开连接)了
- 订阅主题
#举例: AT+QMTSUB=0,1,"/sys/a1mqeQuLw0k/wlan_wifi_test/thing/service/property/set",2
AT+QMTSUB=0,1,"/sys/ProductKey/DeviceName/thing/service/property/set",2
退订也是如此
#举例: AT+QMTUNS=0,1,"/sys/a1mqeQuLw0k/wlan_wifi_test/thing/service/property/set",2
AT+QMTUNS=0,1,"/sys/ProductKey/DeviceName/thing/service/property/set",2
- 数据推送
#举例: AT+QMTPUBEX=0,001,0,1,"/sys/a1mqeQuLw0k/wlan_wifi_test/thing/event/property/post",108
AT+QMTPUBEX=0,001,0,1,"/sys/ProductKey/DeviceName/thing/event/property/post",3
注意: 这个3和108是Length(发送数据的长度),小于发送数据的长度时数据全;大于发送数据的长度时会卡死(等待余下的数据,超时就ERROR)举例中的108是下面数据的长度
记住发送有时间规定
{"method":"thing.event.property.post","id":"726100847","params":{"CurrentTemperature":15},"version":"1.0.0"}
参数可以在这里查看
也可以设置-下发给设备
得到的数据是
+QMTRECV: 0,0,"/sys/a1mqeQuLw0k/wlan_wifi_test/thing/service/property/set","{"method":"thing.service.property.set","id":"1933324072","params":{"CurrentHumidity":20,"CurrentTemperature":10},"version":"1.0.0"}
出现日志中状态都是200
说明上传成功
数据也得到修改
注意一点:
即便是订阅了,发布成功,数据修改了,阿里云也没有显示订阅的Topic。这点我就不是很清楚了
4. (非必要)关闭MQTT连接
AT+QMTDISC=0
5. 总结:AT全部指令(简便式)
AT+CFUN=0 #注销网络
AT+QDSIM=1 #切卡SIM1内置贴片卡
AT+CFUN=1 #重新注册网络
AT+QMTOPEN=0,"a1mqeQuLw0k.iot-as-mqtt.cn-shanghai.aliyuncs.com",1883
AT+QMTCONN=0,"wlan_wifi_test|securemode=3,signmethod=hmacsha1|","wlan_wifi_test&a1mqeQuLw0k","751050e9cca6018089a5dc729a55933e0da6ab74"
AT+QMTSUB=0,123,"/sys/a1mqeQuLw0k/wlan_wifi_test/thing/service/property/set",0
AT+QMTPUBEX=0,001,0,1,"/sys/a1mqeQuLw0k/wlan_wifi_test/thing/event/property/post",108
{"method":"thing.event.property.post","id":"726100847","params":{"CurrentTemperature":15},"version":"1.0.0"}
可以按照这个模板抄,换成自己的DeviceSecret(设备证书)
STM32单片机连接Cat1实现用MQTT连接阿里云
单片机和Cat1进行通讯还是用的AT指令
上例中Cat1默认波特率为115200
因为使用的是STM32所以我们就用CubeMX一笔配置
未完待续