#include "IEC101.h"
#include "usart.h"
#include "timer.h"


uint8_t flgDIR, flgPRM, flgFCB = 0, flgFCV, flgACD;

uint8_t LINK_ADDRESS = 0x01; //定义链路地址
uint8_t ProtocolRxBuffer[64] = {0}; //存储主站发过来的命令
uint8_t TxBuffer[64] = {0};
uint8_t TxAppBuffer[64] = {0};
uint8_t RxControlField = 0; //接收到数据中的控制域
uint8_t RxDIR, RxPRM, RxFCB, RxFCV, RxFunctionCode;
uint8_t LastFCB;
uint8_t TxDIR, TxPRM, TxFCB, TxFCV, TxFunctionCode;
TimeStructure NowTimeStruct;
uint16_t LastType;

uint8_t Info[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //开关量数量 0/1/2 跌落 3跌落状态 4温度状态 5 欠压 6/7/8/9 漏保
uint8_t InfoTemp[8]; //温度
uint8_t DataFromGPRSBuffer[128];
uint8_t moduleMaskEn; // 模块故障MASK
/*
 ****************************************************************************************************
 * 功能描述：初始化链路层参数
 * 输入参数：
 * 返回参数：
 * 说    明：
 ****************************************************************************************************
 */
void LinkInit(void) {
	RxDIR = M2S_DIR; //固定值，从站接收到主站的数据时DIR为0，
	RxPRM = 0; //非固定值
	TxPRM = 0; //非固定值
	RxFCB = 0;
	RxFCV = 0;
	TxDIR = S2M_DIR; //固定值从站发出数据时DIR为1
}

//此函数用于CheckSum函数之后，即已经判断为有效帧后再校验地址是否正确
//返回SUCCESS地址正确，返回ERROR地址不正确
uint8_t CheckLinkAddress(uint8_t* pBuffer) {
	uint16_t LinkAddress = 0;

	if (pBuffer[0] == 0x10) {
		LinkAddress = (uint16_t)pBuffer[2];
	}
	else if (pBuffer[0] == 0x68) {
		LinkAddress = (uint16_t)pBuffer[5];
	}
	else {
		return ERROR; //链路地址不正确
	}

	if (LinkAddress == LINK_ADDRESS) {
		return SUCCESS; //链路地址正确
	}
	else {
		return ERROR; //链路地址不正确
	}
}

/*
 ****************************************************************************************************
 * 功能描述：
 * 输入参数：
 * 返回参数：校验和的值
 * 说    明：
 ****************************************************************************************************
 */
uint8_t GetCheckSum(uint8_t* pBuffer) {
	uint8_t i;
	uint8_t TempSum = 0;
	uint8_t DataLength = 0;

	if (pBuffer[0] == 0x10)
		TempSum = pBuffer[1] + pBuffer[2];

	else if (pBuffer[0] == 0x68) {
		DataLength = pBuffer[1]; //获取可变帧数据长度

		for (i = 0; i < DataLength; i++)
			TempSum += pBuffer[i + 4];
	}
	else
		TempSum = 0;

	return TempSum;
	//////////////////////////////////////////////////////////////////////////
}

/*
 ****************************************************************************************************
 * 功能描述：
 * 输入参数：
 * 返回参数：
 * 说    明：
 ****************************************************************************************************
 */
uint8_t CheckError(uint8_t* pBuffer) {
	uint8_t Length1, Length2;

	if ((pBuffer[0] == 0x68) && (pBuffer[3] == 0x68)) {
		//可变帧长
		Length1 = pBuffer[1];
		Length2 = pBuffer[2];

		if (Length1 != Length2)
			return 0; //两个长度字节不相等,返回错误
		else
			//校验和相等且最后一个字节为0x16
			if ((GetCheckSum(pBuffer) == pBuffer[4 + Length1]) && (pBuffer[5 + Length1] == 0x16)) {
			RxControlField = pBuffer[4]; //帧校验成功后取得控制域数据
			return VARIABLE_DATA;
		}
		else
			return 0;
	}

	/* 固定帧长第一字节和最后字节校验 */
	else if ((pBuffer[0] == 0x10) && (pBuffer[5] == 0x16)) {
		//检验和是否相等
		if (GetCheckSum(pBuffer) == pBuffer[3]) {
			RxControlField = pBuffer[1]; //取得控制域数据
			return STABLE_DATA;
		}
		else
			return 0;
	}
	else
		//无效帧，丢弃
		return 0;
}

/*
 ****************************************************************************************************
 * 功能描述：
 * 输入参数：
 * 返回参数：
 * 说    明：
 ****************************************************************************************************
 */
uint8_t Protocol101_RxLink(void) {
	RxDIR = (RxControlField >> 7) & 0x01; //取得DIR位
	RxPRM = (RxControlField >> 6) & 0x01; //取得PRM位
	RxFCB = (RxControlField >> 5) & 0x01; //取得FCB位
	RxFCV = (RxControlField >> 4) & 0x01; //取得FCV位
	RxFunctionCode = RxControlField & 0x0F; //取得功能码

	if ((RxDIR == M2S_DIR) && (RxPRM == 1))
		return SUCCESS; //接收标志位判断
	else {
		// newFrame = 1;
		LastFCB = RxFCB;
		return ERROR;
	}
}

/*
 ****************************************************************************************************
 * 功能描述：
 * 输入参数：
 * 返回参数：
 * 说    明：
 ****************************************************************************************************
 */
uint8_t SetTxControlField(uint8_t PRM, uint8_t FCB, uint8_t FCV, uint8_t FuncCode) {
	uint8_t Temp = 0;
	Temp |= ((S2M_DIR & 0x01) << 7);
	Temp |= ((PRM & 0x01) << 6);
	Temp |= ((FCB & 0x01) << 5);
	Temp |= ((FCV & 0x01) << 4);
	Temp |= (FuncCode & 0x0F);
	return Temp;
}

void SendStableData(uint8_t PRM, uint8_t FCB, uint8_t FCV, uint8_t FuncCode) {
	uint8_t TxCrtlField = 0;
	uint8_t CheckSum = 0;
	uint8_t FrameData[6] = {0x00};
	TxCrtlField = SetTxControlField(PRM, FCB, FCV, FuncCode);
	FrameData[0] = 0x10;
	FrameData[1] = TxCrtlField;
	FrameData[2] = LINK_ADDRESS;
	CheckSum = FrameData[1] + FrameData[2];
	FrameData[3] = CheckSum;
	FrameData[4] = 0x16;
	SendData(FrameData, 5); //串口发送
}

#if 0
void SendVariableData( uint8_t PRM, uint8_t FCB, uint8_t FCV, uint8_t FuncCode, uint8_t* pBuffer )
{
	ASDU_DataStructure ASDU_DataStruct;
	ASDU_DataStruct.TypeID = 100;
	ASDU_DataStruct.Qualifier = 1;
	ASDU_DataStruct.Reason = 7;
	ASDU_DataStruct.ASDU_Address = LINK_ADDRESS;
	ASDU_DataStruct.InfoAddress1 = 0x0000;
	ASDU_DataStruct.InfoData1 = 0X14;
	ASDU_Init( ASDU_DataStruct, TxAppBuffer );
}
#endif

#if 0
/*
 ****************************************************************************************************
 * 功能描述：
 * 输入参数：TxAppLength:应用层数据不为0，指的是ASDU的长度，发送的是可变帧长数据
 *           pTxBuffer:链路层数据缓存，最后通过物理通道发送出去
 *           pTxAppBuffer:应用层数据缓冲区，会在应用层将数据转移到pTxBuffer中
 * 返回参数：无
 * 说    明：
 ****************************************************************************************************
 */
void Protocol101_TxLink( uint8_t TxAppLength, uint8_t* pTxBuffer, uint8_t* pTxAppBuffer )
{
	uint8_t i;
	uint8_t TempSum = 0;
	uint8_t TxCounter = 0;

	//如果应用层数据不为0，则表示发送的是可变帧长数据
	if ( TxAppLength != 0 ) {
		pTxBuffer[0] = 0x68;
		pTxBuffer[1] = TxAppLength + 3;
		pTxBuffer[2] = TxAppLength + 3;
		pTxBuffer[3] = 0x68;
		pTxBuffer[4] = SetTxControlField();
		TempSum += pTxBuffer[4];
		pTxBuffer[5] = LINK_ADDRESS & 0xff;
		TempSum += pTxBuffer[5];
		pTxBuffer[6] = ( LINK_ADDRESS >> 8 ) & 0xff;
		TempSum += pTxBuffer[6];
		TxCounter = 7;

		for ( i = 0; i <= TxAppLength - 1; i++ ) {
			pTxBuffer[TxCounter] = pTxAppBuffer[i];
			TempSum += pTxBuffer[TxCounter++];
		}

		TempSum &= 0xff;
		pTxBuffer[TxCounter++] = TempSum;
		pTxBuffer[TxCounter++] = 0x16;

	} else {
		pTxBuffer[0] = 0x10;
		pTxBuffer[1] = GetTxControlField();
		pTxBuffer[2] = LINK_ADDRESS & 0xff;
		pTxBuffer[3] = ( LINK_ADDRESS >> 8 ) & 0xff;

		//计算校验和
		for ( i = 1; i < 4; i++ )
			TempSum += pTxBuffer[i];

		pTxBuffer[4] = TempSum;
		pTxBuffer[5] = 0x16;
		TxCounter = 6;
	}

	SendData( pTxBuffer, TxCounter ); //串口发送
}

#endif
uint8_t ASDU_Init(ASDU_DataStructure* ASDU_Struct, uint8_t NumOfInfo, uint8_t* pBuffer) {
	uint8_t i = 0;
	uint8_t ASDU_Length = 0;
	uint8_t ASDU_AddressLow = 0;
	uint8_t ASDU_AddressHigh = 0;
	ASDU_AddressLow = LINK_ADDRESS;
	ASDU_AddressHigh = (LINK_ADDRESS >> 8);
	pBuffer[0] = ASDU_Struct->TypeID;
	pBuffer[1] = ASDU_Struct->Qualifier;
	pBuffer[2] = ASDU_Struct->Reason & 0xff;
	pBuffer[3] = ASDU_Struct->Reason >> 8;
	pBuffer[4] = ASDU_Struct->ASDU_Address & 0xff;
	pBuffer[5] = ASDU_Struct->ASDU_Address >> 8;
	pBuffer[6] = ASDU_Struct->InfoAddress & 0xFF;
	pBuffer[7] = ASDU_Struct->InfoAddress >> 8;
	pBuffer[8] = ASDU_Struct->InfoAddress >> 16;
	ASDU_Length = 9;

	while (NumOfInfo--) {
		pBuffer[i + 9] = ASDU_Struct->InfoData[i];
		ASDU_Length += 1;
		i++;
	}

	return ASDU_Length;
}

#if 0
/*
 ****************************************************************************************************
 * 功能描述：
 * 输入参数：
 *
 *

 *
 * 返回参数：
 * 说    明：
 ****************************************************************************************************
 */
void Protocol101_TxApp( uint8_t TypeID, uint8_t Qual, uint8_t SendReason, uint8_t Func, uint8_t TxAppLength )
{
	TxFunctionCode = Func & 0x0F;

	if ( TxAppLength != 0 ) {
		TxAppBuffer[0] = TypeID;                            //类型标识
		TxAppBuffer[1] = Qual;    //信息体数量
		TxAppBuffer[2] = ( SendReason & 0xff );
		TxAppBuffer[3] = LINK_ADDRESS & 0xFF;         //公共地址低位
		TxAppBuffer[4] = ( LINK_ADDRESS >> 8 ) & 0xFF;  //公共地址高位
	}

	Protocol101_TxLink( TxAppLength, TxBuffer, TxAppBuffer );
}

#endif
uint8_t ResponseLinkStatus(void) {
	uint8_t Temp = 11;
	// txAppLength = 0;
	// i = linkState;
	Temp &= 0x0F;

	switch (Temp) {
	case 11:
		TxFCB = 0;
		SendStableData(0, 0, 0, 11);
		// Protocol101_TxApp(0,0,0,0x0b,0);		/* 0x0b 链路状态响应 */
		break;

	case 14:
		// Protocol101_TxApp(0,0,0,0x0e,0);		/* 0x0e 链路服务未工作 */
		break;

	default:
		// Protocol101_TxApp(0,0,0,0x0f,0);		/* 0x0f 链路服务未完成 */
		break;
	}

	// linkState = 0;
	return 1;
}

//主站复位远方链路
uint8_t ResponseResetRemoteLink(void) {
	SendStableData(0, 0, 0, 0);
	return SUCCESS;
}
// 发送1级数据, 掉用函数,查看当前所有的信息
void Data1Frame(){

	
}

// 发送2级数据, 掉用函数,查看当前所有的信息
void Data2Frame(){

	
}
// 激活结束帧
void overFrame(){
	uint8_t data[32];
	data[0] = data[3] = 0x68;
	data[1] = data[2] = 0x0C;
	data[4] = 0x08;
	data[5] = LINK_ADDRESS;
	data[6] = LastType >> 8; 
	data[7] = 0x01;
	data[8] = 0x0A;
	data[9] = 0x00;
	data[10] = data[11] = 0xFF;
	data[12] = data[13] = data[14] = 0x00;
	if(LastType >> 8 == 0x64)
		data[15] = 0x14;// 结束全局召唤
	else if(LastType >> 8 == 0x65)
		data[15] = 0x05;// 结束召唤电度
	uint8_t crc = 0;
	for(uint8_t i = 0; i < 12; i++){
		crc += data[i + 4];
	}
	data[16] = crc;
	data[17] = 0x16;
	SendData(data, 18); //串口发送
}
//确认帧
uint8_t ConfirmFrame(void) {
	uint8_t TxCtrlField = 0;
	uint8_t CheckSum = 0;
	uint8_t FrameData[6] = {0x00};
	TxCtrlField |= ((M2S_DIR & 0x01) << 7);
	TxCtrlField |= ((0 & 0x01) << 6);
	TxCtrlField |= ((1 & 0x01) << 5);
	TxCtrlField |= ((0 & 0x01) << 4);
	TxCtrlField |= (0 & 0x0F);
	FrameData[0] = 0x10;
	FrameData[1] = TxCtrlField;
	FrameData[2] = LINK_ADDRESS;
	CheckSum = FrameData[1] + FrameData[2];
	FrameData[3] = CheckSum;
	FrameData[4] = 0x16;
	SendData(FrameData, 5); //串口发送
}
//确认总召唤
uint8_t ResponseCallAll(void) {
	uint8_t i = 0;
	uint8_t TxCtrlField = 0;
	uint8_t TempCallAllBuf[64] = {0x00};
	uint8_t TempASDU_Buf[32] = {0x00};
	uint8_t ASDU_Length = 0; // ASDU的长度，并非可变帧长中的L值
	// uint8_t SendLength = 0; //可变帧长总长度，最后通过串口发送
	uint8_t CheckSum = 0;
	ASDU_DataStructure ASDU_DataStruct;
	//获取控制域的值
	TxCtrlField |= ((M2S_DIR & 0x01) << 7);
	TxCtrlField |= ((0 & 0x01) << 6);
	TxCtrlField |= ((1 & 0x01) << 5);
	TxCtrlField |= ((0 & 0x01) << 4);
	TxCtrlField |= (8 & 0x0F);
	ASDU_DataStruct.TypeID = 0x64;
	ASDU_DataStruct.Qualifier = 0x01;
	ASDU_DataStruct.Reason = 0x0007;
	ASDU_DataStruct.ASDU_Address = 0xffff;
	ASDU_DataStruct.InfoAddress = 0x000000;
	ASDU_DataStruct.InfoData[0] = 0x14;
	ASDU_Length = ASDU_Init(&ASDU_DataStruct, 1,
							TempASDU_Buf); //填充ASDU数据并返回ASDU的长度（此值并非L）
	TempCallAllBuf[0] = 0x68;
	TempCallAllBuf[1] = ASDU_Length + 2;
	TempCallAllBuf[2] = ASDU_Length + 2;
	TempCallAllBuf[3] = 0x68;
	TempCallAllBuf[4] = TxCtrlField;
	TempCallAllBuf[5] = LINK_ADDRESS;

	for (i = 0; i < ASDU_Length; i++)
		TempCallAllBuf[i + 6] = TempASDU_Buf[i];

	for (i = 0; i < (ASDU_Length + 2); i++)
		CheckSum += TempCallAllBuf[i + 4]; //计算校验和

	TempCallAllBuf[ASDU_Length + 6] = CheckSum;
	TempCallAllBuf[ASDU_Length + 7] = 0x16;
	SendData(TempCallAllBuf, (ASDU_Length + 8));
	return 1;
}

void UpdateDataForCallAll(void) {
	uint8_t i = 0;
	uint8_t TxCtrlField = 0;
	uint8_t TempCallAllBuf[64] = {0x00};
	uint8_t TempASDU_Buf[32] = {0x00};
	uint8_t ASDU_Length = 0; // ASDU的长度，并非可变帧长中的L值
	// uint8_t SendLength = 0; //可变帧长总长度，最后通过串口发送
	uint8_t CheckSum = 0;
	ASDU_DataStructure ASDU_DataStruct;
	//获取控制域的值
	TxCtrlField = SetTxControlField(0, 0, 0, 0x00);
	ASDU_DataStruct.TypeID = 0x1; //无时标的单点信息
	ASDU_DataStruct.Qualifier = 0x8a; //单地址，6个数据
	ASDU_DataStruct.Reason = 0x14; //响应总召唤
	ASDU_DataStruct.ASDU_Address = LINK_ADDRESS;
	ASDU_DataStruct.InfoAddress = 0x0001;

	if (moduleMaskEn == 0) { //非屏蔽状态及时发送状态

		ASDU_DataStruct.InfoData[0] = Info[0];
		ASDU_DataStruct.InfoData[1] = Info[1];
		ASDU_DataStruct.InfoData[2] = Info[2];
		ASDU_DataStruct.InfoData[3] = Info[3];
		ASDU_DataStruct.InfoData[4] = Info[4];
		ASDU_DataStruct.InfoData[5] = Info[5];
		ASDU_DataStruct.InfoData[6] = Info[6]; //漏保1
		ASDU_DataStruct.InfoData[7] = Info[7]; //漏保2
		ASDU_DataStruct.InfoData[8] = Info[8]; //漏保3
		ASDU_DataStruct.InfoData[9] = Info[9]; //漏保4
	}
	else {
		ASDU_DataStruct.InfoData[0] = 0; //屏蔽状态都按正常处理
		ASDU_DataStruct.InfoData[1] = 0; //屏蔽状态都按正常处理
		ASDU_DataStruct.InfoData[2] = 0; //屏蔽状态都按正常处理
		ASDU_DataStruct.InfoData[3] = 0; //屏蔽状态都按正常处理
		ASDU_DataStruct.InfoData[4] = 0; //屏蔽状态都按正常处理
		ASDU_DataStruct.InfoData[5] = 0; //屏蔽状态都按正常处理
		ASDU_DataStruct.InfoData[6] = 0; //漏保1
		ASDU_DataStruct.InfoData[7] = 0; //漏保2
		ASDU_DataStruct.InfoData[8] = 0; //漏保3
		ASDU_DataStruct.InfoData[9] = 0; //漏保4
	}

	TxCtrlField = SetTxControlField(0, 0, 0, 0x00);
	ASDU_Length = ASDU_Init(&ASDU_DataStruct, 10,
							TempASDU_Buf); //填充ASDU数据并返回ASDU的长度（此值并非L）
	TempCallAllBuf[0] = 0x68;
	TempCallAllBuf[1] = ASDU_Length + 3;
	TempCallAllBuf[2] = ASDU_Length + 3;
	TempCallAllBuf[3] = 0x68;
	TempCallAllBuf[4] = TxCtrlField;
	TempCallAllBuf[5] = LINK_ADDRESS & 0xFF;
	TempCallAllBuf[6] = LINK_ADDRESS >> 8;

	for (i = 0; i < ASDU_Length; i++)
		TempCallAllBuf[i + 7] = TempASDU_Buf[i];

	for (i = 0; i < (ASDU_Length + 3); i++)
		CheckSum += TempCallAllBuf[i + 4]; //计算校验和

	TempCallAllBuf[ASDU_Length + 7] = CheckSum;
	TempCallAllBuf[ASDU_Length + 8] = 0x16;
	SendData(TempCallAllBuf, (ASDU_Length + 9));
}

///遥测1:温度
void UpdateTempForCallAll(void) {
	uint8_t i = 0;
	uint8_t TempCallAllBuf[64] = {0x00};
	uint8_t TxCtrlField = 0;
	ASDU_DataStructure ASDU_DataStruct;
	uint8_t TempASDU_Buf[32] = {0x00};
	uint8_t ASDU_Length = 0; // ASDU的长度，并非可变帧长中的L值
	uint8_t CheckSum = 0;
	//获取控制域的值
	TxCtrlField = SetTxControlField(0, 0, 0, 0x00);
	ASDU_DataStruct.TypeID = 0x15; //类型标示，不带品质因数的遥测量
	ASDU_DataStruct.Qualifier = 0x83; //品质因数，单地址3个数据
	ASDU_DataStruct.Reason = 0x14; //响应总召
	ASDU_DataStruct.ASDU_Address = LINK_ADDRESS;
	ASDU_DataStruct.InfoAddress = 0x0001;

	if (moduleMaskEn == 0) { //非屏蔽状态及时发送状态
		ASDU_DataStruct.InfoData[0] = InfoTemp[0];
		ASDU_DataStruct.InfoData[1] = InfoTemp[1];
		ASDU_DataStruct.InfoData[2] = InfoTemp[2];
	}
	else {
		ASDU_DataStruct.InfoData[0] = 20; //屏蔽状态都按正常处理
		ASDU_DataStruct.InfoData[1] = 20; //屏蔽状态都按正常处理
		ASDU_DataStruct.InfoData[2] = 20; //屏蔽状态都按正常处理
	}

	TxCtrlField = SetTxControlField(0, 0, 0, 0x00);
	ASDU_Length = ASDU_Init(&ASDU_DataStruct, 3,
							TempASDU_Buf); //填充ASDU数据并返回ASDU的长度（此值并非L）
	TempCallAllBuf[0] = 0x68;
	TempCallAllBuf[1] = ASDU_Length + 3;
	TempCallAllBuf[2] = ASDU_Length + 3;
	TempCallAllBuf[3] = 0x68;
	TempCallAllBuf[4] = TxCtrlField;
	TempCallAllBuf[5] = LINK_ADDRESS & 0xFF;
	TempCallAllBuf[6] = LINK_ADDRESS >> 8;

	for (i = 0; i < ASDU_Length; i++)
		TempCallAllBuf[i + 7] = TempASDU_Buf[i];

	for (i = 0; i < (ASDU_Length + 3); i++)
		CheckSum += TempCallAllBuf[i + 4]; //计算校验和

	TempCallAllBuf[ASDU_Length + 7] = CheckSum;
	TempCallAllBuf[ASDU_Length + 8] = 0x16;
	SendData(TempCallAllBuf, (ASDU_Length + 9));
}

void EndOfCallAll(void) {
	uint8_t i = 0;
	uint8_t TxCtrlField = 0;
	uint8_t TempCallAllBuf[64] = {0x00};
	uint8_t TempASDU_Buf[32] = {0x00};
	uint8_t ASDU_Length = 0; // ASDU的长度，并非可变帧长中的L值
	// uint8_t SendLength = 0; //可变帧长总长度，最后通过串口发送
	uint8_t CheckSum = 0;
	ASDU_DataStructure ASDU_DataStruct;
	//获取控制域的值
	TxCtrlField = SetTxControlField(0, 0, 0, 0x00);
	ASDU_DataStruct.TypeID = 0x64;
	ASDU_DataStruct.Qualifier = 0x01;
	ASDU_DataStruct.Reason = 0x0A;
	ASDU_DataStruct.ASDU_Address = LINK_ADDRESS;
	ASDU_DataStruct.InfoAddress = 0x0000;
	ASDU_DataStruct.InfoData[0] = 0x14;
	ASDU_Length = ASDU_Init(&ASDU_DataStruct, 1,
							TempASDU_Buf); //填充ASDU数据并返回ASDU的长度（此值并非L）
	TempCallAllBuf[0] = 0x68;
	TempCallAllBuf[1] = ASDU_Length + 3;
	TempCallAllBuf[2] = ASDU_Length + 3;
	TempCallAllBuf[3] = 0x68;
	TempCallAllBuf[4] = TxCtrlField;
	TempCallAllBuf[5] = LINK_ADDRESS & 0xFF;
	TempCallAllBuf[6] = LINK_ADDRESS >> 8;

	for (i = 0; i < ASDU_Length; i++)
		TempCallAllBuf[i + 7] = TempASDU_Buf[i];

	for (i = 0; i < (ASDU_Length + 3); i++)
		CheckSum += TempCallAllBuf[i + 4]; //计算校验和

	TempCallAllBuf[ASDU_Length + 7] = CheckSum;
	TempCallAllBuf[ASDU_Length + 8] = 0x16;
	SendData(TempCallAllBuf, (ASDU_Length + 9));
}

void GetClockFromServer(TimeStructure* TimeStruct, uint8_t* pBuffer) {
	uint16_t Temp = 0;
	Temp = pBuffer[15] << 8;
	Temp += pBuffer[14];
	TimeStruct->MilliSec = (Temp % 1000);
	TimeStruct->Sec = (uint8_t)(Temp / 1000);
	TimeStruct->Min = pBuffer[16];
	TimeStruct->Hour = pBuffer[17];
	TimeStruct->Day = pBuffer[18];
	TimeStruct->Month = pBuffer[19];
	TimeStruct->Year = pBuffer[20];
}

// InfoAdress -- 上单元编号：1~6
// Info -- 上单元状态：0-正常；1-跌落
//*Time -- 时间结构体

void ChangeUpdate(uint16_t InfoAdress, uint8_t Info, TimeStructure* Time) {
	uint8_t i;
	uint8_t CheckSum = 0;
	uint8_t InfoArray[32] = {0x00};
	// static uint8_t PreInfo = 0;
	// static uint16_t PreInfoAdress = 0;
	// if ((PreInfoAdress != InfoAdress) || (PreInfo != Info))
	//{
	InfoArray[0] = 0x68;
	InfoArray[1] = 0x12;
	InfoArray[2] = 0x12;
	InfoArray[3] = 0x68;
	InfoArray[4] = SetTxControlField(1, 0, 0, 3);
	InfoArray[5] = LINK_ADDRESS & 0xFF;
	InfoArray[6] = LINK_ADDRESS >> 8;
	InfoArray[7] = 0x1E; // 0x1E==30,带CP56Time2a时标的单点信息
	InfoArray[8] = 0x01;
	InfoArray[9] = 0x03; //传送原因:突发
	InfoArray[10] = LINK_ADDRESS & 0xFF;
	InfoArray[11] = LINK_ADDRESS >> 8;
	InfoArray[12] = InfoAdress & 0xFF;
	InfoArray[13] = InfoAdress >> 8;
	InfoArray[14] = Info;
	InfoArray[15] = (uint8_t)((Time->Sec * 1000) + Time->MilliSec);
	InfoArray[16] = ((Time->Sec * 1000) + Time->MilliSec) >> 8;
	InfoArray[17] = Time->Min;
	InfoArray[18] = Time->Hour;
	InfoArray[19] = Time->Day;
	InfoArray[20] = Time->Month;
	InfoArray[21] = Time->Year;

	for (i = 0; i < 0x12; i++)
		CheckSum += InfoArray[i + 4];

	InfoArray[22] = CheckSum;
	InfoArray[23] = 0x16;
	//   PreInfoAdress = InfoAdress;
	//   PreInfo = Info;
	SendData(InfoArray, 24);
	// }
}

void TempChangeUpdate(uint16_t InfoAdress, uint8_t Info, TimeStructure* Time) {
	uint8_t i;
	uint8_t CheckSum = 0;
	uint8_t InfoArray[32] = {0x00};
	static uint8_t PreInfo = 0;
	static uint16_t PreInfoAdress = 0;

	if ((PreInfoAdress != InfoAdress) || (PreInfo != Info)) {
		InfoArray[0] = 0x68;
		InfoArray[1] = 0x12;
		InfoArray[2] = 0x12;
		InfoArray[3] = 0x68;
		InfoArray[4] = SetTxControlField(1, 0, 0, 3);
		InfoArray[5] = LINK_ADDRESS & 0xFF;
		InfoArray[6] = LINK_ADDRESS >> 8;
		InfoArray[7] = 0x23; // 0x23==35,带CP56Time2a时标的测量标量值
		InfoArray[8] = 0x01;
		InfoArray[9] = 0x03; //传送原因:突发
		InfoArray[10] = LINK_ADDRESS & 0xFF;
		InfoArray[11] = LINK_ADDRESS >> 8;
		InfoArray[12] = InfoAdress & 0xFF;
		InfoArray[13] = InfoAdress >> 8;
		InfoArray[14] = Info;
		InfoArray[15] = (uint8_t)((Time->Sec * 1000) + Time->MilliSec);
		InfoArray[16] = ((Time->Sec * 1000) + Time->MilliSec) >> 8;
		InfoArray[17] = Time->Min;
		InfoArray[18] = Time->Hour;
		InfoArray[19] = Time->Day;
		InfoArray[20] = Time->Month;
		InfoArray[21] = Time->Year;

		for (i = 0; i < 0x12; i++)
			CheckSum += InfoArray[i + 4];

		InfoArray[22] = CheckSum;
		InfoArray[23] = 0x16;
		PreInfoAdress = InfoAdress;
		PreInfo = Info;
		SendData(InfoArray, 24);
	}
}

void ResponseTimeSynchronous(void) {
	uint8_t i = 0;
	uint8_t CheckSum = 0;
	uint16_t Temp = 0;
	uint8_t Time[32] = {0x00};
	Temp = NowTimeStruct.Sec * 1000 + NowTimeStruct.MilliSec;
	Time[0] = 0x68;
	Time[1] = 0x11;
	Time[2] = 0x11;
	Time[3] = 0x68;
	Time[4] = SetTxControlField(0, 0, 0, 0);
	Time[5] = LINK_ADDRESS & 0xFF;
	Time[6] = LINK_ADDRESS >> 8;
	Time[7] = 0x67;
	Time[8] = 0x01;
	Time[9] = 0x07; //激活确认
	Time[10] = LINK_ADDRESS & 0xFF;
	Time[11] = LINK_ADDRESS >> 8;
	Time[12] = 0x00;
	Time[13] = 0x00;
	Time[14] = Temp & 0xFF;
	Time[15] = Temp >> 8;
	Time[16] = NowTimeStruct.Min;
	Time[17] = NowTimeStruct.Hour;
	Time[18] = NowTimeStruct.Day;
	Time[19] = NowTimeStruct.Month;
	Time[20] = NowTimeStruct.Year;

	for (i = 0; i < 17; i++)
		CheckSum += Time[i + 4];

	Time[21] = CheckSum;
	Time[22] = 0x16;
	SendData(Time, 23);
}
/*
   更改这个结构，以实现通过GPRS发送一个数据时
   */
uint8_t DataProcess(void) {
	uint8_t TempRxFunctionCode = 0;
	if (CheckLinkAddress(rx_232_Buffer) == SUCCESS) {
		if (CheckError(rx_232_Buffer) == SUCCESS) {
			//数据校验通过，可以开始处理数据
			if (Protocol101_RxLink() == SUCCESS) {
				TempRxFunctionCode = RxFunctionCode;
				switch (TempRxFunctionCode) {
				case 0: //主站复位远方链路
					ResponseResetRemoteLink();
					break;

				case 1: //主站复位用户进程		
					break;

				case 2: //发送\确认链路测试功能
					
					break;

				case 3: //发送\确认用户数据
					if ((rx_232_Buffer[7] == 0x64) && ((rx_232_Buffer[14] == 0x14) || (rx_232_Buffer[15] == 0x14))) {
						ResponseCallAll();
						// SysDelay(1000);
						UpdateDataForCallAll();
	 					UpdateTempForCallAll(); // SysDelay(1000);
						EndOfCallAll();
					}

					if (rx_232_Buffer[7] == 0x67) {
//						//获取时间
//						GetClockFromServer(&NowTimeStruct, ProtocolRxBuffer);
//						//将时间写入时钟芯片
//						Time_Data[0] = NowTimeStruct.Year;
//						Time_Data[1] = NowTimeStruct.Month;
//						Time_Data[2] = NowTimeStruct.Day;
//						Time_Data[3] = NowTimeStruct.Hour;
//						Time_Data[4] = NowTimeStruct.Min;
//						Time_Data[5] = NowTimeStruct.Sec;
//						//回复确认帧
//						ResponseTimeSynchronous();
					}

					break;

				case 4: //发送\无回答用户数据
					break;

				case 9: //主站请求链路状态
					ResponseLinkStatus();
					break;
				case 10://请求1级用户数据
					break;
				case 11://请求2级用户数据
					break;
				}
				
				
				
				
				return SUCCESS;
			}
		}
	}

	return ERROR;
}

//判断属于哪条命令
uint8_t IEC_Protocol(uint8_t* pBuffer) {
	uint8_t pCheckErrorResult;
	pCheckErrorResult = CheckError(pBuffer);
	if (pCheckErrorResult == STABLE_DATA) {
		if (CheckLinkAddress(pBuffer) == 1) {
			if (pBuffer[1] == 0x49) {
				ResponseLinkStatus();
			}
			else if (pBuffer[1] == 0x40) {
				ResponseResetRemoteLink();
			}
			//固定帧
			return STABLE_DATA;
		}
	}
	else if (pCheckErrorResult == VARIABLE_DATA) {
		if (CheckLinkAddress(pBuffer) == 1) {
			if ((pBuffer[7] == 0x64) && (pBuffer[14] == 0x14)) //总召命令
			{
				ResponseCallAll();
			}
			//可变帧长
			return VARIABLE_DATA;
		}
	}
	else {
		return INVALID_DATA;
	}
	return INVALID_DATA;
}
//////////////////////////////////////////
//																			//
//						测试功能函数						   	//
//																		  //
//////////////////////////////////////////
static void test(void const* arg) {
		while (1)		
		{
			while(recv_232_done == 0)  delay_ms(100);// 轮询到232串口接收到数据
			recv_232_done = 0;
			// 先判断是固定帧还是可变帧,并储存控制域->RxControlField
			if(CheckError(rx_232_Buffer) == STABLE_DATA){// 固定帧
				if (CheckLinkAddress(rx_232_Buffer) == SUCCESS) {
					if (Protocol101_RxLink() == SUCCESS) { // 取得功能码RxFunctionCode
						if (rx_232_Buffer[1] == 0x49)// 请求链路
							ResponseLinkStatus();
						else if (rx_232_Buffer[1] == 0x40)// 复位链路
							ResponseResetRemoteLink();
						
						// 请求1级数据 FCB位每次取反,这里没做FCB的取反判断
						else if (rx_232_Buffer[1] == 0x7A || rx_232_Buffer[1] == 0x5A)
						{
							if(LastType == 0x6406)// 回应总召唤
							{
								ResponseCallAll();
								LastType = 0x6407;
							}
							else if(LastType == 0x6407)// 回应已有的1级数据
							{
								uint8_t have_data = 0;//后续调用函数,查看当前所有的数据
								if(have_data)	Data1Frame();//判断是否还有数据
								else	overFrame();
							}	
							
							if(LastType == 0x6506)// 回应电度召唤
							{
								ResponseCallAll();
								LastType = 0x6507;
							}
							else if(LastType == 0x6507)// 回应已有的1级数据
							{
								uint8_t have_data = 0;//后续调用函数,查看当前所有的数据
								if(have_data)	Data2Frame();//判断是否还有数据
								else	overFrame();
							}	
						}
						else if (rx_232_Buffer[1] == 0x7B || rx_232_Buffer[1] == 0x5B)// 请求2级数据 FCB位每次取反
						{
							uint8_t noneData = 0xE5;
							SendData(&noneData,1);
						}
					}//Protocol101_RxLink
				}//CheckLinkAddress
			}//CheckError
			else if(CheckError(rx_232_Buffer) == VARIABLE_DATA)// 可变帧
			{
				if (CheckLinkAddress(rx_232_Buffer) == SUCCESS) {
					if (Protocol101_RxLink() == SUCCESS) { // 取得功能码RxFunctionCode
						if ((rx_232_Buffer[6] == 0x64) && rx_232_Buffer[8] == 0x06 && (rx_232_Buffer[15] == 0x14)) //总召命令激活
						{
							LastType = 0x6406;
							ConfirmFrame();
						}
						if ((rx_232_Buffer[6] == 0x65) && rx_232_Buffer[8] == 0x06 && (rx_232_Buffer[15] == 0x05)) //总召命令激活
						{
							LastType = 0x6506;
							ConfirmFrame();
						}
					}//Protocol101_RxLink
				}//CheckLinkAddress
				
			}//CheckError
	} //while
} //test

void creatTest(void)
{
	osThreadDef(IEC, test, osPriorityNormal, 0, configMINIMAL_STACK_SIZE * 4);
	osThreadCreate (osThread(IEC), NULL);
}

