/************************************************************************************
 * @Copyright (c)    :(C)2017, Qindao ieslab Co., Ltd
 * @FileName   	     :pic24_nb_driver.c
 * @Author           :QDIES PLATFORM TEAM
 * @Version          :V1.0
 * @Date             :2017-03-01
 * @Description     :
 ************************************************************************************/
#include "sys_config.h"
#ifdef MODULE_ML302_TCP
#ifdef	__cplusplus
extern "C"
{
#endif

#include "nb_uart_driver_ml302.h"
#include "nb_driver_ml302.h"
#include "stdio.h"
#include <time.h>
#include "UWater_timer1uS_driver.h"
#include "UWater_uart_driver.h"
#include "UWater_Rtcc_Driver.h"
#include "UWater_frame_app.h"


/********************************变量定义************************************/
//模组信息、网络配置、连接状态相关参数
NBIOT_PARA Nbiot_Para;
//模组数据发送指针
NBIOT_SEND_DATA Nbiot_Send_Data;
//AT指令拼接缓存
static char stringbuffer_temp[UP_BUF_SIZE*2];
//AT指令发送缓存
static char AT_BUF[50 + UP_BUF_SIZE * 2];
//任务完成情况
TYP_TASK_RESULT g_s_nbiot_task_flag = TASK_INIT;
//数据发送通道
u8 g_s_nbiot_send_type;
//模组上电标志
u8 nb_power_flag = FALSE;
//AT指令查询失败次数
u8 at_requestErrorCount=0;
//AT指令执行结果
TYP_RESULT_CODE g_at_request_res;
//AT指令索引
int g_at_index=0;
//TCP要发送数据的长度
u16 tcp_send_len=0;
char tcp_send_len_buf[8];
u8 tcp_send_len_buf_len=0;
//UDP要发送数据的长度
u16 udp_send_len=0;
char udp_send_len_buf[8];
u8 udp_send_len_buf_len=0;
//IP地址
unsigned char *coap_ip;
u16 coap_port;
unsigned char *udp_ip1;
u16 udp_port1;
unsigned char *udp_ip2;
u16 udp_port2;
u8 nbiot_temp_connect_type=NBIOT_CONNECT_COAP;
//AT指令集
static STRUCT_AT_CMD AtCmdBuf[AT_CMD_COUNT]={
	/*****模组初始化指令********************/
	{AT_CODE_AT,      "AT+CMVERSION",           WT_2S, RETRY_5, cst_AT_No_AT},//AT指令
	{AT_CODE_VERCTRL, "AT+VERCTRL?",            WT_2S, RETRY_5, cst_AT_No_VERCTRL_CK},//查询激活方式
	{AT_CODE_VERCTRL1,"AT+VERCTRL=0,1",         WT_2S, RETRY_5, cst_AT_No_AT},//设置自动激活方式
	{AT_CODE_CMEE,    "AT+CMEE=1",              WT_2S, RETRY_5, cst_AT_No_AT_CMEE},//打开ERROR错误码显示
	{AT_CODE_CGSN,    "AT+CGSN=1",              WT_2S, RETRY_5, cst_AT_No_AT_IMEI},//查询IMEI
	{AT_CODE_CPIN,    "AT+CPIN?",               WT_2S, RETRY_5, cst_AT_No_AT_CPIN},//查询SIM卡状态,READY表示SIM卡正常识别运行。
	{AT_CODE_CIMI,    "AT+CIMI",                WT_2S, RETRY_5, cst_AT_No_AT_CIMI},//查询IMSI
	{AT_CODE_ICCID,   "AT+ICCID",               WT_2S, RETRY_5, cst_AT_No_AT_ICCID},//查询ICCID
	{AT_CODE_CFUN_CK, "AT+CFUN?",               WT_2S, RETRY_5, cst_AT_No_AT_CFUN},//查询协议栈是否打开
	{AT_CODE_CFUN0,   "AT+CFUN=0",              WT_2S, RETRY_5, cst_AT_No_AT_CFUN},//
	{AT_CODE_CFUN1,   "AT+CFUN=1",              WT_2S, RETRY_5, cst_AT_No_AT_CFUN},//
	{AT_CODE_CSQ,     "AT+CSQ",                 WT_2S, RETRY_5, cst_AT_No_AT_CSQ},//查询信号质量
	{AT_CODE_TUEINFO, "AT+TUEINFO",             WT_2S, RETRY_2, cst_AT_No_AT_TUEINFO},//查询信号状态
	{AT_CODE_CCED,    "AT+CCED=0,1",            WT_2S, RETRY_2, cst_AT_No_AT_CCED},//Single shot requested.
	{AT_CODE_CGDCONT, "AT+CGDCONT=1,\"IP\",\"", WT_2S, RETRY_1, cst_AT_No_AT},//设置APN  AT+CGDCONT=1,”IP”,”CMIOT”
	{AT_CODE_CGACT,   "AT+CGACT=1,1",           WT_20S,RETRY_2, cst_AT_No_AT_CGACT_how},//激活 PDP  //最长等待20s,期间发送AT指令无应答
	{AT_CODE_CEREG,   "AT+CEREG?",              WT_2S, RETRY_10,cst_AT_No_AT_CEREG},//查询网络注册状态
	{AT_CODE_CGACT_CK,"AT+CGACT?",              WT_5S, RETRY_5,cst_AT_No_AT_CGACT_how},//查询网络附着状态
	{AT_CODE_CCLK,    "AT+CCLK?",               WT_5S, RETRY_3, cst_AT_No_AT_CCLK},//查询模组时间
	 
	{AT_CODE_CTEC_CK,    "AT+CTEC?",            WT_5S, RETRY_1, cst_AT_No_AT_CCLK},//查询模组时间
	{AT_CODE_CCED_CK,    "AT+CCED=0,1",         WT_5S, RETRY_5, cst_AT_No_AT_CCLK},//查询模组时间
	/*****TCP连接指令***********************/
	/*When mode set to 1(transparent mode), n(connect_id) must be 0 and no TCP/UDP connection has already been 
	established.*/
	//{AT_CODE_MIPMODE1,"AT+MIPMODE=0,1",         WT_2S, RETRY_5, cst_AT_No_AT},//设置透传连接方式 AT+MIPMODE=0,1
	//{AT_CODE_MIPOPEN, "AT+MIPOPEN=0,\"TCP\",\"",WT_5S, RETRY_5, cst_AT_No_AT_MIPOPEN},// AT+MIPOPEN=0,"TCP","58.59.6.130",21628
	{AT_CODE_MIPMODE1,"AT+MIPMODE=1,0",         WT_2S, RETRY_5, cst_AT_No_AT},//(不使用透传方式)
	{AT_CODE_MIPOPEN, "AT+MIPOPEN=1,\"TCP\",\"",WT_40S, RETRY_1, cst_AT_No_AT_MIPOPEN},// AT+MIPOPEN=1,"TCP","58.59.6.130",21628 
	/*****TCP数据发送***********************/
	{AT_CODE_MIPSENDCOUNT,"AT+MIPSEND=1,",      WT_5S, RETRY_2, cst_AT_No_AT_MIPSENDCOUNT},//设置发送字节数
	{AT_CODE_TCPSEND, "",                       WT_5S, RETRY_0, cst_AT_No_AT_TCPSEND},// 
	//关闭TCP连接
	{AT_CODE_MIPCLOSE, "AT+MIPCLOSE=1",         WT_5S, RETRY_2, cst_AT_No_AT_MIPCLOSE},//AT+MIPCLOSE=0
	/*****UDP1连接指令**********************/
	{AT_CODE_MIPOPEN_UDP1,"AT+MIPOPEN=2,\"UDP\",\"",WT_5S, RETRY_5, cst_AT_No_AT_MIPOPEN},// AT+MIPOPEN=1,"UDP","60.208.16.58",7833 
	/*****UDP1数据发送***********************/
	{AT_CODE_MIPSENDCOUNT_UDP1,"AT+MIPSEND=2,",  WT_5S, RETRY_2, cst_AT_No_AT_MIPSENDCOUNT},//设置发送字节数
	{AT_CODE_UDPSEND1, "",                       WT_5S, RETRY_0, cst_AT_No_AT_TCPSEND},// 
	//关闭UDP1连接
	{AT_CODE_MIPCLOSE_UDP1, "AT+MIPCLOSE=2",     WT_5S, RETRY_2, cst_AT_No_AT_MIPCLOSE},//AT+MIPCLOSE=0
	/*****UDP2连接指令**********************/
	{AT_CODE_MIPOPEN_UDP2,"AT+MIPOPEN=3,\"UDP\",\"",WT_5S, RETRY_5, cst_AT_No_AT_MIPOPEN},// AT+MIPOPEN=1,"UDP","60.208.16.58",7833 
	/*****UDP2数据发送***********************/
	{AT_CODE_MIPSENDCOUNT_UDP2,"AT+MIPSEND=3,",  WT_5S, RETRY_2, cst_AT_No_AT_MIPSENDCOUNT},//设置发送字节数
	{AT_CODE_UDPSEND2, "",                       WT_5S, RETRY_0, cst_AT_No_AT_TCPSEND},// 
	//关闭UDP2连接
	{AT_CODE_MIPCLOSE_UDP2, "AT+MIPCLOSE=3",     WT_5S, RETRY_2, cst_AT_No_AT_MIPCLOSE},//AT+MIPCLOSE=0
};
/*****************************内部功能状态定义*********************************/
//主状态
TYP_STATE_MAIN_CONNECT g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE; 
//开机状态
TYP_STEP_MODULE_POWERON s_power_on_state = MODULE_IDLE; 
//关机状态
TYP_STATE_POWER_OFF s_power_off_state = S_PWOFF_IDLE; 
//AT指令查询状态
TYP_STATE_AT_REQUEST s_at_requeset_state = AT_REQUEST_IDLE;
//模组初始化状态
TYP_MODULE_INIT s_init_state=S_MODULE_INIT_IDLE;
//TCP连接状态
TYP_TCP_CONNECT s_tcp_connect_state = S_TCP_CONNECT_IDLE;
//TCP发送数据状态
TYP_TCP_SEND s_tcp_send_state;
//UDP连接状态
TYP_UDP_CONNECT s_udp_connect_state = S_UDP_CONNECT_IDLE;
//UDP发送数据状态
TYP_UDP_SEND s_udp_send_state;
/*****************************内部功能状态机函数*********************************/
void NbiotInitMachine(void);
void NbiotPowerOffMachine(void);
void UdpReadDataMachine(void);
//TCP连接
void TcpStartConnect(void);
void TcpConnectMachine(void);
//TCP发送
void StartTcpSendData(void);
void TcpSendDataMachine(void);
//UDP连接
void UdpStartConnect(u8 udp_num);
void UdpConnectMachine(void);
//UDP发送
void StartUdpSendData(void);
void UdpSendDataMachine(void);
/*****************************内部定时器接口**********************************/
void set_timer_1s(u16 time);
u16 check_timer_1s(void);
void set_timer_1ms(u16 time);
u16 check_timer_1ms(void);
void StartNbiotInit(void);
/*****************************外部接口****************************************/
void NB_Power_Disable(void) 
{
	Gpio_WriteOutputIO(BAT_NB_PORT, BAT_NB_PIN, FALSE);
	nb_power_flag = FALSE;
}

void NB_Power_Enable(void)  
{
	Gpio_WriteOutputIO(BAT_NB_PORT, BAT_NB_PIN, TRUE);
	nb_power_flag = TRUE;
}

u8 If_NB_Poweron(void)
{    
	return nb_power_flag;    
}
/***************************************************************************
* @fun_name     void NbModuleIOInit(void)
* @brief        模块供电IO、模块复位、电源、PSM唤醒引脚初始化
***************************************************************************/
void NbModuleIOInit(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    DDL_ZERO_STRUCT(stcGpioCfg);
    stcGpioCfg.enDir = GpioDirOut;    ///< 端口方向配置
    stcGpioCfg.enDrv = GpioDrvL;      ///< 端口驱动能力配置->低驱动能力
    stcGpioCfg.enPu = GpioPuDisable;  ///< 端口上下拉配置->无
    stcGpioCfg.enPd = GpioPdDisable;
    stcGpioCfg.enOD = GpioOdDisable;  ///< 端口开漏输出配置
    stcGpioCfg.enCtrlMode = GpioAHB;  ///< 端口输入/输出值寄存器总线控制模式配置->AHB
    Gpio_Init(BAT_NB_PORT, BAT_NB_PIN, &stcGpioCfg);  //模块供电IO
    Gpio_Init(RSTN_NB_PORT, RSTN_NB_PIN, &stcGpioCfg);
    Gpio_Init(NB_PSM_WAKE_PORT, NB_PSM_WAKE_PIN, &stcGpioCfg);
    Gpio_Init(PWR_NB_PORT, PWR_NB_PIN, &stcGpioCfg);   //电源控制脚
    Gpio_WriteOutputIO(BAT_NB_PORT, BAT_NB_PIN, FALSE);
    Gpio_WriteOutputIO(PWR_NB_PORT, PWR_NB_PIN, FALSE);
	Gpio_WriteOutputIO(RSTN_NB_PORT, RSTN_NB_PIN, FALSE); 
	Gpio_WriteOutputIO(NB_PSM_WAKE_PORT , NB_PSM_WAKE_PIN, FALSE);
}
/*模组端串口调试配置*/
void NB_UartInitForGPIO(void)//debug
{
    stc_gpio_cfg_t stcGpioCfg;

	DDL_ZERO_STRUCT(stcGpioCfg);
    //PA0,PA1:配置为数字输入
    stcGpioCfg.enDir = GpioDirIn;    ///< 端口方向配置->输入
    stcGpioCfg.enDrv = GpioDrvL;     ///< 端口驱动能力配置->低驱动能力
    stcGpioCfg.enPu = GpioPuDisable; ///< 端口上下拉配置->无
    stcGpioCfg.enPd = GpioPdDisable;
    stcGpioCfg.enOD = GpioOdDisable; ///< 端口开漏输出配置->开漏输出关闭
    stcGpioCfg.enCtrlMode = GpioAHB; ///< 端口输入/输出值寄存器总线控制模式配置->AHB
    Gpio_Init(GpioPortA, GpioPin0, &stcGpioCfg);	
    Gpio_Init(GpioPortA, GpioPin1, &stcGpioCfg);
}

/***************************************************************************
 * @fun_name     void NbiotMainMachine()
 * @brief        NBIOT主任务机，放在主程序空间的主循环中，进行NBIOT任务处理
 ***************************************************************************/
void NbiotMainMachine(void)
{
    switch (g_s_nbiot_main_state)
    {
        case S_NBIOT_MAIN_IDLE:
		{
		}
        break;

        case S_NBIOT_MAIN_POWER_INIT:
        {
            if (TASK_INIT == g_s_nbiot_task_flag) //如果是初始状态
            {
                NbiotInitMachine(); //模块初始化状态机
            }
			else
			{
				if (TASK_SUCCESS == g_s_nbiot_task_flag) //任务成功
				{
					Nbiot_Para.net_state = NB_ON_LINE;
					g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE;
				}
				else //任务失败
				{
					*Nbiot_Send_Data.state = NBIOT_ERROR;
					g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE;
				}
				g_s_nbiot_task_flag = TASK_INIT; //清标志位
			}
        }
        break;
        case S_NBIOT_MAIN_TCP_OPEN:
        {
            if (TASK_INIT == g_s_nbiot_task_flag)
            {
				TcpConnectMachine(); //与主站建立连接状态机		
            }
			else
			{
				if (TASK_SUCCESS == g_s_nbiot_task_flag)
				{
					Nbiot_Para.coap_state = CONNECT_ON_LINE;
				}
				else
				{
					Nbiot_Para.coap_state = CONNECT_OFF_LINE;
					*Nbiot_Send_Data.state = NBIOT_ERROR;
				}
				g_s_nbiot_task_flag = TASK_INIT;
				g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE; 
			}
        }
        break;

        case S_NBIOT_MAIN_TCP_SEND:
        {
            if (CONNECT_ON_LINE == Nbiot_Para.coap_state)
            {
                if (TASK_INIT == g_s_nbiot_task_flag)
                {
					TcpSendDataMachine(); //数据发送状态机
                }
				else//发送数据任务成功和失败都回到空闲
				{
					*Nbiot_Send_Data.state = NBIOT_SUCCESS;
					g_s_nbiot_task_flag = TASK_INIT;
					g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE;
				}
            }
			else
			{
				g_s_nbiot_task_flag = TASK_INIT;
				g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE;
			}
        }
        break;
		case S_NBIOT_MAIN_UDP_OPEN:
        {
            if (TASK_INIT == g_s_nbiot_task_flag)
            {
                UdpConnectMachine(); //与主站建立连接状态机
            }
			else
			{
				if (TASK_SUCCESS == g_s_nbiot_task_flag)
				{
					if(nbiot_temp_connect_type == NBIOT_CONNECT_UDP1)
					{
						 Nbiot_Para.udp1_state = CONNECT_ON_LINE;
					}
					else if(nbiot_temp_connect_type == NBIOT_CONNECT_UDP2)
					{
						 Nbiot_Para.udp2_state = CONNECT_ON_LINE;
					}   
				}
				g_s_nbiot_task_flag = TASK_INIT;
				g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE; 
			}
        }
        break;

        case S_NBIOT_MAIN_UDP_SEND:
        {
            if (CONNECT_ON_LINE == Nbiot_Para.udp1_state)
            {
                if (TASK_INIT == g_s_nbiot_task_flag)
                {
                    UdpSendDataMachine(); //数据发送状态机
                }
				else//发送数据任务成功和失败都回到空闲
				{
					g_s_nbiot_task_flag = TASK_INIT;
                    g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE;
				}
            }
			else
			{
				g_s_nbiot_task_flag = TASK_INIT;
				g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE;
			}
        }
        break;
        case S_NBIOT_MAIN_POWER_OFF:
        {
            if (TASK_INIT == g_s_nbiot_task_flag)
            {
                NbiotPowerOffMachine(); //断电关机
            }
            else
            {
                g_s_nbiot_task_flag = TASK_INIT;
                g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE;
                Nbiot_Para.net_state = NB_OFF_LINE;
				Nbiot_Para.coap_state = CONNECT_OFF_LINE;
				Nbiot_Para.udp1_state = CONNECT_OFF_LINE;
				Nbiot_Para.udp2_state = CONNECT_OFF_LINE;
            }
        }
        break;
        default:
        {
            g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE;
        }
        break;
    }
}
/***************************************************************************
 * @fun_name     u8 NbiotIfIdle()
 * @brief        查询模块的空闲状态
 ***************************************************************************/
u8 NbiotIfIdle(void)
{
    if (S_NBIOT_MAIN_IDLE == g_s_nbiot_main_state)
    {
        return TASK_IDLE;
    }
    else
    {	
        return TASK_BUSY;
    }
}

/***************************************************************************
 * @fun_name     u8 NbiotIfOnline()
 * @brief        查询NBIOT是否在线
 ***************************************************************************/
u8 NbiotIfOnline(void)
{
    if (NB_ON_LINE == Nbiot_Para.net_state)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

/***************************************************************************
 * @fun_name     u8 UdpIfOnline()
 * @brief        查询UDP连接是否建立
 ***************************************************************************/
//u8 UdpIfOnline(void)
//{
//    if (CONNECT_ON_LINE == Nbiot_Para.udp1_state)
//    {
//        return TRUE;
//    }
//    else
//    {
//        return FALSE;
//    }
//}
/***************************************************************************
 * @fun_name     u8 ConncetIfOnline()
 * @brief        查询连接是否在线
 ***************************************************************************/
u8 ConncetIfOnline(u8 connect_type)
{  
	if(connect_type == NBIOT_CONNECT_COAP)
	{
		if (CONNECT_ON_LINE == Nbiot_Para.coap_state)
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
	else if(connect_type == NBIOT_CONNECT_UDP1)
	{
		if (CONNECT_ON_LINE == Nbiot_Para.udp1_state)
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
	else if(connect_type == NBIOT_CONNECT_UDP2)
	{
		if (CONNECT_ON_LINE == Nbiot_Para.udp2_state)
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
	return FALSE;
}
/***************************************************************************
 * @fun_name     void NbiotOnlineTask(u8 *state)
 * @brief        NBIOT上线任务
 * @param[in]    state:状态信息
 ***************************************************************************/
void NbiotOnlineTask(u8 *state)
{
    if (S_NBIOT_MAIN_IDLE == g_s_nbiot_main_state)
    {
        if (!NbiotIfOnline())
        {
            if (S_NBIOT_MAIN_IDLE == g_s_nbiot_main_state)
            {
                Nbiot_Send_Data.state = state; //地址拷贝
                *state = NBIOT_ING;
				g_s_nbiot_task_flag = TASK_INIT;
                g_s_nbiot_main_state = S_NBIOT_MAIN_POWER_INIT;
				StartNbiotInit();
            }
        }
        else
        {
            *state = NBIOT_ONLINE;
        }
    }
    else
    {
        *state = NBIOT_ERROR;
    }
}
/***************************************************************************
 * @fun_name     void NB_NetConnectStart
 * @brief        根据连接类型建立连接
 * @param[in]    state:状态信息
 ***************************************************************************/
void NB_NetConnectStart(unsigned char* temp_ip, u16 temp_port, u8 connect_type)
{
	if(connect_type == NBIOT_CONNECT_COAP)
	{
		coap_ip = temp_ip;
		coap_port = temp_port;
		TcpStartConnect();
		nbiot_temp_connect_type = NBIOT_CONNECT_COAP;
		g_s_nbiot_main_state = S_NBIOT_MAIN_TCP_OPEN;
	}
	else if(connect_type == NBIOT_CONNECT_UDP1)
	{
		udp_ip1 = temp_ip;
		udp_port1 = temp_port;
		UdpStartConnect(connect_type);
		g_s_nbiot_main_state = S_NBIOT_MAIN_UDP_OPEN;
	}
	else if(connect_type == NBIOT_CONNECT_UDP2)
	{
		udp_ip2 = temp_ip;
		udp_port2 = temp_port;
		UdpStartConnect(connect_type);
		g_s_nbiot_main_state = S_NBIOT_MAIN_UDP_OPEN;
	}
	g_s_nbiot_task_flag = TASK_INIT;
}
/***************************************************************************
 * @fun_name     void NbiotSendTask(u8 *addr, u16 len, u8 send_type,u8 *state)
 * @brief        NBIOT数据发送任务
 * @param[in]    addr：内容的首地址 len：长度
 * @param[out]   state:状态信息
 * @retval       None
 * @other        state(NBIOT_ING：查询中, NBIOT_SUCCES：成功 其他：异常)
 ***************************************************************************/
void NbiotSendTask(u8 *addr, u16 len, u8 send_type,u8 *state)
{
    if ((S_NBIOT_MAIN_IDLE == g_s_nbiot_main_state) && (len > 0) && (len <= UP_BUF_SIZE))
    {
        Nbiot_Send_Data.buf = addr; //地址拷贝
        Nbiot_Send_Data.len = len; //值拷贝
        Nbiot_Send_Data.state = state; //地址拷贝
        *state = NBIOT_ING;
		g_s_nbiot_send_type = send_type;
		g_s_nbiot_task_flag = TASK_INIT;
		if((SEND_TYPE_UDP1 == g_s_nbiot_send_type)||(SEND_TYPE_UDP2 == g_s_nbiot_send_type))
		{
			g_s_nbiot_main_state = S_NBIOT_MAIN_UDP_SEND;
			StartUdpSendData();
		}
		else
		{
			StartTcpSendData(); 
			g_s_nbiot_main_state = S_NBIOT_MAIN_TCP_SEND; //发送NBIOT数据
		}		
    }
    else
    {
        *state = NBIOT_ERROR;
    }
}
//获取发送类型
u8 GetNbiotSendType(void)
{
	return g_s_nbiot_send_type;	
}
/***************************************************************************
 * @fun_name     void NbiotReadCsqTask(u8 *out_csq,u8 *state)
 * @brief        NBIOT查询信号值任务
 * @param[in]    out_csq：存放数据地址
 * @param[out]   state:状态信息
 * @retval       None
 * @other        state(CSQ_ING：查询中, CSQ_SUCCES：成功 其他：异常)
 ***************************************************************************/
//void NbiotUdpOpenTask(void)
//{
//    if (S_NBIOT_MAIN_IDLE == g_s_nbiot_main_state)
//    {
//		if(!UdpIfOnline())
//		{
//			g_s_nbiot_task_flag = TASK_INIT;
//			g_s_nbiot_main_state = S_NBIOT_MAIN_UDP_OPEN;
//			UdpStartConnect();
//		}        
//    }   	
//}
/***************************************************************************
 * @fun_name     u8 NbiotIfSleep()
 * @brief        是否允许休眠
 * @param[in]    None
 * @param[out]   None
 * @retval       TRUE: 允许  FALSE:不允许
 * @other        None
 ***************************************************************************/
u8 NbiotIfSleep(void)
{
    if (S_NBIOT_MAIN_IDLE == g_s_nbiot_main_state)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

/***************************************************************************
 * @fun_name     void NbiotPreSleep()
 * @brief        休眠前操作
 * @param[in]    None
 * @param[out]   None
 * @retval       None
 * @other        None
 ***************************************************************************/
void NbiotPreSleep(void)
{
    NB_Power_Disable(); //切断电源
    UartPreSleep(NB_UART_COM);
    g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE;
	Nbiot_Para.net_state = NB_OFF_LINE;
	Nbiot_Para.coap_state = CONNECT_OFF_LINE;
	Nbiot_Para.udp1_state = CONNECT_OFF_LINE;
	Nbiot_Para.udp2_state = CONNECT_OFF_LINE;
	
	//配置NB相关引脚
	stc_gpio_cfg_t stcGpioCfg;
	DDL_ZERO_STRUCT(stcGpioCfg);	
	stcGpioCfg.enDir = GpioDirOut;    ///< 端口方向配置	
	stcGpioCfg.enDrv = GpioDrvL;      ///< 端口驱动能力配置->低驱动能力	
	stcGpioCfg.enPu = GpioPuDisable;  ///< 端口上下拉配置->无
	stcGpioCfg.enPd = GpioPdDisable;	
	stcGpioCfg.enOD = GpioOdDisable;  ///< 端口开漏输出配置
	stcGpioCfg.enCtrlMode = GpioAHB;  ///< 端口输入/输出值寄存器总线控制模式配置->AHB
	Gpio_Init(BAT_NB_PORT, BAT_NB_PIN, &stcGpioCfg);  //模块供电IO
    Gpio_Init(RSTN_NB_PORT, RSTN_NB_PIN, &stcGpioCfg);
    Gpio_Init(NB_PSM_WAKE_PORT, NB_PSM_WAKE_PIN, &stcGpioCfg);
    Gpio_Init(PWR_NB_PORT, PWR_NB_PIN, &stcGpioCfg);   //电源控制脚
	
	Gpio_WriteOutputIO(BAT_NB_PORT, BAT_NB_PIN, FALSE);
    Gpio_WriteOutputIO(PWR_NB_PORT, PWR_NB_PIN, FALSE);
	Gpio_WriteOutputIO(RSTN_NB_PORT, RSTN_NB_PIN, FALSE); 
	Gpio_WriteOutputIO(NB_PSM_WAKE_PORT , NB_PSM_WAKE_PIN, FALSE);	
	
	Gpio_Init(LPUART1_TX_PORT, LPUART1_TX_PIN, &stcGpioCfg);
	Gpio_WriteOutputIO(LPUART1_TX_PORT, LPUART1_TX_PIN, FALSE);	//TX也配置为输出低
	
	stcGpioCfg.enDir = GpioDirIn;   //RX输入
	Gpio_Init(LPUART1_RX_PORT, LPUART1_RX_PIN, &stcGpioCfg);
}
/***************************************************************************
 * @fun_name    void NbiotWakeSleep()
 * @brief        休眠后唤醒
 * @param[in]    None
 * @param[out]   None
 * @retval       None
 * @other        None
 ***************************************************************************/
void NbiotWakeSleep(void)
{

}
/******************************内部状态机***********************************/

/***************************************************************************
 * @fun_name     void NetModulePowerOn_Proc()
 * @brief        模组开机状态
 * @param[in] 	 None
 * @param[out] 	 None
 * @retval     	 None
 * @other        None
 ***************************************************************************/
TYP_RESULT_CODE NetModulePowerOn_Proc(void)
{
	switch(s_power_on_state)
	{
		case MODULE_IDLE://模块送电
        {  
        }
        break;
		case MODULE_POWERON://模块送电
        {  
			NbModuleIOInit();  //初始化默认模块断电
            UartInit(NB_UART_COM, BAUD9600, DATA_BIT_8, STOPBIT_1, UART_NONE_PARITY,UART_LPUART_Disable);	
            RSTN_NB_HIG();
            PWR_NB_HIG();
            NB_Power_Enable(); 						//打开电源，延时1S,等待上电稳定
            set_timer_1ms(MODULE_POWER_DELAY_TIME);
            s_power_on_state = MODULE_POWERON_WT;
        }
        break;
        case MODULE_POWERON_WT://NB模块送电
        {
            if (!check_timer_1ms())
            {
                PWR_NB_LOW();
				set_timer_1ms(MODULE_POWERKEY_DELAY_TIME);
                s_power_on_state = MODULE_POWER_KEY_ON_WT;
            }
        }
        break;
        case MODULE_POWER_KEY_ON_WT://NB模块送电
        {
            if (!check_timer_1ms())
            {
				s_power_on_state = MODULE_IDLE;
				return ResultOk;
            }
        }
        break;
		default:
		{
			s_power_on_state = MODULE_IDLE;
		}
		break;
	}
	return ResultBusy;
}
/***************************************************************************
 * @fun_name     void AT_Common_Requeset_Proc()
 * @brief        AT指令集通用查询函数
 * @param[in] 	 None
 * @param[out] 	 None
 * @retval     	 None
 * @other       中国移动的为:898600;898602;898604;898607 中国电信898603;898611
 ***************************************************************************/
int getAtIndexFromCode(TYP_AT_CMDCODE atCode)
{
    for(int i=0;i<AT_CMD_COUNT;i++)
	{
	    if(AtCmdBuf[i].AtCode == atCode)
		{
		    return i;
		}
	}
	return 0;
}
TYP_RESULT_CODE AT_Common_Requeset_Proc(TYP_AT_CMDCODE atCode, char addFlag, char* addBuf, int addLen)
{
	switch(s_at_requeset_state)
	{
		case AT_REQUEST_IDLE:
		{
			g_at_index = getAtIndexFromCode(atCode);
			at_requestErrorCount = 0;
			set_timer_1ms(500);
			s_at_requeset_state = AT_REQUEST_WT;
		}
		break;
		case AT_REQUEST_WT:
		{
			if (!check_timer_1ms())
			{
				set_timer_1s(0);
				s_at_requeset_state = AT_REQUEST_SEND;
			}
		}
		break;
		case AT_REQUEST_SEND:
		{
			if(!check_timer_1s())
			{
				memset(AT_BUF,0,sizeof(AT_BUF));
				int i=0;
				int all_len=0;
				int str_len = strlen(AtCmdBuf[g_at_index].pAtCmdStr);
				const char *p;
				p = AtCmdBuf[g_at_index].pAtCmdStr;
				for(i=0; i<str_len; i++)
				{
					AT_BUF[i] = *p++;
					all_len++;
				}
				if(addFlag==1)
				{
					for(i=0; i<addLen; i++)
					{
						AT_BUF[str_len+i] = *addBuf++;
						all_len++;
					}
				}
				AT_BUF[all_len++] = '\r';
				/*strcpy(AT_BUF, AtCmdBuf[g_at_index].pAtCmdStr);//不能使用strcpy,否则取数据只能到0x00
				if(addFlag==1)
				{
					strcat(AT_BUF, addBuf);
				}
				strcat(AT_BUF, "\r");*/
					
				NbiotUartSend((u8*)AT_BUF, all_len, AtCmdBuf[g_at_index].CaseAtNum);//不能用strlen(AT_BUF),否则只能发送到0x00
				set_timer_1s(AtCmdBuf[g_at_index].WaitTime); 
				s_at_requeset_state = AT_REQUEST_CHECK;
			}
		}
		break;
		case AT_REQUEST_CHECK:
		{
			if (NbiotCheckAtAck() == UART_OK)//返回正确的应答
            {
				s_at_requeset_state = AT_REQUEST_IDLE;
				return ResultOk;
            }
            else if ((!check_timer_1s()) || (NbiotCheckAtAck() == UART_ERROR)) //应答超时或者错误
            {
                if (at_requestErrorCount >= AtCmdBuf[g_at_index].ErrorLimit)
                {
					s_at_requeset_state = AT_REQUEST_IDLE;
					return ResultFail;
                }
                else
                {
					at_requestErrorCount++;
                    set_timer_1s(AtCmdBuf[g_at_index].WaitTime);
					s_at_requeset_state = AT_REQUEST_SEND;
                }
            }
		}
		break;
		default:
		{
			s_at_requeset_state = AT_REQUEST_IDLE;
			return ResultFail;
		}
	}
	return ResultBusy;
}

/***************************************************************************
 * @fun_name     void NbiotInitMachine()
 * @brief       模组初始化状态机
 * @param[in] 	 None
 * @param[out] 	 None
 * @retval     	 None
 * @other       
 ***************************************************************************/
void StartNbiotInit(void)
{
	s_init_state = S_MODULE_INIT_POWER_ON;
	s_power_on_state = MODULE_POWERON;//模块送电
}

void NbiotInitMachine_ML302(void)
{
    switch (s_init_state)
    {
		case S_MODULE_INIT_IDLE:
		{
			break;
		}
        case S_MODULE_INIT_POWER_ON://NB模块送电
        {  
			g_at_request_res = NetModulePowerOn_Proc();
			if(g_at_request_res == ResultOk)
			{
				//NB_UartInitForGPIO();//debug
				//初始化可调参数
				u8 NB_login_ask_times = (FrameCheckParaApp(FramePara_NbParaLoginAckTimes)/3);
				if (NB_login_ask_times < NET_CEREG_MIN_TIMES)
				{
					NB_login_ask_times = NET_CEREG_MIN_TIMES;
				}
				if (NB_login_ask_times > NET_CEREG_MAX_TIMES)
				{
					NB_login_ask_times = NET_CEREG_MAX_TIMES;
				}
				AtCmdBuf[getAtIndexFromCode(AT_CODE_CEREG)].ErrorLimit = NB_login_ask_times;//查询网络注册状态次数
				
				s_init_state = S_MODULE_INIT_AT;
			}
        }
        break;
        case S_MODULE_INIT_AT:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_AT, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CMEE;
			}
			else if(g_at_request_res == ResultFail)
			{
				g_s_nbiot_task_flag = TASK_FAIL; //初始化任务失败
				s_init_state = S_MODULE_INIT_IDLE;
			}
        }
        break;
        case S_MODULE_INIT_CMEE:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CMEE, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CGSN;
			}
			else if(g_at_request_res == ResultFail)
			{
				g_s_nbiot_task_flag = TASK_FAIL; //初始化任务失败
				s_init_state = S_MODULE_INIT_IDLE;
			}
        }
        break;
		case S_MODULE_INIT_CGSN:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CGSN, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CPIN;
			}
			else if(g_at_request_res == ResultFail)
			{
				g_s_nbiot_task_flag = TASK_FAIL; //初始化任务失败
				s_init_state = S_MODULE_INIT_IDLE;
			}
        }
        break;
		case S_MODULE_INIT_CPIN:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CPIN, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CIMI;
			}
			else if(g_at_request_res == ResultFail)
			{
				g_s_nbiot_task_flag = TASK_FAIL; //初始化任务失败
				s_init_state = S_MODULE_INIT_IDLE;
			}
        }
        break;
		case S_MODULE_INIT_CIMI:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CIMI, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_ICCID;
			}
			else if(g_at_request_res == ResultFail)
			{
				g_s_nbiot_task_flag = TASK_FAIL; //初始化任务失败
				s_init_state = S_MODULE_INIT_IDLE;
			}
        }
        break;
		case S_MODULE_INIT_ICCID:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_ICCID, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CFUN_CK;
			}
			else if(g_at_request_res == ResultFail)
			{
				g_s_nbiot_task_flag = TASK_FAIL; //初始化任务失败
				s_init_state = S_MODULE_INIT_IDLE;
			}
        }
        break;
		case S_MODULE_INIT_CFUN_CK:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CFUN_CK, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_VERCTRL;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_CFUN1;
			}
        }
        break;
		case S_MODULE_INIT_CFUN1:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CFUN1, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{	
				s_init_state = S_MODULE_INIT_VERCTRL;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_VERCTRL;
			}
        }
        break;
		case S_MODULE_INIT_VERCTRL://查询激活方式
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_VERCTRL, 0, NULL,0);
            if(g_at_request_res == ResultOk)//如果是自动激活
			{
				s_init_state = S_MODULE_INIT_CSQ;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_VERCTRL1;
			}
        }
        break;
		case S_MODULE_INIT_VERCTRL1://设置自动激活(注意,重启后才能生效,PCBA测试不需要激活成功)
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_VERCTRL1, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CSQ;
			}
			else if(g_at_request_res == ResultFail)
			{
				g_s_nbiot_task_flag = TASK_FAIL; //初始化任务失败
				s_init_state = S_MODULE_INIT_IDLE;
			}
        }
        break;
		case S_MODULE_INIT_CSQ:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CSQ, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CEREG_CK;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_CEREG_CK;
			}
        }
        break;
		/*
		case S_MODULE_INIT_CTEC_CK:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CTEC_CK, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CCED_CK;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_CCED_CK;
			}
        }
        break;
		
		case S_MODULE_INIT_CCED_CK:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CCED_CK, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CEREG_CK;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_CEREG_CK;
			}
        }
        break;
		*/
		/*case S_MODULE_INIT_CGDCONT:
        {
			//获取APN参数
			memset(stringbuffer_temp,0,sizeof(stringbuffer_temp));	
			for(int i = 0; i < Sys_data_object.P1.apn[1]; i++)
			{
				stringbuffer_temp[i] = Sys_data_object.P1.apn[2 + i];
			}	
			stringbuffer_temp[Sys_data_object.P1.apn[1]] = '\"';
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CGDCONT, 1, stringbuffer_temp, Sys_data_object.P1.apn[1]+1);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CGACT;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_CGACT;
			}
        }
        break;
		case S_MODULE_INIT_CGACT:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CGACT, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{			
				s_init_state = S_MODULE_INIT_CEREG_CK;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_CEREG_CK;
			}
        }
        break;
		*/
		case S_MODULE_INIT_CEREG_CK:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CEREG, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CGACT_CK;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_CGACT_CK;
			}
        }
        break;
		case S_MODULE_INIT_CGACT_CK:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CGACT_CK, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_TUEINFO;
			}
			else if(g_at_request_res == ResultFail)
			{
				g_s_nbiot_task_flag = TASK_FAIL; //初始化任务失败
				s_init_state = S_MODULE_INIT_IDLE;
			}
        }
        break;	
		case S_MODULE_INIT_TUEINFO:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_TUEINFO, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CCED;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_CCED;
			}
        }
        break;
		case S_MODULE_INIT_CCED:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CCED, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				s_init_state = S_MODULE_INIT_CCLK;
			}
			else if(g_at_request_res == ResultFail)
			{
				s_init_state = S_MODULE_INIT_CCLK;
			}
        }
        break;
		case S_MODULE_INIT_CCLK:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_CCLK, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				g_s_nbiot_task_flag = TASK_SUCCESS; //初始化任务成功
				s_init_state = S_MODULE_INIT_IDLE;
			}
			else if(g_at_request_res == ResultFail)
			{
				g_s_nbiot_task_flag = TASK_SUCCESS; //初始化任务成功
				s_init_state = S_MODULE_INIT_IDLE;
			}
        }
        break;	
        default:
        {
			g_s_nbiot_task_flag = TASK_FAIL; //初始化任务失败
			s_init_state = S_MODULE_INIT_IDLE;
        }
        break;
    }
}
void NbiotInitMachine(void)
{
    NbiotInitMachine_ML302();
}
/***************************************************************************
 * @fun_name     void TcpConnectMachine()
 * @brief       TCP连接状态机
 * @param[in] 	 None
 * @param[out] 	 None
 * @retval     	 None
 * @other       
 ***************************************************************************/
void TcpStartConnect(void)
{
	s_tcp_connect_state = S_TCP_CONNECT_START;
}
void TcpConnectMachine_ML302(void)
{
	unsigned char *nbiot_ip;
    u16 nbiot_port;
	static int ip_len=0;
	switch (s_tcp_connect_state)
    {
		case S_TCP_CONNECT_IDLE:
		{
			break;
		}
        case S_TCP_CONNECT_START:
        {		
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_MIPMODE1, 0, NULL,0);
            if(g_at_request_res == ResultOk)
			{
				ip_len = 0; 
				nbiot_port = coap_port;//Sys_data_object.P1.server_port.datas;
				nbiot_ip = coap_ip;//Sys_data_object.P1.server_ip;
				memset(stringbuffer_temp,0,sizeof(stringbuffer_temp));
				//IP 的存储仍然使用水表原来格式，不保存“.”号，使用时加入
				int i;
				for (i = 0; i < 4; i++)
				{
					if (nbiot_ip[i] < 10)
					{
						stringbuffer_temp[ip_len++] = nbiot_ip[i] + 0x30;
					}
					else if (nbiot_ip[i] < 100)
					{
						stringbuffer_temp[ip_len++] = (nbiot_ip[i] / 10) + 0x30;
						stringbuffer_temp[ip_len++] = (nbiot_ip[i] % 10) + 0x30;
					}
					else
					{
						stringbuffer_temp[ip_len++] = (nbiot_ip[i] / 100) + 0x30;
						stringbuffer_temp[ip_len++] = (nbiot_ip[i] / 10) % 10 + 0x30;
						stringbuffer_temp[ip_len++] = (nbiot_ip[i] % 10) + 0x30;
					}
					stringbuffer_temp[ip_len++] = '.';
				}
				ip_len--; //消除多余的点号
				stringbuffer_temp[ip_len++] = '\"';
				stringbuffer_temp[ip_len++] = ',';
				stringbuffer_temp[ip_len++] = ((nbiot_port) / 10000) + 0x30;
				stringbuffer_temp[ip_len++] = (((nbiot_port) % 10000) / 1000) + 0x30;
				stringbuffer_temp[ip_len++] = (((nbiot_port) % 1000) / 100) + 0x30;
				stringbuffer_temp[ip_len++] = (((nbiot_port) % 100) / 10) + 0x30;
				stringbuffer_temp[ip_len++] = ((nbiot_port) % 10) + 0x30;
				stringbuffer_temp[ip_len++] = '\r';
				
				s_tcp_connect_state = S_TCP_CONNECT_MIPOPEN;
			}
			else if(g_at_request_res == ResultFail)
			{
				
				s_tcp_connect_state = S_TCP_CONNECT_MIPOPEN;
			}
        }
        break;
		case S_TCP_CONNECT_MIPOPEN:
        {
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_MIPOPEN, 1, stringbuffer_temp,ip_len);
            if(g_at_request_res == ResultOk)
			{
				
                g_s_nbiot_task_flag = TASK_SUCCESS; //成功
				s_tcp_connect_state = S_TCP_CONNECT_IDLE;
			}
			else if(g_at_request_res == ResultFail)
			{
				
				g_s_nbiot_task_flag = TASK_FAIL; //任务失败
				s_tcp_connect_state = S_TCP_CONNECT_IDLE;
			}
        }
        break;
		default:
		{
			
			g_s_nbiot_task_flag = TASK_FAIL; 
			s_tcp_connect_state = S_TCP_CONNECT_IDLE;
			break;
		}
	}
}

void TcpConnectMachine(void)
{
    TcpConnectMachine_ML302();
}
/***************************************************************************
 * @fun_name     void TcpSendDataMachine()
 * @brief       TCP发送数据状态机
 * @param[in] 	 None
 * @param[out] 	 None
 * @retval     	 None
 * @other       
[15:27:39.342]收←◆AT+MIPSEND=1,0352
> 
[15:27:43.341]收←◆AT+MIPSEND=1,0352
[15:27:47.357]收←◆AT+MIPSEND=1,0352
[15:27:51.356]收←◆AT+MIPSEND=1,0352
[15:27:55.371]收←◆AT+MIPSEND=1,0352
注意，如果设置了发送数据长度，但没有发送数据，再设置长度无反应
 ***************************************************************************/
void StartTcpSendData(void)
{
	s_tcp_send_state = S_TCP_SEND_START;
}
void TcpSendDataMachine_ML302(void)
{
	switch (s_tcp_send_state)
	{
		case S_TCP_SEND_IDLE:
		{
		}
		break;
		case S_TCP_SEND_START:
		{			
			NbiotClearMsg();
			memset(stringbuffer_temp,0,sizeof(stringbuffer_temp));
			 //内容
			tcp_send_len = 0;
			for (int i = 0; i < Nbiot_Send_Data.len; i++)//获取发送数据内容
			{
				stringbuffer_temp[tcp_send_len++] = *(Nbiot_Send_Data.buf + i);//数据发送十六进制格式
			}
			memset(tcp_send_len_buf,0,sizeof(tcp_send_len_buf));
			tcp_send_len = Nbiot_Send_Data.len;
			//发送数据长度
			if (tcp_send_len < 10)
			{
				tcp_send_len_buf[0] = tcp_send_len + 0x30;
				tcp_send_len_buf_len = 1;
			}
			else if (tcp_send_len < 100)
			{
				tcp_send_len_buf[0] = (tcp_send_len / 10) + 0x30;
				tcp_send_len_buf[1] = (tcp_send_len % 10) + 0x30;
				tcp_send_len_buf_len = 2;
			}
			else
			{
				tcp_send_len_buf[0] = (tcp_send_len / 100) + 0x30;
				tcp_send_len_buf[1] = (tcp_send_len / 10) % 10 + 0x30;
				tcp_send_len_buf[2] = (tcp_send_len % 10) + 0x30;
				tcp_send_len_buf_len = 3;
			}
			s_tcp_send_state = S_TCP_SEND_DATALEN;
		}
		break;
		case S_TCP_SEND_DATALEN://发送数据长度
		{
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_MIPSENDCOUNT, 1, tcp_send_len_buf, tcp_send_len_buf_len);
            if(g_at_request_res == ResultOk)
			{
				
				s_tcp_send_state = S_TCP_SEND_DATA;
			}
			else if(g_at_request_res == ResultFail)
			{
				
                g_s_nbiot_task_flag = TASK_FAIL; //失败
				s_tcp_send_state = S_TCP_SEND_IDLE;
			}
		}
		break;
		case S_TCP_SEND_DATA://发送数据
		{
			g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_TCPSEND, 1, stringbuffer_temp, tcp_send_len);
            if(g_at_request_res == ResultOk)
			{
				
                g_s_nbiot_task_flag = TASK_SUCCESS; //成功
				s_tcp_send_state = S_TCP_SEND_IDLE;
			}
			else if(g_at_request_res == ResultFail)
			{
				
                g_s_nbiot_task_flag = TASK_FAIL; //失败
				s_tcp_send_state = S_TCP_SEND_IDLE;
			}
		}
		break;
		default:
		{
			
			g_s_nbiot_task_flag = TASK_FAIL; //失败
			s_tcp_send_state = S_TCP_SEND_IDLE;
		}
		break;
	}
}

void TcpSendDataMachine(void)
{
    TcpSendDataMachine_ML302();
}
//启动连接UDP
void UdpStartConnect(u8 udp_num)
{
	nbiot_temp_connect_type = udp_num;
	s_udp_connect_state = S_UDP_CONNECT_START;
}
/***************************************************************************
 * @fun_name     void UdpConnectMachine(void)
 * @brief        连接UDP状态机
 ***************************************************************************/
void UdpConnectMachine_ML302(void)
{
	unsigned char *nbiot_ip;
    u16 nbiot_port;
	static int ip_len=0;
	switch (s_udp_connect_state)
    {
		case S_UDP_CONNECT_IDLE:
		{
			break;
		}
        case S_UDP_CONNECT_START:
        {			
			ip_len = 0; 
			if(nbiot_temp_connect_type == NBIOT_CONNECT_UDP1)
			{
				nbiot_port = udp_port1;//Sys_data_object.P2.server_port.datas;
				nbiot_ip = udp_ip1;//Sys_data_object.P2.server_ip;
			}
			else if(nbiot_temp_connect_type == NBIOT_CONNECT_UDP2)
			{
				nbiot_port = udp_port2;
				nbiot_ip = udp_ip2;
			}
			memset(stringbuffer_temp,0,sizeof(stringbuffer_temp));
			//IP 的存储仍然使用水表原来格式，不保存“.”号，使用时加入
			int i;
			for (i = 0; i < 4; i++)
			{
				if (nbiot_ip[i] < 10)
				{
					stringbuffer_temp[ip_len++] = nbiot_ip[i] + 0x30;
				}
				else if (nbiot_ip[i] < 100)
				{
					stringbuffer_temp[ip_len++] = (nbiot_ip[i] / 10) + 0x30;
					stringbuffer_temp[ip_len++] = (nbiot_ip[i] % 10) + 0x30;
				}
				else
				{
					stringbuffer_temp[ip_len++] = (nbiot_ip[i] / 100) + 0x30;
					stringbuffer_temp[ip_len++] = (nbiot_ip[i] / 10) % 10 + 0x30;
					stringbuffer_temp[ip_len++] = (nbiot_ip[i] % 10) + 0x30;
				}
				stringbuffer_temp[ip_len++] = '.';
			}
			ip_len--; //消除多余的点号
			stringbuffer_temp[ip_len++] = '\"';
			stringbuffer_temp[ip_len++] = ',';
			stringbuffer_temp[ip_len++] = ((nbiot_port) / 10000) + 0x30;
			stringbuffer_temp[ip_len++] = (((nbiot_port) % 10000) / 1000) + 0x30;
			stringbuffer_temp[ip_len++] = (((nbiot_port) % 1000) / 100) + 0x30;
			stringbuffer_temp[ip_len++] = (((nbiot_port) % 100) / 10) + 0x30;
			stringbuffer_temp[ip_len++] = ((nbiot_port) % 10) + 0x30;
			stringbuffer_temp[ip_len++] = '\r';
			
			s_udp_connect_state = S_UDP_CONNECT_MIPOPEN;
        }
        break;
		case S_UDP_CONNECT_MIPOPEN:
        {
			if(nbiot_temp_connect_type == NBIOT_CONNECT_UDP1)
			{
				g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_MIPOPEN_UDP1, 1, stringbuffer_temp,ip_len);
			}
			else if(nbiot_temp_connect_type == NBIOT_CONNECT_UDP2)
			{
				g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_MIPOPEN_UDP2, 1, stringbuffer_temp,ip_len);
			}
            if(g_at_request_res == ResultOk)
			{
				
                g_s_nbiot_task_flag = TASK_SUCCESS; //成功
				s_udp_connect_state = S_UDP_CONNECT_IDLE;
			}
			else if(g_at_request_res == ResultFail)
			{
				
				g_s_nbiot_task_flag = TASK_FAIL; //任务失败
				s_udp_connect_state = S_UDP_CONNECT_IDLE;
			}
        }
        break;
		default:
		{
			
			g_s_nbiot_task_flag = TASK_FAIL; 
			s_udp_connect_state = S_UDP_CONNECT_IDLE;
			break;
		}
	}
}
void UdpConnectMachine(void)
{
   UdpConnectMachine_ML302();
}
//
void StartUdpSendData(void)
{
	s_udp_send_state = S_UDP_SEND_START;
}
//
void UdpSendDataMachine_ML302(void)
{
	switch (s_udp_send_state)
	{ 
		case S_UDP_SEND_IDLE:
		{
		}
		break;
		case S_UDP_SEND_START:
		{			
			NbiotClearMsg();
			memset(stringbuffer_temp,0,sizeof(stringbuffer_temp));
			 //内容
			udp_send_len = 0;
			for (int i = 0; i < Nbiot_Send_Data.len; i++)//获取发送数据内容
			{
				stringbuffer_temp[udp_send_len++] = *(Nbiot_Send_Data.buf + i);//数据发送十六进制格式
			}
			memset(udp_send_len_buf,0,sizeof(udp_send_len_buf));
			udp_send_len = Nbiot_Send_Data.len;
			//发送数据长度
			if (udp_send_len < 10)
			{
				udp_send_len_buf[0] = udp_send_len + 0x30;
				udp_send_len_buf_len = 1;
			}
			else if (udp_send_len < 100)
			{
				udp_send_len_buf[0] = (udp_send_len / 10) + 0x30;
				udp_send_len_buf[1] = (udp_send_len % 10) + 0x30;
				udp_send_len_buf_len = 2;
			}
			else
			{
				udp_send_len_buf[0] = (udp_send_len / 100) + 0x30;
				udp_send_len_buf[1] = (udp_send_len / 10) % 10 + 0x30;
				udp_send_len_buf[2] = (udp_send_len % 10) + 0x30;
				udp_send_len_buf_len = 3;
			}
			s_udp_send_state = S_UDP_SEND_DATALEN;
		}
		break;
		case S_UDP_SEND_DATALEN://发送数据长度
		{
			if(g_s_nbiot_send_type == SEND_TYPE_UDP1)
			{
				g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_MIPSENDCOUNT_UDP1, 1, udp_send_len_buf, udp_send_len_buf_len);
			}
			else if(g_s_nbiot_send_type == SEND_TYPE_UDP2)
			{
				g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_MIPSENDCOUNT_UDP2, 1, udp_send_len_buf, udp_send_len_buf_len);
			}
            if(g_at_request_res == ResultOk)
			{
				
				s_udp_send_state = S_UDP_SEND_DATA;
			}
			else if(g_at_request_res == ResultFail)
			{
				
                g_s_nbiot_task_flag = TASK_FAIL; //失败
				s_udp_send_state = S_UDP_SEND_IDLE;
			}
		}
		break;
		case S_UDP_SEND_DATA://发送数据
		{
			if(g_s_nbiot_send_type == SEND_TYPE_UDP1)
			{
				g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_UDPSEND1, 1, stringbuffer_temp, udp_send_len);
			}
			else if(g_s_nbiot_send_type == SEND_TYPE_UDP2)
			{
				g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_UDPSEND2, 1, stringbuffer_temp, udp_send_len);
			}
            if(g_at_request_res == ResultOk)
			{
				
                g_s_nbiot_task_flag = TASK_SUCCESS; //成功
				s_udp_send_state = S_UDP_SEND_IDLE;
			}
			else if(g_at_request_res == ResultFail)
			{
				
                g_s_nbiot_task_flag = TASK_FAIL; //失败
				s_udp_send_state = S_UDP_SEND_IDLE;
			}
		}
		break;
		default:
		{
			
			g_s_nbiot_task_flag = TASK_FAIL; //失败
			s_udp_send_state = S_UDP_SEND_IDLE;
		}
		break;
	}
}
void UdpSendDataMachine(void)
{
	UdpSendDataMachine_ML302();
}
/***************************************************************************
 * @fun_name    static void NbiotPowerOffMachine()
 * @brief        关机状态机
 ***************************************************************************/
//模组关机状态号
void NbiotPowerOffMachine(void) //先注销网络然后断电关机
{
    switch (s_power_off_state)
    {
		case S_PWOFF_IDLE:
		{
		}
		break;
        case S_PWOFF_TCP_CLOSE:
        {
			if(ConncetIfOnline(NBIOT_CONNECT_COAP) == TRUE)
			{
				g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_MIPCLOSE, 0, NULL,0);
				if(g_at_request_res == ResultOk)
				{
					s_power_off_state = S_PWOFF_UDP1_CLOSE;
				}
				else if(g_at_request_res == ResultFail)
				{
					s_power_off_state = S_PWOFF_UDP1_CLOSE;
				}
			}
			else
			{
				s_power_off_state = S_PWOFF_UDP1_CLOSE;
			}
        }
        break;
		case S_PWOFF_UDP1_CLOSE:
        {
			if(ConncetIfOnline(NBIOT_CONNECT_UDP1) == TRUE)
			{
				g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_MIPCLOSE_UDP1, 0, NULL,0);
				if(g_at_request_res == ResultOk)
				{
					s_power_off_state = S_PWOFF_UDP2_CLOSE;
				}
				else if(g_at_request_res == ResultFail)
				{
					s_power_off_state = S_PWOFF_UDP2_CLOSE;
				}
			}
			else
			{
				s_power_off_state = S_PWOFF_UDP2_CLOSE;
			}
        }
        break;
		case S_PWOFF_UDP2_CLOSE:
        {
			if(ConncetIfOnline(NBIOT_CONNECT_UDP2) == TRUE)
			{
				g_at_request_res = AT_Common_Requeset_Proc(AT_CODE_MIPCLOSE_UDP2, 0, NULL,0);
				if(g_at_request_res == ResultOk)
				{
					s_power_off_state = S_PWOFF_PW_DOWN;
				}
				else if(g_at_request_res == ResultFail)
				{
					s_power_off_state = S_PWOFF_PW_DOWN;
				}
			}
			else
			{
				s_power_off_state = S_PWOFF_PW_DOWN;
			}
        }
        break;
        case S_PWOFF_PW_DOWN:
        {
			if (!check_timer_1s())
			{
				NB_Power_Disable(); //切断电源
				set_timer_1s(1);
				s_power_off_state = S_PWOFF_PW_DOWN_WAIT;
				Nbiot_Para.net_state = NB_OFF_LINE;
				Nbiot_Para.coap_state = CONNECT_OFF_LINE;
				Nbiot_Para.udp1_state = CONNECT_OFF_LINE;
				Nbiot_Para.udp2_state = CONNECT_OFF_LINE;
			}
        }
        break;

        case S_PWOFF_PW_DOWN_WAIT:
        {
            if (!check_timer_1s())
            {
                NbiotPreSleep();
                g_s_nbiot_task_flag = TASK_SUCCESS;
                s_power_off_state = S_PWOFF_IDLE;
            }
        }
        break;

        default:
        {
            s_power_off_state = S_PWOFF_IDLE;
        }
        break;
    }
}

/***************************************************************************
 * @fun_name    定时器资源
 * @brief       该内部接口主要为了方便记忆及使用
 ***************************************************************************/
void set_timer_1s(u16 time)
{
    Set100msTimer(TIMER_100MS_NBIOT, time * 10);
}

u16 check_timer_1s(void)
{
    return Check100msTimer(TIMER_100MS_NBIOT);
}

void set_timer_1ms(u16 time)
{
    Set5msTimer(TIMER_5MS_NBIOT, time / 5);
}

u16 check_timer_1ms(void)
{
    return Check5msTimer(TIMER_5MS_NBIOT);
}

/***************************************************************************
 * @fun_name     void StartPowerOffTask()
 * @brief        关机接口
 ***************************************************************************/
void StartPowerOffTask(void)
{	
    g_s_nbiot_task_flag = TASK_INIT;
    g_s_nbiot_main_state = S_NBIOT_MAIN_POWER_OFF;
	s_power_off_state = S_PWOFF_TCP_CLOSE;	
}

//NB强制关机
void NbForcePowerOff(void)
{
    NB_Power_Disable();
	Nbiot_Para.net_state = NB_OFF_LINE;
	Nbiot_Para.coap_state = CONNECT_OFF_LINE;
	Nbiot_Para.udp1_state = CONNECT_OFF_LINE;
	Nbiot_Para.udp2_state = CONNECT_OFF_LINE;
    g_s_nbiot_task_flag = TASK_INIT;
    g_s_nbiot_main_state = S_NBIOT_MAIN_IDLE;
	s_at_requeset_state = AT_REQUEST_IDLE;
}

UNION_4U8TOU32 net_state_data;
u32 sys_get_net_state(void)
{
	s16 s_temp_data=0;
	if(g_s_nbiot_main_state == S_NBIOT_MAIN_POWER_INIT)
	{
		net_state_data.data_buf[0] = 1;
		net_state_data.data_buf[1] = s_init_state;
		//net_state_buf[2]CEREG
		//net_state_buf[3]cgatt
	}
	else if(g_s_nbiot_main_state == S_NBIOT_MAIN_TCP_OPEN)
	{
		net_state_data.data_buf[0] = 2;
		net_state_data.data_buf[1] = s_tcp_connect_state;
	}
	else if(If_NB_Poweron()==FALSE)
	{
		net_state_data.data_buf[0] = 3;
		//rsrp
		NbiotGetRSRP(&s_temp_data);
		net_state_data.data_buf[1] = -(s_temp_data/10);
		//SNR
		NbiotGetSNR(&s_temp_data);
		if(s_temp_data<0)
		{
			net_state_data.data_buf[2] = (-s_temp_data/10)|0x80;
		}
		else
		{
			net_state_data.data_buf[2] = s_temp_data/10;
		}
		//CSQ
		 NbiotGetCSQ(&net_state_data.data_buf[3]); 
	}
	return net_state_data.datas;
}

void sys_set_net_state(u8 state, u8 data)
{
	net_state_data.data_buf[state] = data;
}
/**NB接口**/
TYP_PSM_STATE getPsmState(void)
{
    return PSM_STATE_OUT;//不进入PSM模式
}	
void NbiotPsmWakeupTask(void)
{
 
}
void NbiotPsmSleepTask(void)
{
 
}
void NbiotPsmCheckTask(void)
{
   
}
#ifdef	__cplusplus
}
#endif

#endif
