正点原子esp8266+mini(rct)板/c8t6上onenet云服务器

Posted 一个月后又可以改名了!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正点原子esp8266+mini(rct)板/c8t6上onenet云服务器相关的知识,希望对你有一定的参考价值。

提供一个wifi上云的代码,可以直接使用正点原子的esp8266wifi模块上onenet云平台,代码需要修改的地方我会指出来,并且上传数据的代码也会标明。

具体操作可以加我qq2947993454,帮助你解决问题。

下面都是需要添加和修改的文件源码。

main函数中只需要采集完后添加这两行就可以成功上传了。
OneNet_SendData();
ESP8266_Clear();

一、修改uasrt.h/.c文件

重新配置uart1并且配置好uart2用来控制wifi,修改后printf函数就不能向串口1传输了。

#ifndef _USART_H_
#define _USART_H_


#include "stm32f10x.h"


#define USART_DEBUG		USART1		//调试打印所使用的串口组


void Usart1_Init(unsigned int baud);

void Usart2_Init(unsigned int baud);

void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len);

void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...);

#endif


//硬件驱动
#include "usart.h"
#include "delay.h"

//C库
#include <stdarg.h>
#include <string.h>
#include <stdio.h>


void Usart1_Init(unsigned int baud)


	GPIO_InitTypeDef gpioInitStruct;
	USART_InitTypeDef usartInitStruct;
	NVIC_InitTypeDef nvicInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	
	//PA9	TXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_9;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	//PA10	RXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_10;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	usartInitStruct.USART_BaudRate = baud;
	usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//无硬件流控
	usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						//接收和发送
	usartInitStruct.USART_Parity = USART_Parity_No;									//无校验
	usartInitStruct.USART_StopBits = USART_StopBits_1;								//1位停止位
	usartInitStruct.USART_WordLength = USART_WordLength_8b;							//8位数据位
	USART_Init(USART1, &usartInitStruct);
	
	USART_Cmd(USART1, ENABLE);														//使能串口
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);									//使能接收中断
	
	nvicInitStruct.NVIC_IRQChannel = USART1_IRQn;
	nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
	nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	nvicInitStruct.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&nvicInitStruct);



/*
************************************************************
*	函数名称:	Usart2_Init
*
*	函数功能:	串口2初始化
*
*	入口参数:	baud:设定的波特率
*
*	返回参数:	无
*
*	说明:		TX-PA2		RX-PA3
************************************************************
*/
void Usart2_Init(unsigned int baud)


	GPIO_InitTypeDef gpioInitStruct;
	USART_InitTypeDef usartInitStruct;
	NVIC_InitTypeDef nvicInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	
	//PA2	TXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_2;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	//PA3	RXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_3;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	usartInitStruct.USART_BaudRate = baud;
	usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//无硬件流控
	usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						//接收和发送
	usartInitStruct.USART_Parity = USART_Parity_No;									//无校验
	usartInitStruct.USART_StopBits = USART_StopBits_1;								//1位停止位
	usartInitStruct.USART_WordLength = USART_WordLength_8b;							//8位数据位
	USART_Init(USART2, &usartInitStruct);
	
	USART_Cmd(USART2, ENABLE);														//使能串口
	
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);									//使能接收中断
	
	nvicInitStruct.NVIC_IRQChannel = USART2_IRQn;
	nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
	nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	nvicInitStruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&nvicInitStruct);



/*
************************************************************
*	函数名称:	Usart_SendString
*
*	函数功能:	串口数据发送
*
*	入口参数:	USARTx:串口组
*				str:要发送的数据
*				len:数据长度
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)


	unsigned short count = 0;
	
	for(; count < len; count++)
	
		USART_SendData(USARTx, *str++);									//发送数据
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);		//等待发送完成
	



/*
************************************************************
*	函数名称:	UsartPrintf
*
*	函数功能:	格式化打印
*
*	入口参数:	USARTx:串口组
*				fmt:不定长参
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...)


	unsigned char UsartPrintfBuf[296];
	va_list ap;
	unsigned char *pStr = UsartPrintfBuf;
	
	va_start(ap, fmt);
	vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							//格式化
	va_end(ap);
	
	while(*pStr != 0)
	
		USART_SendData(USARTx, *pStr++);
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);
	




二、修改delay.c/.h文件

#ifndef _DELAY_H_
#define _DELAY_H_







void Delay_Init(void);

void DelayUs(unsigned short us);

void DelayXms(unsigned short ms);

void DelayMs(unsigned short ms);

#endif


//单片机头文件
#include "stm32f10x.h"

//delay头文件
#include "delay.h"


//延时系数
unsigned char UsCount = 0;
unsigned short MsCount = 0;


/*
************************************************************
*	函数名称:	Delay_Init
*
*	函数功能:	systick初始化
*
*	入口参数:	无
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void Delay_Init(void)


	SysTick->CTRL &= ~(1 << 2);		//选择时钟为HCLK(72MHz)/8		103--9MHz
	
	UsCount = 9;					//微秒级延时系数
	
	MsCount = UsCount * 1000;		//毫秒级延时系数



/*
************************************************************
*	函数名称:	DelayUs
*
*	函数功能:	微秒级延时
*
*	入口参数:	us:延时的时长
*
*	返回参数:	无
*
*	说明:		此时钟(21MHz)最大延时798915us
************************************************************
*/
void DelayUs(unsigned short us)


	unsigned int ctrlResult = 0;
	
	us &= 0x00FFFFFF;											//取低24位
	
	SysTick->LOAD = us * UsCount;								//装载数据
	SysTick->VAL = 0;
	SysTick->CTRL = 1;											//使能倒计数器
	
	do
	
		ctrlResult = SysTick->CTRL;
	
	while((ctrlResult & 0x01) && !(ctrlResult & (1 << 16)));	//保证在运行、检查是否倒计数到0
	
	SysTick->CTRL = 0;											//关闭倒计数器
	SysTick->VAL = 0;



/*
************************************************************
*	函数名称:	DelayXms
*
*	函数功能:	毫秒级延时
*
*	入口参数:	ms:延时的时长
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void DelayXms(unsigned short ms)


	unsigned int ctrlResult = 0;
	
	if(ms == 0)
		return;
	
	ms &= 0x00FFFFFF;											//取低24位
	
	SysTick->LOAD = ms * MsCount;								//装载数据
	SysTick->VAL = 0;
	SysTick->CTRL = 1;											//使能倒计数器
	
	do
	
		ctrlResult = SysTick->CTRL;
	
	while((ctrlResult & 0x01) && !(ctrlResult & (1 << 16)));	//保证在运行、检查是否倒计数到0
	
	SysTick->CTRL = 0;											//关闭倒计数器
	SysTick->VAL = 0;



/*
************************************************************
*	函数名称:	DelayMs
*
*	函数功能:	微秒级长延时
*
*	入口参数:	ms:延时的时长
*
*	返回参数:	无
*
*	说明:		多次调用DelayXms,做到长延时
************************************************************
*/
void DelayMs(unsigned short ms)


	unsigned char repeat = 0;
	unsigned short remain = 0;
	
	repeat = ms / 500;
	remain = ms % 500;
	
	while(repeat)
	
		DelayXms(500);
		repeat--;
	
	
	if(remain)
		DelayXms(remain);


三、添加wifi.c与相关.h文件

下面这两句就是需要修改的地方,第一行是修改wifi名和密码,你想让wifi模块连那个网络就改为那个wifi和wifi密码,如下图所示我连的wifi名是123密码12345678。

#define ESP8266_WIFI_INFO        "AT+CWJAP=\\"123\\",\\"12345678\\"\\r\\n"

#define ESP8266_ONENET_INFO        "AT+CIPSTART=\\"TCP\\",\\"183.230.40.39\\",6002\\r\\n"

//单片机头文件
#include "stm32f10x.h"

//网络设备驱动
#include "esp8266.h"

//硬件驱动
#include "delay.h"
#include "usart.h"

//C库
#include <string.h>
#include <stdio.h>

#define ESP8266_WIFI_INFO		"AT+CWJAP=\\"123\\",\\"12345678\\"\\r\\n"

#define ESP8266_ONENET_INFO		"AT+CIPSTART=\\"TCP\\",\\"183.230.40.39\\",6002\\r\\n"


unsigned char esp8266_buf[128];
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;


//==========================================================
//	函数名称:	ESP8266_Clear
//
//	函数功能:	清空缓存
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_Clear(void)


	memset(esp8266_buf, 0, sizeof(esp8266_buf));
	esp8266_cnt = 0;



//==========================================================
//	函数名称:	ESP8266_WaitRecive
//
//	函数功能:	等待接收完成
//
//	入口参数:	无
//
//	返回参数:	REV_OK-接收完成		REV_WAIT-接收超时未完成
//
//	说明:		循环调用检测是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(void)


	if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数
		return REV_WAIT;
		
	if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同,则说明接收完毕
	
		esp8266_cnt = 0;							//清0接收计数
			
		return REV_OK;								//返回接收完成标志
	
		
	esp8266_cntPre = esp8266_cnt;					//置为相同
	
	return REV_WAIT;								//返回接收未完成标志



//==========================================================
//	函数名称:	ESP8266_SendCmd
//
//	函数功能:	发送命令
//
//	入口参数:	cmd:命令
//				res:需要检查的返回指令
//
//	返回参数:	0-成功	1-失败
//
//	说明:		
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)

	
	unsigned char timeOut = 200;

	Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
	
	while(timeOut--)
	
		if(ESP8266_WaitRecive() == REV_OK)							//如果收到数据
		
			if(strstr((const char *)esp8266_buf, res) != NULL)		//如果检索到关键词
			
				ESP8266_Clear();									//清空缓存
				
				return 0;
			
		
		
		DelayXms(10);
	
	
	return 1;



//==========================================================
//	函数名称:	ESP8266_SendData
//
//	函数功能:	发送数据
//
//	入口参数:	data:数据
//				len:长度
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_SendData(unsigned char *data, unsigned short len)


	char cmdBuf[32];
	
	ESP8266_Clear();								//清空接收缓存
	sprintf(cmdBuf, "AT+CIPSEND=%d\\r\\n", len);		//发送命令
	if(!ESP8266_SendCmd(cmdBuf, ">"))				//收到‘>’时可以发送数据
	
		Usart_SendString(USART2, data, len);		//发送设备连接请求数据
	



//==========================================================
//	函数名称:	ESP8266_GetIPD
//
//	函数功能:	获取平台返回的数据
//
//	入口参数:	等待的时间(乘以10ms)
//
//	返回参数:	平台返回的原始数据
//
//	说明:		不同网络设备返回的格式不同,需要去调试
//				如ESP8266的返回格式为	"+IPD,x:yyy"	x代表数据长度,yyy是数据内容
//==========================================================
unsigned char *ESP8266_GetIPD(unsigned short timeOut)


	char *ptrIPD = NULL;
	
	do
	
		if(ESP8266_WaitRecive() == REV_OK)								//如果接收完成
		
			ptrIPD = strstr((char *)esp8266_buf, "IPD,");				//搜索“IPD”头
			if(ptrIPD == NULL)											//如果没找到,可能是IPD头的延迟,还是需要等待一会,但不会超过设定的时间
			
				//UsartPrintf(USART_DEBUG, "\\"IPD\\" not found\\r\\n");
			
			else
			
				ptrIPD = strchr(ptrIPD, ':');							//找到':'
				if(ptrIPD != NULL)
				
					ptrIPD++;
					return (unsigned char *)(ptrIPD);
				
				else
					return NULL;
				
			
		
		
		DelayXms(5);													//延时等待
	 while(timeOut--);
	
	return NULL;														//超时还未找到,返回空指针



//==========================================================
//	函数名称:	ESP8266_Init
//
//	函数功能:	初始化ESP8266
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_Init(void)

	
	GPIO_InitTypeDef GPIO_Initure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);

	//ESP8266复位引脚
	GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Initure.GPIO_Pin = GPIO_Pin_14;					//GPIOG14-复位
	GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOG, &GPIO_Initure);
    //ESP8266芯片使能引脚
	GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Initure.GPIO_Pin = GPIO_Pin_13;					//GPIOG13-使能
	GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOG, &GPIO_Initure);
    
    GPIO_WriteBit(GPIOG, GPIO_Pin_13, Bit_SET);             //ESP8266高电平使能,芯片正常工作
	
	GPIO_WriteBit(GPIOG, GPIO_Pin_14, Bit_RESET);
	DelayXms(250);
	GPIO_WriteBit(GPIOG, GPIO_Pin_14, Bit_SET);
	DelayXms(500);
	
	ESP8266_Clear();
	
	UsartPrintf(USART_DEBUG, "1. AT\\r\\n");
	while(ESP8266_SendCmd("AT\\r\\n", "OK"))
		DelayXms(500);
	
	UsartPrintf(USART_DEBUG, "2. CWMODE\\r\\n");
	while(ESP8266_SendCmd("AT+CWMODE=1\\r\\n", "OK"))
		DelayXms(500);
	
	UsartPrintf(USART_DEBUG, "3. AT+CWDHCP\\r\\n");
	while(ESP8266_SendCmd("AT+CWDHCP=1,1\\r\\n", "OK"))
		DelayXms(500);
	
	UsartPrintf(USART_DEBUG, "4. CWJAP\\r\\n");
	while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "OK"))
		DelayXms(500);
	
	UsartPrintf(USART_DEBUG, "5. CIPSTART\\r\\n");
	while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))
		DelayXms(500);
	
	UsartPrintf(USART_DEBUG, "6. ESP8266 Init OK\\r\\n");



//==========================================================
//	函数名称:	USART2_IRQHandler
//
//	函数功能:	串口2收发中断
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void USART2_IRQHandler(void)


	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
	
		if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; //防止串口被刷爆
		esp8266_buf[esp8266_cnt++] = USART2->DR;
		
		USART_ClearFlag(USART2, USART_FLAG_RXNE);
	


#ifndef _ESP8266_H_
#define _ESP8266_H_





#define REV_OK		0	//接收完成标志
#define REV_WAIT	1	//接收未完成标志


void ESP8266_Init(void);

void ESP8266_Clear(void);

void ESP8266_SendData(unsigned char *data, unsigned short len);

unsigned char *ESP8266_GetIPD(unsigned short timeOut);


#endif

 四、onenet.c文件与相关.h文件的添加

这里需要改的很多

#define PROID        "503626"

#define AUTH_INFO    "123456"

#define DEVID        "923699269"

这些改为你自己的onenet云配置,产品ID,鉴权信息(自己设置的),设备ID。

然后是发送的数据修改:OneNet_FillBuf(char *buf);在这个函数中修改,按照例子的格式,注意最后一组数据那里没有都好,仔细看看。

//单片机头文件
#include "stm32f10x.h"

//网络设备
#include "esp8266.h"

//协议文件
#include "onenet.h"
#include "mqttkit.h"

//硬件驱动
#include "usart.h"
#include "delay.h"
#include "led.h"

//C库
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define PROID		"503626"

#define AUTH_INFO	"123456"

#define DEVID		"923699269"
	extern int8_t n_sp02;
	extern int32_t n_heart_rate;
	extern short temperature;

extern unsigned char esp8266_buf[128];

float lon = 116.3425;
float lat = 22.9871;



//==========================================================
//	函数名称:	OneNet_DevLink
//
//	函数功能:	与onenet创建连接
//
//	入口参数:	无
//
//	返回参数:	1-成功	0-失败
//
//	说明:		与onenet平台建立连接
//==========================================================
_Bool OneNet_DevLink(void)

	
	MQTT_PACKET_STRUCTURE mqttPacket = NULL, 0, 0, 0;					//协议包

	unsigned char *dataPtr;
	
	_Bool status = 1;
	
	UsartPrintf(USART_DEBUG, "OneNet_DevLink\\r\\n"
							"PROID: %s,	AUIF: %s,	DEVID:%s\\r\\n"
                        , PROID, AUTH_INFO, DEVID);
	
	if(MQTT_PacketConnect(PROID, AUTH_INFO, DEVID, 256, 0, MQTT_QOS_LEVEL0, NULL, NULL, 0, &mqttPacket) == 0)
	
		ESP8266_SendData(mqttPacket._data, mqttPacket._len);			//上传平台
		
		dataPtr = ESP8266_GetIPD(250);									//等待平台响应
		if(dataPtr != NULL)
		
			if(MQTT_UnPacketRecv(dataPtr) == MQTT_PKT_CONNACK)
			
				switch(MQTT_UnPacketConnectAck(dataPtr))
				
					case 0:UsartPrintf(USART_DEBUG, "Tips:	连接成功\\r\\n");status = 0;break;
					
					case 1:UsartPrintf(USART_DEBUG, "WARN:	连接失败:协议错误\\r\\n");break;
					case 2:UsartPrintf(USART_DEBUG, "WARN:	连接失败:非法的clientid\\r\\n");break;
					case 3:UsartPrintf(USART_DEBUG, "WARN:	连接失败:服务器失败\\r\\n");break;
					case 4:UsartPrintf(USART_DEBUG, "WARN:	连接失败:用户名或密码错误\\r\\n");break;
					case 5:UsartPrintf(USART_DEBUG, "WARN:	连接失败:非法链接(比如token非法)\\r\\n");break;
					
					default:UsartPrintf(USART_DEBUG, "ERR:	连接失败:未知错误\\r\\n");break;
				
			
		
		
		MQTT_DeleteBuffer(&mqttPacket);								//删包
	
	else
		UsartPrintf(USART_DEBUG, "WARN:	MQTT_PacketConnect Failed\\r\\n");
	
	return status;
	


unsigned char OneNet_FillBuf(char *buf)

	
	char text[32];

	memset(text, 0, sizeof(text));
	
		strcpy(buf, "");
	
    memset(text, 0, sizeof(text));
		sprintf(text, "\\"heartbeat\\":%d,",n_heart_rate); 
    strcat(buf, text);
		
		memset(text, 0, sizeof(text));
		sprintf(text, "\\"spo2\\":%d,",n_sp02); 
    strcat(buf, text);
	
		memset(text, 0, sizeof(text));
		sprintf(text, "\\"temp\\":%.1f",((float)temperature)/10); 
    strcat(buf, text);

		strcat(buf, "");
	
	return strlen(buf);



//==========================================================
//	函数名称:	OneNet_SendData
//
//	函数功能:	上传数据到平台
//
//	入口参数:	type:发送数据的格式
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void OneNet_SendData(void)

	
	MQTT_PACKET_STRUCTURE mqttPacket = NULL, 0, 0, 0;												//协议包
	
	char buf[128];
	
	short body_len = 0, i = 0;
	
	UsartPrintf(USART_DEBUG, "Tips:	OneNet_SendData-MQTT\\r\\n");
	
//	memset(buf, 0, sizeof(buf));
	UsartPrintf(USART_DEBUG, "Tips:	OneNet_SendData-MQTT11\\r\\n");
	body_len = OneNet_FillBuf(buf);																	//获取当前需要发送的数据流的总长度
	
	if(body_len)
	
		if(MQTT_PacketSaveData(DEVID, body_len, NULL, 3, &mqttPacket) == 0)							//封包
		
			for(; i < body_len; i++)
				mqttPacket._data[mqttPacket._len++] = buf[i];
			
			ESP8266_SendData(mqttPacket._data, mqttPacket._len);									//上传数据到平台
			UsartPrintf(USART_DEBUG, "Send %d Bytes\\r\\n", mqttPacket._len);
			
			MQTT_DeleteBuffer(&mqttPacket);															//删包
		
		else
			UsartPrintf(USART_DEBUG, "WARN:	EDP_NewBuffer Failed\\r\\n");
	
	UsartPrintf(USART_DEBUG, "Tips:	OneNet_SendData-MQTT22\\r\\n");



#ifndef __time_h
#define __time_h
#define __ARMCLIB_VERSION 5060016

#define _ARMABI __declspec(__nothrow)
#define _ARMABI_PURE __declspec(__nothrow) __attribute__((const))

  #ifndef __TIME_DECLS
  #define __TIME_DECLS

    #undef __CLIBNS

    #ifdef __cplusplus
      namespace std 
          #define __CLIBNS std::
          extern "C" 
    #else
      #define __CLIBNS
    #endif  /* __cplusplus */

#if defined(__cplusplus) || !defined(__STRICT_ANSI__)
 /* unconditional in C++ and non-strict C for consistency of debug info */
  #if __sizeof_ptr == 8
    typedef unsigned long size_t;   /* see <stddef.h> */
  #else
    typedef unsigned int size_t;   /* see <stddef.h> */
  #endif
#elif !defined(__size_t)
  #define __size_t 1
  #if __sizeof_ptr == 8
    typedef unsigned long size_t;   /* see <stddef.h> */
  #else
    typedef unsigned int size_t;   /* see <stddef.h> */
  #endif
#endif

#undef NULL
#define NULL 0                   /* see <stddef.h> */

    /* CLOCKS_PER_SEC: the number per second of the value returned by the
     * clock function. */
#if _AEABI_PORTABILITY_LEVEL != 0 || (!defined _AEABI_PORTABILITY_LEVEL && __DEFAULT_AEABI_PORTABILITY_LEVEL != 0)
  extern const int __aeabi_CLOCKS_PER_SEC;
  #define CLOCKS_PER_SEC (__aeabi_CLOCKS_PER_SEC)
#else
  #ifdef __CLK_TCK
    #define CLOCKS_PER_SEC  __CLK_TCK
  #else
    #define CLOCKS_PER_SEC  100
  #endif
#endif

#ifndef __STRICT_ANSI__
  #define CLK_TCK CLOCKS_PER_SEC
#endif

typedef unsigned int clock_t;    /* cpu time type */
typedef unsigned int time_t;     /* date/time in unix secs past 1-Jan-70 */

#pragma push
#pragma anon_unions

struct tm 
    int tm_sec;   /* seconds after the minute, 0 to 60
                     (0 - 60 allows for the occasional leap second) */
    int tm_min;   /* minutes after the hour, 0 to 59 */
    int tm_hour;  /* hours since midnight, 0 to 23 */
    int tm_mday;  /* day of the month, 1 to 31 */
    int tm_mon;   /* months since January, 0 to 11 */
    int tm_year;  /* years since 1900 */
    int tm_wday;  /* days since Sunday, 0 to 6 */
    int tm_yday;  /* days since January 1, 0 to 365 */
    int tm_isdst; /* Daylight Savings Time flag */
    union        /* ABI-required extra fields, in a variety of types */
        struct 
            int __extra_1, __extra_2;
        ;
        struct 
            long __extra_1_long, __extra_2_long;
        ;
        struct 
            char *__extra_1_cptr, *__extra_2_cptr;
        ;
        struct 
            void *__extra_1_vptr, *__extra_2_vptr;
        ;
    ;
;

#pragma pop

   /* struct tm holds the components of a calendar time, called the broken-down
    * time. The value of tm_isdst is positive if Daylight Savings Time is in
    * effect, zero if Daylight Savings Time is not in effect, and negative if
    * the information is not available.
    */

extern _ARMABI clock_t clock(void);
   /* determines the processor time used.
    * Returns: the implementation's best approximation to the processor time
    *          used by the program since program invocation. The time in
    *          seconds is the value returned divided by the value of the macro
    *          CLK_TCK. The value (clock_t)-1 is returned if the processor time
    *          used is not available.
    */
extern _ARMABI double difftime(time_t /*time1*/, time_t /*time0*/);
   /*
    * computes the difference between two calendar times: time1 - time0.
    * Returns: the difference expressed in seconds as a double.
    */
extern _ARMABI time_t mktime(struct tm * /*timeptr*/) __attribute__((__nonnull__(1)));
   /*
    * converts the broken-down time, expressed as local time, in the structure
    * pointed to by timeptr into a calendar time value with the same encoding
    * as that of the values returned by the time function. The original values
    * of the tm_wday and tm_yday components of the structure are ignored, and
    * the original values of the other components are not restricted to the
    * ranges indicated above. On successful completion, the values of the
    * tm_wday and tm_yday structure components are set appropriately, and the
    * other components are set to represent the specified calendar time, but
    * with their values forced to the ranges indicated above; the final value
    * of tm_mday is not set until tm_mon and tm_year are determined.
    * Returns: the specified calendar time encoded as a value of type time_t.
    *          If the calendar time cannot be represented, the function returns
    *          the value (time_t)-1.
    */
extern _ARMABI time_t time(time_t * /*timer*/);
   /*
    * determines the current calendar time. The encoding of the value is
    * unspecified.
    * Returns: the implementations best approximation to the current calendar
    *          time. The value (time_t)-1 is returned if the calendar time is
    *          not available. If timer is not a null pointer, the return value
    *          is also assigned to the object it points to.
    */

extern _ARMABI char *asctime(const struct tm * /*timeptr*/) __attribute__((__nonnull__(1)));
extern _ARMABI char *_asctime_r(const struct tm * /*timeptr*/,
                                char * __restrict /*buf*/) __attribute__((__nonnull__(1,2)));
#ifndef __STRICT_ANSI__
extern _ARMABI char *asctime_r(const struct tm * /*timeptr*/,
                               char * __restrict /*buf*/) __attribute__((__nonnull__(1,2)));
#endif
   /*
    * converts the broken-down time in the structure pointed to by timeptr into
    * a string in the form "Sun Sep 16 01:03:52 1973\\n\\0".
    * Returns: a pointer to the string containing the date and time.
    */
extern _ARMABI char *ctime(const time_t * /*timer*/) __attribute__((__nonnull__(1)));
   /*
    * converts the calendar time pointed to by timer to local time in the form
    * of a string. It is equivalent to asctime(localtime(timer));
    * Returns: the pointer returned by the asctime function with that
    *          broken-down time as argument.
    */
extern _ARMABI struct tm *gmtime(const time_t * /*timer*/) __attribute__((__nonnull__(1)));
   /*
    * converts the calendar time pointed to by timer into a broken-down time,
    * expressed as Greenwich Mean Time (GMT).
    * Returns: a pointer to that object or a null pointer if GMT not available.
    */
extern _ARMABI struct tm *localtime(const time_t * /*timer*/) __attribute__((__nonnull__(1)));
extern _ARMABI struct tm *_localtime_r(const time_t * __restrict /*timer*/,
                                       struct tm * __restrict /*result*/) __attribute__((__nonnull__(1,2)));
#ifndef __STRICT_ANSI__
extern _ARMABI struct tm *localtime_r(const time_t * __restrict /*timer*/,
                                      struct tm * __restrict /*result*/) __attribute__((__nonnull__(1,2)));
#endif
   /*
    * converts the calendar time pointed to by timer into a broken-down time,
    * expressed a local time.
    * Returns: a pointer to that object.
    */
extern _ARMABI size_t strftime(char * __restrict /*s*/, size_t /*maxsize*/,
                       const char * __restrict /*format*/,
                       const struct tm * __restrict /*timeptr*/) __attribute__((__nonnull__(1,3,4)));
   /*
    * places characters into the array pointed to by s as controlled by the
    * string pointed to by format. The format string consists of zero or more
    * directives and ordinary characters. A directive consists of a % character
    * followed by a character that determines the directive's behaviour. All
    * ordinary characters (including the terminating null character) are copied
    * unchanged into the array. No more than maxsize characters are placed into
    * the array. Each directive is replaced by appropriate characters  as
    * described in the following list. The appropriate characters are
    * determined by the LC_TIME category of the current locale and by the
    * values contained in the structure pointed to by timeptr.
    * %a is replaced by the locale's abbreviated weekday name.
    * %A is replaced by the locale's full weekday name.
    * %b is replaced by the locale's abbreviated month name.
    * %B is replaced by the locale's full month name.
    * %c is replaced by the locale's appropriate date and time representation.
    * %d is replaced by the day of the month as a decimal number (01-31).
    * %H is replaced by the hour (24-hour clock) as a decimal number (00-23).
    * %I is replaced by the hour (12-hour clock) as a decimal number (01-12).
    * %j is replaced by the day of the year as a decimal number (001-366).
    * %m is replaced by the month as a decimal number (01-12).
    * %M is replaced by the minute as a decimal number (00-59).
    * %p is replaced by the locale's equivalent of either AM or PM designations
    *       associated with a 12-hour clock.
    * %S is replaced by the second as a decimal number (00-61).
    * %U is replaced by the week number of the year (Sunday as the first day of
    *       week 1) as a decimal number (00-53).
    * %w is replaced by the weekday as a decimal number (0(Sunday) - 6).
    * %W is replaced by the week number of the year (Monday as the first day of
    *       week 1) as a decimal number (00-53).
    * %x is replaced by the locale's appropriate date representation.
    * %X is replaced by the locale's appropriate time representation.
    * %y is replaced by the year without century as a decimal number (00-99).
    * %Y is replaced by the year with century as a decimal number.
    * %Z is replaced by the timezone name or abbreviation, or by no characters
    *       if no time zone is determinable.
    * %% is replaced by %.
    * If a directive is not one of the above, the behaviour is undefined.
    * Returns: If the total number of resulting characters including the
    *          terminating null character is not more than maxsize, the
    *          strftime function returns the number of characters placed into
    *          the array pointed to by s not including the terminating null
    *          character. otherwise, zero is returned and the contents of the
    *          array are indeterminate.
    */

    #ifdef __cplusplus
           /* extern "C" */
        /* namespace std */
    #endif /* __cplusplus */
  #endif /* __TIME_DECLS */

  #if _AEABI_PORTABILITY_LEVEL != 0 && !defined _AEABI_PORTABLE
    #define _AEABI_PORTABLE
  #endif

  #ifdef __cplusplus
    #ifndef __TIME_NO_EXPORTS
      using ::std::clock_t;
      using ::std::time_t;
      using ::std::tm;
      using ::std::tm;
      using ::std::clock;
      using ::std::difftime;
      using ::std::mktime;
      using ::std::time;
      using ::std::asctime;
      using ::std::_asctime_r;
#ifndef __STRICT_ANSI__
      using ::std::asctime_r;
#endif
      using ::std::ctime;
      using ::std::gmtime;
      using ::std::localtime;
      using ::std::_localtime_r;
#ifndef __STRICT_ANSI__
      using ::std::localtime_r;
#endif
      using ::std::strftime;
      using ::std::size_t;
    #endif /* __TIME_NO_EXPORTS */
  #endif /* __cplusplus */

#endif

/* end of time.h */

#ifndef _ONENET_H_
#define _ONENET_H_





_Bool OneNet_DevLink(void);

void OneNet_SendData(void);

void OneNet_RevPro(unsigned char *cmd);

#endif
#ifndef _MQTTKIT_H_
#define _MQTTKIT_H_


#include "Common.h"


//=============================配置==============================
//===========可以提供RTOS的内存管理方案,也可以使用C库的=========
//RTOS
#include <stdlib.h>

#define MQTT_MallocBuffer	malloc

#define MQTT_FreeBuffer		free
//==========================================================


#define MOSQ_MSB(A)         (uint8)((A & 0xFF00) >> 8)
#define MOSQ_LSB(A)         (uint8)(A & 0x00FF)


/*--------------------------------内存分配方案标志--------------------------------*/
#define MEM_FLAG_NULL		0
#define MEM_FLAG_ALLOC		1
#define MEM_FLAG_STATIC		2


typedef struct Buffer

	
	uint8	*_data;		//协议数据
	
	uint32	_len;		//写入的数据长度
	
	uint32	_size;		//缓存总大小
	
	uint8	_memFlag;	//内存使用的方案:0-未分配	1-使用的动态分配		2-使用的固定内存
	
 MQTT_PACKET_STRUCTURE;


/*--------------------------------固定头部消息类型--------------------------------*/
enum MqttPacketType

	
    MQTT_PKT_CONNECT = 1, /**< 连接请求数据包 */
    MQTT_PKT_CONNACK,     /**< 连接确认数据包 */
    MQTT_PKT_PUBLISH,     /**< 发布数据数据包 */
    MQTT_PKT_PUBACK,      /**< 发布确认数据包 */
    MQTT_PKT_PUBREC,      /**< 发布数据已接收数据包,Qos 2时,回复MQTT_PKT_PUBLISH */
    MQTT_PKT_PUBREL,      /**< 发布数据释放数据包, Qos 2时,回复MQTT_PKT_PUBREC */
    MQTT_PKT_PUBCOMP,     /**< 发布完成数据包, Qos 2时,回复MQTT_PKT_PUBREL */
    MQTT_PKT_SUBSCRIBE,   /**< 订阅数据包 */
    MQTT_PKT_SUBACK,      /**< 订阅确认数据包 */
    MQTT_PKT_UNSUBSCRIBE, /**< 取消订阅数据包 */
    MQTT_PKT_UNSUBACK,    /**< 取消订阅确认数据包 */
    MQTT_PKT_PINGREQ,     /**< ping 数据包 */
    MQTT_PKT_PINGRESP,    /**< ping 响应数据包 */
    MQTT_PKT_DISCONNECT,  /**< 断开连接数据包 */
	
	//新增
	
	MQTT_PKT_CMD  		 /**< 命令下发数据包 */
	
;


/*--------------------------------MQTT QOS等级--------------------------------*/
enum MqttQosLevel

	
    MQTT_QOS_LEVEL0,  /**< 最多发送一次 */
    MQTT_QOS_LEVEL1,  /**< 最少发送一次  */
    MQTT_QOS_LEVEL2   /**< 只发送一次 */
	
;


/*--------------------------------MQTT 连接请求标志位,内部使用--------------------------------*/
enum MqttConnectFlag

	
    MQTT_CONNECT_CLEAN_SESSION  = 0x02,
    MQTT_CONNECT_WILL_FLAG      = 0x04,
    MQTT_CONNECT_WILL_QOS0      = 0x00,
    MQTT_CONNECT_WILL_QOS1      = 0x08,
    MQTT_CONNECT_WILL_QOS2      = 0x10,
    MQTT_CONNECT_WILL_RETAIN    = 0x20,
    MQTT_CONNECT_PASSORD        = 0x40,
    MQTT_CONNECT_USER_NAME      = 0x80
	
;


/*--------------------------------消息的packet ID,可自定义--------------------------------*/
#define MQTT_PUBLISH_ID			10

#define MQTT_SUBSCRIBE_ID		20

#define MQTT_UNSUBSCRIBE_ID		30


/*--------------------------------删包--------------------------------*/
void MQTT_DeleteBuffer(MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------解包--------------------------------*/
uint8 MQTT_UnPacketRecv(uint8 *dataPtr);

/*--------------------------------登录组包--------------------------------*/
uint8 MQTT_PacketConnect(const int8 *user, const int8 *password, const int8 *devid,
						uint16 cTime, uint1 clean_session, uint1 qos,
						const int8 *will_topic, const int8 *will_msg, int32 will_retain,
						MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------断开连接组包--------------------------------*/
uint1 MQTT_PacketDisConnect(MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------连接响应解包--------------------------------*/
uint8 MQTT_UnPacketConnectAck(uint8 *rev_data);

/*--------------------------------数据点上传组包--------------------------------*/
uint1 MQTT_PacketSaveData(const int8 *devid, int16 send_len, int8 *type_bin_head, uint8 type, MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------命令下发解包--------------------------------*/
uint8 MQTT_UnPacketCmd(uint8 *rev_data, int8 **cmdid, int8 **req, uint16 *req_len);

/*--------------------------------命令回复组包--------------------------------*/
uint1 MQTT_PacketCmdResp(const int8 *cmdid, const int8 *req, MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------订阅主题组包--------------------------------*/
uint8 MQTT_PacketSubscribe(uint16 pkt_id, enum MqttQosLevel qos, const int8 *topics[], uint8 topics_cnt, MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------订阅主题回复解包--------------------------------*/
uint8 MQTT_UnPacketSubscribe(uint8 *rev_data);

/*--------------------------------取消订阅组包--------------------------------*/
uint8 MQTT_PacketUnSubscribe(uint16 pkt_id, const int8 *topics[], uint8 topics_cnt, MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------取消订阅回复解包--------------------------------*/
uint1 MQTT_UnPacketUnSubscribe(uint8 *rev_data);

/*--------------------------------发布主题组包--------------------------------*/
uint8 MQTT_PacketPublish(uint16 pkt_id, const int8 *topic,
						const int8 *payload, uint32 payload_len,
						enum MqttQosLevel qos, int32 retain, int32 own,
						MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------发布消息回复解包--------------------------------*/
uint8 MQTT_UnPacketPublish(uint8 *rev_data, int8 **topic, uint16 *topic_len, int8 **payload, uint16 *payload_len, uint8 *qos, uint16 *pkt_id);

/*--------------------------------发布消息的Ack组包--------------------------------*/
uint1 MQTT_PacketPublishAck(uint16 pkt_id, MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------发布消息的Ack解包--------------------------------*/
uint1 MQTT_UnPacketPublishAck(uint8 *rev_data);

/*--------------------------------发布消息的Rec组包--------------------------------*/
uint1 MQTT_PacketPublishRec(uint16 pkt_id, MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------发布消息的Rec解包--------------------------------*/
uint1 MQTT_UnPacketPublishRec(uint8 *rev_data);

/*--------------------------------发布消息的Rel组包--------------------------------*/
uint1 MQTT_PacketPublishRel(uint16 pkt_id, MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------发布消息的Rel解包--------------------------------*/
uint1 MQTT_UnPacketPublishRel(uint8 *rev_data, uint16 pkt_id);

/*--------------------------------发布消息的Comp组包--------------------------------*/
uint1 MQTT_PacketPublishComp(uint16 pkt_id, MQTT_PACKET_STRUCTURE *mqttPacket);

/*--------------------------------发布消息的Comp解包--------------------------------*/
uint1 MQTT_UnPacketPublishComp(uint8 *rev_data);

/*--------------------------------心跳请求组包--------------------------------*/
uint1 MQTT_PacketPing(MQTT_PACKET_STRUCTURE *mqttPacket);


#endif

 五、添加MqttKit.h与.c文件

.h在上步已经加过了。


//协议头文件
#include "MqttKit.h"

//C库
#include <string.h>


#define CMD_TOPIC_PREFIX		"$creq"


//==========================================================
//	函数名称:	EDP_NewBuffer
//
//	函数功能:	申请内存
//
//	入口参数:	edpPacket:包结构体
//				size:大小
//
//	返回参数:	无
//
//	说明:		1.可使用动态分配来分配内存
//				2.可使用局部或全局数组来指定内存
//==========================================================
void MQTT_NewBuffer(MQTT_PACKET_STRUCTURE *mqttPacket, uint32 size)

	
	uint32 i = 0;

	if(mqttPacket->_data == NULL)
	
		mqttPacket->_memFlag = MEM_FLAG_ALLOC;
		
		mqttPacket->_data = (uint8 *)MQTT_MallocBuffer(size);
		if(mqttPacket->_data != NULL)
		
			mqttPacket->_len = 0;
			
			mqttPacket->_size = size;
			
			for(; i < mqttPacket->_size; i++)
				mqttPacket->_data[i] = 0;
		
	
	else
	
		mqttPacket->_memFlag = MEM_FLAG_STATIC;
		
		for(; i < mqttPacket->_size; i++)
			mqttPacket->_data[i] = 0;
		
		mqttPacket->_len = 0;
		
		if(mqttPacket->_size < size)
			mqttPacket->_data = NULL;
	



//==========================================================
//	函数名称:	MQTT_DeleteBuffer
//
//	函数功能:	释放数据内存
//
//	入口参数:	edpPacket:包结构体
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void MQTT_DeleteBuffer(MQTT_PACKET_STRUCTURE *mqttPacket)


	if(mqttPacket->_memFlag == MEM_FLAG_ALLOC)
		MQTT_FreeBuffer(mqttPacket->_data);
	
	mqttPacket->_data = NULL;
	mqttPacket->_len = 0;
	mqttPacket->_size = 0;
	mqttPacket->_memFlag = MEM_FLAG_NULL;



int32 MQTT_DumpLength(size_t len, uint8 *buf)

	
	int32 i = 0;
	
	for(i = 1; i <= 4; ++i)
	
		*buf = len % 128;
		len >>= 7;
		if(len > 0)
		
			*buf |= 128;
			++buf;
		
		else
		
			return i;
		
	

	return -1;


int32 MQTT_ReadLength(const uint8 *stream, int32 size, uint32 *len)

	
	int32 i;
	const uint8 *in = stream;
	uint32 multiplier = 1;

	*len = 0;
	for(i = 0; i < size; ++i)
	
		*len += (in[i] & 0x7f) * multiplier;

		if(!(in[i] & 0x80))
		
			return i + 1;
		

		multiplier <<= 7;
		if(multiplier >= 2097152)		//128 * *128 * *128
		
			return -2;					// error, out of range
		
	

	return -1;							// not complete



//==========================================================
//	函数名称:	MQTT_UnPacketRecv
//
//	函数功能:	MQTT数据接收类型判断
//
//	入口参数:	dataPtr:接收的数据指针
//
//	返回参数:	0-成功		其他-失败原因
//
//	说明:		
//==========================================================
uint8 MQTT_UnPacketRecv(uint8 *dataPtr)

	
	uint8 status = 255;
	uint8 type = dataPtr[0] >> 4;				//类型检查
	
	if(type < 1 || type > 14)
		return status;
	
	if(type == MQTT_PKT_PUBLISH)
	
		uint8 *msgPtr;
		uint32 remain_len = 0;
		
		msgPtr = dataPtr + MQTT_ReadLength(dataPtr + 1, 4, &remain_len) + 1;
		
		if(remain_len < 2 || dataPtr[0] & 0x01)					//retain
			return 255;
		
		if(remain_len < ((uint16)msgPtr[0] << 8 | msgPtr[1]) + 2)
			return 255;
		
		if(strstr((int8 *)msgPtr + 2, CMD_TOPIC_PREFIX) != NULL)	//如果是命令下发
			status = MQTT_PKT_CMD;
		else
			status = MQTT_PKT_PUBLISH;
	
	else
		status = type;
	
	return status;



//==========================================================
//	函数名称:	MQTT_PacketConnect
//
//	函数功能:	连接消息组包
//
//	入口参数:	user:用户名:产品ID
//				password:密码:鉴权信息或apikey
//				devid:设备ID
//				cTime:连接保持时间
//				clean_session:离线消息清除标志
//				qos:重发标志
//				will_topic:异常离线topic
//				will_msg:异常离线消息
//				will_retain:消息推送标志
//				mqttPacket:包指针
//
//	返回参数:	0-成功		其他-失败
//
//	说明:		
//==========================================================
uint8 MQTT_PacketConnect(const int8 *user, const int8 *password, const int8 *devid,
						uint16 cTime, uint1 clean_session, uint1 qos,
						const int8 *will_topic, const int8 *will_msg, int32 will_retain,
						MQTT_PACKET_STRUCTURE *mqttPacket)

	
	uint8 flags = 0;
	uint8 will_topic_len = 0;
	uint16 total_len = 15;
	int16 len = 0, devid_len = strlen(devid);
	
	if(!devid)
		return 1;
	
	total_len += devid_len + 2;
	
	//断线后,是否清理离线消息:1-清理	0-不清理--------------------------------------------
	if(clean_session)
	
		flags |= MQTT_CONNECT_CLEAN_SESSION;
	
	
	//异常掉线情况下,服务器发布的topic------------------------------------------------------
	if(will_topic)
	
		flags |= MQTT_CONNECT_WILL_FLAG;
		will_topic_len = strlen(will_topic);
		total_len += 4 + will_topic_len + strlen(will_msg);
	
	
	//qos级别--主要用于PUBLISH(发布态)消息的,保证消息传递的次数-----------------------------
	switch((unsigned char)qos)
	
		case MQTT_QOS_LEVEL0:
			flags |= MQTT_CONNECT_WILL_QOS0;							//最多一次
		break;
		
		case MQTT_QOS_LEVEL1:
			flags |= (MQTT_CONNECT_WILL_FLAG | MQTT_CONNECT_WILL_QOS1);	//最少一次
		break;
		
		case MQTT_QOS_LEVEL2:
			flags |= (MQTT_CONNECT_WILL_FLAG | MQTT_CONNECT_WILL_QOS2);	//只有一次
		break;
		
		default:
		return 2;
	
	
	//主要用于PUBLISH(发布态)的消息,表示服务器要保留这次推送的信息,如果有新的订阅者出现,就把这消息推送给它。如果不设那么推送至当前订阅的就释放了
	if(will_retain)
	
		flags |= (MQTT_CONNECT_WILL_FLAG | MQTT_CONNECT_WILL_RETAIN);
	
	
	//账号为空 密码为空---------------------------------------------------------------------
	if(!user || !password)
	
		return 3;
	
	flags |= MQTT_CONNECT_USER_NAME | MQTT_CONNECT_PASSORD;
	
	total_len += strlen(user) + strlen(password) + 4;
	
	//分配内存-----------------------------------------------------------------------------
	MQTT_NewBuffer(mqttPacket, total_len);
	if(mqttPacket->_data == NULL)
		return 4;
	
	memset(mqttPacket->_data, 0, total_len);
	
/*************************************固定头部***********************************************/
	
	//固定头部----------------------连接请求类型---------------------------------------------
	mqttPacket->_data[mqttPacket->_len++] = MQTT_PKT_CONNECT << 4;
	
	//固定头部----------------------剩余长度值-----------------------------------------------
	len = MQTT_DumpLength(total_len - 5, mqttPacket->_data + mqttPacket->_len);
	if(len < 0)
	
		MQTT_DeleteBuffer(mqttPacket);
		return 5;
	
	else
		mqttPacket->_len += len;
	
/*************************************可变头部***********************************************/
	
	//可变头部----------------------协议名长度 和 协议名--------------------------------------
	mqttPacket->_data[mqttPacket->_len++] = 0;
	mqttPacket->_data[mqttPacket->_len++] = 4;
	mqttPacket->_data[mqttPacket->_len++] = 'M';
	mqttPacket->_data[mqttPacket->_len++] = 'Q';
	mqttPacket->_data[mqttPacket->_len++] = 'T';
	mqttPacket->_data[mqttPacket->_len++] = 'T';
	
	//可变头部----------------------protocol level 4-----------------------------------------
	mqttPacket->_data[mqttPacket->_len++] = 4;
	
	//可变头部----------------------连接标志(该函数开头处理的数据)-----------------------------
    mqttPacket->_data[mqttPacket->_len++] = flags;
	
	//可变头部----------------------保持连接的时间(秒)----------------------------------------
	mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB(cTime);
	mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB(cTime);
	 
/*************************************消息体************************************************/

	//消息体----------------------------devid长度、devid-------------------------------------
	mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB(devid_len);
	mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB(devid_len);
	
	strncat((int8 *)mqttPacket->_data + mqttPacket->_len, devid, devid_len);
	mqttPacket->_len += devid_len;
	
	//消息体----------------------------will_flag 和 will_msg---------------------------------
	if(flags & MQTT_CONNECT_WILL_FLAG)
	
		unsigned short mLen = 0;
		
		if(!will_msg)
			will_msg = "";
		
		mLen = strlen(will_topic);
		mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB(mLen);
		mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB(mLen);
		strncat((int8 *)mqttPacket->_data + mqttPacket->_len, will_topic, mLen);
		mqttPacket->_len += mLen;
		
		mLen = strlen(will_msg);
		mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB(mLen);
		mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB(mLen);
		strncat((int8 *)mqttPacket->_data + mqttPacket->_len, will_msg, mLen);
		mqttPacket->_len += mLen;
	
	
	//消息体----------------------------use---------------------------------------------------
	if(flags & MQTT_CONNECT_USER_NAME)
	
		unsigned short user_len = strlen(user);
		
		mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB(user_len);
		mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB(user_len);
		strncat((int8 *)mqttPacket->_data + mqttPacket->_len, user, user_len);
		mqttPacket->_len += user_len;
	

	//消息体----------------------------password----------------------------------------------
	if(flags & MQTT_CONNECT_PASSORD)
	
		unsigned short psw_len = strlen(password);
		
		mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB(psw_len);
		mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB(psw_len);
		strncat((int8 *)mqttPacket->_data + mqttPacket->_len, password, psw_len);
		mqttPacket->_len += psw_len;
	

	return 0;



//==========================================================
//	函数名称:	MQTT_PacketDisConnect
//
//	函数功能:	断开连接消息组包
//
//	入口参数:	mqttPacket:包指针
//
//	返回参数:	0-成功		1-失败
//
//	说明:		
//==========================================================
uint1 MQTT_PacketDisConnect(MQTT_PACKET_STRUCTURE *mqttPacket)


	MQTT_NewBuffer(mqttPacket, 2);
	if(mqttPacket->_data == NULL)
		return 1;
	
/*************************************固定头部***********************************************/
	
	//固定头部----------------------头部消息-------------------------------------------------
	mqttPacket->_data[mqttPacket->_len++] = MQTT_PKT_DISCONNECT << 4;
	
	//固定头部----------------------剩余长度值-----------------------------------------------
	mqttPacket->_data[mqttPacket->_len++] = 0;
	
	return 0;



//==========================================================
//	函数名称:	MQTT_UnPacketConnectAck
//
//	函数功能:	连接消息解包
//
//	入口参数:	rev_data:接收的数据
//
//	返回参数:	1、255-失败		其他-平台的返回码
//
//	说明:		
//==========================================================
uint8 MQTT_UnPacketConnectAck(uint8 *rev_data)


	if(rev_data[1] != 2)
		return 1;
	
	if(rev_data[2] == 0 || rev_data[2] == 1)
		return rev_data[3];
	else
		return 255;



//==========================================================
//	函数名称:	MQTT_PacketSaveData
//
//	函数功能:	数据点上传组包
//
//	入口参数:	devid:设备ID(可为空)
//				send_buf:json缓存buf
//				send_len:json总长
//				type_bin_head:bin文件的消息头
//				type:类型
//
//	返回参数:	0-成功		1-失败
//
//	说明:		
//==========================================================
uint1 MQTT_PacketSaveData(const int8 *devid, int16 send_len, int8 *type_bin_head, uint8 type, MQTT_PACKET_STRUCTURE *mqttPacket)


	if(MQTT_PacketPublish(MQTT_PUBLISH_ID, "$dp", NULL, send_len + 3, MQTT_QOS_LEVEL1, 0, 1, mqttPacket) == 0)
	
		mqttPacket->_data[mqttPacket->_len++] = type;					//类型
		
		mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB(send_len);
		mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB(send_len);
	
	else
		return 1;
	
	return 0;



//==========================================================
//	函数名称:	MQTT_UnPacketCmd
//
//	函数功能:	命令下发解包
//
//	入口参数:	rev_data:接收的数据指针
//				cmdid:cmdid-uuid
//				req:命令
//
//	返回参数:	0-成功		其他-失败原因
//
//	说明:		
//==========================================================
uint8 MQTT_UnPacketCmd(uint8 *rev_data, int8 **cmdid, int8 **req, uint16 *req_len)


	int8 *dataPtr = strchr((int8 *)rev_data + 6, '/');	//加6是跳过头信息
	
	uint32 remain_len = 0;
	
	if(dataPtr == NULL)									//未找到'/'
		return 1;
	dataPtr++;											//跳过'/'
	
	MQTT_ReadLength(rev_data + 1, 4, &remain_len);		//读取剩余字节
	
	*cmdid = (int8 *)MQTT_MallocBuffer(37);				//cmdid固定36字节,多分配一个结束符的位置
	if(*cmdid == NULL)
		return 2;
	
	memset(*cmdid, 0, 37);								//全部清零
	memcpy(*cmdid, (const int8 *)dataPtr, 36);			//复制cmdid
	dataPtr += 36;
	
	*req_len = remain_len - 44;							//命令长度 = 剩余长度(remain_len) - 2 - 5($creq) - 1(\\) - cmdid长度
	*req = (int8 *)MQTT_MallocBuffer(*req_len + 1);		//分配命令长度+1
	if(*req == NULL)
	
		MQTT_FreeBuffer(*cmdid);
		return 3;
	
	
	memset(*req, 0, *req_len + 1);						//清零
	memcpy(*req, (const int8 *)dataPtr, *req_len);		//复制命令
	
	return 0;



//=============================&

以上是关于正点原子esp8266+mini(rct)板/c8t6上onenet云服务器的主要内容,如果未能解决你的问题,请参考以下文章

正点原子esp8266+mini(rct)板/c8t6上onenet云服务器

物联网中你需要了解的ESP8266最基本的知识!

2.13 正点原子ESP8266模块的STA模式 调试2

2.12 正点原子ESP8266模块的STA模式 调试

2.14 正点原子ESP8266模块的STA模式 调试3

基于STM32的ESP8266获取心知天气数据