📄 iec103_sf.cpp
字号:
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 + -