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

审核编辑:符乾江

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 物联网
    +关注

    关注

    2836

    文章

    38979

    浏览量

    352813
  • STM32
    +关注

    关注

    2191

    文章

    10027

    浏览量

    344971
收藏 人收藏

    评论

    相关推荐

    esp8266设置为station透传模式

    STM32CubeMX ESP8266 AT指令实现MQTT协议并接入阿里云IOT平台源码解析【附Github源码地址】一、esp8266驱动我将esp8266设置为station透传模式
    发表于 08-10 08:02

    STM32+ESP8266+MQTT协议

    STM32+ESP8266+MQTT协议上传云平台(OneNET)
    发表于 09-08 07:21

    esp8266怎样通过MQTT协议连接阿里云

    STM32F103单片机应用WIFI模块esp8266通过MQTT协议连接阿里云:复制这段内容后打开百度网盘手机App,操作更方便哦–来自百度网盘超级会员V3的分享...
    发表于 11-26 08:24

    STM32+ESP8266+MQTT协议如何连接OneNet物联网平台

    STM32+ESP8266+MQTT协议如何连接OneNet物联网平台
    发表于 12-02 06:52

    如何去实现一种STM32F103ZE+ESP8266+腾讯云物联网平台+微信小程序设计

    STM32F103ZET6上网方式:采用ESP8266,也可以使用其他设备代替,只要支持TCP协议即可。比如:GSM模块、有线网卡等。与物联网云平台的通信协议:标准
    发表于 02-11 06:43

    怎样通过MQTT实现ESP8266与ONENET平台数据交互呢

    MQTT协议连接ONENET,实现ESP8266与ONENET平台数据交互。
    发表于 02-24 07:50

    stm32通过esp8266 AT命令连接阿里云物联网

    stm32通过esp8266 AT命令连接阿里云物联网。不引用库,自己写协议数据以便了解MQTT为方便调试,上位机的AT命令可以通过stm32发送给esp8266,1、先看效果依次发送AT命令
    发表于 03-30 14:01

    ESP32和ESP8266基于Arduino的MQTT收发资料说明

    ESP32和ESP8266基于Arduino的MQTT收发资料说明。
    发表于 01-24 08:00 102次下载
    <b>ESP</b>32和<b>ESP8266</b>基于Arduino的<b>MQTT</b>收发资料说明

    Esp8266(NodeMCU)连接阿里云服务器

    Esp8266【NodeMCU】连接阿里云服务器创建阿里云产品添加设备Esp8266代码MQTT_PASSWD密码生成工具修改PubSubClient.h文件(不修改无法连接Mqtt服务器)设备测试
    发表于 11-16 10:21 15次下载
    <b>Esp8266</b>(NodeMCU)<b>连接</b>阿里云服务器

    STM32 ES8266上阿里云IOT MQTT实践【第七章】:ESP8266+MQTT上阿里云物联网平台实践

    stm32接入阿里云IOT,WiFi模块为ESP8266,可以实现发布以及订阅。
    发表于 11-21 19:06 53次下载
    <b>STM32</b> ES<b>8266</b>上阿里云<b>IOT</b> <b>MQTT</b>实践【第七章】:<b>ESP8266+MQTT</b>上阿里云物联网<b>平台</b>实践

    Building a battery powered WiFi IoT Sensor with ESP8266, MS-5611 (GY-63), nodemcu and MQTT

    iot-sensor-with-esp8266-ms-5611-gy-63-nodemcu-and-mqtt/IntroductionThe ESP8266 is a 32 bit micro controller with an integrated
    发表于 12-17 18:01 5次下载
    Building a battery powered WiFi <b>IoT</b> Sensor with <b>ESP8266</b>, MS-5611 (GY-63), nodemcu and <b>MQTT</b>

    ESP8266通过MQTT协议连接ONENET

    ESP8266通过MQTT协议连接ONENET一、设计目标二、ONENET平台搭建三、硬件准备四、程序烧写五、ONENET平台控件配置     本文
    发表于 01-12 19:58 48次下载
    <b>ESP8266</b>通过<b>MQTT</b><b>协议</b><b>连接</b>ONENET

    使用esp8266实现STM32联网(最简单USART方法)

    esp8266STM32连接,电脑通过STM32配置esp8266实现联网发送数据具体流程如下图 2= esp8266怎么和STM32连接(引脚连
    发表于 11-22 11:51 1.1w次阅读

    STM32 + ESP8266 + MQTT协议连接OneNet

    STM32+ESP8266使用标准MQTT协议登录Onenet服务器,实现数据交互。
    的头像 发表于 02-28 13:22 1.6w次阅读
    <b>STM32</b> + <b>ESP8266</b> + <b>MQTT</b><b>协议</b><b>连接</b>OneNet

    如何用一个ESP8266加上STM32单片机做一个小产品?

    mqtt协议,为啥第二步要学习mqtt协议呢?因为我们esp8266是要连接服务器的,简单地说mqtt就是ESP8266与服务器之间的通信协议,这个协议不难,我已经写好了笔记到时候在这个公众号直接发布就可以了。
    的头像 发表于 07-05 15:50 3400次阅读