吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

STM32 + ESP8266 + MQTT協議連接騰訊IOT平臺

DS小龍哥-嵌入式技術 ? 來源:DS小龍哥-嵌入式技術 ? 作者:DS小龍哥-嵌入式技 ? 2022-02-28 13:28 ? 次閱讀

?

一、環境介紹

單片機采用:STM32F103C8T6

上網方式:采用ESP8266,也可以使用其他設備代替,只要支持TCP協議即可。比如:GSM模塊、有線網卡等。

開發軟件:keil5

物聯網平臺: 騰訊IOT物聯網物聯網平臺。騰訊的物聯網平臺比起其他廠家的物聯網平臺更加有優勢,騰訊物聯網平臺可以將數據推到微信小程序上,用戶可以直接使用小程序綁定設備,完成與設備之間交互,現在用戶基本都會使用微信,所以使用起來非常方便。

二、功能介紹

本文章接下會介紹如何在騰訊物聯網平臺上創建設備、配置設備、推送到微信小程序、并編寫STM32設備端代碼,使用ESP8266聯網登錄騰訊物聯網平臺,完成數據交互。

功能: STM32采集環境溫度、濕度、光照強度實時上傳至物聯網平臺,在微信小程序頁面上,用戶可以實時查看這些數據,并且可以通過界面上的按鈕控制設備端的電機LED燈的開關,完成數據上傳和遠程控制。

說明: STM32設備端所有代碼均有自己全部編寫,沒有使用任何廠家的SDK,MQTT協議也是參考MQTT官方文檔編寫;ESP8266也沒有使用任何專用固件,所以代碼的移植性非常高。 任何能夠聯網的設備都可以參考本篇文章代碼連接騰訊物聯網平臺,達到相同的效果。

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

三、登錄騰訊物聯網平臺創建設備

騰訊云官網:騰訊云 - 產業智變 云啟未來

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

下面是手機上的截圖:操作過程

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

現在設備是離線狀態,是無法查看的,接下來就使用MQTT客戶端模擬設備,登錄測試。

四、使用MQTT客戶端模擬設備--測試

4.1 下載MQTT客戶端

MQTT客戶端可執行文件下載地址(.exe): MQTT客戶端_v2.4(協議3.1.1).exe_stc15單片機+esp8266+騰訊連連小程序(三)-桌面系統文檔類資源-CSDN下載

這個MQTT客戶端采用QT開發,如果需要了解它的源碼,請看這里:QT應用編程: 編寫MQTT客戶端登錄OnetNet服務器完成主題訂閱與發布_DS小龍哥的專欄-CSDN博客_onenet topic訂閱與發布

4.2 查看物聯網平臺端口號與域名(IP地址)

官方文檔:物聯網通信 設備基于 TCP 的 MQTT 接入 - 開發者手冊 - 文檔中心 - 騰訊云

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

通過這里得到信息: 如果是廣州域的設備(其實哪里都一樣,只是服務器距離的遠近),就填入 <產品ID>.iotcloud.tencentdevices.com ,端口號是 1883(這是密匙認證的端口號,如果是證書認證就是另一個)。

查看產品ID的方法:

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

得打產品ID之后,那么要連接我的設備,域名就填:8O76VHCU7Y.iotcloud.tencentdevices.com 端口就填: 1883

由于我的測試用的MQTT客戶端不支持域名輸入,只支持IP地址輸入,所有我這里需要先將域名轉為IP地址在進行下面的測試,ESP8266內部支持域名解析的,所有可以直接輸入域名即可,不需要做這一步。

在線解析域名的網址:ip地址查詢 ip查詢 查ip 公網ip地址歸屬地查詢 網站ip查詢 同ip網站查詢 iP反查域名 iP查域名 同ip域名

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

得到廣州騰訊云的IP地址為: 106.55.124.154

4.3 生成MQTT登錄參數

就像我們登錄QQ、登錄微信需要賬號密碼一樣,設備登錄物聯網平臺也需要類似的東西。

官方文檔地址:物聯網通信 設備基于 TCP 的 MQTT 接入 - 開發者手冊 - 文檔中心 - 騰訊云

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

?

上面需要的參數,在設備調試頁面,點擊具體的設備進行查看:

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

Python源代碼:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import base64
import hashlib
import hmac
import random
import string
import time
import sys
# 生成指定長度的隨機字符串
def RandomConnid(length):
    return  ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(length))
# 生成接入物聯網通信平臺需要的各參數
def IotHmac(productID, devicename, devicePsk):
     # 1. 生成 connid 為一個隨機字符串,方便后臺定位問題
     connid   = RandomConnid(5)
     # 2. 生成過期時間,表示簽名的過期時間,從紀元1970年1月1日 00:00:00 UTC 時間至今秒數的 UTF8 字符串
     expiry   = int(time.time()) + 30*24*60 * 60
     # 3. 生成 MQTT 的 clientid 部分, 格式為 ${productid}${devicename}
     clientid = "{}{}".format(productID, devicename)
     # 4. 生成 MQTT 的 username 部分, 格式為 ${clientid};${sdkappid};${connid};${expiry}
     username = "{};12010126;{};{}".format(clientid, connid, expiry)
     # 5. 對 username 進行簽名,生成token
     secret_key = devicePsk.encode('utf-8')  # convert to bytes
     data_to_sign = username.encode('utf-8')  # convert to bytes
     secret_key = base64.b64decode(secret_key)  # this is still bytes
     token = hmac.new(secret_key, data_to_sign, digestmod=hashlib.sha256).hexdigest()
     # 6. 根據物聯網通信平臺規則生成 password 字段
     password = "{};{}".format(token, "hmacsha256")
     return {
        "clientid" : clientid,
        "username" : username,
        "password" : password
     }
if __name__ == '__main__':
    # 參數分別填入: 產品ID,設備名稱,設備密匙
    print(IotHmac("8O76VHCU7Y","SmartAgriculture","OHXqYLklNBU4xLqqoZbXMQ=="))
poYBAGDYdXCAWkKMAAAAK8RNs4s030.pngpoYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

得到的登錄信息如下:

clientid: 8O76VHCU7YSmartAgriculture
username: 8O76VHCU7YSmartAgriculture;12010126;J4MCD;1623766532
password: a962b484079864239148b255281d54372aa66247aa8d6259d11aa6fef650fd5b;hmacsha256
poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

4.4 了解主題上報和訂閱的格式

登錄之前需要先了解如何訂閱設備的主題和上報的數據流格式。

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

如果設備端想要得到APP頁面的按鈕狀態就需要訂閱屬性下發和屬性上報的響應,主題格式就是這樣的:

格式:
$thing/down/property/8O76VHCU7Y/設備名稱
示例:
$thing/down/property/8O76VHCU7Y/SmartAgriculture
poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

如果設備端想要像APP頁面上傳數據,那么就需要使用屬性上報--發布主題:

格式:
$thing/up/property/8O76VHCU7Y/${deviceName}
示例:
$thing/up/property/8O76VHCU7Y/SmartAgriculture
poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

設備端向APP頁面上報屬性時,需要上傳具體的數據,數據流的格式如下:

官方文檔: 物聯網開發平臺 物模型協議 - 云端開發指南 - 文檔中心 - 騰訊云

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

比如: 我的產品里有溫度、濕度、電機三個設備,我可以選擇一次上傳3個設備的信息,數據格式就這樣寫:

{"method":"report","clientToken":"123","params":{"temperature":20.23,"humidity":50,"Motor":1}}
poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

其中:"temperature"、"humidity"、"Motor" 是設備的標識符,根據自己的情況修改,冒號后面就是給這個設備上傳的具體數據。

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

4.5使用MQTT客戶端登錄設備測試

萬事俱備,下面就使用MQTT客戶端進行登錄測試。

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

MQTT客戶端操作步驟:

1. 填寫相關參數

2. 點擊登錄

3. 訂閱主題

4. 發布主題

5. 去APP頁面查看信息

4.6 微信小程序效果

已經收到MQTT客戶端上傳的數據,點擊按鈕,MQTT客戶端也會收到按鈕下發的數據。

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

五、STM32設備端代碼

本文章配套使用的STM32設備端完整源代碼下載地址: STM32+MQTT協議連接騰訊物聯網平臺_完成主題訂閱與發布(MQTT).zip_騰訊物聯網平臺-桌面系統文檔類資源-CSDN下載

5.1 下載程序

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.pngpoYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

5.2 連接狀態

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

?

STM32設備上按下按鍵后,手機打開微信小程序可以看到實時上傳的數據,速度非常快。

5.3 main.c文件

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include 
#include "timer.h"
#include "bluetooth.h"
#include "esp8266.h"
#include "mqtt.h"

//騰訊物聯網服務器的設備信息
#define MQTT_ClientID "8O76VHCU7YSmartAgriculture"
#define MQTT_UserName "8O76VHCU7YSmartAgriculture;12010126;J4MCD;1623766532"
#define MQTT_PassWord "a962b484079864239148b255281d54372aa66247aa8d6259d11aa6fef650fd5b;hmacsha256"

//訂閱與發布的主題
#define SET_TOPIC  "$thing/down/property/8O76VHCU7Y/SmartAgriculture"  //訂閱
#define POST_TOPIC "$thing/up/property/8O76VHCU7Y/SmartAgriculture"  //發布

char mqtt_message[200];//上報數據緩存區

int main()
{
   u32 time_cnt=0;
   u32 i;
   u8 key;
   LED_Init();
   BEEP_Init();
   KEY_Init();
   USART1_Init(115200);
   TIMER1_Init(72,20000); //超時時間20ms
   USART2_Init(9600);//串口-藍牙
   TIMER2_Init(72,20000); //超時時間20ms
   USART3_Init(115200);//串口-WIFI
   TIMER3_Init(72,20000); //超時時間20ms
   USART1_Printf("正在初始化WIFI請稍等.\n");
   if(ESP8266_Init())
   {
      USART1_Printf("ESP8266硬件檢測錯誤.\n");  
   }
   else
   {
      //加密端口
      //USART1_Printf("WIFI:%d\n",ESP8266_STA_TCP_Client_Mode("OnePlus5T","1126626497","183.230.40.16",8883,1));
      
      //非加密端口
      USART1_Printf("WIFI:%d\n",ESP8266_STA_TCP_Client_Mode("CMCC-Cqvn","99pu58cb","106.55.124.154",1883,1));
  
   }
   
    //2. MQTT協議初始化	
    MQTT_Init(); 
    //3. 連接OneNet服務器        
    while(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord))
    {
        USART1_Printf("服務器連接失敗,正在重試...\n");
        delay_ms(500);
    }
    USART1_Printf("服務器連接成功.\n");
    
    //3. 訂閱主題
    if(MQTT_SubscribeTopic(SET_TOPIC,0,1))
    {
        USART1_Printf("主題訂閱失敗.\n");
    }
    else
    {
        USART1_Printf("主題訂閱成功.\n");
    }        
    
    while(1)
    {    
        key=KEY_Scan(0);
        if(key==2)
        {
            time_cnt=0;
            sprintf(mqtt_message,"{"method":"report","clientToken":"123","params":{"temperature":20.23,"humidity":50,"Motor":1}}");
            MQTT_PublishData(POST_TOPIC,mqtt_message,0);
            USART1_Printf("發送狀態1\r\n");
        }
        else if(key==3)
        {
            time_cnt=0;
            sprintf(mqtt_message,"{"method":"report","clientToken":"123","params":{"temperature":10.23,"humidity":60,"Motor":0}}");
            MQTT_PublishData(POST_TOPIC,mqtt_message,0);
            USART1_Printf("發送狀態0\r\n");
        }  

        if(USART3_RX_FLAG)
        {
            USART3_RX_BUFFER[USART3_RX_CNT]='\0';
            for(i=0;i
poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

5.4 mqtt.c

#include "mqtt.h"

u8 *mqtt_rxbuf;
u8 *mqtt_txbuf;
u16 mqtt_rxlen;
u16 mqtt_txlen;
u8 _mqtt_txbuf[256];//發送數據緩存區
u8 _mqtt_rxbuf[256];//接收數據緩存區

typedef enum
{
	//名字 	    值 			報文流動方向 	描述
	M_RESERVED1	=0	,	//	禁止	保留
	M_CONNECT		,	//	客戶端到服務端	客戶端請求連接服務端
	M_CONNACK		,	//	服務端到客戶端	連接報文確認
	M_PUBLISH		,	//	兩個方向都允許	發布消息
	M_PUBACK		,	//	兩個方向都允許	QoS 1消息發布收到確認
	M_PUBREC		,	//	兩個方向都允許	發布收到(保證交付第一步)
	M_PUBREL		,	//	兩個方向都允許	發布釋放(保證交付第二步)
	M_PUBCOMP		,	//	兩個方向都允許	QoS 2消息發布完成(保證交互第三步)
	M_SUBSCRIBE		,	//	客戶端到服務端	客戶端訂閱請求
	M_SUBACK		,	//	服務端到客戶端	訂閱請求報文確認
	M_UNSUBSCRIBE	,	//	客戶端到服務端	客戶端取消訂閱請求
	M_UNSUBACK		,	//	服務端到客戶端	取消訂閱報文確認
	M_PINGREQ		,	//	客戶端到服務端	心跳請求
	M_PINGRESP		,	//	服務端到客戶端	心跳響應
	M_DISCONNECT	,	//	客戶端到服務端	客戶端斷開連接
	M_RESERVED2		,	//	禁止	保留
}_typdef_mqtt_message;

//連接成功服務器回應 20 02 00 00
//客戶端主動斷開連接 e0 00
const u8 parket_connetAck[] = {0x20,0x02,0x00,0x00};
const u8 parket_disconnet[] = {0xe0,0x00};
const u8 parket_heart[] = {0xc0,0x00};
const u8 parket_heart_reply[] = {0xc0,0x00};
const u8 parket_subAck[] = {0x90,0x03};

void MQTT_Init(void)
{
    //緩沖區賦值
	mqtt_rxbuf = _mqtt_rxbuf;
    mqtt_rxlen = sizeof(_mqtt_rxbuf);
	mqtt_txbuf = _mqtt_txbuf;
    mqtt_txlen = sizeof(_mqtt_txbuf);
	memset(mqtt_rxbuf,0,mqtt_rxlen);
	memset(mqtt_txbuf,0,mqtt_txlen);
	
	//無條件先主動斷開
	MQTT_Disconnect();
    delay_ms(100);
	MQTT_Disconnect();
    delay_ms(100);
}

/*
函數功能: 登錄服務器
函數返回值: 0表示成功 1表示失敗
*/
u8 MQTT_Connect(char *ClientID,char *Username,char *Password)
{
    u8 i,j;
    int ClientIDLen = strlen(ClientID);
    int UsernameLen = strlen(Username);
    int PasswordLen = strlen(Password);
    int DataLen;
	mqtt_txlen=0;
	//可變報頭+Payload  每個字段包含兩個字節的長度標識
    DataLen = 10 + (ClientIDLen+2) + (UsernameLen+2) + (PasswordLen+2);
	
	//固定報頭
	//控制報文類型
    mqtt_txbuf[mqtt_txlen++] = 0x10;		//MQTT Message Type CONNECT
	//剩余長度(不包括固定頭部)
	do
	{
		u8 encodedByte = DataLen % 128;
		DataLen = DataLen / 128;
		// if there are more data to encode, set the top bit of this byte
		if ( DataLen > 0 )
			encodedByte = encodedByte | 128;
		mqtt_txbuf[mqtt_txlen++] = encodedByte;
	}while ( DataLen > 0 );
    	
	//可變報頭
	//協議名
    mqtt_txbuf[mqtt_txlen++] = 0;        	// Protocol Name Length MSB    
    mqtt_txbuf[mqtt_txlen++] = 4;           // Protocol Name Length LSB    
    mqtt_txbuf[mqtt_txlen++] = 'M';        	// ASCII Code for M    
    mqtt_txbuf[mqtt_txlen++] = 'Q';        	// ASCII Code for Q    
    mqtt_txbuf[mqtt_txlen++] = 'T';        	// ASCII Code for T    
    mqtt_txbuf[mqtt_txlen++] = 'T';        	// ASCII Code for T    
	//協議級別
    mqtt_txbuf[mqtt_txlen++] = 4;        		// MQTT Protocol version = 4   對于 3.1.1 版協議,協議級別字段的值是 4(0x04)   
	//連接標志
    mqtt_txbuf[mqtt_txlen++] = 0xc2;        	// conn flags 
    mqtt_txbuf[mqtt_txlen++] = 0;        		// Keep-alive Time Length MSB    
    mqtt_txbuf[mqtt_txlen++] = 100;        	// Keep-alive Time Length LSB  100S心跳包    保活時間
	
    mqtt_txbuf[mqtt_txlen++] = BYTE1(ClientIDLen);// Client ID length MSB    
    mqtt_txbuf[mqtt_txlen++] = BYTE0(ClientIDLen);// Client ID length LSB  	
	memcpy(&mqtt_txbuf[mqtt_txlen],ClientID,ClientIDLen);
    mqtt_txlen += ClientIDLen;
    
    if(UsernameLen > 0)
    {   
        mqtt_txbuf[mqtt_txlen++] = BYTE1(UsernameLen);		//username length MSB    
        mqtt_txbuf[mqtt_txlen++] = BYTE0(UsernameLen);    	//username length LSB    
		memcpy(&mqtt_txbuf[mqtt_txlen],Username,UsernameLen);
        mqtt_txlen += UsernameLen;
    }
    
    if(PasswordLen > 0)
    {    
        mqtt_txbuf[mqtt_txlen++] = BYTE1(PasswordLen);		//password length MSB    
        mqtt_txbuf[mqtt_txlen++] = BYTE0(PasswordLen);    	//password length LSB  
		memcpy(&mqtt_txbuf[mqtt_txlen],Password,PasswordLen);
        mqtt_txlen += PasswordLen; 
    }    
	
  
    memset(mqtt_rxbuf,0,mqtt_rxlen);
    MQTT_SendBuf(mqtt_txbuf,mqtt_txlen);
    for(j=0;j<10;j++)
    {
        delay_ms(50);
        if(USART3_RX_FLAG)
        {
            memcpy((char *)mqtt_rxbuf,USART3_RX_BUFFER,USART3_RX_CNT);
            
            //memcpy
           
             for(i=0;i 0 )
			encodedByte = encodedByte | 128;
		mqtt_txbuf[mqtt_txlen++] = encodedByte;
	}while ( DataLen > 0 );	
	
	//可變報頭
    mqtt_txbuf[mqtt_txlen++] = 0;			//消息標識符 MSB
    mqtt_txbuf[mqtt_txlen++] = 0x0A;        //消息標識符 LSB
	//有效載荷
    mqtt_txbuf[mqtt_txlen++] = BYTE1(topiclen);//主題長度 MSB
    mqtt_txbuf[mqtt_txlen++] = BYTE0(topiclen);//主題長度 LSB   
	memcpy(&mqtt_txbuf[mqtt_txlen],topic,topiclen);
    mqtt_txlen += topiclen;
    
    if(whether)
    {
       mqtt_txbuf[mqtt_txlen++] = qos;//QoS級別
    }
    
    for(i=0;i<10;i++)
    {
        memset(mqtt_rxbuf,0,mqtt_rxlen);
		MQTT_SendBuf(mqtt_txbuf,mqtt_txlen);
        for(j=0;j<10;j++)
        {
            delay_ms(50);
            if(USART3_RX_FLAG)
			{
                memcpy((char *)mqtt_rxbuf,(char*)USART3_RX_BUFFER,USART3_RX_CNT);
				USART3_RX_FLAG=0;
				USART3_RX_CNT=0;
			}
			
			if(mqtt_rxbuf[0]==parket_subAck[0] && mqtt_rxbuf[1]==parket_subAck[1]) //訂閱成功			   
			{
				return 0;//訂閱成功
			}
        }
    }
	return 1; //失敗
}

//MQTT發布數據打包函數
//topic   主題 
//message 消息
//qos     消息等級 
u8 MQTT_PublishData(char *topic, char *message, u8 qos)
{  
    int topicLength = strlen(topic);    
    int messageLength = strlen(message);     
    static u16 id=0;
	int DataLen;
	mqtt_txlen=0;
	//有效載荷的長度這樣計算:用固定報頭中的剩余長度字段的值減去可變報頭的長度
	//QOS為0時沒有標識符
	//數據長度             主題名   報文標識符   有效載荷
    if(qos)	DataLen = (2+topicLength) + 2 + messageLength;       
    else	DataLen = (2+topicLength) + messageLength;   

    //固定報頭
	//控制報文類型
    mqtt_txbuf[mqtt_txlen++] = 0x30;    // MQTT Message Type PUBLISH  

	//剩余長度
	do
	{
		u8 encodedByte = DataLen % 128;
		DataLen = DataLen / 128;
		// if there are more data to encode, set the top bit of this byte
		if ( DataLen > 0 )
			encodedByte = encodedByte | 128;
		mqtt_txbuf[mqtt_txlen++] = encodedByte;
	}while ( DataLen > 0 );	
	
    mqtt_txbuf[mqtt_txlen++] = BYTE1(topicLength);//主題長度MSB
    mqtt_txbuf[mqtt_txlen++] = BYTE0(topicLength);//主題長度LSB 
	memcpy(&mqtt_txbuf[mqtt_txlen],topic,topicLength);//拷貝主題
    mqtt_txlen += topicLength;
        
	//報文標識符
    if(qos)
    {
        mqtt_txbuf[mqtt_txlen++] = BYTE1(id);
        mqtt_txbuf[mqtt_txlen++] = BYTE0(id);
        id++;
    }
	memcpy(&mqtt_txbuf[mqtt_txlen],message,messageLength);
    mqtt_txlen += messageLength;
        
	MQTT_SendBuf(mqtt_txbuf,mqtt_txlen);
    return mqtt_txlen;
}

void MQTT_SentHeart(void)
{
	MQTT_SendBuf((u8 *)parket_heart,sizeof(parket_heart));
}

void MQTT_Disconnect(void)
{
	MQTT_SendBuf((u8 *)parket_disconnet,sizeof(parket_disconnet));
}

void MQTT_SendBuf(u8 *buf,u16 len)
{
	USARTx_DataSend(USART3,buf,len);
}	
poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

本文章配套使用的STM32設備端完整源代碼下載地址: https://download.csdn.net/download/xiaolong1126626497/18785807

STM32+ESP8266使用MQTT協議連接OneNET 中國移動物聯網開發平臺:https://blog.csdn.net/xiaolong1126626497/article/details/107385118

STM32+ESP8266使用MQTT協議連接阿里云物聯網開發平臺:https://blog.csdn.net/xiaolong1126626497/article/details/107311897

審核編輯:符乾江

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 物聯網
    +關注

    關注

    2914

    文章

    44939

    瀏覽量

    377094
  • STM32
    +關注

    關注

    2272

    文章

    10924

    瀏覽量

    357604
收藏 人收藏

    評論

    相關推薦

    esp8266連接阿里云平臺mqtt連接超時

    esp8266nodemcu在使用arduino.ide連接阿里云平臺的時候,wifi配置正常但連接不上mqtt,顯示報錯如下: Attem
    發表于 10-26 21:39

    ESP8266 太空人動畫的 OLED 顯示

    ESP8266 太空人動畫的 OLED 顯示
    的頭像 發表于 10-08 15:06 ?342次閱讀
    <b class='flag-5'>ESP8266</b> 太空人動畫的 OLED 顯示

    ESP8266 通過 MQTT 協議實現 LED 的遠程控制

    本文簡要介紹了搭建 EMQX 服務器實現基于 MQTT 協議遠程控制 NodeMCU ESP8266 板載 LED 的解決方案。
    的頭像 發表于 09-25 09:11 ?2214次閱讀
    <b class='flag-5'>ESP8266</b> 通過 <b class='flag-5'>MQTT</b> <b class='flag-5'>協議</b>實現 LED 的遠程控制

    STM32 ESP8266阿里云鏈接源碼

    stm32F103C8T6 ESP8266 物聯網電表 登錄阿里云
    發表于 08-29 14:21 ?6次下載

    esp32和esp8266代碼共用嗎

    本文將介紹ESP32和ESP8266兩款流行的微控制器在代碼共用性方面的可能性與差異性。 一、引言 隨著物聯網技術的飛速發展,越來越多的智能設備開始進入我們的生活。其中,ESP32和ESP82
    的頭像 發表于 08-19 18:23 ?1432次閱讀

    esp8266esp32區別是什么

    以下是關于ESP8266ESP32的主要區別: 處理器和架構 : ESP8266 :使用一個Tensilica L106 80MHz的處理器,屬于Xtensa架構。 ESP32 :使
    的頭像 發表于 08-19 18:16 ?5979次閱讀

    esp8266不燒錄可以使用嗎

    ,可以方便地與其他硬件設備進行連接。 2. ESP8266的硬件特性 處理器 :Tensilica L106,最高頻率160MHz 內存 :64KB SRAM,1MB Flash Wi-Fi :支持802.11 b/g/n協議
    的頭像 發表于 08-19 17:28 ?1006次閱讀

    esp8266wifi模塊怎么連接手機

    ESP8266 WiFi模塊連接手機主要可以通過兩種方式實現: 通過路由器連接(STA模式)和直接作為熱點連接(AP模式) 。以下是兩種連接
    的頭像 發表于 08-19 17:27 ?3591次閱讀

    ESP8266作Client建立TCP連接出現報錯?

    請教下,ESP8266作Client建立TCP連接,出現錯誤 是按照《4B-ESP8266__AT Command Examples__CN_v1.3》文檔上操作的 AT+CIPSTART
    發表于 07-17 07:16

    ESP8266 IoT_Demo行不通的原因?

    的開發板在 AI Thinker 的引導下無限閃爍。 以下是日志: al@pc:~/Desktop/sdk_201_esp8266/sdk/IoT_Demo$ esptool.py --port /dev
    發表于 07-11 08:13

    求助,請問如何在RTOS SDK 1.5的PlatformIO IDE ESP8266實現MQTT

    ESP8266設備連接mqtt 代理。但 PlatformIO IDE 內置的 RTOS SDK 1.5 版本不支持 mqtt。此 SDK 沒有
    發表于 07-08 06:22

    國產低成本Wi-Fi SoC解決方案芯片ESP8266ESP8285對比差異

    ESP8266ESP8285對比差異 ESP8285相當于在ESP8266基礎上多加了1/2MB Flash, ESP8285與
    的頭像 發表于 05-17 11:44 ?1515次閱讀
    國產低成本Wi-Fi SoC解決方案芯片<b class='flag-5'>ESP8266</b>與<b class='flag-5'>ESP</b>8285對比差異

    確定ESP8266固件下載成功的方法

    在物聯網設備的開發過程中,確定esp8266固件是否成功下載至設備十分關鍵。以下是一種簡單有效的確認方法:機智云物聯網平臺首先,確保你的ESP8266模塊已經正確連接至計算機,并通過串
    的頭像 發表于 05-16 08:10 ?693次閱讀
    確定<b class='flag-5'>ESP8266</b>固件下載成功的方法

    使用Wi-Fi ESP8266方案模組接入云平臺

    ESP8266的模塊芯片是基于無線通信協議的UARTWi-Fi透傳模塊芯片,支持802.11b/g/n的無線標準,并帶有三種可選擇的工作模式。ESP8266模塊的控制是通過AT指令的形式控制,例如
    的頭像 發表于 05-10 08:20 ?1938次閱讀
    使用Wi-Fi <b class='flag-5'>ESP8266</b>方案模組接入云<b class='flag-5'>平臺</b>

    STM32ESP8266MQTT連接阿里云物聯網的串口通信異常解析

    STM32ESP8266MQTT協議連接阿里云物聯網平臺時常見的串口通信異常介紹 在構建物聯
    的頭像 發表于 04-19 17:19 ?1567次閱讀
    包赢百家乐官网的玩法技巧和规则| 定远县| 百家乐最好的投注方法| 百家乐官网稳一点的押法| 威尼斯人娱乐网网上百家乐的玩法技巧和规则| 粤港澳百家乐官网娱乐场| 大发扑克娱乐场| 百家乐布| 真人百家乐官网对决| 澳门体育博彩| 基础百家乐规则| 欧洲百家乐官网的玩法技巧和规则| 姚记娱乐城官网| 百家乐庄闲和的倍数| 破战百家乐官网的玩法技巧和规则| 百家乐必胜| 网上百家乐公| 百家乐真钱棋牌| 百家乐官网作弊知识| 利记娱乐场| 赌博百家乐官网的玩法技巧和规则 | 一筒百家乐的玩法技巧和规则| 凯斯百家乐官网的玩法技巧和规则| 百家乐官网怎么对冲打| 大发888怎么玩能赢| 百家乐计划| KTV百家乐官网的玩法技巧和规则 王子百家乐官网的玩法技巧和规则 | 百家乐官网赌场策略大全| 旧金山百家乐的玩法技巧和规则| 百家乐代理占成| 怎么赌百家乐官网能赢| 百家乐官网路单之我见| 网上娱乐城开户| 威尼斯人娱乐城备用网| 太阳城百家乐如何看路| 大发百家乐官网的玩法技巧和规则| 怎么玩百家乐官网网上赌博| 双柏县| 六合彩现场开奖结果| 大发888怎么申请账号| 百家乐走势图备用网站|