/******************************************************************************

版权所有 (C), 2013-2023, 科大智能电气有限公司

******************************************************************************
文 件 名   : lib60870_process.c
版 本 号   : V1.0
生成日期   : 2022年04月07日
最近修改   :
功能描述   : 101及104规约实现中的公共流程实现模块
函数列表   :
修改历史   :
1.日    期   : 2022年04月07日
修改内容   : 创建文件
*******************************************************************************/
/*************************************文件包含*********************************/
#include "lib60870_process.h"

/***************************************数据定义*******************************/

/*************************************外部接口函数*****************************/
/**
* @brief    更新数据池中故障事件及SOE指针
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void CheckUpdate_SoeEvent(CS10xHandle_t pstSelf)
{
	if(pstSelf->usSoeSendNoAckNum)
	{
		if(NULL != pstSelf->pfnUpdata_SOE_Pout)
		{
			pstSelf->pfnUpdata_SOE_Pout(pstSelf->pUsrData, pstSelf->usSoeSendNoAckNum);
			pstSelf->usCosSendNoAckNum -= pstSelf->usSoeSendNoAckNum;
			pstSelf->usSoeSendNoAckNum = 0;
		}
	}

	if(pstSelf->usEventSendNoAckNum)
	{
		if(NULL != pstSelf->pfnUpdata_FaultEvent_Pout)
		{
			pstSelf->pfnUpdata_FaultEvent_Pout(pstSelf->pUsrData, pstSelf->usEventSendNoAckNum);
			pstSelf->usEventSendNoAckNum = 0;
		}
	}

	if(pstSelf->usDduSendNoAckNum)
	{
		if(NULL != pstSelf->pfnUpdata_TimeDdu_Pout)
		{
			pstSelf->pfnUpdata_TimeDdu_Pout(pstSelf->pUsrData, pstSelf->usDduSendNoAckNum);
			pstSelf->usDduSendNoAckNum = 0;
		}
	}
}

/**
* @brief    更新数据池中扰动遥测指针
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void CheckUpdate_DiturbYcEvent(CS10xHandle_t pstSelf)
{
	if(pstSelf->usDiturbYcSendNoAckNum)
	{
		if(NULL != pstSelf->pfnUpdata_DiturbYc_Pout)
		{
			pstSelf->pfnUpdata_DiturbYc_Pout(pstSelf->pUsrData, pstSelf->usDiturbYcSendNoAckNum);
			pstSelf->usDiturbYcSendNoAckNum = 0;
		}
	}
}

/**
* @brief    检查数据池中SOE待发送数量
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void CheckSOE_SendInfo(CS10xHandle_t pstSelf)
{
	if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M)  //作为主站时直接返回
	{
		return;
	}

	if(NULL == pstSelf->pfnGetSOE_SendNum)
	{
		return;
	}

	/* 链路未初始化完成，不进行任务调度*/
	if(1 != pstSelf->ucInitStatus)
	{
		pstSelf->usSoeSendSetup = 0;
		return;
	}

	/*cos-soe处理*/
	pstSelf->usSoeSendNum = pstSelf->pfnGetSOE_SendNum(pstSelf->pUsrData);

	if(0 == pstSelf->usSoeSendSetup)
	{
		pstSelf->usCosSendNoAckNum = pstSelf->usSoeSendNum;
		pstSelf->usSoeSendSetup = 1;
	}

	if(pstSelf->usSoeSendNum)
	{
		if(pstSelf->usSoeSendNum != pstSelf->usSoeSendNoAckNum)
		{
			if(pstSelf->usSoeSendNum > pstSelf->usCosSendNoAckNum)
			{
				// 发送SOE/COS使能参数
				if(pstSelf->ucSenCosEa == 0)
				{
					pstSelf->usCosSendNoAckNum = pstSelf->usSoeSendNum;
				}
				else
				{
					SetSendTask(pstSelf, TSKID_SendCOS, COT_SPONT, 0); //正常发送COS
				}
			}
			else
			{
				// 发送SOE/COS使能参数
				pstSelf->usCosSendNoAckNum = pstSelf->usSoeSendNum;

				if(pstSelf->ucSenSoeEa == 0)
				{
					pstSelf->usSoeSendNoAckNum = pstSelf->usSoeSendNum;
				}
				else
				{
					SetSendTask(pstSelf, TSKID_SendSOE, COT_SPONT, 0); //正常发送SOE
				}
			}
		}
	}
	else
	{
		pstSelf->usSoeSendNoAckNum = 0;
		pstSelf->usCosSendNoAckNum = 0;
	}
}

/**
* @brief    检查数据池中故障事件待发送数量
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void CheckFaultEvent_SendInfo(CS10xHandle_t pstSelf)
{
	unsigned short usEventSendNum = 0;

	if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M)  //作为主站时直接返回
	{
		return;
	}

	if(NULL == pstSelf->pfnGetEvent_SendNum)
	{
		return;
	}

	/* 链路未初始化完成，不进行任务调度*/
	if(1 != pstSelf->ucInitStatus)
	{
		return;
	}

	/* 故障事件处理*/
	if(pstSelf->usFaultEnable)
	{
		usEventSendNum = pstSelf->pfnGetEvent_SendNum(pstSelf->pUsrData);

		if(usEventSendNum)
		{
			if(usEventSendNum != pstSelf->usEventSendNoAckNum)
			{
				SetSendTask(pstSelf, TSKID_FaultSoe, COT_SPONT, 0); // 第一次重启补发SOE
			}
		}
		else
		{
			pstSelf->usEventSendNoAckNum = 0;
		}
	}
}

/**
* @brief    检查数据池中电度待发送数量
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void CheckTimeDd_SendInfo(CS10xHandle_t pstSelf)
{
	unsigned short usTimeDdSendNum = 0;

	if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M)  //作为主站时直接返回
	{
		return;
	}

	if(NULL == pstSelf->pfnGetTimeDdu_SendNum)
	{
		return;
	}

	/* 链路未初始化完成，不进行任务调度*/
	if(1 != pstSelf->ucInitStatus)
	{
		return;
	}

	/* 电度数据处理*/
	usTimeDdSendNum = pstSelf->pfnGetTimeDdu_SendNum(pstSelf->pUsrData);

	if(usTimeDdSendNum)
	{
		if(usTimeDdSendNum != pstSelf->usDduSendNoAckNum)
		{
			SetSendTask(pstSelf, TSKID_DdTimeData, COT_SPONT, 0); // 第一次重启补发SOE
		}
	}
	else
	{
		pstSelf->usDduSendNoAckNum = 0;
	}
}


/**
* @brief    检查数据池中扰动遥测待发送数量
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void CheckDiturbYc_SendInfo(CS10xHandle_t pstSelf)
{
	unsigned short usDiturbYcSendNum = 0;

	if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M)  //作为主站时直接返回
	{
		return;
	}

	if(NULL == pstSelf->pfnGetDiturbYc_SendNum)
	{
		return;
	}

	usDiturbYcSendNum = pstSelf->pfnGetDiturbYc_SendNum(pstSelf->pUsrData); //获取数据表中待发的数量

	if(usDiturbYcSendNum)
	{
		/*未初始化完成，直接清空缓冲*/
		if((0 == pstSelf->ucInitStatus) && (NULL != pstSelf->pfnUpdata_DiturbYc_Pout))
		{
			pstSelf->pfnUpdata_DiturbYc_Pout(pstSelf->pUsrData, usDiturbYcSendNum);
		}
		else
		{
			SetSendTask(pstSelf, TSKID_YcDisturb, COT_SPONT, 0); //正常发送扰动遥测
		}
	}
}

/**
* @brief    检查是否有读取任务
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void PollFileTransTask(CS10xHandle_t pstSelf)
{
	int ret;

	if(NULL == pstSelf->pfnCheckTransFileObj ||
	        NULL == pstSelf->pfnCheckTransTimeOut)
	{
		return ;
	}

	if(GetTaskFlag(&pstSelf->stTaskFlags, TSKID_StartLink)
	   || pstSelf->bContinueSendFlag == false)
	{
		//IEC_PRINT("主模式下, 存在U帧激活任务, 直接返回\n");
		return ;
	}

	if(pstSelf->ucTransStatus != FILE_ST_IDLE) //主模式每次传输目录/文件完成, 置位传输状态
	{
		ret = pstSelf->pfnCheckTransTimeOut(pstSelf->pUsrData);

		if(ret < 0)
		{
			return ;
		}
		else
		{
			pstSelf->ucTransStatus = FILE_ST_IDLE;
			ClearTaskFlag(&pstSelf->stTaskFlags, TSKID_FilePro);// 直接清空上次文件传输任务
		}
	}

	ret = pstSelf->pfnCheckTransFileObj(&pstSelf->stRdSet, pstSelf->pUsrData);

	if(ret == TRANS_DIR)
	{
		SetSendTask(pstSelf, TSKID_FilePro, FILE_ST_RD_DIR, 0);
		pstSelf->ucTransStatus = FILE_ST_RD_DIR;
	}
	else if(ret == TRANS_FILE)
	{
		SetSendTask(pstSelf, TSKID_FilePro, FILE_ST_RD_FILE_ACT, 0);
		pstSelf->ucTransStatus = FILE_ST_RD_FILE_ACT;
	}
	else
	{
	}
}

/**
* @brief    设置M端对S端初始化后总召及对时处理
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void CS10x_M_Scheduled(CS10xHandle_t pstSelf, unsigned short usGap)
{
	if(CS104_TYPE_M == pstSelf->eCS10x_Type || CS101_TYPE_M == pstSelf->eCS10x_Type)  //主站
	{
		if(pstSelf->uiSummon_Gap)  //总召间隔
		{
			pstSelf->uiSummon_Tcn += usGap;

			if(pstSelf->uiSummon_Tcn >= pstSelf->uiSummon_Gap)
			{
				SetSendTask(pstSelf, TSKID_SummonResponse, COT_ACT, 0);
				pstSelf->uiSummon_Tcn = 0;
			}
		}

		if(pstSelf->uiESummon_Gap)  //总召间隔
		{
			pstSelf->uiESummon_Tcn += usGap;

			if(pstSelf->uiESummon_Tcn >= pstSelf->uiESummon_Gap)
			{
				SetSendTask(pstSelf, TSKID_DdSummon, COT_ACT, 0);
				pstSelf->uiESummon_Tcn = 0;
			}
		}

		if(pstSelf->uiSyn_Gap)  //同步间隔
		{
			pstSelf->uiTimeSyn_Tcn += usGap;

			if(pstSelf->uiTimeSyn_Tcn >= pstSelf->uiSyn_Gap)
			{
				pstSelf->uiTimeSyn_Tcn = 0;
				SetSendTask(pstSelf, TSKID_TimeSyn, COT_ACT, 0);
			}
		}

		if(pstSelf->pfnPollFileTransTask != NULL)
		{
			pstSelf->pfnPollFileTransTask(pstSelf);
		}
	}
}

/**
* @brief    接收到初始化完成标识
* @return     无
*/
void CS10x_M_Finish(CS10xHandle_t pstSelf)
{
	pstSelf->ucInitStatus = 1;

	/*101主站模式*/
	if(CS101_TYPE_M == pstSelf->eCS10x_Type)  //主站
	{
		SetSendTask(pstSelf, TSKID_SummonResponse, COT_ACT, 0);
		pstSelf->ucInitStatus = 1;
		pstSelf->uiInit_Tcn = 0;
		pstSelf->uiInit_Resend_Ncn = 0;
		pstSelf->ucRxLinkStatusFlag = 0;
		pstSelf->ucRxLinkRequestFlag = 0;
		pstSelf->ucRxAckFlag = 0;
		pstSelf->ucRxLinkResetFlag = 0;
	}
	else if(CS104_TYPE_M == pstSelf->eCS10x_Type)
	{
		SetSendTask(pstSelf, TSKID_SummonResponse, COT_ACT, 0);
		pstSelf->ucInitStatus = 1;
	}
}

/***************************************内部函数*******************************/
