📄 dnp3dll.cpp
字号:
#include "msystem.h"#include "Dnp3dll.h"void CDNP3DLL::BuildCID(BYTE& byCID,BYTE byFC,bool bPRM,bool bFCV){ byCID = byFC; if (m_bDIR) byCID |= 0x80; if (bPRM) { byCID |= 0x40; if (bFCV) { byCID |= 0x10; if (m_bFCB) byCID |= 0x20; m_bFCB = !m_bFCB; } } else { if (m_bDataFlowCtrl) byCID |= 0x10; }}void CDNP3DLL::Resp(BYTE byFC){ CFrameNode FNSend; FNSend.m_wSAddr = m_wSrcAddr; FNSend.m_wDAddr = m_wDesAddr; BuildCID(FNSend.m_byCID,byFC,false,false); SetupFrame(&FNSend); CDataNode dn; FrameToBuffer(dn); WriteToPL(dn.m_pbyData,dn.m_wSize);}void CDNP3DLL::ExpResp(){ CFrameNode* pFNResp; if (m_queResp.Get(pFNResp,1000)) { if (pFNResp->m_byCID & 0x10) // DFC m_nStatus = 0x31; else { BYTE byFC = pFNResp->m_byCID & 0xf; switch (byFC) { case 0: case 11: m_nStatus = 0; break; case 1: m_nStatus = 0x21; break; case 14: case 15: default: m_nStatus = 0x11; break; } } delete pFNResp; } else m_nStatus = 0x41;}int CDNP3DLL::GetStatus(){ switch (m_nStatus) { case 0: break; case 0x21://test peer link layer status TestPLLS(); break; case 0x31://query peer link layer status QueryPLLS(); break; case 0x11://Reset peer link layer default: //ready for write, Get data From queue// ResetPLL(); m_nStatus = 0; break; } return m_nStatus & 0xf;}void CDNP3DLL::QueryPLLS(){ CFrameNode FNSend; FNSend.m_wSAddr = m_wSrcAddr; FNSend.m_wDAddr = m_wDesAddr; BuildCID(FNSend.m_byCID,9,true,false); SetupFrame(&FNSend); CDataNode dn; FrameToBuffer(dn); WriteToPL(dn.m_pbyData,dn.m_wSize); ExpResp();}void CDNP3DLL::TestPLLS(){}void CDNP3DLL::ResetPLL(){ CFrameNode FNSend; FNSend.m_wSAddr = m_wSrcAddr; FNSend.m_wDAddr = m_wDesAddr; BuildCID(FNSend.m_byCID,0,true,false); SetupFrame(&FNSend); CDataNode dn; FrameToBuffer(dn); WriteToPL(dn.m_pbyData,dn.m_wSize); ExpResp();}bool CDNP3DLL::WriteToPL(BYTE* pBuf,WORD wSize,DWORD dwTimeout){ bool bRet = false; pthread_mutex_lock(&m_csWrite); { m_PhyService.Write(pBuf,wSize); usleep(10000);/*if (wSize >= 18){ cout << endl <<"Resp:"; for (WORD w=0; w<wSize; w++) { char c[16]; sprintf(c," %02x" ,pBuf[w]); cout << c; } cout <<endl;}*/ bRet = true; } pthread_mutex_unlock(&m_csWrite); return bRet;}void* thrdRead(void* pVoid){ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); CDNP3DLL *pDL = (CDNP3DLL *)pVoid; sleep(5); while (1) { pDL->ReadFrmPL(); } return 0;}CDNP3DLL::CDNP3DLL(CSerialPortDef* pChannel,bool bDIR,WORD wSrcAddr,WORD wDesAddr) : CDLService(pChannel){ m_bDIR = bDIR; pthread_mutex_init(&m_csWrite,NULL);// PTHREAD_MUTEX_INITIALIZER) m_wSrcAddr = wSrcAddr; m_wDesAddr = wDesAddr; m_pFrame = new CDNP3Frame; m_byMaxRepeatTimes = 2; m_nStatus = 0x11; m_bPeerStatus = false; m_bDataFlowCtrl = false;}bool CDNP3DLL::Init(){ bool bRet = false; if (m_PhyService.Status() == 0) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); if (pthread_create(&m_pThrdReadFrmPL,&attr,thrdRead,(void *)this) == 0) bRet = true; pthread_attr_destroy(&attr); } return bRet;}CDNP3DLL::~CDNP3DLL(){ if (m_pThrdReadFrmPL) { cout << "CDNP3DLL: " << m_pThrdReadFrmPL << endl; pthread_cancel(m_pThrdReadFrmPL); } if (m_pFrame) delete m_pFrame; pthread_mutex_destroy(&m_csWrite);}void CDNP3DLL::ReadFrmPL(){ CFrameNode FNRecv; int nIndications = -1; if (m_PhyService.Status() == 0) { nIndications = 0; CDQue* pDQueRecv = m_PhyService.GetRecvQueue(); CDNP3Frame frmInput; if (frmInput.BufferToFrame(pDQueRecv)) { frmInput.FrameToBuf(FNRecv); m_wDesAddr = FNRecv.m_wSAddr; if ((FNRecv.m_wDAddr == m_wSrcAddr) || (FNRecv.m_wDAddr == 0xffff)) nIndications = 1; } } if (nIndications == 1) { BYTE byFC = FNRecv.m_byCID & 0xf; bool bPRM = (FNRecv.m_byCID & 0x40)?true:false;// bool bDIR = (FNRecv.m_byCID & 0x80)?true:false;// assert(bDIR != m_bDIR) if (bPRM) //primary { bool bRefuse = false; if (FNRecv.m_byCID & 0x10) //FCV { if (m_bPeerStatus == false) bRefuse = true; else if (((FNRecv.m_byCID & 0x20)?true:false) == m_bPeerFCB) m_bPeerFCB = !m_bPeerFCB; else //拒绝报文 bRefuse = true; } if (bRefuse == false) { switch (byFC) { case 0://reset link layer m_bPeerFCB = true; m_bPeerStatus = true; Resp(0); //ack break; case 1://reset user process ??? break; case 2://test Resp(0); //ack break; case 3://Send/confirm Resp(0); //ack case 4://Send/no confirm { CFrameNode* pfn = new CFrameNode; *pfn = FNRecv; m_queIND.Add(pfn);// append tsdu to queIND } break; case 9://查询链路状态 //rep linklayer status Resp(m_bPeerStatus ? 11 : 15); //ack break; default: break; } } } else //FRM == 0: { CFrameNode* pfn = new CFrameNode; *pfn = FNRecv; m_queResp.Add(pfn); } }}int CDNP3DLL::REQ(BYTE byService,CFrameNode *pFNSend,BYTE byPriority/*0:H;1:L*/,bool bRetry){ int nConfirm = 4; //等待物理层可用 if (m_PhyService.Status() == 0) { BYTE b; for (b=0;b<m_byMaxRepeatTimes;b++) { switch (byService) { case 0: //send-confirm; Request-Respond if (GetStatus() == 0) { pFNSend->m_wSAddr = m_wSrcAddr; pFNSend->m_wDAddr = m_wDesAddr; BuildCID(pFNSend->m_byCID,3,true,true); SetupFrame(pFNSend); CDataNode dn; FrameToBuffer(dn); WriteToPL(dn.m_pbyData,dn.m_wSize); ExpResp(); if (m_nStatus == 0)//ack nConfirm = 0; else if (m_nStatus == 0x21)//nack nConfirm = 2; else if (m_nStatus == 0x41)//no resp nConfirm = 3; else if (m_nStatus == 0x11)//link layer service is not working or no use link layer service nConfirm = 1; } break;/* AddIOStream(1,dn.m_pbyData,dn.m_wSize); if (BufferToFrame(pDQueRecv)) { AddIOStream(2,m_pFrame->m_pbyInBuf,m_pFrame->m_wInLength); m_pFrame->FrameToBuf(FNRecv); nConfirm = 1; }*/ case 1: //send-no-reply if (GetStatus() == 0) { pFNSend->m_wSAddr = m_wSrcAddr; pFNSend->m_wDAddr = m_wDesAddr; BuildCID(pFNSend->m_byCID,4,true,false); SetupFrame(pFNSend); CDataNode dn; FrameToBuffer(dn); CDQue* pDQueRecv = m_PhyService.GetRecvQueue(); pDQueRecv->RemoveAll(); WriteToPL(dn.m_pbyData,dn.m_wSize);// m_PhyService.Write(dn.m_pbyData,dn.m_wSize);// AddIOStream(1,dn.m_pbyData,dn.m_wSize); nConfirm = 0; } break; case 2: //send-confirm ,cancel current secondary frames for half duplex break; case 3: //send-no-reply ,cancel current secondary frames for half duplex break; case 4: //return link status, return successful if the data link is not busy nConfirm = GetStatus(); break; default: break; } if ((nConfirm == 0) || (bRetry == false)) break; } } return nConfirm;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -