/**
* author wulianwei
* title ESP8266模块驱动
*/
#include "stm32f10x.h"
//网络设备驱动
#include "esp8266.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 uint8 tcp_connect_status;

extern valid_data_t valid_data;



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

	char cmdBuf[SEND_SIZE]={0};
	uart_recv_clear();								//清空接收缓存
	//esp8266_tcp_reconnect();
	snprintf(cmdBuf,SEND_SIZE,"AT+CIPSEND=%d\r\n", len);		//发送命令
	if(!at_send_cmd(cmdBuf, ">"))				//收到‘SEND OK’时可以发送数据
	{
		// Usart_SendString(USART2, data, len);		//发送设备连接请求数据
		 
		 if(!at_send_byte((char*)data,len,"SEND OK"))
		 {
			 return 0;
		 } 
		 
	}
	return -1;
}



//==========================================================
//	函数名称：	esp8266_get_data
//
//	函数功能：	获取平台返回的数据
//
//	入口参数：	data:存储有效数据(数组),len:有效数据长度,timeOut:等待的时间(ms)
//
//	返回参数：	平台返回的原始数据
//
//	说明：		不同网络设备返回的格式不同，需要去调试
//==========================================================
static int esp8266_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 = "+IPD";

	if(!uart_recv_match_wait(recvSign,timeOut))
	{
		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[1]);
	  minLen = data_len < len? data_len : len;
		memcpy(data,(char*)recvdiff[2],minLen); 
		uart_recv_clear();
	  return data_len;
	}
	uart_recv_clear();
	return -1;
}

//==========================================================
//	函数名称：	esp8266_init
//
//	函数功能：	初始化esp8266
//
//	入口参数：	无
//
//	返回参数：	0 成功 -1失败
//
//	说明：		
//==========================================================
static int esp8266_init(void)
{
	char recv[300];
	GPIO_InitTypeDef GPIO_Initure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

	//ESP8266复位引脚
	GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Initure.GPIO_Pin = GPIO_Pin_7;					//GPIOA0-复位
	GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_Initure);
	
	GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_RESET);
	delay_ms(250);
	GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_SET);
	
	
	UsartPrintf(USART_DEBUG, "1.AT\r\n");
	at_send_cmd_back(AT,recv,sizeof(recv));
	UsartPrintf(USART_DEBUG, "%s\r\n",recv);
	
	UsartPrintf(USART_DEBUG, "2.RESTORE\r\n");
	at_send_cmd_back_wait(RESTORE,recv,sizeof(recv),1000);
	UsartPrintf(USART_DEBUG, "%s\r\n",recv);
	
	
	UsartPrintf(USART_DEBUG, "3.CWMODE\r\n");
	at_send_cmd_back_wait(CWMODE,recv,sizeof(recv),500);
	UsartPrintf(USART_DEBUG, "%s\r\n",recv);
	
	
	
	UsartPrintf(USART_DEBUG, "4.禁止回显\r\n");
	at_send_cmd_back(ATE0,recv,sizeof(recv));
	UsartPrintf(USART_DEBUG, "%s\r\n",recv);
	if(!strstr(recv,"OK"))
	{
		UsartPrintf(USART_DEBUG,"禁止回显失败\r\n");
		return -1;
	}
	
	
	UsartPrintf(USART_DEBUG, "5.禁止休眠\r\n");
	at_send_cmd_back(NSLEEP,recv,sizeof(recv));
	UsartPrintf(USART_DEBUG, "%s\r\n",recv);
	
	UsartPrintf(USART_DEBUG, "6.连接WiFi\r\n");
	at_send_cmd_back_wait(CWJAP,recv,sizeof(recv),6000);
	UsartPrintf(USART_DEBUG, "%s\r\n",recv);
	if(!strstr(recv,"WIFI GOT IP"))
	{
		UsartPrintf(USART_DEBUG,"连接WiFi失败\r\n");
		return -1;
	}
	
	UsartPrintf(USART_DEBUG, "\r\n ESP8266 初始化完成\r\n");
	return 0;
}


/**
* @Title TCP连接
* @Param ip:地址, port:端口
* @Return 0:成功,-1:失败
*/
static void esp8266_tcp_connect(const char *ip, const char *port)
{
	 char conCmd[200]={0};
	 UsartPrintf(USART_DEBUG, "连接TCP服务器\r\n");
	 snprintf(conCmd,sizeof(conCmd),CIPSTART,ip,port);
	 at_send_simple_cmd(conCmd);
	 tcp_connect_status = TCP_CONNECTING;
}

/**
* @Title TCP通道关闭
* @Return 0:成功,-1:失败
*/
static int esp8266_tcp_close(void)
{
	 
	 if(at_send_cmd(CIPCLOSE,"CLOSED"))
	 {
		 return -1;
	 }
	 tcp_connect_status = TCP_CLOSED; //tcp断开
	 UsartPrintf(USART_DEBUG, "断开TCP服务器\r\n");
	 return 0;
}

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



static void esp8266_tcp_reconnect(const char *ip, const char *port)
{
	 
	 if(esp8266_tcp_state())
	 {
		 UsartPrintf(USART_DEBUG, "重连服务器\r\n");
		 esp8266_tcp_close();
		 esp8266_tcp_connect(ip,port);
	 }
}

static void esp8266_tcp_online_event(void)
{
	UsartPrintf(USART_DEBUG, "esp8266_tcp_online_event\r\n");
	tcp_connect_status = TCP_OPEN;// tcp在线
}

static void esp8266_tcp_close_event(void)
{
	UsartPrintf(USART_DEBUG, "esp8266_tcp_close_event\r\n");
	tcp_connect_status = TCP_CLOSED; //tcp断线
}

static void esp8266_wifi_reconnect_event(void)
{
	UsartPrintf(USART_DEBUG, "esp8266_wifi_reconnect_event\r\n");
	tcp_connect_status = TCP_CLOSED; //tcp断线
}

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

void esp8266_busy_event(void)
{
	UsartPrintf(USART_DEBUG, "esp8266_busy_event:%s\r\n",uart_recv.buf);
}

void esp8266_error_event(void)
{
	UsartPrintf(USART_DEBUG, "error_event:%s\r\n",uart_recv.buf);
}

at_event_t esp8266_at_event[] = {
		{ "WIFI GOT IP", esp8266_wifi_reconnect_event},//wifi重连
	  { "CONNECT\r\n\r\nOK", esp8266_tcp_online_event}, //tcp连接成功
		{ "ALREADY CONNECTED", esp8266_tcp_online_event}, //tcp连接成功
		//{ "CLOSED", esp8266_tcp_close_event}, //tcp断开
		{ "+IPD,", esp8266_recv_event},
		{ "busy,", esp8266_busy_event},
		{ "ERROR", esp8266_error_event}
};

static void esp8266_handle_event(void)
{
	int i = 0;
	char *start_addr;
	if(uart_recv.len ==0) return;
	//UsartPrintf(USART_DEBUG, "uart_recv buff:%s\r\n",uart_recv.buf);
	for(i=0;i<sizeof(esp8266_at_event)/sizeof(esp8266_at_event[0]);i++)
	{
		at_event_t* event =  &esp8266_at_event[i];
		start_addr = strstr(uart_recv.buf, event->event_header);
		if(start_addr)
		{
			uart_recv.start_addr = start_addr;
			event->event_callback();
			uart_recv_clear();
			break;
		}
		
	}
	
}

at_module_t at_module_esp8266 = {
    .init               = esp8266_init,
    .connect            = esp8266_tcp_connect,
	  .reconnect          = esp8266_tcp_reconnect,
	  .tcpstate           = esp8266_tcp_state,
    .send               = esp8266_send_data,
    .recv_timeout       = esp8266_get_data,
    .close              = esp8266_tcp_close,
	  .handle_event       = esp8266_handle_event,
		.handle_event       = esp8266_handle_event,
};


int esp8266_sal_init()
{
	if(at_module_register(&at_module_esp8266))
	{
		return -1;
	}
	if(at_module_init())
	{
		return -1;
	}
	return 0;
}


