文章目錄
- 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一筆配置
未完待續