/*
*********************************************************************************************************
*                                       IAR Development Kits
*                                              on the
*
*                                    M451
*
* Filename      : uart_dtu.c
* Version       : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/

#include  "includes.h"

#include "drv_dtu.h"
#include "drv_gps.h"

// GPS开启计时
volatile uint32_t DTU_gpsTime = 0;

// 是否需要检查并重启GPS
uint8_t DTU_needCheckGPS = 0;

// **************** 上传GPS调试信息 ********************
// GPS闪断次数：取值为0~599循环计数
uint16_t GPS_BOD_COUNT = 0;
// *****************************************************

// 打开GPS功能
uint32_t DTU_EnableGPS()
{
	char cmd[50], buff[50];
	uint8_t try_count = 2;
	static uint8_t first = 1;
	
	// 禁止重启GPS
	DTU_needCheckGPS = 0;
	
	if(!IS_VCC_GPS_ON())
	{
		VCC_GPS_ON();
		delay_ms(2500);
	}
	
//	DTU_ExecuteCmd("AT+QGPSDEL=3", "OK", "ERROR", buff, DTU_tmrQPendShort);
//	DTU_ExecuteCmd("AT+QGPSXTRA=0", "OK", "ERROR", buff, DTU_tmrQPendShort);
//	return FALSE;
	
#if 0
	// 检查QGPSXTRA
	if(!DTU_ExecuteCmd("AT+QGPSXTRA?", "+QGPSXTRA: 1", "+QGPSXTRA: 0", buff, DTU_tmrQPendShort))
	{
		// 如果没有， 则设置并重启
		if(DTU_ExecuteCmd("AT+QGPSXTRA=1", "OK", "ERROR", buff, DTU_tmrQPendShort))
		{
			DTU_PowerOff();
			delay_ms(200);
			NVIC_SystemReset();
		}
	}
		
	// 检查QGPSXTRADATA
	if(DTU_ExecuteCmd("AT+QGPSXTRADATA?", "+QGPSXTRADATA: ", "ERROR", buff, DTU_tmrQPendShort)
		&& strstr(buff, "+QGPSXTRADATA: 0,"))
	{
		// 先删除内存文件
		DTU_ExecuteCmd("AT+QFDEL=\"RAM:xtra2.bin\"", "OK", "ERROR", buff, DTU_tmrQPendShort);
		// 下载XTRADATA
		if(Sim808_GPRSDial()
			&& DTU_ExecuteCmd("AT+QHTTPCFG=\"contextid\",1", "OK", "ERROR", buff, DTU_tmrQPendShort)
			&& DTU_ExecuteCmd("AT+QHTTPCFG=\"responseheader\",0", "OK", "ERROR", buff, DTU_tmrQPendShort)
			&& DTU_ExecuteCmd("AT+QHTTPURL=40,10", "CONNECT", "ERROR", buff, DTU_tmrQPendShort)
		)
		{
			strcpy(cmd, "http://xtrapath1.izatcloud.net/xtra2.bin");
			UART_Transmit(&huart1, (uint8_t *) cmd, strlen(cmd));
			if(DTU_ParseResult("OK", "ERROR", buff, DTU_tmrQPendShort)
				&& DTU_ExecuteCmd("AT+QHTTPGET=80", "+QHTTPGET: 0,", "ERROR", buff, DTU_tmrQPendSpec)
				&& DTU_ExecuteCmd("AT+QHTTPREADFILE=\"RAM:xtra2.bin\",80", "+QHTTPREADFILE: 0", "ERROR", buff, DTU_tmrQPendSpec)
				&& DTU_ExecuteCmd("AT+QLTS=2", "+QLTS: ", "ERROR", buff, DTU_tmrQPendShort) // Get UTC time
			)
			{
				// 获取时间
				memset(cmd, 0, sizeof(cmd));
				strncpy(cmd, strstr(buff, "+QLTS: \"") + 8, 19);
				// 注入时间、XTRADATA
				sprintf(buff, "AT+QGPSXTRATIME=0,\"%s\",1,1,3500", cmd);	// Inject UTC time
				strcpy(cmd, buff);
				if(DTU_ExecuteCmd(cmd, "OK", "ERROR", buff, DTU_tmrQPendShort)
					&& DTU_ExecuteCmd("AT+QGPSXTRADATA=\"RAM:xtra2.bin\"", "OK", "ERROR", buff, DTU_tmrQPendShort)
				)
				{
					printf("\nGPS XTRADATA Injected.\n");
				}
			}
		}
	}
#endif
	
	while(try_count--)
	{
		delay_ms(200);

		// 先停止GPS定位
		if(DTU_ExecuteCmd("AT+QGPSEND", "OK", "ERROR", buff, DTU_tmrQPendShort))
		{
			printf("\nGPS disabled.\n");
			delay_ms(200);
		}

		// 查询当前输出端口是否为uartdebug
		if(first || !DTU_ExecuteCmd("AT+QGPSCFG=\"outport\"", "+QGPSCFG:", "ERROR", buff, DTU_tmrQPendShort)
			|| strstr(buff, "uartdebug") == 0)
		{
			// 设置当前输出端口为uartdebug
			if(!DTU_ExecuteCmd("AT+QGPSCFG=\"outport\",\"uartdebug\"", "OK", "ERROR", buff, DTU_tmrQPendShort))
			{
				printf("\nSet GPS outport failed.\n");
				continue;
			}
			first = 0;
		}
		if(DTU_ExecuteCmd("AT+QGPS=1,255,50,0,4", "OK", "ERROR", buff, DTU_tmrQPendShort))
		{
			printf("\nGPS enabled.\n");
			// 允许重启GPS
			DTU_needCheckGPS = 1;
			return TRUE;
		}
	}

	printf("\nGPS enable failed.\n");
	// 允许重启GPS
	DTU_needCheckGPS = 1;
	return FALSE;
}

// 关闭GPS功能
void DTU_DisableGPS()
{
	char buff[50];
	
	if(IS_VCC_GPS_ON())
	{
		VCC_GPS_OFF();
		if(DTU_ExecuteCmd("AT+QGPSEND", "OK", "ERROR", buff, DTU_tmrQPendShort))
			printf("\nGPS disabled.\n");
		else
			printf("\nGPS disable failed.\n");
	}
}

// 处理时差函数
void GPS_ProcessTimeLag(date_time_t *sysTime, int8_t timeLag)
{
	// 处理时差：正时差
	if(timeLag > 0)
	{
		sysTime->hour += timeLag;
		if(sysTime->hour >= 24)
		{
			sysTime->hour %= 24;
			if(sysTime->day < get_month_days(sysTime->year + 2000, sysTime->month))
				sysTime->day++;
			else
			{
				sysTime->day = 1;
				if(sysTime->month < 12)
					sysTime->month++;
				else
				{
					sysTime->month = 1;
					sysTime->year++;
				}
			}
		}
	}
	// 处理时差：负时差
	else if(timeLag < 0)
	{
		// hour是无符号数
		if(sysTime->hour >= (-timeLag))
			sysTime->hour += timeLag;
		else
		{
			sysTime->hour += (24 + timeLag);
			if(sysTime->day > 1)
				sysTime->day--;
			else
			{
				if(sysTime->month > 1)
				{
					sysTime->month--;
					sysTime->day = get_month_days(sysTime->year + 2000, sysTime->month);
				}
				else
				{
					sysTime->month = 12;
					sysTime->day = 31;
					sysTime->year--;
				}
			}
		}
	}
}

// ASCII重组
void ASCII2Hex(char hchar, char lchar, uint8_t* hex)
{
    uint8_t h = 0, l = 0;

    if(hchar >= '0' && hchar <= '9')
    {
        h = hchar - '0';
    }
    else if(hchar >= 'A' && hchar <= 'F')
    {
        h = hchar - 'A' + 10;
    }
    else if(hchar >= 'a' && hchar <= 'f')
    {
        h = hchar - 'a' + 10;
    }

    if(lchar >= '0' && lchar <= '9')
    {
        l = lchar - '0';
    }
    else if(lchar >= 'A' && lchar <= 'F')
    {
        l = lchar - 'A' + 10;
    }
    else if(lchar >= 'a' && lchar <= 'f')
    {
        l = lchar - 'a' + 10;
    }

    *hex = (h << 4) | l;
}

uint8_t check_sum(char *message)
{
    int16_t i, len = strlen(message);
    uint8_t cs0, cs1 = 0;

    if(len < 4 || message[0] != '$' || message[len - 3] != '*')
        return 0;

    for(i = 1; i < len - 3; i++)
    {
        cs1 ^= message[i];
    }

    ASCII2Hex(message[len - 2], message[len - 1], &cs0);

    if(cs1 == cs0)
        return 1;

	printf("\nCheck sum error: %s<>%02X", message, cs1);
    return 0;
}

uint32_t parse_vtg(char *message, data_dtu_t *sample)
{
    char *p = message, *pe = p + strlen(message), *p1 = NULL;
	char buff[20];

    // $GNVTG,293.56,T,,M,1.13,N,2.10,K,A*28

    // 运动角度
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // T=真北参照系
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // 运动角度
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // M=磁北参照系
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // 水平运动速度（节）
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // N=节
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // 水平运动速度（千米）
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;
    p1 = strstr(p, ",");
	if(!p1)
		return 0;
    memset(buff, 0, sizeof(buff));
    strncpy(buff, p, p1 - p);
    sample->speed = atof(buff);

    return 1;
}

uint32_t parse_gga(char *message, data_dtu_t *sample)
{
    char *p = message, *pe = p + strlen(message), *p1 = NULL;
	char buff[20];

    // $GNGGA,014600.000,3029.3359,N,10357.9168,E,1,4,4.16,200.1,M,-32.0,M,,*6B

	if(!check_sum(message))
		return 0;
	
    // UTC 时间
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // 纬度
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // N/S
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // 经度
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // E/W
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // GPS状态
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // 正在使用的卫星数
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;
    p1 = strstr(p, ",");
	if(!p1)
		return 0;	
    memset(buff, 0, sizeof(buff));
    strncpy(buff, p, p1 - p);
    sample->sateCount = atoi(buff);

    return 1;
}

uint32_t parse_rmc(char *message, data_dtu_t *sample)
{
    char *p = message, *pe = p + strlen(message), *p1 = NULL;
	char buff[20];
	uint16_t deg;
	float fen;

    // $GNRMC,014600.000,A,3029.3359,N,10357.9168,E,1.13,293.56,070417,,,A*7C

	if(!check_sum(message))
		return 0;
	
    // UTC时间
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;
	p1 = strstr(p, ",");
	if(!p1 || p1 < p + 6)
		return 0;
    // 2位小时
    memset(buff, 0, sizeof(buff));
    strncpy(buff, p, 2);
    p += 2;
    sample->sysTime.hour = atoi(buff);
	// 2位分钟
    memset(buff, 0, sizeof(buff));
    strncpy(buff, p, 2);
    p += 2;
    sample->sysTime.minute = atoi(buff);
    // 2位秒
    memset(buff, 0, sizeof(buff));
    strncpy(buff, p, 2);
    p += 2;
    sample->sysTime.second = atoi(buff);
	if(sample->sysTime.hour > 23 || sample->sysTime.minute > 59 || sample->sysTime.second > 59)
		return 0;	

    // 定位状态
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;
    sample->posState = (*p == 'A');

    // 纬度
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;
	p1 = strstr(p, ",");
	if(!p1 || p1 < p + 11)
		return 0;
	memset(buff, 0, sizeof(buff));
	strncpy(buff, p, 2);
	deg = atoi(buff);
	p += 2;
	strncpy(buff, p, 9);
	fen = atof(buff);
	if(deg > 90 || fen >= 60 || (deg == 90 && fen  > 0))
		return 0;
	sample->latitude = (deg + fen / 60) * 1000000ul;

    // N/S
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;
	if(*p == 'S')
		sample->latitude = -sample->latitude;

    // 经度
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;
	p1 = strstr(p, ",");
	if(!p1 || p1 < p + 12)
		return 0;
	memset(buff, 0, sizeof(buff));
	strncpy(buff, p, 3);
	deg = atoi(buff);
	p += 3;
	strncpy(buff, p, 9);
	fen = atof(buff);
	if(deg > 180 || fen >= 60 || (deg == 180 && fen  > 0))
		return 0;
	sample->longitude = (deg + fen / 60) * 1000000ul;

    // E/W
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;
	if(*p == 'W')
		sample->longitude = -sample->longitude;

    // 速度（节）
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;
    p1 = strstr(p, ",");
	if(!p1)
		return 0;
    memset(buff, 0, sizeof(buff));
    strncpy(buff, p, p1 - p);
    sample->speed = atof(buff) * 1.852;

    // 方位角
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;

    // UTC日期
    p = strstr(p, ",");
	if(!p || ++p >= pe)
		return 0;
	p1 = strstr(p, ",");
	if(!p1 || p1 < p + 6)
		return 0;
    // 2位日期
    memset(buff, 0, sizeof(buff));
    strncpy(buff, p, 2);
    p += 2;
    sample->sysTime.day = atoi(buff);
    // 2位月份
    memset(buff, 0, sizeof(buff));
    strncpy(buff, p, 2);
    p += 2;
    sample->sysTime.month = atoi(buff);
    // 2位年份
    memset(buff, 0, sizeof(buff));
    strncpy(buff, p, 2);
    p += 2;
    sample->sysTime.year = atoi(buff);
	if(sample->sysTime.month < 1 || sample->sysTime.month > 12 || sample->sysTime.day < 1 || sample->sysTime.day > 31)
		return 0;	

    // 处理时差
    GPS_ProcessTimeLag(&sample->sysTime, dcBuff.configData.timeLag);

    return 1;
}

uint8_t parse_frame(uint8_t *bufIdx, char *message, data_dtu_t *sample)
{
	uint8_t ret = 0;
    S_RTC_TIME_DATA_T sRTC;
	
    if(strncmp(message, "$GPGGA", 6) == 0)
	{
//		printf("\n%s\n", message);
		*bufIdx = 1 - *bufIdx;
	}
    else if(strncmp(message, "$GPRMC", 6) == 0)
	{
		printf("\n%s\n", message);

		// 获取当前时间
		RTC_GetDateAndTime(&sRTC);
		// 记录GPS上次数据时间
		DTU_gpsTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
				sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);

		parse_gga(DTU_gpsData[1 - *bufIdx], sample);
        ret = parse_rmc(message, sample);
		if(!ret)
			sample->posState = 0;
	}

	return ret;
}

void DTU_CheckGPS()
{
	uint32_t time;
    S_RTC_TIME_DATA_T sRTC;

	if(IS_VCC_GPS_ON())
	{
		// 获取当前时间
		RTC_GetDateAndTime(&sRTC);
		// 计算自上次gps定位以来的时间
		time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
				sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
		if(!Wakeup_Sleeping && time > DTU_gpsTime + 30 && (GPS_Waiting || dcBuff.configDisplay.op_SEND_GPS_DATA))
		{
			// 如果是第一次，或者曾经有输出了，则闪断计数
			if(GPS_BOD_COUNT == 599)
				GPS_BOD_COUNT = 0;
			else
				GPS_BOD_COUNT++;			
			printf("\nGPS_BOD_COUNT: %d\n", GPS_BOD_COUNT);
			
			printf("\n*** Restart GPS module ***\n");
			DTU_EnableGPS();
			DTU_gpsTime = time;
		}
	}
}
