/*******************************************************************************
*
* 文件名  ：dsuRpFunc.c
* 版权说明：北京瑞安时代科技有限责任公司
* 版本号  ：1.0  
* 创建时间：2009.11.20
* 作者    ：车载及协议部
* 功能描述：与Rp协议相关的dsu查询函数函数体
* 使用注意：无
* 修改记录：无
*
*******************************************************************************/

#include "dsuProtclFun.h"
#include "CommonMemory.h"
#include "Convert.h"
#include "dfsDataRead.h"
#include "dquDataTypeDefine.h"

#ifdef DEV_IP_TABLE_NO_HLHT
#define DSU_IP_INFO_STRU_SIZE (22) /*设备IP地址表列占字节长度*/
#else
#define DSU_IP_INFO_STRU_SIZE (30) /*设备IP地址表列占字节长度*/
#endif

#define DSU_COMM_PROTCL_STRU_SIZE (3) /*设备通信协议表列占字节长度*/

/*FS的sheet页信息*/
typedef struct
{
	UINT32 Id; /*序号*/
	UINT32 Len; /*长度*/
	UINT16 RowCount; /*行总数*/
	UINT32 ColLen; /*列字节长度*/
	UINT8* Data; /*数据*/
} SheetInfo;

static void InitSheet(SheetInfo* sheetInfo, UINT8 data[], const UINT32 dataLen, const UINT32 excelId, const UINT32 sheetId);
static void StDsuPtclFindExcel(SheetInfo* sheetInfo, UINT8 data[], const UINT32 dataLen, UINT32 idx, UINT32 excelCount, const UINT32 excelId, const UINT32 sheetId);
static UINT8 StDsuPtclFindSheet(SheetInfo* sheetInfo, UINT8 data[], const UINT32 dataLen, UINT32 curExcelStartPos, UINT32* curExcelPos, UINT32 sheetCount, const UINT32 sheetId);
static void StDsuPtclSetDevNum(UINT8 locType, UINT8 oppType, SheetInfo* outDevIpSheet, SheetInfo* inDevIpSheet, UINT16* dupOppHlhtIdLen, UINT32* dupOppHlhtId, UINT16 outInDevIpRowCount, UINT8* devNum);
static UINT8 GetCommOppDevTypes(SheetInfo* commSheet, UINT8 locType, UINT8* oppTypes, UINT8* oppTypePtls, UINT16* oppTypeNum, const UINT16 maxOppTypeNum);
static void GetCommOppDevNum(SheetInfo* devIpSheet, UINT8 oppType, UINT16* dupOppHlhtIdsLen, UINT32* dupOppHlhtIds, const UINT16 maxDupOppHlhtIdsLen, UINT8* devNum);

/**
 * @brief DsuCommonInfoInit 适配层查询函数初始化
 * @param pFsName FS文件路径 取值范围:字节数组
 * @param pDsuProtclBookIpInfo 查询表信息 取值范围:参考结构体DSU_PROTCL_BOOK_IP_INFO_STRU
 * @param 0:失败;1:成功
 */
UINT8 DsuCommonInfoInit(UINT8* pFsName, DSU_PROTCL_BOOK_IP_INFO_STRU* pDsuProtclBookIpInfo)
{
	/*- 定义局部变量*/
	UINT8 rtn = 0u; /*-< 设置函数返回值为失败*/
	UINT8 readRtn = 0u;	/*读取FS返回值*/
	UINT8* pData = NULL;	/*读出的数据*/
	UINT32 dataLen = 0u;	/*读出的数据长度*/
	UINT32 mallocLen = 0u;	/*分配空间大小*/
	UINT32 offset = 0u;	/*数据偏移量*/
	UINT32 i = 0u;	/*用于循环*/
	UINT8 deepPro = 0u; /*-< 设置处理标志为不处理*/

	if ((NULL != pFsName) && (NULL != pDsuProtclBookIpInfo)) /*-< 参数是否非空*/
	{
		readRtn = dquGetConfigData((CHAR*)pFsName, DSU_DEVICE_IP_CONFIG_TYPE, DSU_DATA_IP_IP_ID, &pData, &dataLen);	/*-< 调用函数读取设备IP地址表*/
		if ((1u == readRtn) && (DSU_IP_INFO_STRU_SIZE <= dataLen)) /*-< 是否有数据*/
		{
			pDsuProtclBookIpInfo->IpDevLen = (UINT16)(dataLen / DSU_IP_INFO_STRU_SIZE); /*-< 得到行数*/
			mallocLen = sizeof(UINT16) * (pDsuProtclBookIpInfo->IpDevLen);	/*-< 得到类型ID需分配空间大小*/
			pDsuProtclBookIpInfo->IpDevTypeIds = (UINT16*)malloc(mallocLen); /*-< 分配空间*/
			if (NULL != pDsuProtclBookIpInfo->IpDevTypeIds) /*-< 是否分配成功*/
			{
				CommonMemSet(pDsuProtclBookIpInfo->IpDevTypeIds, mallocLen, 0u, mallocLen); /*-< 初始清零*/

				mallocLen = sizeof(UINT32) * (pDsuProtclBookIpInfo->IpDevLen); /*-< 得到互联互通ID需分配空间大小*/
#ifndef DEV_IP_TABLE_NO_HLHT
				pDsuProtclBookIpInfo->IpDevHlhtIds = (UINT32*)malloc(mallocLen); /*-< 分配空间*/
				if (NULL != pDsuProtclBookIpInfo->IpDevHlhtIds) /*-< 是否分配成功*/
				{
					CommonMemSet(pDsuProtclBookIpInfo->IpDevHlhtIds, mallocLen, 0u, mallocLen); /*-< 初始清零*/
#endif

					for (i = 0u; i < pDsuProtclBookIpInfo->IpDevLen; i++) /*-< 设备类型ID数下标是否小于总数*/
					{
						/*- 得到2字节设备类型ID*/
						pDsuProtclBookIpInfo->IpDevTypeIds[i] = ShortFromChar(&pData[offset]);
#ifndef DEV_IP_TABLE_NO_HLHT
						/*- 得到4字节互联互通ID*/
						pDsuProtclBookIpInfo->IpDevHlhtIds[i] = LongFromChar(&pData[offset + 2u]);
#endif
						offset += DSU_IP_INFO_STRU_SIZE; /*-< 数据下标自增列数据长度*/
					}
					if (offset == dataLen)	/*-< 设备类型ID赋值成功*/
					{
						deepPro = 1u; /*-< 设置处理标志为处理*/
					}

#ifndef DEV_IP_TABLE_NO_HLHT
				}
#endif				
			}

			if (1u == deepPro) /*-< 处理标志是否为处理*/
			{
				pDsuProtclBookIpInfo->pCommProtclStru = NULL; /*-< 设置通信类型变量为空*/
				readRtn = dquGetConfigData((CHAR*)pFsName, DSU_DEVICE_IP_CONFIG_TYPE, DSU_DATA_IP_COMM_PROTCL_ID, &pData, &dataLen); /*-< 调用函数读取设备通信协议表*/
				if ((1u == readRtn) && (DSU_COMM_PROTCL_STRU_SIZE <= dataLen)) /*-< 是否有数据*/
				{
					pDsuProtclBookIpInfo->CommProtclStruLen = (UINT16)(dataLen / DSU_COMM_PROTCL_STRU_SIZE); /*-< 得到行数*/
					mallocLen = sizeof(DSU_PROTCL_COMM_PROTCL_STRU) * (pDsuProtclBookIpInfo->CommProtclStruLen); /*-< 得到需分配空间大小*/
					pDsuProtclBookIpInfo->pCommProtclStru = (DSU_PROTCL_COMM_PROTCL_STRU*)malloc(mallocLen); /*-< 分配空间*/
				}
				if (NULL != pDsuProtclBookIpInfo->pCommProtclStru) /*-< 通信类型变量是否非空*/
				{
					CommonMemSet(pDsuProtclBookIpInfo->pCommProtclStru, mallocLen, 0u, mallocLen); /*-< 初始清零*/

					offset = 0u; /*-< 偏移从零开始*/
					for (i = 0u; i < pDsuProtclBookIpInfo->CommProtclStruLen; i++) /*-< 通信类型ID数下标是否小于总数*/
					{
						/*- 1字节本方类型*/
						pDsuProtclBookIpInfo->pCommProtclStru[i].EmitterType = pData[offset];
						offset++; /*-< 数据下标自增1*/
						/*- 1字节对方类型*/
						pDsuProtclBookIpInfo->pCommProtclStru[i].ReceptorType = pData[offset];
						offset++; /*-< 数据下标自增1*/
						/*1字节协议类型*/
						if ((DSU_PROTCL_RSSP2 + 4u) == pData[offset]) /*-< 是否RSSPII*//*RSSPII协议数据配置中为9,适配层代码中用的下标为5*/
						{
							pDsuProtclBookIpInfo->pCommProtclStru[i].CommuType = DSU_PROTCL_RSSP2; /*-< 设置通信类型为RSSPII*/
						}
						else
						{
							pDsuProtclBookIpInfo->pCommProtclStru[i].CommuType = pData[offset]; /*-< 数据中通信类型设置到通信类型*/
						}
						offset++; /*-< 数据下标自增1*/
					}
					if (offset == dataLen)	/*-< 设备通信协议表赋值成功*/
					{
						rtn = 1u; /*-< 设置函数返回值为成功*/
					}
				}
			}

		}
	}

	return rtn; /*-< 返回函数返回值*/
}

/*
*函数名:	DsuProtclGetProtclType
*功能描述:	根据本方类型ID与对方类型ID查找所使用的协议类型
*输入参数:	UINT16 locTypeId	本方类型ID
*			UINT16 oppTypeId	对方类型ID
*			DSU_PROTCL_BOOK_IP_INFO_STRU *pDsuProtclBookIpInfo 适配层使用表
*输入出参:	无
*输出参数:	UINT8 *pProtclType	协议类型
*返回值:	1:成功;0失败
*/
UINT8 DsuProtclGetProtclType(UINT16 locTypeId, UINT16 oppTypeId, UINT8 *pProtclType, DSU_PROTCL_BOOK_IP_INFO_STRU *pDsuProtclBookIpInfo)
{
	UINT8 rtn = 0;	/*返回值*/
	UINT8 locType = (UINT8)((locTypeId >> 8) & 0x00FF);	/*本方类型*/
	UINT8 oppType = (UINT8)((oppTypeId >> 8) & 0x00FF);	/*对方类型*/
	UINT32 i = 0;	/*用于循环*/

	if ((NULL != pProtclType) && (NULL != pDsuProtclBookIpInfo)&&(NULL!= pDsuProtclBookIpInfo->pCommProtclStru))	/*输入参非空*/
	{
		for (i = 0; i < pDsuProtclBookIpInfo->CommProtclStruLen; i++)	/*遍历设备通信协议表*/
		{
			/*匹配本方对方类型*/
			if ((pDsuProtclBookIpInfo->pCommProtclStru[i].EmitterType == locType) && (pDsuProtclBookIpInfo->pCommProtclStru[i].ReceptorType == oppType))
			{
				*pProtclType = pDsuProtclBookIpInfo->pCommProtclStru[i].CommuType;
				break;	/*找到退出循环*/
			}
		}
		if (i != pDsuProtclBookIpInfo->CommProtclStruLen)	/*找到*/
		{
			rtn = 1;
		}
	}

	return rtn;
}

/**
 * @brief DsuGetProtclTypeInfo 根据本方类型ID查找与对方通信时使用协议的最大通信设备数量(最大链路数)
 * @param locTypeId 本方类型ID 取值范围:0x0000-0xFFFF
 * @param dsuProtclTypeInfo 各协议数量 取值范围:参考结构体DSU_PROTCL_TYPE_STRU
 * @param pDsuProtclBookIpInfo 适配层使用表 取值范围:参考结构体DSU_PROTCL_BOOK_IP_INFO_STRU
 * @param globalVarOppTypePtl 对方协议类型数组 取值范围:字节数组
 * @param globalVarOppTypePtlLen 对方协议类型数组长度 取值范围:0x0000-0xFFFF
 * @param inDataLen 内部数据长度 取值范围:0x00000000-0xFFFFFFFF
 * @param inData 内部数据 取值范围:字节数组
 * @return 0:失败 1:成功
 */
UINT8 DsuGetProtclTypeInfo(UINT16 locTypeId, DSU_PROTCL_TYPE_STRU* dsuProtclTypeInfo, DSU_PROTCL_BOOK_IP_INFO_STRU* pDsuProtclBookIpInfo, UINT8 globalVarOppTypePtl[], UINT16 globalVarOppTypePtlLen, UINT32 inDataLen, UINT8 inData[])
{
	/*- 定义局部变量*/
	UINT8 rtn = 0u;	/*返回值*/
	UINT8 locType = (UINT8)(locTypeId >> 8);	/*本方类型*/
	UINT32 i = 0u;	/*用于循环*/
	UINT8 outCanGetComm = 0u; /*外网是否配置错误*/
	UINT8 inCanGetComm = 0u;	/*内网是否配置错误*/
	UINT16 oppTypeNum = 0u;	/*对方类型数量*/
	UINT16 dupOppHlhtIdLen = 0u;	/*重复对方类型ID长度*/
	UINT8 devNum = 0u;	/*设备数量*/
	UINT32 oppTypeSpLen = 0u; /*对方设备类型数组分配空间长度*/
	UINT32 dupOppHlhtIdSpLen = 0u; /*重复对方互联互通ID数组分配空间长度*/
	UINT8* oppType = NULL; /*对方设备类型数组*/
	UINT8* oppTypePtl = NULL; /*对方设备类型协议数组*/
	UINT32* dupOppHlhtId = NULL; /*重复对方互联互通ID数组*/
	SheetInfo outCommSheet = { 0 }; /*外网不同类型sheet页*/
	SheetInfo inCommSheet = { 0 }; /*内网不同类型sheet页*/
	SheetInfo outDevIpSheet = { 0 }; /*外网相同类型sheet页*/
	SheetInfo inDevIpSheet = { 0 }; /*内网相同类型sheet页*/
	UINT32 outInCommRowCount = 0u; /*外内网通信协议类型sheet页行总数*/
	UINT32 outInDevIpRowCount = 0u; /*外内网设备IP地址sheet页行总数*/

	if ((NULL != dsuProtclTypeInfo) && (NULL != pDsuProtclBookIpInfo) && (NULL != globalVarOppTypePtl)) /*-< 参数是否非空*/
	{
		/*- 读取外部内不数据*/
		InitSheet(&outCommSheet, g_pDataBuf, g_DataBufLen, DSU_DEVICE_IP_CONFIG_TYPE, DSU_DATA_IP_COMM_PROTCL_ID);
		InitSheet(&inCommSheet, inData, inDataLen, DSU_DEVICE_IP_CONFIG_TYPE, DSU_DATA_IP_COMM_PROTCL_ID);
		InitSheet(&outDevIpSheet, g_pDataBuf, g_DataBufLen, DSU_DEVICE_IP_CONFIG_TYPE, DSU_DATA_IP_IP_ID);
		InitSheet(&inDevIpSheet, inData, inDataLen, DSU_DEVICE_IP_CONFIG_TYPE, DSU_DATA_IP_IP_ID);

		outInCommRowCount = pDsuProtclBookIpInfo->CommProtclStruLen + inCommSheet.RowCount; /*-< 得到内部通信类型行数*/
		outInDevIpRowCount = pDsuProtclBookIpInfo->IpDevLen + inDevIpSheet.RowCount; /*-< 得到内部设备IP行数*/

		oppTypeSpLen = sizeof(UINT8) * (outInCommRowCount);	/*-< 对方类型数组空间长度*/
		dupOppHlhtIdSpLen = sizeof(UINT32) * (outInDevIpRowCount);	/*-< 重复对方类型ID数组空间长度*/
		oppType = (UINT8*)malloc(oppTypeSpLen);	/*-< 对方类型数组*/
		oppTypePtl = (UINT8*)malloc(oppTypeSpLen);	/*-< 各对方类型使用协议*/
		dupOppHlhtId = (UINT32*)malloc(dupOppHlhtIdSpLen);	/*-< 重复对方类型ID数组*/

		if ((NULL != oppType) && (NULL != oppTypePtl) && (NULL != dupOppHlhtId)) /*-< 输入参数非空*/
		{
			CommonMemSet(oppType, oppTypeSpLen, 0u, oppTypeSpLen); /*-< 对方类型初始清零*/
			CommonMemSet(oppTypePtl, oppTypeSpLen, 0u, oppTypeSpLen); /*-< 对方类型初始清零*/
			CommonMemSet(dupOppHlhtId, dupOppHlhtIdSpLen, 0u, dupOppHlhtIdSpLen); /*-< 对方互联互通ID初始清零*/

			outCanGetComm = GetCommOppDevTypes(&outCommSheet, locType, oppType, oppTypePtl, &oppTypeNum, (UINT16)(outInCommRowCount)); /*-< 调用获取通信的对方设备类型数组函数*/
			if (1u == outCanGetComm) /*-< 配置是否正常*/
			{
				inCanGetComm = GetCommOppDevTypes(&inCommSheet, locType, oppType, oppTypePtl, &oppTypeNum, (UINT16)(outInCommRowCount)); /*-< 调用获取通信的对方设备类型数组函数*/
				if ((1u == outCanGetComm) && ((0u == inCommSheet.RowCount) || (0u < inCommSheet.RowCount && 1u == inCanGetComm))) /*-< 配置正常*/
				{
					for (i = 0u; i < oppTypeNum; i++) /*-< 对方类型数下标是否小于总数*/
					{
						if (oppType[i] < globalVarOppTypePtlLen) /*-< 对方协议类型是否合法*/
						{
							globalVarOppTypePtl[oppType[i]] = oppTypePtl[i]; /*-< 设置全局与通信的对方设备类型协议数组*/
						}

						devNum = 0u; /*-< 清设备数量为0*/
						StDsuPtclSetDevNum(locType, oppType[i], &outDevIpSheet, &inDevIpSheet, &dupOppHlhtIdLen, dupOppHlhtId, (UINT16)(outInDevIpRowCount), &devNum); /*-< 调用设置设备数量函数*/

						/*加到对应协议类型的通信设备数量上*/
						switch (oppTypePtl[i]) /*-< 判断对方协议类型*/
						{
						case DSU_PROTCL_SFP: /*-< 对方协议类型是否SFP*/
							(dsuProtclTypeInfo->sfpProtclNum) += devNum; /*-< SFP数量自加设备数量*/
							break;
						case DSU_PROTCL_RSSP: /*-< 对方协议类型是否RSSP*/
							(dsuProtclTypeInfo->rsspProtclNum) += devNum; /*-< RSSPI数量自加设备数量*/
							break;
						case DSU_PROTCL_RSR: /*-< 对方协议类型是否RSR*/
							(dsuProtclTypeInfo->rsrProtclNum) += devNum; /*-< RSR数量自加设备数量*/
							break;
						case DSU_PROTCL_RP: /*-< 对方协议类型是否RP*/
							(dsuProtclTypeInfo->redunProtclNum) += devNum; /*-< RP数量自加设备数量*/
							break;
						case DSU_PROTCL_RSSP2: /*-< 对方协议类型是否RSSPII*/
							(dsuProtclTypeInfo->rssp2ProtclNum) += devNum; /*-< RSSPII数量自加设备数量*/
							break;
						case DSU_PROTCL_FSFB: /*-< 对方协议类型是否FSFB*/
							(dsuProtclTypeInfo->fsfbProtclNum) += devNum; /*-< FSFB数量自加设备数量*/
							break;
						default: /*-< 其他*/
							break;
						}
					}

					rtn = 1u; /*-< 设置函数返回值为1*/
				}
			}

			/*- 释放动态内存*/
			free(oppType);
			oppType = NULL;
			free(oppTypePtl);
			oppTypePtl = NULL;
			free(dupOppHlhtId);
			dupOppHlhtId = NULL;
		}
	}

	return rtn; /*-< 返回函数返回值*/
}

/**
 * @brief InitSheet 初始化sheet页信息
 * @param sheetInfo sheet页信息 取值范围:参考结构体SheetInfo
 * @param data 数据数组 取值范围:字节数组
 * @param dataLen 数据长度 取值范围:0x00000000-0xFFFFFFFF
 * @param excelId excle的ID 取值范围:0x00000000-0xFFFFFFFF
 * @param sheetId sheet页ID 取值范围:0x00000000-0xFFFFFFFF
 */
static void InitSheet(SheetInfo* sheetInfo, UINT8 data[], const UINT32 dataLen, const UINT32 excelId, const UINT32 sheetId)
{
	/*- 定义局部变量*/
	UINT32 idx = 0u; /*数据下标*/
	UINT32 crcVal = 0u; /*crc值*/
	UINT32 crc = 0u; /*计算的crc*/
	UINT32 curLen = 0u; /*当前长度*/
	UINT32 excelCount = 0u; /*excel数量*/

	if ((NULL != sheetInfo) && (0u < dataLen) && (NULL != data)) /*-< 参数是否非空*/
	{
		sheetInfo->Id = 0u; /*-< 设置sheet页信息序号为0*/
		sheetInfo->Len = 0u; /*-< 设置sheet页信息长度为0*/
		sheetInfo->RowCount = 0u; /*-< 设置sheet页信息行总数为0*/
		sheetInfo->ColLen = 0u; /*-< 设置sheet页信息列字节长度为0*/
		sheetInfo->Data = NULL; /*-< 设置sheet页信息数据为NULL*/

		if ((idx + 40u) <= dataLen) /*-< 需使用数据长度是否合法*/
		{
			crcVal = LongFromChar(&data[idx]); /*-< 得到CRC值*/
			idx += 4u; /*-< 当前数据下标自增4*/

			/*4字节版本*/
			idx += 4u; /*-< 当前数据下标自增4*/

			curLen = LongFromChar(&data[idx]); /*-< 得到数据中长度*/
			idx += 4u; /*-< 当前数据下标自增4*/

			if ((curLen == dataLen) && (4u < curLen)) /*-< 数据中长度是否合法*/
			{
				crc = Crc32(&data[4u], curLen - 4u); /*-< 计算数据CRC值*/
				if (crc == crcVal) /*-< 计算数据CRC值是否与数据中CRC相等*/
				{
					excelCount = LongFromChar(&data[idx]); /*-< 得到excel数量*/
					idx += 4u; /*-< 当前数据下标自增4*/

					/*24字节预留*/
					idx += 24u; /*-< 当前数据下标自增24*/

					StDsuPtclFindExcel(sheetInfo, data, dataLen, idx, excelCount, excelId, sheetId); /*-< 调用找对应excle数据函数*/
				}
			}
		}
	}
}

/**
 * @brief StDsuPtclFindExcel 找对应excle数据
 * @param sheetInfo sheet页信息 取值范围:参考结构体SheetInfo
 * @param data 数据数组 取值范围:字节数组
 * @param dataLen 数据长度 取值范围:0x00000000-0xFFFFFFFF
 * @param idx 数据数组 取值范围:0x00000000-0xFFFFFFFF
 * @param excelCount excle数量 取值范围:0x00000000-0xFFFFFFFF
 * @param excelId excle的ID 取值范围:0x00000000-0xFFFFFFFF
 * @param sheetId sheet页ID 取值范围:0x00000000-0xFFFFFFFF
 */
static void StDsuPtclFindExcel(SheetInfo* sheetInfo, UINT8 data[], const UINT32 dataLen, UINT32 idx, UINT32 excelCount, const UINT32 excelId, const UINT32 sheetId)
{
	/*- 定义局部变量*/
	UINT32 excelIdx = 0u; /*excel下标*/
	UINT8 deepPro = 0u; /*-< 设置处理标志为不处理*/
	UINT32 curExcelId = 0u; /*当前excel序号*/
	UINT32 curExcelPos = 0u; /*当前在excel位置*/
	UINT32 curExcelStartPos = 0u; /*当前excel开始位置*/
	UINT32 crcVal = 0u; /*crc值*/
	UINT32 crc = 0u; /*计算的crc*/
	UINT32 curLen = 0u; /*当前长度*/
	UINT8 isBreak = 0u; /*-< 设置是否退出遍历标识为否*/
	UINT32 sheetCount = 0u; /*sheet数量*/

	if ((NULL != sheetInfo) && (NULL != data)) /*-< 参数是否非空*/
	{
		for (excelIdx = 0u; excelIdx < excelCount; excelIdx++) /*-< excel下标是否小于excel数量*/
		{
			deepPro = 0u; /*-< 设置处理标志为不处理*/

			if ((idx + 24u) <= dataLen) /*-< 需使用数据长度是否合法*/
			{
				curExcelId = LongFromChar(&data[idx]); /*-< 得到当前excle的ID*/
				idx += 4u; /*-< 当前数据下标自增4*/

				if (curExcelId == excelId) /*-< 得到当前excle的ID是否为要找的*/
				{
					/*4字节长度*/
					idx += 4u; /*-< 当前数据下标自增4*/

					/*4字节excel位置*/
					curExcelPos = LongFromChar(&data[idx]); /*-< 得到当前excel位置*/
					curExcelStartPos = curExcelPos; /*-< 记录当前excel位置为excel开始位置*/
					idx += 4u; /*-< 当前数据下标自增4*/

					/*12字节预留*/
					idx += 12u; /*-< 当前数据下标自增12*/

					if ((curExcelPos + 40u) <= dataLen) /*-< 需使用数据长度是否合法*/
					{
						crcVal = LongFromChar(&data[curExcelPos]); /*-< 得到CRC值*/
						curExcelPos += 4u; /*-< 当前excel位置自增4*/

						/*4字节excel版本*/
						curExcelPos += 4u; /*-< 当前excel位置自增4*/

						curLen = LongFromChar(&data[curExcelPos]); /*-< 得到excel长度*/
						curExcelPos += 4u; /*-< 当前excel位置自增4*/

						if ((4u < curLen) && ((curExcelStartPos + curLen) <= dataLen)) /*-< excel长度大于4 且excel开始位置加长度小于等于数据长度*/
						{
							deepPro = 1u; /*-< 设置处理标志为处理*/
						}
						else /*长度错误*/
						{
							isBreak = 1u; /*-< 设置是否退出遍历标识为是*/
						}
					}
					else /*长度错误*/
					{
						isBreak = 1u; /*-< 设置是否退出遍历标识为是*/
					}
				}
				else /*继续找*/
				{
					idx += 20u; /*-< 当前数据下标自增20*/
				}
			}
			else /*长度错误*/
			{
				isBreak = 1u; /*-< 设置是否退出遍历标识为是*/
			}

			if (1u == deepPro) /*-< 处理标志是否为处理*/
			{
				crc = Crc32(&data[curExcelStartPos + 4u], curLen - 4u); /*-< 计算excel数据CRC值*/
				if (crc == crcVal) /*-< 计算CRC值是否与数据中相等*/
				{
					sheetCount = LongFromChar(&data[curExcelPos]); /*-< 得到sheet页数量*/
					curExcelPos += 4u; /*-< 当前excel位置自增4*/

					/*24字节预留*/
					curExcelPos += 24u; /*-< 当前excel位置自增24*/

					isBreak = StDsuPtclFindSheet(sheetInfo, data, dataLen, curExcelStartPos, &curExcelPos, sheetCount, sheetId); /*-< 调用找对应sheet页数据函数*/
				}
				else /*crc错误*/
				{
					isBreak = 1u; /*-< 设置是否退出遍历标识为是*/
				}
			}

			if (1u == isBreak) /*-< 退出遍历标识为是否为是*/
			{
				break; /*-< 退出遍历*/
			}
		}
	}
}

/**
 * @brief StDsuPtclFindSheet 找对应sheet页数据
 * @param sheetInfo sheet页信息 取值范围:参考结构体SheetInfo
 * @param data 数据数组 取值范围:字节数组
 * @param dataLen 数据长度 取值范围:0x00000000-0xFFFFFFFF
 * @param curExcelStartPos excel开始位置 取值范围:0x00000000-0xFFFFFFFF
 * @param curExcelPos 当前excel位置 取值范围:0x00000000-0xFFFFFFFF
 * @param sheetCount sheet页数量 取值范围:0x00000000-0xFFFFFFFF
 * @param sheetId sheet页ID 取值范围:0x00000000-0xFFFFFFFF
 * @return 0:不退出遍历 1:退出遍历
 */
static UINT8 StDsuPtclFindSheet(SheetInfo* sheetInfo, UINT8 data[], const UINT32 dataLen, UINT32 curExcelStartPos, UINT32* curExcelPos, UINT32 sheetCount, const UINT32 sheetId)
{
	/*- 定义局部变量*/
	UINT8 rtnVal = 0u; /*-< 设置函数返回值为不退出遍历*/
	UINT32 sheetIdx = 0u; /*sheet下标*/
	UINT32 curSheetId = 0u; /*当前sheet序号*/
	UINT32 curSheetStartPos = 0u; /*当前sheet开始位置*/

	if ((NULL != sheetInfo) && (NULL != data) && (NULL != curExcelPos)) /*-< 参数是否非空*/
	{
		for (sheetIdx = 0u; sheetIdx < sheetCount; sheetIdx++) /*-< sheet页下标是否sheet页数量*/
		{
			if (((*curExcelPos) + 24u) <= dataLen) /*-< 需使用数据长度是否合法*/
			{
				curSheetId = LongFromChar(&data[*curExcelPos]); /*-< 得到当前sheet页ID*/
				(*curExcelPos) += 4u; /*-< 当前excel位置自增4*/
				if (curSheetId == sheetId) /*-< 得到当前sheet页ID是否为要找的*/
				{
					sheetInfo->Id = curSheetId; /*-< 设置当前sheet页ID到sheet页信息*/

					sheetInfo->Len = LongFromChar(&data[*curExcelPos]); /*-< 设置长度到sheet页信息*/
					(*curExcelPos) += 4u; /*-< 当前excel位置自增4*/

					curSheetStartPos = LongFromChar(&data[*curExcelPos]); /*-< 设置sheet相对excel位置到sheet页信息*/
					(*curExcelPos) += 4u; /*-< 当前excel位置自增4*/

					sheetInfo->RowCount = ShortFromChar(&data[*curExcelPos]); /*-< 设置行数到sheet页信息*/
					(*curExcelPos) += 2u; /*-< 当前excel位置自增2*/

					/*2字节列数-无用*/
					(*curExcelPos) += 2u; /*-< 当前excel位置自增2*/
					/*8字节预留*/
					(*curExcelPos) += 8u; /*-< 当前excel位置自增8*/

					sheetInfo->Data = &data[curExcelStartPos + curSheetStartPos]; /*-< 设置sheet页开始数据到sheet页信息*/

					if (0u < sheetInfo->RowCount) /*-< 是否有行数*/
					{
						if ((0u < sheetInfo->Len) && (0u == (sheetInfo->Len % sheetInfo->RowCount))) /*-< 是否有数据且数据长度行数可整除*/
						{
							sheetInfo->ColLen = sheetInfo->Len / sheetInfo->RowCount; /*-< 得到列数据长度*/
						}
						else /*数据错误*/
						{
							sheetInfo->Len = 0u; /*-< 设置数据长度为0*/
							sheetInfo->RowCount = 0u; /*-< 设置行数为0*/
							sheetInfo->Data = NULL; /*-< 设置数据为NULL*/
						}
					}
					else /*无行数*/
					{
						sheetInfo->Len = 0u; /*-< 设置数据长度为0*/
						sheetInfo->Data = NULL; /*-< 设置数据为NULL*/
					}

					rtnVal = 1u; /*-< 设置函数返回值为退出遍历*/
				}
				else
				{
					(*curExcelPos) += 20u; /*-< 当前excel位置自增20*/
				}
			}
			else /*长度错误*/
			{
				rtnVal = 1u; /*-< 设置函数返回值为退出遍历*/
			}

			if (1u == rtnVal) /*-< 函数返回值是否为退出遍历*/
			{
				break; /*-< 退出遍历*/
			}
		}
	}

	return rtnVal; /*-< 返回函数返回值*/
}

/**
 * @brief StDsuPtclSetDevNum 设置设备数量
 * @param locType 本方类型 取值范围:0x00-0xFF
 * @param oppType 对方类型 取值范围:0x00-0xFF
 * @param outDevIpSheet 外部设备IP表 取值范围:参考结构体SheetInfo
 * @param inDevIpSheet 内部设备IP表 取值范围:参考结构体SheetInfo
 * @param dupOppHlhtIdLen 对方互联互通ID数组长度 取值范围:0x0000-0xFFFF
 * @param dupOppHlhtId 对方互联互通ID数组 取值范围:0x0000-0xFFFF
 * @param outInDevIpRowCount 设备IP最大行数 取值范围:0x00000000-0xFFFFFFFF
 * @param devNum 设备数量 取值范围:0x00-0xFF
 */
static void StDsuPtclSetDevNum(UINT8 locType, UINT8 oppType, SheetInfo* outDevIpSheet, SheetInfo* inDevIpSheet, UINT16* dupOppHlhtIdLen, UINT32* dupOppHlhtId, UINT16 outInDevIpRowCount, UINT8* devNum)
{
	if (NULL != devNum) /*-< 参数是否非空*/
	{
		(*devNum) = 0u; /*-< 清设备数量为0*/

		if (((VOBC_TYPE == locType) || (IVOC_TYPE == locType)) && ((AOM_TYPE == oppType) || (IVOC_AOM_TYPE == oppType) || (ITE_TYPE == oppType))) /*-< 本方类型为CBTC车或IVOC车 且对方类型为CBTC的AOM或IVOC的AOM或ITE*/
		{
			/*- 本方是ATP对方是AOM,ITE时通信数量固定为2*/
			(*devNum) = 2u;
		}
		else if (((VOBC_TYPE == locType) || (IVOC_TYPE == locType)) && ((CI_TYPE == oppType) || (RC_TYPE == oppType) || (ZC_TYPE == oppType) || (ATS_TYPE == oppType) || (PSC_TYPE == oppType) || (OC_TYPE == oppType))) /*-< 本方类型为CBTC车或IVOC车 且对方类型为CI或RC或ZC或ATS或PSC或OC*/
		{
			/*- 本方是ATP对方是CI,ZC,ATS,PSC,OC时通信数量固定为3*/
			(*devNum) = 3u;
		}
		else
		{
			GetCommOppDevNum(outDevIpSheet, oppType, dupOppHlhtIdLen, dupOppHlhtId, outInDevIpRowCount, devNum); /*- 调用函数获取外部通信的对方设备数量*/
			GetCommOppDevNum(inDevIpSheet, oppType, dupOppHlhtIdLen, dupOppHlhtId, outInDevIpRowCount, devNum); /*- 调用函数获取内部通信的对方设备数量*/
		}
	}
}

/**
 * @brief GetCommOppDevTypes 获取通信的对方设备类型数组
 * @param commSheet 设备通信协议表 取值范围:参考结构体SheetInfo
 * @param locType 本方类型 取值范围:0x00-0xFF
 * @param oppTypes 对方类型数组 取值范围:字节数组
 * @param oppTypePtls 对方类型协议数组 取值范围:字节数组
 * @param oppTypeNum 对方类型数量 取值范围:0x0000-0xFFFF
 * @param maxOppTypeNum 最大对方类型数量 取值范围:0x0000-0xFFFF
 * @return 0:失败 1:成功
 */
static UINT8 GetCommOppDevTypes(SheetInfo* commSheet, UINT8 locType, UINT8* oppTypes, UINT8* oppTypePtls, UINT16* oppTypeNum, const UINT16 maxOppTypeNum)
{
	/*- 定义局部变量*/
	const UINT32 commColLen = 3u; /*需要设备通信协议表列长度*/
	UINT8 retVal = 0u; /*-< 设置函数返回值为0*/
	UINT32 i = 0u; /*用于循环*/
	UINT32 j = 0u; /*用于循环*/
	UINT8 locDevType = 0u; /*本方设备类型*/
	UINT8 oppDevType = 0u; /*对方设备类型*/
	UINT8 ptlType = 0u; /*协议类型*/
	UINT8 isAddOppType = 0u;	/*是否添加对方类型*/
	UINT8 isConfigErr = 0u; /*是否配置错误*/

	if ((NULL != commSheet) && (NULL != oppTypes) && (NULL != oppTypePtls) && (NULL != oppTypeNum) && (NULL != commSheet->Data) && (commSheet->ColLen >= commColLen)) /*-< 参数非空 且有数据*/
	{
		for (i = 0u; i < commSheet->RowCount; i++) /*-< 行数下标是否小于总行数*/
		{
			locDevType = commSheet->Data[i * commSheet->ColLen]; /*-< 得到本方类型ID*/
			oppDevType = commSheet->Data[(i * commSheet->ColLen) + 1u]; /*-< 得到对方类型ID*/
			ptlType = commSheet->Data[(i * commSheet->ColLen) + 2u]; /*-< 得到协议类型ID*/
			if (9u == ptlType) /*-< 数据中RSSPII类型是否为9*/
			{
				ptlType = DSU_PROTCL_RSSP2; /*-< 设置内部RSSPII类型为5*/
			}
			if (locDevType == locType) /*-< 是否为本方类型*/
			{
				isAddOppType = 0u; /*-< 设置是否增加类型为否*/
				for (j = 0u; j < (*oppTypeNum); j++) /*-< 遍历查看是否有重复对方类型*/
				{
					if (oppTypes[j] == oppDevType) /*-< 有重复对方类型*/
					{
						if (oppTypePtls[j] != ptlType) /*-< 使用协议类型不同*/
						{
							isConfigErr = 1u; /*-< 设置配置错误*/
						}
						break;
					}
				}
				if (j == (*oppTypeNum))	/*-< 类型不重复*/
				{
					isAddOppType = 1u; /*-< 设置是否增加类型为是*/
				}
				if (0u == isConfigErr) /*-< 配置正常*/
				{
					if ((1u == isAddOppType) && ((*oppTypeNum) < maxOppTypeNum)) /*-< 是增加类型*/
					{
						oppTypes[*oppTypeNum] = oppDevType;	/*-< 设置对方类型*/
						oppTypePtls[*oppTypeNum] = ptlType;	/*-< 设置使用协议类型*/
						(*oppTypeNum)++; /*-< 设置使用协议类型数自增1*/
					}
				}
				else /*配置错误,退出遍历*/
				{
					break;
				}
			}
		}
		if (0u == isConfigErr)	/*-< 配置正常*/
		{
			retVal = 1u; /*-< 设置函数返回值为1*/
		}
	}

	return retVal; /*-< 返回函数返回值*/
}

/**
 * @brief GetCommOppDevNum 获取通信的对方设备数量
 * @param devIpSheet 设备IP表 取值范围:参考结构体SheetInfo
 * @param oppType 对方类型 取值范围:0x00-0xFF
 * @param dupOppHlhtIdsLen 重复的对方互联互通ID长度 取值范围:0x0000-0xFFFF
 * @param dupOppHlhtIds 重复的对方互联互通ID 取值范围:字节数组
 * @param maxDupOppHlhtIdsLen 最大重复的对方互联互通ID长度 取值范围:0x0000-0xFFFF
 * @param devNum 设备数量 取值范围:0x00-0xFF
 */
static void GetCommOppDevNum(SheetInfo* devIpSheet, UINT8 oppType, UINT16* dupOppHlhtIdsLen, UINT32* dupOppHlhtIds, const UINT16 maxDupOppHlhtIdsLen, UINT8* devNum)
{
	/*- 定义局部变量*/
	const UINT32 devIpColLen = 6u; /*需要设备IP地址列长度*/
	UINT32 i = 0u; /*用于循环*/
	UINT32 j = 0u; /*用于循环*/
	UINT16 devId = 0u; /*设备ID*/
	UINT32 hlhtId = 0u; /*HLHT ID*/

	if ((NULL != devIpSheet) && (NULL != dupOppHlhtIdsLen) && (NULL != dupOppHlhtIds) && (NULL != devNum) && (NULL != devIpSheet->Data) && (devIpSheet->ColLen >= devIpColLen)) /*-< 参数非空 且有数据*/
	{
		for (i = 0u; i < devIpSheet->RowCount; i++) /*-< 行数下标是否小于总行数*/
		{
			devId = ShortFromChar(&devIpSheet->Data[i * devIpSheet->ColLen]); /*-< 得到设备ID*/
			hlhtId = LongFromChar(&devIpSheet->Data[(i * devIpSheet->ColLen) + 2]); /*-< 得到互联互通ID*/
			if (((UINT8)(devId >> 8)) == oppType) /*-< 设备类型是否对方类型*/
			{
				for (j = 0u; j < (*dupOppHlhtIdsLen); j++) /*-< 设备类型是否对方类型*/
				{
#ifdef DEV_IP_TABLE_NO_HLHT
					if (dupOppHlhtIds[j] == devId)	/*-< 此HLHT ID重复,退出遍历*/
					{
						break;
					}
#else
					if (dupOppHlhtIds[j] == hlhtId)	/*-< 此HLHT ID重复,退出遍历*/
					{
						break;
					}
#endif
				}
				if ((j == (*dupOppHlhtIdsLen)) && ((*dupOppHlhtIdsLen) < maxDupOppHlhtIdsLen))	/*-< 此HLHT ID不重复*/
				{
#ifdef DEV_IP_TABLE_NO_HLHT
					dupOppHlhtIds[*dupOppHlhtIdsLen] = devId; /*-< 添加HLHT ID*/
#else
					dupOppHlhtIds[*dupOppHlhtIdsLen] = hlhtId; /*-< 添加HLHT ID*/
#endif
					(*dupOppHlhtIdsLen)++; /*-< 用来比较的HLHT ID加1*/
					(*devNum)++; /*-< 设备数量加1*/
				}
			}
		}
	}
}
