其他分享
首页 > 其他分享> > 实验:STM32-ARDUINO-ESP01采用AT指令,通过MQTT连接上ONENET

实验:STM32-ARDUINO-ESP01采用AT指令,通过MQTT连接上ONENET

作者:互联网

 

 2.程序结构

 

 

 

 

 3.程序代码汇总

#include "main.h"

void setup() {
  System_Init();  
}

void loop() {
  System_main();
}

  

#include "main.h"


void AT_ClearPara(void)
{
    int ch;
    String strTemp="";
    
    while(1)
    {
      if(Serial2.available())
      {
        ch=Serial2.read();
        strTemp=strTemp+(char)ch;
      }
      else
      {
        break;
      }
    }

    Serial.print(strTemp);
}


unsigned char g_ArrTemp[1024];
int AT_SendCmd ( char * atCmd, char * res, int timeout )
{
    int tt=0;
    int i=0;
    int status=1;
    String strTemp;
    
    AT_ClearPara();
    Serial2.print((char *)atCmd);
    Serial.print((char *)atCmd);

    while(1)
    {
        delay(1);
        tt++;
        if(tt>timeout && timeout!=0)break;
        
        if(Serial2.available())
        {
            delay(20);//
            strTemp="";
            while(1)
            {
                if(!Serial2.available())break;

                if(i<1024)
                {
                  g_ArrTemp[i]= Serial2.read();
                  strTemp=strTemp+(char)g_ArrTemp[i];
                  i++;
                }
                
            }

            Serial.print(strTemp);
            
            if(strstr((char *)g_ArrTemp,res)!=NULL)
            {
                 status=0;
                 break;
            }
        }
    }
    
    AT_ClearPara();
    return status;
}

int AT_SendData ( unsigned char *data, unsigned int len )
{

    char cmdBuf[100];
    
    AT_ClearPara();   

    sprintf( cmdBuf,"AT+CIPSEND=%d\r\n",len);           
    
    if (AT_SendCmd ( cmdBuf, ">", 400)==0)       
    {
        delay ( 10 );
        Serial2.write ( data, len );    
        return 0;
    }
   
    return 1;
}

  

#ifndef _ATCOMMAND_H_
#define _ATCOMMAND_H_


void AT_ClearPara ( void );
int AT_SendCmd (  char *atCmd, char * res, int timeout );
int AT_SendData ( unsigned char *data, unsigned int len );


#endif

  

/**
	************************************************************
	************************************************************
	************************************************************
	*	文件名: 	MqttKit.c
	*
	*	作者: 		张继瑞
	*
	*	日期: 		2018-04-27
	*
	*	版本: 		V1.4
	*
	*	说明: 		MQTT协议
	*
	*	修改记录:	V1.1:解决MQTT_PacketSubscribe订阅不为2个topic
	*						个数时协议错误的bug
	*				V1.2:修复MQTT_PacketCmdResp的bug
	*				V1.3:将strncpy替换为memcpy,解决潜在bug
	*				V1.4:修复	MQTT_PacketPublishAck
	*							MQTT_PacketPublishRel
	*							函数封包错误的bug
	*				V1.5:增加	MQTT_UnPacketCmd
	*							MQTT_UnPacketPublish
	*							接口对消息内容长度的提取参数
	************************************************************
	************************************************************
	************************************************************
**/

//协议头文件
#include "MqttKit.h"
#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:连接保持时间,  Keep Alive?????
//				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_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;

}

//==========================================================
//	函数名称:	MQTT_PacketCmdResp
//
//	函数功能:	命令回复组包
//
//	入口参数:	cmdid:cmdid
//				req:命令
//				mqttPacket:包指针
//
//	返回参数:	0-成功		1-失败
//
//	说明:
//==========================================================
uint1 MQTT_PacketCmdResp ( const int8 *cmdid, const int8 *req, MQTT_PACKET_STRUCTURE *mqttPacket )
{

    uint16 cmdid_len = strlen ( cmdid );
    uint16 req_len = strlen ( req );
    int status = 0;

    int8 *payload = (char *)MQTT_MallocBuffer ( cmdid_len + 6 );
    if ( payload == NULL )
    {
        return 1;
    }

    memset ( payload, 0, cmdid_len + 6 );
    memcpy ( payload, "$crsp/", 6 );
    strncat ( payload, cmdid, cmdid_len );

    if ( MQTT_PacketPublish ( MQTT_PUBLISH_ID, payload, req, strlen ( req ), MQTT_QOS_LEVEL0, 0, 1, mqttPacket ) == 0 )
    {
        status = 0;
    }
    else
    {
        status = 1;
    }

    MQTT_FreeBuffer ( payload );

    return status;

}

//==========================================================
//	函数名称:	MQTT_PacketSubscribe
//
//	函数功能:	Subscribe消息组包
//
//	入口参数:	pkt_id:pkt_id
//				qos:消息重发次数
//				topics:订阅的消息
//				topics_cnt:订阅的消息个数
//				mqttPacket:包指针
//
//	返回参数:	0-成功		其他-失败
//
//	说明:
//==========================================================
uint8 MQTT_PacketSubscribe ( uint16 pkt_id, enum MqttQosLevel qos, const char *topic, MQTT_PACKET_STRUCTURE *mqttPacket )
{

    uint32 topic_len = 0, remain_len = 0;
    int16 len = 0;
    // uint8 i = 0;

    if ( pkt_id == 0 )
    {
        return 1;
    }

    //计算topic长度-------------------------------------------------------------------------

    topic_len += strlen ( topic );


    //2 bytes packet id + topic filter(2 bytes topic + topic length + 1 byte reserve)------
    remain_len = 2 + 3  + topic_len;

    //分配内存------------------------------------------------------------------------------
    MQTT_NewBuffer ( mqttPacket, remain_len + 5 );
    if ( mqttPacket->_data == NULL )
    {
        return 3;
    }

    /*************************************固定头部***********************************************/

    //固定头部----------------------头部消息-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = MQTT_PKT_SUBSCRIBE << 4 | 0x02;

    //固定头部----------------------剩余长度值-----------------------------------------------
    len = MQTT_DumpLength ( remain_len, mqttPacket->_data + mqttPacket->_len );
    if ( len < 0 )
    {
        MQTT_DeleteBuffer ( mqttPacket );
        return 4;
    }
    else
    {
        mqttPacket->_len += len;
    }

    /*************************************payload***********************************************/

    //payload----------------------pkt_id---------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB ( pkt_id );
    mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB ( pkt_id );

    //payload----------------------topic_name-----------------------------------------------

    topic_len = strlen ( topic );
    mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB ( topic_len );
    mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB ( topic_len );

    strncat ( ( int8 * ) mqttPacket->_data + mqttPacket->_len, topic, topic_len );
    mqttPacket->_len += topic_len;

    mqttPacket->_data[mqttPacket->_len++] = qos & 0xFF;


    return 0;

}

//==========================================================
//	函数名称:	MQTT_UnPacketSubscrebe
//
//	函数功能:	Subscribe的回复消息解包
//
//	入口参数:	rev_data:接收到的信息
//
//	返回参数:	0-成功		其他-失败
//
//	说明:
//==========================================================
uint8 MQTT_UnPacketSubscribe ( uint8 *rev_data )
{

    uint8 result = 255;

    if ( rev_data[2] == MOSQ_MSB ( MQTT_SUBSCRIBE_ID ) && rev_data[3] == MOSQ_LSB ( MQTT_SUBSCRIBE_ID ) )
    {
        switch ( rev_data[4] )
        {
            case 0x00:
            case 0x01:
            case 0x02:
                //MQTT Subscribe OK
                result = 0;
                break;

            case 0x80:
                //MQTT Subscribe Failed
                result = 1;
                break;

            default:
                //MQTT Subscribe UnKnown Err
                result = 2;
                break;
        }
    }

    return result;

}

//==========================================================
//	函数名称:	MQTT_PacketUnSubscribe
//
//	函数功能:	UnSubscribe消息组包
//
//	入口参数:	pkt_id:pkt_id
//				qos:消息重发次数
//				topics:订阅的消息
//				topics_cnt:订阅的消息个数
//				mqttPacket:包指针
//
//	返回参数:	0-成功		其他-失败
//
//	说明:
//==========================================================
uint8 MQTT_PacketUnSubscribe ( uint16 pkt_id, const int8 *topics[], uint8 topics_cnt, MQTT_PACKET_STRUCTURE *mqttPacket )
{

    uint32 topic_len = 0, remain_len = 0;
    int16 len = 0;
    uint8 i = 0;

    if ( pkt_id == 0 )
    {
        return 1;
    }

    //计算topic长度-------------------------------------------------------------------------
    for ( ; i < topics_cnt; i++ )
    {
        if ( topics[i] == NULL )
        {
            return 2;
        }

        topic_len += strlen ( topics[i] );
    }

    //2 bytes packet id, 2 bytes topic length + topic + 1 byte reserve---------------------
    remain_len = 2 + ( topics_cnt << 1 ) + topic_len;

    //分配内存------------------------------------------------------------------------------
    MQTT_NewBuffer ( mqttPacket, remain_len + 5 );
    if ( mqttPacket->_data == NULL )
    {
        return 3;
    }

    /*************************************固定头部***********************************************/

    //固定头部----------------------头部消息-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = MQTT_PKT_UNSUBSCRIBE << 4 | 0x02;

    //固定头部----------------------剩余长度值-----------------------------------------------
    len = MQTT_DumpLength ( remain_len, mqttPacket->_data + mqttPacket->_len );
    if ( len < 0 )
    {
        MQTT_DeleteBuffer ( mqttPacket );
        return 4;
    }
    else
    {
        mqttPacket->_len += len;
    }

    /*************************************payload***********************************************/

    //payload----------------------pkt_id---------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB ( pkt_id );
    mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB ( pkt_id );

    //payload----------------------topic_name-----------------------------------------------
    for ( i = 0; i < topics_cnt; i++ )
    {
        topic_len = strlen ( topics[i] );
        mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB ( topic_len );
        mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB ( topic_len );

        strncat ( ( int8 * ) mqttPacket->_data + mqttPacket->_len, topics[i], topic_len );
        mqttPacket->_len += topic_len;
    }

    return 0;

}

//==========================================================
//	函数名称:	MQTT_UnPacketUnSubscribe
//
//	函数功能:	UnSubscribe的回复消息解包
//
//	入口参数:	rev_data:接收到的信息
//
//	返回参数:	0-成功		其他-失败
//
//	说明:
//==========================================================
uint1 MQTT_UnPacketUnSubscribe ( uint8 *rev_data )
{

    uint1 result = 1;

    if ( rev_data[2] == MOSQ_MSB ( MQTT_UNSUBSCRIBE_ID ) && rev_data[3] == MOSQ_LSB ( MQTT_UNSUBSCRIBE_ID ) )
    {
        result = 0;
    }

    return result;

}

//==========================================================
//	函数名称:	MQTT_PacketPublish
//
//	函数功能:	Pulish消息组包
//
//	入口参数:	pkt_id:pkt_id
//				topic:发布的topic
//				payload:消息体
//				payload_len:消息体长度
//				qos:重发次数
//				retain:离线消息推送
//				own:
//				mqttPacket:包指针
//
//	返回参数:	0-成功		其他-失败
//
//	说明:
//==========================================================
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 )
{

    uint32 total_len = 0, topic_len = 0;
    int32 len = 0;
    uint8 flags = 0;

    //pkt_id检查----------------------------------------------------------------------------
    if ( pkt_id == 0 )
    {
        return 1;
    }

    //$dp为系统上传数据点的指令--------------------------------------------------------------
    for ( topic_len = 0; topic[topic_len] != '\0'; ++topic_len )
    {
        if ( ( topic[topic_len] == '#' ) || ( topic[topic_len] == '+' ) )
        {
            return 2;
        }
    }

    //Publish消息---------------------------------------------------------------------------
    flags |= MQTT_PKT_PUBLISH << 4;

    //retain标志----------------------------------------------------------------------------
    if ( retain )
    {
        flags |= 0x01;
    }

    //总长度--------------------------------------------------------------------------------
    total_len = topic_len + payload_len + 2;

    //qos级别--主要用于PUBLISH(发布态)消息的,保证消息传递的次数-----------------------------
    switch ( qos )
    {
        case MQTT_QOS_LEVEL0:
            flags |= MQTT_CONNECT_WILL_QOS0;	//最多一次
            break;

        case MQTT_QOS_LEVEL1:
            flags |= 0x02;						//最少一次
            total_len += 2;
            break;

        case MQTT_QOS_LEVEL2:
            flags |= 0x04;						//只有一次
            total_len += 2;
            break;

        default:
            return 3;
    }

    //分配内存------------------------------------------------------------------------------
    MQTT_NewBuffer ( mqttPacket, total_len + 3 );
    if ( mqttPacket->_data == NULL )
    {
        return 4;
    }

    memset ( mqttPacket->_data, 0, total_len + 3 );

    /*************************************固定头部***********************************************/

    //固定头部----------------------头部消息-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = flags;

    //固定头部----------------------剩余长度值-----------------------------------------------
    len = MQTT_DumpLength ( total_len, mqttPacket->_data + mqttPacket->_len );
    if ( len < 0 )
    {
        MQTT_DeleteBuffer ( mqttPacket );
        return 5;
    }
    else
    {
        mqttPacket->_len += len;
    }

    /*************************************可变头部***********************************************/

    //可变头部----------------------写入topic长度、topic-------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB ( topic_len );
    mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB ( topic_len );

    strncat ( ( int8 * ) mqttPacket->_data + mqttPacket->_len, topic, topic_len );
    mqttPacket->_len += topic_len;
    if ( qos != MQTT_QOS_LEVEL0 )
    {
        mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB ( pkt_id );
        mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB ( pkt_id );
    }

    //可变头部----------------------写入payload----------------------------------------------
    if ( payload != NULL )
    {
        strncat ( ( int8 * ) mqttPacket->_data + mqttPacket->_len, payload, payload_len );
        mqttPacket->_len += payload_len;
    }

    return 0;

}

//==========================================================
//	函数名称:	MQTT_UnPacketPublish
//
//	函数功能:	Publish消息解包
//
//	入口参数:	flags:MQTT相关标志信息
//				pkt:指向可变头部
//				size:固定头部中的剩余长度信息
//
//	返回参数:	0-成功		其他-失败原因
//
//	说明:
//==========================================================
uint8 MQTT_UnPacketPublish ( uint8 *rev_data, int8 **topic, uint16 *topic_len, int8 **payload, uint16 *payload_len, uint8 *qos, uint16 *pkt_id )
{

    const int8 flags = rev_data[0] & 0x0F;
    uint8 *msgPtr;
    uint32 remain_len = 0;

    const int8 dup = flags & 0x08;

    *qos = ( flags & 0x06 ) >> 1;

    msgPtr = rev_data + MQTT_ReadLength ( rev_data + 1, 4, &remain_len ) + 1;

    if ( remain_len < 2 || flags & 0x01 )							//retain
    {
        return 255;
    }

    *topic_len = ( uint16 ) msgPtr[0] << 8 | msgPtr[1];
    if ( remain_len < *topic_len + 2 )
    {
        return 255;
    }

    if ( strstr ( ( int8 * ) msgPtr + 2, CMD_TOPIC_PREFIX ) != NULL )	//如果是命令下发
    {
        return MQTT_PKT_CMD;
    }

    switch ( *qos )
    {
        case MQTT_QOS_LEVEL0:									// qos0 have no packet identifier

            if ( 0 != dup )
            {
                return 255;
            }

            *topic =(char *) MQTT_MallocBuffer ( *topic_len + 1 );			//为topic分配内存
            if ( *topic == NULL )
            {
                return 255;
            }

            memset ( *topic, 0, *topic_len + 1 );
            memcpy ( *topic, ( int8 * ) msgPtr + 2, *topic_len );		//复制数据

            *payload_len = remain_len - 2 - *topic_len;			//为payload分配内存
            *payload = (char *)MQTT_MallocBuffer ( *payload_len + 1 );
            if ( *payload == NULL )								//如果失败
            {
                MQTT_FreeBuffer ( *topic );						//则需要把topic的内存释放掉
                return 255;
            }

            memset ( *payload, 0, *payload_len + 1 );
            memcpy ( *payload, ( int8 * ) msgPtr + 2 + *topic_len, *payload_len );

            break;

        case MQTT_QOS_LEVEL1:
        case MQTT_QOS_LEVEL2:

            if ( *topic_len + 2 > remain_len )
            {
                return 255;
            }

            *pkt_id = ( uint16 ) msgPtr[*topic_len + 2] << 8 | msgPtr[*topic_len + 3];
            if ( pkt_id == 0 )
            {
                return 255;
            }

            *topic =(char *) MQTT_MallocBuffer ( *topic_len + 1 );			//为topic分配内存
            if ( *topic == NULL )
            {
                return 255;
            }

            memset ( *topic, 0, *topic_len + 1 );
            memcpy ( *topic, ( int8 * ) msgPtr + 2, *topic_len );		//复制数据

            *payload_len = remain_len - 4 - *topic_len;
            *payload =(char *) MQTT_MallocBuffer ( *payload_len + 1 );		//为payload分配内存
            if ( *payload == NULL )								//如果失败
            {
                MQTT_FreeBuffer ( *topic );						//则需要把topic的内存释放掉
                return 255;
            }

            memset ( *payload, 0, *payload_len + 1 );
            memcpy ( *payload, ( int8 * ) msgPtr + 4 + *topic_len, *payload_len );

            break;

        default:
            return 255;
    }

    if ( strchr ( ( int8 * ) topic, '+' ) || strchr ( ( int8 * ) topic, '#' ) )
    {
        return 255;
    }

    return 0;

}

//==========================================================
//	函数名称:	MQTT_PacketPublishAck
//
//	函数功能:	Publish Ack消息组包
//
//	入口参数:	pkt_id:packet id
//				mqttPacket:包指针
//
//	返回参数:	0-成功		1-失败原因
//
//	说明:		当收到的Publish消息的QoS等级为1时,需要Ack回复
//==========================================================
uint1 MQTT_PacketPublishAck ( uint16 pkt_id, MQTT_PACKET_STRUCTURE *mqttPacket )
{

    MQTT_NewBuffer ( mqttPacket, 4 );
    if ( mqttPacket->_data == NULL )
    {
        return 1;
    }

    /*************************************固定头部***********************************************/

    //固定头部----------------------头部消息-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = MQTT_PKT_PUBACK << 4;

    //固定头部----------------------剩余长度-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = 2;

    /*************************************可变头部***********************************************/

    //可变头部----------------------pkt_id长度-----------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = pkt_id >> 8;
    mqttPacket->_data[mqttPacket->_len++] = pkt_id & 0xff;

    return 0;

}

//==========================================================
//	函数名称:	MQTT_UnPacketPublishAck
//
//	函数功能:	Publish Ack消息解包
//
//	入口参数:	rev_data:收到的数据
//
//	返回参数:	0-成功		1-失败原因
//
//	说明:
//==========================================================
uint1 MQTT_UnPacketPublishAck ( uint8 *rev_data )
{

    if ( rev_data[1] != 2 )
    {
        return 1;
    }

    if ( rev_data[2] == MOSQ_MSB ( MQTT_PUBLISH_ID ) && rev_data[3] == MOSQ_LSB ( MQTT_PUBLISH_ID ) )
    {
        return 0;
    }
    else
    {
        return 1;
    }

}

//==========================================================
//	函数名称:	MQTT_PacketPublishRec
//
//	函数功能:	Publish Rec消息组包
//
//	入口参数:	pkt_id:packet id
//				mqttPacket:包指针
//
//	返回参数:	0-成功		1-失败原因
//
//	说明:		当收到的Publish消息的QoS等级为2时,先收到rec
//==========================================================
uint1 MQTT_PacketPublishRec ( uint16 pkt_id, MQTT_PACKET_STRUCTURE *mqttPacket )
{

    MQTT_NewBuffer ( mqttPacket, 4 );
    if ( mqttPacket->_data == NULL )
    {
        return 1;
    }

    /*************************************固定头部***********************************************/

    //固定头部----------------------头部消息-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = MQTT_PKT_PUBREC << 4;

    //固定头部----------------------剩余长度-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = 2;

    /*************************************可变头部***********************************************/

    //可变头部----------------------pkt_id长度-----------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = pkt_id >> 8;
    mqttPacket->_data[mqttPacket->_len++] = pkt_id & 0xff;

    return 0;

}

//==========================================================
//	函数名称:	MQTT_UnPacketPublishRec
//
//	函数功能:	Publish Rec消息解包
//
//	入口参数:	rev_data:接收到的数据
//
//	返回参数:	0-成功		1-失败
//
//	说明:
//==========================================================
uint1 MQTT_UnPacketPublishRec ( uint8 *rev_data )
{

    if ( rev_data[1] != 2 )
    {
        return 1;
    }

    if ( rev_data[2] == MOSQ_MSB ( MQTT_PUBLISH_ID ) && rev_data[3] == MOSQ_LSB ( MQTT_PUBLISH_ID ) )
    {
        return 0;
    }
    else
    {
        return 1;
    }

}

//==========================================================
//	函数名称:	MQTT_PacketPublishRel
//
//	函数功能:	Publish Rel消息组包
//
//	入口参数:	pkt_id:packet id
//				mqttPacket:包指针
//
//	返回参数:	0-成功		1-失败原因
//
//	说明:		当收到的Publish消息的QoS等级为2时,先收到rec,再回复rel
//==========================================================
uint1 MQTT_PacketPublishRel ( uint16 pkt_id, MQTT_PACKET_STRUCTURE *mqttPacket )
{

    MQTT_NewBuffer ( mqttPacket, 4 );
    if ( mqttPacket->_data == NULL )
    {
        return 1;
    }

    /*************************************固定头部***********************************************/

    //固定头部----------------------头部消息-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = MQTT_PKT_PUBREL << 4 | 0x02;

    //固定头部----------------------剩余长度-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = 2;

    /*************************************可变头部***********************************************/

    //可变头部----------------------pkt_id长度-----------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = pkt_id >> 8;
    mqttPacket->_data[mqttPacket->_len++] = pkt_id & 0xff;

    return 0;

}

//==========================================================
//	函数名称:	MQTT_UnPacketPublishRel
//
//	函数功能:	Publish Rel消息解包
//
//	入口参数:	rev_data:接收到的数据
//
//	返回参数:	0-成功		1-失败
//
//	说明:
//==========================================================
uint1 MQTT_UnPacketPublishRel ( uint8 *rev_data, uint16 pkt_id )
{

    if ( rev_data[1] != 2 )
    {
        return 1;
    }

    if ( rev_data[2] == MOSQ_MSB ( pkt_id ) && rev_data[3] == MOSQ_LSB ( pkt_id ) )
    {
        return 0;
    }
    else
    {
        return 1;
    }

}

//==========================================================
//	函数名称:	MQTT_PacketPublishComp
//
//	函数功能:	Publish Comp消息组包
//
//	入口参数:	pkt_id:packet id
//				mqttPacket:包指针
//
//	返回参数:	0-成功		1-失败原因
//
//	说明:		当收到的Publish消息的QoS等级为2时,先收到rec,再回复rel
//==========================================================
uint1 MQTT_PacketPublishComp ( uint16 pkt_id, MQTT_PACKET_STRUCTURE *mqttPacket )
{

    MQTT_NewBuffer ( mqttPacket, 4 );
    if ( mqttPacket->_data == NULL )
    {
        return 1;
    }

    /*************************************固定头部***********************************************/

    //固定头部----------------------头部消息-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = MQTT_PKT_PUBCOMP << 4;

    //固定头部----------------------剩余长度-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = 2;

    /*************************************可变头部***********************************************/

    //可变头部----------------------pkt_id长度-----------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = pkt_id >> 8;
    mqttPacket->_data[mqttPacket->_len++] = pkt_id & 0xff;

    return 0;

}

//==========================================================
//	函数名称:	MQTT_UnPacketPublishComp
//
//	函数功能:	Publish Comp消息解包
//
//	入口参数:	rev_data:接收到的数据
//
//	返回参数:	0-成功		1-失败
//
//	说明:
//==========================================================
uint1 MQTT_UnPacketPublishComp ( uint8 *rev_data )
{

    if ( rev_data[1] != 2 )
    {
        return 1;
    }

    if ( rev_data[2] == MOSQ_MSB ( MQTT_PUBLISH_ID ) && rev_data[3] == MOSQ_LSB ( MQTT_PUBLISH_ID ) )
    {
        return 0;
    }
    else
    {
        return 1;
    }

}

//==========================================================
//	函数名称:	MQTT_PacketPing
//
//	函数功能:	心跳请求组包
//
//	入口参数:	mqttPacket:包指针
//
//	返回参数:	0-成功		1-失败
//
//	说明:
//==========================================================
uint1 MQTT_PacketPing ( MQTT_PACKET_STRUCTURE *mqttPacket )
{

    MQTT_NewBuffer ( mqttPacket, 2 );
    if ( mqttPacket->_data == NULL )
    {
        return 1;
    }

    /*************************************固定头部***********************************************/

    //固定头部----------------------头部消息-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = MQTT_PKT_PINGREQ << 4;

    //固定头部----------------------剩余长度-------------------------------------------------
    mqttPacket->_data[mqttPacket->_len++] = 0;

    return 0;

}

  

#ifndef _MQTTKIT_H_
#define _MQTTKIT_H_


#include "types.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			12

#define MQTT_SUBSCRIBE_ID		1

#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 );


/*--------------------------------命令下发解包--------------------------------*/
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 char *topic, 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

  

#include "main.h"


int NetApi_SendData ( unsigned char *data, unsigned short len )
{
    if ( g_selchip == CHIP_W5500 )
    {
       // W5500_SendData ( data, len );
    }
    if ( g_selchip == CHIP_SIM900 )
    {
       // Sim900_SendData( data, len );
    }
    if ( g_selchip == CHIP_ESP8266 )
    {
        Esp8266_SendData ( data, len );
    }
  
}


int NetApi_AccessNetwork ( void )
{
    if ( g_selchip == CHIP_W5500 )
    {
       //return  W5500_AccessNetwork (  );
    }
    if ( g_selchip == CHIP_SIM900 )
    {
       //return Sim900_AccessNetwork (  );
    }
    if ( g_selchip == CHIP_ESP8266 )
    {
       return Esp8266_AccessNetwork (  );
    }
}
unsigned char *NetApi_RecvData ( unsigned short timeOut )
{
    if ( g_selchip == CHIP_W5500 )
    {
       //return  W5500_RecvData ( timeOut );
    }
    if ( g_selchip == CHIP_SIM900 )
    {
       //return Sim900_RecvData (timeOut  );
    }
    if ( g_selchip == CHIP_ESP8266 )
    {
       return Esp8266_RecvData ( timeOut );
    }
}
int NetApi_TcpConnect ( void )
{
    if ( g_selchip == CHIP_W5500 )
    {
       //return  W5500_TcpConnect (  );
    }
    if ( g_selchip == CHIP_SIM900 )
    {
       //return Sim900_TcpConnect (  );
    }
    if ( g_selchip == CHIP_ESP8266 )
    {
       return Esp8266_TcpConnect (  );
    }
}

void NetApi_InitAccessNetwork(void)
{
    if ( g_selchip == CHIP_W5500 )
    {
       // W5500_InitAccessNetwork (  );
    }
    if ( g_selchip == CHIP_SIM900 )
    {
       // Sim900_InitAccessNetwork (  );
    }
    if ( g_selchip == CHIP_ESP8266 )
    {
        Esp8266_InitAccessNetwork (  );
    }
}
void NetApi_InitTcpConnect(void)
{
    if ( g_selchip == CHIP_W5500 )
    {
       // W5500_InitTcpConnect (  );
    }
    if ( g_selchip == CHIP_SIM900 )
    {
       // Sim900_InitTcpConnect (  );
    }
    if ( g_selchip == CHIP_ESP8266 )
    {
        Esp8266_InitTcpConnect (  );
    }
}

  

#ifndef _NETAPI_H_
#define _NETAPI_H_


int NetApi_SendData ( unsigned char *data, unsigned short len );


int NetApi_AccessNetwork ( void );
unsigned char *NetApi_RecvData ( unsigned short timeOut );
int NetApi_TcpConnect ( void );

void NetApi_InitAccessNetwork(void);
void NetApi_InitTcpConnect(void);

#endif

  

#include "main.h"

void Esp8266_Rst(void)
{
  pinMode(PB1, OUTPUT);

  digitalWrite(PB1,LOW);
  delay(10);
  digitalWrite(PB1,HIGH);
  delay(4000); //等待复位完成4second
  AT_ClearPara();
  
}

int Esp8266_AccessNetwork ( void )
{
    char strTemp[100] = {0};   
    sprintf ( strTemp, "AT+CWJAP=\"%s\",\"%s\"\r\n",g_SysPara.wifi_ssid, g_SysPara.wifi_password);
    
    if ( AT_SendCmd ( "AT\r\n", "OK", 100 )!=0 )
    {
        delay ( 1500 );

        if ( AT_SendCmd ( "AT\r\n", "OK", 100 )!=0 )
        {
          return 1;
        }
    }

    if ( AT_SendCmd ( "ATE0\r\n", "OK", 100 )!=0 )
    {

        delay ( 1500 );
        if ( AT_SendCmd ( "AT\r\n", "OK", 100 )!=0 )
        {            
            return 1;            
        }
    }

    if ( AT_SendCmd ( "AT+CWMODE=1\r\n", "OK", 100 )!=0 ) // ?????station
    {
        return 1;
    }


    if ( AT_SendCmd ( "AT+CIPMODE=0\r\n", "OK", 100 ) !=0) // 0-???????
    {
        return 1;
    }

    if ( AT_SendCmd ( strTemp, "CONNECTED", 13000 ) !=0) //?????·????
    {
        if ( AT_SendCmd ( strTemp, "CONNECTED", 13000 )!=0 )
        {
            return 1;
        }
    }

    return 0;    
    
}

int Esp8266_TcpConnect ( void )
{
    char strTemp[200] = {0};

    sprintf ( strTemp, "AT+CIPSTART=\"TCP\",\"%s\",%s\r\n", g_SysPara.host_ip, g_SysPara.host_port );   
    if ( AT_SendCmd ( strTemp, "CONNECT", 22500 )!=0 )
    {
        delay ( 3500 );
        if ( AT_SendCmd ( strTemp, "CONNECT", 22500 )!=0 )
        {            
            return 1;            
        }
    }
    return 0;
}
void Esp8266_InitAccessNetwork(void)
{
}
void Esp8266_InitTcpConnect(void)
{
}

int Esp8266_SendData ( unsigned char *data, unsigned short len )
{
    return AT_SendData(data,len);
}


unsigned char g_Buffer[1024];

unsigned char *Esp8266_RecvData ( unsigned short timeOut )
{
    int tt=0;
    int i;
    unsigned long num = 0;
    String strTemp="";

    char *ptrIPD = NULL;
  
    num = Serial2.available();
    if((num==0) && (timeOut==0))return NULL;

    while(1)
    {
        delay ( 1 );
        tt++;
        if(tt>timeOut)
        {
              //关闭连接,从头开始
              ReSet_SystemStatus();
              break;
        }
        
        num = Serial2.available();
        if ( num > 0 )
        {            

            strTemp="";
            for(i=0;i<1024;i++)
            {
                if(Serial2.available())
                {
                  g_Buffer[i]= Serial2.read();
                  strTemp=strTemp+(char)g_Buffer[i];
                }
                else
                {
                  delay ( 1000 );
                  if(!Serial2.available()) break;
                }
            }

            Serial.print(strTemp);
            

            //8266接收数据格式
            ptrIPD = strstr ( ( char * ) g_Buffer, "IPD," );
            if ( ptrIPD != NULL )
            {
                ptrIPD = strchr ( ptrIPD, ':' );              
                if ( ptrIPD != NULL )
                {
                    ptrIPD++;
                    return ( unsigned char * ) ( ptrIPD );
                }
            }

        }       

    }
    

    return NULL;                       

}

  

#ifndef _ESP8266_H_
#define _ESP8266_H_

void Esp8266_Rst(void);

int Esp8266_SendData ( unsigned char *data, unsigned short len );


int Esp8266_AccessNetwork ( void );
unsigned char *Esp8266_RecvData ( unsigned short timeOut );
int Esp8266_TcpConnect ( void );

void Esp8266_InitAccessNetwork(void);
void Esp8266_InitTcpConnect(void);

#endif

  

/**
******************************************************************************
* @file    			main.c
* @author  			重庆光明顶工作室:物联网应用创新中心
* @version 			V1.0
* @date    			2015-02-14
* @brief   			用3.5.0版本库建的工程模板
* @attention
*
*               内网测试,请适配版与路由器相接。并确认路由器的
*               DHCP功能处于打开的状态。
******************************************************************************
*/
#include "main.h"

//---------------------------------
//云服务选择:每种云的JSON格式数据不同。
#define CLOUD_ONENET  0//中移物联网
#define CLOUD_BAIDU  	1//百度云
#define CLOUD_ALI     2//阿里云
#define CLOUD_TENCENT 3//腾讯云
#define CLOUD_TLINK   4//TLINK云  :数据直接上传到云服务。

int g_selcloud = CLOUD_ONENET;


//---------------------------------
//网络选择
int  g_selchip = USE_CHIP;

//---------------------------------
//系统参数
SYS_PARA g_SysPara;
void Net_DefPara ( void );

//--------------------------------
#define ST_MQTT_INIT        0
#define ST_MQTT_ACESSNET    1
#define ST_MQTT_TCP         2
#define ST_MQTT_CONNECTED   3
#define ST_MQTT_SUBSCRIBE   4
#define ST_MQTT_WORK        5


uint8  g_SysStatus;
void ReSet_SystemStatus ( void )
{
    g_SysStatus = ST_MQTT_INIT;
}

//mqtt fun
int OneNet_Connect ( void );
int OneNet_Subscribe ( const char *topic );
int OneNet_Publish ( char *topic, const char *msg );
void OneNet_HeartBeat ( void );
void OneNet_PollRecv ( void );





void Net_DefPara ( void )
{

    //wifi para
    strcpy ( g_SysPara.wifi_ssid, "yan" );
    strcpy ( g_SysPara.wifi_password, "12345678" );

    //server ip,  port
    //不同的云,域名参数不同
    if ( g_selcloud == CLOUD_ONENET )
    {
        strcpy ( g_SysPara.host_ip, "183.230.40.39" );//固定,有线DNS解析"183.230.40.39" ,mqtt.heclouds.com       
        strcpy ( g_SysPara.host_port, "6002" );

        //mqtt login: clientid, username,passwd
        strcpy ( g_SysPara.mqtt_clientid, "833570179" );//deviceid
        strcpy ( g_SysPara.mqtt_username, "466095" );//produceid
        strcpy ( g_SysPara.mqtt_passwd, "devti" );//password

    }
    if ( g_selcloud == CLOUD_BAIDU )
    {
        strcpy ( g_SysPara.host_ip, "apgvzfj.iot.bj.baidubce.com" );//变化
        strcpy ( g_SysPara.host_port, "1883" );
				
				//mqtt login: clientid, username,passwd
				strcpy ( g_SysPara.mqtt_clientid, "thingidp@apgvzfjlgate]1644332494|MD5" );
        strcpy ( g_SysPara.mqtt_username, "thingidp@apgvzfjlgate]1644332494|MD5" );
        strcpy ( g_SysPara.mqtt_passwd, "56df928bcb875e9a91eb9f47c476278c" );
				
    }
    if ( g_selcloud == CLOUD_ALI )
    {
        strcpy ( g_SysPara.host_ip, "a13lidNT5LV.iot-as-mqtt.cn-shanghai.aliyuncs.com" );
        strcpy ( g_SysPara.host_port, "1883" );
			
				//mqtt login: clientid, username,passwd
				strcpy ( g_SysPara.mqtt_clientid, "a13lidNT5LV.gatelsecuremode=2,signmethod=hmacsha256,timestamp=2524608000000|" );//变化
        strcpy ( g_SysPara.mqtt_username, "gate&a13lidNT5LV" );
        strcpy ( g_SysPara.mqtt_passwd, "f5a95cc2d99ca99c93708d21f6b00162f8f26d4b2e3bf584d62f2e65ac8d0b4d" );
				
    }
    if ( g_selcloud == CLOUD_TENCENT )
    {
        strcpy ( g_SysPara.host_ip, "iotcloud-mqtt.gz.tencentdevices.com" );
        strcpy ( g_SysPara.host_port, "1883" );
			
				//mqtt login: clientid, username,passwd
				strcpy ( g_SysPara.mqtt_clientid, "N4TX5JROKOsim" );
        strcpy ( g_SysPara.mqtt_username, "N4TX5JROKOsim;12010126;N7MYl;1680383966" );
        strcpy ( g_SysPara.mqtt_passwd, "aa1357ca2b8f40155ce977265131568926ef5f41acee6b097540508348fb7787;hmacsha256" );
    }
		
		if ( g_selcloud == CLOUD_TLINK )
    {
        strcpy ( g_SysPara.host_ip, "mq.tlink.io" );
        strcpy ( g_SysPara.host_port, "1883" );
			
				//mqtt login: clientid, username,passwd
				strcpy ( g_SysPara.mqtt_clientid, "373U788J8LZ16781" );
        strcpy ( g_SysPara.mqtt_username, "15922524833" );//登录平台的用户名
        strcpy ( g_SysPara.mqtt_passwd, "yan750924" );//登录平台的密码
    }


    //??
    strcpy ( g_SysPara.mqtt_subtopic1, "$crep" );
    strcpy ( g_SysPara.mqtt_subtopic2, "cmd/#" );

    strcpy ( g_SysPara.mqtt_pubtopic1, "$dp" );
    strcpy ( g_SysPara.mqtt_pubtopic2, "data/devti" );

}

//------------------------------------------------------------------
//状态机函数

//初始状态
void ST_MQTT_INITf ( void )
{
    NetApi_InitAccessNetwork();    
    g_SysStatus = ST_MQTT_ACESSNET;
}
//接入网络
void ST_MQTT_ACESSNETf ( void )
{
    int retcode = 0;
    retcode = NetApi_AccessNetwork();    
    if ( retcode == 0 )
    {
        g_SysStatus = ST_MQTT_TCP;        
        NetApi_InitTcpConnect();        
    }
}

//TCP连接
void ST_MQTT_TCPf ( void )
{
    int retcode = 0;    
    retcode = NetApi_TcpConnect();
    if ( retcode == 0 )
    {
        g_SysStatus = ST_MQTT_CONNECTED;
    }
}
//登录
void ST_MQTT_CONNECTEDf ( void )
{
    int retcode = 0;
    retcode = OneNet_Connect();

    if ( retcode == 0 )
    {
        g_SysStatus = ST_MQTT_SUBSCRIBE;
    }
    else
    {
        g_SysStatus = ST_MQTT_TCP;//重新连接
    }

}
//订阅主题
void ST_MQTT_SUBSCRIBEf ( void )
{
    if ( OneNet_Subscribe ( g_SysPara.mqtt_subtopic2 ) == 0 )
    {       
				if ( OneNet_Subscribe ( g_SysPara.mqtt_subtopic1 ) == 0 ) {;} //订阅 $crep 返回都不成功
				{
						g_SysStatus = ST_MQTT_WORK;
						return;
				}       
    }

    g_SysStatus = ST_MQTT_CONNECTED;//重新连接

}

//工作状态
void ST_MQTT_WORKf ( void )
{
    static int t_heart = 0;
    static int t_data = 0;

    delay ( 1 );

    //每3秒发布一个数据
    t_data++;
    if ( t_data > 3000 )
    {
        char msg[] = "{\"tmp\":27}";
        t_data = 0;
        OneNet_Publish ( g_SysPara.mqtt_pubtopic1, msg );
        delay ( 2000 );
        OneNet_Publish ( g_SysPara.mqtt_pubtopic2, msg );
    }



    //每10秒心跳包数据
    t_heart++;
    if ( t_heart > 10000 )
    {
        t_heart = 0;
        OneNet_HeartBeat();

        t_data = 0;
    }

    OneNet_PollRecv();


}



//------------------------------------------------------------
//MQTT封装
//如果已经连接登录,再次连接,则不返回登录成功,没有应答信息

int OneNet_Connect ( void )
{

    MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};					//协议包
    unsigned char *dataPtr ;
    int status = 1;


    //Keep Alive=256 秒= 4分钟
    //最小数值为0,标识客户端不断开
    if ( MQTT_PacketConnect ( g_SysPara.mqtt_username, g_SysPara.mqtt_passwd, g_SysPara.mqtt_clientid, 256, 0, MQTT_QOS_LEVEL0, NULL, NULL, 0, &mqttPacket ) == 0 )
    {
        //25   (37)
        //10 23 00 04 4D 51 54 54 04 C0   01 00 00 09 36 32 32 39 32 33     36 39 35 00 06 33 36 38 37 36    33 00 04 67 61 74 65

        printf ( "Tips:	登录云服务\r\n" );

        NetApi_SendData ( mqttPacket._data, mqttPacket._len ); //发送出去
        dataPtr = NetApi_RecvData ( 5000 );//超时接收数据
       
        if ( dataPtr != NULL )
        {
            //对接收的数据进行分析
            if ( MQTT_UnPacketRecv ( dataPtr ) == MQTT_PKT_CONNACK )
            {
                switch ( MQTT_UnPacketConnectAck ( dataPtr ) )
                {
                    case 0:
                        printf ( "Tips:	连接成功\r\n" );
                        status = 0;
                        break;

                    case 1:
                        printf ( "WARN:	连接失败:协议错误\r\n" );
                        break;
                    case 2:
                        printf ( "WARN:	连接失败:非法的clientid\r\n" );
                        break;
                    case 3:
                        printf ( "WARN:	连接失败:服务器失败\r\n" );
                        break;
                    case 4:
                        printf ( "WARN:	连接失败:用户名或密码错误\r\n" );
                        break;
                    case 5:
                        printf ( "WARN:	连接失败:非法链接(比如token非法)\r\n" );
                        break;

                    default:
                        printf ( "ERR:	连接失败:未知错误\r\n" );
                        break;
                }
            }

        }


        MQTT_DeleteBuffer ( &mqttPacket );								//删包
    }


    return status;

}

//==========================================================
//	函数名称:	OneNet_Subscribe
//
//	函数功能:	订阅
//
//	入口参数:	topic:订阅的topic
//
//	返回参数:	0-成功	1-失败
//
//	说明:
//==========================================================
int OneNet_Subscribe ( const char *topic )
{

    unsigned char *dataPtr ;
    int status = 1;

    MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};


    printf ( "Subscribe:topic=%s\n", topic );


    //-------------------------------------------步骤一:组包----------------------------------------------
    if ( MQTT_PacketSubscribe ( MQTT_SUBSCRIBE_ID, MQTT_QOS_LEVEL1,  topic,  &mqttPacket ) == 0 )
    {
        //82 0A 00 14 00 05 24 63 72 65 78 02 00 00 00 33 33 35 37 30 E0
        //----------------------------------------------步骤二:发送数据-----------------------------------------------
        
       NetApi_SendData ( mqttPacket._data, mqttPacket._len ); //发送出去
       dataPtr = NetApi_RecvData ( 5000 );//超时接收数据
        

        //分析接收的数据
        if ( dataPtr != NULL )
        {
            if ( MQTT_UnPacketRecv ( dataPtr ) == MQTT_PKT_SUBACK ) //订阅应答
            {
                if ( MQTT_UnPacketSubscribe ( dataPtr ) == 0 )
                {
                    status = 0;
                    printf ( "Tips:	MQTT Subscribe OK\r\n" );
                }
            }

        }

        //---------------------------------------------步骤三:删包------------------------------------------------
        MQTT_DeleteBuffer ( &mqttPacket );
    }

    return status;

}
//==========================================================
//	函数名称:	OneNet_Publish
//
//	函数功能:	发布消息
//
//	入口参数:	topic:发布的主题
//				msg:消息内容
//
//	返回参数:	0-成功	1-失败
//
//	说明:
//==========================================================
uint1 MQTT_PacketSaveData ( char *strTopic, int16 send_len, int8 *type_bin_head, MQTT_PACKET_STRUCTURE *mqttPacket )
{

    if ( strcmp ( strTopic, "$dp" ) == 0 ) //支持onenet上云,JSON格式
    {
        //onenet特殊协议 "$dp", send_len + 3
        if ( MQTT_PacketPublish ( MQTT_PUBLISH_ID, "$dp", NULL, send_len + 3, MQTT_QOS_LEVEL0, 0, 1, mqttPacket ) == 0 )
        {
            mqttPacket->_data[mqttPacket->_len++] = 3;					//json类型3

            mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB ( send_len );
            mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB ( send_len );

            return 0;
        }
    }
    else
    {
        //普通透明传输协议  strTopic, send_len
        if ( MQTT_PacketPublish ( MQTT_PUBLISH_ID, strTopic, NULL, send_len, MQTT_QOS_LEVEL0, 0, 1, mqttPacket ) == 0 )
        {
            return 0;
        }

    }

    return 1;




}
int OneNet_Publish ( char *topic, const char *msg )
{

    short body_len = 0, i = 0;
    MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};

    printf ( "Publish Topic: %s, Msg: %s\r\n", topic, msg );

    body_len = strlen ( msg );

    if ( MQTT_PacketSaveData ( topic,  body_len, NULL,  &mqttPacket ) == 0 )							//??
    {
        for ( i = 0; i < body_len; i++ )
        {
            mqttPacket._data[mqttPacket._len++] = msg[i];
        }        
        NetApi_SendData ( mqttPacket._data, mqttPacket._len );
        
        
        MQTT_DeleteBuffer ( &mqttPacket );															//??
    }

    return 0;

}

//==========================================================
//	函数名称:	OneNet_HeartBeat
//
//	函数功能:	心跳检测
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:
//==========================================================
void OneNet_HeartBeat ( void )
{

    MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};


    //  unsigned char sCount = 3, *dataPtr;

    //---------------------------------------------步骤一:组包---------------------------------------------
    if ( MQTT_PacketPing ( &mqttPacket ) )
    {
        return;
    }


    {
        //----------------------------------------------步骤二:发送数据------------------------------------------        
        NetApi_SendData ( mqttPacket._data, mqttPacket._len );      
        
    }

    //delay_ms(10);
    //---------------------------------------------???:??---------------------------------------------
    MQTT_DeleteBuffer ( &mqttPacket );

}

void OneNet_PollRecv ( void )
{

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

    char *req_payload = NULL;
    char *cmdid_topic = NULL;
    unsigned short topic_len;

    unsigned short req_len = 0;

    unsigned char type = 0;

    short result = 0;

    char *dataPtr = NULL;
    char numBuf[10];
    int num = 0;
    uint8 qos;
    uint16 pkt_id;

    uint8 *cmd;
    cmd = NetApi_RecvData ( 0 );    //检查接收数据  

    if ( cmd == NULL )
    {
        return;
    }

    type = MQTT_UnPacketRecv ( cmd );
    switch ( type )
    {
        case MQTT_PKT_PINGRESP://心跳响应

            break;
        case MQTT_PKT_CMD:															//命令下发

            result = MQTT_UnPacketCmd ( cmd, &cmdid_topic, &req_payload, &req_len );	//解出topic和消息体
            if ( result == 0 )
            {
                printf ( "cmdid: %s, req: %s, req_len: %d\r\n", cmdid_topic, req_payload, req_len );

                if ( MQTT_PacketCmdResp ( cmdid_topic, req_payload, &mqttPacket ) == 0 )	//命令回复组包
                {
                    printf ( "Tips:	Send CmdResp\r\n" );
                    NetApi_SendData ( mqttPacket._data, mqttPacket._len );
                    
                    MQTT_DeleteBuffer ( &mqttPacket );									//删包
                }
            }

            break;
        case MQTT_PKT_PUBLISH:														//接收的Publish消息


            result = MQTT_UnPacketPublish ( cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id );
            if ( result == 0 )
            {

                // int  num;

                printf (  "topic: %s\r\npayload: %s\r\n", cmdid_topic, req_payload );


                //包的处理方法及分析,网关信息,命令包,进行转发处理
                //去掉空格
                //int i,m=0, num;
                num = strlen ( req_payload );


                //通过串口发送出去-----命令的处理
                // Usart3_SendString ( ( unsigned char * ) req_payload, num );



                switch ( qos )
                {
                    case 1:															//收到publish的qos为1,设备需要回复Ack

                        if ( MQTT_PacketPublishAck ( pkt_id, &mqttPacket ) == 0 )
                        {
                            printf (  "Tips:	Send PublishAck\r\n" );                            
                            NetApi_SendData ( mqttPacket._data, mqttPacket._len );                           
                            MQTT_DeleteBuffer ( &mqttPacket );
                        }

                        break;

                    case 2:															//收到publish的qos为2,设备先回复Rec
                        //平台回复Rel,设备再回复Comp
                        if ( MQTT_PacketPublishRec ( pkt_id, &mqttPacket ) == 0 )
                        {
                            printf (  "Tips:	Send PublishRec\r\n" );
                            NetApi_SendData ( mqttPacket._data, mqttPacket._len );
                            MQTT_DeleteBuffer ( &mqttPacket );
                        }

                        break;

                    default:
                        break;
                }
            }



            break;
        case MQTT_PKT_PUBACK:														//发送Publish消息,平台回复的Ack

            if ( MQTT_UnPacketPublishAck ( cmd ) == 0 )
            {
                printf ( "Tips:	MQTT Publish Send OK\r\n" );
            }

            break;
        case MQTT_PKT_PUBREC:														//发送Publish消息,平台回复的Rec,设备需回复Rel消息

            if ( MQTT_UnPacketPublishRec ( cmd ) == 0 )
            {
                printf ( "Tips:	Rev PublishRec\r\n" );
                if ( MQTT_PacketPublishRel ( MQTT_PUBLISH_ID, &mqttPacket ) == 0 )
                {
                    printf (  "Tips:	Send PublishRel\r\n" );                    
                    NetApi_SendData ( mqttPacket._data, mqttPacket._len );                    
                    MQTT_DeleteBuffer ( &mqttPacket );
                }
            }

            break;
        case MQTT_PKT_PUBREL:														//收到Publish消息,设备回复Rec后,平台回复的Rel,设备需再回复Comp

            if ( MQTT_UnPacketPublishRel ( cmd, pkt_id ) == 0 )
            {
                printf (  "Tips:	Rev PublishRel\r\n" );
                if ( MQTT_PacketPublishComp ( MQTT_PUBLISH_ID, &mqttPacket ) == 0 )
                {
                    printf (  "Tips:	Send PublishComp\r\n" );
                   
                    NetApi_SendData ( mqttPacket._data, mqttPacket._len );
                    MQTT_DeleteBuffer ( &mqttPacket );
                }
            }

            break;

        case MQTT_PKT_PUBCOMP:														//发送Publish消息,平台返回Rec,设备回复Rel,平台再返回的Comp

            if ( MQTT_UnPacketPublishComp ( cmd ) == 0 )
            {
                printf ( "Tips:	Rev PublishComp\r\n" );
            }

            break;
        case MQTT_PKT_SUBACK:														//发送Subscribe消息的Ack

            if ( MQTT_UnPacketSubscribe ( cmd ) == 0 )
            {
                printf ( "Tips:	MQTT Subscribe OK\r\n" );
            }
            else
            {
                printf (  "Tips:	MQTT Subscribe Err\r\n" );
            }

            break;
        case MQTT_PKT_UNSUBACK:														//发送UnSubscribe消息的Ack

            if ( MQTT_UnPacketUnSubscribe ( cmd ) == 0 )
            {
                printf (  "Tips:	MQTT UnSubscribe OK\r\n" );
            }
            else
            {
                printf (  "Tips:	MQTT UnSubscribe Err\r\n" );
            }

            break;
        default:
            result = -1;
            break;
    }

    if ( result == -1 )
    {
        return;
    }

    dataPtr = strchr ( req_payload, '}' );					//搜索'}'

    if ( dataPtr != NULL && result != -1 )					//如果找到了
    {
        dataPtr++;

        while ( *dataPtr >= '0' && *dataPtr <= '9' )		//判断是否是下发的命令控制数据
        {
            numBuf[num++] = *dataPtr++;
        }

        num = atoi ( ( const char * ) numBuf );				//转为数值形式
    }

    if ( type == MQTT_PKT_CMD || type == MQTT_PKT_PUBLISH )
    {
        MQTT_FreeBuffer ( cmdid_topic );
        MQTT_FreeBuffer ( req_payload );
    }

}

//----------------------------------------------
void System_Init(){
  
  Esp8266_Rst();
  Serial.begin(115200);  //usb usart monitor
  Serial2.begin(115200);//at
  
  Net_DefPara();//参数初始化
  g_SysStatus = ST_MQTT_INIT;
  
}



void System_main() {
  switch ( g_SysStatus )
        {
            case ST_MQTT_INIT:  //初始化参数
                ST_MQTT_INITf();
                break;
            case ST_MQTT_ACESSNET:  //加入到网络DHCP,解析域名
                ST_MQTT_ACESSNETf();
                break;

            case ST_MQTT_TCP: //TCP连接云 183.230.40.39:6002
                ST_MQTT_TCPf();
                break;
            case ST_MQTT_CONNECTED://MQTT登录  produceID(user),auth(password),deviceID(clientID)
                ST_MQTT_CONNECTEDf();
                break;
            case ST_MQTT_SUBSCRIBE://订阅主题  $crep,  其他cmd/#
                ST_MQTT_SUBSCRIBEf();
                break;
            case ST_MQTT_WORK:  //MQTT循环工作状态,publish
                ST_MQTT_WORKf();
                break;
        }

}

  

#ifndef MAIN_HEAD
#define MAIN_HEAD

//#include "arduino.h"
#include <arduino.h>
#include "stdio.h"
#include "string.h"

#include "AtCommand.h"
#include "esp8266.h"

#include "MqttKit.h"
#include "netapi.h"

//---------------------------------
//网络选择
#define CHIP_W5500    0
#define CHIP_SIM900    1
#define CHIP_ESP8266  2

//选择使用什么硬件
#define USE_CHIP   CHIP_ESP8266
extern int  g_selchip;



typedef struct
{
    char  saveflag;//存储标志0x55

    char wifi_ssid[50];		// = "yan1234";
    char wifi_password[50];		// = "12345678";


    char host_ip[50];		// = "mqtt.heclouds.com";
    char host_port[10];		//"6002"

    char mqtt_clientid[20];		//"622913695":deviceID
    char mqtt_username[20];	//"368763":producei
    char mqtt_passwd[20];		// "gate":author

    char mqtt_subtopic1[50];// "$crep"  //除onenet外,其他不支持$
    char mqtt_subtopic2[50];// "cmd/#"

    char mqtt_pubtopic1[50];// "$dp"		//除onenet外,其他不支持$
    char mqtt_pubtopic2[50];// "data/gate"

} SYS_PARA;

extern SYS_PARA g_SysPara;

void ReSet_SystemStatus ( void );

void System_Init();
void System_main();

#endif

  

#ifndef _TYPE_H_
#define _TYPE_H_

#define	MAX_SOCK_NUM		8	/**< Maxmium number of socket  */

#define int8 char

#define vint8 volatile char 

#define uint8  unsigned char 

#define vuint8  volatile unsigned char 

#define int16  int 

#define uint16 unsigned short 

#define int32 long

#define uint32 unsigned long

#define u_char uint8			
#define SOCKET  uint8 			

/*
typedef union _un_l2cval
{
    u_long	lVal;
    u_char	cVal[4];
} un_l2cval;

typedef union _un_i2cval
{
    u_int	iVal;
    u_char	cVal[2];
} un_i2cval;
*/

#define  uint1  unsigned char
#endif		/* _TYPE_H_ */

  

标签:ESP01,ONENET,return,ARDUINO,len,topic,MQTT,mqttPacket,data
来源: https://www.cnblogs.com/cqmcu/p/15905400.html