/*
 * @Author       : ChenJie
 * @Date         : 2022-02-10 11:43:56
 * @Version      : V3.0
 * @LastEditors  : ChenJie
 * @LastEditTime : 2022-02-14 15:50:00
 * @Description  : file content
 * @FilePath     : \S32K146_4G\src\AppTaskUart1.c
 */
/*
 * AppTaskUart1.c
 *  wifi的串口函数
 *  Created on: 2022年5月11日
 *      Author: cw
 */
#include "stdio.h"
#include "AppTaskUart1.h"
/***************************************************
* esp8266使用的串口1
* esp8266默认TCP默认断开时间为180s

* 主机配置
* ESP8266作服务器时，IP固定为192.168.4.1
* AT+CWMODE=2 								//设置模块 WIFI 模式为 AP 模式
* AT+CWSAP_DEF=”my_test1”,”12345678”,1,4 		//设置模块的 AP 参数：SSID 为my_test1，密码为12345678，通道号为 1，加密方式为：WPA_WPA2_PSK
* AT+CIPMUX=1 								//开启多连接
* AT+CIPSERVER=1,8086 						//开启 SERVER 模式，设置端口为 8086
* AT+CIPSEND=0,25 							//向 ID0 发送 25 字节数据包

* 从机配置
* AT+CWMODE=1 								//设置模块 WIFI 模式为 STA 模式
* AT+CWJAP_DEF="my_test1","12345678" 			//加入 WIFI 热点
* AT+CIPMUX=0 								//开启单连接
* AT+CIPSTART="TCP","192.168.4.1",8086		//建立 TCP 连接到” 192.168.4.1”,8086
* AT+CIPMODE=1 								//开启透传模式
* AT+CIPSEND 									//开始传输
****************************************************/
typedef sint8 (*pFunc)(char *PSendStr, char *pReadStr, uint8 CmdIdx, uint16 pReadLen);

typedef struct
{
	ATCmd cmd; /*指令序号*/
    char *str; /*指令内容*/
    pFunc cb;  /*对应的执行*/
} ATCmdFunc_t;
static void wifi_init(uint8 Step);
static void AtcmdTransmit(sint8 CmdIdx, uint8 *SetValuePtr, uint16 SetValueLen, sint8 *retFunc);
static sint8 at_callbackFunc(char *PSendStr, char *pReadStr, uint8 CmdIdx, uint16 pReadLen);
static uint8 wifiDataDecode(uint8 *dataIn,uint16 dataLen);

sint8 tcpSendFunc(uint8 TcpConnectId, uint8 *SendDataPtr, uint16 SendDataLen);
volatile uint32 TimerCounter = 0; //ms单位
static sint8 TCP_ConnectEstablish(uint32 timeoutMs);
static sint8 WiFiDisconnec(void);
static void WiFiStaMan(void);
/* 获取x中第i个字节 */
#define  GET_LOW_BYTE(x,i)    ((x >>  i*8) & 0x000000FF)


const ATCmdFunc_t Atcmdfunc[] =
{
	{AT_CMD_TEST, "AT\r\n", at_callbackFunc},
	{ATE_0, "ATE0\r\n", at_callbackFunc},
	{AT_SET_MODE, "AT+CWMODE=1\r\n", at_callbackFunc},  /* 建立SoftAP 模式 */
	{AT_CWAUTOCONN, "AT+CWAUTOCONN=0\r\n", at_callbackFunc},  /* 建立Soft Station 模式 */
	{AT_CWJAP, "AT+CWJAP=", at_callbackFunc},  /* 连接WiFi */
	{AT_CIPSTART, "AT+CIPSTART=", at_callbackFunc},  /* 连接IP */
	{AT_CIPMODE, "AT+CIPMODE=1\r\n", at_callbackFunc},  /* 设置透传模式 */
	{AT_CIPSEND, "AT+CIPSEND\r\n", at_callbackFunc},  /* 开始发送数据 */
	{AT_SEND_DATA, "AT+CIPSEND=0,", at_callbackFunc},
	{AT_CIFSR, "AT+CIFSR\r\n", at_callbackFunc},        /* 查看IP信息 */
	{AT_CWQAP, "AT+CWQAP\r\n", at_callbackFunc},        /* 断开AP连接 */
	{AT_ISNOCON, "AT+CWJAP?\r\n", at_callbackFunc},  /* 连接WiFi */
};




void wifi_task(void *pvParameters)
{
	(void)pvParameters;
	uint16 ReadLen = 0;
	uint8 UartDataBuffer[512] = {0};
	//TimerHandle_t softTimer1 = xTimerCreate("softTimer1", 10, pdTRUE, (void *)0, vTimerCallback);

	/* 等待钥匙下电 */
	if(1 == KeySignal)
	{
		vTaskDelay(pdMS_TO_TICKS(10));
	}

    Dio_WriteChannel(DioConf_DioChannel_PTD16_GPIO_OUT_MCU_WIFI_POW_EN, STD_ON);//wifi开机
	vTaskDelay(pdMS_TO_TICKS(3000));//开机后等一段时间模块可能会返回开机后的指令 不做处理
	tcp_server_process_status = TCP_UNCONNECT;
	wifi_init(0);
	//TCP_ConnectEstablish(0);
	while(1)
	{

		WiFiStaMan();
		switch(tcp_server_process_status)
		{
			case TCP_CONNECT://可以正常进行数据交互
			{

				/*********主机收到上位机的指令,向WIFI从机发送数据*********/
				/*********************主机收到WIFI从机的数据****************/
				memset(UartDataBuffer, 0x00, sizeof(UartDataBuffer));
				UART_Receive_Data(UART_LPUART1,(uint8*)UartDataBuffer,(uint16*)&ReadLen,100);
				if(ReadLen>0)
				{
					if(strstr((char *)UartDataBuffer,(char *)("WIFI DISCONNECT")))/* WiFi断开 */
					{
						tcp_server_process_status = TCP_UNCONNECT;
						wifiAskFlg = false;
					}
					else if(strstr((char *)UartDataBuffer,(char *)("CLOSED")))  /* 网络链接断开 */
					{
						tcp_server_process_status = TCP_UNCONNECT;
						wifiAskFlg = false;
					}
					else if(strstr((char *)UartDataBuffer, (char *)("+IPD"))) //收到从机的数据
					{
						uint8 *retptr = NULL;
						uint16 TcpDataLen = 0;
						uint16 NumCalTemp = 1;
						retptr = (uint8 *)strstr((char *)UartDataBuffer, (char *)(":"));
						/* 获取接受数据长度 */
						for (uint8 i = 0; i < 3; i++)
						{
							if (*(retptr - i - 1) == ',')
							{
								break;
							}
							TcpDataLen = TcpDataLen + CharToHex(*(retptr - i - 1)) * NumCalTemp;
							NumCalTemp = NumCalTemp * 10;
						}
						/* 数据解码 */
						wifiDataDecode(retptr+1,TcpDataLen);
					}
					else
					{

					}
				}

				/* 解码部分 */
				if(ReadLen > 0)
				{
					wifiDataDecode(UartDataBuffer, ReadLen);
					vTaskDelay(pdMS_TO_TICKS(10));
				}
				/* 心跳报文发送 */
				static uint64 tickcount = 0;
				if(xTaskGetTickCount() - tickcount > pdMS_TO_TICKS(3000) && MAX_LOSTHEART >= heartTickLost_W)
				{
					tickcount = xTaskGetTickCount();
					uint16 dataOutLen = 0;
					uint8 dataOutBuffer[128] = {0};
					/* 组包 */
					dataOutLen = DecodeSlaveBuffer(dataOutBuffer, sizeof(dataOutBuffer),  HEARTBEAT_S);
					/* 数据发送 */
					tcpSendFunc(0,dataOutBuffer,dataOutLen);
					heartTickLost_W++; /* 心跳计数 */
				}
				/* 断开WiFi连接 */
				if(heartTickLost_W > MAX_LOSTHEART || 2 == WiFiConnectControl)
				{
					if(0 == WiFiDisconnec())
					{
						tickcount = 0;
						tcp_server_process_status = TCP_UNCONNECT;
						heartTickLost_W = 0;
					}
				}
				break;
			}
			case TCP_UNCONNECT:
			{
				break;
			}
			default:break;
		}
	}
}

/**************************解码部分***********************************/
static uint8 wifiDataDecode(uint8 *dataIn,uint16 dataLen)
{
	(void)dataLen;
	uint8 cmd = 0;
	cmd = dataIn[5];
	uint8 sendBuffer[255];
	uint16 dataOutLen = 0;
	uint16 frameLen = 0;
	static uint16 lockOrUnlockIng = 0; /* 目前等待解锁或者加锁反馈 0 无 LOCK_M 加锁 UNLOCK_M 解锁 */
	static uint32 awaitTick = 0;

	for(uint16 i = 0; i < dataLen - 23; i++)
	{
		if(0X68 == dataIn[i] && 0X23 == dataIn[i + 1] && 0X24 == dataIn[i + 2])
		{
			frameLen = dataIn[i + 3] + (dataIn[i + 4] << 8);
			if((i + frameLen <= dataLen) && 0X68 == dataIn[frameLen - 1])
			{
				cmd  = dataIn[i + 5];
				EffectiveDataFed = 1;
				break;
			}

			else
			{
				cmd = 0XFF;
			}

		}
	}

	switch(cmd)
	{
		case LOCK_M:
		{
			LockSta = 1;
			if(LOCK_M != lockOrUnlockIng)
			{
				lockOrUnlockIng = LOCK_S;
				awaitTick = xTaskGetTickCount();
			}
			break;
		}
		case UNLOCK_M:
		{
			UnlockSta = 1;
			if(UNLOCK_M != lockOrUnlockIng)
			{
				lockOrUnlockIng = UNLOCK_S;
				awaitTick = xTaskGetTickCount();
			}
			break;
		}
		case GETINFO_M:
		{
			dataOutLen = DecodeSlaveBuffer(sendBuffer, sizeof(sendBuffer), GETINFO_S);
			tcpSendFunc(0,sendBuffer,dataOutLen);
			break;
		}
		case HEARTBEAT_M:
		{
			/* 心跳响应 处理心跳返回包内的内容*/
			heartTickLost_W = 0;
		}
		default:
			break;
	}
	if((0 != lockOrUnlockIng) &&
			((xTaskGetTickCount() - awaitTick >= pdMS_TO_TICKS(20000)) ||
			((LOCK_S == lockOrUnlockIng && 0 == SolValActuSt) ||
			(UNLOCK_S == lockOrUnlockIng && 1 == SolValActuSt))))
	{
		dataOutLen = DecodeSlaveBuffer(sendBuffer, sizeof(sendBuffer), lockOrUnlockIng);
		tcpSendFunc(0,sendBuffer,dataOutLen);
		if(LOCK_S == lockOrUnlockIng)
			UnlockSta = 0;
		else if(UNLOCK_S == lockOrUnlockIng)
			LockSta = 0;
		else {}
		lockOrUnlockIng = 0; // 复位
	}
	else{}

	return 0;
}


sint8 tcpSendFunc(uint8 TcpConnectId, uint8 *SendDataPtr, uint16 SendDataLen)
{
	sint8 outValue = -1;
	(void)TcpConnectId;
#ifdef AT_CMD_SEND  /* 启用AT指令发送数据 */

	uint8  sendErrConuter= 0;
	uint16 ReadLen = 0;
	char AtCmdSend[30] = {0};
	uint8 AtCmdSendTotalLen = 0;
	uint8 UartRecvPtr[128] = {0};
	sint8 ret = -1;
#if WIFI_MASTER
	sprintf(AtCmdSend, "AT+CIPSEND=%d,%d\r\n", TcpConnectId, SendDataLen);
#elif WIFI_SLAVE
	sprintf(AtCmdSend, "AT+CIPSEND=%d\r\n", SendDataLen);
#endif
	AtCmdSendTotalLen = mstrlen(AtCmdSend);

		memset(UartRecvPtr, 0x00, sizeof(UartRecvPtr));
		UART_Send_Data(UART_LPUART1,(uint8 *)AtCmdSend,AtCmdSendTotalLen,100);
//		ret = UART_Query_Data(UART_LPUART1, UART_LPUART1, (uint8 *)AtCmdSend, AtCmdSendTotalLen, UartRecvPtr, &ReadLen, 1000);
		ret = AtcmdDelayRecvFunc(UART_LPUART1,(char *)(">"),3000);
		if (ret==0)
		{
			UART_Send_Data(UART_LPUART1, (uint8 *)SendDataPtr, SendDataLen, 100);
			ret = AtcmdDelayRecvFunc(UART_LPUART1, "SEND OK", 1000);
			outValue = ret;
		}
#else
	/* 透传 */
	outValue = UART_Send_Data(UART_LPUART1, (uint8 *)SendDataPtr, SendDataLen, 500);
#endif/* #ifdef AT_CMD_SEND  */
	return outValue;
}
/**********************************************************************************************/
/* CMD send and get ret */
#define WIFI_CMD_INIT(AT_CMD,INPUT_VALUE,INPUT_VALUE_LEN,INITSTEP,ATRET)\
	do{\
		AtcmdTransmit(AT_CMD, (uint8*)INPUT_VALUE, INPUT_VALUE_LEN, &ATRET);\
		if(0 == ATRET || 3 == ATRET)\
		{\
			INITSTEP++;\
		}\
		else\
		{\
			/* INITSTEP = 0; */\
		}\
	}while(0);
static void wifi_init(uint8 Step)
{
	//WIFI模块初始化
	uint8 InitStep = Step;
	sint8 ATRet = -1;
	while(1)
	{
		switch (InitStep)
		{
			case 0: // AT指令同步
			{
				WIFI_CMD_INIT(AT_CMD_TEST,NULL,0,InitStep,ATRet);
				break;
			}
			case 1:
			{
				//WIFI_CMD_INIT(ATE_0,NULL,0,InitStep,ATRet);
				InitStep++;
				break;
			}
			case 2: //设置工作模式
			{
				WIFI_CMD_INIT(AT_SET_MODE,NULL,0,InitStep,ATRet);
				break;
			}
			case 3:
			{
				WIFI_CMD_INIT(AT_CWAUTOCONN,NULL,0,InitStep,ATRet);
				break;
			}
			default:
			{
				return;
				break;
			}
		}
		vTaskDelay(pdMS_TO_TICKS(1));
	}
}


/***********************************************************************************************/
static void AtcmdTransmit(sint8 CmdIdx, uint8 *SetValuePtr, uint16 SetValueLen, sint8 *retFunc)
{
	/* 读取长度 */
	uint16 ReadLen = 0;
	uint8 UartRecvBuffer[256] = {0};
	uint8 *PtrATCmdSend = NULL;
	uint8 ATCmdFixedLen = 0;
	uint16 ATCmdTotalLen = 0;
	/* 获取指令长度 */
	ATCmdFixedLen = mstrlen(Atcmdfunc[CmdIdx].str);
	/*  */
	ATCmdTotalLen = ATCmdFixedLen + SetValueLen;

	/* 分配指令内存空间 */
	PtrATCmdSend = malloc(ATCmdTotalLen+1);
	memset(PtrATCmdSend, 0x00, ATCmdTotalLen+1);
	memcpy(PtrATCmdSend, Atcmdfunc[CmdIdx].str, ATCmdFixedLen);
	if (SetValuePtr != NULL)
	{
		memcpy(PtrATCmdSend + ATCmdFixedLen, SetValuePtr, SetValueLen);
	}
	memset(UartRecvBuffer, 0X00, sizeof(UartRecvBuffer));
	UART_Query_Data(UART_LPUART1, UART_LPUART1, PtrATCmdSend, ATCmdTotalLen, UartRecvBuffer, &ReadLen, 5000);
	*retFunc = Atcmdfunc[CmdIdx].cb((char*)PtrATCmdSend, (char*)UartRecvBuffer, CmdIdx, ReadLen);
	/*将获得的IP信息保存到一个缓冲区内*/
	if(AT_CIFSR == CmdIdx && 0 == *retFunc)
	{
		memset(IP_GetInfo, 0, sizeof(IP_GetInfo));
		IP_GetInfo[0] = ReadLen - strlen("AT+CIFSR\r\n") - 6;
		memcpy(IP_GetInfo + 1, UartRecvBuffer + strlen("AT+CIFSR\r\n"), IP_GetInfo[0]);
	}
	if (PtrATCmdSend != NULL)
	{
		memset(PtrATCmdSend, 0x00, ATCmdTotalLen+1);
		free(PtrATCmdSend);
	}
	PtrATCmdSend = NULL;
	return;
}


/*修改*/
static sint8 at_callbackFunc(char *PSendStr, char *pReadStr, uint8 CmdIdx, uint16 pReadLen)
{
	sint8 OutValue = -1;
	(void)pReadLen;
	(void)PSendStr;
	uint8 *retptr = NULL;
	char *OkAns = "OK";
	char *Error = "ERROR";
	//char *FAIL = "FAIL";
	//char* isBuilded = "link is builded";
	char* noChange = "no change";
	char* ALCON = "ALREADY CONNECTED";
	char* busy = "busy p...";

	retptr = (uint8 *)strstr((char *)pReadStr, noChange);
	if(retptr)
	{
		OutValue = 3; /* no Change*/
		return OutValue;
	}
	retptr = (uint8 *)strstr((char *)pReadStr, OkAns);
	switch (CmdIdx)
	{
		case AT_CMD_TEST:
		case ATE_0:
		case AT_SET_MODE:
		case AT_CWAUTOCONN:
		case AT_CIFSR:
		case AT_CIPMODE:
		case AT_CWQAP:
		{
			if (retptr)
			{
				OutValue = 0;
			}
			break;
		}
		case AT_CWJAP:
		case AT_CIPSTART:
		{
			while(!strstr(pReadStr, OkAns) && !strstr(pReadStr, Error))
			{
				static uint8 cyclNum = 0;
				uint8 ReadLen = 0;
				if(cyclNum > 5)
				{
					break;
				}
				UART_Receive_Data(UART_LPUART1, (uint8*)pReadStr,(uint16*)&ReadLen, 500);

				cyclNum++;
			}
			if (strstr(pReadStr, OkAns) || strstr(pReadStr, ALCON))
			{
				OutValue = 0;
			}
			break;
		}
		case AT_ISNOCON:
		{
			char* iscon = "+CWJAP:0";

			retptr = (uint8 *)strstr((char *)pReadStr, iscon);
			if(0 != retptr)
			{
				return 0;
			}
		}
		default:
			break;
	}
	retptr = (uint8 *)strstr((char *)pReadStr, busy);
	if(0 != retptr)
	{
		vTaskDelay(pdMS_TO_TICKS(800));
	}
	return OutValue;
}
static sint8 WiFiDisconnec(void)
{
	/* 退出WiFi 断开连接 */
	UART_Send_Data(UART_LPUART1, (uint8 *)"+++", 3, 100);
	vTaskDelay(pdMS_TO_TICKS(400));
	UART_Send_Data(UART_LPUART1, (uint8 *)"\r\n", 2, 100);
	sint8 ret = 0;
	vTaskDelay(pdMS_TO_TICKS(400));
	UART_Reset(UART_LPUART1);
	AtcmdTransmit(AT_CWQAP, NULL, 0, &ret);
	if(0 != ret)
	{
		vTaskDelay(pdMS_TO_TICKS(400));
		UART_Reset(UART_LPUART1);
		AtcmdTransmit(AT_ISNOCON, NULL, 0, &ret);
	}
	EffectiveDataFed = 0;
	return ret;
}
/*
 * 建立TCP连接函数
 * timeoutMs 超时时间
 * 数值为0时意为一直等待连接
 * */
static sint8 TCP_ConnectEstablish(uint32 timeoutMs)
{
	//WIFI模块初始化
	uint8 InitStep = 0;
	sint8 ATRet = -1;
	uint32 initTime = xTaskGetTickCount();
	while(1)
	{

		switch(InitStep)
		{
			case 0:
			{
				//const char* wifi_init = "\"Hoisting\",\"jx999999\"\r\n";
				const char* wifi_init = "\"123456\",\"12345678\"\r\n";
				WIFI_CMD_INIT(AT_CWJAP,(uint8*)wifi_init,strlen(wifi_init),InitStep,ATRet);
				break;
			}
			case 1:
			{
				//const char* wifi_ip_info_init = "\"TCP\",\"192.168.3.177\",5588\r\n";
				const char* wifi_ip_info_init = "\"TCP\",\"192.168.0.181\",5588\r\n";
				WIFI_CMD_INIT(AT_CIPSTART,wifi_ip_info_init,strlen(wifi_ip_info_init),InitStep,ATRet);
				break;
			}
			case 2:/* 设置透传模式 */
			{
				WIFI_CMD_INIT(AT_CIPMODE,NULL,0,InitStep,ATRet);
				if(0 == ATRet)
				{
					vTaskDelay(pdMS_TO_TICKS(1000));
					AtcmdTransmit(AT_CIPSEND, NULL, 0, &ATRet);
				}
				break;
			}
			default:
				return 0;
				break;
		}
		if(xTaskGetTickCount() - initTime > pdMS_TO_TICKS(timeoutMs) && 0 != timeoutMs)
		{
			/* 超时退出 */
			return 1;
		}

	}
	return 0;
}

static void WiFiStaMan(void)
{

	if((WIFI_UNENABLE != tcp_server_process_status && 1 == WiFiPwrControl)
			|| (1 == KeySignal && TCP_CONNECT != tcp_server_process_status)) /* WiFi关机 */
	{

		WiFiPwrControl = 0;
		if(TCP_CONNECT == tcp_server_process_status)
		{
			WiFiDisconnec();
		}
		else
		{
			;
		}
		Dio_WriteChannel(DioConf_DioChannel_PTD16_GPIO_OUT_MCU_WIFI_POW_EN, STD_OFF);
		tcp_server_process_status = WIFI_UNENABLE;

	}
	if(WIFI_UNENABLE == tcp_server_process_status && 2 == WiFiPwrControl) /* WiFi开机 */
	{
		WiFiPwrControl = 0;
		Dio_WriteChannel(DioConf_DioChannel_PTD16_GPIO_OUT_MCU_WIFI_POW_EN, STD_ON);
	}
	if(TCP_UNCONNECT == tcp_server_process_status && 1 == WiFiConnectControl) /* 连接WiFi */
	{
		WiFiConnectControl = 0;
		TCP_ConnectEstablish(0);
		tcp_server_process_status = TCP_CONNECT;
	}
	if(TCP_CONNECT == tcp_server_process_status && 2 == WiFiConnectControl) /* 断开WiFi */
	{
		WiFiConnectControl = 0;
		WiFiDisconnec();
		tcp_server_process_status = TCP_UNCONNECT;
	}
}
