/********************************************************************************
 * @file    AT_Module.c
 * @author  度云未来 DOIOT
 * @brief   针对公司模块AT指令的处理库
 ******************************************************************************
 * @attention
 * <h2><center>&copy; Copyright (c) 2019 成都度云未来
 * All rights reserved.</center></h2>
 * 注意:本程序针对cubemx 生成的hal库程序快速开发
 * 环境:keil5.0
 * STM32Cube FW_F1 V1.8.0
 * 文件版本：1.3		更新时间2020/10/15   降低了文件之间的耦合度
********************************************************************************/
 
#include "includes.h"
#include "trace.h"
#include "at_module.h"
#include "stdarg.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"  


uint8_t AT_CMD_SEND(AT_CMD task);
extern int uart_blocking_read(char *buffer, u8 uartid, u32 timeout);
char at_rxbuff[1024];
int Module_Blocking_Read(char *buffer, u32 timeout)
{
	return uart_blocking_read(buffer, UART_ME3616, timeout);
}

uint8_t AT_TASK_START(AT_CMD task[],uint8_t Size)
{
	uint32_t i;
	for(i=0;i<Size;i++)
	{
		AT_INFO("Start Task %d",i+1);

		if(AT_CMD_SEND(task[i]))
		{
			/*校验成功,开始延时*/
			HAL_Delay(task[i].delay_time);	
		}
		else
		{
			/*校验失败,开始处理*/
			if(task[i].REF_Count!=0)
			{
				task[i].REF_Count--;
				i--;/*下一次迭代会回到这个地方*/
				AT_INFO("开始重发");
			}
			else/*没有重发次数或者次数已尽*/
			{
			/*装载跳跃位置*/
				if(task[i].jump!=0)
				{
				i=task[i].jump-2;
				AT_INFO("开始跳转");
				}
			}
		}
	}
	return 1;
}

uint8_t AT_CMD_SEND(AT_CMD task)
{
	uint8_t i=0;
	rxbuff(buff);
	
	/*先执行前调函数*/
	if(task.BeforeCpltCallback!=NULL)
	{
		task.BeforeCpltCallback();
	}
		
	module_printf("%s", task.SEND_CMD);
	AT_INFO("SEND:%s",task.SEND_CMD);
	
	for(i=0;i<task.crc_size;i++)
	{

		Module_Blocking_Read(buff,task.timeout);
		AT_INFO("ASK:%s",buff);
		
		if(strstr(buff,task.ASK[i]))
		{	
		}else
		{
			AT_ERROR("%s",buff);
			/*校验失败，执行失败回掉*/
			if(task.ErrorCpltCallback!=NULL)
			{
				task.ErrorCpltCallback(buff);
			}
			return 0;
		}
	}
		/*校验成功，执行完成回调函数*/
	if(task.AfterCpltCallback!=NULL)
	{
		task.AfterCpltCallback(buff);
	}
		return 1;
}

/**
* @param sned_cmd	: 发送的指令
* @param cmd_arry	: 要校验的响应数组
* @param ack_str: 响应的校验的字串
* @param overtime	: 校验的数量【如果响应组是3，校验是2，则会读取三次，但只校验到第2组】
*/

uint8_t Module_SEND_CRC(char* send_cmd,char *ack_str,uint32_t overtime)
{
	//char rxbuf[cmd_length];
	module_printf("%s", send_cmd);
	if(Module_Read_A_CRC(ack_str,overtime)) return 1;//校验成功;	
	else return 0;/*阻塞的读取一次响应,超时返回失败*/
}


/**
* @param sned_cmd	: 发送的指令
* @param cmd_arry	: 要校验的响应数组
* @param arry_size: 响应的校验组数量
* @param crc_size	: 校验的数量【如果响应组是3，校验是2，则会读取三次，但只校验到第2组】
*/

uint8_t Module_SEND_A_CRC(char* send_cmd,char cmd_arry[][cmd_length],uint8_t arry_size,uint8_t crc_size)
{
	char rxbuf[cmd_length];
	uint8_t i;
	module_printf("%s", send_cmd);
	for(i=0;i<arry_size;i++)							/*读取完指定次数*/
	{	
		if(Module_Blocking_Read(rxbuf,1000));	/*阻塞的读取一次响应,超时返回失败*/
		else return 0;
			
		if(i<crc_size)												/*校验指定的次数*/
		{
			if(strstr(rxbuf,cmd_arry[i])) 
			{
			}else goto cmd_fail;
		}
	}
	return 1;//校验成功
	
	cmd_fail: 
	{
		/*自写错误处理*/
	}
	return  0;
}

/**
* @param 阻塞读取一次数据并校验
* @param cmd_arry	: 要校验的响应数组
* @param overtime	: 超时时间
*/

uint8_t Module_Read_A_CRC(char cmd_arry[],uint32_t overtime)
{
	//rxbuff(at_rxbuff);

	memset(at_rxbuff, 0, sizeof(at_rxbuff));	

	if(Module_Blocking_Read(at_rxbuff,overtime)) /*阻塞的读取一次响应,超时返回失败*/
	{
//		printf("%s\r\n", at_rxbuff);
		if(strstr(at_rxbuff,cmd_arry))
		return 1;	
		else 
		{
			return 0;
		}
	}
	else return 0;
}

uint8_t Module_Read_A_CRC_DA(char cmd_arry[],char head_arry[], uint32_t len, uint32_t overtime)
{
	//rxbuff(at_rxbuff);
    int i = 0,rcv_size = 0;
    memset(at_rxbuff, 0, sizeof(at_rxbuff));
    rcv_size = Module_Blocking_Read(at_rxbuff,overtime);
    if(rcv_size) /*阻塞的读取一次响应,超时返回失败*/
    {

//        data_dump("net sendx", (uint8_t *)at_rxbuff, len);
//        if(strstr(at_rxbuff+len/2,cmd_arry))
//            return 1;
//        else
//        {
//            return 0;
//        }

        for(i=len/2; i<rcv_size; i++){
            if(at_rxbuff[i]==0x0D && at_rxbuff[i+1]==0x0A){
                if(strstr(at_rxbuff+i,cmd_arry)){
                    return 1;
                }
                else continue;
            }
        }
        return 0;
    }
    else return 0;
}

/**@brief AT_CMD_Polling:按指定的指令轮询直到响应对应的ACK才返回
* @param  send_cmd			 : 需要轮询的指令
* @param  Polling_fre	   : 轮询间隔
* @param  overtime       : 超时时间
*/
uint8_t AT_CMD_Polling(char *send_cmd,char*ack,uint32_t Polling_delay,uint32_t overtime)
{
	uint32_t time_count=0;
	while(1)
	{
		if(time_count%Polling_delay==0)
		{
		module_printf("%s", send_cmd);
		if(Module_Read_A_CRC(ack,100)) return 1;
		}
		time_count++;
		HAL_Delay(1);
		if(time_count>overtime) return 0;
	}
}

/**@brief AT_GET_data:提取字符串中第Number_of_groups组被特定字符包裹的信息，标志必须是成对闭合的
* @param  buff			 : 待提取的字符串，可以是数组或静态字符串
* @param  get_data	 : 提取后装载的数组，必须是数组，不能是静态字符串因为需要写
* @param  sign       : 包裹符号,是一个字符
* @param  Number_of_groups : 提取的是第几组
* 例：字符串 "AT+MIPOPEN=1,"TCP","122.114.122.174",41838,100,0,1,2,11002"
*			参数Number_of_groups=2提取第二组，装载结果get_data: 122.114.122.174
*/
uint8_t AT_GET_Data(char * buff,uint8_t get_data[],char*sign,uint8_t Number_of_groups)
{
	uint16_t  i=0,count=0;
	while(buff[i]!='\0')				/*获取分隔符整数*/
	{
	if(buff[i]==sign[0]) count++;
	i++;
	}
	if(count%2==0&&count>=Number_of_groups*2)							/*偶数分隔符数才继续进行*/
	{
		char chBuffer[512] ;				/*按需调整*/
		char *pchDilem =sign;				/*分隔符*/
		char *pchStrTmpIn = NULL;		/*剩下的缓存*/
		char *pchTmp = NULL;				/*提取出的字符*/
		i=0;
		strcpy(chBuffer,buff);
		pchTmp = chBuffer;
		while(NULL != ( pchTmp = strtok_r( pchTmp, pchDilem, &pchStrTmpIn) ))
		{
		//	uart1_printf("\n pchTmp[%s] \n",pchTmp);
			i++;
			if(i==Number_of_groups*2) strcpy((char*)get_data,pchTmp);
			pchTmp = NULL;
		}
		return 1;
	}
	else return 0;							/*非偶数分隔符直接结束*/
}

/**@brief AT_GET_Data_2Param :提取被头尾字符串包裹的字串
* @param  buff			 : 待提取的字符串，可以是数组或静态字符串
* @param  get_data	 : 提取后装载的数组，必须是数组，不能是静态字符串因为需要写
* @param  head       : 头字符串【任意长度符串】
* @param  tail			 : 尾字符串【任意长度字符串】
* 例：字符串 "+QGPSGNMEA: $GPRMC,021229.00,A,3041.560083,N,10405.832869,E,0.0,247.3,040920,1.9,W,A*28"
*			参数head ",A",tail ",N",装载结果get_data: "3041.560083"
*/
uint8_t AT_GET_Data_2Param(char * buff,uint8_t get_data[],char*head,char*tail)
{
	if(strstr(buff,head)&&strstr(buff,tail))
	{
		uint16_t i;
		uint16_t len1,len2;
		char *t = NULL;
		char *h=strstr(buff,head);
		len1=strlen(h);				/*剩余长度*/	
		len2=strlen(head);		/*头子串长度*/	
		t=strstr(h+len2,tail);
		if(len1>len2)
		{
					for(i=0;h+i+len2!=t;i++)
					{
						get_data[i]=h[i+len2];	
					}
					get_data[i]='\0';//加上结束符
		}else 
		{
			debug_printf("\r\n字串长度错误\r\n");
			return 0;
		}
	}else
	{
		if(!strstr(buff,head))debug_printf("\r\n未能检索到头字串\r\n");
		if(!strstr(buff,tail))debug_printf("\r\n未能检索到尾字串\r\n");
		
		debug_printf("\r\n请检查你的数据原文:\r\n");
		debug_printf("%s", buff);
		return 0;
	}
	return 1;
}
/**@brief AT_Data_Replace :提取被头尾字符包裹的字串
* @param  buff			 : 待提取的字符串，必须是实体数组，需要写入
* @param  str1	 		 : 被替换的子串，可以是数组和静态字符串
* @param  str2       : 替换成的子串，可以是数组和静态字符串
* 例：字符串 AT+QMTCFG="aliauth",0,"a1XVq3z4DsR"
*			参数str1 "aliauth",str2 "recv/mode",替换结果buff: AT+QMTCFG="recv/mode",0,"a1XVq3z4DsR"
*/
uint8_t AT_Data_Replace(char buff[],char *str1, char *str2) {
    int i,flag = 0;
    char *p,*q,*ts;
    for(i = 0; buff[i]; ++i)
		{
						if(buff[i] == str1[0]) 
						{
								p = buff + i;
								q = str1;
								while(*q && (*p++ == *q++));
								if(*q == '\0') 
									{
										ts = (char *)malloc(strlen(buff) + 1);
										strcpy(ts,p);
										buff[i] = '\0';
										strcat(buff,str2);
										strcat(buff,ts);
										free(ts);
										flag = 1;
									}
						}
    }
    return flag;
}

/**@brief AT_GET_Data_Param_number :指定的标志位开始，提取后面的数据，直到遇到\r,\n,
* @param  buff			 : 待提取的字符串，可以是数组或静态字符串
* @param  get_data	 : 提取后装载的数组，必须是数组，不能是静态字符串因为需要写
* @param  head       : 头字符串【任意长度符串】
* 例：字符串 "  +ESOERR=1,4   "
*			参数head ",",装载结果get_data: "4"
*/
uint8_t AT_GET_Data_Param(char * buff,uint8_t get_data[],char*head)
{
	char *h=strstr(buff,head);
	if(h!=NULL)
	{
		uint16_t i;
		int len=strlen(head);
		for(i=0;h[i+len]!='\r'&&h[i+len]!='\n'&&h[i+len]!=' ';i++)
		{
			get_data[i]=h[i+len];	
		}
		get_data[i]='\0';//加上结束符
	}else
	{
		if(!strstr(buff,head))debug_printf("\r\n未能检索到标志位\r\n");	
		debug_printf("\r\n请检查你的数据原文:\r\n");
		debug_printf("%s", buff);
		return 0;
	}
	return 1;
}




/**@brief AT_Extract_numbers :导入的数组进行提纯，去掉非数字的部分
* @param  buff			 : 待提纯的字符串，必须是实体数组，需要写入
*/
uint8_t AT_Extract_numbers(char buff[]) {
		
	uint16_t i=0,n=0;
	int len=strlen(buff);
	char fifo[32];/*浪费空间，但是效率更高*/
	memset(fifo,0, sizeof(fifo));
	for(;buff[i]!='\0';)
	{
		if(buff[i]>='0'&&buff[i]<='9')
		{			
			fifo[n]=buff[i];
			n++;
			i++;
		}
		else
		{
			i++;
		}
	}
	strcpy(buff,fifo);
	return 1;
}

/**@brief AT_Extract_numbers :导入的数组进行提纯，去掉非数字和非字母的部分
* @param  buff			 : 待提纯的字符串，必须是实体数组，需要写入
*/
uint8_t AT_Extract_numbers_letters(char buff[]) {
		
	uint16_t i=0,n=0;
	int len=strlen(buff);
	char fifo[256];/*浪费空间，但是效率更高*/
	memset(fifo,0,len+1);
	for(;buff[i]!='\0';)
	{
		if((buff[i]>='0'&&buff[i]<='9')||(buff[i]>='A'&&buff[i]<='Z')||(buff[i]>='a'&&buff[i]<='z'))
		{			
			fifo[n]=buff[i];
			n++;
			i++;
		}
		else
		{
			i++;
		}
	}
	//debug_printf("\r\n");
	//debug_printf(fifo);
	strcpy(buff,fifo);
	return 1;
}

/**@brief AT_Remove_spaces :去掉空字符,\r,\n,space
* @param  buff			 : 待提纯的字符串，必须是实体数组，需要写入
*/
uint8_t AT_Remove_spaces(char buff[]) {
		
	uint16_t i=0,n=0;
	int len=strlen(buff);
	char fifo[256];/*浪费空间，但是效率更高*/
	memset(fifo,0,len+1);
	for(;buff[i]!='\0';)
	{
		if((buff[i]!='\r')&&(buff[i]!='\n')&&(buff[i]!=' '))
		{			
			fifo[n]=buff[i];
			n++;
			i++;
		}
		else
		{
			i++;
		}
	}
	//debug_printf("\r\n");
	//debug_printf(fifo);
	strcpy(buff,fifo);
	return 1;
}

