主頁 >  其他 > MQTT協議 STM32、ESP8266基于EMQ個人服務器——報文處理(1)

MQTT協議 STM32、ESP8266基于EMQ個人服務器——報文處理(1)

2021-07-27 08:56:33 其他

新人博主第一次寫blog,本文主要是對于MQTT協議報文和stm32的硬體、代碼層面進行講解,有不足的地方歡迎大家指正,

本人在學習MQTT協議時走了不少彎路,而且網路上對于STM32與MQTT通訊的資料少之又少,所以寫下本文供大家參考

前期準備

本次實驗材料主要有: STM32F103ZET6開發板/核心板+ESP8266開發板+n個led燈

上面這款ESP8266就可以,很方便使用

MQTT協議

基本原理

先講一下MQTT是怎么通訊的吧

MQTT共有3個角色和1個資料流:發布者(Publisher),訂閱者(Subscriber)、代理者(Broker)、主題(public)

相信大家都用過B站,我在這里做個比喻:b站用戶好比是訂閱者,up主是發布者,b站平臺是代理者

我們之間有這樣的關系:

我們先只看藍色部分就是一次MQTT通訊,up主發布視頻到視頻發布主題,b站服務器收到后通知用戶,

當然我們可以建立多個public進行雙向資料交流,互不干涉(筆者第一從想實作雙向通訊,當時只建立了一個主題,導致雙方的資料紊亂,大家記得避坑)

我們的STM32與EMQ服務器通訊也是同理,stm32(Pubilsher)與EMQ服務器的Websocket(Subscriber)同時訂閱一個主題,就可以實作將stm32資料傳輸到主題中,Websocket從主題中獲取資料

報文

由于報文內容太多,網路上的資料很詳細,這里不在詳細講解,想了解報文的同學可以移步mqtt報文決議—超詳細_不懂一休-CSDN博客_mqtt報文

筆者當時在學習報文的時候被搞得頭大,所以為了方便大家學習使用,在這里我們只講幾個簡單無腦常用的報文型別的寫法

CONNECT:

固定報頭:10 ??

此處?? 為剩余長度,即可變報頭長度+負載長度,通常是構建完可變報頭和負載才去計算的,舉個例子,如果剩余長度小于128,例如剩余長度=88,則此位為0x58,固定報頭為10 58 ,如果大于128,則固定報頭再加一個位元組為10 ?? ?? ,例如剩余長度為152,則第2位元組=152/128=1=0x01,第3位元組=152%128=24=0x18,固定報頭為 10 01 18,

ps:一定注意報文都是HEX(16進制)格式

可變報頭:00 04 4D 51 54 54 04 C2 00 64

負載報文:?? "客戶端ID" ?? "用戶名" ?? "密碼"

負載報文上的3個??分別為ID長度、用戶名長度、密碼長度,它們的計算方法與固定報頭中的剩余長度一樣,這里給大家舉一個簡單的例子

ID:123

用戶名:LOUIS

密碼:123456

則負載報文為:03 31 32 33 05 4C 4F 55 49 53 06 31 32 33 34 35 36

最終這個CONNECT報文就為:10 18 00 04 4D 51 54 54 04 C2 00 64 03 31 32 33 05 4C 4F 55 49 53 06 31 32 33 34 35 36

下面是connect報文資料的處理代碼

/*----------------------------------------------------------*/
/*函式名:連接服務器報文                                    */
/*參  數:無                                                */
/*回傳值:無                                                */
/*----------------------------------------------------------*/
void MQTT_ConectPack(void)
{	
	int temp,Remaining_len;
	
	Fixed_len = 1;                                                        //連接報文中,固定報頭長度暫時先=1
	Variable_len = 10;                                                    //連接報文中,可變報頭長度=10
	Payload_len = 2 + ClientID_len + 2 + Username_len + 2 + Passward_len; //連接報文中,負載長度      
	Remaining_len = Variable_len + Payload_len;                           //剩余長度=可變報頭長度+負載長度
	
	temp_buff[0]=0x10;                       //固定報頭第1個位元組 :固定0x01		
	do{                                      //回圈處理固定報頭中的剩余長度位元組,位元組量根據剩余位元組的真實長度變化
		temp = Remaining_len%128;            //剩余長度取余128
		Remaining_len = Remaining_len/128;   //剩余長度取整128
		if(Remaining_len>0)               	
			temp |= 0x80;                    //按協議要求位7置位          
		temp_buff[Fixed_len] = temp;         //剩余長度位元組記錄一個資料
		Fixed_len++;	                     //固定報頭總長度+1    
	}while(Remaining_len>0);                 //如果Remaining_len>0的話,再次進入回圈
	
	temp_buff[Fixed_len+0]=0x00;    //可變報頭第1個位元組 :固定0x00	            
	temp_buff[Fixed_len+1]=0x04;    //可變報頭第2個位元組 :固定0x04
	temp_buff[Fixed_len+2]=0x4D;	//可變報頭第3個位元組 :固定0x4D
	temp_buff[Fixed_len+3]=0x51;	//可變報頭第4個位元組 :固定0x51
	temp_buff[Fixed_len+4]=0x54;	//可變報頭第5個位元組 :固定0x54
	temp_buff[Fixed_len+5]=0x54;	//可變報頭第6個位元組 :固定0x54
	temp_buff[Fixed_len+6]=0x04;	//可變報頭第7個位元組 :固定0x04
	temp_buff[Fixed_len+7]=0xC2;	//可變報頭第8個位元組 :使能用戶名和密碼校驗,不使用遺囑,不保留會話
	temp_buff[Fixed_len+8]=0x00; 	//可變報頭第9個位元組 :保活時間高位元組 0x00
	temp_buff[Fixed_len+9]=0x64;	//可變報頭第10個位元組:保活時間高位元組 0x64   100s
	
	/*     CLIENT_ID      */
	temp_buff[Fixed_len+10] = ClientID_len/256;                			  			    //客戶端ID長度高位元組
	temp_buff[Fixed_len+11] = ClientID_len%256;               			  			    //客戶端ID長度低位元組
	memcpy(&temp_buff[Fixed_len+12],ClientID,ClientID_len);                 			//復制過來客戶端ID字串	
	/*     用戶名        */
	temp_buff[Fixed_len+12+ClientID_len] = Username_len/256; 				  		    //用戶名長度高位元組
	temp_buff[Fixed_len+13+ClientID_len] = Username_len%256; 				 		    //用戶名長度低位元組
	memcpy(&temp_buff[Fixed_len+14+ClientID_len],Username,Username_len);                //復制過來用戶名字串	
	/*      密碼        */
	temp_buff[Fixed_len+14+ClientID_len+Username_len] = Passward_len/256;			    //密碼長度高位元組
	temp_buff[Fixed_len+15+ClientID_len+Username_len] = Passward_len%256;			    //密碼長度低位元組
	memcpy(&temp_buff[Fixed_len+16+ClientID_len+Username_len],Passward,Passward_len);   //復制過來密碼字串

	TxDataBuf_Deal(temp_buff, Fixed_len + Variable_len + Payload_len);                  //加入發送資料緩沖區
}

Subscribe:

固定:82 ??(此處為剩余長度與connect同理計算)

可變:00 01

負載:?? "主題名" 00 (此處00為訂閱等級Qs0)(計算與connect負載同理)

/*----------------------------------------------------------*/
/*函式名:SUBSCRIBE訂閱topic報文                            */
/*參  數:QoS:訂閱等級                                     */
/*參  數:topic_name:訂閱topic報文名稱                     */
/*回傳值:無                                                */
/*----------------------------------------------------------*/
void MQTT_Subscribe(char *topic_name, int QoS)
{	
	Fixed_len = 2;                              //SUBSCRIBE報文中,固定報頭長度=2
	Variable_len = 2;                           //SUBSCRIBE報文中,可變報頭長度=2	
	Payload_len = 2 + strlen(topic_name) + 1;   //計算有效負荷長度 = 2位元組(topic_name長度)+ topic_name字串的長度 + 1位元組服務等級
	
	temp_buff[0]=0x82;                                    //第1個位元組 :固定0x82                      
	temp_buff[1]=Variable_len + Payload_len;              //第2個位元組 :可變報頭+有效負荷的長度	
	temp_buff[2]=0x00;                                    //第3個位元組 :報文識別符號高位元組,固定使用0x00
	temp_buff[3]=0x01;		                              //第4個位元組 :報文識別符號低位元組,固定使用0x01
	temp_buff[4]=strlen(topic_name)/256;                  //第5個位元組 :topic_name長度高位元組
	temp_buff[5]=strlen(topic_name)%256;		          //第6個位元組 :topic_name長度低位元組
	memcpy(&temp_buff[6],topic_name,strlen(topic_name));  //第7個位元組開始 :復制過來topic_name字串		
	temp_buff[6+strlen(topic_name)]=QoS;                  //最后1個位元組:訂閱等級
	
	TxDataBuf_Deal(temp_buff, Fixed_len + Variable_len + Payload_len);  //加入發送資料緩沖區
}

PING:

固定:C0 00

/*----------------------------------------------------------*/
/*函式名:PING報文,心跳包                                  */
/*參  數:無                                                */
/*回傳值:無                                                */
/*----------------------------------------------------------*/
void MQTT_PingREQ(void)
{
	temp_buff[0]=0xC0;              //第1個位元組 :固定0xC0                      
	temp_buff[1]=0x00;              //第2個位元組 :固定0x00 

	TxDataBuf_Deal(temp_buff, 2);   //加入資料到緩沖區
}

Publish:

固定:30 ??

可變:?? "主題名"

??為主題名的長度

負載:?? "要發送的資料"

??為資料的長度

/*----------------------------------------------------------*/
/*函式名:等級0 發布訊息報文                                */
/*參  數:topic_name:topic名稱                             */
/*參  數:data:資料                                        */
/*參  數:data_len:資料長度                                */
/*回傳值:無                                                */
/*----------------------------------------------------------*/
void MQTT_PublishQs0(char *topic, char *data, int data_len)
{	
	int temp,Remaining_len;
	
	Fixed_len = 1;                              //固定報頭長度暫時先等于:1位元組
	Variable_len = 2 + strlen(topic);           //可變報頭長度:2位元組(topic長度)+ topic字串的長度
	Payload_len = data_len;                     //有效負荷長度:就是data_len
	Remaining_len = Variable_len + Payload_len; //剩余長度=可變報頭長度+負載長度
	
	temp_buff[0]=0x30;                       //固定報頭第1個位元組 :固定0x30   	
	do{                                      //回圈處理固定報頭中的剩余長度位元組,位元組量根據剩余位元組的真實長度變化
		temp = Remaining_len%128;            //剩余長度取余128
		Remaining_len = Remaining_len/128;   //剩余長度取整128
		if(Remaining_len>0)               	
			temp |= 0x80;                    //按協議要求位7置位          
		temp_buff[Fixed_len] = temp;         //剩余長度位元組記錄一個資料
		Fixed_len++;	                     //固定報頭總長度+1    
	}while(Remaining_len>0);                 //如果Remaining_len>0的話,再次進入回圈
		             
	temp_buff[Fixed_len+0]=strlen(topic)/256;                      //可變報頭第1個位元組     :topic長度高位元組
	temp_buff[Fixed_len+1]=strlen(topic)%256;		               //可變報頭第2個位元組     :topic長度低位元組
	memcpy(&temp_buff[Fixed_len+2],topic,strlen(topic));           //可變報頭第3個位元組開始 :拷貝topic字串	
	memcpy(&temp_buff[Fixed_len+2+strlen(topic)],data,data_len);   //有效負荷:拷貝data資料
	
	TxDataBuf_Deal(temp_buff, Fixed_len + Variable_len + Payload_len);  //加入發送資料緩沖區
}

處理Publisher發送的命令,筆者這里用的是EMQ個人服務器所以Publisher發的報文相對簡單

只有長度+資料的格式

下面是對收到的資料的處理

*----------------------------------------------------------*/
/*函式名:處理服務器發來的等級0的推送                       */
/*參  數:redata:接收的資料                                */
/*回傳值:無                                                */
/*----------------------------------------------------------*/
void MQTT_DealPushdata_Qs0(unsigned char *redata)
{
	int  re_len;               	           //定義一個變數,存放接收的資料總長度
	int  pack_num;                         //定義一個變數,當多個推送一起過來時,保存推送的個數
    int  temp,temp_len;                    //定義一個變數,暫存資料
    int  totle_len;                        //定義一個變數,存放已經統計的推送的總資料量
	int  topic_len;              	       //定義一個變數,存放推送中主題的長度
	int  cmd_len;                          //定義一個變數,存放推送中包含的命令資料的長度
	int  cmd_loca;                         //定義一個變數,存放推送中包含的命令的起始位置
	int  i;                                //定義一個變數,用于for回圈
	int  local,multiplier;
	unsigned char tempbuff[RBUFF_UNIT];	   //臨時緩沖區
	unsigned char *data;                   //redata過來的時候,第一個位元組是資料總量,data用于指向redata的第2個位元組,真正的資料開始的地方
		
	re_len = redata[0]*256+redata[1];                               //獲取接收的資料總長度		
	data = &redata[2];                                              //data指向redata的第2個位元組,真正的資料開始的 
	pack_num = temp_len = totle_len = temp = 0;                	    //各個變數清零
	local = 1;
	multiplier = 1;
	do{
		pack_num++;                                     			//開始回圈統計推送的個數,每次回圈推送的個數+1	
		do{
			temp = data[totle_len + local];   
			temp_len += (temp & 127) * multiplier;
			multiplier *= 128;
			local++;
		}while ((temp & 128) != 0);
		totle_len += (temp_len + local);                          	//累計統計的總的推送的資料長度
		re_len -= (temp_len + local) ;                              //接收的資料總長度 減去 本次統計的推送的總長度      
		local = 1;
		multiplier = 1;
		temp_len = 0;
	}while(re_len!=0);                                  			//如果接收的資料總長度等于0了,說明統計完畢了
	u1_printf("本次接收了%d個推送資料\r\n",pack_num);//串口輸出資訊
	temp_len = totle_len = 0;                		            	//各個變數清零
	local = 1;
	multiplier = 1;
	for(i=0;i<pack_num;i++){                                        //已經統計到了接收的推送個數,開始for回圈,取出每個推送的資料 		
		do{
			temp = data[totle_len + local];   
			temp_len += (temp & 127) * multiplier;
			multiplier *= 128;
			local++;
		}while ((temp & 128) != 0);				
		topic_len = data[local+totle_len]*256+data[local+1+totle_len] + 2;    //計算本次推送資料中主題占用的資料量
		cmd_len = temp_len-topic_len;                               //計算本次推送資料中命令資料占用的資料量
		cmd_loca = totle_len + local +  topic_len;                  //計算本次推送資料中命令資料開始的位置
		memcpy(tempbuff,&data[cmd_loca],cmd_len);                   //命令資料拷貝出來		                 
		CMDBuf_Deal(tempbuff, cmd_len);                             //加入命令到緩沖區
		totle_len += (temp_len+local);                              //累計已經統計的推送的資料長度
		local = 1;
		multiplier = 1;
		temp_len = 0;
	}	
}

初始化

下面是各部分緩沖區初始化,及上面函式中變數的相關定義

#include "stm32f10x.h"    
#include "mqtt.h"         
#include "string.h"      
#include "stdio.h"       
#include "usart1.h"         
#include "wifi.h"         

unsigned char  MQTT_RxDataBuf[R_NUM][RBUFF_UNIT];           //資料的接識訓沖區,所有服務器發來的資料,存放在該緩沖區,緩沖區第一個位元組存放資料長度
unsigned char *MQTT_RxDataInPtr;                            //指向接識訓沖區存放資料的位置
unsigned char *MQTT_RxDataOutPtr;                           //指向接識訓沖區讀取資料的位置
unsigned char *MQTT_RxDataEndPtr;                           //指向接識訓沖區結束的位置

unsigned char  MQTT_TxDataBuf[T_NUM][TBUFF_UNIT];           //資料的發送緩沖區,所有發往服務器的資料,存放在該緩沖區,緩沖區第一個位元組存放資料長度
unsigned char *MQTT_TxDataInPtr;                            //指向發送緩沖區存放資料的位置
unsigned char *MQTT_TxDataOutPtr;                           //指向發送緩沖區讀取資料的位置
unsigned char *MQTT_TxDataEndPtr;                           //指向發送緩沖區結束的位置

unsigned char  MQTT_CMDBuf[C_NUM][CBUFF_UNIT];              //命令資料的接識訓沖區
unsigned char *MQTT_CMDInPtr;                               //指向命令緩沖區存放資料的位置
unsigned char *MQTT_CMDOutPtr;                              //指向命令緩沖區讀取資料的位置
unsigned char *MQTT_CMDEndPtr;                              //指向命令緩沖區結束的位置

char ClientID[128];                                          //存放客戶端ID的緩沖區
int  ClientID_len;                                           //存放客戶端ID的長度

char Username[128];                                          //存放用戶名的緩沖區
int  Username_len;											 //存放用戶名的長度

char Passward[128];                                          //存放密碼的緩沖區
int  Passward_len;											 //存放密碼的長度

char ServerIP[128];                                          //存放服務器IP或是域名
int  ServerPort;                                             //存放服務器的埠號

int   Fixed_len;                       					     //固定報頭長度
int   Variable_len;                     					 //可變報頭長度
int   Payload_len;                       					 //有效負荷長度
unsigned char  temp_buff[TBUFF_UNIT];						 //臨時緩沖區,構建報文用

char Ping_flag;           //ping報文狀態      0:正常狀態,等待計時時間到,發送Ping報文
                          //ping報文狀態      1:Ping報文已發送,當收到 服務器回復報文的后 將1置為0
char Connect_flag;        //同服務器連接狀態  0:還沒有連接服務器  1:連接上服務器了
char ConnectPack_flag;    //CONNECT報文狀態   1:CONNECT報文成功
char SubcribePack_flag;   //訂閱報文狀態      1:訂閱報文成功

/*----------------------------------------------------------*/
/*函式名:初始化接收,發送,命令資料的 緩沖區 以及各狀態引數  */
/*參  數:無                                                */
/*回傳值:無                                                */
/*----------------------------------------------------------*/
void MQTT_Buff_Init(void)
{	
	MQTT_RxDataInPtr=MQTT_RxDataBuf[0];               //指向發送緩沖區存放資料的指標歸位
	MQTT_RxDataOutPtr=MQTT_RxDataInPtr;               //指向發送緩沖區讀取資料的指標歸位
    MQTT_RxDataEndPtr=MQTT_RxDataBuf[R_NUM-1];        //指向發送緩沖區結束的指標歸位
	
	MQTT_TxDataInPtr=MQTT_TxDataBuf[0];               //指向發送緩沖區存放資料的指標歸位
	MQTT_TxDataOutPtr=MQTT_TxDataInPtr;               //指向發送緩沖區讀取資料的指標歸位
	MQTT_TxDataEndPtr=MQTT_TxDataBuf[T_NUM-1];        //指向發送緩沖區結束的指標歸位
	
	MQTT_CMDInPtr=MQTT_CMDBuf[0];                     //指向命令緩沖區存放資料的指標歸位
	MQTT_CMDOutPtr=MQTT_CMDInPtr;                     //指向命令緩沖區讀取資料的指標歸位
	MQTT_CMDEndPtr=MQTT_CMDBuf[C_NUM-1];              //指向命令緩沖區結束的指標歸位

    MQTT_ConectPack();                                //發送緩沖區添加連接報文
	MQTT_Subscribe(S_TOPIC_NAME,0);	                  //發送緩沖區添加訂閱topic,等級0	
	
	Ping_flag = ConnectPack_flag = SubcribePack_flag = 0;  //各個引數清零
}
/*----------------------------------------------------------*/
/*函式名:云初始化引數,得到客戶端ID,用戶名和密碼          */
/*參  數:無                                                */
/*回傳值:無                                                */
/*----------------------------------------------------------*/
void IoT_Parameter_Init(void)
{	
	memset(ClientID,128,0);                              //客戶端ID的緩沖區全部清零
	sprintf(ClientID,"%s",DEVICEID);                     //構建客戶端ID,并存入緩沖區
	ClientID_len = strlen(ClientID);                     //計算客戶端ID的長度
	
	memset(Username,128,0);                              //用戶名的緩沖區全部清零
	sprintf(Username,"%s",PRODUCTID);                    //構建用戶名,并存入緩沖區
	Username_len = strlen(Username);                     //計算用戶名的長度
	
	memset(Passward,128,0);                              //用戶名的緩沖區全部清零
	sprintf(Passward,"%s",AUTHENTICATION);               //構建密碼,并存入緩沖區
	Passward_len = strlen(Passward);                     //計算密碼的長度
	
	memset(ServerIP,0,128);  
	sprintf(ServerIP,"%s","39.104.27.119");              //構建服務器域名
	ServerPort = 1883;                                    //服務器埠號1883
	
	u1_printf("服 務 器:%s:%d\r\n",ServerIP,ServerPort); //串口輸出除錯資訊
	u1_printf("客戶端ID:%s\r\n",ClientID);               //串口輸出除錯資訊
	u1_printf("用 戶 名:%s\r\n",Username);               //串口輸出除錯資訊
	u1_printf("密    碼:%s\r\n",Passward);               //串口輸出除錯資訊
}
/*----------------------------------------------------------*/
/*函式名:處理發送緩沖區                                    */
/*參  數:data:資料                                        */
/*參  數:size:資料長度                                    */
/*回傳值:無                                                */
/*----------------------------------------------------------*/
void TxDataBuf_Deal(unsigned char *data, int size)
{
	memcpy(&MQTT_TxDataInPtr[2],data,size);      //拷貝資料到發送緩沖區	
	MQTT_TxDataInPtr[0] = size/256;              //記錄資料長度
	MQTT_TxDataInPtr[1] = size%256;              //記錄資料長度
	MQTT_TxDataInPtr+=TBUFF_UNIT;                 //指標下移
	if(MQTT_TxDataInPtr==MQTT_TxDataEndPtr)      //如果指標到緩沖區尾部了
		MQTT_TxDataInPtr = MQTT_TxDataBuf[0];    //指標歸位到緩沖區開頭
}
/*----------------------------------------------------------*/
/*函式名:處理命令緩沖區                                    */
/*參  數:data:資料                                        */
/*參  數:size:資料長度                                    */
/*回傳值:無                                                */
/*----------------------------------------------------------*/
void CMDBuf_Deal(unsigned char *data, int size)
{
	memcpy(&MQTT_CMDInPtr[2],data,size);      //拷貝資料到命令緩沖區
	MQTT_CMDInPtr[0] = size/256;              //記錄資料長度
	MQTT_CMDInPtr[1] = size%256;              //記錄資料長度
	MQTT_CMDInPtr[size+2] = '\0';             //加入字串結束符
	MQTT_CMDInPtr+=CBUFF_UNIT;                 //指標下移
	if(MQTT_CMDInPtr==MQTT_CMDEndPtr)         //如果指標到緩沖區尾部了
		MQTT_CMDInPtr = MQTT_CMDBuf[0];       //指標歸位到緩沖區開頭
}

頭檔案

為了方便大家使用代碼筆者順便把mqtt頭檔案貼出來吧

#ifndef __MQTT_H
#define __MQTT_H

#define  R_NUM               5     //接識訓沖區個數
#define  RBUFF_UNIT          300   //接識訓沖區長度

#define  T_NUM               5     //發送緩沖區個數  
#define  TBUFF_UNIT          300   //發送緩沖區長度

#define  C_NUM               5     //命令緩沖區個數
#define  CBUFF_UNIT          300   //命令緩沖區長度

#define  MQTT_TxData(x)       u2_TxData(x)                                         //串口2負責資料發送

#define  PRODUCTID            "Car001"                                      //ID
#define  PRODUCTID_LEN        strlen(PRODUCTID)                             //ID長度
#define  DEVICEID             "OurIoT"                                      //用戶名  
#define  DEVICEID_LEN         strlen(DEVICEID)                              //用戶名長度
#define  AUTHENTICATION       "000000"                                      //密碼 
#define  AUTHENTICATION_LEN    strlen(AUTHENTICATION)                       //密碼長度
#define  S_TOPIC_NAME         "t/c"                                   //需要訂閱的主題  
#define  P_TOPIC_NAME         "t/v"                                   //需要發布的主題  

extern unsigned char  MQTT_RxDataBuf[R_NUM][RBUFF_UNIT];       //外部變數宣告,資料的接識訓沖區,所有服務器發來的資料,存放在該緩沖區,緩沖區第一個位元組存放資料長度
extern unsigned char *MQTT_RxDataInPtr;                        //外部變數宣告,指向緩沖區存放資料的位置
extern unsigned char *MQTT_RxDataOutPtr;                       //外部變數宣告,指向緩沖區讀取資料的位置
extern unsigned char *MQTT_RxDataEndPtr;                       //外部變數宣告,指向緩沖區結束的位置
extern unsigned char  MQTT_TxDataBuf[T_NUM][TBUFF_UNIT];       //外部變數宣告,資料的發送緩沖區,所有發往服務器的資料,存放在該緩沖區,緩沖區第一個位元組存放資料長度
extern unsigned char *MQTT_TxDataInPtr;                        //外部變數宣告,指向緩沖區存放資料的位置
extern unsigned char *MQTT_TxDataOutPtr;                       //外部變數宣告,指向緩沖區讀取資料的位置
extern unsigned char *MQTT_TxDataEndPtr;                       //外部變數宣告,指向緩沖區結束的位置
extern unsigned char  MQTT_CMDBuf[C_NUM][CBUFF_UNIT];          //外部變數宣告,命令資料的接識訓沖區
extern unsigned char *MQTT_CMDInPtr;                           //外部變數宣告,指向緩沖區存放資料的位置
extern unsigned char *MQTT_CMDOutPtr;                          //外部變數宣告,指向緩沖區讀取資料的位置
extern unsigned char *MQTT_CMDEndPtr;                          //外部變數宣告,指向緩沖區結束的位置

extern char ClientID[128];     //外部變數宣告,存放客戶端ID的緩沖區
extern int  ClientID_len;      //外部變數宣告,存放客戶端ID的長度
extern char Username[128];     //外部變數宣告,存放用戶名的緩沖區
extern int  Username_len;	   //外部變數宣告,存放用戶名的長度
extern char Passward[128];     //外部變數宣告,存放密碼的緩沖區
extern int  Passward_len;	   //外部變數宣告,存放密碼的長度
extern char ServerIP[128];     //外部變數宣告,存放服務器IP或是域名
extern int  ServerPort;        //外部變數宣告,存放服務器的埠號

extern char Ping_flag;         //外部變數宣告,ping報文狀態      0:正常狀態,等待計時時間到,發送Ping報文
                               //外部變數宣告,ping報文狀態      1:Ping報文已發送,當收到 服務器回復報文的后 將1置為0
extern char Connect_flag;      //外部變數宣告,同服務器連接狀態  0:還沒有連接服務器  1:連接上服務器了
extern char ReConnect_flag;    //外部變數宣告,重連服務器狀態    0:連接還存在  1:連接斷開,重連
extern char ConnectPack_flag;  //外部變數宣告,CONNECT報文狀態   1:CONNECT報文成功
extern char SubcribePack_flag; //外部變數宣告,訂閱報文狀態      1:訂閱報文成功

void MQTT_Buff_Init(void);
void IoT_Parameter_Init(void);
void MQTT_ConectPack(void);
void MQTT_Subscribe(char *, int);
void MQTT_PingREQ(void);
void MQTT_PublishQs0(char *, char *, int);
void MQTT_DealPushdata_Qs0(unsigned char *);	
void TxDataBuf_Deal(unsigned char *, int);
void CMDBuf_Deal(unsigned char *, int);

#endif

本節主要講解了報文的資料發送處理,之后會更新esp8266如何連接mqtt服務器,以及stm32對服務器命令的相關處理,最終實作服務器控制點燈,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/290361.html

標籤:其他

上一篇:真實世界中的網路與圖模型

下一篇:圖形繪制——pygame之旅

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more