#include "connect.h"
#include "esp8266.h"
#include "pro_phy.h"
#include "timer.h"
#include "usart.h"
#include "pro_memory.h"
#include "led.h"
#include "bsp.h"

ESP8266_obj esp8266;
Store_obj Store_Data;
static msg_obj msg[MAX_NODE_NUM];

char post_buff[PAYLOAD_DATA_LEN]={0};
static char ser_data[512]={0};
static char cmd_buf[256]={0};

static const char html_head[]="<html><head><title>Config</title></head><body  style=\"font-size:20px\">";
static const char html_set1[]="<a href=\"/set_apiKey\"><input type=\"button\" style=\"font-size:75px\" value=\"Set ApiKey\"></a><br><br>";
static const char html_set2[]="<a href=\"/set_server\"><input type=\"button\" style=\"font-size:75px\" value=\"Set Server\"></a><br><br>";
static const char html_set3[]="<a href=\"/set_ssid\"><input type=\"button\" style=\"font-size:75px\" value=\"Set Router\"></a><br><br>";
static const char html_exit[]="<a href=\"/exit\"><input type=\"button\" style=\"font-size:75px\" value=\"Exit\"></a><br>";
static const char html_login[]="<form method=\"POST\"><div style=\"font-size:75px\">username<input type=\"username\" name=\"user\" style=\"font-size:75px\"><br>password<input type=\"password\" name=\"pwd\" style=\"font-size:75px\"><br><button type=\"submit\"  style=\"font-size:75px\">ok</button></div></form>";
static const char html_set_apiKey[]="<form method=\"POST\"><div style=\"font-size:75px\">apiKey<input type=\"username\" name=\"new_apiKey\" style=\"font-size:75px\"><br><button type=\"submit\" style=\"font-size:75px\">ok</button></div></form>";
static const char html_set_server[]="<form method=\"POST\"><div style=\"font-size:75px\">server<input type=\"username\" name=\"new_server\" style=\"font-size:75px\"><br><button type=\"submit\" style=\"font-size:75px\">ok</button></div></form>";
static const char html_end[]="</body></html>";

void Connect_Init(void)
{
	HTTP_LED=1;
	ESP_Init();
	MemSet((BYTE *)&esp8266,0,sizeof(ESP8266_obj));
	MemSet((BYTE *)&Store_Data,0,sizeof(Store_obj));
	MemSet((BYTE *)&msg,0,sizeof(msg_obj)*MAX_NODE_NUM);
	esp8266.state=WAIT_LOGIN;
	if(NRF_IsHaveStoreData(PRO_STORE_FLAG,PRO_STORE_FLASH_ADDRESS))
	{
		NRF_ReadDataFromStore(PRO_STORE_FLAG,PRO_STORE_FLASH_ADDRESS,(u8 *)&Store_Data,sizeof(Store_obj));
	}
	esp8266.state=WAIT_LOGIN;
	esp8266.mode=ESP_CLIENT;//
	ESP_PowerOn();//ESP8266模块上电
	ESP_HardReset();
	esp8266.port=8080;
	HTTP_LED=0;
}

void Msg_Get(u8 *node,u8 *val,u8 *type)
{
	u8 i;

	*node=msg[0].addr;//获取消息
	*val=msg[0].data;
	*type=msg[0].type;
	for(i=1;i<MAX_NODE_NUM;i++)//消息右移
	{
		msg[i-1].addr=msg[i].addr;
		msg[i-1].data=msg[i].data;
		msg[i-1].type=msg[i].type;
	}
}

u8 Msg_Put(u8 node,u8 val,u8 type)
{
	u8 k=0;
	
	if(node)//有效地址
	{
		for(k=0; k<MAX_NODE_NUM; k++)//遍历
		{
			if(msg[k].addr==node)//有地址,更新
			{
				msg[k].addr=node;
				msg[k].data=val;
				msg[k].type=type;
				return 1;
			}
		}
		for(k=0; k<MAX_NODE_NUM; k++)//没有地址
		{
			if(!msg[k].addr)
			{
				msg[k].addr=node;
				msg[k].data=val;
				msg[k].type=type;
				return 1;
			}
		}
	}
	return 0;
}

void ESP_SensorUpdate(u8 addr,u8 val,u8 type)
{
	Msg_Put(addr,val,type);
	esp8266.sensor=TRUE;
}

u8 ESP_LinkServer(char *ser,u16 port)
{
	u8 link_cnt=2;

	while(link_cnt)//连接失败重连，重连失败退出
	{
		Idle();
		if(ESP_StartMux(TCP,ser,port,300))//建立tcp链接//3秒超时
		{
			return TRUE;
		}
		Delay10Ms(30);//300毫秒
		link_cnt--;
	}
	return FALSE;
}

u8 ESP_CloseLink(void)
{
	if(esp8266.link)
	{
		ESP_SendString((char*)"AT+CIPCLOSE\r\n");
		esp8266.link=FALSE;
		esp8266.bind=FALSE;
		esp8266.state=LINK;
		return TRUE;
	}
	return FALSE;
}

u8 ESP_SendCmd(u8 sid,u8 nid,u8 data,u8 *p,u8 flag)
{
	char tmpBuf[10]={0};
	
	sprintf(tmpBuf,"%s ok",p);
	Delay10Ms(10);//100毫秒
	if(!flag)
	{
		sprintf(cmd_buf,"mode=%s&apikey=%s&data={ck%03d%03d%s}",p,Store_Data.apiKey,sid,nid,p);
	}
	else
	{
		sprintf(cmd_buf,"mode=%s&apikey=%s&data={ck%03d%03d%01d%s}",p,Store_Data.apiKey,sid,nid,data,p);
	}
	if(ESP_SendTcpUdp(cmd_buf,1500))//15秒超时
	{
		u32 start=Get_RunTime();

		while(Get_RunTime()-start<200)
		{
			Idle();
			if(USART2_Recv_Flag||ESP_GetSendDataFlag())//esp8266接收处理
			{
				USART2_Recv_Flag=0;
				ESP_SetSendDataFlag(FALSE);
				esp8266.ishttpget=1;
				HTTP_LED=0;//指示灯
				printf("\r\n\r\n<<< reply %d ms\r\n",(Get_RunTime()-esp8266.timer)*10);//打印时间
				//printf("%s\r\n",USART2_Recv_Buff);
				if(strstr(USART2_Recv_Buff,tmpBuf))
				{
					return TRUE;
				}
				else
				{
					return FALSE;
				}
			}
		}
		return FALSE;
	} 
	else
	{
		return FALSE;
	}
}

void ESP_Connect(void)
{
	u32 main_time=Get_RunTime();

	switch(esp8266.state)
	{	
		case WAIT_LOGIN:
			Delay10Ms(30);//300毫秒
			if(ESP_JoinAP((char *)Store_Data.ssid,(char *)Store_Data.pwd,2000))//登陆路由器:20秒超时
			{
				esp8266.login=TRUE;
				printf("\r\nJoin AP ok\r\n");
				Delay10Ms(100);//1秒
				esp8266.state=LINK;
			}
			else
			{
				esp8266.login=FALSE;
				printf("\r\nJoin AP fail\r\n");
				esp8266.state=SERVER;
				esp8266.ser_time=Get_RunTime();
				SetLed(0xff,50,50);
			}
			break;
		case LINK:
			if(!esp8266.link)
			{
				if(ESP_LinkServer((char *)Store_Data.server,esp8266.port))
				{
					esp8266.link=TRUE;
					SetLed(1,10,50);
					Delay10Ms(10);//100毫秒
				}
				else
				{
					esp8266.state=SERVER;
					esp8266.ser_time=Get_RunTime();
					SetLed(0xff,100,100);
				}
			}
			else//连接ok
			{
				if(!esp8266.bind)
				{
					if(ESP_SendCmd(1,0,0,(u8 *)"bind",FALSE))//绑定ok
					{
						esp8266.bind=TRUE;
						esp8266.state=LIVE;
						esp8266.last_http=Get_RunTime()-LIVE_INTERVAL+100; 
						esp8266.ishttpget=1;
						SetLed(0xff,10,500);
					}
					else
					{
						if(ESP_SendCmd(1,0,0,(u8 *)"del",FALSE))
						{
							Delay10Ms(30);//300毫秒
						}
						else
						{
							ESP_CloseLink();
							Delay10Ms(30);//300毫秒
						}
					}
				}
				else
				{
					esp8266.state=LIVE;
					SetLed(0xff,10,500);
				}
			}
			break;
		case LIVE:
			if(main_time-esp8266.last_http>LIVE_INTERVAL)//间隔60秒,esp8266发送心跳包到服务器
			{
				static u8 nCnt=0;
				
				esp8266.last_http=main_time;
				if(esp8266.ishttpget)
				{
					esp8266.ishttpget=0;
					esp8266.timer=main_time;
					HTTP_LED=1;//指示灯
					printf("\r\n>>> REQ\r\n");
					if(ESP_SendCmd(1,0,0,(u8 *)"live",FALSE))
					{
						nCnt=0;
					}
					else
					{
						nCnt++;
					}
				}
				else
				{
					nCnt++;
				}
				if(nCnt>=2)
				{
					nCnt=0;
					ESP_CloseLink();
				}
			}
			if(esp8266.sensor)
			{
				esp8266.sensor=FALSE;
				esp8266.state=SENSOR_UPDATE;
			}
			break;
		case SENSOR_UPDATE://更新
			if(esp8266.ishttpget||main_time-esp8266.last_http>500)//间隔5秒
			{
				static u8 addr=0,data=0,type=0;
				
				esp8266.last_http=main_time;
				if(esp8266.ishttpget)
				{
					Msg_Get(&addr,&data,&type);
				}
				else
				{
					addr=0;
				}
				if(addr)
				{
					HTTP_LED=1;//指示灯
					esp8266.ishttpget=0;
					esp8266.timer=main_time;
					printf("\r\n>>> SENSOR_UPDATE\r\n");
					switch(type)
					{
						case UPDATE:
							if(!ESP_SendCmd(addr/10,Get_Nid(addr),data,(u8 *)"update",TRUE))
								ESP_CloseLink();
							break;
						case UPLOAD:
							if(!ESP_SendCmd(addr/10,Get_Nid(addr),data,(u8 *)"upload",TRUE))
								ESP_CloseLink();
							break;
						default: break;
					}
				}
				else 
				{
					esp8266.sensor=FALSE;
					esp8266.state=LIVE;
					SetLed(0xff,10,500);
				}
			}
			break;
		case SERVER: 
			if(esp8266.mode==ESP_CLIENT)
			{
				if(ESP_StartServer(esp8266.port))
				{
					esp8266.login=FALSE;
					esp8266.link=FALSE;
					esp8266.bind=FALSE;
					esp8266.mode=ESP_SERVER;
				}
			}
			if(esp8266.mode==ESP_SERVER)
			{
				if(main_time-esp8266.ser_time>=6000)//间隔3分钟18000
				{
					if(ESP_CloseServer())
					{
						esp8266.mode=ESP_CLIENT;
						if(!esp8266.login)
							esp8266.state=WAIT_LOGIN;
						else if(!esp8266.link||!esp8266.bind)
							esp8266.state=LINK;
						else
						{
							esp8266.state=LIVE;
							SetLed(0xff,10,500);
						}
					}
					else
					{
						esp8266.ser_time=main_time;
					}
				}
			}
			break;
		default:
			esp8266.state=WAIT_LOGIN;
			break;
	}
}

void ESP_RecvData(void)
{
	if(USART2_Recv_Flag)//esp8266接收处理
	{
		USART2_Recv_Flag=0;
		USART1_DMA_SendStr(USART2_Recv_Buff);//串口1DMA发送程序
		if(strstr(USART2_Recv_Buff,"WIFI DISCONNECT"))
		{
			esp8266.login=FALSE;
			esp8266.link=FALSE;
			esp8266.bind=FALSE;
		}
		if(strstr(USART2_Recv_Buff,"CLOSED"))//服务器断开连接
		{
			esp8266.link=FALSE;
			esp8266.bind=FALSE;
			esp8266.state=LINK;
		}
		if(strstr(USART2_Recv_Buff,"IPD"))//+IPD接收到网络数据
		{
			switch(esp8266.mode)
			{	
				case ESP_SERVER:
					esp8266.ser_time=Get_RunTime();
					ESP_HandleServerPackage();//处理Server包
					break;
				case ESP_CLIENT:
					ESP_HandleClientPackage();//处理Client包
					break;
				default:
					break;
			}
		}
	}
}

//单路连接时(+CIPMUX=0)+IPD,<len>:<data>
//多路连接时(+CIPMUX=1)+IPD,<id>,<len>:<data>
void ESP_HandleServerPackage()//处理Server包
{
	char* position=NULL;
	u8 ch_id,rec_len;

	position=strstr(USART2_Recv_Buff,"+IPD");
	ch_id=GetValue(position,",");//获取多路连接的ID
	printf("\r\n\r\nconnect_id=%d\r\n",ch_id);
	if(strstr(USART2_Recv_Buff,"GET / HTTP/1.1")||strstr(USART2_Recv_Buff,"GET /favicon.ico HTTP/1.1"))//检测关键字
	{
		sprintf(ser_data,"%s%s%s%s%s%s",html_head,html_set1,html_set2,html_set3,html_exit,html_end);
		ESP_SendTcpMux(ch_id,ser_data,800);//多路连接时(+CIPMUX=1)发送TCP数据包
	}
	if(strstr(USART2_Recv_Buff,"GET /set_apiKey HTTP/1.1"))//
	{
		sprintf(ser_data,"%s%s%s",html_head,html_set_apiKey,html_end);
		ESP_SendTcpMux(ch_id,ser_data,800);
	}
	if(strstr(USART2_Recv_Buff,"GET /set_server HTTP/1.1"))
	{
		sprintf(ser_data,"%s%s%s",html_head,html_set_server,html_end);
		ESP_SendTcpMux(ch_id,ser_data,800);
	}
	if(strstr(USART2_Recv_Buff,"GET /set_ssid HTTP/1.1"))
	{
		sprintf(ser_data,"%s%s%s",html_head,html_login,html_end);
		ESP_SendTcpMux(ch_id,ser_data,800);
	}
	if(strstr(USART2_Recv_Buff,"POST /set_apiKey HTTP/1.1"))
	{
		position=strstr(USART2_Recv_Buff,"apiKey=");//查找
		if(position!=0)
		{
			rec_len=GetDataLength(position+7,"\0");
			if(rec_len==16)
			{
				MemSet((BYTE *)&Store_Data.apiKey,0,sizeof(Store_Data.apiKey));
				memcpy(Store_Data.apiKey,position+7,rec_len);//从第7个开始复制
				Store_Data.apiKey[rec_len]='\0';
				NRF_WriteDataToStore(PRO_STORE_FLAG,PRO_STORE_FLASH_ADDRESS,(u8 *)&Store_Data,sizeof(Store_obj));
			}	
			printf("\r\napiKey=%s; rec_len=%d\r\n",Store_Data.apiKey,rec_len);
			sprintf(ser_data,"%s%s%s%s%s%s",html_head,html_set1,html_set2,html_set3,html_exit,html_end);
			ESP_SendTcpMux(ch_id,ser_data,800);
		}
	}
	if(strstr(USART2_Recv_Buff,"POST /set_server HTTP/1.1"))
	{
		position=strstr(USART2_Recv_Buff,"server=");//查找
		if(position!=0)
		{
			rec_len=GetDataLength(position+7,"\0");
			if(rec_len!=0&&rec_len<sizeof(Store_Data.server))
			{
				MemSet((BYTE *)&Store_Data.server,0,sizeof(Store_Data.server));
				memcpy(Store_Data.server,position+7,rec_len);//从第7个开始复制
				Store_Data.server[rec_len]='\0';
				NRF_WriteDataToStore(PRO_STORE_FLAG,PRO_STORE_FLASH_ADDRESS,(u8 *)&Store_Data,sizeof(Store_obj));
			}
			printf("\r\nserver=%s; rec_len=%d\r\n",Store_Data.server,rec_len);
			sprintf(ser_data,"%s%s%s%s%s%s",html_head,html_set1,html_set2,html_set3,html_exit,html_end);
			ESP_SendTcpMux(ch_id,ser_data,800);
		}
	}
	if(strstr(USART2_Recv_Buff,"POST /set_ssid HTTP/1.1"))
	{
		position=strstr(USART2_Recv_Buff,"user=");//查找用户名
		if(position!=0)
		{
			rec_len=GetDataLength(position+5,"&");
			if(rec_len!=0&&rec_len<sizeof(Store_Data.ssid))
			{
				MemSet((BYTE *)&Store_Data.ssid,0,sizeof(Store_Data.ssid));
				memcpy(Store_Data.ssid,position+5,rec_len);//从第5个开始复制
				Store_Data.ssid[rec_len]='\0';
				NRF_WriteDataToStore(PRO_STORE_FLAG,PRO_STORE_FLASH_ADDRESS,(u8 *)&Store_Data,sizeof(Store_obj));
			}	
			printf("\r\nssid=%s; rec_len=%d\r\n",Store_Data.ssid,rec_len);
		}
		position=strstr(USART2_Recv_Buff,"pwd=");//查找密码
		if(position!=0)
		{
			rec_len=GetDataLength(position+4,"\0");
			if(rec_len>7&&rec_len<sizeof(Store_Data.pwd))
			{
				MemSet((BYTE *)&Store_Data.pwd,0,sizeof(Store_Data.pwd));
				memcpy(Store_Data.pwd,position+4,rec_len);//从第4个开始复制密码
				Store_Data.pwd[rec_len]='\0';
				NRF_WriteDataToStore(PRO_STORE_FLAG,PRO_STORE_FLASH_ADDRESS,(u8 *)&Store_Data,sizeof(Store_obj));
			}	
			printf("\r\npwd=%s; rec_len=%d\r\n",Store_Data.pwd,rec_len);
		}
		sprintf(ser_data,"%s%s%s%s%s%s",html_head,html_set1,html_set2,html_set3,html_exit,html_end);
		ESP_SendTcpMux(ch_id,ser_data,800);
	}
	if(strstr(USART2_Recv_Buff,"GET /exit HTTP/1.1"))
	{
		if(ESP_CloseServer())
		{
			esp8266.mode=ESP_CLIENT;
			esp8266.state=WAIT_LOGIN;
		}
	}
}

void ESP_HandleClientPackage()//处理Client包
{
	char body[PAYLOAD_DATA_LEN]={0};
	u8 sid,nid,addr;

	if(strstr(USART2_Recv_Buff,(char *)Store_Data.apiKey))//检测关键字
	{
		printf("\r\n\r\n<<< reply %d ms\r\n",(Get_RunTime()-esp8266.timer)*10);//打印时间
		esp8266.ishttpget=1;//收到数据标记
		HTTP_LED=0;//指示灯关闭
		GetBody(body,USART2_Recv_Buff);//获取只是{xxxxxxxx}的字符
		sid=GetNumber(body,3,3);//获取sid
		nid=GetNumber(body,6,3);//获取nid
		if(sid>2&&nid<10)
		{
			addr=sid*10+nid;//获取地址
			if(0xFF!=NRF_HeartTableFindValidNode(addr))
			{
				NRF_SendData(addr,ONE_DATA,(u8 *)body,NRF_SendCallBack);
			}
			else
			{
				u8 path[MAX_HOP_NUM]={0};

				NRF_SendData(addr,ASSIGN_ADDR,path,NRF_SendCallBack);//发送数据接口
			}
		}
	}
}
