W5100S——MQTT連線百度天工雲平臺
上篇文章主要講解了W5100S特色功能——SOCKET - less PING功能。
本篇文章則是講解,如何讓W5100S 通過MQTT連線百度天工雲平臺。
STM32+W5500_百度雲天工MQTT 例程下載------------>www.w5100s.com
1. 準備
-
軟體環境:Windows
-
硬體環境:STM32F103+W5500
-
開發工具:Keil uVision5
-
除錯工具:串列埠除錯助手
2. MQTT簡介
2.1 MQTT協議特點
MQTT是一個基於客戶端-伺服器的訊息釋出/訂閱傳輸協議。MQTT協議是輕量、簡單、開放和易於實現的,這些特點使它適用範圍非常廣泛。在很多情況下,包括受限的環境中,如:機器與機器(M2M)通訊和物聯網(IoT)。其在,通過衛星鏈路通訊感測器、偶爾撥號的醫療裝置、智慧家居、及一些小型化裝置中已廣泛使用。
MQTT協議當前版本為,2014年釋出的MQTT v3.1.1。除標準版外,還有一個簡化版MQTT-SN,該協議主要針對嵌入式裝置,這些裝置一般工作於百TCP/IP網路,如:ZigBee。
MQTT協議執行在TCP/IP或其他網路協議,提供有序、無損、雙向連線。其特點包括:
- 使用的釋出/訂閱訊息模式,它提供了一對多訊息分發,以實現與應用程式的解耦。
- 對負載內容遮蔽的訊息傳輸機制。
- 對傳輸訊息有三種服務質量(QoS):
- 最多一次,這一級別會發生訊息丟失或重複,訊息釋出依賴於底層TCP/IP網路。即:<=1
- 至多一次,這一級別會確保訊息到達,但訊息可能會重複。即:>=1
- 只有一次,確保訊息只有一次到達。即:=1。在一些要求比較嚴格的計費系統中,可以使用此級別
資料傳輸和協議交換的最小化(協議頭部只有2位元組),以減少網路流量
通知機制,異常中斷時通知傳輸雙方
2.2 MQTT協議原理及實現方式
實現MQTT協議需要:客戶端和伺服器端
MQTT協議中有三種身份:釋出者(Publish)、代理(Broker)(伺服器)、訂閱者(Subscribe)。其中,訊息的釋出者和訂閱者都是客戶端,訊息代理是伺服器,訊息釋出者可以同時是訂閱者。
MQTT傳輸的訊息分為:主題(Topic)和訊息的內容(payload)兩部分
Topic,可以理解為訊息的型別,訂閱者訂閱(Subscribe)後,就會收到該主題的訊息內容(payload)
payload,可以理解為訊息的內容,是指訂閱者具體要使用的內容
2.3 百度雲天工MQTT連線步驟
2.3.1.進入管理控制檯(請提前登入);
2.3.2. 選擇“物接入IoT Hub”板塊
2.3.3. 建立專案
(例程搭配資料型裝置使用,詳細資料型與裝置型差異,請前往百度雲天工查詢)
2.3.4. 專案提交後,進入專案建立子使用者
名稱:MQTT連線報文中的使用者名稱
身份:確定訪問形式,可以使用金鑰連線。
策略:繫結對應許可權與主題。
金鑰:請妥善保管,此為連線的密碼。(遺忘可在身份列表重置)
專案建立成功後,記錄下:名稱、身份、金鑰。即可通過例程修改對應字串連線自己所建立的裝置。
3. 例程實驗現象
首選我們檢視燒錄程式後,應有的實驗現象。
注:測試W5100S訂閱主題後的接收訊息和向主題釋出訊息,是在百度雲建立了第二個裝置B。B裝置釋出訊息和接收W5100S發的主題訊息。以此檢驗是否W5100S能收到主題訊息或傳送主題訊息。
3.1.串列埠列印資訊顯示“連線成功”或者“連線失敗的具體原因”。
3.2.訂閱主題
3.3.接收主題訊息
3.4.釋出主題訊息
4. 例程程式碼
由於程式碼內涉及MQTT的拆包組包部分,詳細講解太過冗雜。
故此次解析,僅從函式功能及程式碼框架解析,不對函式實現做過多拆解。
4.1.主函式整體框架流程
#include <stdio.h>
#include <string.h>
#include "stm32f10x.h"
#include "bsp_usart1.h"
#include "bsp_fsmc.h"
#include "bsp_spi.h"
#include "w5100s.h"
#include "W5100s_conf.h"
#include "wizchip_conf.h"
#include "w5100s_conf.h"
#include "utility.h"
#include "tcp_demo.h"
#include "MqttKit.h"
int main(void)
{
systick_init(72); // 初始化滴答定時器
USART1_Config(); // 初始化USART1:[email protected]
reset_break_gpio_init(); // 復位與中斷管腳初始化
#if (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_)
spi_gpio_init(); // SPI管腳初始化
spiinitailize(); // SPI配置初始化
reg_wizchip_spi_cbfunc(spi_read_byte,spi_send_byte); // SPI讀寫資料函式對映
reg_wizchip_cs_cbfunc(cs_low,cs_high); // SPI片選控制函式對映
#elif (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_)
FSMC_gpio_init(); // FSMC管腳初始化c
FSMCInitialize(); // FSMC配置初始化
#endif
printf("\r\n 煒世科技--WIZnet W5100S官方代理商。全程技術支援,價格優勢大!\r\n\r\n");
reset_w5100s(); // W5100S硬體復位
PHY_check(); // 網線檢測程式
set_w5100s_mac(); // 設定W5100SMAC地址
set_w5100s_netinfo(); // 設定W5100S網路引數
wizchip_init(txsize,rxsize); // 初始化4個Socket的傳送接收快取大小
printf("\r\n W5100S網路引數配置完成,請使用電腦 'PING' W5100SIP地址,檢查網路是否暢通。");
while(1) /*迴圈執行的函式*/
{
do_tcp_client(); // TCP 客戶端資料迴環測試
delay_ms(100);
if(User1 == 0) //訂閱
{
while(User1 == 0);
MQTT_STATE = MQTT_PKT_SUBSCRIBE;
}
// if(KEY_5 == 0) //取消訂閱
// {
// MQTT_STATE = MQTT_PKT_UNSUBSCRIBE;
// }
else if(User0 == 0) //釋出
{
while(User0 == 0);
MQTT_STATE =MQTT_PKT_PUBLISH;
}
}
}
主函式部分,程式碼整體框架還是十分明瞭的。
main函式之前是微控制器和W5100S使用前的初始化部分。
main內則是基本的TCP客戶端程式和按鍵檢測,不同按鍵改變MQTT_STATE的不同狀態。
接下來詳細進一步探究do_tcp_client()函式。
4.2.do_tcp_client()函式
uint8 buff[2048]; /*定義一個2KB的快取*/
uint8 BD_TG_server_ip[4] = {163,177,150,12}; //BD_TG伺服器IP地址
uint16 BD_TG_server_port = 1883; //BD_TG伺服器埠號
int MQTT_STATE = MQTT_PKT_CONNECT; //連線
const char *topics[] = {"test"}; //主題
uint8 BD_TG_ping_pak[2] = {0xC0,0x00}; //心跳報文
unsigned char *data_ptr = NULL; //指標指空
/**
*@brief TCP Client迴環演示函式。
*@param 無
*@return 無
*/
void do_tcp_client(void)
{
uint16 len=0;
switch(getSn_SR(SOCK_TCPC)) /*獲取socket的狀態*/
{
case SOCK_CLOSED: /*socket處於關閉狀態*/
socket(SOCK_TCPC,Sn_MR_TCP,local_port++,Sn_MR_ND);
break;
case SOCK_INIT: /*socket處於初始化狀態*/
connect(SOCK_TCPC,BD_TG_server_ip,BD_TG_server_port); /*socket連線伺服器*/
break;
case SOCK_ESTABLISHED: /*socket處於連線建立狀態*/
if(getSn_IR(SOCK_TCPC) & Sn_IR_CON)
{
setSn_IR(SOCK_TCPC, Sn_IR_CON); /*清除接收中斷標誌位*/
}
len=getSn_RX_RSR(SOCK_TCPC); /*定義len為已接收資料長度*/
if(len>0)
{
recv(SOCK_TCPC,buff,len); /*接收來自Server的資料*/
data_ptr = buff;
if(data_ptr != NULL)
BD_TG_RevPro(data_ptr);
if(publish_buf[0] == 0x31)
{
LED_ALL_ON;
}
else if(publish_buf[0] == 0x32)
{
LED_ALL_OFF;
}
}
switch(MQTT_STATE)
{
/*MQTT協議連線BD_TG代理平臺*/
case MQTT_PKT_CONNECT:
BD_TG_DevLink();
MQTT_STATE = MQTT_PKT_PINGREQ;
break;
/*訂閱主題*/
case MQTT_PKT_SUBSCRIBE:
BD_TG_Subscribe(topics,1);
MQTT_STATE = MQTT_PKT_PINGREQ;
break;
/*Qos2級別釋出訊息*/
case MQTT_PKT_PUBLISH:
BD_TG_Publish(*topics, "MQTT Publish Test"); //釋出訊息
delay_ms(300); //等待平臺響應
/*接收平臺傳送的PubRec並回復PubRel響應*/
len=getSn_RX_RSR(SOCK_TCPC);
recv(SOCK_TCPC,buff,len);
data_ptr = buff;
if(data_ptr != NULL)
BD_TG_RevPro(data_ptr);
delay_ms(100); //PubRel響應等待平臺響應
len=getSn_RX_RSR(SOCK_TCPC);
recv(SOCK_TCPC,buff,len);
data_ptr = buff;
if(data_ptr != NULL)
BD_TG_RevPro(data_ptr);
MQTT_STATE = MQTT_PKT_PINGREQ;
/*120秒傳送一次Ping響應保持長連線*/
break;
case MQTT_PKT_UNSUBSCRIBE:
MQTT_UnSubscribe(topics,1);
MQTT_STATE = MQTT_PKT_PINGREQ;
break;
case MQTT_PKT_PINGREQ:
if(BD_TG_ping_time > 120)
{
send(SOCK_TCPC,BD_TG_ping_pak,2);
BD_TG_ping_time = 0;
}
break;
}
break;
case SOCK_CLOSE_WAIT: /*socket處於等待關閉狀態*/
close(SOCK_TCPC);
break;
}
}
主要是個狀態機的編寫格式,基本的TCP建立連線(SOCK_ESTABLISHED狀態)後,通過MQTT_STATE變數的狀態,判斷是傳送MQTT連線報文、MQTT訂閱報文、MQTT訊息釋出、MQTT取消訂閱、MQTT心跳報文等不同的case。
最開始會先預設進入MQTT_PKT_CONNECT,傳送連線報文,我們連線百度雲,主要有以下引數需要更改。
#define PROID "7321ph4/w5500" // 裝置全稱
#define AUTH_INFO "23h0wtzkmmti982q" // API金鑰
#define DEVID "qwe" // 身份
以上資訊,在百度雲建立裝置時,會讓客戶設定。我們只需要把設定的複製,替換上述字串即可。
而我們MQTT的功能實現,則替換以下函式相應的傳參字元即可。
const char *topics[] = {"test"}; //主題
BD_TG_Subscribe(topics,1); //訂閱主題,數量 1
BD_TG_Publish(*topics, "MQTT Publish Test"); //釋出的主題,釋出的訊息
MQTT_UnSubscribe(topics,1); //取消訂閱的主題,數量 1
對於MQTT基本的訂閱、釋出,修改上述引數即可完成。
其他功能,則需要根據組包函式的說明,修改相應傳參。
上述的程式碼,均是www.w5100s.com內17.MQTT_BDTG例程內的,該例程已經過實測,可正常連線百度天工雲平臺,實現MQTT訂閱、釋出等相關功能。
W5100S目前已經到貨,煒世已經正式調通並將配套的資料例程補充完畢。
相關資料煒世已經整理上傳至www.w5100s.com網址內,歡迎各位前往瀏覽。
WIZnet W5100S技術交流群:579842114,群內有“大神”為大家答疑解惑。
後續我將會陸續釋出關於W5100S各類功能測試博文,有興趣的朋友歡迎關注。
煒世是WIZnet的的的官方代理商,W5100S可提供模組/評估板供客戶測試。
如需詳細資料/樣品申請/技術支援等,歡迎與我們聯絡。
煒世為客戶提供全程的技術支援與優異的價格優勢。
電話:0755-86568556
QQ:2571856470