#include <stdio.h>
#include <stdlib.h>
#include "lib60870_public.h"
#include "gb103.h"

#define CS103_BUF_SIZE 512

uint8_t CS103_CmdYK(CS103 *self, uint8_t *pBuf);
uint8_t CS103_CmdGetAll(CS103 *self, uint8_t *pBuf);
uint8_t CS103_CmdSetTime(CS103 *self, uint8_t *pBuf);
uint8_t CS103_CmdFixedData(CS103 *self, uint8_t *pBuf, uint8_t ucCode);
bool CS103_FixedData(CS103 *self, const uint8_t *pBuf, uint16_t usLen);
bool CS103_VariableData(CS103 *self, const uint8_t *pBuf, uint16_t usLen);
void CS103_ASDU1(CS103 *self, const uint8_t *pBuf, uint16_t usLen);
void CS103_ASDU5(CS103 *self, const uint8_t *pBuf, uint16_t usLen);
void CS103_ASDU10(CS103 *self, const uint8_t *pBuf, uint16_t usLen);
void CS103_ASDU40(CS103 *self, const uint8_t *pBuf, uint16_t usLen);
void CS103_ASDU41(CS103 *self, const uint8_t *pBuf, uint16_t usLen);
void CS103_ASDU44(CS103 *self, const uint8_t *pBuf, uint16_t usLen);
void CS103_ASDU50(CS103 *self, const uint8_t *pBuf, uint16_t usLen);
void CS103_ASDU60(CS103 *self, const uint8_t *pBuf, uint16_t usLen);
void CS103_ASDU10AllValue(CS103 *self, const uint8_t *pBuf, uint32_t usLen);

/**
 * @brief    规约使用前初始化
 * @param[in]  cb-发送函数指针
 * @param[in]  arg-用户数据指针
 * @param[in]  type-规约类型 主从
 * @param[out] 无
 * @return     规约实体指针
 */
CS103 *CS103_Init(CS103_SendCb cb, void *arg, CS103_Type type)
{
	uint8_t *pchar = NULL;

	CS103 *pcs103 = calloc(1, sizeof(CS103));
	if (NULL == pcs103)
	{
		return NULL;
	}

	pchar = malloc(CS103_BUF_SIZE);

	if (NULL != pchar)
	{
		pcs103->stRecvBuf.usBufSize = CS103_BUF_SIZE;
		pcs103->stRecvBuf.pBuf = pchar;
	}
	else
	{
		goto destory;
	}

	pchar = malloc(CS103_BUF_SIZE);

	if (NULL != pchar)
	{
		pcs103->stSendBuf.usBufSize = CS103_BUF_SIZE;
		pcs103->stSendBuf.pBuf = pchar;
	}
	else
	{
		goto destory;
	}

	pcs103->SendCb = cb;
	pcs103->pUsrData = arg;

	pcs103->ucAddr = 1;
	pcs103->ucReSend_Num = 10;	   //重发次数
	pcs103->usReSend_Gap = 5000;   //重发间隔默认值
	pcs103->ulSummon_Gap = 120000; //总招默认值
	pcs103->ulSyn_Gap = 300000;	   //对时默认值

	SetTaskFlag(&pcs103->stTaskFlags, CMD_RESET_NUM);

	return pcs103;

destory:

	if (pcs103)
	{
		if (pcs103->stRecvBuf.pBuf)
		{
			free(pcs103->stRecvBuf.pBuf);
			pcs103->stRecvBuf.pBuf = NULL;
		}
		if (pcs103->stSendBuf.pBuf)
		{
			free(pcs103->stSendBuf.pBuf);
			pcs103->stSendBuf.pBuf = NULL;
		}

		free(pcs103);
		pcs103 = NULL;
	}

	return NULL;
}

/*
 *   @brief 规约实体销毁
 *   @param[self]    规约实体
 */
void CS103_Destory(CS103 *self)
{
	if (self)
	{
		if (self->stRecvBuf.pBuf)
		{
			free(self->stRecvBuf.pBuf);
		}
		if (self->stSendBuf.pBuf)
		{
			free(self->stSendBuf.pBuf);
		}
		free(self);
	}
}

/**
 * @brief 设置设备地址
 *
 * @param self
 * @param pstParam
 */
void CS103_SetAddr(CS103 *self, uint8_t ucAddr)
{
	self->ucAddr = ucAddr;
}

/**
 * @brief 设置总召定时间隔关联
 *
 * @param self
 * @param pstParam
 */
void CS103_SetSummonGap(CS103 *self, uint32_t ulGap)
{
	self->ulSummon_Gap = ulGap;
}

/**
 * @brief 设置对时同步间隔关联
 *
 * @param self
 * @param pstParam
 */
void CS103_SetSynTimeGap(CS103 *self, uint32_t ulGap)
{
	self->ulSyn_Gap = ulGap;
}

/**
 * @brief 101规约重发间隔时间参数输入
 * @param self
 * @param pstParam
 */
void CS103_ResendGap(CS103 *self, uint16_t usGap)
{
	self->usReSend_Gap = usGap;
}
/**
 * @brief 101规约重发次数参数输入
 * @param self
 * @param pstParam
 */
void CS103_ResendCnt(CS103 *self, uint8_t ucCnt)
{
	self->ucReSend_Num = ucCnt;
}

/**
 * @brief 获取时间接口
 *
 * @param self
 * @param cb
 */
void CS103_GetTimeHandler(CS103 *self, CS10x_GetTime cb)
{
	self->GetTime = cb;
}

/**
 * @brief 设置接收遥测接口
 *
 * @param self
 * @param cb
 */
void CS103_SetValueHandler(CS103 *self, CS103_SetValue cb)
{
	self->SetValue = cb;
}

/**
 * @brief 设置接收遥信接口
 *
 * @param self
 * @param cb
 */
void CS103_SetStatusHandler(CS103 *self, CS103_SetStatus cb)
{
	self->SetStatus = cb;
}

/**
 * @brief 设置接收SOE处理函数
 *
 * @param self
 * @param cb
 */
void CS103_AddSOEHandler(CS103 *self, CS103_AddSOE cb)
{
	self->AddSOE = cb;
}


void CS103_SetYkTask(CS103 *self, uint8_t ucFun, uint8_t ucInf, uint8_t ucSE, uint8_t ucACT, uint8_t ucQU, uint8_t ucDCS)
{
	if (!self->stIEC103CodeS2C.fcv)
	{
		return;
	}
	self->ucYkFun = ucFun;
	self->ucYkInf = ucInf;
	self->ucYkSE = ucSE;
	self->ucYkACT = ucACT;
	self->ucYkQU = ucQU;
	self->ucYkDCS = ucDCS;
	SetTaskFlag(&self->stTaskFlags, CMD_YK);
}

/**
 * @brief 103规约处理函数接口
 * @param self     规约实体
 * @param pBuf     接收缓冲
 * @param usLen    接收数据长度
 */
bool CS103_DoRecv(CS103 *self, uint8_t *pBuf, uint16_t usLen)
{
	if (usLen < 5)
	{
		return false;
	}
	if (START_10H == pBuf[0]) //固定长度报文(固定五个字节)
	{
		CS103_FixedData(self, pBuf, usLen); // 处理定长数据
	}
	else if (START_68H == pBuf[0]) //可变长报文(最少14个字节)
	{
		if (!CS103_VariableData(self, pBuf, usLen)) // 处理可变长数据
		{
			return false;
		}
	}
	else
	{
		return false;
	}
	return true;
}

/**
 * @brief 103规约数据发送
 * @param self     规约实体
 */
void CS103_SendHandler(CS103 *self)
{
	if(self->ulSend_Gap)
	{
		return;
	}

	if (0 == self->usTaskID)
	{
		self->stSendBuf.usWritePtr = 0;
		self->usResend_Ncn = 0; //重复次数重置

		if (GetTaskFlag(&self->stTaskFlags, CMD_RESET_CON))
		{
			ClearTaskFlag(&self->stTaskFlags, CMD_RESET_CON);
			self->usTaskID = CMD_RESET_CON;

			memset(&self->stIEC103CodeS2C, 0, sizeof(IEC103CodeS2C)); //重置FCB FCV

			uint8_t code = PRA_1 | 0 | 0 | FNA_S2C_RESET_CON;
			self->stSendBuf.usWritePtr = CS103_CmdFixedData(self, self->stSendBuf.pBuf, code);
		}
		else if (GetTaskFlag(&self->stTaskFlags, CMD_RESET_NUM))
		{
			ClearTaskFlag(&self->stTaskFlags, CMD_RESET_NUM);
			self->usTaskID = CMD_RESET_NUM;

			memset(&self->stIEC103CodeS2C, 0, sizeof(IEC103CodeS2C)); //重置FCB FCV

			uint8_t code = PRA_1 | 0 | 0 | FNA_S2C_RESET_NUM;
			self->stSendBuf.usWritePtr = CS103_CmdFixedData(self, self->stSendBuf.pBuf, code);
		}
		else if (GetTaskFlag(&self->stTaskFlags, CMD_YK))
		{
			ClearTaskFlag(&self->stTaskFlags, CMD_YK);
			self->usTaskID = CMD_YK;
			self->stSendBuf.usWritePtr = CS103_CmdYK(self, self->stSendBuf.pBuf);
		}
		else if (GetTaskFlag(&self->stTaskFlags, CMD_RESET_TIMESTAMP))
		{
			ClearTaskFlag(&self->stTaskFlags, CMD_RESET_TIMESTAMP);
			self->usTaskID = CMD_RESET_TIMESTAMP;
			self->stSendBuf.usWritePtr = CS103_CmdSetTime(self, self->stSendBuf.pBuf);
		}
		else if (GetTaskFlag(&self->stTaskFlags, CMD_GET_ALL))
		{
			ClearTaskFlag(&self->stTaskFlags, CMD_GET_ALL);
			self->usTaskID = CMD_GET_ALL;
			self->stSendBuf.usWritePtr = CS103_CmdGetAll(self, self->stSendBuf.pBuf);
		}
		else if (GetTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV1))
		{
			ClearTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV1);
			self->usTaskID = CMD_GET_DATA_LV1;
			uint8_t code = PRA_1 | self->stIEC103CodeS2C.fcb | self->stIEC103CodeS2C.fcv | FNA_S2C_GETDATA_LV1;
			self->stSendBuf.usWritePtr = CS103_CmdFixedData(self, self->stSendBuf.pBuf, code);
		}
		else if (GetTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV2))
		{
			ClearTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV2);
			self->usTaskID = CMD_GET_DATA_LV2;
			uint8_t code = PRA_1 | self->stIEC103CodeS2C.fcb | self->stIEC103CodeS2C.fcv | FNA_S2C_GETDATA_LV2;
			self->stSendBuf.usWritePtr = CS103_CmdFixedData(self, self->stSendBuf.pBuf, code);
		}
		
	}

	if (self->usTaskID)
	{
		if (self->usResend_Ncn < self->ucReSend_Num)
		{
			self->usResend_Ncn++;
			self->usResend_Tcn = self->usReSend_Gap;
			if (self->stSendBuf.usWritePtr)
			{
				if (self->SendCb)
				{
					self->SendCb(self->stSendBuf.pBuf, self->stSendBuf.usWritePtr, self->pUsrData);
				}

				self->ulSend_Gap = 800;
				self->stSendBuf.usWritePtr = 0;
			}

			if(CMD_RESET_TIMESTAMP == self->usTaskID)
			{
				self->usTaskID = 0;
				self->usResend_Ncn = 0; // 重复清零
				self->usResend_Tcn = 0; // 重发间隔清零

				self->ulSend_Gap = 100;
			}
		}
		else
		{
			//重置链路
			if (CMD_RESET_CON == self->usTaskID || CMD_RESET_NUM == self->usTaskID)
			{
				SetTaskFlag(&self->stTaskFlags, CMD_RESET_CON);
			}
			else
			{
				SetTaskFlag(&self->stTaskFlags, CMD_RESET_NUM);
			}
			self->usTaskID = 0;		// 任务关闭
			self->usResend_Ncn = 0; // 重复清零
			self->usResend_Tcn = 0; // 重发间隔清零
		}
	}
}

/**
 * @brief 103规约时间处理函数
 * @param self     规约实体
 * @param usGap    时间间隔
 */
void CS103_TimerHandle(CS103 *self, uint16_t usGap)
{
	if (self->usResend_Tcn)
	{
		if (self->usResend_Tcn < usGap)
		{
			self->usResend_Tcn = 0;
		}
		else
		{
			self->usResend_Tcn -= usGap;
		}
	}

	if (self->ulSend_Gap)
	{
		if (self->ulSend_Gap < usGap)
		{
			self->ulSend_Gap = 0;
		}
		else
		{
			self->ulSend_Gap -= usGap;
		}
	}

	/*重发间隔*/
	if (0 == self->usResend_Tcn)
	{
		CS103_SendHandler(self);
	}

	if (self->stIEC103CodeS2C.fcv)
	{
		self->ulSummon_Tcn += usGap;
		if (self->ulSummon_Tcn > self->ulSummon_Gap)
		{
			self->ulSummon_Tcn = 0;
			// SetTaskFlag(&self->stTaskFlags, CMD_GET_ALL);
		}

		self->ulTimeSyn_Tcn += usGap;
		if (self->ulTimeSyn_Tcn > self->ulSyn_Gap)
		{
			self->ulTimeSyn_Tcn = 0;
			SetTaskFlag(&self->stTaskFlags, CMD_RESET_TIMESTAMP);
		}
	}
}

/**
 * @brief 103规约遥控
 * @param self 		规约实体
 * @param pBuf    	缓冲
 */
uint8_t CS103_CmdYK(CS103 *self, uint8_t *pBuf)
{
	uint8_t usLen = 4;
	pBuf[0] = START_68H;
	pBuf[3] = START_68H;
	pBuf[usLen++] = PRA_1 | self->stIEC103CodeS2C.fcb | self->stIEC103CodeS2C.fcv | FNA_S2C_POSTDATA_3;
	pBuf[usLen++] = self->ucAddr;
	pBuf[usLen++] = ASDU60;
	pBuf[usLen++] = 0x01;				  // vsq
	pBuf[usLen++] = COT_S2C_REMOTE; //总召唤
	pBuf[usLen++] = self->ucAddr;
	pBuf[usLen++] = self->ucYkFun; // FUN
	pBuf[usLen++] = self->ucYkFun;
	pBuf[usLen++] = (self->ucYkSE << 7) | (self->ucYkACT << 6) | (self->ucYkQU << 2) | (self->ucYkDCS);
	pBuf[usLen++] = 0;
	pBuf[1] = usLen - 4;
	pBuf[2] = usLen - 4;
	pBuf[usLen] = checksum_8(&pBuf[4], usLen - 4);
	usLen++;
	pBuf[usLen++] = END_16H;
	return usLen;
}

/**
 * @brief 103规约总召唤
 * @param self 		规约实体
 * @param pBuf    	缓冲
 */
uint8_t CS103_CmdGetAll(CS103 *self, uint8_t *pBuf)
{
	uint8_t usLen = 4;
	pBuf[0] = START_68H;
	pBuf[3] = START_68H;
	pBuf[usLen++] = PRA_1 | self->stIEC103CodeS2C.fcb | self->stIEC103CodeS2C.fcv | FNA_S2C_POSTDATA_3;
	pBuf[usLen++] = self->ucAddr;
	pBuf[usLen++] = ASDU7_GETALL;
	pBuf[usLen++] = 0x81;				  // vsq
	pBuf[usLen++] = COT_S2C_GETALL_START; //总召唤
	pBuf[usLen++] = self->ucAddr;
	pBuf[usLen++] = FUN_GLB; // FUN
	pBuf[usLen++] = 0x00;
	pBuf[usLen++] = 4;
	pBuf[1] = usLen - 4;
	pBuf[2] = usLen - 4;
	pBuf[usLen] = checksum_8(&pBuf[4], usLen - 4);
	usLen++;
	pBuf[usLen++] = END_16H;
	return usLen;
}

/**
 * @brief 103规约对时指令
 * @param self 		规约实体
 * @param pBuf    	缓冲
 */
uint8_t CS103_CmdSetTime(CS103 *self, uint8_t *pBuf)
{
	uint8_t usLen = 4;
	pBuf[0] = START_68H;
	pBuf[3] = START_68H;
	pBuf[usLen++] = PRA_1 | FNA_S2C_POSTDATA_4;
	pBuf[usLen++] = 0xFF;
	pBuf[usLen++] = ASDU6_TIMESTAMP;
	pBuf[usLen++] = 0x81;			   // vsq
	pBuf[usLen++] = COT_S2C_TIMESTAMP; //时钟同步
	pBuf[usLen++] = 0xFF;
	pBuf[usLen++] = FUN_GLB; // FUN
	pBuf[usLen++] = 0x00;

	/*获取系统时间*/
	if (NULL != self->GetTime)
	{
		__CP56Time2a Cp56Time;
		memset(&Cp56Time, 0, sizeof(__CP56Time2a));
		self->GetTime(&Cp56Time);

		pBuf[usLen++] = Cp56Time.ucLMs;
		pBuf[usLen++] = Cp56Time.ucHMs;
		pBuf[usLen++] = Cp56Time.ucMin & 0x3F;
		pBuf[usLen++] = Cp56Time.ucHour & 0x1F;
		pBuf[usLen++] = Cp56Time.ucWeek & 0x1F;
		pBuf[usLen++] = Cp56Time.ucMonth;
		pBuf[usLen++] = Cp56Time.ucYear;
	}
	else
	{
		usLen += 7;
	}

	pBuf[1] = usLen - 4;
	pBuf[2] = usLen - 4;
	pBuf[usLen] = checksum_8(&pBuf[4], usLen - 4);
	usLen++;
	pBuf[usLen++] = END_16H;
	return usLen;
}

/**
 * @brief 103规约短帧封装
 * @param self 		规约实体
 * @param pBuf    	缓冲
 * @param ucCode	功能码
 */
uint8_t CS103_CmdFixedData(CS103 *self, uint8_t *pBuf, uint8_t ucCode)
{
	pBuf[0] = START_10H;
	pBuf[1] = ucCode;
	pBuf[2] = self->ucAddr;
	pBuf[3] = pBuf[1] + pBuf[2];
	pBuf[4] = END_16H;

	return 5;
}

/*
 * @brief: 处理接收到的固定长度报文
 * @Param: pData　解析数据开始地址
 * @Param: dataLen　解析数据长度
 * @Return: 解析成功或失败
 */
bool CS103_FixedData(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	self->stIEC103CodeS2C.fcb ^= FCB_1;
	self->stIEC103CodeS2C.fcv = FCV_1;

	self->usResend_Tcn = 0;
	self->ulSend_Gap = 0;

	//通信复位的确认处理
	if (CMD_RESET_CON == self->usTaskID || CMD_RESET_NUM == self->usTaskID)
	{
		SetTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV1);
		self->usTaskID = 0;
		return true;
	}

	//判断是否有一级数据上送,有则继续召唤一级数据，没有则召唤二级数据
	if ((pBuf[1] & ACD_1) == ACD_1)
	{
		if(++self->usFirstNum > 5)
		{
			self->usFirstNum = 0;
			SetTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV2);
		}
		else
		{
			SetTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV1);
		}
	}
	else
	{
		SetTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV2);
	}

	if (CMD_GET_DATA_LV2 == self->usTaskID && (pBuf[1] & 0x0F) == 9) //从站没有所召唤的数据
	{
	}
	self->usTaskID = 0;
	return true;
}

/*
 * @Desc: 处理接收到的可变长度报文
 * @Param: pData　解析数据开始地址
 * @Param: dataLen　解析数据长度
 * @Return: 解析成功或失败
 */
bool CS103_VariableData(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	self->stIEC103CodeS2C.fcv = FCV_1;
	self->stIEC103CodeS2C.fcb ^= FCB_1;
	self->usResend_Tcn = 0;
	self->ulSend_Gap = 0;
	uint8_t asduType = pBuf[6]; // asdu类型

	// if ((CMD_GET_DATA_LV1 == self->usTaskID) && (5 == asduType)) //复位通信或复位帧计数位一级数据召唤
	// {
	// 	if ((pBuf[4] & ACD_1) != ACD_1)
	// 	{
	// 		if (!self->bIsResetConEnd)
	// 		{
	// 			self->bIsResetConEnd = true;	//复位通信单元完成
	// 			SetTaskFlag(self->stTaskFlags, CMD_RESET_NUM);
	// 			self->usTaskID = 0;
	// 			return true;
	// 		}

	// 		if (!self->bIsResetNumEnd)
	// 		{
	// 			self->bIsResetNumEnd = true;  //复位帧计数位完成
	// 			// self->usTaskID = CMD_GET_ALL; //复位帧计数位
	// 			SetTaskFlag(self->stTaskFlags, CMD_GET_ALL);
	// 			self->usTaskID = 0;
	// 			return true;
	// 		}
	// 	}
	// 	return true;
	// }

	//判断是否有一级数据上送,有则继续召唤一级数据，没有则召唤二级数据
	if ((pBuf[4] & ACD_1) == ACD_1)
	{
		if(++self->usFirstNum > 5)
		{
			self->usFirstNum = 0;
			SetTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV2);
		}
		else
		{
			SetTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV1);
		}
	}
	else
	{
		SetTaskFlag(&self->stTaskFlags, CMD_GET_DATA_LV2);
	}

	switch (asduType)
	{
	case 1:
		CS103_ASDU1(self, pBuf, usLen);
		break;
	case 5:
		CS103_ASDU5(self, pBuf, usLen);
		// self->ucIDCount++;
		// if (self->ucIDCount > 2)
		// {
		// 	self->ucIDCount = 0;
		// 	SetTaskFlag(&self->stTaskFlags, CMD_RESET_TIMESTAMP);
		// 	SetTaskFlag(&self->stTaskFlags, CMD_GET_ALL);
		// }
		break;
	case 10:
		CS103_ASDU10(self, pBuf, usLen);
		break;
	case 40:
		CS103_ASDU40(self, pBuf, usLen);
		break;
	case 41:
		CS103_ASDU41(self, pBuf, usLen);
		break;
	case 44:
		CS103_ASDU44(self, pBuf, usLen);
		break;
	case 50:
		CS103_ASDU50(self, pBuf, usLen);
		break;
	case 60:
		CS103_ASDU60(self, pBuf, usLen);
		break;
	default:
		break;
	}

	self->usTaskID = 0;
	return true;
}

/*
 * @Desc: 解析ASDU1遥信变位上送
 * @param: self 规约实体
 * @Param: pBuf 开始地址
 * @Param: usLen 开始地址
 */
void CS103_ASDU1(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	// uint8_t code = pBuf[CODE_POSI];
	uint8_t clientAddr = pBuf[ADDR_POSI];
	uint8_t fun = pBuf[FUN_POSI];
	uint8_t inf = pBuf[INF_POSI];
	uint8_t dpi = pBuf[DPI_POSI];

	dpi -= 1;

	stTime7Byte Time4Byte;
	memset(&Time4Byte, 0, sizeof(stTime7Byte));
	memcpy(&Time4Byte, pBuf + ASDU_1_TIMESTAMP, 4); //取四字节时间

	IEC_PRINT("addr:%d fun:%d inf:%03d dpi:%d %d:%d:%d\n", clientAddr, fun, inf, dpi, Time4Byte.hour, Time4Byte.min, Time4Byte.msec);

	// if(0 == dpi|| 1 == dpi)
	// {
	// 	if (self->AddSOE)
	// 	{
	// 		self->AddSOE(fun, inf, dpi, &Time4Byte, self->pUsrData);
	// 	}
	// }
}

/*
 * @Desc: 解析ASDU5
 * @param: self 规约实体
 * @Param: pBuf 开始地址
 * @Param: usLen 开始地址
 */
void CS103_ASDU5(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	// uint8_t code = pBuf[CODE_POSI];
	// uint8_t clientAddr = pBuf[ADDR_POSI];
	// uint8_t fun = pBuf[FUN_POSI];
	// uint8_t inf = pBuf[INF_POSI];
	uint8_t cot = pBuf[COT_POSI];

	if(5 == cot)
	{
		SetTaskFlag(&self->stTaskFlags, CMD_RESET_TIMESTAMP);
		// SetTaskFlag(&self->stTaskFlags, CMD_GET_ALL);
	}

}

/*
 * @Desc: 解析通用分类数据响应（读目录，读一个组的描述，读一个组的值）
 * @param: self 规约实体
 * @Param: pBuf 开始地址
 * @Param: usLen 开始地址
 */
void CS103_ASDU10(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	uint8_t fun = pBuf[FUN_POSI];
	uint8_t inf = pBuf[INF_POSI];

	if ((FUN_GEN == fun) && (0xF0 == inf)) //通用分类数据响应命令（装置响应的读目录）
	{
	}
	else if ((FUN_GEN == fun) && (INF_READ_GROUP == inf)) //通用分类数据响应命令(读一个组的描述或值)
	{
		CS103_ASDU10AllValue(self, pBuf, usLen);
	}
	else if ((FUN_GEN == fun) && (INF_READ_EBTRY == inf)) //通用分类数据响应命令(读一个条目的描述或值)
	{
		CS103_ASDU10AllValue(self, pBuf, usLen);
	}
	else if ((FUN_GEN == fun) && (INF_CONFIRM_WRITE == inf)) //带确认的写条目响应
	{
		CS103_ASDU10AllValue(self, pBuf, usLen);
	}
	else if ((FUN_GEN == fun) && (INF_EXEC_WRITE == inf)) //带执行的写条目响应
	{
		// uint8_t rii = pBuf[RII_POSI];
	}

	self->usTaskID = 0;
	return;
}

/*
 * @Desc: 解析ASDU40上送变位遥信
 * @param: self 规约实体
 * @Param: pBuf 开始地址
 * @Param: usLen 开始地址
 */
void CS103_ASDU40(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	uint8_t clientAddr = pBuf[5];
	uint8_t fun = pBuf[10];
	uint8_t inf = pBuf[11];
	uint8_t siq = pBuf[12]; //带品质描述的单点信息字节
	bool bValue = false;

	if (siq & 0x80) //无效
	{
		return;
	}
	if (0x01 & siq)
	{
		bValue = true; // true为合，false为分
	}

	IEC_PRINT("addr:%d fun:%d inf:%03d val:%d\n", clientAddr, fun, inf, bValue); //构造103地址

	if (self->SetStatus)
	{
		self->SetStatus(fun, inf, bValue, self->pUsrData);
	}
}

/*
 * @Desc: 解析ASDU44上送SOE
 * @param: self 规约实体
 * @Param: pBuf 开始地址
 * @Param: usLen 开始地址
 */
void CS103_ASDU41(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	uint8_t clientAddr = pBuf[5];
	uint8_t fun = pBuf[10];
	uint8_t inf = pBuf[11];
	uint8_t siq = pBuf[12]; //带品质描述的单点信息字节
	// uint8_t ucHour, ucMin;
	// uint16_t usMs;

	stTime7Byte stTime;

	bool bValue = false;

	if (siq & 0x80) //无效
	{
		return;
	}
	if (0x01 & siq)
	{
		bValue = true; // true为合，false为分
	}

	stTime.msec = pBuf[13] + (pBuf[14] << 8);
	stTime.min = pBuf[15] & 0x3F;
	stTime.hour = pBuf[16] & 0x7F;

	IEC_PRINT("addr:%d fun:%d inf:%03d val:%d\n", clientAddr, fun, inf, bValue); //构造103地址

	if (self->SetStatus)
	{
		self->SetStatus(fun, inf, bValue, self->pUsrData);
	}

	if (self->AddSOE)
	{
		self->AddSOE(fun, inf, bValue, &stTime, self->pUsrData);
	}
}

void CS103_ASDU42(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	uint8_t vsq = pBuf[VSQ_POSI];
	uint8_t clientAddr = pBuf[ADDR_POSI];
	uint8_t fun = pBuf[FUN_POSI];
	;
	uint8_t inf = pBuf[INF_POSI];
	uint8_t dpiNum = vsq & 0x7F; // 信息元个数

	for (uint8_t i = 0; i < dpiNum; ++i)
	{
		uint8_t dpi = pBuf[DPI_POSI + i]; //品质描述的双点信息

		if (!((dpi == 0x01) || (dpi == 0x02))) //当前值无效  dpi为2位数组，值=0/3为无意义，值=1为分，值=2为合
		{
			continue;
		}

		IEC_PRINT("addr:%d fun:%d inf:%03d dpi:%d\n", clientAddr, fun, inf, dpi); //构造103地址
	}
}

/*
 * @Desc: 解析ASDU44上送全遥信
 * @param: self 规约实体
 * @Param: pBuf 开始地址
 * @Param: usLen 开始地址
 */
void CS103_ASDU44(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	uint8_t clientAddr = pBuf[5];
	uint8_t vsq = pBuf[7];
	uint8_t fun = pBuf[10];
	uint8_t inf = pBuf[11];
	uint8_t scdNum = vsq & 0x7F; // 信息元个数
	bool bValue = false;

	for (uint8_t i = 0; i < scdNum; ++i)
	{
		//信息元
		uint8_t pScd = pBuf[12 + i * 5];
		uint8_t qds = pBuf[16 + i * 5]; //品质描述字节
		if (qds & 0x80)			   //当前值无效
		{
			++inf;
			continue;
		}
		if (0x01 & pScd)
		{
			bValue = true; // true为合，false为分
		}
		IEC_PRINT("addr:%d fun:%d inf:%03d val:%d\n", clientAddr, fun, inf, bValue); //构造103地址

		if (self->SetStatus)
		{
			self->SetStatus(fun, inf, bValue, self->pUsrData);
		}
		++inf;
	}
}

/*
 * @Desc: 解析ASDU50遥测上送
 * @param: self 规约实体
 * @Param: pBuf 开始地址
 * @Param: usLen 开始地址
 */
void CS103_ASDU50(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	uint8_t vsq = pBuf[VSQ_POSI];
	uint8_t clientAddr = pBuf[ADDR_POSI];
	uint8_t fun = pBuf[FUN_POSI];
	uint8_t inf = pBuf[INF_POSI];
	uint8_t scdNum = vsq & 0x7F; // 信息元个数
	int16_t sVal = 0;
	float fVal = 0.0f;
	for (uint8_t i = 0; i < scdNum; ++i)
	{
		//信息元
		uint8_t qds = pBuf[12 + i * 2];
		uint16_t tmpValue = pBuf[12 + i * 2] + (pBuf[13 + i * 2] << 8);
		if (qds & 0x02) //当前值无效
		{
			++inf;
			continue;
		}

		if (tmpValue & 0x8000) //负数
		{
			sVal = (tmpValue >> 3) - 1; //减一
			sVal = ~sVal & 0x1fff;					  //取反取原码
			fVal = (float)(0 - sVal) * 12 / 4095;
		}
		else
		{
			if (tmpValue & 0x01)
				fVal = (float)((tmpValue >> 3) + 4095) * 12.0 / 4095.0; //溢出
			else
				fVal = (float)(tmpValue >> 3) * 12.0 / 4095.0;
		}

		// value = (flag?(-tmpValue):tmpValue)*GetRateByPrivateAddr(addr);
		IEC_PRINT("addr:%d fun:%d inf:%03d qds:%d val:%f\n", clientAddr, fun, inf, qds, fVal); //构造103地址
		if (self->SetValue)
		{
			self->SetValue(fun, inf, fVal, self->pUsrData);
		}
		++inf;
	}
}

/*
 * @Desc: 解析ASDU60遥控功能
 * @param: self 规约实体
 * @Param: pBuf 开始地址
 * @Param: usLen 开始地址
 */
void CS103_ASDU60(CS103 *self, const uint8_t *pBuf, uint16_t usLen)
{
	// uint8_t vsq = pBuf[VSQ_POSI];
	// uint8_t clientAddr = pBuf[ADDR_POSI];
	uint8_t fun = pBuf[FUN_POSI];
	uint8_t inf = pBuf[INF_POSI];
	// uint8_t ucCot = pBuf[COT_POSI];
	uint8_t ucDcc = pBuf[12];
	// uint8_t ucRII = pBuf[13];

	uint8_t ucSE = (ucDcc & 0x80) ? 1:0;
	uint8_t ucAct = (ucDcc & 0x40) ? 1:0;
	uint8_t ucQu = (ucDcc & 0x3C) >> 2;
	uint8_t ucDcs = ucDcc & 0x03;

	/*遥控选择*/
	if(1 == ucSE && 0 == ucAct)
	{
		/*选择成功执行任务*/
		CS103_SetYkTask(self, fun, inf, 0, 0, ucQu, ucDcs);
	}
	/*遥控执行*/
	else if(0 == ucSE && 0 == ucAct)
	{

	}
	/*遥控撤销*/
	else if(1 == ucSE && 1 == ucAct)
	{

	}
}
void CS103_ASDU10AllValue(CS103 *self, const uint8_t *pBuf, uint32_t usLen)
{
	// uint8_t code = pBuf[CODE_POSI];
	uint8_t clientAddr = pBuf[ADDR_POSI];
	uint8_t ngdNum = pBuf[NGD_POSI] & 0x3F; // 返回的数据个数
	uint16_t offset = 0;					//数据的偏移量

	for (uint8_t i = 0; i < ngdNum; ++i)
	{
		stDataUnit dataUnit;
		memcpy(&dataUnit, pBuf + GROUP_POSI + offset, sizeof(stDataUnit));

		IEC_PRINT("addr:%d group:%d entry:%03d ", clientAddr, dataUnit.groupNo, dataUnit.entryNo); //构造103地址

		//不是遥信或者遥测数据
		// if (self->ucYcGroupNum != dataUnit.groupNo && self->ucYxGroupNum != dataUnit.groupNo)
		// {
		// 	break;
		// }

		UnionConvert4Byte convertUnion4Byte;
		UnionConvert2Byte convertUnion2Byte;
		switch (dataUnit.datatype)
		{
		case 3: // 2字节无符号整形
			memcpy(convertUnion2Byte.buf, pBuf + GID_POSI + offset, dataUnit.datasize);
			IEC_PRINT("%u\n", convertUnion2Byte.uValue);
			break;

		case 7: //短实数
			memcpy(convertUnion4Byte.buf, pBuf + GID_POSI + offset, dataUnit.datasize);
			IEC_PRINT("%.4f\n", convertUnion4Byte.fValue);
			break;

		case 9: //双点描述 dpi=1为分，=2为和   0和3无意义
			if (!(((pBuf + GID_POSI + offset)[0] == 0x01) || ((pBuf + GID_POSI + offset)[0] == 0x02)))
			{
				break;
			}
			IEC_PRINT("%d\n", ((pBuf + GID_POSI + offset)[0] - 1) & 0x01);
			break;

		case 10: //单点描述 siq=0为分，=1为和
			if (!(((pBuf + GID_POSI + offset)[0] == 0x00) || ((pBuf + GID_POSI + offset)[0] == 0x01)))
			{
				break;
			}
			IEC_PRINT("%d\n", (pBuf + GID_POSI + offset)[0] & 0x01);
			break;

		case 12: //带品质描述词的被测值
			//信息元
			//			uint8_t qds = valueStr[0];
			//			uint16_t tmpValue = valueStr[0];
			//			  value = 0.0f;
			//			if(qds & 0x02) //当前值无效
			//			{
			//				continue;
			//			}
			//
			//			bool flag = (tmpValue & 0x8000) ? true: false; //是否为负数
			//			tmpValue = ~tmpValue;
			//			tmpValue &= 0xfff8; //品质位置0
			//			tmpValue &= 0x7ff8; //符号位置0
			//			tmpValue >>= 3;
			//			tmpValue += 1;
			//			value = (flag?(-tmpValue):tmpValue)*GetRateByPrivateAddr(addr);
			//			sprintf(tagTemp.pdata, "%.4f", value);
			IEC_PRINT("\n");
			break;
		default:
			IEC_PRINT("\n");
			break;
		}
		offset = offset + dataUnit.datasize + 6; //通用分类数据单元占6个字节
	}
}
