STM32 + ESP8266 + MQTT协议连接腾讯IOT平台

发布时间:2024-09-06  

一、环境介绍

单片机采用: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的方法:

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.png


得到的登录信息如下:

clientid: 8O76VHCU7YSmartAgriculture

username: 8O76VHCU7YSmartAgriculture;12010126;J4MCD;1623766532

password: a962b484079864239148b255281d54372aa66247aa8d6259d11aa6fef650fd5b;hmacsha256


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}}


其中:'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:%dn',ESP8266_STA_TCP_Client_Mode('OnePlus5T','1126626497','183.230.40.16',8883,1));

      

      //非加密端口

      USART1_Printf('WIFI:%dn',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('发送状态1rn');

        }

        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('发送状态0rn');

        }  


        if(USART3_RX_FLAG)

        {

            USART3_RX_BUFFER[USART3_RX_CNT]='�';

            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

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>