智慧农业: STM32F103ZE+ESP8266+腾讯云物联网平台+微信小程序设计

简介: 智慧农业: STM32F103ZE+ESP8266+腾讯云物联网平台+微信小程序设计

一、环境介绍

单片机采用:STM32F103ZET6


上网方式:采用ESP8266,也可以使用其他设备代替,只要支持TCP协议即可。比如:GSM模块、有线网卡等。


与物联网云平台的通信协议:  标准MQTT协议3.1.1(TCP)


开发软件:keil5


物联网平台: 腾讯IOT物联网物联网平台。腾讯的物联网平台比起其他厂家的物联网平台更加有优势,腾讯物联网平台可以将数据推到微信小程序上,用户可以直接使用小程序绑定设备,完成与设备之间交互,现在用户基本都会使用微信,所以使用起来非常方便。


本项目完整代码下载地址: https://download.csdn.net/download/xiaolong1126626497/18973282

image.png

image.png

image.png

image.png

image.png

二、智慧农业介绍

智慧农业就是将物联网技术运用到传统农业中去,运用传感器和软件通过移动平台或者电脑平台对农业生产进行控制,使传统农业更具有“智慧”。除 了精准感知、控制与决策管理外,从广泛意义上讲,智慧农业还包括农业电子商务、食品溯源防伪、农业休闲旅游、农业信息服务等方面的内容。

所谓“智慧农业”就是充分应用现代信息技术成果,集成应用计算机与网络技术、物联网技术、音视频技术、3S技术、无线通信技术及专家智慧与知识,实现农业可视化远程诊断、远程控制、灾变预警等智能管理。


智慧农业是农业生产的高级阶段,是集新兴的互联网、移动互联网、云计算和物联网技术为一体,依托部署在农业生产现场的各种传感节点(环境温湿度、土壤水分、二氧化碳、图像等)和无线通信网络实现农业生产环境的智能感知、智能预警、智能决策、智能分析、专家在线指导,为农业生产提供精准化种植、可视化管理、智能化决策。

“智慧农业”是云计算、传感网、3S等多种信息技术在农业中综合、全面的应用,实现更完备的信息化基础支撑、更透彻的农业信息感知、更集中的数据资源、更广泛的互联互通、更深入的智能控制、更贴心的公众服务。“智慧农业”与现代生物技术、种植技术等科学技术融合于一体,对建设世界水平农业具有重要意义。


  本项目采用STM32F103ZET6 + ESP8266 设计一个智慧农业管理系统, 能够获取空气中的温湿度数据,光照度数据等,根据种植区的空气温湿度数据,判断是否进行灌溉;可以通过ESP8266 + MQTT 协议将采集的温湿度、光照度上传至腾讯云物联网平台,并推送到微信小程序上实时查看;可以在小程序上直接控制电机抽水灌溉。


硬件详情介绍:


主控MCU:  STM32F103ZET6


环境光传感器: BH1750


温湿度传感器: SHT30


本地OLED显示屏:   中景园电子0.96寸 SPI接口 OLED显示屏


电机:  微型直流电机


三、创建腾讯云物联网平台设备并配置微信小程序

如果之前从来没有使用过腾讯云物联网平台,创建的详细步骤请看这里:  https://blog.csdn.net/xiaolong1126626497/article/details/116902653


下面就是登录腾讯云物联网平台,创建一个智慧农业的设备的关键步骤,有些细节步骤没写,细节请看上面链接这篇文章。


官网地址: https://console.cloud.tencent.com/iotexplorer

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

四、生成腾讯物联网平台的设备登录信息

使用MQTT协议登录需要一些参数信息,需要使用官网提供的方式生成。

image.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("6142CX41XE", "SmartAgriculture","20Y/aAcmj+y6SDDh+ANR9g=="))

输出的登录参数,用于MQTT协议填参数:

{'clientid': '6142CX41XESmartAgriculture', 'username': '6142CX41XESmartAgriculture;12010126;HUA2G;1624271589', 
'password': 'a8aadebe9721f70e6f9e14fe56ff1d2b5cac9625fa1f96af2f0e0098597fe78b;hmacsha256'}

五、使用MQTT软件测试

MQTT客户端软件下载地址: https://download.csdn.net/download/xiaolong1126626497/18784012


该软件采用QT开发,源码地址: https://blog.csdn.net/xiaolong1126626497/article/details/116779490

image.png

设备主题发布与定义的格式:

image.png

设备消息数据上传格式:

{"method":"report","clientToken":"123","params":{"light":78.4,"temperature":21.4,"humidity":60.8,"motor":1}}

登录成功之后,就可以看到设备在线:

image.png

打开微信小程序可以查看到设备上传的数据:

image.png

六、编写STM32设备端代码

image.png

image.png

6.1 main.c代码

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include "timer.h"
#include "esp8266.h"
#include "mqtt.h"
#include "oled.h"
#include "fontdata.h"
#include "bh1750.h"
#include "iic.h"
#include "sht3x.h"
/*
硬件连接方式:
ESP8266串口WIFI模块与STM32的串口3相连接。
PB10--RXD 模块接收脚
PB11--TXD 模块发送脚
GND---GND 地
VCC---VCC 电源(3.3V~5.0V)
OLED接线:
D0----SCK-----PB14
D1----MOSI----PB13
RES—复位(低电平有效)—PB12
DC---数据和命令控制管脚—PB1
CS---片选引脚-----PA7
微型直流电机:  PB8
紫光灯:        PB9
LED硬件连接: PB5 PE5
KEY硬件连接:PE3 PE4
*/
#define ESP8266_WIFI_AP_SSID  "CMCC-Cqvn"   //将要连接的路由器名称 --不要出现中文、空格等特殊字符
#define ESP8266_AP_PASSWORD "99pu58cb"     //将要连接的路由器密码
//腾讯物联网服务器的设备信息
#define MQTT_ClientID "6142CX41XESmartAgriculture"
#define MQTT_UserName "6142CX41XESmartAgriculture;12010126;HUA2G;1624271589"
#define MQTT_PassWord "a8aadebe9721f70e6f9e14fe56ff1d2b5cac9625fa1f96af2f0e0098597fe78b;hmacsha256"
//订阅与发布的主题
#define SET_TOPIC  "$thing/down/property/6142CX41XE/SmartAgriculture"  //订阅
#define POST_TOPIC "$thing/up/property/6142CX41XE/SmartAgriculture"  //发布
char mqtt_message[200];//上报数据缓存区
char OLED_ShowBuff[100];
u8 ESP8266_Stat=0;
/*
函数功能: 温湿度\光强度显示
*/
void ShowTemperatureAndHumidity(float temp,float humi,float light)
{
    sprintf(OLED_ShowBuff,"T: %.2f",temp);
  OLED_ShowString(40,16*0,16,OLED_ShowBuff); 
    sprintf(OLED_ShowBuff,"H: %.2f%%",humi);
  OLED_ShowString(40,16*1,16,OLED_ShowBuff);
    sprintf(OLED_ShowBuff,"L: %.2f%%",light);
  OLED_ShowString(40,16*2,16,OLED_ShowBuff); 
}
/*
函数功能: ESP8266显示页面
*/
void ESP8266_ShowPageTable(void)
{
    if(ESP8266_Stat)OLED_ShowString(0,16*0,16,"WIFI STAT:ERROR");
    else OLED_ShowString(0,16*0,16,"WIFI STAT:OK");
    //显示字符串
    sprintf((char*)OLED_ShowBuff,"%s",ESP8266_WIFI_AP_SSID);
    OLED_ShowString(0,16*1,16,OLED_ShowBuff); 
    sprintf((char*)OLED_ShowBuff,"%s",ESP8266_AP_PASSWORD);   
    OLED_ShowString(0,16*2,16,OLED_ShowBuff);    
}
int main()
{
   u32 time_cnt=0;
   u32 i;
   u8 key;
   u8 page=0;
   float temp=0;
   float humi=0;
   float light=0;
   u8 motor_state=0;
   float Humidity;
   float Temperature;
   delay_ms(1000);
   delay_ms(1000);
   LED_Init();
   KEY_Init();
   IIC_Init();
    //OLED初始化
   OLED_Init(0xc8,0xa1); //OLED显示屏初始化--正常显示;
     //清屏
   OLED_Clear(0);
   USART1_Init(115200);
   TIMER1_Init(72,20000); //超时时间20ms
   USART3_Init(115200);//串口-WIFI
   TIMER3_Init(72,20000); //超时时间20ms
   Init_SHT30();
   USART1_Printf("正在初始化WIFI请稍等.\n");
   if(ESP8266_Init())
   {
      ESP8266_Stat=1;
      USART1_Printf("ESP8266硬件检测错误.\n");  
   }
   else
   {
      //非加密端口
      USART1_Printf("WIFI:%d\n",ESP8266_STA_TCP_Client_Mode(ESP8266_WIFI_AP_SSID,ESP8266_AP_PASSWORD,"106.55.124.154",1883,1));
   }
    //2. MQTT协议初始化  
    MQTT_Init(); 
    //3. 连接腾讯云IOT服务器        
    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==1)
        {
            //清屏
            OLED_Clear(0);
            //翻页
            if(page>=1)
            {
                page=0;
            }
            else
            {
                 page++;
            }         
            LED1=!LED1;  //LEd状态灯
        }
        else if(key==2)
        {
            LED1=!LED1;  //LEd状态灯
            time_cnt=0;
            //电机状态改变
            MOTOR_DEV=!MOTOR_DEV;
            //电机状态
            motor_state=MOTOR_DEV;
            //补光灯
            LIGHT_DEV=!LIGHT_DEV;      
        }  
        //微信小程序开锁方式: 接收WIFI返回的数据
        if(USART3_RX_FLAG)
        {
            USART3_RX_BUFFER[USART3_RX_CNT]='\0';
            //向串口打印微信小程序返回的数据
            for(i=0;i<USART3_RX_CNT;i++)
            {
                USART1_Printf("%c",USART3_RX_BUFFER[i]);
            }
            //如果是下发了属性,判断是开锁还是关锁
            if(USART3_RX_CNT>5)
            {
                //使用字符串查找函数
                if(strstr((char*)&USART3_RX_BUFFER[5],"\"motor\":1"))
                {
                     LED1=0;  //亮灯
                     MOTOR_DEV=1; //开电机
                     motor_state=1;
                }
                else if(strstr((char*)&USART3_RX_BUFFER[5],"\"motor\":0"))
                {
                    LED1=1;  //灭灯
                    MOTOR_DEV=0; //关电机
                    motor_state=0;
                }
            }
            USART3_RX_CNT=0;
            USART3_RX_FLAG=0;
        }
        //定时与保持与微信小程序的同步--1秒一次
        delay_ms(10);
        time_cnt++;
        if(time_cnt==50)
        {
            time_cnt=0;
            //状态灯 --表示程序还活着
            LED2=!LED2;
            //读取光强度
            light=Read_BH1750_Data();
            //读取温湿度
            SHT3x_ReadData(&Humidity,&Temperature);
            humi=Humidity;
            temp=Temperature;
            //上传数据
             sprintf(mqtt_message,"{\"method\":\"report\",\"clientToken\":\"123\",\"params\":{\"temperature\":%f,\"humidity\":%f,\"motor\":%d,\"light\":%f}}",
            temp,humi,motor_state,light);
            MQTT_PublishData(POST_TOPIC,mqtt_message,0);
            //根据湿度自动灌溉
            if(humi<50.0)  //小于50自动灌溉
            {
                 motor_state=1; //电机状态更新
                 MOTOR_DEV=1;  //开电机
            } 
        }
        //OLED显示屏
        if(page==0)
        {
            ShowTemperatureAndHumidity(temp,humi,light);
        }
        else if(page==1)
        {
            ESP8266_ShowPageTable();
        }
    }
}

6.2 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<USART3_RX_CNT;i++)USART1_Printf("%#x ",USART3_RX_BUFFER[i]);
            USART3_RX_FLAG=0;
            USART3_RX_CNT=0;
        }
        //CONNECT
        if(mqtt_rxbuf[0]==parket_connetAck[0] && mqtt_rxbuf[1]==parket_connetAck[1]) //连接成功        
        {
            return 0;//连接成功
        }
    }
  return 1;
}
/*
函数功能: MQTT订阅/取消订阅数据打包函数
函数参数:
    topic       主题   
    qos         消息等级 0:最多分发一次  1: 至少分发一次  2: 仅分发一次
    whether     订阅/取消订阅请求包 (1表示订阅,0表示取消订阅)
返回值: 0表示成功 1表示失败
*/
u8 MQTT_SubscribeTopic(char *topic,u8 qos,u8 whether)
{    
    u8 i,j;
  mqtt_txlen=0;
    int topiclen = strlen(topic);
  int DataLen = 2 + (topiclen+2) + (whether?1:0);//可变报头的长度(2字节)加上有效载荷的长度
  //固定报头
  //控制报文类型
    if(whether)mqtt_txbuf[mqtt_txlen++] = 0x82; //消息类型和标志订阅
    else  mqtt_txbuf[mqtt_txlen++] = 0xA2;    //取消订阅
  //剩余长度
  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;     //消息标识符 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);
} 



相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
目录
相关文章
|
数据采集 小程序 物联网
微信小程序快速接入物联网平台|学习笔记
快速学习微信小程序快速接入物联网平台
1527 0
|
9月前
|
传感器
STM32+ESP8266+QT客户端上位机显示DHT11温湿度与点灯
STM32+ESP8266+QT客户端上位机显示DHT11温湿度与点灯
|
9月前
|
网络协议 网络架构
|
9月前
|
数据安全/隐私保护
Esp8266+阿里云+STM32点灯(二)
Esp8266+阿里云+STM32点灯(二)
|
9月前
|
开发工具
Esp8266+阿里云+STM32点灯(一)
Esp8266+阿里云+STM32点灯(一)
|
存储 JSON 移动开发
基于STM32+ESP8266的奥运会奖牌榜设计之经典
基于STM32+ESP8266的奥运会奖牌榜设计之经典
194 0
基于STM32+ESP8266的奥运会奖牌榜设计之经典
|
10月前
|
传感器 网络架构 智能硬件
STM32通过esp8266连接WiFi接入MQTT服务器
STM32通过esp8266连接WiFi接入MQTT服务器
573 1
|
11月前
|
传感器 数据采集 编解码
基于STM32的物联网环境监测系统
基于STM32的物联网环境监测系统
266 0
基于STM32的物联网环境监测系统

相关产品

  • 物联网平台