📄 protocol101.cpp
字号:
// Protocol101.cpp: implementation of the CProtocol101 class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RTUSim.h"
#include "Protocol101.h"
#include "SOERec.h"
#include "FaultRec.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/*附:
101规约报文格式:(不同厂家对101规约中的具体定义格式不同,要针对具体的问题
来看,对不同厂家的报文格式进行分析)
读CLASS1(读遥信) ->10 4a 01 4b 16
<-68H+L+L+68H+C(88 以数据响应请求帧)+地址+类型标识(01)
+限定词(SQ=1)+传送原因(05)+公共地址+信息体地址(0x0001)
+数据+CS+16H
读CLASS2(读遥测) ->10 4b 01 4c 16
(无SOE)<-68H+L+L+68H+C(a8)+地址+类型标识21+限定词(SQ=0)+传送原因05
+公共地址+信息体地址(从0x0701开始)+数据+CS+16H
(有SOE)<-68H+L+L+68H+C(a8)+地址+类型标识17+限定词(SQ=0)+传送原因03
+公共地址+信息体地址(0x0801开始)+数据+CS+16H
读电度量 ->68 09 09 68 53 01 65 01 06 01 00 00 41 02 16
<-69 09 09 68 80 01 0f 01 25 01 01 0c 01 00 00 13 41 19 16
//遥控合选择
>-68 09 09 68 53 01 2e 01 06 01 01 0b 82 18 16
<-68 09 09 68 80 01 2e 01 07 01 01 0b 82 3a 16
//遥控合执行
>-68 09 09 68 53 01 2e 01 06 01 01 0b 02 98 16
<-68 09 09 68 80 01 2e 01 07 01 01 0b 02 ba 16
//遥控分选择
>-68 09 09 68 53 01 2e 01 06 01 01 0b 81 17 16
<-68 09 09 68 80 01 2e 01 07 01 01 0b 81 39 16
//遥控分执行
>-68 09 09 68 53 01 2e 01 06 01 01 0b 01 97 16
<-68 09 09 68 80 01 2e 01 07 01 01 0b 01 b9 16
//
*/
CProtocol101::CProtocol101()
{
m_nOrderType = UNDEFINE_ORDER;
//m_bSwitchState = FALSE;
//m_bFault = FALSE;
m_bOpenSelect = FALSE;
m_bCloseSelect = FALSE;
}
CProtocol101::~CProtocol101()
{
}
void CProtocol101::Explain()
{
if (!ExplainInData(m_baInBuffer))
{
return;
};
if (m_nOrderType != UNDEFINE_ORDER)
{
Respond(m_baOutBuffer) ;
SendRespons();
return;
}
else
return;
}
BOOL CProtocol101::ExplainInData(CByteArray& bReceive)
{
BYTE CSByte = 0x00;
BYTE OrderByte = 0x00;
BYTE State = 0x00;
int Head = 0;//Head是以0开头的.
if(bReceive.GetSize()<5)//判断是否可能含有一个完整的命令
return FALSE;
for( Head = 0; !((bReceive[Head] == 0x10)||(bReceive[Head] == 0x68)); )//判断是否含有命令头0x10或0x68
{
Head++;
if(Head >= bReceive.GetSize())
{
bReceive.RemoveAll();
return FALSE;
}
}
bReceive.RemoveAt(0,Head);
if(bReceive[0] == 0x10)
{
if(bReceive.GetSize() < 5)//判断从0x10开始是否可能含有一个完整的命令
return FALSE;
if((BYTE)m_wAddr != bReceive[2])//判断所收报文目的地址是否为本FTU地址
{
bReceive.RemoveAt(0,5);
return FALSE;
}
CSByte = bReceive[1]+bReceive[2];
if(CSByte != bReceive[3])//判断校验码
{ //校验码不对时如何清空要看实际的情况,待定
bReceive.RemoveAt(0,5);
return FALSE;
}
OrderByte = bReceive[1]&0x0F;//分析命令类型
switch(OrderByte)
{
case 0x00:
m_nOrderType = LINK_RESET;
break;
case 0x09:
m_nOrderType = REQ_LINK;
break;
case 0x0a:
m_nOrderType = READ_CLASS1;
break;
case 0x0b:
m_nOrderType = READ_CLASS2;
break;
case 0x0c:
m_nOrderType = READ_FAULT_DATA;
break;
default:
m_nOrderType = UNDEFINE_ORDER;
}
bReceive.RemoveAt(0,5);
}
else
if(bReceive[0] == 0x68)
{
if(bReceive.GetSize() < 6)//判断从0x68开始是否可能含有一个完整的命令
return FALSE; //以0x68开始的报文至少有6个字节.
if(bReceive.GetSize() < (bReceive[1]+6))//判断是否含有一个完整的命令
return FALSE;
if((BYTE)m_wAddr != bReceive[5])//判断所收报文目的地址是否为本FTU地址
{
bReceive.RemoveAt(0,(bReceive[1]+6));
return FALSE;
}
for(int i=4; i < (bReceive[1]+4);i++)
CSByte += bReceive[i];
if( CSByte != bReceive[bReceive[1]+4])//判断校验码
{
bReceive.RemoveAt(0,(bReceive[1]+6));
return FALSE;
}
m_chTypeMark = bReceive[6];
if(m_chTypeMark == 0x2e)
{
State = bReceive[8];
OrderByte = bReceive[12];
if((State == 0x06)&&(OrderByte == 0x82))
m_nOrderType = CLOSE_SELECT;
if((State == 0x06)&&(OrderByte == 0x02))
m_nOrderType = CLOSE_EXECUTE;
if((State == 0x06)&&(OrderByte == 0x81))
m_nOrderType = OPEN_SELECT;
if((State == 0x06)&&(OrderByte == 0x01))
m_nOrderType = OPEN_EXECUTE;
if((State == 0x08)&&(OrderByte == 0x02))
m_nOrderType = CANCEL_CLOSE_SELECT;
if((State == 0x08)&&(OrderByte == 0x01))
m_nOrderType = CANCEL_OPEN_SELECT;
/*if(m_bType&&m_bControl)
m_nOrderType = CLOSE_EXECUTE;
if((!m_bType)&&m_bControl)
m_nOrderType = CLOSE_SELECT;
if(m_bType&&(!m_bControl))
m_nOrderType = OPEN_EXECUTE;
if((!m_bType)&&(!m_bControl))
m_nOrderType = OPEN_SELECT; */
}
else
if (m_chTypeMark == 0x65)
{
if(bReceive[12] == 0x41)
m_nOrderType = READ_COUNT;
else
m_nOrderType = UNDEFINE_ORDER;
}
else
if (m_chTypeMark == 0x67)
{
if (bReceive[8] == 0x06)
{
m_nOrderType = SYN_TIME;
for(int n=0;n<7;n++)
{
m_bTimeData[n] = bReceive[12+n];
}
}
else
m_nOrderType = UNDEFINE_ORDER;
}
else
if (m_chTypeMark == 0x69)
{
if(bReceive[8] == 0x06)
m_nOrderType = RTU_RESET;
else
m_nOrderType = UNDEFINE_ORDER;
}
else
m_nOrderType = UNDEFINE_ORDER;
bReceive.RemoveAt(0,(bReceive[1]+6));
}
return TRUE;
}
int CProtocol101::Respond(CByteArray& bSend)
{
switch(m_nOrderType)
{
case RTU_RESET:
RespondRTUReset(bSend);
break;
case LINK_RESET:
RespondLinkReset(bSend);
break;
case SYN_TIME:
RespondSynTime(bSend);
break;
case READ_CLASS1:
RespondReadClass1(bSend);
break;
case READ_CLASS2:
RespondReadClass2(bSend);
break;
case OPEN_SELECT:
RespondOpenSelect(bSend);
break;
case OPEN_EXECUTE:
RespondOpenExecute(bSend);
break;
case CLOSE_SELECT:
TRACE("close select");
RespondCloseSelect(bSend);
break;
case CLOSE_EXECUTE:
RespondCloseExecute(bSend);
break;
case READ_COUNT:
RespondReadCount(bSend);
break;
case CANCEL_OPEN_SELECT:
RespondCancelOpenSelect(bSend);
break;
case CANCEL_CLOSE_SELECT:
RespondCancelCloseSelect(bSend);
break;
case READ_FAULT_DATA:
RespondReadFaultData(bSend);
default:
;
}
return m_nOrderType;
}
void CProtocol101::RespondRTUReset(CByteArray &bSend)
{
BYTE CSByte = 0;
BYTE bMessageLen;
bMessageLen = 15;
bSend.SetSize(bMessageLen);
bSend[0] = 0x68;
bSend[1] = bSend[2] = 0x09;
bSend[3] = 0x68;
bSend[4] = 0x80;
bSend[5] = bSend[9] = BYTE(m_wAddr);
bSend[6] = 0x69;
bSend[7] = 0x01;
bSend[8] = 0x07;
bSend[10] = 0x00;
bSend[11] = 0x00;
bSend[12] = 0x01;
for(int i=4;i<13;i++)
CSByte += bSend[i];
bSend[13] = CSByte;
bSend[14] = 0x16;
}
void CProtocol101::RespondLinkReset(CByteArray& bSend)
{
BYTE CSByte = 0;
BYTE bMessageLen;
bMessageLen = 5;
bSend.SetSize(bMessageLen);
bSend[0] = 0x10;
bSend[1] = 0x80;
bSend[2] = BYTE(m_wAddr);
CSByte = bSend[1]+bSend[2];
bSend[3] = CSByte;
bSend[4] = 0x16;
}
void CProtocol101::RespondSynTime(CByteArray &bSend)
{
BYTE CSByte = 0;
BYTE bMessageLen;
bMessageLen = 21;
bSend.SetSize(bMessageLen);
bSend[0] = 0x68;
bSend[1] = bSend[2] = 0x15;
bSend[3] = 0x68;
bSend[4] = 0x80;//C
bSend[5] = bSend[9] = BYTE(m_wAddr);
bSend[6] = 0x67; //类型标识
bSend[7] = 0x01;//信息体个数
bSend[8] = 0x07;//传送原因
bSend[10] = 0x00;
bSend[11] = 0x00;
for(int i=0;i<7;i++)
bSend[12+i] = m_bTimeData[i];
for(int n=4;n<19;n++)
CSByte += bSend[n];
bSend[19] = CSByte;
bSend[20] = 0x16;
}
void CProtocol101::RespondReadClass1(CByteArray& bSend)
{
BYTE CSBtyte= 0;
BYTE bMessageLen;
bMessageLen = 12 + 3*(m_baDigital.GetSize());
bSend.SetSize(bMessageLen);
bSend[0] = 0x68;
bSend[1] = bSend[2] = bMessageLen - 6;
bSend[3] = 0x68;
bSend[4] = 0xa8;//C
bSend[5] = bSend[9] = BYTE(m_wAddr);
bSend[6] = 0x01; //类型标识
bSend[7] = BYTE(m_baDigital.GetSize());//信息体个数
bSend[8] = 0x05;//传送原因
for(int i = 0,n = 0;i<m_baDigital.GetSize(); i++)//
{
bSend[10+n] = BYTE(0xa1+i);
bSend[11+n] = 0x0c;
bSend[12+i] = m_baDigital[i];
n += 3;
}
for(i = 4;i<bMessageLen-2;i++)
{
CSBtyte += bSend[i];
}
bSend[bMessageLen-2] = CSBtyte;
bSend[bMessageLen-1] = 0x16;
}
void CProtocol101::RespondReadClass2(CByteArray& bSend)
{
DWORD YCData = 0;
BYTE *pYCByte = 0;
BYTE bCSByte = 0x00;
BYTE bMessageLen = 0x00;
if (m_paSOE.GetSize()>0) //是否发生故障
{
CSOERec* SOEData;
BYTE FaultType;
WORD Milliseconds;
BYTE Minutes;
BYTE *pSOETime;
bMessageLen = (m_paSOE.GetSize())*8+12;
bSend.SetSize(bMessageLen);
bSend[0] = 0x68;
bSend[1] = bSend[2] = bMessageLen - 6;
bSend[3] = 0x68;
bSend[4] = 0xa8;
bSend[5] = bSend[9] = BYTE(m_wAddr);
bSend[6] = 0x11;//类型标识
bSend[7] = BYTE(m_paSOE.GetSize());//信息体数目
bSend[8] = 0x03;//传送原因
for(int i = 0,n = 0;m_paSOE.GetSize()>0;i++)
{
SOEData = (CSOERec*)(m_paSOE.GetAt(0));
FaultType = (SOEData->m_uDigitalNO)*2+1;
if (SOEData->m_bOpened) //如果状态变为1,则FaultType加1,
{ //如果变为0,FaultType不加,详见SOE表
FaultType += 1; //即:,FALSE状态的在前,TURE状态的在后
} //因为每个遥信号对应着开/合两种状态.
bSend[10+n] = FaultType;
bSend[11+n] = 0x08;
bSend[12+n] = 0x00;
Milliseconds = (SOEData->m_stTime.wSecond)*1000 + SOEData->m_stTime.wMilliseconds;
pSOETime = (unsigned char *)(&Milliseconds);
bSend[13+n] = bSend[15+n] = pSOETime[0];
bSend[14+n] = bSend[16+n] = pSOETime[1];
Minutes = (BYTE)SOEData->m_stTime.wMinute;
bSend[17+n] = Minutes;
n += 8;
m_paSOE.RemoveAt(0);
delete SOEData;
}
for( i=4;i<bMessageLen-2;i++)
{
bCSByte += bSend[i];
}
bSend[bMessageLen-2] = bCSByte;
bSend[bMessageLen-1] = 0x16;
m_paSOE.RemoveAll();
}
else//无状态变位
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -