⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iec103_sf.cpp

📁 四方公司103规约
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		if (0x10 == pSend[0])
		{
			LPDU_Fix_Fmt *pFmt = (LPDU_Fix_Fmt *)pSend;
			addr = pFmt->addr;
		}
		else
		{
			LPDU_Vol_Head *pHead = (LPDU_Vol_Head *)pSend;
			addr = pHead->addr;
		}

		BYTE byNodeID = m_IEC103Data.m_addrtoID[addr];
		RealRunIED *pRunIed = m_IEC103Data.m_RunIed[byNodeID];	
		if (pRunIed)
		{
			pRunIed->linkRes = 1;
			pRunIed->lnkNoRecvCnt ++;
			if (pRunIed->lnkNoRecvCnt > 5)
			{
				CIED* pIED = pRunIed->pDevData;
				//DevYxPara devYx = pBayDev->GetDevYxPara();
				//pIED->SetYaoXinRecvVal(devYx.wComYxId, 1);
			}
		}
	}

	//链路层解帧
	void CIEC103_SFPtl::UnpackLPDU(BYTE *pRecvBuf)
	{
		// 链路层解帧
		BYTE* pRecv = pRecvBuf;

		LinkCtrl lnkCtrl;
		BYTE	 addr;
		// 固定帧长
		if (0x10 == pRecv[0])
		{	
			LPDU_Fix_Fmt *pFmt = (LPDU_Fix_Fmt *)pRecv;
			lnkCtrl = pFmt->ctrl;
			addr = pFmt->addr;
		}
		else
		{	// 可变帧长
			LPDU_Vol_Head *pHead = (LPDU_Vol_Head *)pRecv;
			lnkCtrl = pHead->ctrl;
			addr = pHead->addr;
		}

		BOOL bACD = FALSE;
		BYTE byNodeID = m_IEC103Data.m_addrtoID[addr];			//装置地址值是从接收的数据中取得
		RealRunIED *pRunIed = m_IEC103Data.m_RunIed[byNodeID];	//装置节点则是m_addrtoID[addr]
		if (pRunIed)											//由装置节点取得设备描述指针
		{
			// 链路恢复正常
			if (pRunIed->linkRes)
			{
				pRunIed->linkRes = pRunIed->linkQuery = pRunIed->fcb = 0;
				pRunIed->queryFull = pRunIed->query = 1;

				// 通讯恢复正常
				pRunIed->lnkNoRecvCnt = 0;
				//CIED *pIED = pRunIed->pDevData;
				//DevYxPara devYx = pBayDev->GetDevYxPara();
				//pBayDev->SetYaoXinRecvVal(devYx.wComYxId, 0);
			}	
			if (0x68 == pRecv[0])
			{	
				UnpackASDU_Ied(pRecvBuf, pRunIed);
			}

			pRunIed->acd = lnkCtrl.fcbAcd;
			pRunIed->linkQuery = lnkCtrl.fcvDfc;

			if(pRunIed->acd)//080905修改,适应现场需要,如果有1级数据立刻查询,不再等到下一轮
			{
				m_IEC103Data.m_byCycCnt = byNodeID;
				bACD = TRUE;
			}
		}

		//if(!bACD)//080905修改,适应现场需要,如果有1级数据立刻查询,不再等到下一轮
		//	m_IEC103Data.m_byCycCnt = (m_IEC103Data.m_byCycCnt+1) % CH_MAX_IED_NUM;
		// 转入组帧过程
		m_IEC103Data.m_runStep = PtlRun_PackASDU;
	}

	/*****
	*UnpackASDU_Ied - 应用层解帧函数
	*
	*功能:
	*	应用服务数据单元解帧函数 
	*
	******/
	void CIEC103_SFPtl::UnpackASDU_Ied(BYTE *pRecvBuf, RealRunIED *pRunIed)
	{
		// 防护
		if (!pRunIed)
			return;

		ASDU_Head *pHead = (ASDU_Head *)(pRecvBuf + sizeof(LPDU_Vol_Head));

		BYTE* buf = pRecvBuf + sizeof(LPDU_Vol_Head);	//buf指向ASDU的首地址TYPE
		BYTE  len = pRecvBuf[1] - 2;					//len代表ASDU的长度

		switch (pHead->type)
		{
		case M_TM_TA_3:
			Unpack_Asdu_1(buf, len, pRunIed);
			break;
		case M_TMR_TA_3:
			Unpack_Asdu_2(buf, len, pRunIed);
			break;
		case M_GD_NTA_3://1.解遥测;2.通用分类服务总召结束
			Unpack_ASDU_10(buf,len,pRunIed);
			break;
		case M_MEVII_NA_3:
			Unpack_Asdu_50(buf, len, pRunIed);
			break;
		case M_IT_NA_3:
			Unpack_Asdu_36(buf, len-1, pRunIed);
			break;
		case M_IT_TA_3:
			Unpack_Asdu_37(buf, len-1, pRunIed);
			break;
		case M_MEI_NA_3:
			Unpack_Asdu_3(buf, len, pRunIed);
			break;
		case M_TME_TA_3:
			Unpack_Asdu_4(buf, len, pRunIed);
			break;
		case M_IRC_NA_3:
			{
				Unpack_Asdu_5(buf, len, pRunIed);
				if(pRunIed->step == eInitStart)
				{
					pRunIed->nASDU5Cnt++;
					if(pRunIed->nASDU5Cnt >= 2)
						pRunIed->step = eInitTime;
				}
				break;
			}
		case M_SYN_TA_3://时钟同步
			Unpack_Asdu_6(buf, len, pRunIed);
			if(eInitTime == pRunIed->step)
				pRunIed->step = eInitGenAsk;
			break;
		case M_TGI_NA_3://总招结束
			Unpack_Asdu_8(buf, len, pRunIed);
			if(eInitGenAsk == pRunIed->step)
			{
				pRunIed->step = eInitGenGroupAsk;//总召结束,进入通用分类数据总召
				//pRunIed->step = eInitEnd;
				//pRunIed->bCommInitFlag = FALSE;
				//pRunIed->nASDU5Cnt = 0;
			}
			break;
		case M_MEII_NA_3:
			Unpack_Asdu_9(buf, len, pRunIed);
			break;
		case M_GI_NTA_3:
			Unpack_Asdu_11(buf, len, pRunIed);
			break;
		case M_LRT_TA_3:
			Unpack_Asdu_23(buf, len, pRunIed);
			break;
		case M_RTD_TA_3:
			Unpack_Asdu_26(buf, len, pRunIed);
			break;
		case M_RTC_NA_3:
			Unpack_Asdu_27(buf, len, pRunIed);
			break;
		case M_RTT_NA_3:
			Unpack_Asdu_28(buf, len, pRunIed);
			break;
		case M_TDT_TA_3:
			Unpack_Asdu_29(buf, len, pRunIed);
			break;
		case M_TDN_NA_3:
			Unpack_Asdu_30(buf, len, pRunIed);
			break;
		case M_EOT_NA_3:
			Unpack_Asdu_31(buf, len, pRunIed);
			break;
		case M_MEIII_TA_3:
			Unpack_Asdu_32(buf, len, pRunIed);
			break;
		case M_MEIV_TA_3:
			Unpack_Asdu_33(buf, len, pRunIed);
			break;
		case M_MEV_TA_3:
			Unpack_Asdu_34(buf, len, pRunIed);
			break;
		case M_MEVI_TA_3:
			Unpack_Asdu_35(buf, len, pRunIed);
			break;
		case M_ST_NA_3:
			Unpack_Asdu_38(buf, len, pRunIed);
			break;
		case M_ST_TA_3:
			Unpack_Asdu_39(buf, len, pRunIed);
			break;
		case M_SP_NA_3:
		case M_DP_NA_3:
			Unpack_Asdu_4042(buf, len-1, pRunIed);
			break;
		case M_SP_TA_3:
		case M_DP_TA_3:
			Unpack_Asdu_4143(buf, len-1, pRunIed);
			break;
		case M_SS_NA_3:
		case M_DS_NA_3:
			Unpack_Asdu_4446(buf, len-1, pRunIed);
			break;
		case M_SS_TA_3:
		case M_DS_TA_3:
			Unpack_Asdu_4547(buf, len-1, pRunIed);
			break;
		case M_WL_TA_3:
			Unpack_Asdu_48(buf, len, pRunIed);
			break;
		case M_DC_NA_3:
			Unpack_Asdu_64(buf, len, pRunIed);
			break;
		case M_RC_NA_3:			
			Unpack_Asdu_65(buf, len, pRunIed);
			break;
		case M_SE_NA_3:
			Unpack_Asdu_66(buf, len, pRunIed);
			break;
		case M_CC_NA_3:
			Unpack_Asdu_67(buf, len, pRunIed);
			break;
		case M_ASDU_70:
			Unpack_Asdu_70(buf, len, pRunIed);
			break;
		case M_CI_NA_3:
			Unpack_Asdu_88(buf, len, pRunIed);
			break;
		case 0x31://VQC装置上送保护事项的桢格式
			//	Unpack_Asdu_49(buf, len, pRunIed);
		default:
			break;
		}
	}

	// 带时标的报文(事项)
	void CIEC103_SFPtl::Unpack_Asdu_1(BYTE* buf, BYTE len, RealRunIED *pRunIed)
	{
		int nIndex;
		TASK *pTask = NULL;
		CIED *pIED = pRunIed->pDevData;
		BYTE byNodeID = pIED->m_IEDConfig.byNodeID;

		ASDU_1_Fmt *pFmt = (ASDU_1_Fmt *)buf;
		//调整时间
		WB_UNION wb;
		wb.bwUnion.byVal[0] = pFmt->tm.byHighMs;
		wb.bwUnion.byVal[1] = pFmt->tm.byLowMs;

		BYTE yxBit = (pFmt->dpi & 0x03) >> 1;
		// 命令确认报文(肯定/否定)
		if (M_AFM_ORD == pFmt->head.cot || M_NEG_ORD == pFmt->head.cot) 
		{
			if((WatchTask(pTask, taskCmdYkSelect, byNodeID) ||
				WatchTask(pTask, taskCmdYkExecute, byNodeID) ||
				WatchTask(pTask, taskCmdYkCancel, byNodeID)) && pTask)
			{
				// 遥控命令
				YK_COMMAND *pCommand = (YK_COMMAND *)pTask->iUserData;
				nIndex = GetnIndexbyFuninf(pIED, dataYk, pFmt->head.funInf);
				if(nIndex >= 0)
				{
					if (nIndex != pCommand->byYkNode || M_NEG_ORD == pFmt->head.cot) 
					{
						if (pCommand->byAction == yk_PrevH ||pCommand->byAction == yk_PrevF)
							pCommand->eReturn = fj_wrong;
						else
							pCommand->eReturn = act_wrong;
						pTask->eTaskReturn=retWrong;
					}
					else
					{
						if (pCommand->byAction == yk_PrevH ||pCommand->byAction == yk_PrevF)
							pCommand->eReturn = fj_right;
						else
							pCommand->eReturn = act_right;
						pTask->eTaskReturn=retRight;
					}
					pTask->eRespType = taskCmdYkReturn;
					m_pCH->TaskResp(pTask);
					//m_pCH->m_pTaskQue->UnLockTask();
				}
			}
			else if(WatchTask(pTask, taskCmdBhReset, byNodeID) && pTask)
			{// 保护复归
				/*	if (M_NEG_ORD == pFmt->head.cot)
				pTask->iUserData[0] = retWrong;
				else
				pTask->iUserData[0] = retRight;

				pTask->eRespType = taskRespBhReset;
				m_pCH->TaskResp(pTask);
				m_pCH->m_pTaskQue->UnLockTask();
				*/}
			// 通道任务(复归)
			else if(WatchTask(pTask, taskChThree, byNodeID) && pTask) 
			{
				/*
				* 
				*=======================================================
				*	描述					偏移量				占位空间	
				*-------------------------------------------------------
				*	相应数据总长度			0~1				2
				*	**103数据帧总个数N		2~3				2
				*-------------------------------------------------------
				*	**103数据帧1总长度L1	4					1
				*	**103数据帧1			5~L1+5				L1
				*	**103数据帧2总长度L2	L1+6				1
				*	**103数据帧2			L1+7~L1+7+8 	L2
				*	**。。。	。。。	。。。
				*	**103数据帧2总长度LN 	X					1
				*	**103数据帧N			X~X+LN			LN
				*/
				pTask->pbyBuff = g_pTaskDataBuff->QueryBuf(pTask->byDataBufIndex);//分配空间
				if(pTask->pbyBuff == NULL)
					return;
				pTask->nDataBufLen = 0;
				pTask->bWithDataF = TRUE;
				if(SaveTaskRespFmt(buf - sizeof(LPDU_Vol_Head), len + 8, pTask))
				{
					pTask->eRespType = taskZF;
					m_pCH->TaskResp(pTask);
					//m_pCH->m_pTaskQue->UnLockTask();
				}
			}
		}
		// 通用数据传输
		else 
		{
			// 主动传送/测试模式(事项存储)
			BOOL bStateChg = FALSE;
			eDataSort data;
			nIndex = GetnIndexbyFuninf(pIED, dataYx, pFmt->head.funInf);//先取实遥信的索引
			data = dataYx;
			if(nIndex == -1)
			{
				nIndex = GetnIndexbyFuninf(pIED, dataBhYx, pFmt->head.funInf);//取保护虚遥信索引
				data = dataBhYx;
			}
			TIME_STRUCT sysTime;
			g_pMainApp->GetSystime(&sysTime);
			if(data == dataBhYx)
			{
				//存事项
				BHEVENT_STRUCT bhevent;
				bhevent.eDS=(eDataSource)m_pCH->m_ChConfig.eDS;			// 数据源
				bhevent.nIEDType=pIED->m_IEDConfig.usIEDType;//iedSF103;							// 装置类型
				//printf("装置类型:%d\n",pIED->m_IEDConfig.usIEDType);
				bhevent.eEventType=dataBh;								// 事项类型()
				bhevent.nEventNode=nIndex;								// 事项点
				bhevent.nNode=pIED->m_IEDConfig.byNodeID;
				bhevent.nEventVal=0x10;
				if(yxBit == 1)
					bhevent.nEventVal = 0x01;
				bhevent.nFunCode=bhevent.nEventVal;// 事项值

				bhevent.TimeStamp.nMs = wb.bwUnion.wVal % 1000;
				bhevent.TimeStamp.bySecond = wb.bwUnion.wVal / 1000;
				bhevent.TimeStamp.byMinute = pFmt->tm.Minutes;
				bhevent.TimeStamp.byHour	 = pFmt->tm.Hours;
				bhevent.TimeStamp.byDay    = sysTime.byDay;
				bhevent.TimeStamp.byMonth  = sysTime.byMonth;
				bhevent.TimeStamp.nYear    = sysTime.nYear;

				memcpy(bhevent.byUserData, buf, len);					//事项数据
				bhevent.nUserDataLen = len;							//记录数据缓冲区长度

				m_pCH->m_pBhSoeQue->Add(bhevent);

				if(!m_IEC103PtlPara.bEventVirtualYX)//参数设置,保护事项不需要转成虚遥信
					return;
			}
			// 遥信变位判别
			BYTE byYXRecvVal = pIED->GetDataRecvVal(data,0,nIndex);
			if (nIndex >= 0) 
			{
				if (byYXRecvVal != yxBit)
					bStateChg = TRUE;
			}

			// 遥信存储
			if (nIndex >= 0)//设置遥信值
				pIED->SetDataRecvVal(data,0,nIndex,yxBit);
			// 事项存储等待
			if (bStateChg) 
			{	
				// 遥信变位存储
				// 事项存储
				EVENT_STRUCT bhent;

				bhent.eDS		 = (eDataSource)m_pCH->m_ChConfig.eDS;	// 数据源
				bhent.eEventType = data;					// 事项类型(开关类)
				bhent.nEventNode = nIndex;					// 事项点
				bhent.nEventVal  = 0x10;					// 事项值
				if(yxBit == 1)
					bhent.nEventVal = 0x01;
				bhent.nNode      = pIED->m_IEDConfig.byNodeID;// 设备节点
				bhent.TimeStamp.nMs = wb.bwUnion.wVal % 1000;
				bhent.TimeStamp.bySecond = wb.bwUnion.wVal / 1000;
				bhent.TimeStamp.byMinute = pFmt->tm.Minutes;
				bhent.TimeStamp.byHour	 = pFmt->tm.Hours;
				bhent.TimeStamp.byDay    = sysTime.byDay;
				bhent.TimeStamp.byMonth  = sysTime.byMonth;
				bhent.TimeStamp.nYear    = sysTime.nYear;

				m_pCH->m_pYxbwSoeQue->Add(bhent);
				m_pCH->m_pYxSoeQue->Add(bhent);	
			}
		}
	}

	// 带相对时间的时标报文,在许继103中是保护动作事项报文
	void CIEC103_SFPtl::Unpack_Asdu_2(BYTE* buf, BYTE len, RealRunIED *pRunIed)
	{
		ASDU_2_Fmt *pFmt = (ASDU_2_Fmt *)buf;
		TIME_STRUCT sysTime;
		g_pMainApp->GetSystime(&sysTime);
		//调整数据值
		WB_UNION wb;
		wb.bwUnion.byVal[0] = pFmt->ret.byHigh;
		wb.bwUnion.byVal[1] = pFmt->ret.byLow;

		wb.bwUnion.byVal[0] = pFmt->fan.byHigh;
		wb.bwUnion.byVal[1] = pFmt->fan.byLow;


		CIED *pIED = pRunIed->pDevData;
		if(pIED == NULL)
			return;

		eDataSort data;
		int	nIndex = GetnIndexbyFuninf(pIED, dataBhYx, pFmt->head.funInf);//取保护虚遥信索引
		data = dataBhYx;
		if(nIndex == -1)
			return;

		BYTE yxBit = (pFmt->dpi & 0x03) >> 1;//单点遥信

		//存事项
		BHEVENT_STRUCT bhevent;
		bhevent.eDS=(eDataSource)m_pCH->m_ChConfig.eDS;			// 数据源
		bhevent.nServID = 0;							//new 08.9.12
		bhevent.nIEDType=pIED->m_IEDConfig.usIEDType;//iedSF103;							// 装置类型
		bhevent.eEventType=dataBh;								// 事项类型()
		bhevent.nEventNode=nIndex;								// 事项点
		bhevent.nNode=pIED->m_IEDConfig.byNodeID;
		bhevent.nEventVal=0x10;
		if(yxBit == 1)
			bhevent.nEventVal = 0x01;
		bhevent.nFunCode=bhevent.nEventVal;// 事项值

		wb.bwUnion.byVal[0] = pFmt->tm.byHighMs;
		wb.bwUnion.byVal[1] = pFmt->tm.byLowMs;

		bhevent.TimeStamp.nMs = wb.bwUnion.wVal % 1000;
		bhevent.TimeS

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -