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

📄 processnzctd.cpp

📁 这是一个变电站的监控程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
///////////////////////////////////////////////////////////////////////
// this ProcessCDT.cpp is added by lqs on 2001-7-22

#include "stdafx.h"
#include "fert2000.h"
#include "process.h"

extern bool bStopFlag;
extern CHANNEL Channels[MAX_CHANNEL_NUM];
extern RTU Rtus[MAX_RTU_NUM];
extern SYSTEMCOUNT SystemCount;
extern EVENT Events;
extern long ProgramStartTime;
extern char YKEchoFlag[MAX_RTU_NUM];
extern BYTE YKEcho[MAX_RTU_NUM][6];
extern BYTE YKReserved[24];
extern unsigned char TBCH0[];   
extern  CFert2000App theApp;

//////////////////////////////////////////////////////////////////////////

BYTE DtoH(BYTE dData)
{
	BYTE Temp=0;
	BYTE tt1,tt2;
	tt1=dData/16;
	tt2=dData%16;
	Temp=tt1*10+tt2;
	return Temp;
}

void NZ_CDT(int i)
{
	BYTE RtuNo=Channels[i].ChRtuNo[0];
	if (!Rtus[RtuNo].Flag) return;
	if (NZ_CDT_Rec(i,RtuNo))
	{
		Rtus[RtuNo].bWorking=TRUE;
		Channels[i].bWorking=true;
		NZ_CDT_Protocol(i,RtuNo);
	}
	else
		Rtus[RtuNo].bWorking=FALSE;
	NZ_CDT_Send(i,RtuNo);
}

bool NZ_CDT_Rec(int i,BYTE RtuNo)
{
	BYTE Temp;
	int SynstrCount = Channels[i].SynstrCount;
	int InLen = MoxaBufIqueue(i);
	if (InLen<6) return false;
	if ((SynstrCount<6) && !(Channels[i].ChStatus & 0x2000))//同步字个数小于6,并且不是第一个信息字
	{
		for (int j=0;j<InLen;j++)//去掉同步字
		{
			MoxaBufRead(i,&Temp,1);
			if(Temp == Rtus[RtuNo].SynWord[SynstrCount+1]) SynstrCount++; 
			else SynstrCount = 0;
			if (SynstrCount==6) break;			
		}
		Channels[i].SynstrCount = SynstrCount;
	}

	InLen=MoxaBufIqueue(i);
	if (SynstrCount==6)
	{
		if (InLen<6) return false;
		MoxaBufRead(i,Channels[i].FileHead,6);//读取控制字
		if (Channels[i].FileHead[5] != CDT_CheckCRC(Channels[i].FileHead))
		{
			Rtus[Channels[i].ChRtuNo[0]].ErrFrameSum += 5;
			Rtus[Channels[i].ChRtuNo[0]].RecFrameSum += 5;
            Channels[i].SynstrCount = 0;
			return false;
		}
		Channels[i].SynstrCount = 0;
		InLen -= 6;
		Channels[i].ChStatus |= 0x2000;
	}

	if (Channels[i].ChStatus & 0x2000)//读取信息字
	{
		int Lenth;
		if(Channels[i].FileHead[0]==0x72 && Channels[i].FileHead[1]==0x40)
			Lenth=6*8;
		else
			Lenth = Channels[i].FileHead[2] * 6;
		if (InLen <= Lenth && Lenth != 0) 
			return false;
		else
		{
			if(Channels[i].FileHead[0]==0x72 && Channels[i].FileHead[1]==0x40)
				Rtus[Channels[i].ChRtuNo[0]].RecFrameSum +=8+1;
            else
			    Rtus[Channels[i].ChRtuNo[0]].RecFrameSum += Channels[i].FileHead[2] + 1;
			for (int j=0;j<6;j++) 
				Rtus[RtuNo].RecBuf[j] = Channels[i].FileHead[j];//保存的数据从控制字开始
			MoxaBufRead(i,&Rtus[RtuNo].RecBuf[6],Lenth);
			Rtus[RtuNo].RecBufPtr=Lenth+6;
			Rtus[RtuNo].RecLen=Lenth+6;
			Rtus[RtuNo].bReceiveCanDisp = TRUE;	
			SynstrCount = 0;
			Channels[i].ChStatus &= 0xdfff;
		}
	}
	else 
		return false;
	return true;
}

void NZ_CDT_Protocol(int i,BYTE RtuNo) 
{
	int NonceInfoWord;
	BYTE* RtuRecBuf=&(Rtus[RtuNo].RecBuf[0]);//保存的数据从控制字开始
	//保证同一个功能码的信息字只处理一次,消除某些误码或者遥信变位连送三遍的情况下出现的不一致现象
	bool bInfoWordIsHandle[255];
	for (int kk = 0;kk < 255;kk++)
		bInfoWordIsHandle[kk] = false;
	///////////////////////////////////////
	if(RtuRecBuf[0]==0x72 && RtuRecBuf[1]==0x40)//处理保护事件(这是南自扩展规约相对于CDT的不同之处)
	{
		WORD MilliSeconds;
		FERTEVENT Event;
		FERTEVENT *CurEventP;
		SYSTEMTIME CurTime;
		BYTE *RecBuf=&Rtus[RtuNo].RecBuf[6];//取信息字
		BYTE *SOEInfo = Rtus[RtuNo].CDT_SOEInfo;
		GetLocalTime(&CurTime);
		if ((RecBuf[1] == SOEInfo[0]) && (RecBuf[22] == SOEInfo[1]) && (RecBuf[15] == SOEInfo[2]) && (RecBuf[16] == SOEInfo[3]) && (RecBuf[14] == SOEInfo[4]))
			return;//由于事件上传多次,保证对相同事件只处理一次
		if((Events.EventNum+1)==Events.EventSendNum)
		{
			Beep(1200,500);
			return;
		}
		MilliSeconds=DtoH(RecBuf[15]+RecBuf[16]*256);
		if (Rtus[RtuNo].TimeForbit == 1)
		{
			Event.ms = CurTime.wMilliseconds % 256;
			Event.hundms = CurTime.wMilliseconds / 256;
			Event.seconds = (BYTE)CurTime.wSecond;
			Event.minute = (BYTE)CurTime.wMinute;
			Event.hour = (BYTE)CurTime.wHour;
		}
		else
		{
			Event.ms = MilliSeconds % 256;
			Event.hundms = MilliSeconds / 256;
			Event.seconds = DtoH(RecBuf[14]);
			Event.minute =DtoH(RecBuf[13]);
			Event.hour =DtoH( RecBuf[10]);
		}
		Event.day=(BYTE)CurTime.wDay;
		Event.month=(BYTE)CurTime.wMonth;
		Event.year=CurTime.wYear;
		Event.Recms = CurTime.wMilliseconds % 256;
		Event.Rechundms = CurTime.wMilliseconds/256;
		Event.Recseconds = (BYTE)CurTime.wSecond;
		Event.Recminute = (BYTE)CurTime.wMinute;
		Event.Rechour = (BYTE)CurTime.wHour;
		Event.Recday = (BYTE)CurTime.wDay;
		Event.rtuno = RtuNo;
		Event.yxno = RecBuf[22]+(RecBuf[1]-1)*8;
		Event.cause = 1;
		Event.type = 1;
		SOEInfo[0] = RecBuf[1];
		SOEInfo[1] = RecBuf[22];
		SOEInfo[2] = RecBuf[15];
		SOEInfo[3] = RecBuf[16];
		SOEInfo[4] = RecBuf[14];
		CurEventP = Events.EventBuf + Events.EventNum;
		memcpy(CurEventP,&Event,sizeof(FERTEVENT));
		if(++Events.EventNum>=MAX_EVENT_NUM)
			Events.EventNum=0;
	}
	else
	{
		for (NonceInfoWord=6;NonceInfoWord < Rtus[RtuNo].RecBufPtr;NonceInfoWord +=6)//以信息字为单位,一个一个处理
		{
			int InfoCode=RtuRecBuf[NonceInfoWord];//功能码
			if (CDT_CheckCRC(&RtuRecBuf[NonceInfoWord])!=RtuRecBuf[NonceInfoWord+5])//校验不对
			{
				Rtus[Channels[i].ChRtuNo[0]].ErrFrameSum++;
				continue;
			} 
		//保证同一个功能码的信息字只处理一次,消除某些误码或者遥信变位连送三遍的情况下出现的不一致现象
			if (bInfoWordIsHandle[InfoCode] == true)
				continue;
			else
				bInfoWordIsHandle[InfoCode] = true;
			////////////////////////////////////////////
			if ((InfoCode>=Rtus[RtuNo].ProtocolStamp[0])&&(InfoCode<=0x7f))//遥测,功能码在遥测定义起始码和7F之间
			{
				for (int j=0;j<2;j++)
				{
					WORD YcValue;
					if (Rtus[RtuNo].ProtocolStamp[5]) //高低交换
						YcValue=RtuRecBuf[NonceInfoWord+j*2+2] + RtuRecBuf[NonceInfoWord+j*2+1]*256;
					else 
						YcValue = RtuRecBuf[NonceInfoWord+j*2+1] + RtuRecBuf[NonceInfoWord+j*2+2]*256;
					WORD YcSign = (Rtus[RtuNo].ProtocolStamp[3])?0x8000:0x800;//遥测符号位:15 or 11
					if (YcSign == 0x800)//遥测符号位:11
					{
						if ((YcValue & 0x8000) || (YcValue & 0x4000)) continue;
						if (YcValue & YcSign)//遥测为负数 
						{
							YcValue &= 0x7ff;
							if(Rtus[RtuNo].ProtocolStamp[6]==1)//补码表示负数 
								YcValue = 0x7ff + 1 - YcValue;
							Rtus[RtuNo].YcValue[(InfoCode-Rtus[RtuNo].ProtocolStamp[0])*2+j]=-(float)YcValue;
						}
						else
						{
							YcValue = YcValue & 0x7ff;
							Rtus[RtuNo].YcValue[(InfoCode-Rtus[RtuNo].ProtocolStamp[0])*2+j]=(float)YcValue;
						}
					}
					else if (YcSign == 0x8000)//遥测符号位:15
					{
						if (YcValue & YcSign)//遥测为负数 
						{
							YcValue &= 0x7fff;
							if(Rtus[RtuNo].ProtocolStamp[6]==1)//补码表示负数 
								YcValue = 0x7fff + 1 - YcValue;
							if(Rtus[RtuNo].ProtocolStamp[4])//数值进制为BCD码
								YcValue=(YcValue & 0xf) + ((YcValue & 0xf0)>>4)*10
									+((YcValue & 0xf00)>>8)*100 + ((YcValue & 0x7000)>>12)*1000; 
							Rtus[RtuNo].YcValue[(InfoCode-Rtus[RtuNo].ProtocolStamp[0])*2+j]=-(float)YcValue;
						}
						else
						{
							YcValue &= 0x7fff;
							if(Rtus[RtuNo].ProtocolStamp[4])//数值进制为BCD码
								YcValue=(YcValue & 0xf) + ((YcValue & 0xf0)>>4)*10
									+((YcValue & 0xf00)>>8)*100 + ((YcValue & 0x7000)>>12)*1000; 
							Rtus[RtuNo].YcValue[(InfoCode-Rtus[RtuNo].ProtocolStamp[0])*2+j]=(float)YcValue;
						}
					}
				}
			}
			else if ((InfoCode>=Rtus[RtuNo].ProtocolStamp[1]) && (InfoCode<=0xff))//遥信
			{
				int iPosition = InfoCode - 0xf0;//第几组谣信已收到
				int YxDWordPtr = InfoCode-Rtus[RtuNo].ProtocolStamp[1];
				int YxValuePtr=YxDWordPtr*32;	
				DWORD YxWord=*(DWORD*)&RtuRecBuf[NonceInfoWord+1];
				BYTE State=0;
				for (int k=0;k<32;k++)
				{
					State = (YxWord & (1<<k)) ? 1 : 0;
					if (Rtus[RtuNo].YxValue[YxValuePtr+k] != State)
					{
						Rtus[RtuNo].YxValue[YxValuePtr+k] = State;
						if (Rtus[RtuNo].RecFullYx & (1<<iPosition)) 
							YxEvent(RtuNo,YxValuePtr+k,State);//生成变位遥信Event
					}
				}
				Rtus[RtuNo].RecFullYx |= (1<<iPosition);
			}
			else if((InfoCode>=Rtus[RtuNo].ProtocolStamp[2]) && (InfoCode<=0xdf))//电能KWH
			{
				if (!(RtuRecBuf[NonceInfoWord+4] & 0x80))//有效
				{
					DWORD KWHValue = 0;
					if ((RtuRecBuf[NonceInfoWord+4] & 0x20) == 0)//not bcd
					{
						KWHValue = RtuRecBuf[NonceInfoWord+1] + RtuRecBuf[NonceInfoWord+2] * 256 
							+ RtuRecBuf[NonceInfoWord+3] * 256 * 256;
					}
					else
					{
						BYTE *t = &RtuRecBuf[NonceInfoWord+1];
						KWHValue = ((t[2] & 0xf0)/16*10 + t[2] & 0x0f)*256*256 
							+ ((t[1] & 0xf0)/16*10 + t[1] & 0x0f)*256 + ((t[0] & 0xf0)/16*10 + t[0] & 0x0f);
					}
					Rtus[RtuNo].KwhValue[InfoCode-Rtus[RtuNo].ProtocolStamp[2]]=KWHValue;
				}
			}
			else if ((InfoCode>=0x8d) && (InfoCode<=0x92))//水位
			{
				float WaterValue;
			
				WaterValue =(float)((RtuRecBuf[NonceInfoWord+1] & 0xf)/100.0);
				WaterValue +=(float)((RtuRecBuf[NonceInfoWord+1]>>4)/10.0);
				WaterValue +=(RtuRecBuf[NonceInfoWord+2] & 0xf);
				WaterValue +=(float)((RtuRecBuf[NonceInfoWord+2]>>4)*10.0);
				WaterValue +=(float)((RtuRecBuf[NonceInfoWord+3] & 0xf)*100.0);
				WaterValue +=(float)((RtuRecBuf[NonceInfoWord+3]>>4)*1000.0);
				Rtus[RtuNo].Water[InfoCode-0x8d]=WaterValue;
			}
			else if ((InfoCode>=0x86) && (InfoCode<=0x89))//总加遥测
			{
			}
			else if (InfoCode==0x8a)//频率
			{
				float Freq;
				for (int k=0;k<2;k++)
				{
					Freq =0;
					Freq =(float)((RtuRecBuf[NonceInfoWord+k*2+1] & 0xf)/100.0);
					Freq +=(float)((RtuRecBuf[NonceInfoWord+k*2+1]>>4)/10.0);
					Freq +=(float)(RtuRecBuf[NonceInfoWord+k*2+2] & 0xf);
					Freq +=(float)((RtuRecBuf[NonceInfoWord+k*2+2]>>4)*10.0);
					Rtus[RtuNo].Freq[k] = Freq;
				}
			}
			else 
				NZ_CDT_Answer(i,RtuNo,NonceInfoWord);//SOE、子站时钟返送、子站状态信息、遥控返校、升降返校
		}
	}
	Rtus[RtuNo].RecBufPtr=0;
}										

				

void NZ_CDT_Answer(int i,int RtuNo,int &NonceInfoWord)
{	
	switch(Rtus[RtuNo].RecBuf[NonceInfoWord])
	{
	case 0x80://0x81  SOE
//		CDT_SOE_Event(RtuNo,NonceInfoWord);	//南自保护事件,没有SOE。注意:报文格式不同于CDT
		break;
	case 0x84:
	case 0x85://子站时钟

⌨️ 快捷键说明

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