//单片机头文件
#include "stm32f4xx.h"                  // Device header
#include "common.h"      

//网络设备驱动
#include "esp8266.h"

//硬件驱动

#include "usart.h"

//C库
#include <string.h>
#include <stdio.h>


#define WIFI_SSID 						"hzxy"								//	WIFI的名称 必须用2.4G的wifi不能用5G的，且不能用中文、空格
#define WIFI_PSWD 						"123456789"				//	WIFI密码

#define SERVER_HOST						"mqtt.mqttbai.xyz"			//	MQTT服务器域名或IP
#define SERVER_PORT						"1883"									//	MQTT服务器端口（一般为1883不用改）


#define ESP8266_WIFI_INFO			"AT+CWJAP=\"" WIFI_SSID "\",\"" WIFI_PSWD "\"\r\n"
#define ESP8266_ONENET_INFO		"AT+CIPSTART=\"TCP\",\"" SERVER_HOST "\"," SERVER_PORT "\r\n"

unsigned char esp8266_buf[512];
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;

extern u8 ESP8266_INIT_OK;

uint8_t aRxBuffer1[1];		// 用来接收串口1发送的数据
uint8_t aRxBuffer2[1];		// 用来接收串口2发送的数据
uint8_t aRxBuffer6[1];		// 用来接收串口6发送的数据
u8 RX_num=0;   //接收计数变量
u8  RX_buffer[tbuf];


//==========================================================
//	函数名称：	ESP8266_Clear
//
//	函数功能：	清空缓存
//
//	入口参数：	无
//
//	返回参数：	无
//
//	说明：		
//==========================================================
void ESP8266_Clear(void)
{

	memset(esp8266_buf, 0, sizeof(esp8266_buf));
	esp8266_cnt = 0;

}

//==========================================================
//	函数名称：	ESP8266_WaitRecive
//
//	函数功能：	等待接收完成
//
//	入口参数：	无
//
//	返回参数：	REV_OK-接收完成		REV_WAIT-接收超时未完成
//
//	说明：		循环调用检测是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(void)
{

	if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中，所以直接跳出，结束函数
		return REV_WAIT;
		
	if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同，则说明接收完毕
	{
		esp8266_cnt = 0;							//清0接收计数
			
		return REV_OK;								//返回接收完成标志
	}
		
	esp8266_cntPre = esp8266_cnt;					//置为相同
	
	return REV_WAIT;								//返回接收未完成标志

}

//==========================================================
//	函数名称：	ESP8266_SendCmd
//
//	函数功能：	发送命令
//
//	入口参数：	cmd：命令
//				res：需要检查的返回指令
//
//	返回参数：	0-成功	1-失败
//
//	说明：		
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)
{
	
	unsigned char timeOut = 200;
	HAL_UART_Transmit(&huart2,(unsigned char *)cmd,strlen((const char *)cmd),100);
	//HAL_UART_Transmit(&huart1,(unsigned char *)cmd,strlen((const char *)cmd),100);
	
	while(timeOut--)
	{
		if(ESP8266_WaitRecive() == REV_OK)							//如果收到数据
		{
			
			if(strstr((const char *)esp8266_buf, res) != NULL)		//如果检索到关键词
			{
				ESP8266_Clear();									//清空缓存
				
				return 0;
			}
		}
		
		HAL_Delay(10);
	}
	
	return 1;

}

//==========================================================
//	函数名称：	ESP8266_SendData
//
//	函数功能：	发送数据
//
//	入口参数：	data：数据
//				len：长度
//
//	返回参数：	无
//
//	说明：		
//==========================================================
void ESP8266_SendData(unsigned char *data, unsigned short len)
{

	char cmdBuf[32];
	
	ESP8266_Clear();								//清空接收缓存
	sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len);		//发送命令
	if(!ESP8266_SendCmd(cmdBuf, ">"))				//收到‘>’时可以发送数据
	{
		HAL_UART_Transmit(&huart2,data,len,100);		//发送设备连接请求数据
	}

}

//==========================================================
//	函数名称：	ESP8266_GetIPD
//
//	函数功能：	获取平台返回的数据
//
//	入口参数：	等待的时间(乘以10ms)
//
//	返回参数：	平台返回的原始数据
//
//	说明：		不同网络设备返回的格式不同，需要去调试
//				如ESP8266的返回格式为	"+IPD,x:yyy"	x代表数据长度，yyy是数据内容
//==========================================================
unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{

	char *ptrIPD = NULL;
	
	do
	{
		if(ESP8266_WaitRecive() == REV_OK)								//如果接收完成
		{
			ptrIPD = strstr((char *)esp8266_buf, "IPD,");				//搜索“IPD”头
			if(ptrIPD == NULL)											//如果没找到，可能是IPD头的延迟，还是需要等待一会，但不会超过设定的时间
			{
				printf("\"IPD\" not found\r\n");
			}
			else
			{
				ptrIPD = strchr(ptrIPD, ':');							//找到':'
				if(ptrIPD != NULL)
				{
					ptrIPD++;
					return (unsigned char *)(ptrIPD);
				}
				else
					return NULL;
				
			}
		}
		HAL_Delay(5);
		timeOut--;	//延时等待
	} while(timeOut > 0);
	
	return NULL;														//超时还未找到，返回空指针

}

//==========================================================
//	函数名称：	ESP8266_Init
//
//	函数功能：	初始化ESP8266
//
//	入口参数：	无
//
//	返回参数：	无
//
//	说明：		
//==========================================================
void ESP8266_Init(void)
{
	
  HAL_GPIO_WritePin(ESP8266_RST_GPIO_Port, ESP8266_RST_Pin, GPIO_PIN_RESET);
	HAL_Delay(250);
	HAL_GPIO_WritePin(ESP8266_RST_GPIO_Port, ESP8266_RST_Pin, GPIO_PIN_SET);
	HAL_Delay(500);
	
	ESP8266_Clear();
	
	printf("0. AT - 测试MCU-8266通讯\r\n");
	while(ESP8266_SendCmd("AT\r\n","OK"))
		HAL_Delay(500);
	
	printf("1. AT+RST - 软复位8266\r\n");
	ESP8266_SendCmd("AT+RST\r\n", "");
		HAL_Delay(500);
	ESP8266_SendCmd("AT+CIPCLOSE\r\n", "");
		HAL_Delay(500);
	printf("2. AT+CWMODE=1,1 - 设置8266工作模式为STA\r\n");
	while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))
		HAL_Delay(500);
	
	printf("3. AT+CWDHCP=1,1 - 使能STA模式下DHCP\r\n");
	while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))
		HAL_Delay(500);
	
	printf("4. AT+CWJAP - 连接WIFI\r\n");
	while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))
		HAL_Delay(500);
	
	printf("5. AT+CIPSTART - 连接服务器\r\n");
	while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))
		HAL_Delay(500);
	ESP8266_INIT_OK = 1;
	printf("6. ESP8266 Init OK - ESP8266初始化成功\r\n");
	printf("ESP8266初始化			[OK]");
}

//==========================================================
//	函数名称：	USART2_IRQHandler
//
//	函数功能：	串口2收发中断
//
//	入口参数：	无
//
//	返回参数：	无
//
//	说明：		
//==========================================================
//void USART2_IRQHandler(void)
//{
////printf("asd\n");
//	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
//	{
//		if(esp8266_cnt >= sizeof(esp8266_buf))	
//		{
//			esp8266_cnt = 0; //防止串口被刷爆
//		}
//		esp8266_buf[esp8266_cnt++] = USART_ReceiveData(USART2);
//		//printf("%c\n",esp8266_buf[esp8266_cnt++]); 
//		USART_ClearFlag(USART2, USART_FLAG_RXNE);
//	}

//}


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//串口回调函数
{
	if(huart->Instance == USART1)	// 判断是由哪个串口触发的中断
	{
		HAL_UART_Transmit(&huart1,aRxBuffer1,1,100);	// 接收到数据马上使用串口1发送出去
		//HAL_UART_Transmit(&huart6,aRxBuffer1,1,100);	// 接收到数据马上使用串口1发送出去
		HAL_UART_Receive_IT(&huart1,aRxBuffer1,1);		// 重新使能串口1接收中断
	}	
	if(huart->Instance == USART2)	// 判断是由哪个串口触发的中断
	{
		if(esp8266_cnt >= sizeof(esp8266_buf))	
		{
			esp8266_cnt = 0; //防止串口被刷爆
		}
	  esp8266_buf[esp8266_cnt++] = aRxBuffer2[0];
		
		
		//HAL_UART_Transmit(&huart1,aRxBuffer2,1,100);	// 接收到数据马上使用串口1发送出去
		
		HAL_UART_Receive_IT(&huart2,aRxBuffer2,1);		// 重新使能串口1接收中断
	}
	if(huart->Instance == USART6)	// 判断是由哪个串口触发的中断
	{
		HAL_UART_Transmit(&huart1,aRxBuffer6,1,100);	// 接收到数据马上使用串口1发送出去
		HAL_UART_Receive_IT(&huart6,aRxBuffer6,1);		// 重新使能串口1接收中断
	}
	
	
}

