📄 iec103_xuji.cpp
字号:
else
DafaultPtlPara();
m_pCH->m_ChConfig.byPtlKind=0;
m_ePtlType = ptl103;
for(i=0; i<m_pCH->m_ChConfig.byIEDNum; i++)
{
CIED *pIED = m_pCH->m_pIED[i];
if(pIED == NULL)
continue;
CreateRealRunIED(pIED);
m_IEC103Data.m_addrtoID[pIED->m_IEDConfig.byNodeAddr] = pIED->m_IEDConfig.byNodeID;
}
// 规约运行步骤
m_IEC103Data.m_runStep = PtlRun_PackASDU;
m_IEC103Data.m_byCycCnt = 0;
// 规约任务区
memset(&m_IEC103Data.m_task103, 0, sizeof(m_IEC103Data.m_task103));
// 服务原语
memset(&m_IEC103Data.m_prmSend, 0, sizeof(CommPrim));
memset(&m_IEC103Data.m_prmRecv, 0, sizeof(CommPrim));
// 收发缓冲区
m_IEC103Data.m_wLinkLen = 0;
m_IEC103Data.m_wSendNum = 0;
// 计时器初始化
DWORD dwRatio = GetChRatio();
DWORD dwDly = (3*11*1000 + dwRatio-1) / dwRatio;
// 帧超时时间
m_IEC103Data.m_frmOver.SetWaitSpan(m_IEC103PtlPara.dwFrameOver);
// 帧间隔时间
m_IEC103Data.m_frmDly33.SetWaitSpan(dwDly);
// 总召唤间隔
m_IEC103Data.m_queryCnt.SetWaitSpan((m_IEC103PtlPara.dwQuery/2) * 1000);
m_IEC103Data.m_queryCnt.Start(m_nCnt);
//校时间隔
m_IEC103Data.m_timeover.SetWaitSpan(m_IEC103PtlPara.wTimeOver * 1000);
m_IEC103Data.m_timeover.Start(m_nCnt);
// 通道无数据接收监视,
m_IEC103Data.m_lnkSerialError = 0;
m_IEC103Data.m_bySendCnt = 0;
m_IEC103Data.m_bySin = 0;
memset(&m_IEC103Data.m_OldCmd, 0, sizeof(m_IEC103Data.m_OldCmd));
QueryRecvLPDU();
m_nCnt = 0;
SetTimer(2);
m_bAdjustTime = false;
}
void CIEC103_XUJIPtl::OnTimer(void)
{
m_nCnt++;
}
//组帧函数
INT CIEC103_XUJIPtl::Frame(BYTE* pSendBuf, INT nLen)
{
INT nret = 0;
// 总召唤/召唤脉冲计数定时到
if (m_IEC103Data.m_queryCnt.IsOverTime(m_nCnt))
{
m_IEC103Data.m_queryCnt.Start(m_nCnt);
for (int i = 0; i < CH_MAX_IED_NUM; i++)
{
RealRunIED *pRunIED = m_IEC103Data.m_RunIed[i];
if(pRunIED)
{
pRunIED->queryFull ^= 1; // 查询标志取反
pRunIED->query = 1;
}
}
}
/*应用层组帧
* 1) 发送通道任务命令
* 2) 发送普通的循环任务
*/
if (PtlRun_PackASDU == m_IEC103Data.m_runStep)
{
// 要求进行组帧处理
m_IEC103Data.m_wSendNum = 0;
m_IEC103Data.m_wLinkLen = 0;
// 初始化服务原语
memset(&m_IEC103Data.m_prmSend, 0, sizeof(CommPrim));
memset(&m_IEC103Data.m_prmRecv, 0, sizeof(CommPrim));
// 通道任务检测
if (!PackTask())
{
PackCyc(); // 循环查询任务
}
// 转入链路帧发送过程
m_IEC103Data.m_bySendCnt = 0;
if (m_IEC103Data.m_wSendNum > 0)
m_IEC103Data.m_runStep = PtlRun_SendLPDU;
}
// 辅机直接转入链路接收过程中
/*if (!lpCh->m_pDevDB->GetCcsModule( ))
{
pPtlData->m_runStep = PtlRun_RecvLPDU;
QueryRecvLPDU(lpCh);
}*/
// 等待链路接收
if (PtlRun_RecvLPDU == m_IEC103Data.m_runStep)
{
if (m_IEC103Data.m_frmOver.IsOverTime(m_nCnt))
{
m_IEC103Data.m_bySendCnt ++;
if (m_IEC103Data.m_bySendCnt > 2)
{
NoLPDU();
m_IEC103Data.m_runStep = PtlRun_PackASDU;
}
else
m_IEC103Data.m_runStep = PtlRun_SendLPDU;
}
}
// 链路层发送
if (PtlRun_SendLPDU == m_IEC103Data.m_runStep)
{
// 主机发送数据,辅机仅接收数据
//if (lpCh->m_pDevDB->GetCcsModule( ))
//{
// 等待超时监视
if(m_bAdjustTime)
{
m_bAdjustTime = false;
m_IEC103Data.m_runStep = PtlRun_PackASDU;
nret = m_IEC103Data.m_wSendNum;
}else
nret = PtlSendLPDU();
memcpy(pSendBuf, m_IEC103Data.m_bySend, nret);
//}
}
return nret;
}
// 链路层传输服务
// 1. 站初始化
// 2. 链路状态控制
BOOL CIEC103_XUJIPtl::PackLinkCmm(BYTE byNodeID)
{
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[byNodeID];
if(!pDevRun)
return FALSE;
if (!pDevRun->linkQuery && !pDevRun->linkRes)
return FALSE;
if (pDevRun->linkRes) { // 初始化
PackLPDU_Fix(byNodeID, ResCU_code);
pDevRun->bCommInitFlag = TRUE;
pDevRun->nASDU5Cnt = 0;
pDevRun->step = eInitStart;
}else if (pDevRun->linkQuery){ // 链路状态
PackLPDU_Fix(byNodeID, QueryLink_code);
}
return TRUE;
}
// 固定帧长链路数据组帧
void CIEC103_XUJIPtl::PackLPDU_Fix(BYTE byNodeID, BYTE byCode)
{
// if(m_IEC103Data.m_frmOver.IsOverTime(m_nCnt))
{
PackLPDU(byNodeID, byCode);
}
}
void CIEC103_XUJIPtl::PackLPDU(BYTE byNodeID, BYTE code)
{
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[byNodeID];
if(!pDevRun)
return;
LinkCtrl linkCtrl;
linkCtrl.funcode = code;
linkCtrl.res = 0;
linkCtrl.prm = 1;
switch(code)
{
case ResCU_code:
case ResFcb_code:
m_IEC103Data.m_lnkSvrCls = SendConfirm;
linkCtrl.fcvDfc = 0;
break;
case NoReply_code:
m_IEC103Data.m_lnkSvrCls = SendNoreply;
linkCtrl.fcvDfc = 0;
break;
case QueryLink_code:
m_IEC103Data.m_lnkSvrCls = RequestRespond;
linkCtrl.fcvDfc = 0;
break;
case SendCon_code:
m_IEC103Data.m_lnkSvrCls = SendConfirm;
linkCtrl.fcvDfc = 1;
break;
case CallClass1_code:
case CallClass2_code:
m_IEC103Data.m_lnkSvrCls = RequestRespond;
linkCtrl.fcvDfc = 1;
break;
default:
break;
}
// 链路帧控制字
linkCtrl.fcbAcd = 0;
if (linkCtrl.fcvDfc)
{
pDevRun->fcb = ~pDevRun->fcb;
linkCtrl.fcbAcd = pDevRun->fcb;
}
if (0 == m_IEC103Data.m_wSendNum)
{ // 固定帧长
LPDU_Fix_Fmt *pFmt = (LPDU_Fix_Fmt *)(m_IEC103Data.m_bySend);
pFmt->head = 0x10;
pFmt->ctrl = linkCtrl;
pFmt->addr = pDevRun->pDevData->m_IEDConfig.byNodeAddr;
pFmt->sum = pFmt->ctrl.lnkCtrl + pFmt->addr;
pFmt->tail = 0x16;
m_IEC103Data.m_wSendNum = sizeof(LPDU_Fix_Fmt);
}else {
LPDU_Vol_Head *pHead = (LPDU_Vol_Head *)(m_IEC103Data.m_bySend);
pHead->head1 = pHead->head2 = 0x68;
pHead->len1 = pHead->len2 = m_IEC103Data.m_wSendNum + 2;
pHead->ctrl = linkCtrl;
pHead->addr = pDevRun->pDevData->m_IEDConfig.byNodeAddr;
m_IEC103Data.m_wSendNum += sizeof(LPDU_Vol_Head);
m_IEC103Data.m_bySend[m_IEC103Data.m_wSendNum ++] = SumMod(m_IEC103Data.m_bySend + 4, pHead->len1);
m_IEC103Data.m_bySend[m_IEC103Data.m_wSendNum ++] = 0x16;
}
}
//循环查询组帧
/****
*PackCyc - 循环查询组帧函数
*
*功能:
* 1。总查询命令
* 2。故障录波
* 3。通用分类服务总查询
* 4。通用2级数据查询
*
****/
void CIEC103_XUJIPtl::PackCyc(void)
{
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[m_IEC103Data.m_byCycCnt];
if (pDevRun)
{
if (!PackLinkCmm(m_IEC103Data.m_byCycCnt))
{ // 链路层组帧
/*
* 应用层组帧
*
*命令优先级
* 1。扰动数据传输
* 2。通用分类服务总查询
* 3。召唤电度脉冲量
* 4。总查询(总召唤)
* 5。循环查询2级数据
**/
if(pDevRun->bCommInitFlag && !pDevRun->acd)
{
if(eInitTime == pDevRun->step && pDevRun->nASDU5Cnt>=2)//校时
{
SendAdjustTime103(pDevRun->pDevData->m_IEDConfig.byNodeAddr);
}else if(eInitGenAsk == pDevRun->step)//总召唤
{
Pack_Asdu_7(m_IEC103Data.m_byCycCnt);
}else
{
BYTE Code = CallClass2_code;
PackLPDU_Fix(m_IEC103Data.m_byCycCnt, Code);
}
}else if (!pDevRun->acd && pDevRun->query && !pDevRun->bCommInitFlag)
{
if (!pDevRun->queryFull)
{// 召唤电度量
if(pDevRun->pDevData->m_IEDConfig.nDdNum > 0)
Pack_Asdu_88(m_IEC103Data.m_byCycCnt);
}else// 总召唤
Pack_Asdu_7(m_IEC103Data.m_byCycCnt);
// 清除查询标志
pDevRun->query = 0;
}else if(m_IEC103Data.m_timeover.IsOverTime(m_nCnt) && !pDevRun->bCommInitFlag)//校时
{
m_IEC103Data.m_timeover.Start(m_nCnt);
BYTE byaddr = 0xff;
SendAdjustTime103(byaddr);
m_bAdjustTime = true;
}
else
{ // 通用查询
BYTE byCode = CallClass2_code;
if (pDevRun->acd)
byCode = CallClass1_code;
PackLPDU_Fix(m_IEC103Data.m_byCycCnt, byCode);
}
}
}
m_IEC103Data.m_byCycCnt = (m_IEC103Data.m_byCycCnt+1) % CH_MAX_IED_NUM;
}
//asdu88
void CIEC103_XUJIPtl::Pack_Asdu_88(BYTE byNodeID)
{
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[byNodeID];
BYTE byAddr = 0;
if(m_IEC103PtlPara.bCommAddr)
byAddr = m_IEC103PtlPara.byCKCPUAddr;
else
byAddr = pDevRun->pDevData->m_IEDConfig.byNodeAddr;
ASDU_88_Fmt *pFmt = (ASDU_88_Fmt *)(m_IEC103Data.m_bySend + sizeof(LPDU_Vol_Head));
pFmt->head.type = 88;
pFmt->head.vsq.vsq = 0x81;
pFmt->head.cot = 0x02;
pFmt->head.addr = byAddr;//
pFmt->head.fun = 1;
pFmt->head.inf = 0;
pFmt->qcc.frz = 0;
pFmt->qcc.rqt = 5;
pFmt->rii = m_IEC103Data.m_bySin ++;
m_IEC103Data.m_wSendNum = sizeof(ASDU_88_Fmt);
PackLPDU(byNodeID, SendCon_code);
}
//asdu7
void CIEC103_XUJIPtl::Pack_Asdu_7(BYTE byNodeID)
{
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[byNodeID];
BYTE byAddr = 0;
if(m_IEC103PtlPara.bCommAddr)
byAddr = m_IEC103PtlPara.byCKCPUAddr;
else
byAddr = pDevRun->pDevData->m_IEDConfig.byNodeAddr;
ASDU_7_Fmt *pFmt = (ASDU_7_Fmt *)(m_IEC103Data.m_bySend + sizeof(LPDU_Vol_Head));
pFmt->head.type = 7;
pFmt->head.vsq.vsq = 0x81;
pFmt->head.cot = 9;
pFmt->head.addr = byAddr;
pFmt->head.fun = 0xff;
pFmt->head.inf = 0;
pFmt->scn = m_IEC103Data.m_bySin ++;
m_IEC103Data.m_wSendNum = sizeof(ASDU_7_Fmt);
PackLPDU(byNodeID, SendCon_code);
}
//任务组帧
BOOL CIEC103_XUJIPtl::PackTask(void)
{
TASK *pTask = NULL;
pTask = m_pCH->GetTask();
// 检索通道命令
if (!pTask)
return FALSE;
// 时间校准命令
if (taskAdjustTime == pTask->eTaskType)
{
return FALSE;
/* m_bAdjustTime = true;
return SendAdjustTime103(pTask);
*/ }
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[pTask->byDestNodeID];
if(!pDevRun)
return FALSE;
if (tsNull == pTask->eStatus)
return FALSE;
//判断是否任务队列已经冻结,如果没有冻结认为是新任务,则清数据区
// 任务检测:数据区、设备描述区、系统描述区
// if(!m_pCH->m_pTaskQue->IsLock())
{
memset(&m_IEC103Data.m_task103, 0, sizeof(m_IEC103Data.m_task103));
// 记录规约运行号
m_IEC103Data.m_task103.wStep = 0;
m_IEC103Data.m_task103.task = *pTask;
}
BOOL bRtn = FALSE;
//在下列任务类型中选择需要冻结得任务类型,然后调用冻结函数冻结任务队列
//在解帧函数中,调用解除任务队列冻结函数
if (!PackLinkCmm(pTask->byDestNodeID))
{
switch(pTask->eTaskType)
{
// 任务类型
case taskCmdYkSelect: // 遥控选择
case taskCmdYkExecute: // 遥控执行
case taskCmdYkCancel: // 遥控取消
{
bRtn = PackYaoKong(pTask, pDevRun);
// if(bRtn)
// m_pCH->m_pTaskQue->LockTask();
}
break;
case taskAskBhYc: //保护相关:模拟量、定值、复归
{// 召唤保护模拟量
bRtn = PackCallProtMea(pTask, pDevRun);
// if(bRtn)
// m_pCH->m_pTaskQue->LockTask();
}
break;
case taskAskBhdz:
{// 召唤保护定值
bRtn = PackCallProtSetting(pTask, pDevRun);
// if(bRtn)
// m_pCH->m_pTaskQue->LockTask();
}
break;
case taskCmdModifyBhdz:
{// 修改保护定值
bRtn = PackModifyProtSetting(pTask, pDevRun);
// if(bRtn)
// m_pCH->m_pTaskQue->LockTask();
}
break;
case taskCmdEnableBhdz:
{// 确认保护定值
bRtn = PackEnableProtSetting(pTask, pDevRun);
// if(bRtn)
// m_pCH->m_pTaskQue->LockTask();
}
break;
case taskCmdCancelBhdz:
{// 取消修改保护定值
bRtn = PackCancelProtSetting(pTask, pDevRun);
// if(bRtn)
// m_pCH->m_pTaskQue->LockTask();
}
break;
case taskCmdSetBhdzGroup:
{// 设置保护定值组
bRtn = PackModifyProtSettingGroup(pTask, pDevRun);
// if(bRtn)
// m_pCH->m_pTaskQue->LockTask();
}
break;
case taskCmdEnableBhdzGroup:
{// 确认设置的保护定值组
bRtn = PackEnableProtSettingGroup(pTask, pDevRun);
// if(bRtn)
// m_pCH->m_pTaskQue->LockTask();
}
break;
case taskCmdCancelBhDzGroup:
{// 取消修改定值组号
bRtn = PackCancelProtSettingGroup(pTask, pDevRun);
// if(bRtn)
// m_pCH->m_pTaskQue->LockTask();
}
break;
case taskCmdBhReset: // 保护复归
bRtn = PackProtRes(pTask, pDevRun);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -