Smart Agriculture: STM32F103ZE+ESP8266 + Tencent cloud Internet of things platform + wechat applet design

Posted by duall on Mon, 10 Jan 2022 10:48:16 +0100

1, Environment introduction

Single chip microcomputer: STM32F103ZET6

Internet access mode: ESP8266 can be used, or other devices can be used instead, as long as TCP protocol is supported. For example: GSM module, wired network card, etc.

Communication protocol with Internet of things cloud platform: Standard MQTT protocol 3.1.1(TCP)

Development software: keil5

Internet of things platform: Tencent IOT Internet of things platform. Tencent's Internet of things platform has more advantages than other manufacturers' Internet of things platforms. Tencent's Internet of things platform can push data to wechat applets. Users can directly use applets to bind devices and complete interaction with devices. Now users basically use wechat, so it is very convenient to use.

Download address of complete code of the project: https://download.csdn.net/download/xiaolong1126626497/18973282

2, Introduction to smart agriculture

Smart agriculture is to apply Internet of things technology to traditional agriculture, use sensors and software to control agricultural production through mobile platform or computer platform, so as to make traditional agriculture more "smart". In addition to precise perception, control and decision-making management, in a broad sense, smart agriculture also includes agricultural e-commerce, food traceability and anti-counterfeiting, agricultural leisure tourism, agricultural information services, etc. The so-called "smart agriculture" is to make full use of the achievements of modern information technology, integrate and apply computer and network technology, Internet of things technology, audio and video technology, 3S technology, wireless communication technology and expert wisdom and knowledge, and realize intelligent management such as agricultural visual remote diagnosis, remote control and disaster early warning.

Smart agriculture is an advanced stage of agricultural production. It integrates emerging Internet, mobile Internet, cloud computing and Internet of things technologies, and relies on various sensor nodes (environmental temperature and humidity, soil moisture, carbon dioxide, image, etc.) and wireless communication networks deployed on the agricultural production site to realize the intelligent perception, intelligent early warning, intelligent decision-making of the agricultural production environment Intelligent analysis and expert online guidance provide precision planting, visual management and intelligent decision-making for agricultural production. "Smart agriculture" is a comprehensive and comprehensive application of cloud computing, sensor network, 3S and other information technologies in agriculture to achieve more complete information-based support, more thorough agricultural information perception, more centralized data resources, wider interconnection, deeper intelligent control and more intimate public services. The integration of "smart agriculture" with modern biotechnology, planting technology and other science and technology is of great significance to the construction of world-class agriculture.

The project uses STM32F103ZET6 + ESP8266 to design an intelligent agricultural management system, which can obtain the temperature and humidity data and illumination data in the air, and judge whether to carry out irrigation according to the air temperature and humidity data in the planting area; The collected temperature, humidity and illumination can be uploaded to Tencent cloud Internet of things platform through ESP8266 + MQTT protocol and pushed to wechat applet for real-time viewing; The motor pumping irrigation can be directly controlled on the applet.

Hardware details:

Main control MCU: stm32f103zet6

Ambient light sensor: BH1750

Temperature and humidity sensor: SHT30

Local OLED display: zhongjingyuan electronics 0.96-inch SPI interface OLED display

Motor: micro DC motor

3, Create Tencent cloud Internet of things platform equipment and configure wechat applet

If you have never used Tencent cloud Internet of things platform before, please see the detailed steps of creation here: https://blog.csdn.net/xiaolong1126626497/article/details/116902653

The following are the key steps to log in to Tencent cloud Internet of things platform and create a smart agriculture device. Some details are not written. Please see the link above for details.

Official website address: https://console.cloud.tencent.com/iotexplorer

4, Generate the device login information of Tencent Internet of things platform

Logging in using MQTT protocol requires some parameter information, which needs to be generated in the way provided on the official website.

Python sample code:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import base64
import hashlib
import hmac
import random
import string
import time
import sys
# Generates a random string of the specified length
def RandomConnid(length):
    return  ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(length))
# Generate parameters required for accessing the Internet of things communication platform
def IotHmac(productID, devicename, devicePsk):
     # 1. Generate connid as a random string to facilitate background positioning
     connid   = RandomConnid(5)
     # 2. Generate expiration time, which represents the expiration time of the signature. It is a UTF8 string in seconds from 00:00:00 UTC time on January 1, 1970
     expiry   = int(time.time()) + 30*24*60 * 60
     # 3. Generate the clientid part of MQTT in the format ${productid}${devicename}
     clientid = "{}{}".format(productID, devicename)
     # 4. Generate the username part of MQTT in the format of ${ClientID}$ {sdkappid};$ {connid};$ {expiry}
     username = "{};12010126;{};{}".format(clientid, connid, expiry)
     # 5. Sign the username and generate a 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. Generate the password field according to the rules of the Internet of things communication platform
     password = "{};{}".format(token, "hmacsha256")
     return {
        "clientid" : clientid,
        "username" : username,
        "password" : password
     }
if __name__ == '__main__':
    # The parameters are filled in respectively: Product ID, equipment name and equipment key
    print(IotHmac("6142CX41XE", "SmartAgriculture","20Y/aAcmj+y6SDDh+ANR9g=="))

The output login parameters are used for MQTT protocol parameters:

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

5, Test with MQTT software

MQTT client software download address: https://download.csdn.net/download/xiaolong1126626497/18784012

The software is developed by QT. The source code address is: https://blog.csdn.net/xiaolong1126626497/article/details/116779490

Format of equipment theme publishing and definition:

Device message data upload format:

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

After successful login, you can see that the device is online:

Open wechat applet to view the data uploaded by the device:

6, Write STM32 device side code

6.1 main.c code

#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"

/*
Hardware connection mode:

ESP8266 The serial WIFI module is connected with serial port 3 of STM32.
PB10--RXD Module receiving pin
PB11--TXD Module sending pin
GND---GND land
VCC---VCC Power supply (3.3V~5.0V)

OLED Wiring:
D0----SCK-----PB14
D1----MOSI----PB13
RES—Reset (active low) - PB12
DC---Data and command control pin - PB1
CS---Chip selection pin ----- PA7

Micro DC motor: PB8
 Purple light: PB9

LED Hardware connection: PB5 PE5
KEY Hardware connection: PE3 PE4
*/

#define ESP8266_ WIFI_ AP_ SSID "CMCC cqvn" / / the name of the router to be connected -- do not appear Chinese, spaces and other special characters
#define ESP8266_AP_PASSWORD "99pu58cb" / / password of the router to be connected


//Equipment information of Tencent Internet of things server
#define MQTT_ClientID "6142CX41XESmartAgriculture"
#define MQTT_UserName "6142CX41XESmartAgriculture;12010126;HUA2G;1624271589"
#define MQTT_PassWord "a8aadebe9721f70e6f9e14fe56ff1d2b5cac9625fa1f96af2f0e0098597fe78b;hmacsha256"

//Topics for subscriptions and publications
#define SET_ Topic "$thing / down / property / 6142cx41xe / smartagriculture" / / subscription
#define POST_TOPIC "$thing/up/property/6142CX41XE/SmartAgriculture" / / release


char mqtt_message[200];//Report data buffer
char OLED_ShowBuff[100];
u8 ESP8266_Stat=0;


/*
Function: temperature and humidity \ light intensity display
*/
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); 
}

/*
Function function: ESP8266 display page
*/
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");

    //display string
    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 initialization
   OLED_Init(0xc8,0xa1); //OLED display initialization - normal display;
     //Clear screen
   OLED_Clear(0);
    
   USART1_Init(115200);
   TIMER1_Init(72,20000); //Timeout 20ms

   USART3_Init(115200);//Serial WIFI
   TIMER3_Init(72,20000); //Timeout 20ms
    
   Init_SHT30();
    
   USART1_Printf("Initializing WIFI One moment please.\n");
   
   if(ESP8266_Init())
   {
      ESP8266_Stat=1;
      USART1_Printf("ESP8266 Hardware detection error.\n");  
   }
   else
   {
      //Unencrypted port
      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 protocol initialization	
    MQTT_Init(); 
   
    //3. Connect to Tencent cloud IOT server        
    while(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord))
    {
        USART1_Printf("Server connection failed,Retrying...\n");
        delay_ms(500);
    }
    USART1_Printf("Server connection succeeded.\n");
    
    
    //3. Subscribe to topics
    if(MQTT_SubscribeTopic(SET_TOPIC,0,1))
    {
        USART1_Printf("Topic subscription failed.\n");
    }
    else
    {
        USART1_Printf("Topic subscription succeeded.\n");
    }        
        
    while(1)
    {    
        //Press the key to test unlocking and locking
        key=KEY_Scan(0);
        if(key==1)
        {
            //Clear screen
            OLED_Clear(0);
            
            //Turn pages
            if(page>=1)
            {
                page=0;
            }
            else
            {
                 page++;
            }         
        
            LED1=!LED1;  //LEd status light
        }
        else if(key==2)
        {
            LED1=!LED1;  //LEd status light
            time_cnt=0;
            //Motor status change
            MOTOR_DEV=!MOTOR_DEV;
            //Motor status
            motor_state=MOTOR_DEV;
            //fill-in light
            LIGHT_DEV=!LIGHT_DEV;      
        }  
        
        //Unlocking mode of wechat applet: receive the data returned by WIFI
        if(USART3_RX_FLAG)
        {
            USART3_RX_BUFFER[USART3_RX_CNT]='\0';
            
            //Print the data returned by wechat applet to the serial port
            for(i=0;i<USART3_RX_CNT;i++)
            {
                USART1_Printf("%c",USART3_RX_BUFFER[i]);
            }
            
            //If the attribute is issued, judge whether to unlock or close the lock
            if(USART3_RX_CNT>5)
            {
                //Use string lookup function
                if(strstr((char*)&USART3_RX_BUFFER[5],"\"motor\":1"))
                {
                     LED1=0;  //Light up
                     MOTOR_DEV=1; //Turn on the motor
                     motor_state=1;
                }
                else if(strstr((char*)&USART3_RX_BUFFER[5],"\"motor\":0"))
                {
                    LED1=1;  //Lights out
                    MOTOR_DEV=0; //Turn off the motor
                    motor_state=0;
                }
            }
           
            USART3_RX_CNT=0;
            USART3_RX_FLAG=0;
        }
              
        //Timing and keeping synchronization with wechat applet -- once a second
        delay_ms(10);
        time_cnt++;
        if(time_cnt==50)
        {
            time_cnt=0;
            
            //Status light -- indicates that the program is still alive
            LED2=!LED2;
            
            //Read light intensity
            light=Read_BH1750_Data();
           
            //Read temperature and humidity
            SHT3x_ReadData(&Humidity,&Temperature);
            humi=Humidity;
            temp=Temperature;
            
            //Upload data
             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);
            //Automatic irrigation according to humidity
            if(humi<50.0)  //Less than 50 automatic irrigation
            {
                 motor_state=1; //Motor status update
                 MOTOR_DEV=1;  //Turn on the motor
            } 
        }
         
        //OLED display
        if(page==0)
        {
            ShowTemperatureAndHumidity(temp,humi,light);
        }
        else if(page==1)
        {
            ESP8266_ShowPageTable();
        }
    }
}

6.2 mqtt.c code

#include "mqtt.h"

u8 *mqtt_rxbuf;
u8 *mqtt_txbuf;
u16 mqtt_rxlen;
u16 mqtt_txlen;
u8 _mqtt_txbuf[256];//Send data buffer
u8 _mqtt_rxbuf[256];//Receive data buffer

typedef enum
{
	//name 	     Value 			 Message flow direction 	 describe
	M_RESERVED1	=0	,	//	prohibit 	 retain
	M_CONNECT		,	//	Client to server 	 The client requests to connect to the server
	M_CONNACK		,	//	Server to client 	 Connection message confirmation
	M_PUBLISH		,	//	Both directions are allowed 	 Release news
	M_PUBACK		,	//	Both directions are allowed 	 QoS 1 message publishing receipt confirmation
	M_PUBREC		,	//	Both directions are allowed 	 Release received (first step of guaranteed delivery)
	M_PUBREL		,	//	Both directions are allowed 	 Release release (the second step of guaranteed delivery)
	M_PUBCOMP		,	//	Both directions are allowed 	 QoS 2 message publishing is completed (the third step of ensuring interaction)
	M_SUBSCRIBE		,	//	Client to server 	 Client subscription request
	M_SUBACK		,	//	Server to client 	 Subscription request message confirmation
	M_UNSUBSCRIBE	,	//	Client to server 	 Client unsubscribe request
	M_UNSUBACK		,	//	Server to client 	 Unsubscribe message confirmation
	M_PINGREQ		,	//	Client to server 	 Heartbeat request
	M_PINGRESP		,	//	Server to client 	 Heartbeat response
	M_DISCONNECT	,	//	Client to server 	 Client disconnect
	M_RESERVED2		,	//	prohibit 	 retain
}_typdef_mqtt_message;

//Connection succeeded. The server responded 20 02 00 00
//Client actively disconnects 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)
{
    //Buffer assignment
	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);
	
	//Unconditional active disconnection
	MQTT_Disconnect();
    delay_ms(100);
	MQTT_Disconnect();
    delay_ms(100);
}

/*
Function function: login server
 Function return value: 0 means success, 1 means failure
*/
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;
	//Variable header + Payload each field contains a two byte length identifier
    DataLen = 10 + (ClientIDLen+2) + (UsernameLen+2) + (PasswordLen+2);
	
	//Fixed header
	//Control message type
    mqtt_txbuf[mqtt_txlen++] = 0x10;		//MQTT Message Type CONNECT
	//Remaining length (excluding fixed head)
	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 );
    	
	//Variable header
	//Protocol name
    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    
	//Protocol level
    mqtt_txbuf[mqtt_txlen++] = 4;        		// MQTT Protocol version = 4 for version 3.1.1 protocol, the value of the protocol level field is 4(0x04)   
	//Connection flag
    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 heartbeat packet keep alive time
	
    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]) //Connection succeeded			   
        {
            return 0;//Connection succeeded
        }
    }
    
	return 1;
}

/*
Function function: MQTT subscription / unsubscribe data packaging function
 Function parameters:
    topic       theme   
    qos         Message level 0: distribute at most once 1: distribute at least once 2: distribute only once
    whether     Subscribe / unsubscribe request package (1 means subscribe, 0 means unsubscribe)
Return value: 0 indicates success, 1 indicates failure
*/
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);//The length of the variable header (2 bytes) plus the length of the payload
	//Fixed header
	//Control message type
    if(whether)mqtt_txbuf[mqtt_txlen++] = 0x82; //Message type and flag subscription
    else	mqtt_txbuf[mqtt_txlen++] = 0xA2;    //Unsubscribe

	//Remaining length
	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 );	
	
	//Variable header
    mqtt_txbuf[mqtt_txlen++] = 0;			//Message identifier MSB
    mqtt_txbuf[mqtt_txlen++] = 0x0A;        //Message identifier LSB
	//Payload
    mqtt_txbuf[mqtt_txlen++] = BYTE1(topiclen);//Subject length MSB
    mqtt_txbuf[mqtt_txlen++] = BYTE0(topiclen);//Subject length LSB   
	memcpy(&mqtt_txbuf[mqtt_txlen],topic,topiclen);
    mqtt_txlen += topiclen;
    
    if(whether)
    {
       mqtt_txbuf[mqtt_txlen++] = qos;//QoS level
    }
    
    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]) //Subscription succeeded			   
			{
				return 0;//Subscription succeeded
			}
        }
    }
	return 1; //fail
}

//MQTT publish data packaging function
//Topic topic 
//Message message
//qos message level 
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;
	//The length of the payload is calculated by subtracting the length of the variable header from the value of the remaining length field in the fixed header
	//No identifier when QOS is 0
	//Data length subject name message identifier payload
    if(qos)	DataLen = (2+topicLength) + 2 + messageLength;       
    else	DataLen = (2+topicLength) + messageLength;   

    //Fixed header
	//Control message type
    mqtt_txbuf[mqtt_txlen++] = 0x30;    // MQTT Message Type PUBLISH  

	//Remaining length
	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);//Subject length MSB
    mqtt_txbuf[mqtt_txlen++] = BYTE0(topicLength);//Subject length LSB 
	memcpy(&mqtt_txbuf[mqtt_txlen],topic,topicLength);//Copy theme
    mqtt_txlen += topicLength;
        
	//message identifier 
    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);
}