/*************************** (C) COPYRIGHT 2017 CXHY ****************************
 * 文件名  ：gsm_uart.c
 * 描  述  ：GSM控制串口（串口2）
 * 版  本  ：V1.0
 * 作  者  ：XuZhongPing
 * 日  期  ：2017/04/26 
*********************************************************************************/
#include "netwer_appcall.h"
#include "timer.h"
#include "data_typedef.h"
#include "tcp_protocol.h"
#include "message.h"
#include "gsm_uart_conf.h"
#include "ec200x.h"
#include "at_proc.h"

uint8_t isSendDataMark = 0;								//是否有数据要发送标志
uint8_t isReceiveDataMark = 0;						//是否有接收到数据标志
uint8_t dataSendSuccessMark = 0;					//数据发送成功标志
uint8_t dataSendFailureMark = 0;					//数据发送失败标志
uint8_t dataSendOkButNoAckMark = 0;				//数据发送成功但没有收运应答

uint16_t sendDataLen = 0;									//发送的数据长度


void show_hex(uint8_t num[], uint8_t n)
{
    uint8_t i;
		printf("\r\n");
    for(i=0; i<n; i++)
		{
      printf("%02X ",num[i]);
		}
		printf("\r\n");
}

/*
***********************************************************************
*	函 数 名: ChackIccidNumber
*	功能说明: 判断当前的ICCID号和之前的是否相等
*	形    参：
*	返 回 值: 不相等返回1，相等返回0
***********************************************************************
*/
uint8_t ChackIccidNumber(char* preId, char* curId)
{
	uint8_t i;
	
	for(i = 0; i < 20; i++)
	{
		if(preId[i] != curId[i]) return 1;
	}
	return 0;
}


static uint8_t delaySendMark = 0;								//延时发送标志
/*
***********************************************************************
*	函 数 名: NetReconnectDelaySendHandler
*	功能说明: 网络重连后数据延时发送处理
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void NetReconnectDelaySendHandler(void)
{
	uint8_t i;
	static uint8_t currentStatus = 0x00;
	static uint8_t nextStatus = 0x00;
	
	static uint8_t initRandomSendTimerFalg = 0;						//初始化随机延迟发送时间标志
	static uint32_t timeSeed = 0;													//生成随机延时时间的种子
	static char preICCID[24] = {0};												//之前的ICCID号
	static uint8_t preNetworkConnectionCount = 0;					//上一次的建立网络连接次数
	static uint8_t reuploadICCID = 0;											//重新上传ICCID号
	uint8_t msgBufSurplus = 0;														//消息队列还剩余空间
	
	static timer waitingTimer;														//等待时间
	static timer delayRandomSendTimer;										//延迟随机发送时间
	
	static uint8_t timer_ok = 0;
	if(timer_ok == 0)
	{
		timer_ok = 1;
		
		timer_set(&waitingTimer, CLOCK_SECOND*60*2);
		timer_set(&delayRandomSendTimer, CLOCK_SECOND*1);
	}
	
	if(gsm_msg.Running == 1)										//网络已经建立
	{
		if(initRandomSendTimerFalg == 0)					//初始化随机延迟发送时间
		{
			initRandomSendTimerFalg = 1;
			
			timeSeed = (uint32_t)(gsm_msg.IMEI_HEX[4] << 24) | (gsm_msg.IMEI_HEX[5] << 16) | (gsm_msg.IMEI_HEX[6] << 8) | gsm_msg.IMEI_HEX[7];
			printf("\r\ntimeSeed = %llu\r\n", (uint64_t)timeSeed);
			srand(timeSeed);
			delayRandomTime = rand()%60;																							//得到随机延迟发送时间
			printf("\r\ndelayRandomTime = %d\r\n", delayRandomTime);

			timer_set(&delayRandomSendTimer, CLOCK_SECOND*delayRandomTime);
			
			memset(preICCID, 0, 24);
			memcpy(preICCID, gsm_msg.ICCID, 20);																			//取出当前的ICCID号
			printf("\r\n延时发送时间初始化成功！\r\n");
		}
	}
	
	//当物联网卡的ICCID号有发生变化，则重新上传
	if(reuploadICCID == 1)					
	{
		msgBufSurplus = GetMessageRemainingSpace(MSG_FIFO_PROTOCOL);
		if(msgBufSurplus >= 5)				//发送消息队列有空间时才发送，不然会发送不成功
		{
			printf("\r\n当前队列状态：%d\r\n", msgBufSurplus);
			reuploadICCID = 0;
			
			sendMsg.msgType = 1003;
			MessageSend(MSG_FIFO_PROTOCOL, sendMsg);
		}
	}
	
	currentStatus = nextStatus;
	switch(currentStatus)
	{
		case 0x00:		//初始状态
			//判断当前有没有出现网络重连
			if(preNetworkConnectionCount != networkConnectionCount)
			{
				preNetworkConnectionCount = networkConnectionCount;
				
				if(networkConnectionCount != 1)			//不是首次建立网络，标志当前有网络重连
				{
					printf("\r\n出现了网络重连！\r\n");
					delaySendMark = 1;								//标志当前网络出现了网络重连
					
					if(ChackIccidNumber(preICCID, gsm_msg.ICCID))
					{
						printf("\r\nICCID号发生改变！\r\n");
						reuploadICCID = 1;

						printf("\r\n当前队列状态：%d\r\n", GetMessageRemainingSpace(MSG_FIFO_PROTOCOL));
						
						memcpy(preICCID, gsm_msg.ICCID, 20);
					}
					
					timer_restart(&delayRandomSendTimer);
					timer_restart(&waitingTimer);
					nextStatus = 0x01;
				}
			}
			break;
			
		case 0x01:		//有断线重新连接网络，则延迟随机数定时后再发送数据
			if(timer_expired(&delayRandomSendTimer))
			{
				printf("\r\n等待延时发送时间到！\r\n");
				delaySendMark = 0;
				nextStatus = 0x00;
				break;
			}
			
			if(timer_expired(&waitingTimer))
			{
				printf("\r\n延时发送等待超时！\r\n");
				delaySendMark = 0;
				nextStatus = 0x00;
				break;
			}
			break;
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: SendNetworkData
*	功能说明: 发送网络数据
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void SendNetworkData(uint8_t *sendBuf, uint16_t dataLength)
{
	sendDataLen = dataLength;
// 	memcpy(GPRS_TX_BUF, sendBuf, GPRS_sendDataLength);
	isSendDataMark = 1;
}

/*
***********************************************************************
*	函 数 名: DataUploadPollingTask
*	功能说明: 数据上传轮询任务
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void DataUploadPollingTask(void)
{
	static uint8_t currentStatus = 0x00;
	static uint8_t nextStatus = 0x00;
	
	uint8_t sendFailureFlag = 0;
	
	static MESSAGE *pMsg;
	static uint16_t dataBufLength = 0;
	
	static uint32_t nowTime = 0;													//当前发送指令的时间
	static uint32_t preSendTime_1001 = 0;									//前一次发送指令的时间
	static uint32_t preSendTime_6004 = 0;
	uint16_t repeatCmdIntervalTime = 600;									//重复指令间隔时间（单位为0.1秒）
	
	static timer uploadIntervalTime;											//心跳上传时间间隔限制（限制同一时间内重复上传心跳包）
	static timer responseTimeout;													//应答超时时间间隔
	static timer sendTimeout;															//发送超时时间间隔
	
	static uint8_t timer_ok = 0;
	if(timer_ok == 0)
	{
		timer_ok = 1;
		
		timer_set(&uploadIntervalTime, CLOCK_SECOND*3);  			
		timer_set(&responseTimeout, CLOCK_SECOND*3);
		timer_set(&sendTimeout, CLOCK_SECOND*120);
	}
	
	NetReconnectDelaySendHandler();
	
	currentStatus = nextStatus;
	switch(currentStatus)
	{
		case 0x00:
			if(ConnectionStatus == ONLINE)
			{
				if(delaySendMark == 0)		//是否要延迟发送
				{
					pMsg = MessageGet(MSG_FIFO_PROTOCOL);					//读取消息对列
					if(pMsg)		//如果消息对列中有消息则进行数据发送
					{
						sendOrderCode = pMsg->msgType;										//取得发送的协议码
						
						nowTime = time_value;															//取出当前发送指令的时间
						if(sendOrderCode == 1001)													//当前发送的是1001指令
						{
							if((preSendTime_1001 != 0) && ((nowTime - preSendTime_1001) < repeatCmdIntervalTime))
							{
								printf("\r\n重复1001指令取消发送！\r\n");
								nextStatus = 0x00;
								break;
							}
							preSendTime_1001 = nowTime;
						}
						
						if(sendOrderCode == 6004)													//当前发送的是6004指令
						{
							if((preSendTime_6004 != 0) && ((nowTime - preSendTime_6004) < repeatCmdIntervalTime))
							{
								printf("\r\n重复6004指令取消发送！\r\n");
								nextStatus = 0x00;
								break;
							}
							preSendTime_6004 = nowTime;
						}
						
						printf("\r\nTCP Sending data......\r\n");
						nextStatus = 0x01;								//跳转到发送数据
						break;
					}
				}
			}
			break;
			
		case 0x01:		
			dataBufLength = SendProtocolPackaging(sendOrderCode);	//通过消息的类型进行相应协议打包
			SendNetworkData(GPRS_DATA_BUF, dataBufLength);
			
			isReceiveDataMark = 0;
			dataSendSuccessMark = 0;
			dataSendFailureMark = 0;
			timer_restart(&sendTimeout);
			nextStatus = 0x02;
			break;
			
		case 0x02:		//等待发送完成
			if(isReceiveDataMark == 1)
			{
				isReceiveDataMark = 0;
				printf("\r\n数据发送成功！\r\n");
// 				show_hex(GPRS_RECV_DATA_BUF, receiveDataLen);
// 				printf("\r\ndata=%s\r\n", GPRS_DATA_BUF);
// 				TCP_Protocol(GPRS_RECV_DATA_BUF, receiveDataLen);				
// 				memset(GPRS_RECV_DATA_BUF, 0x00, 1024);
				nextStatus = 0x00;
				break;
			}
			
			//数据已发送到服务器，但没有收到应答
			if(dataSendOkButNoAckMark == 1)
			{
				printf("\r\n数据已发送，但没有应答！\r\n");
				dataSendOkButNoAckMark = 0;
				
				nextStatus = 0x00;
				break;
			}
			
			//发送失败
			if(dataSendFailureMark == 1)
			{
				dataSendFailureMark = 0;
				printf("\r\n数据发送失败！\r\n");
				sendFailureFlag = 1;
			}
			
			//发送超时
			if(timer_expired(&sendTimeout))						//超时还未接收到应答
			{
				printf("\r\n发送超时！\r\n");
				sendFailureFlag = 1;
			}
			
			if(sendFailureFlag == 1)
			{
				printf("\r\nTCP send data failure!\r\n");
				nextStatus = 0x00;		
				break;
			}
			
			break;
			
		default:
			break;
	}
}

/******************** (C) COPYRIGHT 2017 CXHY *****END OF FILE*******************/ 

