 #include "RRMDataPrepare.h"
 #include "RRMManageAPI.h"

#if LINE_MAX_TRAIN > 255
#error LINE_MAX_TRAIN数值不能超过255，目前设备ID定义（类型（1字节）+ID（1字节））
#endif


/**============================================= 静态函数声明区 ==================================================== */
static UINT8 rrm_AddACInRRMPathSeq(UINT16 ACID,UINT8 dir,UINT8 type,OUT RRMPathOfACSeqStruct* pACSeq);    /** 添加计轴信息到RRM路径序列中 */


static UINT8 rrm_CheckObsAndSafeProtect(UINT8 funValid,UINT16 trainID,IN const RRMPathOfACSeqStruct* pACSeq,OUT UINT8* rrmReason);  /** 检查RRM路径中障碍物是否符合要求或者区段进行了安全防护 */
static UINT8 rrm_CheckSecStatus(UINT8 funValid,UINT16 trainID,IN const RRMPathOfACSeqStruct* pACSeq,OUT UINT8* rrmReason);  /** 检查RRM路径中区段是否符合要求（空闲/锁闭/锁闭方向一致） */
static UINT8 rrm_CheckSignalStatus(UINT8 funValid,UINT16 trainID,IN const RRMPathOfACSeqStruct* pACSeq,OUT UINT8* rrmReason); /** 检查列车车头前方至下一站站台终端之间信号机状态都为允许 */
static UINT8 rrm_CheckNextStation(UINT8 funValid,UINT16 trainID,UINT16 searchNextStaID,OUT UINT8* rrmReason);    /** 检查查询到的下一站信息是否与列车发送的下一站一致*/
static UINT8 rrm_CheckRRMPathAndSwtich(UINT8 funValid,UINT16 trainID,IN const EnvelopeStruct* pTemp,OUT RRMPathOfACSeqStruct* pACSeq, \
	OUT UINT8 *pNextTIOC,OUT UINT16 *pNextSta,OUT UINT8* rrmReason);  /** 查询RRM路径及道岔状态是否正确 */
static UINT8 rrm_CheckWLBrake(UINT8 funValid,UINT16 trainID,OUT UINT8* rrmReason);   /* 检查是否设置了全线紧急制动 */
static UINT8 rrm_CheckDirAndActIsSame(UINT8 funValid,UINT16 trainID, IN const EnvelopeStruct* pTemp,OUT UINT8* rrmReason);       /* 检查列车运行方向和激活端是否一致 */
static UINT8 rrm_CheckTrainInSta(UINT8 funValid,UINT16 trainID, IN const EnvelopeStruct* pTemp,OUT UINT8* rrmReason);            /* 检查列车是否在站台 */
static UINT8 rrm_ChecKForwardTrainAndArea(UINT8 funValid,UINT16 trainID, IN const EnvelopeStruct* pTemp,OUT UINT8* rrmReason);   /* 检查列车是否存在前方列车及是否在正线 */
static void rrm_ProcessTrainRRMRequst(UINT16 trainID);           /* 处理单车的远程RM申请 */

/**
 * @brief 检查是否是列车车头包络进入目标站台占压未进入
 * @param[in] UINT16 trainID 列车ID
 * @param[in] IN const EnvelopeStruct* pTemp 包络指针
 * @param[out] UINT16* pNextSta 下一站台
 * @return UINT8
		   CI_ERROR  否
		   CI_SUCCESS 是
 * by cgh 20241022
 */
static UINT8 rrm_CheckTrainHeadInFreeSta(UINT16 trainID, IN const EnvelopeStruct* pTemp, OUT UINT16* pNextSta);

/**
 * @brief 检查进路状态是否满足
 * @param[in] UINT16 wRouteId 进路ID
 * @return CI_ERROR 不满足
		   CI_SUCCESS 满足
 * @note BY CGH 20250807
 */
static UINT8 rrm_CheckRouteState(UINT16 wRouteId);

/**
 * @brief 添加计轴信息到RRM路径序列中
 * @param[in] UINT16 ACID 计轴ID
 * @param[in] UINT8 dir 方向
 * @param[in] UINT8 type 类型
 * @param[out] RRMPathOfACSeqStruct* pACSeq RRM路径包含的计轴序列
 * @return UINT8
           CI_SUCCESS 处理成功
           CI_ERROR 处理失败
 * @note 无
 */
static UINT8 rrm_AddACInRRMPathSeq(UINT16 ACID,UINT8 dir,UINT8 type,OUT RRMPathOfACSeqStruct* pACSeq)
{
	UINT8 ret = CI_ERROR;

	/** 入口参数校验 */
	ASSERT_RET_VALUE((NULL == pACSeq) || (MAX_AC_IN_RRM_PATH <= pACSeq->acCnt),ret,0x80000000u);
	ASSERT_RET_VALUE((ELM_DIR_SAME != dir) && (ELM_DIR_CONVERT != dir),ret,0x40000000u);
	ASSERT_RET_VALUE((TYPE_OF_PATH_A != type) && (TYPE_OF_PATH_B != type) && (TYPE_OF_PATH_C != type),ret,0x20000000u);


	pACSeq->ACID[pACSeq->acCnt] = ACID;
	pACSeq->runDir[pACSeq->acCnt] = dir;
	pACSeq->pathType[pACSeq->acCnt] = type;
	pACSeq->acCnt++;
	ret = CI_SUCCESS;

	return ret;
}




/**
 * @brief 检查RRM路径中障碍物是否符合要求或者区段进行了安全防护
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] RRMPathOfACSeqStruct* pACSeq RRM路径包含的计轴序列
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
           CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note 无
 */
static UINT8 rrm_CheckObsAndSafeProtect(UINT8 funValid,UINT16 trainID,IN const RRMPathOfACSeqStruct* pACSeq,OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0u;
	UINT8 funRtn = CI_ERROR;
	UINT16 cycle = 0u;
	UINT8 FlockStatus = ELM_AC_OCC;
	UINT8 FlockType = SEC_LOCK_ERROR;

	/** 入口参数校验 */
	ASSERT_RET_VALUE(NULL == pACSeq,ret,0x80000000u);
	ASSERT_RET_VALUE(NULL == rrmReason,ret,0x40000000u);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffu;
	}
	else
	{
		for(cycle = 0u; cycle < pACSeq->acCnt;cycle++)
		{
			/** 获取区段的封锁状态及封锁类型 */
			rrm_PrepareACFLockStatusAndType(pACSeq->ACID[cycle],&FlockStatus,&FlockType);
			if (PHYSICAL_SECTION_FLOCK_NO == FlockStatus)
			{
				/** 区段未封锁，ESB是否按下 */
				funRtn = rrm_PrepareESBStatOfAC(pACSeq->ACID[cycle]);
				if (CI_ERROR == funRtn)
				{
					*rrmReason = TRAIN_RRM_RESON_08;
					errorCode += 0x20000000u;
					break;
				}
				else
				{
					/** 继续遍历*/
				}


				/** PSD是否打开*/
				funRtn = rrm_PreparePSDStatOfAC(pACSeq->ACID[cycle]);
				if (CI_ERROR == funRtn)
				{
					*rrmReason = TRAIN_RRM_RESON_09;
					errorCode += 0x10000000u;
					break;
				}
				else
				{
					/** 继续遍历 */
				}

				/** 区段是否存在防护区域 */
				funRtn = rrm_PrepareSafeProtectOfAC(pACSeq->ACID[cycle]);
				if (CI_ERROR == funRtn)
				{
					*rrmReason = TRAIN_RRM_RESON_06;
					errorCode += 0x08000000u;
					break;
				}
				else
				{
					/** 继续遍历 */
				}

				/** 获取区段是否存在侵限或者侧防风险 */
				funRtn = rrm_PrepareVainAndLtrlDfncCheck(pACSeq->ACID[cycle]);
				if (CI_ERROR == funRtn)
				{
					*rrmReason = TRAIN_RRM_RESON_06;
					errorCode += 0x04000000u;
					break;
				}
				else
				{
					/** 继续遍历 */
				}

				/** 防淹门*/
				funRtn = rrm_PrepareFGStatOfAC(pACSeq->ACID[cycle]);
				if (CI_ERROR == funRtn)
				{
					*rrmReason = TRAIN_RRM_RESON_0C;
					errorCode += 0x01000000u;
					break;
				}
				else
				{
					/** 继续遍历 */
				}

				/** 获取区段是否存在区域紧急制动 */
				funRtn = rrm_PrepareAreaUrgentStatOfAC(pACSeq->ACID[cycle]);
				if (CI_ERROR == funRtn)
				{
					*rrmReason = TRAIN_RRM_RESON_06;
					errorCode += 0x00800000u;
					break;
				}
				else
				{
					/** 继续遍历 */
				}

			}
			else
			{
				if (PHY_SEC_FLOCK_TYPE_SPKS == FlockType)
				{
					*rrmReason = TRAIN_RRM_RESON_07;
				}
				else
				{
					*rrmReason = TRAIN_RRM_RESON_06;
				}
				errorCode += 0x02000000u;
				break;
			}
		}

		if (cycle == pACSeq->acCnt)
		{
			ret = CI_SUCCESS;
		}
		else
		{
			ret = CI_ERROR;	
		}
	}

	ASSER_DEBUG(0u != errorCode,RRM_LOG_LOC(RRM_LOG_ERROR,"errno:0x%08x info:Train%d not allow RRM by Obs error or Safe Protect.",errorCode,trainID));
	return ret;
}


/**
 * @brief 检查RRM路径中区段是否符合要求（空闲/锁闭/锁闭方向一致）
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] RRMPathOfACSeqStruct* pACSeq RRM路径包含的计轴序列
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
           CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note 无
 */
static UINT8 rrm_CheckSecStatus(UINT8 funValid,UINT16 trainID,IN const RRMPathOfACSeqStruct* pACSeq,OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0U;
	UINT16 cycle = 0U;
	UINT8 acOccStatus = ELM_AC_OCC;
	UINT8 acLockStatus = SEC_LOCK_ERROR;
	UINT8 acLockDir = 0U;
	UINT8 isReverArea = CI_ERROR;
	UINT8 isOverlapLock = CI_ERROR;

	/** 入口参数校验 */
	ASSERT_RET_VALUE(NULL == pACSeq,ret,0x80000000U);
	ASSERT_RET_VALUE(NULL == rrmReason,ret,0x40000000U);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffU;
	}
	else
	{
		for(cycle = 0u; cycle < pACSeq->acCnt;cycle++)
		{
			/** 获取计轴区段占用状态 */
			acOccStatus = rrm_PrepareACStatus(pACSeq->ACID[cycle]);
			rrm_PrepareACLockStatAndDir(pACSeq->ACID[cycle],pACSeq->pathType[cycle],&acLockStatus,&acLockDir);

			if (TYPE_OF_PATH_A == pACSeq->pathType[cycle])
			{
				isReverArea = rrm_PrepareACisRevertArea(pACSeq->ACID[cycle]);

				if (CI_SUCCESS == isReverArea)
				{
					if (SEC_LOCK_ERROR == acLockStatus)
					{
						/** 如果是折返区域，不检查车身处计轴的锁闭方向 */
						errorCode += 0x20000000U;
					}
					else
					{
						; /** 继续遍历 */
					}
				}
				else
				{
					if ((SEC_LOCK_ERROR == acLockStatus) || (acLockDir != pACSeq->runDir[cycle]))
					{
						errorCode += 0x10000000U;
					}
					else
					{
						; /** 继续遍历 */
					}
				}				
			}
			else if (TYPE_OF_PATH_C == pACSeq->pathType[cycle])
			{
				isOverlapLock = rrm_PrepareACisOverlapLock(pACSeq->ACID[cycle - 1U], pACSeq->ACID[cycle]);
				if (CI_TRUE == isOverlapLock)
				{
					; /*没有保护区段，此步跳过继续检查*/
				}
				else
				{
					if ((CI_ERROR == isOverlapLock) || (ELM_AC_FREE != acOccStatus) || (SEC_LOCK_ERROR == acLockStatus) || (acLockDir != pACSeq->runDir[cycle]))
					{
						/** 保护区段锁闭失败 */
						errorCode += 0x08000000U;
					}
					else
					{
						; /** 继续遍历 */
					}
				}
			}
			else
			{
				if ((ELM_AC_FREE != acOccStatus) || (SEC_LOCK_ERROR == acLockStatus) || (acLockDir != pACSeq->runDir[cycle]))
				{
					errorCode += 0x04000000U;
				}
				else
				{
					; /** 继续遍历 */
				}
			}

			if (0U != errorCode)
			{
				break;
			}
			else
			{
				; /*继续查找*/
			}
		}

		if (cycle == pACSeq->acCnt)
		{
			ret = CI_SUCCESS;
		}
		else
		{
			*rrmReason = TRAIN_RRM_RESON_06;
			ret = CI_ERROR;	
		}
	}

	ASSER_DEBUG(0U != errorCode,RRM_LOG_LOC(RRM_LOG_ERROR,"errno:0x%08x info:Train%d not allow RRM by SEC%d status error.",errorCode,trainID,pACSeq->ACID[cycle]));
	return ret;
}


/**
 * @brief 检查列车车头前方至下一站站台终端之间信号机状态都为允许
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] RRMPathOfACSeqStruct* pACSeq RRM路径包含的计轴序列
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
           CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note 
 */
static UINT8 rrm_CheckSignalStatus(UINT8 funValid,UINT16 trainID,IN const RRMPathOfACSeqStruct* pACSeq,OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0U;
	UINT16 cycle = 0U;
	UINT16 headOfRoute = 0U;  /*车头所在进路ID*/
	UINT16 tempofRoute = 0U;
	UINT8 sigOfRoutePass = CI_ERROR;
	UINT8 cCheckFlag = FLAG_UNSET;
	UINT8 chTempCheckFlag = 0U; /*临时检查标志*/
	UINT8 chLocalCiId = 0U;
	UINT8 chRouteBelongCiId = 0U;

	/** 入口参数校验 */
	ASSERT_RET_VALUE(NULL == pACSeq, ret, 0x80000000U);
	ASSERT_RET_VALUE(NULL == rrmReason, ret, 0x40000000U);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffU;
	}
	else
	{
		for (cycle = 0U; cycle < pACSeq->acCnt; cycle++)
		{
			if (TYPE_OF_PATH_A == pACSeq->pathType[cycle])
			{
				/*如果是车脚下区段，更新成车头最后一个计轴区段锁闭所属进路*/
				headOfRoute = rrm_PrepareAcofRoute(pACSeq->ACID[cycle]);
				if (0U == headOfRoute)
				{
					errorCode += 0x10000000U;
					cCheckFlag = FLAG_SET;  /** 区段进路未办理，那么肯定未锁闭 */
				}
				else
				{
					chTempCheckFlag = rrm_CheckRouteState(headOfRoute);
					if (CI_SUCCESS == chTempCheckFlag)
					{
						;
					}
					else
					{
						errorCode += 0x08000000U;
						cCheckFlag = FLAG_SET;
					}
				}
			}
			else if (TYPE_OF_PATH_C == pACSeq->pathType[cycle])
			{
				/** 无需处理*/
			}
			else if (TYPE_OF_PATH_B == pACSeq->pathType[cycle])
			{
				/** 查询当前区段所属已办进路 */
				tempofRoute = rrm_PrepareAcofRoute(pACSeq->ACID[cycle]);

				if (0U == tempofRoute)
				{
					errorCode += 0x04000000U;
					cCheckFlag = FLAG_SET;  /** 区段进路未办理，那么肯定未锁闭 */
				}
				else if (tempofRoute == headOfRoute)
				{
					/** 无需判断该进路始端信号机状态*/
				}
				else
				{
					/** 判断该进路始端信号机状态是否开放 */
					sigOfRoutePass = rrm_PrepareOriginSigStatOfRoute(tempofRoute);

					if (CI_SUCCESS == sigOfRoutePass)
					{
						/** 信号开放，继续遍历*/
					}
					else
					{
						chLocalCiId = GetSystemParaLocalCiId();
						chRouteBelongCiId = GetRouteBelongCiId(tempofRoute);
						chTempCheckFlag = rrm_CheckRouteState(tempofRoute);

						if ((chLocalCiId != chRouteBelongCiId) && (0U != chRouteBelongCiId) && (0U != chLocalCiId)
							&& (CI_SUCCESS == chTempCheckFlag))
						{
							/*非本控区内的信号正常关闭，继续检查*/
						}
						else
						{
							errorCode += 0x02000000U;
							cCheckFlag = FLAG_SET;
						}	
					}
				}
			}
			else
			{
				errorCode += 0x01000000U;
				cCheckFlag = FLAG_SET;  /** 路径错误，检查失败*/
			}

			if (FLAG_SET == cCheckFlag)
			{
				break;
			}
			else
			{
				; /*继续检查*/
			}
		}

		if (cycle == pACSeq->acCnt)
		{
			ret = CI_SUCCESS;
		}
		else
		{
			*rrmReason = TRAIN_RRM_RESON_05;
			errorCode += 0x20000000u;
			ret = CI_ERROR;
		}
	}

	ASSER_DEBUG(0u != errorCode,RRM_LOG_LOC(RRM_LOG_ERROR,"errno:0x%08x info:Train%d not allow RRM by tempofRoute%d or headOfRoute%d signal not open.",errorCode,trainID,tempofRoute, headOfRoute));
	return ret;
}



/**
 * @brief 检查查询到的下一站信息是否与列车发送的下一站一致
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] UINT16 searchNextStaID 查询到的下一站台ID
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
           CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note 无
 */
static UINT8 rrm_CheckNextStation(UINT8 funValid,UINT16 trainID,UINT16 searchNextStaID,OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0u;
	UINT16 trainNextStaID = 0u;

	/** 入口参数校验 */
	ASSERT_RET_VALUE(NULL == rrmReason,ret,0x80000000u);
	
	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffu;
	}
	else
	{
		/** 获取列车的下一张站台*/
		trainNextStaID = rrm_PrepareNextStaOfTrain(trainID);

		if (trainNextStaID == searchNextStaID)
		{
			ret = CI_SUCCESS;
		}
		else
		{
			*rrmReason = TRAIN_RRM_RESON_0B;
			errorCode += 0x40000000u;
			ret = CI_ERROR;	
		}
	}

	ASSER_DEBUG(0u != errorCode,RRM_LOG_LOC(RRM_LOG_ERROR,"errno:0x%08x info:Train%d not allow RRM by dst error.",errorCode,trainID));
	return ret;
}

/**
 * @brief 查询RRM路径及道岔状态是否正确
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] IN const EnvelopeStruct* pTemp 包络指针
 * @param[out] RRMPathOfACSeqStruct* pACSeq RRM路径包含的计轴序列
 * @param[out] UINT8 *pNextTIOC 下一TIOC ID
 * @param[out] UINT16 *pNextSta 下一站台
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
           CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note 无
 */
static UINT8 rrm_CheckRRMPathAndSwtich(UINT8 funValid,UINT16 trainID,IN const EnvelopeStruct* pTemp,OUT RRMPathOfACSeqStruct* pACSeq,OUT UINT8 *pNextTIOC,OUT UINT16 *pNextSta,OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0u;
	UINT8 validFlag = 0u;
	UINT8 funRtn = CI_ERROR;
	UINT16 nexStaID = 0u;
	UINT8 nextOCId = 0u;
	UINT8 ACIsOwn = 0u;
	UINT8 cycle = 0u;
	UINT8 cyclePath = 0u;
	UINT16 curACID = 0u;
	UINT8 curDir = 0u;
	UINT16 nextACCnt = 0u;
	UINT16 nextACId[AC_MAXCNT_IN_SWITCH] = {0u};
	UINT8 cDirectionPointFlag = 0U;			/*是否具有方向变化点标志*/
	UINT8 chAtsLgcStaIsOwnCheck = CI_ERROR;/*ATS下发的停车区域ID是否属于本控区检查*/
	UINT16 wAtsLgcStaId = 0U;
	UINT8 chHeadStationCheck = 0U;/*车头站台检查*/

	/** 入口参数校验*/
	ASSERT_RET_VALUE((NULL == pTemp) || (0u == pTemp->ACCnt),ret,0x80000000u);
	ASSERT_RET_VALUE(NULL == rrmReason,ret,0x40000000u);
	ASSERT_RET_VALUE(NULL == pACSeq,ret,0x20000000u);
	ASSERT_RET_VALUE(NULL == pNextTIOC,ret,0x10000000u);
	ASSERT_RET_VALUE(NULL == pNextSta,ret,0x08000000u);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffu;
	}
	else
	{
		/** 缓存车尾计轴区段 */
		curACID = pTemp->ACID[0u];
		curDir = pTemp->startPos.Dir;
		funRtn = rrm_AddACInRRMPathSeq(curACID,curDir,TYPE_OF_PATH_A,pACSeq);
		ASSER_ERROR(CI_ERROR ==funRtn,errorCode,0x04000000u);

		if (0u == errorCode)
		{
			/** 缓存车身范围内的计轴区段 */
			for (cycle = 1u; cycle < pTemp->ACCnt;cycle++)
			{
				nextACCnt = rrm_PrepareAdjacentAC(curACID, curDir, nextACId, &cDirectionPointFlag);

				/** 如果查询多个计轴区段，则代表道岔位置不符合要求或者查询掉头失败 */
				if ((1u == nextACCnt) && (nextACId[0u] == pTemp->ACID[cycle]))
				{
					/** 判断是否遇到方向变化点 */
					curDir = (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag) ? ((UINT8)(~curDir)) : curDir;

					/** 更换基准查询计轴 */
					curACID = nextACId[0u];

					/** 将查询成功的计轴插入到计轴序列中 */
					funRtn = rrm_AddACInRRMPathSeq(curACID,curDir,TYPE_OF_PATH_A,pACSeq);
					ASSERT_BREAK(CI_ERROR == funRtn,errorCode,0x02000000u);
				}
				else
				{
					/** 如果查询多个计轴区段，则代表道岔位置不符合要求或者查询掉头失败或者包络路径错误 */
					errorCode += 0x01000000u;
					break;
				}
			}

			/** 继续查询车头到下一站台之间的计轴区段 */
			if (cycle == pTemp->ACCnt)
			{
				chHeadStationCheck = rrm_CheckTrainHeadInFreeSta(trainID, pTemp,&nexStaID);
				if (CI_SUCCESS == chHeadStationCheck)
				{
					/** 找到下一站台，查询站台前方信息 */
					nextACCnt = rrm_PrepareAdjacentAC(curACID, curDir, nextACId, &cDirectionPointFlag);

					if (0U == nextACCnt)
					{
						/** 如果下一计轴区段数目为0，说明是尽头线，此时不记录下一站台前方计轴区段，但需要往下记录计算出的逻辑站台ID by cgh 20231102*/
						;
					}
					else
					{
						/** 如果查询多个计轴区段，则代表道岔位置不符合要求 */
						ASSER_ERROR(1u != nextACCnt, errorCode, 0x00004000u);

						/** 判断是否遇到方向变化点 */
						curDir = (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag) ? ((UINT8)(~curDir)) : curDir;

						curACID = nextACId[0U];

						/** 将查询成功的计轴插入到计轴序列*/
						funRtn = rrm_AddACInRRMPathSeq(curACID, curDir, TYPE_OF_PATH_C, pACSeq);
						ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x00002000u);
					}

					/** 缓存下一站站台ID*/
					*pNextSta = nexStaID;

					/** 不进入循环 */
					validFlag = 0xffu;
				}
				else
				{
					nexStaID = 0U; /*其他情况继续查找*/
				}

				while (0u == validFlag)
				{
					/** 有rrm_AddACInRRMPathSeq函数做死循环防护 */
					nextACCnt = rrm_PrepareAdjacentAC(curACID, curDir, nextACId, &cDirectionPointFlag);

					/** 如果查询多个计轴区段，则代表道岔位置不符合要求或者查询掉头失败 */
					ASSERT_BREAK((1u != nextACCnt) || (nextACId[0u] == pACSeq->ACID[pACSeq->acCnt - 1u]), errorCode, 0x00800000u);

					/** 判断是否为站台 */
					nexStaID = rrm_PrepareAtsLgcStaOfAC(nextACId[0u]);
					ASSERT_BREAK(0xffffu == nexStaID, errorCode, 0x00400000u);

					/** 查询计轴是否属于本集中区 */
					ACIsOwn = rrm_PrepareACIsSelf(nextACId[0u], &nextOCId);
					ASSERT_BREAK(0u == nextOCId, errorCode, 0x00200000u);

					if ((ELM_BELONG_OWNER != ACIsOwn) && (0u != nextOCId))
					{
						/*需要先判断计轴区段所属控区！
						 *若先判断站台，在列车跨分界点且车头在相邻控区站台时，本控区将会先查到站台轨并且将其归类TYPE_OF_PATH_B，在区段检查时将因为占用而失败，
						 *将不再向相邻RC申请RRM，与需求方案不符*/
						wAtsLgcStaId = rrm_PrepareNextStaOfTrain(trainID);

						chAtsLgcStaIsOwnCheck = rrm_PrepareAtsLgcStaIsOwn(wAtsLgcStaId);

						if (CI_SUCCESS == chAtsLgcStaIsOwnCheck)
						{
							/*当RRM命令中站台ID有误，为本控区站台但不在列车前方路径（在列车后方或列车前方为上行轨道，命令站台在下行轨道）
						 *本控区应直接检查失败不向相邻RC继续发送申请*/

							*pNextTIOC = nextOCId;  /** 设置下一TIOC ID*/
						}
						else
						{
							;
						}
						ASSER_ERROR(CI_ERROR == chAtsLgcStaIsOwnCheck, errorCode, 0x00100000U);
						validFlag = 0xffu;  /** 退出循环 */
					}
					else if (0u != nexStaID)
					{
						/** 判断是否遇到方向变化点 */
						curDir = (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag) ? ((UINT8)(~curDir)) : curDir;

						/** 更换基准查询计轴 */
						curACID = nextACId[0u];

						/** 将查询成功的计轴插入到计轴序列*/
						funRtn = rrm_AddACInRRMPathSeq(curACID, curDir, TYPE_OF_PATH_B, pACSeq);
						ASSERT_BREAK(CI_ERROR == funRtn, errorCode, 0x00080000u);

						/** 找到下一站台，查询站台前方信息 */
						nextACCnt = rrm_PrepareAdjacentAC(curACID, curDir, nextACId, &cDirectionPointFlag);

						if (0U == nextACCnt)
						{
							/** 如果下一计轴区段数目为0，说明是尽头线，此时不记录下一站台前方计轴区段，但需要往下记录计算出的逻辑站台ID by cgh 20231102*/
							;
						}
						else
						{
							/** 如果查询多个计轴区段，则代表道岔位置不符合要求 */
							ASSERT_BREAK((1u != nextACCnt) || (nextACId[0u] == pACSeq->ACID[pACSeq->acCnt - 1u]), errorCode, 0x00040000u);

							/** 判断是否遇到方向变化点 */
							curDir = (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag) ? ((UINT8)(~curDir)) : curDir;

							/** 更换基准查询计轴 */
							curACID = nextACId[0u];

							/** 将查询成功的计轴插入到计轴序列*/
							funRtn = rrm_AddACInRRMPathSeq(curACID, curDir, TYPE_OF_PATH_C, pACSeq);
							ASSERT_BREAK(CI_ERROR == funRtn, errorCode, 0x00020000u);
						}

						/** 缓存下一站站台ID*/
						*pNextSta = nexStaID;

						/** 退出循环 */
						validFlag = 0xffu;
					}
					else
					{
						/** 判断是否遇到方向变化点 */
						curDir = (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag) ? ((UINT8)(~curDir)) : curDir;

						/** 更换基准查询计轴 */
						curACID = nextACId[0u];

						/** 将查询成功的计轴插入到计轴序列*/
						funRtn = rrm_AddACInRRMPathSeq(curACID, curDir, TYPE_OF_PATH_B, pACSeq);
						ASSERT_BREAK(CI_ERROR == funRtn, errorCode, 0x00010000u);
					}
				}

				if (0u != errorCode)
				{
					if (0x00100000U == (errorCode & 0x00100000U))
					{
						*rrmReason = TRAIN_RRM_RESON_0B;
					}
					else
					{
						*rrmReason = TRAIN_RRM_RESON_0A;
					}
					ret = CI_ERROR;
				}
				else
				{
					/** 校验路径内的道岔位置是否正确 */
					for (cyclePath = 0u; cyclePath < pACSeq->acCnt; cyclePath++)
					{
						funRtn = rrm_PrepareSwitchStatOfAC(pACSeq->ACID[cyclePath]);
						ASSERT_BREAK(CI_ERROR == funRtn, errorCode, 0x00008000u);
					}

					if (cyclePath == pACSeq->acCnt)
					{
						ret = CI_SUCCESS;
					}
					else
					{
						*rrmReason = TRAIN_RRM_RESON_0A;
						ret = CI_ERROR;
					}
				}
			}
			else
			{
				*rrmReason = TRAIN_RRM_RESON_0A;
				ret = CI_ERROR;	
			}
		}
		else
		{
			/** 处理失败 */
			*rrmReason = TRAIN_RRM_RESON_0A;
			ret = CI_ERROR;	
		}
	}

	debug_infor_printf((const)"rrm_CheckRRMPathAndSwtich:num = %d\n", pACSeq->acCnt);
	debug_out_array(0xAA, pACSeq->ACID, pACSeq->acCnt * 2u);

	ASSER_DEBUG(0u != errorCode,RRM_LOG_LOC(RRM_LOG_ERROR,"errno:0x%08x info:Train%d not allow RRM by seach Path error .",errorCode,trainID));
	return ret;
}


/**
 * @brief 检查是否设置了全线紧急制动
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
           CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note 无
 */
static UINT8 rrm_CheckWLBrake(UINT8 funValid,UINT16 trainID,OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT8 funRtn = rrm_PrepareWLBrake();
	UINT32 errorCode = 0u;

	/** 入口参数校验 */
	ASSERT_RET_VALUE(NULL == rrmReason,ret,0x80000000u);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffu;
	}
	else
	{
		if (CI_SUCCESS == funRtn)
		{
			errorCode += 0x40000000u;
			*rrmReason = TRAIN_RRM_RESON_02;
			ret = CI_ERROR;	
		}
		else
		{
			ret = CI_SUCCESS;	
		}
	}
	ASSER_DEBUG(0u != errorCode,RRM_LOG_LOC(RRM_LOG_ERROR,(const)"errno:0x%08x info:Train%d not allow RRM by WlBrake .",errorCode,trainID));
	return ret;
}

/**
 * @brief 检查列车运行方向和激活端是否一致
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] IN const EnvelopeStruct* pTemp 包络指针
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
           CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note 无
 */
static UINT8 rrm_CheckDirAndActIsSame(UINT8 funValid,UINT16 trainID, IN const EnvelopeStruct* pTemp,OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0u;
	UINT8 chDir = 0u;
	UINT8 chAct = 0u;

	/** 入口参数校验 */
	ASSERT_RET_VALUE((NULL == pTemp) || (0u == pTemp->trianCnt),ret,0x80000000u);
	ASSERT_RET_VALUE(NULL == rrmReason,ret,0x40000000u);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffu;
	}
	else
	{
		/** 获取列车的激活端 */
		rrm_PrepareTrainDirAndAct(trainID,&chDir,&chAct);

		if ((trainID == pTemp->trainID[pTemp->trianCnt - 1u])
			&& (pTemp->ACTPort[pTemp->trianCnt - 1u] == chAct))
		{
			/** 运行方向一致 */
			ret = CI_SUCCESS;	
		}
		else
		{

			errorCode += 0x10000000u;
			*rrmReason = TRAIN_RRM_RESON_17;
			ret = CI_ERROR;	
		}
	}

	ASSER_DEBUG(0u != errorCode,RRM_LOG_LOC(RRM_LOG_ERROR,(const)"errno:0x%08x info:Train%d not allow RRM by Dir or act not same .",errorCode,trainID));
	return ret;
}


/**
 * @brief 检查列车是否在站台
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] IN const EnvelopeStruct* pTemp 包络指针
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
           CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note 无
 */
static UINT8 rrm_CheckTrainInSta(UINT8 funValid,UINT16 trainID, IN const EnvelopeStruct* pTemp,OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0U;
	UINT8 RRMStaSwitch = rrm_PrepareRRMStaSwitch();
	UINT16 headRelStaID = 0U;
	UINT16 tailRelStaID = 0U;
	UINT16 trainNextSta = 0U;
	UINT16 preEnvelopeid = 0U;
	UINT16 backEnvelopeid = 0U;
	UINT8 chCheckFlag = CI_ERROR;
	UINT8 chHeadAcStatus = 0U; /*车头计轴区段占用状态*/

	/** 入口参数校验 */
	ASSERT_RET_VALUE((NULL == pTemp) || (0U == pTemp->ACCnt),ret,0x80000000U);
	ASSERT_RET_VALUE(NULL == rrmReason,ret,0x40000000U);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffU;
	}
	else
	{
		headRelStaID = rrm_PrepareAtsLgcStaOfAC(pTemp->ACID[pTemp->ACCnt - 1U]);
		tailRelStaID = rrm_PrepareAtsLgcStaOfAC(pTemp->ACID[0U]);
		ASSER_ERROR((0xffffU == headRelStaID) || (0xffffU == tailRelStaID),errorCode,0x20000000U);

		if (0U == errorCode)
		{
			trainNextSta = rrm_PrepareNextStaOfTrain(trainID);

			if (0U != headRelStaID)
			{
				ret = CI_ERROR;
				if (trainNextSta == headRelStaID)
				{
					chHeadAcStatus = rrm_PrepareACStatus(pTemp->ACID[pTemp->ACCnt - 1U]);
					if (ELM_AC_OCC == chHeadAcStatus)
					{
						/** 列车到达站台 */
						errorCode += 0x10000000U;
						*rrmReason = TRAIN_RRM_RESON_0D;
					}
					else
					{
						/*车头包络进入但占压未进入，等待*/
						ret = CI_SUCCESS;
					}
				}
				else
				{
					if (CI_SUCCESS == RRMStaSwitch)
					{
						/*跨分界点，当前为出发站台支持出站RRM，前方有自己包络，要返回成功*/
						chCheckFlag = elm_GetNearEnvelopRelSameTra(pTemp->id, &preEnvelopeid, &backEnvelopeid);
						if ((CI_SUCCESS == chCheckFlag) && (0U != preEnvelopeid))
						{
							ret = CI_SUCCESS;
						}
						else
						{
							/** 列车在站台 */
							errorCode += 0x01000000U;
							*rrmReason = TRAIN_RRM_RESON_0E;
						}

					}
					else
					{
						/** 列车在站台 */
						errorCode += 0x08000000U;
						*rrmReason = TRAIN_RRM_RESON_0E;
					}
				}		
			}
			else if(0U != tailRelStaID)
			{
				if (CI_SUCCESS == RRMStaSwitch)
				{
					if (trainNextSta == tailRelStaID)
					{
						/** 列车到达站台 */
						errorCode += 0x04000000U;
						*rrmReason = TRAIN_RRM_RESON_0D;
						ret = CI_ERROR;

					}
					else
					{
						/** 允许RRM */
						ret = CI_SUCCESS;	
					}
				}
				else
				{
					/** 列车在站台 */
					errorCode += 0x02000000U;
					*rrmReason = TRAIN_RRM_RESON_0E;
					ret = CI_ERROR;	
				}
			}
			else
			{
				/** 允许RRM */
				ret = CI_SUCCESS;	
			}
		}
	}
	ASSER_DEBUG(0U != errorCode,RRM_LOG_LOC(RRM_LOG_ERROR,(const)"errno:0x%08x info:Train%d In sta not allow RRM.",errorCode,trainID));
	return ret;
}


/**
 * @brief 检查列车是否存在前方列车及是否在正线
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] IN const EnvelopeStruct* pTemp 包络指针
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
           CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note 无
 */
static UINT8 rrm_ChecKForwardTrainAndArea(UINT8 funValid,UINT16 trainID, IN const EnvelopeStruct* pTemp,OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT8 funRtn = CI_ERROR;
	UINT32 errorCode = 0u;

	/** 入口参数校验 */
	ASSERT_RET_VALUE((NULL == pTemp) || (0u == pTemp->trianCnt),ret,0x80000000u);
	ASSERT_RET_VALUE(NULL == rrmReason,ret,0x40000000u);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffu;
	}
	else
	{
		if ((0u == pTemp->headTrainID) && (trainID == pTemp->trainID[pTemp->trianCnt - 1u]))
		{
			/** 判断列车车头占压区段是否存在其他通信车 */
			funRtn = rrm_PrepareForwardTrain(pTemp);
			if (CI_SUCCESS == funRtn)
			{
				/** 判断列车是否都处于正线 */
				funRtn = rrm_PrepareTrainAreaIsZX(pTemp);

				if (CI_SUCCESS == funRtn)
				{
					ret = CI_SUCCESS;
				}
				else
				{
					errorCode += 0x20000000u;
					ret = CI_ERROR;
					*rrmReason = TRAIN_RRM_RESON_16;
				}
			}
			else
			{
				errorCode += 0x10000000u;
				ret = CI_ERROR;
				*rrmReason = TRAIN_RRM_RESON_16;
			}
		}
		else
		{
			errorCode += 0x08000000u;
			ret = CI_ERROR;
			*rrmReason = TRAIN_RRM_RESON_16;
		}
	}

	ASSER_DEBUG(0u != errorCode,RRM_LOG_LOC(RRM_LOG_ERROR,(const)"errno:0x%08x info:Train%d ChecKForwardTrainAndArea error.",errorCode,trainID));
	return ret;
}


/**
 * @brief 处理单车的远程RM申请
 * @param[in] UINT16 trainID 列车ID
 * @param[out] 无
 * @return 无
 * @note 无
 */
static void rrm_ProcessTrainRRMRequst(UINT16 trainID)
{
	UINT8 funValid = RRM_CHECK_VALID;
	UINT8 funRtn = CI_ERROR;
	UINT32 errorCode = 0u;
	const EnvelopeStruct* pTemp = NULL;
	UINT8 rrmReason = TRAIN_RRM_RESON_FF;
	UINT8 NextTIOC = 0u;
	UINT16 NextSta = 0u;
	RRMPathOfACSeqStruct ACSeq = {0u};
	UINT8 chRrmDstAllowed = TRAIN_RRM_OTHERCI_NOT_ALLOW;/* 跨控区远程RM-目标TIOC不允许*/
	UINT16 wAxisRelateCfpId = 0U;/*计轴区段关联分界点ID*/
	UINT16 trainNextStaID = 0U;/*列车发送的下一站ID*/
	UINT8 cLocalCiId = 0U;

	/** 获取列车关联的UCT包络 */
	pTemp = rrm_PrepareTrainRelELM(trainID);

	/** 判断列车是否关联UCT包络 */
	if (NULL == pTemp)
	{
		RRM_LOG(RRM_LOG_FATAL,"info:Train%d not exit UCT ELM.\n!",trainID);
		rrm_SetRRMResult(trainID,TRAIN_RRM_DEFAULT,TRAIN_RRM_RESON_FF,0u);
	}
	else
	{
		/** 检查列车是否处于分界点且未向移交RC申请RRM */
		funRtn = rrm_CfpTrainApplyCheck(trainID, pTemp);
		ASSERT_SETRET(CI_SUCCESS == funRtn, rrmReason, rrmReason, TRAIN_RRM_RESON_15);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x80000000u);

		/** 检查列车是否存在前方列车及是否在正线 */
		funRtn = rrm_ChecKForwardTrainAndArea(funValid, trainID, pTemp, &rrmReason);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x40000000u);

		/** 检查列车是否在站台 */
		funRtn = rrm_CheckTrainInSta(funValid, trainID, pTemp, &rrmReason);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x20000000u);

		/** 检查列车运行方向和激活端是否一致 */
		funRtn = rrm_CheckDirAndActIsSame(funValid, trainID, pTemp, &rrmReason);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x10000000u);

		/** 检查是否设置了全线紧急制动*/
		funRtn = rrm_CheckWLBrake(funValid, trainID, &rrmReason);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x08000000u);

		/** 查询本控区RRM路径及道岔状态是否正确 */
		funRtn = rrm_CheckRRMPathAndSwtich(funValid, trainID, pTemp, &ACSeq, &NextTIOC, &NextSta, &rrmReason);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x04000000u);

		/** 检查列车车头前方至下一站站台终端(或到分界点)之间信号机状态都为允许 */
		funRtn = rrm_CheckSignalStatus(funValid, trainID, &ACSeq, &rrmReason);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x02000000u);

		/** 检查本控区RRM路径中区段是否符合要求（空闲/锁闭/锁闭方向一致） */
		funRtn = rrm_CheckSecStatus(funValid, trainID, &ACSeq, &rrmReason);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x01000000u);

		/** 检查本控区RRM路径中障碍物是否符合要求或者区段进行了安全防护 */
		funRtn = rrm_CheckObsAndSafeProtect(funValid, trainID, &ACSeq, &rrmReason);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x00800000u);

		if ((RRM_CHECK_VALID == funValid) && (0u == errorCode))
		{
			if (0U == NextTIOC)
			{
				/** 路径都在本集中区*/
				/*查询RM路径时，查到下一站ID或者下一个控区ID会跳出，此时若下一个控区ID为0；说明本控区存在站台
				 *若跨控区，列车发送的“运行方向”查询到分界点处无其他站台检查条件自然在下面可检查
				 *若不跨控区，检查查询到的下一站信息是否与列车发送的下一站一致 */
				funRtn = rrm_CheckNextStation(funValid, trainID, NextSta, &rrmReason);
				ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
				ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x00400000u);

				if (RRM_CHECK_VALID == funValid)
				{
					rrm_SetRRMResult(trainID, TRAIN_RRM_YES, TRAIN_RRM_RESON_FF, 0U);
					RRM_LOG_LOC(RRM_LOG_ERROR, "Train%d allow RRM.",trainID);
				}
				else
				{
					/** 处理失败 */
					rrm_SetRRMResult(trainID, TRAIN_RRM_NO, rrmReason, 0u);
					RRM_LOG_LOC(RRM_LOG_ERROR, "errno:0x%08x info:Train%d not allow RRM.", errorCode, trainID);
				}
			}
			else
			{
				/*远程RM跨控区*/
				if (0U != NextSta)
				{
					/*查询RM路径时，查到下一站ID或者下一个控区ID会跳出，此时若下一个控区ID不为0；说明本控区不存在站台，列车发送的“运行方向”查询到分界点处无其他站台检查条件自然通过*/
					/*跨联锁远程RM:查询到分界点处无其他站台*/
					rrmReason = TRAIN_RRM_RESON_0B;
					funRtn = CI_ERROR;
					ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
					ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x00200000u);

					rrm_SetRRMResult(trainID, TRAIN_RRM_NO, rrmReason, NextTIOC);
					RRM_LOG_LOC(RRM_LOG_ERROR, "errno:0x%08x info:Train%d OtherCI not allow RRM.", errorCode, trainID);
				}
				else
				{
					funRtn = rrm_PrepareRcIsZXorSCX(NextTIOC);  /*检查下一控区是否为正线或试车线*/
					if (CI_SUCCESS == funRtn)
					{
						/*本控区所有条件检查通过，发送相邻联锁检查剩余区段*/
						wAxisRelateCfpId = GetAxisRelateCfpId(ACSeq.ACID[ACSeq.acCnt - 1U]);
						SetCfpRrmSrcApplyState(wAxisRelateCfpId, TRAIN_RRM_LOCALCI_APPLY);
						SetCfpRrmTrainId(wAxisRelateCfpId, trainID);

						trainNextStaID = rrm_PrepareNextStaOfTrain(trainID);
						SetCfpRrmTrainNextStaId(wAxisRelateCfpId, trainNextStaID);

						cLocalCiId = GetSystemParaLocalCiId();
						SetCfpRrmSrcRcId(wAxisRelateCfpId, cLocalCiId);

						/*继续检查跨控区远程RM时，目标TIOC允许状态*/
						chRrmDstAllowed = GetCfpRrmDstAllowState(wAxisRelateCfpId);
						if (TRAIN_RRM_OTHERCI_ALLOW == chRrmDstAllowed)
						{
							rrm_SetRRMResult(trainID, TRAIN_RRM_YES, TRAIN_RRM_RESON_FF, NextTIOC);
							RRM_LOG_LOC(RRM_LOG_ERROR, "Train%d allow RRM.", trainID);
						}
						else
						{
							rrmReason = TRAIN_RRM_RESON_15;
							rrm_SetRRMResult(trainID, TRAIN_RRM_NO, rrmReason, NextTIOC);
							errorCode += 0x00100000U;
							RRM_LOG_LOC(RRM_LOG_ERROR, "errno:0x%08x info:Train%d OtherCI not allow RRM.", errorCode, trainID);
						}
					}
					else
					{
						funValid = RRM_CHECK_UNVALID;
						rrmReason = TRAIN_RRM_RESON_16;
						rrm_SetRRMResult(trainID, TRAIN_RRM_NO, rrmReason, NextTIOC);
						errorCode += 0x00080000U;
						RRM_LOG_LOC(RRM_LOG_ERROR, "errno:0x%08x info:Train%d OtherCI not allow RRM.", errorCode, trainID);
					}
				}
			}
		}
		else
		{
			/** 处理失败 */
			rrm_SetRRMResult(trainID, TRAIN_RRM_NO, rrmReason, 0u);
			RRM_LOG_LOC(RRM_LOG_ERROR, "errno:0x%08x info:Train%d not allow RRM.", errorCode, trainID);
		}
	}
}

/**
 * @brief 远程RM主处理函数
 * @param[in] 无
 * @param[out] 无
 * @return 无
 * @note 无
 */
void rrm_MainProcess(void)
{
	UINT16 cycle = 0u;
	UINT8 rrmFunSwitch = rrm_PrepareRRMSwitch();
	UINT8 rrmRequest = CI_ERROR;

	/** 判断功能开关是否打开 */
	if (CI_SUCCESS == rrmFunSwitch)
	{
		/*- 处理车的远程RM申请 */
		for (cycle = 1u; cycle < TRAIN_SUM_MAX;cycle++)
		{
			/** 获取列车的RRM申请状态 */
			rrmRequest = rrm_PrepareRRMRequest(cycle);

			if (CI_SUCCESS == rrmRequest)
			{
				/** 列车RRM处理 */
				rrm_ProcessTrainRRMRequst(cycle);
			}
			else
			{
				/** 列车未申请，设置列车RRM允许标志位为默认值，不允许原因为默认值 */
				rrm_SetRRMResult(cycle,TRAIN_RRM_DEFAULT,TRAIN_RRM_RESON_FF,0u);
			}
		}
	}
	else
	{
		/** 功能开关未打开，无需处理 */
	}
}


/**
 * @brief 接口：获取发送给ATS的UCT列车信息
 * @param[in] 无
 * @param[out] ATSTrainInfoStru* pInfo)
 * @return 无
 * @note 无
 */
void rrm_GetInfToATSUCTInfo(OUT ATSTrainInfoStru* pInfo)
{
	UINT16 cycle = 0u;
	UINT16 secTail = 0u;
	const EnvelopeStruct* pTemp = NULL;

	/** 入口参数校验 */
	if (NULL == pInfo)
	{
		/** 入口参数错误*/
	}
	else
	{
		/** 清空缓存区 */
		(void)CommonMemSet(pInfo, (UINT32)sizeof(ATSTrainInfoStru), 0u , (UINT32)sizeof(ATSTrainInfoStru));

		for (cycle = 0u; cycle < LINE_MAX_TRAIN;cycle++)
		{
			/** 获取列车关联的包络 */
			pTemp = rrm_PrepareTrainRelELM(cycle);

			if ((NULL != pTemp) && (pInfo->trainCnt < TRAIN_SUM_MAX_IN_OC))
			{
				secTail = rrm_PrepareSecIDofTail(cycle,pTemp);

				if (0u != secTail)
				{
					pInfo->TrainID[pInfo->trainCnt] = (UINT16)(cycle & 0x00ffu) + (UINT16)(DEVTYPE_VOBC << 8u);
					pInfo->TailSecID[pInfo->trainCnt] = secTail;
					pInfo->trainCnt++;
				}
				else
				{
					/** 查询失败，不向ATS汇报该UCT列车 */
				}
			}
			else
			{
				/** 不处理 */
			}
		}
	}
}

/**
 * @brief 相邻联锁RRM条件检查
 * @param[in] const UINT16 wTrainID 列车ID
 * @param[in] const UINT16 wTrainNextStaId 列车下一站站台ID
 * @param[in] const UINT16 wAxisSecId 边界计轴区段ID
 * @param[in] const UINT8 chCheckDir 查询方向
 * @param[out] 无
 * @return CI_ERROR 检查失败
 *		   CI_SUCCESS 检查成功
 * @note by cgh 20240221
 */
UINT8 rrm_OtherCiConditionsCheck(const UINT16 wTrainID, const UINT16 wTrainNextStaId, const UINT16 wAxisSecId, const UINT8 chCheckDir)
{
	UINT8 chReval = CI_ERROR;/*检查结果*/
	UINT8 funValid = RRM_CHECK_VALID;
	UINT8 funRtn = CI_ERROR;
	UINT32 errorCode = 0U;
	UINT8 rrmReason = TRAIN_RRM_RESON_FF;
	UINT8 NextTIOC = 0U;
	UINT16 NextSta = 0U;
	RRMPathOfACSeqStruct ACSeq = { 0U };
	EnvelopeStruct* pTemp = NULL;
	UINT8 chRrmDstAllowed = TRAIN_RRM_OTHERCI_NOT_ALLOW;/* 跨控区远程RM-目标TIOC不允许*/
	UINT16 wAxisRelateCfpId = 0U;/*计轴区段关联分界点ID*/
	UINT8 cLocalCiId = 0U;

	/*入参防护*/
	ASSERT_RET_VALUE(((0U == (wTrainID & 0x00FFU)) || (0x00FFU == (wTrainID & 0x00FFU))), chReval, 0x80000000U);
	ASSERT_RET_VALUE((0U == wTrainNextStaId) || (UINT16_MAX == wTrainNextStaId), chReval, 0x40000000U);
	ASSERT_RET_VALUE((0U == wAxisSecId) || (AXIS_SECTION_SUM_MAX <= wAxisSecId), chReval, 0x20000000U);
	ASSERT_RET_VALUE((EMAP_CONVER_DIR != chCheckDir) && (EMAP_SAME_DIR != chCheckDir), chReval, 0x10000000U);

	/** 可能列车跨着分界点，此时获取列车关联的UCT包络 */
	pTemp = rrm_PrepareTrainRelELM(wTrainID);

	if (NULL != pTemp)
	{
		/*说明列车跨着分界点申请,此时需要检查车脚下区段及车头是否在站台*/
		/** 检查列车是否存在前方列车及是否在正线 */
		funRtn = rrm_ChecKForwardTrainAndArea(funValid, wTrainID, pTemp, &rrmReason);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x08000000U);

		/** 检查列车是否在站台 */
		funRtn = rrm_CheckOtherCiTrainInSta(funValid, wTrainID, wTrainNextStaId, pTemp, &rrmReason);
		ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
		ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x04000000U);
	}
	else
	{
		; /*列车不在分界点，继续进行下列检查*/
	}

	/** 检查是否设置了全线紧急制动*/
	funRtn = rrm_CheckWLBrake(funValid, wTrainID, &rrmReason);
	ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
	ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x02000000U);

	/** 查询其他控区RRM路径及道岔状态是否正确 */
	funRtn = rrm_CheckOtherCiRRMPathAndSw(funValid, wTrainID, wTrainNextStaId,pTemp, wAxisSecId, chCheckDir, &ACSeq, &NextTIOC, &NextSta, &rrmReason);
	ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
	ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x01000000U);

	/** 检查分界点至下一站站台终端之间信号机状态都为允许 */
	funRtn = rrm_CheckSignalStatus(funValid, wTrainID, &ACSeq, &rrmReason);
	ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
	ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x00800000U);

	/** 检查RRM路径中区段是否符合要求（空闲/锁闭/锁闭方向一致） */
	funRtn = rrm_CheckSecStatus(funValid, wTrainID, &ACSeq, &rrmReason);
	ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
	ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x00400000U);

	/** 检查RRM路径中障碍物是否符合要求或者区段进行了安全防护 */
	funRtn = rrm_CheckObsAndSafeProtect(funValid, wTrainID, &ACSeq, &rrmReason);
	ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
	ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x00200000U);

	if ((RRM_CHECK_VALID == funValid) && (0U == errorCode))
	{
		if (0U == NextTIOC)
		{
			/** 检查查询到的下一站信息是否与列车发送的下一站一致 */
			funRtn = rrm_CheckOtherCiNextStation(funValid, wTrainID, wTrainNextStaId, NextSta, &rrmReason);
			ASSERT_SETRET(CI_SUCCESS == funRtn, funValid, funValid, RRM_CHECK_UNVALID);
			ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x00100000U);

			if (RRM_CHECK_VALID == funValid)
			{
				SetTrainOtherRcRrmReson(wTrainID, TRAIN_RRM_RESON_FF);
				chReval = CI_SUCCESS;  /*返回成功*/
			}
			else
			{
				SetTrainOtherRcRrmReson(wTrainID, rrmReason);
			}
		}
		else
		{
			/*远程RM跨控区*/
			if (0U != NextSta)
			{
				/*查询RM路径时，查到下一站ID或者下一个控区ID会跳出，此时若下一个控区ID不为0；说明本控区不存在站台，列车发送的“运行方向”查询到分界点处无其他站台检查条件自然通过*/
				/*跨联锁远程RM:查询到分界点处无其他站台*/
				SetTrainOtherRcRrmReson(wTrainID, TRAIN_RRM_RESON_0B);
				errorCode += 0x00080000u;
			}
			else
			{
				funRtn = rrm_PrepareRcIsZXorSCX(NextTIOC);  /*检查下一控区是否为正线或试车线*/
				if ((CI_SUCCESS == funRtn) && (0U < ACSeq.acCnt))
				{
					/*本控区所有条件检查通过，发送相邻联锁检查剩余区段*/
					wAxisRelateCfpId = GetAxisRelateCfpId(ACSeq.ACID[ACSeq.acCnt - 1U]);
					SetCfpRrmSrcApplyState(wAxisRelateCfpId, TRAIN_RRM_LOCALCI_APPLY);
					SetCfpRrmTrainId(wAxisRelateCfpId, wTrainID);

					SetCfpRrmTrainNextStaId(wAxisRelateCfpId, wTrainNextStaId);

					cLocalCiId = GetSystemParaLocalCiId();
					SetCfpRrmSrcRcId(wAxisRelateCfpId, cLocalCiId);

					/*继续检查跨控区远程RM时，目标TIOC允许状态*/
					chRrmDstAllowed = GetCfpRrmDstAllowState(wAxisRelateCfpId);
					if (TRAIN_RRM_OTHERCI_ALLOW == chRrmDstAllowed)
					{
						SetTrainOtherRcRrmReson(wTrainID, TRAIN_RRM_RESON_FF);
						chReval = CI_SUCCESS;  /*返回成功*/
					}
					else
					{
						SetTrainOtherRcRrmReson(wTrainID, TRAIN_RRM_RESON_15);
						errorCode += 0x00040000U;
					}
				}
				else
				{
					SetTrainOtherRcRrmReson(wTrainID, TRAIN_RRM_RESON_16);
					errorCode += 0x00020000U;
				}
			}
		}		
	}
	else
	{
		SetTrainOtherRcRrmReson(wTrainID, rrmReason);
		errorCode += 0x00010000U;
	}

	ASSER_DEBUG(0U != errorCode, RRM_LOG_LOC(RRM_LOG_ERROR, "errno:0x%08x info:Train%d rrm_OtherCiConditionsCheck ERROR:not allow RRM.", errorCode, wTrainID));

	return chReval;
}

/**
 * @brief 检查列车是否在站台
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] const UINT16 wTrainNextStaId 列车下一站站台ID
 * @param[in] IN const EnvelopeStruct* pTemp 包络指针
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
		   CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note by cgh 20240222
 */
UINT8 rrm_CheckOtherCiTrainInSta(UINT8 funValid, UINT16 trainID, const UINT16 wTrainNextStaId, IN const EnvelopeStruct* pTemp, OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0U;
	UINT16 headRelStaID = 0U;
	UINT8 chHeadAcStatus = 0U; /*车头计轴区段占用状态*/

	/** 入口参数校验 */
	ASSERT_RET_VALUE((NULL == pTemp) || (0U == pTemp->ACCnt), ret, 0x80000000U);
	ASSERT_RET_VALUE(NULL == rrmReason, ret, 0x40000000U);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffU;
	}
	else
	{
		headRelStaID = rrm_PrepareAtsLgcStaOfAC(pTemp->ACID[pTemp->ACCnt - 1U]);
		ASSER_ERROR((0xffffu == headRelStaID), errorCode, 0x20000000U);

		if (0U == errorCode)
		{
			if (0U != headRelStaID)
			{
				ret = CI_ERROR;
				if (wTrainNextStaId == headRelStaID)
				{
					chHeadAcStatus = rrm_PrepareACStatus(pTemp->ACID[pTemp->ACCnt - 1U]);
					if (ELM_AC_OCC == chHeadAcStatus)
					{
						/** 列车到达站台 */
						errorCode += 0x10000000U;
						*rrmReason = TRAIN_RRM_RESON_0D;
					}
					else
					{
						/*包络进入但占压未进入，等待*/
						ret = CI_SUCCESS;
					}
				}
				else
				{
					/** 列车在站台 */
					errorCode += 0x08000000U;
					*rrmReason = TRAIN_RRM_RESON_0E;
				}
			}
			else
			{
				/** 允许RRM */
				ret = CI_SUCCESS;
			}
		}
	}
	ASSER_DEBUG(0U != errorCode, RRM_LOG_LOC(RRM_LOG_ERROR, "errno:0x%08x info:Train%d rrm_CheckOtherCiTrainInSta error:In sta not allow RRM.", errorCode, trainID));
	return ret;
}

/**
 * @brief 查询RRM路径及道岔状态是否正确
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] UINT16 wAtsLgcStaId ATS停车区域ID
 * @param[out] RRMPathOfACSeqStruct* pACSeq RRM路径包含的计轴序列
 * @param[out] UINT8 *pNextTIOC 下一TIOC ID
 * @param[out] UINT16 *pNextSta 下一站台
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
		   CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note by cgh 20240221
 */
UINT8 rrm_CheckOtherCiRRMPathAndSw(UINT8 funValid, UINT16 trainID, UINT16 wAtsLgcStaId, IN const EnvelopeStruct* pTemp,UINT16 wAxieSecId, UINT8 chCheckDir, OUT RRMPathOfACSeqStruct* pACSeq, OUT UINT8* pNextTIOC, OUT UINT16* pNextSta, OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0U;
	UINT8 validFlag = 0U;
	UINT8 funRtn = CI_ERROR;
	UINT16 nexStaID = 0U;
	UINT8 nextOCId = 0U;
	UINT8 ACIsOwn = 0U;
	UINT16 cyclePath = 0U;
	UINT16 curACID = 0U;
	UINT8 curDir = 0U;
	UINT16 nextACCnt = 0u;
	UINT16 nextACId[AC_MAXCNT_IN_SWITCH] = { 0U };
	UINT8 cDirectionPointFlag = 0U;			/*是否具有方向变化点标志*/
	UINT8 cycle = 0U;
	UINT8 chAtsLgcStaIsOwnCheck = CI_ERROR;/*ATS下发的停车区域ID是否属于本控区检查*/
	UINT8 chHeadStationCheck = 0U;/*车头站台检查*/

	/** 入口参数校验*/
	ASSERT_RET_VALUE(NULL == rrmReason, ret, 0x80000000U);
	ASSERT_RET_VALUE(NULL == pACSeq, ret, 0x40000000U);
	ASSERT_RET_VALUE(NULL == pNextTIOC, ret, 0x20000000U);
	ASSERT_RET_VALUE(NULL == pNextSta, ret, 0x10000000U);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffU;
	}
	else
	{
		if (NULL != pTemp)
		{
			if ((wAxieSecId == pTemp->ACID[0U]) && (chCheckDir == pTemp->startPos.Dir))
			{
				/*说明列车是跨着分界点申请远程RM*/
				curACID = pTemp->ACID[0U];
				curDir = pTemp->startPos.Dir;

				funRtn = rrm_AddACInRRMPathSeq(curACID, curDir, TYPE_OF_PATH_A, pACSeq);
				ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x04000000U);

				for (cycle = 1U; cycle < pTemp->ACCnt; cycle++)
				{
					nextACCnt = rrm_PrepareAdjacentAC(curACID, curDir, nextACId, &cDirectionPointFlag);

					/** 如果查询多个计轴区段，则代表道岔位置不符合要求或者查询掉头失败 */
					if ((1U == nextACCnt) && (nextACId[0U] == pTemp->ACID[cycle]))
					{
						/** 判断是否遇到方向变化点 */
						curDir = (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag) ? ((UINT8)(~curDir)) : curDir;

						/** 更换基准查询计轴 */
						curACID = nextACId[0U];

						/** 将查询成功的计轴插入到计轴序列中 */
						funRtn = rrm_AddACInRRMPathSeq(curACID, curDir, TYPE_OF_PATH_A, pACSeq);
						ASSERT_BREAK(CI_ERROR == funRtn, errorCode, 0x02000000U);
					}
					else
					{
						/** 如果查询多个计轴区段，则代表道岔位置不符合要求或者查询掉头失败或者包络路径错误 */
						errorCode += 0x01000000U;
						break;
					}
				}

				/*不为空说明列车跨着分界点，此时列车脚下路径已经添加过，获取下一个*/
				nextACCnt = rrm_PrepareAdjacentAC(curACID, curDir, nextACId, &cDirectionPointFlag);
				ASSER_ERROR(((1U != nextACCnt) && (0U != nextACCnt)), errorCode, 0x00800000U);

				/** 判断是否遇到方向变化点 */
				curDir = (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag) ? ((UINT8)(~curDir)) : curDir;

				/** 更换基准查询计轴 */
				curACID = nextACId[0U];
			}
			else
			{
				errorCode += 0x08000000U;
			}
		}
		else
		{
			/** 缓存跨控区的分界点计轴区段*/
			curACID = wAxieSecId;
			curDir = chCheckDir;
		}

		if (0U == errorCode)
		{
			chHeadStationCheck = rrm_CheckTrainHeadInFreeSta(trainID, pTemp,&nexStaID);
			if (CI_SUCCESS == chHeadStationCheck)
			{
				if (0U == nextACCnt)
				{
					/** 如果下一计轴区段数目为0，说明是尽头线，此时不记录下一站台前方计轴区段，但需要往下记录计算出的逻辑站台ID by cgh 20231102*/
					;
				}
				else
				{
					/** 将查询成功的计轴插入到计轴序列*/
					funRtn = rrm_AddACInRRMPathSeq(curACID, curDir, TYPE_OF_PATH_C, pACSeq);
					ASSER_ERROR(CI_ERROR == funRtn, errorCode, 0x00002000u);
				}

				/** 缓存下一站站台ID*/
				*pNextSta = nexStaID;

				/** 不进入循环 */
				validFlag = 0xffu;
			}
			else
			{
				nexStaID = 0U; /*其他情况继续查找*/
			}
		}
		else
		{
			; /*不执行检查*/
		}
		
		
		/** 继续查询分界点到下一站台之间的计轴区段 */
		while ((0U == validFlag) && (0U == errorCode))
		{
			/** 判断是否为站台 */
			nexStaID = rrm_PrepareAtsLgcStaOfAC(curACID);
			ASSERT_BREAK(0xffffU == nexStaID, errorCode, 0x00400000U);

			/** 查询计轴是否属于本集中区 */
			ACIsOwn = rrm_PrepareACIsSelf(curACID, &nextOCId);
			ASSERT_BREAK(0U == nextOCId, errorCode, 0x00200000U);

			/** 有rrm_AddACInRRMPathSeq函数做死循环防护 */
			nextACCnt = rrm_PrepareAdjacentAC(curACID, curDir, nextACId, &cDirectionPointFlag);

			if ((ELM_BELONG_OWNER != ACIsOwn) && (0u != nextOCId))
			{
				/*需要先判断计轴区段所属控区！
				 *若先判断站台，在列车跨分界点且车头在相邻控区站台时，本控区将会先查到站台轨并且将其归类TYPE_OF_PATH_B，在区段检查时将因为占用而失败，将不再向相邻RC申请RRM，与需求方案不符*/
				
				chAtsLgcStaIsOwnCheck = rrm_PrepareAtsLgcStaIsOwn(wAtsLgcStaId);
				if (CI_SUCCESS == chAtsLgcStaIsOwnCheck)
				{
					/*当RRM命令中站台ID有误，为本控区站台但不在列车前方路径（在列车后方或列车前方为上行轨道，命令站台在下行轨道）
				 *本控区应直接检查失败不向相邻RC继续发送申请*/

					*pNextTIOC = nextOCId;  /** 设置下一TIOC ID*/
				}
				else
				{
					;
				}
				ASSER_ERROR(CI_ERROR == chAtsLgcStaIsOwnCheck, errorCode, 0x00004000U);
				validFlag = 0xffu;  /** 退出循环 */
			}
			else if (0U != nexStaID)
			{
				if (0U == nextACCnt)
				{
					/** 如果下一计轴区段数目为0，说明是尽头线，此时不记录下一站台前方计轴区段，但需要往下记录计算出的逻辑站台ID by cgh 20231102*/
					;
				}
				else
				{
					/** 将查询成功的计轴插入到计轴序列*/
					funRtn = rrm_AddACInRRMPathSeq(curACID, curDir, TYPE_OF_PATH_B, pACSeq);
					ASSERT_BREAK(CI_ERROR == funRtn, errorCode, 0x00100000U);

					/** 如果查询多个计轴区段，则代表道岔位置不符合要求 */
					ASSERT_BREAK((1U != nextACCnt) || (nextACId[0U] == pACSeq->ACID[pACSeq->acCnt - 1U]), errorCode, 0x00080000U);

					/** 判断是否遇到方向变化点 */
					curDir = (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag) ? ((UINT8)(~curDir)) : curDir;

					/** 更换基准查询计轴 */
					curACID = nextACId[0U];

					/** 将查询成功的计轴插入到计轴序列*/
					funRtn = rrm_AddACInRRMPathSeq(curACID, curDir, TYPE_OF_PATH_C, pACSeq);
					ASSERT_BREAK(CI_ERROR == funRtn, errorCode, 0x00040000U);
				}

				/** 缓存下一站站台ID*/
				*pNextSta = nexStaID;

				/** 退出循环 */
				validFlag = 0xffU;
			}
			else
			{

				/** 将查询成功的计轴插入到计轴序列*/
				funRtn = rrm_AddACInRRMPathSeq(curACID, curDir, TYPE_OF_PATH_B, pACSeq);
				ASSERT_BREAK(CI_ERROR == funRtn, errorCode, 0x00020000U);

				/** 如果查询多个计轴区段，则代表道岔位置不符合要求或者查询掉头失败 */
				ASSERT_BREAK((1U != nextACCnt) || (nextACId[0U] == pACSeq->ACID[pACSeq->acCnt - 1U]), errorCode, 0x00010000U);

				/** 判断是否遇到方向变化点 */
				curDir = (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag) ? ((UINT8)(~curDir)) : curDir;

				/** 更换基准查询计轴 */
				curACID = nextACId[0U];
			}
		}

		if (0U != errorCode)
		{
			if (0x00004000U == (errorCode & 0x00004000U))
			{
				*rrmReason = TRAIN_RRM_RESON_0B;
			}
			else
			{
				*rrmReason = TRAIN_RRM_RESON_0A;
			}
			ret = CI_ERROR;
		}
		else
		{
			/** 校验路径内的道岔位置是否正确 */
			for (cyclePath = 0U; cyclePath < pACSeq->acCnt; cyclePath++)
			{
				funRtn = rrm_PrepareSwitchStatOfAC(pACSeq->ACID[cyclePath]);
				ASSERT_BREAK(CI_ERROR == funRtn, errorCode, 0x00008000U);
			}

			if (cyclePath == pACSeq->acCnt)
			{
				ret = CI_SUCCESS;
			}
			else
			{
				*rrmReason = TRAIN_RRM_RESON_0A;
				ret = CI_ERROR;
			}
		}
	}

	debug_infor_printf((const)"rrm_CheckOtherCiRRMPathAndSw:num = %d\n", pACSeq->acCnt);
	debug_out_array(0xAA, pACSeq->ACID, pACSeq->acCnt * 2u);

	ASSER_DEBUG(0U != errorCode, RRM_LOG_LOC(RRM_LOG_ERROR, "errno:0x%08x info:Train%d rrm_CheckOtherCiRRMPathAndSw error:not allow RRM by seach Path error .", errorCode, trainID));
	return ret;
}

/**
 * @brief 检查查询到的下一站信息是否与列车发送的下一站一致
 * @param[in] UINT8 funValid 函数处理可用性标志
 * @param[in] UINT16 trainID 列车ID
 * @param[in] const UINT16 wTrainNextStaId 列车下一站站台ID
 * @param[in] UINT16 searchNextStaID 查询到的下一站台ID
 * @param[out] UINT8* rrmReason 不允许的理由
 * @return UINT8
		   CI_ERROR 处理失败
		   CI_SUCCESS 处理成功
		   0xFF 未处理
 * @note by cgh 20240221
 */
UINT8 rrm_CheckOtherCiNextStation(UINT8 funValid,UINT16 trainID, const UINT16 wTrainNextStaId, const UINT16 searchNextStaID, OUT UINT8* rrmReason)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0U;

	/** 入口参数校验 */
	ASSERT_RET_VALUE(NULL == rrmReason, ret, 0x80000000U);

	if (RRM_CHECK_UNVALID == funValid)
	{
		ret = 0xffU;
	}
	else
	{
		if (wTrainNextStaId == searchNextStaID)
		{
			ret = CI_SUCCESS;
		}
		else
		{
			*rrmReason = TRAIN_RRM_RESON_0B;
			errorCode += 0x40000000U;
			ret = CI_ERROR;
		}
	}

	ASSER_DEBUG(0U != errorCode, RRM_LOG_LOC(RRM_LOG_ERROR, "errno:0x%08x info:Train%d rrm_CheckOtherCiNextStation error:not allow RRM by dst error.", errorCode, trainID));
	return ret;
}

/**
 * @brief 检查是否是列车车头包络进入目标站台占压未进入
 * @param[in] UINT16 trainID 列车ID
 * @param[in] IN const EnvelopeStruct* pTemp 包络指针
 * @param[out] UINT16* pNextSta 下一站台
 * @return UINT8
		   CI_ERROR  否
		   CI_SUCCESS 是
 * by cgh 20241022
 */
static UINT8 rrm_CheckTrainHeadInFreeSta(UINT16 trainID, IN const EnvelopeStruct* pTemp, OUT UINT16* pNextSta)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0U;
	UINT16 headRelStaID = 0U;
	UINT16 trainNextSta = 0U;
	UINT8 chHeadAcStatus = 0U; /*车头计轴区段占用状态*/

	/** 入口参数校验 */
	ASSERT_RET_VALUE((NULL == pTemp) || (0U == pTemp->ACCnt), errorCode, 0x80000000U);

	headRelStaID = rrm_PrepareAtsLgcStaOfAC(pTemp->ACID[pTemp->ACCnt - 1U]);

	ASSER_ERROR((0xffffU == headRelStaID), errorCode, 0x40000000U);

	if (0U == errorCode)
	{
		trainNextSta = rrm_PrepareNextStaOfTrain(trainID);

		if (0U != headRelStaID)
		{

			if (trainNextSta == headRelStaID)
			{
				chHeadAcStatus = rrm_PrepareACStatus(pTemp->ACID[pTemp->ACCnt - 1U]);
				if (ELM_AC_FREE == chHeadAcStatus)
				{
					*pNextSta = headRelStaID;
					ret = CI_SUCCESS;
				}
				else
				{
					/*目标站台有占用，前面检查返回错误，此处其实不可达，仅为异常防护 */
					ret = CI_ERROR;
				}
			}
			else
			{
				errorCode = 0x20000000U;
				/*不是目标站台，继续执行路径查找*/
				ret = CI_ERROR;
			}
		}
		else
		{
			/** 车头不在站台 */
			ret = CI_ERROR;
		}
	}
	else
	{
		ret = CI_ERROR;
	}
	ASSER_DEBUG(0U != errorCode, RRM_LOG_LOC(RRM_LOG_ERROR, (const)"errno:0x%08x info:Train%d headexistStationButNotNextSta.", errorCode, trainID));
	return ret;
}

/**
 * @brief 检查进路状态是否满足
 * @param[in] UINT16 wRouteId 进路ID
 * @return CI_ERROR 不满足
		   CI_SUCCESS 满足
 * @note BY CGH 20250807
 */
static UINT8 rrm_CheckRouteState(UINT16 wRouteId)
{
	UINT8 chReval = CI_ERROR;
	UINT8 chRouteState = 0U;/*进路状态*/

	if ((0U < wRouteId) && (ROUTE_SUM_MAX > wRouteId))
	{
		chRouteState = GetRouteState(wRouteId);

		if ((ROUTE_STATE_YUXIAN_OPEN == chRouteState)
			|| (ROUTE_STATE_NEAR_LOCK == chRouteState)
			|| (ROUTE_STATE_NEAR_OPEN == chRouteState)
			|| (ROUTE_STATE_AUTO_UNLOCK == chRouteState)
			|| (ROUTE_STATE_HALF_UNLOCK == chRouteState)
			)
		{
			chReval = CI_SUCCESS;
		}
		else
		{
			; 
		}
	}
	else
	{
		;
	}

	return chReval;
}

