目录

前言

一、 实现代码

1.1 EC20.H

1.2 EC20.C


前言

每天进步,记录开发历程,希望可以和大家交流记录

一、 实现代码

1.1 EC20.H

#ifndef EC20_H
#define EC20_H

#include "FreeRTOS.h"
#include "queue.h"
#include "util.h"
#include "stdbool.h"


#define EC20_MAX_SIZE  1024
#define EC20_NET_NAME_SIZE 256
#define EC20_NET_PASSWD_SIZE 256

typedef struct {
	QueueHandle_t rcvCmdQueue;   // 串口接收队列
	QueueHandle_t sndCmdQueue;   // 串口发送队列
	uint8_t rcvBuf[EC20_MAX_SIZE];
	uint8_t sendBuf[EC20_MAX_SIZE];
	uint16_t rcvLen;
	char *str;                   // 数据指针
	uint32_t rcvTickEnd;         // 接收数据缓存
	uint8_t  sendNum;
	uint32_t rstNum;	
} EC20_OPTION;

typedef enum
{
	WORK_RST_FUN = 0x00U,
	WORK_ATE0_FUN,
	WORK_CMEE_FUN,
	WORK_CSQ_FUN,
	WORK_ATI_FUN,	
	WORK_CPIN_FUN,
	WORK_CREG_FUN,
	WORK_COPS_FUN,
	WORK_QICLOSE_FUN,
	WORK_QICSGP_FUN,
	WORK_QIDEACT_FUN,
	WORK_QIACT_FUN,	
	WORK_GET_QIACT_FUN,
	WORK_CTZU_FUN,	
	WORK_QNTP_FUN,	
	WORK_QCCLK_FUN,
	WORK_QMTCFG_FUN,
	WORK_QMTOPEN_FUN,
	WORK_SET_QMTOPEN_FUN,
	WORK_GET_QMTOPEN_FUN,
	WORK_TEST_QMTCONN_FUN,
	WORK_SET_QMTCONN_FUN,
	WORK_TEST_QMTSUB_FUN,
	WORK_SET_QMTSUB_FUN,
	WORK_INIT_COMPLETE,
} EC20_WORK_STA;

typedef struct {
    uint8_t	CSQ;
	uint8_t user_Name[EC20_NET_NAME_SIZE];
	uint8_t user_Passwd[EC20_NET_PASSWD_SIZE];
	TIME time;
} EC20_PARAM;

#endif

1.2 EC20.C

#include "ec20.h"

EC20_OPTION EC20_Option = {0};
EC20_PARAM EC20_Param = {0};


/*
 * @brief AT指令发送
 */
static void EC20_SendATCmd(char *cmd)
{
	printf("TX->EC20:%s",cmd);
    uart_SendDate(USART5,cmd,strlen(cmd), 1000);   
}



/*
 * @brief 初始化接收变量
 * @param first 是否第一次发送
 * @param reset_SendNum 是否将发送次数清0
 */
int init_Option(bool first,bool reset_SendNum)
{	
	if ( first )
	{
		EC20_Option.str = NULL;
		EC20_Option.rcvTickEnd = 0;
		EC20_Option.sendNum = 0;
		
	    EC20_Option.rcvCmdQueue = xQueueCreate(EC20_MAX_SIZE, 1);
		memset(EC20_Option.rcvBuf,0,EC20_MAX_SIZE);
		EC20_Option.rcvLen = 0;
		
		if ( EC20_Option.rcvCmdQueue == NULL )
		{
			return -1;
		}
	}
	else
	{		
		EC20_Option.str = NULL;
		EC20_Option.rcvTickEnd = xTaskGetTickCount();
		memset(EC20_Option.rcvBuf,0,EC20_MAX_SIZE);
		EC20_Option.rcvLen = 0;
		xQueueReset(EC20_Option.rcvCmdQueue);
		
		if ( reset_SendNum )
		{
			EC20_Option.sendNum = 1;
		}
		else
		{
			EC20_Option.sendNum ++;
		}
	}
		
	return 0;
}


/*
 * @brief 复位EC20
 */
void reset_EC20(void)
{
	gpio_bit_reset(MOD_4G_RST_PORT,MOD_4G_RST_PIN);
	vTaskDelay(500);
	gpio_bit_set(MOD_4G_RST_PORT,MOD_4G_RST_PIN);
}


/*
 * @brief 复位EC20
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_RstFun(EC20_WORK_STA *next_sta)
{
	reset_EC20();
	init_Option(false,true);
	EC20_Option.rstNum ++;
	
	printf("\r\n START RST: %d \r\n",xTaskGetTickCount());
	
	while ( EC20_Option.str == NULL )
	{		
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 15000 )
		{
			return -1;
		}
		
		if(rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"RDY");	
		
			if ( EC20_Option.str != NULL )
			{	
				printf("\r\n START END: %d \r\n",xTaskGetTickCount());
				printf("\r\n EC20-RX:%s\r\n",EC20_Option.rcvBuf);
				
				*next_sta = WORK_ATE0_FUN;
				break;
			}
		}
		else
		{
			return -1;
		}
	}
	
	return 0;
}

/*
 * @brief 关闭命令回显
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_Ate0Fun(EC20_WORK_STA *next_sta)
{
	EC20_SendATCmd("ATE0\r\n");  
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 1000 )
		{
				
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("ATE0\r\n");  
			init_Option(false,false);

		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_CMEE_FUN;	
			break;
		}
	}
	
	return 0;	
}

/*
 * @brief 启用结果代码
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_CmeeFun(EC20_WORK_STA *next_sta)
{
	EC20_SendATCmd("AT+CMEE=1\r\n"); 
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+CMEE=1\r\n");  
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_CSQ_FUN;
			break;			
		}
	}
	
	return 0;	
}


/*
 * @brief 启用结果代码
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_CsqFun(EC20_WORK_STA *next_sta)
{
	int result = 0;
	
	EC20_SendATCmd("AT+CSQ\r\n");
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{
						
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+CSQ\r\n");
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"+CSQ: ");	
			EC20_Option.str += strlen("+CSQ: ");
			if ( EC20_Option.str != NULL )
			{
				if (ParseInt(EC20_Option.str, NULL, ",", 0, 0, &result) == 0)          	
				{             
					EC20_Param.CSQ = result;  
					*next_sta = WORK_ATI_FUN;	
					break;					
				}	
				else
				{
					return -1;
				}
			}
		}
	}
	
	return 0;	
}


/*
 * @brief 读取产品信息
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_AtiFun(EC20_WORK_STA *next_sta)
{
	EC20_SendATCmd("ATI\r\n");
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
				
			EC20_SendATCmd("ATI\r\n"); 
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_CPIN_FUN;
			break;
		}
	}
	
	return 0;	
}


/*
 * @brief 检查sim卡是否到位
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_CpinFun(EC20_WORK_STA *next_sta)
{	
	EC20_SendATCmd("AT+CPIN?\r\n");
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+CPIN?\r\n");  
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"+CPIN: READY");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_CREG_FUN;
			break;
		}
	}
	
	return 0;	
}

/*
 * @brief 查看CREG
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_CregFun(EC20_WORK_STA *next_sta)
{	
	int result = 0;
	
	EC20_SendATCmd("AT+CREG?\r\n"); 
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 1000 )
		{	
			if ( EC20_Option.sendNum >= 10 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+CREG?\r\n");  
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"+CREG: ");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			
			EC20_Option.str = EC20_Option.str + strlen("+CREG: ") + 2;
			
			if (ParseInt(EC20_Option.str, NULL, NULL, 0, 1, &result) == 0)          		
			{             	
				if ( result == 1 || result == 5 )
				{
					*next_sta = WORK_COPS_FUN;
					break;
				}					
			}
				
			if ( EC20_Option.sendNum >= 10 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+CREG?\r\n");  
			init_Option(false,false);	
		}
	}
	
	return 0;	
}


/*
 * @brief 查询注网方式
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_CopsFun(EC20_WORK_STA *next_sta)
{	
	EC20_SendATCmd("AT+COPS?\r\n"); 
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+COPS?\r\n"); 
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_QICLOSE_FUN;
			break;
		}
	}
	
	return 0;	
}

/*
 * @brief 查询注网方式
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_QicloseFun(EC20_WORK_STA *next_sta)
{	
	EC20_SendATCmd("AT+QICLOSE=0\r\n");  
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QICLOSE=0\r\n"); 
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_QICSGP_FUN;
			break;
		}
	}
	
	return 0;	
}

/*
 * @brief 查询注网方式
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_QicsgpFun(EC20_WORK_STA *next_sta)
{	
	EC20_SendATCmd("AT+QICSGP=1,1,\"CMNET\",\"\",\"\",0\r\n"); 
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QICSGP=1,1,\"CMNET\",\"\",\"\",0\r\n");  
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_QIDEACT_FUN;
			break;
		}
	}
	
	return 0;	
}


/*
 * @brief 去激活
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_QideactFun(EC20_WORK_STA *next_sta)
{	
	EC20_SendATCmd("AT+QIDEACT=1\r\n");; 
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QIDEACT=1\r\n");  
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_QIACT_FUN;
			break;
		}
	}
	
	return 0;	
}

/*
 * @brief 激活
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_QiactFun(EC20_WORK_STA *next_sta)
{	
	EC20_SendATCmd("AT+QIACT=1\r\n");
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 150000 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QIACT=1\r\n");
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{		
		}
			
		if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK") )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_GET_QIACT_FUN;
			break;
		}
	    else if( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"ERROR") )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QIACT=1\r\n");
			init_Option(false,false);
		
		}
	}
	
	return 0;	
}


/*
 * @brief 获取激活状态
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_GetQiactFun(EC20_WORK_STA *next_sta)
{	
	int result = 0;
		
	EC20_SendATCmd("AT+QIACT?\r\n"); 
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 150000 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QIACT?\r\n"); 
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{		
		}
			
		if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK") )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"+QIACT: ");
						
			if ( EC20_Option.str != NULL )
			{
				EC20_Option.str += strlen("+QIACT: ") + 2;
				if (ParseInt(EC20_Option.str, NULL, NULL, 0, 1, &result) == 0)          	
				{             
					if ( result == 1 )
					{
						printf("\r\n QIACT SUCESS\r\n");
						*next_sta = WORK_CTZU_FUN;
						break;
					}
					else
					{	
						if ( EC20_Option.sendNum >= 15 )
						{	
							return -1;
						}
							
						EC20_SendATCmd("AT+QIACT?\r\n"); 
						init_Option(false,false);
					}
				}	
			}
			else
			{					
				if ( EC20_Option.sendNum >= 15 )
				{	
					return -1;		
				}
									
				EC20_SendATCmd("AT+QIACT?\r\n"); 		
				init_Option(false,false);
			}
		}
	    else if( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"ERROR") )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
				
			EC20_SendATCmd("AT+QIACT?\r\n"); 
			init_Option(false,false);
		
		}
	}
	
	return 0;	
}


/*
 * @brief 配置CTZU
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_CtzuFun(EC20_WORK_STA *next_sta)
{	
	EC20_SendATCmd("AT+CTZU=3\r\n");
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+CTZU=3\r\n");
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK");	
		}
			
		if ( EC20_Option.str != NULL )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_QNTP_FUN;
			break;
		}
	}
	
	return 0;	
}


/*
 * @brief 注册NTP
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_QntpFun(EC20_WORK_STA *next_sta)
{	

	memset(EC20_Option.sendBuf,0,EC20_MAX_SIZE);
	
//	sprintf(EC20_Option.sendBuf,"%s\"%d.%d.%d.%d\",%d\r\n","AT+QNTP=1,",g_Param.cfgInfo.ntp_ip[0],g_Param.cfgInfo.ntp_ip[1]
//	,g_Param.cfgInfo.ntp_ip[2],g_Param.cfgInfo.ntp_ip[3],(g_Param.cfgInfo.ntp_port[2] << 8) | g_Param.cfgInfo.ntp_port[3]);
	
	EC20_SendATCmd((char *)EC20_Option.sendBuf);
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 125000 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd((char *)EC20_Option.sendBuf);
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
		}
			
		if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK") )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_QCCLK_FUN;
			break;
		}
		else if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"ERROR") )
		{				
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd((char *)EC20_Option.sendBuf);
			init_Option(false,false);
		}
	}
	
	return 0;	
}

/*
 * @brief 获取时间
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_ClkFun(EC20_WORK_STA *next_sta)
{	
	int result = 0;
	uint32_t sec = 0;
		
	EC20_SendATCmd("AT+CCLK?\r\n");
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+CCLK?\r\n");
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
			
		}
			
				
		if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK") )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			
		
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*) "+CCLK: ");
			
			if ( NULL != EC20_Option.str)
			{  
				EC20_Option.str = EC20_Option.str + strlen("+CCLK: ") + 1;
				
				if (ParseInt(EC20_Option.str, NULL, NULL, 0, 2, &result) == 0)          	
				{    	
					EC20_Param.time.year = result;            
				}
				
				EC20_Option.str += 3;
				if (ParseInt(EC20_Option.str, NULL, NULL, 0, 2, &result) == 0)          
				{             	
					EC20_Param.time.month = result;            	
				}
			
				EC20_Option.str += 3;
				if (ParseInt(EC20_Option.str, NULL, NULL, 0, 2, &result) == 0)          
				{             	
					EC20_Param.time.day = result;            
				}
	 	 	
				EC20_Option.str += 3;	
				if (ParseInt(EC20_Option.str, NULL, NULL, 0, 2, &result) == 0)          
				{             	
					EC20_Param.time.hour = result;            
				}
	 	
				EC20_Option.str += 3;
				if (ParseInt(EC20_Option.str, NULL, NULL, 0, 2, &result) == 0)          	
				{             	
					EC20_Param.time.minute = result;            	
				}
	 
				EC20_Option.str += 3;	
				if (ParseInt(EC20_Option.str, NULL, NULL, 0, 2, &result) == 0)          	
				{             
					EC20_Param.time.second = result;            
				}

				EC20_Option.str += 2;

				if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*) "+"))
				{
					EC20_Option.str +=1;
					if (ParseInt(EC20_Option.str, NULL, "\"", 0, 0, &result) == 0)          	
					{  
					
						sec = TimeToSec(EC20_Param.time) + result/4*60*60;
						
						if ( SecIsVaild(sec) == 0 )
						{
							SecToTime(sec,&EC20_Param.time);		
							rtc_SetTime(EC20_Param.time);			
							set_UserName();	
							set_Passwd();
							
						}			
					}
				
				}
				else
				{
					EC20_Option.str += 1;
					if (ParseInt(EC20_Option.str, NULL, "\"", 0, 0, &result) == 0)          	
					{             
						sec = TimeToSec(EC20_Param.time) - result/4*60*60;
						if ( SecIsVaild(sec) == 0 )
						{
							SecToTime(sec,&EC20_Param.time);		
							rtc_SetTime(EC20_Param.time);			
							set_UserName();	
							set_Passwd();	
						}
								
					}

				
				}
			
			
				break;
			}
		
		}
	}
	
	return 0;	
}


/*
 * @brief 配置NTP接收模式
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_QmtcfgFun(EC20_WORK_STA *next_sta)
{	

	EC20_SendATCmd("AT+QMTCFG=\"recv/mode\",0,0,1\r\n");	
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QMTCFG=\"recv/mode\",0,0,1\r\n");	
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
		}
			
		if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK") )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_QMTOPEN_FUN;
			break;
		}

	}
	
	return 0;	
}


/*
 * @brief 打开MQTT客户端,测试命令
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_QmtOpenFun(EC20_WORK_STA *next_sta)
{	

	EC20_SendATCmd("AT+QMTOPEN=?\r\n");
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 500 )
		{	
			if ( EC20_Option.sendNum >= 3 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QMTOPEN=?\r\n");	
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
		}
			
		if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK") )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_QMTOPEN_FUN;
			break;
		}

	}
	
	return 0;	
}


/*
 * @brief 打开MQTT测试端设置命令
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_SetQmtOpenFun(EC20_WORK_STA *next_sta)
{	

	memset(EC20_Option.sendBuf,0,EC20_MAX_SIZE);
	EC20_SendATCmd("AT+QMTOPEN=?\r\n");	
	EC20_SendATCmd((char *)EC20_Option.sendBuf);	
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 120000 )
		{	
			if ( EC20_Option.sendNum >= 2 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QMTOPEN=?\r\n");	
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
		}
			
			
		EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"+QMTOPEN:");	
		
		if ( EC20_Option.str != NULL )
		{	
			printf("RX:%s\n",EC20_Option.rcvBuf);
			
			if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"+QMTOPEN: 0,0") )
			{
				*next_sta = WORK_GET_QMTOPEN_FUN;
				break;
			}
			else
			{
				if ( EC20_Option.sendNum >= 2 )	
				{
					return -1;
				}				
			
				if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd < 120000 )
				{	
					EC20_SendATCmd((char *)EC20_Option.sendBuf);	
					init_Option(false,false);
				}
			}
			
		}

	}
	
	return 0;	
}

/*
 * @brief 打开MQTT 查询指令
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_GetQmtOpenFun(EC20_WORK_STA *next_sta)
{	

	memset(EC20_Option.sendBuf,0,EC20_MAX_SIZE);
	EC20_SendATCmd("AT+QMTOPEN?\r\n");	
	EC20_SendATCmd((char *)EC20_Option.sendBuf);	
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 1000 )
		{	
			if ( EC20_Option.sendNum >= 2 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QMTOPEN=?\r\n");	
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
		}
			
		
		if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK") )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_TEST_QMTCONN_FUN;
			break;
		}

	}
	
	return 0;	
}

/*
 * @brief 连接客户MQTT服务器 测试指令
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_TestQmtConFun(EC20_WORK_STA *next_sta)
{	

	EC20_SendATCmd("AT+QMTCONN=?\r\n");
		
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 1000 )
		{	
			if ( EC20_Option.sendNum >= 2 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QMTCONN=?\r\n");
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
		}
			
		
		if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"OK") )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_TEST_QMTCONN_FUN;
			break;
		}

	}
	
	return 0;	
}


/*
 * @brief 连接客户MQTT服务器 设置指令
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_SetQmtConFun(EC20_WORK_STA *next_sta)
{	

	memset(EC20_Option.sendBuf,0,EC20_MAX_SIZE);
//	sprintf(EC20_Option.sendBuf,"%s\"%s\",\"%s\",\"%s\"\r\n","AT+QMTCONN=0,",deviceId,user_name,passwd);
	EC20_SendATCmd((char *)EC20_Option.sendBuf);	
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 6000 )
		{	
			if ( EC20_Option.sendNum >= 2 )
			{
				return -1;
			}
			
			EC20_SendATCmd((char *)EC20_Option.sendBuf);
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
		}
			
		
		if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"+QMTCONN: 0,0,0") )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_TEST_QMTSUB_FUN;
			break;
		}

	}
	
	return 0;	
}

/*
* @brief 订阅服务器测试指令
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_TestQmtSubFun(EC20_WORK_STA *next_sta)
{
	
	EC20_SendATCmd("AT+QMTSUB=?\r\n");
	init_Option(false,true);
	
	while ( EC20_Option.str == NULL )
	{
		if ( xTaskGetTickCount() - EC20_Option.rcvTickEnd > 6000 )
		{	
			if ( EC20_Option.sendNum >= 2 )
			{
				return -1;
			}
			
			EC20_SendATCmd("AT+QMTSUB=?\r\n");
			init_Option(false,false);
		}
		
		if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
		{	
		}
			
		
		if ( NULL != strstr((const char*)EC20_Option.rcvBuf,(const char*)"+QMTCONN: 0,0,0") )
		{
			printf("RX:%s\n",EC20_Option.rcvBuf);
			*next_sta = WORK_SET_QMTSUB_FUN;
			break;
		}

	}
	
	return 0;	
}



/*
 * @brief 订阅服务器
 * @param next_sta 输出,下个执行状态
 * @return 0=正常 -1=异常
 */
static int EC20_SetQmtSubFun(EC20_WORK_STA *next_sta)
{
	uint8_t action_num = 0;
	
	int result = -1;

	while(actionName[action_num] != NULL)
	{	
		result = -1;	
		
		if (action_num != 0 )
		{
			SetRequestTopic(actionName[action_num]);	
		}
		else
		{
			SetResponseTopic(actionName[action_num]);	
		}
	
	
		sprintf((char *)EC20_Option.sendBuf,"%s%s,0\r\n","AT+QMTSUB=0,1,",EC20_TopicReport);
			
		EC20_SendATCmd((char *)EC20_Option.sendBuf);		
	
		init_Option(false,true);
		
		while(1)
		{	
			if (xTaskGetTickCount() - EC20_Option.rcvTickEnd > 15000)
			{
				return -1;
			}
			
				
			if ( rcv_QueueBuf(EC20_Option.rcvCmdQueue,EC20_Option.rcvBuf,&EC20_Option.rcvLen,100,EC20_MAX_SIZE) == 0 )
			{	
			}
				
			printf("RX:%s\n",EC20_Option.rcvBuf);	
					
			EC20_Option.str = strstr((const char*)EC20_Option.rcvBuf,(const char*)"+QMTSUB:");	
			EC20_Option.str = strstr((const char*)EC20_Option.str,(const char*)",");
			EC20_Option.str = strstr((const char*)(EC20_Option.str + 1),(const char*)",");	
			
								
			if ( EC20_Option.str != NULL)
			{			
				if (ParseInt(EC20_Option.str + 1, NULL, NULL, 0, 1, &result) == 0)          			
				{    				
					if (result == 0)
					{																				
						action_num ++;	
						break;
							
					}	
					else		
					{	
						return -1;	
					}	
				}		
				else	
				{
					return -1;		
				}
					
			}		
			else
			{		
				return -1;	
			}
		}

	}
	
	*next_sta = WORK_INIT_COMPLETE;
	return 0;
	

}


/*
 * @brief 初始化EC20
 */
int EC20_Init(void)
{
	static EC20_WORK_STA work_Sta = WORK_RST_FUN;

	while(1)
	{
		switch ( work_Sta )
		{
			case WORK_RST_FUN :
			EC20_RstFun(&work_Sta);	
			break;
		
			case WORK_ATE0_FUN:
			EC20_Ate0Fun(&work_Sta);
			break;
		
			case WORK_CMEE_FUN:	
			EC20_CmeeFun(&work_Sta);
			break;
		
			case WORK_CSQ_FUN:
			EC20_CsqFun(&work_Sta);
			break;

			case WORK_ATI_FUN:
			EC20_AtiFun(&work_Sta);
			break;
		
			case WORK_CPIN_FUN:
			EC20_CpinFun(&work_Sta);	
			break;
			
			case WORK_CREG_FUN:	
			EC20_CregFun(&work_Sta);
			break;
		
			case WORK_COPS_FUN:	
			EC20_CopsFun(&work_Sta);
			break;
		
			case WORK_QICLOSE_FUN:	
			EC20_QicloseFun(&work_Sta);
			break;
			
			case WORK_QICSGP_FUN:
			EC20_QicsgpFun(&work_Sta);			
			break;
		
			case WORK_QIDEACT_FUN:
			EC20_QideactFun(&work_Sta);
			break;
		
			case WORK_QIACT_FUN:	
			EC20_QiactFun(&work_Sta);
			break;
		
			case WORK_GET_QIACT_FUN:
			EC20_GetQiactFun(&work_Sta);	
			break;
			
			case WORK_CTZU_FUN:	
			EC20_CtzuFun(&work_Sta);
			break;
			
			case WORK_QNTP_FUN:	
			EC20_QntpFun(&work_Sta);
			break;
			
			case WORK_QCCLK_FUN:
			EC20_ClkFun(&work_Sta);
			break;
			
			case WORK_QMTCFG_FUN:
			EC20_QmtcfgFun(&work_Sta);
			break;
					
			case WORK_QMTOPEN_FUN:
			EC20_QmtOpenFun(&work_Sta);
			break;
			
			case WORK_SET_QMTOPEN_FUN:
			EC20_SetQmtOpenFun(&work_Sta);	
			break;
			
			case WORK_GET_QMTOPEN_FUN:		
			EC20_GetQmtOpenFun(&work_Sta);
			break;
			
			case WORK_TEST_QMTCONN_FUN:
			EC20_TestQmtConFun(&work_Sta);
			break;
			
			case WORK_SET_QMTCONN_FUN:
			EC20_SetQmtConFun(&work_Sta);
			break;
			
			case WORK_TEST_QMTSUB_FUN:
			EC20_TestQmtSubFun(&work_Sta);
			break;
			
			case WORK_SET_QMTSUB_FUN:
			EC20_SetQmtSubFun(&work_Sta);	
			break;
			
			case WORK_INIT_COMPLETE:
			return 0;
			default:
			work_Sta = WORK_RST_FUN;
			break;	
		}
	}

}