正点原子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云服务器的主要内容,如果未能解决你的问题,请参考以下文章