/**
* author wulianwei
* title BC260Y模块驱动
*/
#include "stm32f10x.h"
#include "bc26.h"
#include "sys.h"
#include "module_wrapper.h"
#include "at.h"
//C库
#include <string.h>
#include <stdio.h>

extern uart_recv_t uart_recv;


extern valid_data_t valid_data;


uint8_t err_cout = MODULE_FAIL;

static at_event_t* event = NULL;//当前事件


//从睡眠中唤醒BC26
static void bc26_wake(void)
{
	at_send_simple_cmd(AT); //AT触发
}

//==========================================================
//	函数名称：	bc26_send_data
//
//	函数功能：	发送数据
//
//	入口参数：	data：数据(数组)
//				len：长度
//
//	返回参数：	无
//
//	说明：		
//==========================================================
static int bc26_send_data(const void *data, int len)
{

	char cmdBuf[SEND_SIZE+20]={0};
	char hexData[SEND_SIZE] = {0};
	bc26_wake();	
	//bc26_tcp_reconnect();
	byteToHexStr(data,hexData,len);
	snprintf(cmdBuf,SEND_SIZE,"AT+QISEND=0,%d,\"%s\",%d\r\n", len,hexData,0);		//发送数据，返回后不释放链接
//	UsartPrintf(USART_DEBUG, "raisend:%s\r\n",cmdBuf);
	if(!at_send_cmd(cmdBuf, "SEND OK"))				
	{
		// Usart_SendString(USART2, data, len);		//发送设备连接请求数据
		 
		return 0;
		 
	}
	return -1;
}

static int bc26_send_data_rai(const void *data, int len,int rai)
{

	char cmdBuf[SEND_SIZE+20]={0};
	char hexData[SEND_SIZE] = {0};
	bc26_wake();
	delay_ms(3);
	bc26_wake();
	//清空接收缓存
	//bc26_tcp_reconnect();
	len = len<=SEND_SIZE/2 ? len:SEND_SIZE/2;
	byteToHexStr(data,hexData, len);
	snprintf(cmdBuf,sizeof(cmdBuf),"AT+QISEND=0,%d,\"%s\",%d\r\n", len,hexData,rai);		//发送数据，返回后释放链接
	//UsartPrintf(USART_DEBUG, "\r\nraisend:%s,%d\r\n",cmdBuf,strlen(cmdBuf));
	if(!at_send_cmd(cmdBuf, "SEND OK"))				
	{
		// Usart_SendString(USART2, data, len);		//发送设备连接请求数据
		return 0;
	}
	return -1;
}

/**选择通道发送数据*/
static int bc26_send_data_ch(const void *data, int len,uint8_t ch,int rai)
{

	char cmdBuf[SEND_SIZE+20]={0};
	char hexData[SEND_SIZE] = {0};
	bc26_wake();
	delay_ms(3);
	bc26_wake();
	//清空接收缓存
	//bc26_tcp_reconnect();
	len = len<=SEND_SIZE/2 ? len:SEND_SIZE/2;
	byteToHexStr(data,hexData, len);
	snprintf(cmdBuf,sizeof(cmdBuf),"AT+QISEND=%d,%d,\"%s\",%d\r\n", ch,len,hexData,rai);		//发送数据，返回后释放链接
	//UsartPrintf(USART_DEBUG, "\r\nraisend:%s,%d\r\n",cmdBuf,strlen(cmdBuf));
	if(!at_send_cmd(cmdBuf, "SEND OK"))				
	{
		// Usart_SendString(USART2, data, len);		//发送设备连接请求数据
		return 0;
	}
	return -1;
}

//==========================================================
//	函数名称：	bc26_get_data
//
//	函数功能：	获取平台返回的数据
//
//	入口参数：	data:存储有效数据(数组),len:有效数据长度,timeOut:等待的时间(ms)
//
//	返回参数：	平台返回的原始数据
//
//	说明：		不同网络设备返回的格式不同，需要去调试
//==========================================================
static int bc26_get_data(void *data,int len,int timeOut)
{

	int minLen  = 0;
	char *recvdiff[4] = {0};//分割字符串地址
	char recvbuf[RECV_SIZE] = {0};
	int data_len = 0;//有效数据长度
	char *recvSign = "+QIURC: \"recv\",0,";

	if(!uart_recv_match_wait(recvSign,timeOut))
	{
		uart_recv.start_addr = strstr(uart_recv.buf,recvSign);
		UsartPrintf(USART_DEBUG, "返回数据:%d,%s\r\n",uart_recv.len,uart_recv.start_addr);
		memcpy((char*)recvbuf, (char*)uart_recv.start_addr, uart_recv.len);
		split((char*)recvbuf,",",recvdiff,sizeof(recvdiff));
		data_len = my_atoi(recvdiff[2]);
	  minLen = data_len < len? data_len : len;
		memcpy(data,(char*)recvdiff[3]+1,minLen); //有效数据前后多了一个双引号
		uart_recv_clear();
	  return data_len;
	}
	uart_recv_clear();
	return -1;
}

static void bc26_restart(void)
{
	UsartPrintf(USART_DEBUG, "自动重启\r\n");
	BC26_RST_HIGH();
	delay_ms(60);
	BC26_RST_LOW();
	uart_recv_clear();
}



static int bc26_config(void)
{
	char recv[300] = {0};
	at_send_cmd_back_wait(AT,recv,sizeof(recv),100); //AT触发
	UsartPrintf(USART_DEBUG, "1.休眠\r\n");
	at_send_cmd_back(LIGHTSLEEP,recv,sizeof(recv));
	if(!strstr(recv,"OK"))
	{
		UsartPrintf(USART_DEBUG,"休眠失败\r\n");
		return -1;
	}
	
	UsartPrintf(USART_DEBUG, "2.不回显命令\r\n");
	at_send_cmd_back(ATE0,recv,sizeof(recv));
	if(!strstr(recv,"OK"))
	{
		UsartPrintf(USART_DEBUG,"禁止回显失败\r\n");
		return -1;
	}
	
	UsartPrintf(USART_DEBUG, "3.16进制发送数据\r\n");
	at_send_cmd_back(QICFG,recv,sizeof(recv));
	if(!strstr(recv,"OK"))
	{
		UsartPrintf(USART_DEBUG,"16进制发送数据失败\r\n");
		return -1;
	}
	
	module_init_status = MODULE_OK;
	return 0;
}



//==========================================================
//	函数名称：	bc26_init
//
//	函数功能：	初始化BC26
//
//	入口参数：	无
//
//	返回参数：	0 成功 1失败
//
//	说明：		
//==========================================================
static int bc26_init(void)
{
	return bc26_config();
}

/**
* @Title 模块ue功能关闭
* @Return 0:成功,-1:失败
*/
static int bc26_ue_down(void)
{
	 bc26_wake();//唤醒
	 delay_ms(10);
	 if(at_send_cmd(CFUN0,"OK"))
	 {
		 UsartPrintf(USART_DEBUG, "UE功能关闭\r\n");
		 return -1;
	 }
	 tcp_connect_status = TCP_CLOSED; //tcp断开
	 UsartPrintf(USART_DEBUG, "UE功能关闭失败\r\n");
	 return 0;
}

/**
* @Title TCP连接
* @Param ip:地址, port:端口
*/
static void bc26_tcp_connect(const char *ip, const char *port)
{
	 char conCmd[200]={0};
	 bc26_wake();//唤醒
	 UsartPrintf(USART_DEBUG, "连接TCP服务器\r\n");
	 snprintf(conCmd,sizeof(conCmd),QIOPEN,ip,port);
	 at_send_simple_cmd(conCmd);
	 tcp_connect_status = TCP_CONNECTING;
}

/**
* @Title 链接自定义
* @Param ip:地址, port:端口
*/
static void bc26_channel_open(const char *ip, const char *port,uint8_t proto, uint8_t channel)
{
	 char conCmd[200]={0};
	 if(channel<MIN_CHANNEL_NUM) return;
	 bc26_wake();//唤醒
	 UsartPrintf(USART_DEBUG, "连接服务器channel:%d\r\n",channel);
	 if(proto == UDP)
	 {
		 snprintf(conCmd,sizeof(conCmd),QIOPENOPT,channel,"UDP",ip,port);
	 }
	 else if(proto == TCP)
	 {
		 snprintf(conCmd,sizeof(conCmd),QIOPENOPT,channel,"TCP",ip,port);
	 }
	 at_send_simple_cmd(conCmd);
	 module_channel[channel].proto = proto;
	 module_channel[channel].connect_status = TCP_CONNECTING;
	 if(channel == 0)
	 {
		 tcp_connect_status = TCP_CONNECTING;
	 }
}

/**
* @Title 打开UDP端口
* @Param ip:地址, port:端口
*/
static void bc26_udp_open(const char *ip, const char *port)
{
	 char conCmd[200]={0};
	// bc26_wake();//唤醒
	 snprintf(conCmd,sizeof(conCmd),QIOPENUDP,ip,port);
	 UsartPrintf(USART_DEBUG, "连接UDP服务器\r\n");
	 at_send_simple_cmd(conCmd);
	 tcp_connect_status = TCP_CONNECTING;
}



/**
* @Title TCP通道关闭
* @Return 0:成功,-1:失败
*/
static int bc26_tcp_close(void)
{
	 bc26_wake();//唤醒
	 delay_ms(10);
	 //UsartPrintf(USART_DEBUG, "断开TCP操作：%s\r\n",QICLOSE);
	 if(at_send_cmd(QICLOSE,"CLOSE OK"))
	 {
		 return -1;
	 }
	 tcp_connect_status = TCP_CLOSED; //tcp断开
	 UsartPrintf(USART_DEBUG, "断开TCP服务器\r\n");
	 return 0;
}

/**
* @Title TCP通道关闭
* @Return 0:成功,-1:失败
*/
static int bc26_channel_close(uint8_t channel)
{
 	 char conCmd[20]={0};
	 snprintf(conCmd,sizeof(conCmd),QICLOSECH,channel);
	 bc26_wake();//唤醒
	 delay_ms(10);
	 //UsartPrintf(USART_DEBUG, "断开TCP操作：%s\r\n",QICLOSE);
	 if(at_send_cmd(conCmd,"CLOSE OK"))
	 {
		 return -1;
	 }
	 module_channel[channel].connect_status = TCP_CLOSED; //tcp断开
	 UsartPrintf(USART_DEBUG, "断开服务器:%d\r\n",channel);
	 return 0;
}

/**
* @Title 判断tcp连接状态
* @Return 0 保持连接,-1 断开连接
*/
static int bc26_tcp_state(void)
{
	 char *statebuf[8] ={0};
	 char recvbuf[200] = {0};
	 bc26_wake();
	 delay_ms(15);
	 at_send_cmd_back(QISTATE,recvbuf,sizeof(recvbuf));
	 if(strstr(recvbuf,"OK"))
	 {
		 if(strstr((char *)recvbuf,"+QISTATE: 0"))
		 {
			 split((char*)recvbuf,",",statebuf,sizeof(statebuf));
			 if(statebuf[5])
			 {
				 if(*(statebuf[5]) == '2')
				 {
					 tcp_connect_status = TCP_OPEN; //tcp连接
					 UsartPrintf(USART_DEBUG, "TCP服务器保持链接\r\n");
					 return 0;
				 }
					 
			 }
		 }
	 }
	 tcp_connect_status = TCP_CLOSED; //tcp断开
	 UsartPrintf(USART_DEBUG, "TCP服务器已断开\r\n");
	 return -1;
	 
}

/**
* @Title 判断通道链接状态
* @Return 0 保持连接,-1 断开连接
*/
static int bc26_channel_state(uint8_t channel)
{
	 char *statebuf[8] ={0};
	 char recvbuf[200] = {0};
	 char conCmd[20]={0};
	 char signbuf[20]={0};
	 bc26_wake();
	 delay_ms(15);
	 snprintf(conCmd,sizeof(conCmd),QISTATECH,channel);
	 at_send_cmd_back(conCmd,recvbuf,sizeof(recvbuf));
	 if(strstr(recvbuf,"OK"))
	 {
		 if(strstr((char *)recvbuf,"+QISTATE: "))
		 {
			 split((char*)recvbuf,",",statebuf,sizeof(statebuf));
			 if(statebuf[5])
			 {
				 if(*(statebuf[5]) == '2')
				 {
					 module_channel[channel].connect_status = TCP_OPEN; //tcp连接
					 UsartPrintf(USART_DEBUG, "通道服务器保持链接:%d\r\n",channel);
					 return 0;
				 }
					 
			 }
		 }
	 }
	 module_channel[channel].connect_status = TCP_CLOSED; //tcp断开
	 UsartPrintf(USART_DEBUG, "通道服务器已断开:%d\r\n",channel);
	 return -1;
	 
}

static void bc26_tcp_reconnect(const char *ip, const char *port)
{
	 bc26_wake();//唤醒
	 if(bc26_tcp_state())
	 {
		 UsartPrintf(USART_DEBUG, "重连服务器\r\n");
		 bc26_tcp_close();
		 bc26_tcp_connect(ip,port);
	 }
}

static void bc26_udp_reopen(const char *ip, const char *port)
{
	 bc26_wake();//唤醒
	 if(bc26_tcp_state())
	 {
		 UsartPrintf(USART_DEBUG, "重连服务器\r\n");
		 bc26_tcp_close();
		 bc26_udp_open(ip,port);
	 }
}

static void bc26_channel_reopen(const char *ip, const char *port,uint8_t proto, uint8_t channel)
{
	 bc26_wake();//唤醒
	 if(bc26_channel_state(channel))
	 {
		 UsartPrintf(USART_DEBUG, "重连服务器\r\n");
		 bc26_channel_close(channel);
		 bc26_channel_open(ip,port,proto,channel);
	 }
}


static void bc26_online_event(void)
{
	char *recvdiff[4] = {0};//分割字符串地址
	uint8_t ch = 0;
	uint16_t result = 0;
	UsartPrintf(USART_DEBUG, "bc26_online_event:%s\r\n",uart_recv.start_addr);
	splitCharLimit((char*)(uart_recv.start_addr+strlen(event->event_header)),',',recvdiff,2);
	ch = my_atoi(recvdiff[0]);
	result = my_atoi(recvdiff[1]);
	if(result == 0)
	{
		module_channel[ch].connect_status = TCP_OPEN;
		if(ch == 0)
		{
			tcp_connect_status = TCP_OPEN;// tcp在线
		}
	}
	
	
}


static void bc26_close_event(void)
{
	char *recvdiff[4] = {0};//分割字符串地址
	uint8_t ch = 0;
	UsartPrintf(USART_DEBUG, "bc26_close_event\r\n");
	splitCharLimit((char*)(uart_recv.start_addr+strlen(event->event_header)),',',recvdiff,2);
	ch = my_atoi(recvdiff[1]);
	module_channel[ch].connect_status = TCP_CLOSED;
	if(ch == 0)
	{
		tcp_connect_status = TCP_CLOSED; //tcp断线
	}
	
}


static void bc26_recv_event(void)
{
	int i;
	int minLen  = 0;
	char *recvdiff[4] = {0};//分割字符串地址
	char recvbuf[RECV_SIZE] = {0};
	int data_len = 0;//有效数据长度
	uint8_t ch = 0;
	int valid_data_size = sizeof(valid_data.buf);
	uart_recv_wait(150);//有效数据返回有延迟
	memcpy((char*)recvbuf,(char*)uart_recv.start_addr,uart_recv.len);
	splitCharLimit((char*)recvbuf,',',recvdiff,4);
	ch = my_atoi(recvdiff[1]);
	data_len = my_atoi(recvdiff[2]);
  minLen = data_len < valid_data_size-1? data_len : valid_data_size-1;
	if(ch == 0)
	{
		valid_data.len = minLen;
		memcpy(valid_data.buf,(char*)recvdiff[3]+1,minLen); //有效数据前后多了一个双引号
	}
	module_channel[ch].valid_data.len = minLen;
	memcpy(module_channel[ch].valid_data.buf,(char*)recvdiff[3]+1,minLen); //有效数据前后多了一个双引号
	UsartPrintf(USART_DEBUG, "bc26_recv_event\r\n");
	
}

void bc26_error_event(void)
{
	UsartPrintf(USART_DEBUG, "error_event:%s\r\n",uart_recv.buf);
	if(err_cout == 5) //连续出错5次UsartPrintf,重启模块
	{
		err_cout= 0;
		module_start_status = MODULE_FAIL;
		module_init_status = MODULE_FAIL;
	}
}

void bc26_sleep_event(void)
{
	UsartPrintf(USART_DEBUG, "ENTER DEEPSLEEP\r\n",uart_recv.buf);
	
}

static void bc26_restart_event(void)
{
	int i= sizeof(module_channel)/sizeof(module_channel[0]);
	UsartPrintf(USART_DEBUG, "bc26_restart_event:%s\r\n",uart_recv.buf);
	module_start_status = MODULE_OK; //bc260启动成功
	module_init_status = MODULE_FAIL; //重新配置参数
	tcp_connect_status = TCP_CLOSED;//TCP 需要重连
	while(i--)
	{
		module_channel[i].connect_status = TCP_CLOSED;
	}
	bc26_config();//配置
}

at_event_t bc26_at_event[] = {
		{ "+IP:", bc26_restart_event}, //tcp连接成功
    { "+QIOPEN: ", bc26_online_event}, //tcp连接成功
		{ "+QIURC: \"closed\"", bc26_close_event}, //tcp断开链接
		{ "+QIURC: \"recv\"", bc26_recv_event},
		{ "ERROR", bc26_error_event}, 
		{ "+QNBIOTEVENT: \"ENTER DEEPSLEEP\"", bc26_sleep_event}
};


static void bc26_handle_event(void)
{
	int i = 0;
	char *start_addr;
	if(uart_recv.len ==0) return;
	for(i=0;i<sizeof(bc26_at_event)/sizeof(bc26_at_event[0]);i++)
	{
		event =  &bc26_at_event[i];
		start_addr = strstr(uart_recv.buf, event->event_header);
		if(start_addr)
		{
			if(event->event_callback == bc26_error_event)
			{
				err_cout++;
			}
			else
			{
				err_cout=0;
			}
			uart_recv.start_addr = start_addr;
			event->event_callback();
			uart_recv_clear();
			break;
		}
		
	}
	
}



at_module_t at_module_bc26 = {
		.start              = bc26_restart,
    .init               = bc26_init,
    .connect            = bc26_tcp_connect,
	  .reconnect          = bc26_tcp_reconnect,
	  .udpreopen          = bc26_udp_reopen,
	  .channel_open       = bc26_channel_open,
	  .channel_reopen     = bc26_channel_reopen,
	  .tcpstate           = bc26_tcp_state,
	  .channel_state      = bc26_channel_state,
    .send               = bc26_send_data,
		.send_rai           = bc26_send_data_rai,
	  .send_ch            = bc26_send_data_ch,
    .recv_timeout       = bc26_get_data,
    .close              = bc26_tcp_close,
	  .channel_close      = bc26_channel_close,
	  .handle_event       = bc26_handle_event,
		.cmd_back           = at_send_cmd_back,
		.cmd                = at_send_simple_cmd,
		.low_power          = bc26_ue_down,
	  .udpopen            = bc26_udp_open,
};


int bc26_sal_init()
{
	if(at_module_register(&at_module_bc26))
	{
		module_init_status = MODULE_FAIL;
		return -1;
	}
	if(at_module_init())
	{
		module_init_status = MODULE_FAIL;
		return -1;
	}
	module_init_status = MODULE_OK;
	return 0;
}

void bc26_sal_register()
{
	at_module_register(&at_module_bc26);
}
