📄 processnzctd.cpp
字号:
///////////////////////////////////////////////////////////////////////
// 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 + -