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

📄 protocolcdt91.cpp

📁 能够模拟电表的645协议
💻 CPP
字号:
// ProtocolCDT91.cpp: implementation of the CProtocolCDT91 class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "RTUSim.h"
#include "ProtocolCDT91.h"
#include "ProtocalBase.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
extern BOOL OnOff;

BYTE bch_table[256] = {
				0x00,0x07,0x0E,0x09,0x1C,0x1B,0x12,0x15,
				0x38,0x3F,0x36,0x31,0x24,0x23,0x2A,0x2D,
				0x70,0x77,0x7E,0x79,0x6C,0x6B,0x62,0x65,
				0x48,0x4F,0x46,0x41,0x54,0x53,0x5A,0x5D,
				0xE0,0xE7,0xEE,0xE9,0xFC,0xFB,0xF2,0xF5,
				0xD8,0xDF,0xD6,0xD1,0xC4,0xC3,0xCA,0xCD,
				0x90,0x97,0x9E,0x99,0x8C,0x8B,0x82,0x85,
				0xA8,0xAF,0xA6,0xA1,0xB4,0xB3,0xBA,0xBD,
				0xC7,0xC0,0xC9,0xCE,0xDB,0xDC,0xD5,0xD2,
				0xFF,0xF8,0xF1,0xF6,0xE3,0xE4,0xED,0xEA,
				0xB7,0xB0,0xB9,0xBE,0xAB,0xAC,0xA5,0xA2,
				0x8F,0x88,0x81,0x86,0x93,0x94,0x9D,0x9A,
				0x27,0x20,0x29,0x2E,0x3B,0x3C,0x35,0x32,
				0x1F,0x18,0x11,0x16,0x03,0x04,0x0D,0x0A,
				0x57,0x50,0x59,0x5E,0x4B,0x4C,0x45,0x42,
				0x6F,0x68,0x61,0x66,0x73,0x74,0x7D,0x7A,
				0x89,0x8E,0x87,0x80,0x95,0x92,0x9B,0x9C,
				0xB1,0xB6,0xBF,0xB8,0xAD,0xAA,0xA3,0xA4,
				0xF9,0xFE,0xF7,0xF0,0xE5,0xE2,0xEB,0xEC,
				0xC1,0xC6,0xCF,0xC8,0xDD,0xDA,0xD3,0xD4,
				0x69,0x6E,0x67,0x60,0x75,0x72,0x7B,0x7C,
				0x51,0x56,0x5F,0x58,0x4D,0x4A,0x43,0x44,
				0x19,0x1E,0x17,0x10,0x05,0x02,0x0B,0x0C,
				0x21,0x26,0x2F,0x28,0x3D,0x3A,0x33,0x34,
				0x4E,0x49,0x40,0x47,0x52,0x55,0x5C,0x5B,
				0x76,0x71,0x78,0x7F,0x6A,0x6D,0x64,0x63,
				0x3E,0x39,0x30,0x37,0x22,0x25,0x2C,0x2B,
				0x06,0x01,0x08,0x0F,0x1A,0x1D,0x14,0x13,
				0xAE,0xA9,0xA0,0xA7,0xB2,0xB5,0xBC,0xBB,
				0x96,0x91,0x98,0x9F,0x8A,0x8D,0x84,0x83,
				0xDE,0xD9,0xD0,0xD7,0xC2,0xC5,0xCC,0xCB,
				0xE6,0xE1,0xE8,0xEF,0xFA,0xFD,0xF4,0xF3
				}; 

CProtocolCDT91::CProtocolCDT91()
{
	m_KgState=FALSE;
	m_SendNo=0;
	m_bFlag=FALSE;
} 

CProtocolCDT91::~CProtocolCDT91()
{

}

void CProtocolCDT91::Explain()
{
	//查看有无SOE、校时信息,无则发送全数据
	while(m_baInBuffer.GetSize()>10)
	{
		if(m_baInBuffer[0] == 0xeb && m_baInBuffer[1] == 0x90&&m_baInBuffer[2] == 0xeb && m_baInBuffer[3] == 0x90&&m_baInBuffer[4] == 0xeb && m_baInBuffer[5] == 0x90)
		{
			if(m_baInBuffer[6] == 0x71 && m_baInBuffer[10] == (BYTE)m_wAddr)
			{
				switch(m_baInBuffer[7])
				{
				case 0x7a://校时
					timeSynch();
					m_baInBuffer.RemoveAll();
					break;
				case 0x61://遥控选择
					PreOperate();
					m_baInBuffer.RemoveAll();
					break;
				case 0xc2://遥控执行
					Oper();
					m_baInBuffer.RemoveAll();
					break;
				case 0xb3://遥控撤销
					CancelOper();
					m_baInBuffer.RemoveAll();
					break;
				case 0x3d://复归命令
					break;
				default:
					break;
				}
			}
		}
		else
		{
			if(m_baInBuffer.GetSize() > 1)
				m_baInBuffer.RemoveAt(0,1);
		}
	}
	//判断是否有遥信变位
	if(m_baDigital.GetSize() <= 0)
		return;
	if(m_KgState != (BYTE)(m_baDigital[0]&0x01))
	{
		m_KgState=m_baDigital[0]&0x01;
		SOE((BYTE)m_wAddr);
		SendRespons();
		Sleep(100);
	}

	m_baOutBuffer.RemoveAll();
	DataSend((BYTE)m_wAddr);
}

//CRC解调
BOOL CProtocolCDT91::check_revcode(BYTE *array)
{
	BYTE temp;
	temp = 0x00 ;
	for( int i = 0 ;i < 5; i++ )
    {
    	temp = temp ^ array[i] ;
        temp = bch_table[ temp];
	}
	temp = temp^0xff ;
  
	if(  temp  == array[5] )
        return TRUE ;
    else	
		return FALSE;
}

//CRC调制
BOOL CProtocolCDT91::check_sendcode(int bufno)
{
	BYTE temp;
	temp = 0x00 ;
	for( int m = 0 ;m < 5; m++ )
    {
    	temp = temp ^ m_baOutBuffer[bufno+m] ;
        temp = bch_table[temp];
	}
	temp = temp^0xff ;
    //m_baOutBuffer[bufno+5]=(char)temp;
	m_baOutBuffer.Add(temp);
	return TRUE;
}

//更新计算机时间
void CProtocolCDT91::timeSynch()
{	
	BYTE array[6];
	if(m_baInBuffer.GetSize() < 18)	
		return;
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<6;j++)
		{
			array[j]=m_baInBuffer[i*6+j+6];
		}
		if(!check_revcode(array))
			return;
	}
	
	SYSTEMTIME tm;
	GetLocalTime(&tm);
 	LPSYSTEMTIME lpSystemTime =&tm;

	lpSystemTime->wMonth=(WORD)m_baInBuffer[21];
	lpSystemTime->wDay=(WORD)m_baInBuffer[20];
	lpSystemTime->wHour=(WORD)m_baInBuffer[19];
	lpSystemTime->wMinute=(WORD)m_baInBuffer[16];
	lpSystemTime->wSecond=(WORD)m_baInBuffer[15];
	lpSystemTime->wMilliseconds=(WORD)m_baInBuffer[13];
	//更新计算机时间
	SetLocalTime(lpSystemTime);
}

//遥控返校
BOOL CProtocolCDT91::OperBack(BYTE rtuAddress,BOOL state)
{
	Data_ArrayS();
	Data_ArrayC(rtuAddress,0x7a,2);
	for(int i=0;i<3;i++)
	{
		m_baOutBuffer.Add(0xe1);
		if(!state)
			m_baOutBuffer.Add(0xff);
		else
			m_baOutBuffer.Add(m_baInBuffer[13+i*6]);
		m_baOutBuffer.Add(m_baInBuffer[14+i*6]);
		if(!state)
			m_baOutBuffer.Add(0xff);
		else
			m_baOutBuffer.Add(m_baInBuffer[15+i*6]);
		m_baOutBuffer.Add(m_baInBuffer[16+i*6]);
		check_sendcode(12+6*i);
	}
	SendRespons();
	return TRUE;
}

//置开关位置
BOOL CProtocolCDT91::Oper()
{
	BYTE array[6];
	if(!m_bFlag)
		return FALSE;
	m_bFlag=!m_bFlag;
	if(m_baInBuffer.GetSize() < 30)	
	{
		TRACE("遥控执行字节长度:%d\n",m_baInBuffer.GetSize());
		return	FALSE;
	}
	for(int i=0;i<4;i++)
	{
		for(int j=0;j<6;j++)
		{
			array[j]=m_baInBuffer[i*6+j+6];
		}
		
		if(!check_revcode(array))
			return FALSE;
	}
	if(m_baInBuffer[10] != m_wAddr)
		return FALSE;
	
	m_KgState=!m_KgState;
	OnOff=m_KgState;//通知界面

	return TRUE;
}

//置SOE
BOOL CProtocolCDT91::SOE(BYTE rtuAddress)
{
	int nCount=0;
	SYSTEMTIME tm;
	GetLocalTime(&tm);
 	LPSYSTEMTIME lpSystemTime =&tm;

	Data_ArrayS();
	Data_ArrayC(rtuAddress,0x26,5);

	for(int i=0;i<6;i+=2)
	{
		nCount=12+i*6;
		m_baOutBuffer.Add(0x80);
		m_baOutBuffer.Add((BYTE)lpSystemTime->wMilliseconds);
		m_baOutBuffer.Add((BYTE)lpSystemTime->wMilliseconds>>8);
		m_baOutBuffer.Add((BYTE)lpSystemTime->wSecond);
		m_baOutBuffer.Add((BYTE)lpSystemTime->wMinute);
		check_sendcode(nCount);
		m_baOutBuffer.Add(0x81);	
		m_baOutBuffer.Add((BYTE)lpSystemTime->wHour);
		m_baOutBuffer.Add((BYTE)lpSystemTime->wDay);
		m_baOutBuffer.Add(0x01);
		m_baOutBuffer.Add(m_KgState<<7);
		check_sendcode(nCount+6);
	}

	return TRUE;
}

//置信息字
void CProtocolCDT91::Data_ArrayS()
{	
	for(int i=0;i<6;i=i+2)
	{
		m_baOutBuffer.Add(0xeb);
		m_baOutBuffer.Add(0x90);
	}
}

//置控制字
void CProtocolCDT91::Data_ArrayC(BYTE rtuAddress,BYTE ctrl,BYTE infoNum)
{
	m_baOutBuffer.Add(0x71);
	m_baOutBuffer.Add(ctrl);
	m_baOutBuffer.Add(infoNum+1);
	m_baOutBuffer.Add(rtuAddress);		//源地址	
	m_baOutBuffer.Add(0x00);			//目标地址
	check_sendcode(6);					//校验码
}

void CProtocolCDT91::DataSend(BYTE rtuAddr)
{
	Data_ArrayS();
	switch(m_SendNo)
	{
	case 0:
	case 1:	
	case 2:
	case 3:	
	case 4:
	case 6:
	case 8:
		if(m_waAnalog.GetSize()%2 == 0)
			Data_ArrayC(rtuAddr,0x61,m_waAnalog.GetSize()/2-1);
		else
			Data_ArrayC(rtuAddr,0x61,m_waAnalog.GetSize()/2);
		SendYc();
		break;

	case 5:
	case 9:
		if(m_baDigital.GetSize()%4 == 0)
			Data_ArrayC(rtuAddr,0xf4,m_baDigital.GetSize()/4-1);
		else
			Data_ArrayC(rtuAddr,0xf4,m_baDigital.GetSize()/4);
		SendYx();
		break;

	case 7:
		Data_ArrayC(rtuAddr,0x85,m_dwaCount.GetSize()-1);
		SendDd();
		break;
	default:
		break;
	}
	m_SendNo++;
	if(m_SendNo > 9)
		m_SendNo=0;
	SendRespons();
}

void CProtocolCDT91::SendYx()
{
	int digLen=m_baDigital.GetSize();
	if(digLen < 0 )
		return;
	int yushu=digLen%4;	//取余数
	int shang=digLen/4;	//商

	BYTE funcode=0xf0;

	if(yushu != 0)
		shang +=1;

	for(int i=0;i<shang;i++)
	{
		m_baOutBuffer.Add(funcode);
		if(shang-i != 1)
		{
			m_baOutBuffer.Add(m_baDigital[i*4]);
			m_baOutBuffer.Add(m_baDigital[i*4+1]);
			m_baOutBuffer.Add(m_baDigital[i*4+2]);
			m_baOutBuffer.Add(m_baDigital[i*4+3]);
		}
		else
		{
			for(int j=0;j<yushu;j++)
			{
				m_baOutBuffer.Add(m_baDigital[i*4+j]);
			}
			for(int m=0;m<4-j;m++)
			{
				m_baOutBuffer.Add(0x00);
			}
		}
		check_sendcode(i*6+12);
		funcode++;
		if(funcode > 0xfe)
			break;
	}
}

void CProtocolCDT91::SendYc()
{
	int anaLen=m_waAnalog.GetSize();
	if(anaLen < 0 )
		return;
	int yushu=anaLen%2;	//取余数
	int shang=anaLen/2;	//商
	BYTE funcode=0x00;
	if(yushu != 0)
		shang +=1;
	for(int i=0;i<shang;i++)
	{
		m_baOutBuffer.Add(funcode);
		if(shang-i != 1)
		{
			m_baOutBuffer.Add((BYTE)m_waAnalog[i*2]);
			m_baOutBuffer.Add((BYTE)(m_waAnalog[i*2]>>8));
			m_baOutBuffer.Add((BYTE)m_waAnalog[i*2+1]);
			m_baOutBuffer.Add((BYTE)(m_waAnalog[i*2+1]>>8));
		}
		else
		{
			for(int j=0;j<1;j++)
			{
				m_baOutBuffer.Add((BYTE)m_waAnalog[i*2+2*j]);
				m_baOutBuffer.Add((BYTE)m_waAnalog[i*2+2*j]>>8);
			}
			for(int m=0;m<1;m++)
			{
				m_baOutBuffer.Add(0x00);
				m_baOutBuffer.Add(0x00);
			}
		}
		check_sendcode(i*6+12);
		funcode++;
		if(funcode > 0x7e)
			break;
	}
}
void CProtocolCDT91::SendDd()
{
	int countLen=m_dwaCount.GetSize();
	if(countLen < 0)
		return;
	BYTE funcode=0xa0;

	for(int i=0;i<countLen;i++)
	{
		m_baOutBuffer.Add(funcode);
	
		m_baOutBuffer.Add((BYTE)m_dwaCount[i]);
		m_baOutBuffer.Add((BYTE)m_dwaCount[i]>>8);
		m_baOutBuffer.Add((BYTE)m_dwaCount[i]>>16);
		m_baOutBuffer.Add((BYTE)m_dwaCount[i]>>24);

		check_sendcode(i*6+12);
		funcode++;
		if(funcode > 0xde)
			break;
	}
}
void CProtocolCDT91::PreOperate()
{
	BYTE array[6];
	if(m_baInBuffer.GetSize() < 30)	
		return;
	for(int i=0;i<4;i++)
	{
		for(int j=0;j<6;j++)
		{
			array[j]=m_baInBuffer[i*6+j+6];
		}
		if(!check_revcode(array))
			OperBack(m_baInBuffer[10],FALSE);
	}
	if(m_baInBuffer[10] != m_wAddr)
		return;
//m_KgState	1=合闸 0-分闸
	if((m_baInBuffer[13] == 0xcc)&&(!m_KgState))//合闸
	{
		OperBack(m_baInBuffer[10],TRUE);	
		m_bFlag=TRUE;
	}
	else if((m_baInBuffer[13] == 0x33)&&m_KgState)//分闸
	{
		OperBack(m_baInBuffer[10],TRUE);
		m_bFlag=TRUE;
	}
	else
	{
		OperBack(m_baInBuffer[10],FALSE);
	}
	TRACE("收到遥控选择命令并返回正确!\n");
}

void CProtocolCDT91::CancelOper()
{

}

⌨️ 快捷键说明

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