You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3696 lines
88 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//***************************************************************
//* buban101.cpp *
//* aaawen 2005.09.08 *
//***************************************************************
//_DEBUG_MSG_,_OS_WINDOWS_DEBUG_
#ifdef OS_LINUX
#include "baohulib/commport.h"
#include "baohulib/serialport.h"
#else
#include "commport.h"
#include "udpcomm.h"
#include "display.h"
#endif
#include <math.h>
#include <time.h>
#include "buban101.h"
#include "scadaprotect.h"
extern SIO_PARAM_DEF SioParam[];
extern FUNCTION_CALL *FunCallPtr;
extern void *pvconf_handle;
extern void *pvportconf_handle;
extern void *pvdataconf_handle;
extern char pvDataFileName[256];
extern char IniFilePath[256];
const char *gpStrBuban101Cmd[BUBAN101_TIMER_CMD_NUM] =
{
"总召唤电度数据",
"召唤初始化数据"
};
/*!
组织结构:链路(间隔)+装置
*/
char *gpStrBuban101ConfigInfo[] =
{
" ; ***** 部颁101规约参数定义 *****",
" ",
" ; 所有命令召唤周期均以秒为单位。",
" 站地址 = 1 ; 缺省= 0 。",
" 平衡式通讯 = 0 ; 缺省= 0 。",
" 总召唤电度数据 = 120",
" 召唤初始化数据 = 300",
" 超时时间 = 20.0",
" 遥控方式=0",
" ; =0双点遥控(缺省)=1单点遥控。",
" ",
"遥测信息体起始地址=0x701",
"遥信信息体起始地址=0x001",
"遥脉信息体起始地址=0xC01",
"遥控信息体起始地址=0xB01",
" ;以上信息体地址可以配置,缺省值为97版部颁101所规定值",
" ",
" 版本号 = 1",
" ;=0 是buban101(缺省值); =1 是IEC_870_5_101规约",
" ;注意:转发仅支持Buban101规约",
" ",
"*******部颁101规约结束*******",
"", // 结束标志(中间不能含有该空字符串)
};
//********************************************************************
//* 读取配置函数 *
//*参数int commid : 端口号 *
//********************************************************************
void Buban101ReadConfig(int commid)
{
int i;
char szSection[128], szbuf[128];
char szPortConfig[256];
pBUBAN101PORTPARAM pPortParam;
#ifdef OS_LINUX
strcpy(szPortConfig, "portconfig.ini");
#else
//GetCurrentDirectory(sizeof(szDir), szDir);
sprintf(szPortConfig, "%s/portconfig.ini", IniFilePath);
#endif
SioParam[commid].ExtInfo = HEAP_MALLOC(sizeof(BUBAN101PORTPARAM));
if(!SioParam[commid].ExtInfo)
{
sprintf(szbuf, "WARN(%04d): commid_%02d ExtInfo=malloc(%d) failed.\n",
getpid(), commid, sizeof(BUBAN101PORTPARAM));
DebugPrint(szbuf);
return;
}
memset(SioParam[commid].ExtInfo, 0, sizeof(BUBAN101PORTPARAM));
pPortParam = (pBUBAN101PORTPARAM)SioParam[commid].ExtInfo;
/* 只有在SioParam[commid].m_psBaoHu非空时才会运行到这里 */
pPortParam->m_psBaoHu = SioParam[commid].m_psBaoHu;
sprintf(szSection, "Port%d", commid+1);
if(GetPrivateProString(szSection, "站地址", "0", szbuf, 120, szPortConfig) > 0)
{
pPortParam->LinkAddr = atoi(szbuf);
}
if(GetPrivateProString(szSection, "平衡式通讯", "0", szbuf, 120, szPortConfig) > 0)
{
pPortParam->BalanceOrNot = atoi(szbuf);
}
if(GetPrivateProString(szSection, "遥控方式", "0", szbuf, 120, szPortConfig) > 0)
{
pPortParam->YkMode = atoi(szbuf);
}
if(GetPrivateProString(szSection, "超时时间", "20.0", szbuf, 120, szPortConfig) > 0)
{
pPortParam->lTimeOutConst = (long)(atof(szbuf)*1000/TIMER_CNT);
}
pPortParam->RtuVersion = GetPrivateProInt(szSection, "版本号", 0, szPortConfig);
pPortParam->iAiBaseAddr = GetPrivateProInt(szSection, "遥测信息体起始地址", INFO_AI_BASEADDR, szPortConfig);
pPortParam->iDiBaseAddr = GetPrivateProInt(szSection, "遥信信息体起始地址", INFO_DI_BASEADDR, szPortConfig);
pPortParam->iPiBaseAddr = GetPrivateProInt(szSection, "遥脉信息体起始地址", INFO_PI_BASEADDR, szPortConfig);
pPortParam->iYkBaseAddr = GetPrivateProInt(szSection, "遥控信息体起始地址", INFO_YKYT_BASEADDR, szPortConfig);
// 轮询指令配置
for(i=0; i<BUBAN101_TIMER_CMD_NUM; i++)
{
GetPrivateProString(szSection, (char *)gpStrBuban101Cmd[i], "0", szbuf, 120, szPortConfig);
pPortParam->CmdTime[i].CmdTimerConst = (long)(atof(szbuf)*1000/TIMER_CNT);
if(pPortParam->CmdTime[i].CmdTimerConst > 5)
{
pPortParam->CmdTime[i].CmdTimerCnt = pPortParam->CmdTime[i].CmdTimerConst - 5;
}
}
InitBuban101CommandBuffer(commid);
}
//********************************************************************
//* 读取端口数据函数 *
//*参数int commid : 端口号 *
//* u_char buf : 数据源缓冲区指针 *
//* int len : 数据源长度 *
//********************************************************************
void Buban101RecvData(int commid, u_char *buf, int len)// 规约读数据处理
{
int i;
pBUBAN101PORTPARAM pPortParam;
#ifdef _DEBUG_MSG_
char szbuf[256];
#endif
if(!IsExtInfoPtr(commid))
return;
pPortParam = (pBUBAN101PORTPARAM)SioParam[commid].ExtInfo;
// wen 2005.09.12 有数据接收,就清空复位计数
if(len > 0)
{
pPortParam->LinkOkCnt = 0;
}
for(i=0; i<len; i++)
{
switch(pPortParam->m_psBaoHu->m_iRevStatus)
{
case 0:// 0x10 / 0x68
pPortParam->m_iRecvLen = 0;
if(buf[i] == 0x10)
{
pPortParam->m_psBaoHu->m_iRevStatus = 4;
pPortParam->m_psBaoHu->m_iNeedRevLength = 4;
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
}
else if(buf[i] == 0x68)
{
pPortParam->m_psBaoHu->m_iRevStatus++;
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
}
else if(buf[i] == 0xE5)
{
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
Buban101ProcessData(commid, pPortParam, TRUE);
//pPortParam->LinkOkCnt = 0;
pPortParam->m_psBaoHu->RevCmdFlag = 1;
#ifndef OS_LINUX
if((GetCurPort() == commid) && IsRealDataDisp())
{
WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA,
(BYTE *)pPortParam->m_au8RecvBuf, pPortParam->m_iRecvLen);
}
#endif
break;
}
else
{
pPortParam->m_psBaoHu->m_iRevStatus = 5;
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
}
break;
case 1:
case 2:
pPortParam->m_psBaoHu->m_iRevStatus++;
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
break;
case 3:// 长度计算
if(buf[i] == 0x68)
{
if(pPortParam->m_au8RecvBuf[1] != pPortParam->m_au8RecvBuf[2])
{
pPortParam->m_psBaoHu->m_iRevStatus=1;
SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen;
Buban101ProcessData(commid, pPortParam, FALSE);
pPortParam->m_iRecvLen = 0;
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
}
else
{
pPortParam->m_psBaoHu->m_iRevStatus++;
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
pPortParam->m_psBaoHu->m_iNeedRevLength = (BYTE)(pPortParam->m_au8RecvBuf[1])+2;
}
}
else
{
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
pPortParam->m_psBaoHu->m_iRevStatus=5;
}
break;
case 4:// 正确接收数据
pPortParam->m_psBaoHu->m_iNeedRevLength--;
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
if(pPortParam->m_psBaoHu->m_iNeedRevLength > 0)
break;
if(buf[i] != 0x16)
{
pPortParam->m_psBaoHu->m_iRevStatus=5;
break;
}
if(Buban101Check(pPortParam->m_au8RecvBuf, pPortParam->m_iRecvLen) == TRUE)
{
Buban101ProcessData(commid, pPortParam, TRUE);
pPortParam->m_psBaoHu->m_iRevStatus = 0;
pPortParam->m_psBaoHu->RevCmdFlag = 1;
}
else
{
SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen;
SioParam[commid].LostSyncCnt++;
pPortParam->m_psBaoHu->m_iRevStatus = 5;
}
#ifndef OS_LINUX
if((GetCurPort() == commid) && IsRealDataDisp())
{
WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA,
(BYTE *)pPortParam->m_au8RecvBuf, pPortParam->m_iRecvLen);
}
#endif
//pPortParam->LinkOkCnt = 0;
break;
case 5:// 错误接收数据
default:
//if(buf[i] == 0x16)
if(buf[i] == 0x10)
{
#ifndef OS_LINUX
// wen 2004.11.22 增加显示
if((GetCurPort() == commid) && IsRealDataDisp())
{
WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA,
(BYTE *)pPortParam->m_au8RecvBuf, pPortParam->m_iRecvLen);
}
#endif
Buban101ProcessData(commid, pPortParam, FALSE);
SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen;
pPortParam->m_psBaoHu->m_iRevStatus = 4;
pPortParam->m_psBaoHu->m_iNeedRevLength = 4;
pPortParam->m_iRecvLen = 1;
pPortParam->m_au8RecvBuf[0] = buf[i];
}
else if(buf[i] == 0x68)
{
#ifndef OS_LINUX
// wen 2004.11.22 增加显示
if((GetCurPort() == commid) && IsRealDataDisp())
{
WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA,
(BYTE *)pPortParam->m_au8RecvBuf, pPortParam->m_iRecvLen);
}
#endif
Buban101ProcessData(commid, pPortParam, FALSE);
SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen;
pPortParam->m_psBaoHu->m_iRevStatus = 1;
pPortParam->m_iRecvLen = 1;
pPortParam->m_au8RecvBuf[0] = buf[i];
}
else if((buf[i] == 0x16) || (buf[i] == 0xE5))
{
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
#ifndef OS_LINUX
// wen 2004.11.22 增加显示
if((GetCurPort() == commid) && IsRealDataDisp())
{
WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA,
(BYTE *)pPortParam->m_au8RecvBuf, pPortParam->m_iRecvLen);
}
#endif
Buban101ProcessData(commid, pPortParam, FALSE);
SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen;
pPortParam->m_psBaoHu->m_iRevStatus = 0;
pPortParam->m_iRecvLen = 0;
}
else
{
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
if(pPortParam->m_iRecvLen > 200)
{
#ifndef OS_LINUX
// wen 2004.11.22 增加显示
if((GetCurPort() == commid) && IsRealDataDisp())
{
WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA,
(BYTE *)pPortParam->m_au8RecvBuf, pPortParam->m_iRecvLen);
}
#endif
Buban101ProcessData(commid, pPortParam, FALSE);
SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen;
pPortParam->m_iRecvLen = 0;
}
}
//pPortParam->LinkOkCnt = 0;
break;
}
}
#ifdef _DEBUG_MSG_
sprintf(szbuf, "wen: commid = %d, send=%d, recv=%d, error=%d, lost=%d\n", commid,
SioParam[commid].SendCharNum, SioParam[commid].RecvCharNum,
SioParam[commid].ErrMsgNum, SioParam[commid].LostSyncCnt);
DebugPrint(szbuf);
#endif
}
//********************************************************************
//* 定时器处理函数 *
//*参数int commid : 端口号 *
//********************************************************************
void Buban101Timer(int commid)
{
BUBAN101PORTPARAM *pPortParam;
if(IsExtInfoPtr(commid) == FALSE)
{
return;
}
pPortParam = (pBUBAN101PORTPARAM)SioParam[commid].ExtInfo;
// 如果为转发端口,则不进行轮询指令的生成。
if(PROTOCOL_SLAVE != pPortParam->m_psBaoHu->PortType)
{
if(pPortParam->LinkOk)
{
pPortParam->LinkOkCnt++;
if(pPortParam->LinkOkCnt >= pPortParam->lTimeOutConst)
{
InitBuban101CommandBuffer(commid);
return;
}
}
Buban101FindNextCmd(commid);
}
Buban101SendCmdFormPollCmdBuf(commid);
}
//********************************************************************
//* 遥控遥调数据处理函数 *
//*参数int commid : 端口号 *
//* u_char buf : 数据源缓冲区指针 *
//* int len : 数据源长度 *
//********************************************************************
void Buban101YkYtProcess(int commid, u_char *buf, int len) // 遥控遥调处理
{
int portno, ykytpnt;
int iDirect;
// buf[0] --- 端口号(=commid)
// buf[1]
// buf[2]
// buf[3]
// buf[4] --- 控点号
// buf[5]
// buf[6]
// buf[7]
// buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控;
// 遥调:4=选择,5=执行,6=取消,8=急停)
// buf[9] --- 控制状态(1=分到合2=合到分)
// (最高位为1时为返校命令, 1=控合, 2=控分, 3=失败)
// 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口
// 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。
if(IsExtInfoPtr(commid) == FALSE)
{
return;
}
iDirect = buf[9] & 0x80;
portno = buf[0]+buf[1]*256+buf[2]*65536+buf[3]*16777216;
ykytpnt = buf[4]+buf[5]*256+buf[6]*65536+buf[7]*16777216;
// 返校信息(反馈信号)
if(iDirect)
{
Buban101ProvMakeYkYtCommand(commid, buf, len);
}
else
{
MakeBuBan101YkYtCommand(commid, buf, len);
}
}
//********************************************************************
//* 系统下发对时函数 *
//*参数int commid : 端口号 *
//********************************************************************
void Buban101SendSystemTime(int commid) // 系统对时
{
BUBAN101PORTPARAM *pPortParam;
if(IsExtInfoPtr(commid) == FALSE)
{
return;
}
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if(2 != pPortParam->m_psBaoHu->CheckTime)
{
return;
}
if(pPortParam->Initdata)
{
if(PROTOCOL_SLAVE != pPortParam->m_psBaoHu->PortType)
{
MakeBuban101Command(commid, RTU_TIME);
}
}
}
//********************************************************************
//* 系统退出时规约处理函数 *
//*参数int commid : 端口号 *
//********************************************************************
void Buban101Exit(int commid)
{
// 释放所有分配的内存
}
// 该函数用来驱动由转发端口下发到实际装置的保护命令
void Buban101BaoHuCmdProcess(int commid, RTUMSG *rtumsg, BOOL bUpData)
{
}
int Buban101GetBaohuDataBase(int commid, int iProvAddr, GROUPDEF **ppBaoHuDB)
{
return 0;
}
/////////////////////////通用函数接口结束///////////////////////////////
/////////////////////////buban101公共函数接口///////////////////////////
// 校验数据帧是否正确
BOOL Buban101Check(u_char* msg, int len)
{
BOOL bRetval = FALSE;
int iCheckLen;
if( len == 1 )
{
if( msg[0] == 0xE5 )
bRetval = TRUE;
}
else
{
switch( msg[0] )
{
case 0x10: // 短帧
if ( msg[4] != 0x16 )
break;
if ( CalBuban101Lpc( &msg[1], 2 ) != msg[3] )
break;
bRetval = TRUE;
break;
case 0x68: // 长帧
if ( msg[0] != msg[3] )
break;
if ( msg[len-1] != 0x16 )
break;
if ( msg[1] != msg[2] )
break;
iCheckLen = msg[1];
if ( CalBuban101Lpc( &msg[4], iCheckLen ) != msg[len-2] )
break;
bRetval = TRUE;
break;
default:
break;
}
}
return bRetval;
}
//计算 Buban101 累加和检验码
u_char CalBuban101Lpc(u_char* msg, int len)
{
int i;
u_char retval = 0;
for (i = 0 ; i < len; i++)
retval += msg[i];
return retval;
}
//指令缓冲区初始化
void InitBuban101CommandBuffer(int commid)
{
pBUBAN101PORTPARAM pPortParam;
pPortParam = (pBUBAN101PORTPARAM)SioParam[commid].ExtInfo;
pPortParam->LinkOk = false;
pPortParam->RstLinkOk = false;
pPortParam->Initdata = false;
pPortParam->CtlByte = 0;
pPortParam->CurCmdIdx = 0;
pPortParam->LinkOkCnt = 0;
ClearAllCmdFromPollCmdBuf(commid);
}
/////////////////////////buban101公共函数接口结束///////////////////////
void Buban101ProvMakeYkYtCommand(int commid, u_char *buf, int len)
{
// buf[0] --- 端口号(=commid)
// buf[1]
// buf[2]
// buf[3]
// buf[4] --- 控点号
// buf[5]
// buf[6]
// buf[7]
// buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控;
// 遥调:4=选择,5=执行,6=取消,8=急停)
// buf[9] --- 控制状态(1=分到合2=合到分)
// (最高位为1时为返校命令, 1=控合, 2=控分, 3=失败)
// 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口
// 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。
int ykpoint;
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
static int iYkStatus = 0;
BUBAN101PORTPARAM *pPortParam;
if(IsExtInfoPtr(commid) == FALSE)
{
return;
}
if((buf[9] & 0x80) == 0)
{
return;
}
pPortParam = (pBUBAN101PORTPARAM)SioParam[commid].ExtInfo;
memset( (char*)commandbuf, 0x00, MAX_POLLCMD_BUF_LEN );
ykpoint = buf[4]+buf[5]*256+buf[6]*65536+buf[7]*16777216;
ykpoint += pPortParam->iYkBaseAddr - 1;
switch(buf[8])
{
case 1:
case 4: // 选择
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x53;
commandbuf[5] = pPortParam->LinkAddr;
switch(pPortParam->YkMode)
{
case CONTROL_SINGAL: // 单点控制
if(VER_IEC870_5_101 != pPortParam->RtuVersion)
commandbuf[6] = 46;
else
commandbuf[6] = 45;
break;
case CONTROL_DOUBLE: // 双点控制
case CONTROL_DIRECT: // 直接控制
commandbuf[6] = 46;//(rtumsg->MsgData[3] == 1) ? 46 : 47;
break;
}
commandbuf[7] = 1;
if((buf[9] & 0x03) == 0x03)
{
commandbuf[8] = 0x47;
}
else
{
commandbuf[8] = 7;
}
commandbuf[9] = pPortParam->LinkAddr;
// wen 2002.11.18 字节顺序修改
commandbuf[10] = (char)(ykpoint & 0x00ff);
commandbuf[11] = (char)((ykpoint & 0xff00)>>8);
if(commandbuf[8] == 0x07)
{
if((buf[9] & 0x01) == 1)
{
if( commandbuf[6] != 45)
{
commandbuf[12] = 0xfc + 2;
iYkStatus = 2;
}
else
{
commandbuf[12] = 0xfc + 1;
iYkStatus = 1;
}
}
else
{
if( commandbuf[6] != 45 )
{
commandbuf[12] = 0xfc + 1;
iYkStatus = 1;
}
else
{
commandbuf[12] = 0xfc;
iYkStatus = 0;
}
}
}
commandbuf[13] = CalBuban101Lpc(&commandbuf[4], 9);
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, 15);
break;
case 2:
case 5: // 执行
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x53;
commandbuf[5] = pPortParam->LinkAddr;
switch(pPortParam->YkMode )
{
case CONTROL_SINGAL: // 单点控制
if(VER_IEC870_5_101 != pPortParam->RtuVersion)
commandbuf[6] = 46;
else
commandbuf[6] = 45;
break;
case CONTROL_DOUBLE: // 双点控制
case CONTROL_DIRECT: // 直接控制
commandbuf[6] = 46;//(rtumsg->MsgData[3] == 1) ? 46 : 47;
break;
}
commandbuf[7] = 1;
if(buf[9] & 0x01)
{
commandbuf[8] = 7;
}
else
{
commandbuf[8] = 0x47;
}
commandbuf[9] = pPortParam->LinkAddr;
// wen 2002.11.18 字节顺序修改
//*(WORD*)&commandbuf[10] = ykpoint;
commandbuf[10] = (char)(ykpoint & 0x00ff);
commandbuf[11] = (char)((ykpoint & 0xff00)>>8);
commandbuf[12] = (char)(0x7c + iYkStatus);
commandbuf[13] = CalBuban101Lpc(&commandbuf[4], 9);
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, 15);
break;
case 3:
case 6:
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x53;
commandbuf[5] = pPortParam->LinkAddr;
switch(pPortParam->YkMode)
{
case CONTROL_SINGAL: // 单点控制
if(VER_IEC870_5_101 != pPortParam->RtuVersion)
commandbuf[6] = 46;
else
commandbuf[6] = 45;
break;
case CONTROL_DOUBLE: // 双点控制
case CONTROL_DIRECT: // 直接控制
commandbuf[6] = 46;//(rtumsg->MsgData[3] == 1) ? 46 : 47;
break;
}
commandbuf[7] = 1;
if(buf[9] & 0x01)
{
commandbuf[8] = 9;
}
else
{
commandbuf[8] = 0x49;
}
commandbuf[9] = pPortParam->LinkAddr;
// wen 2002.11.18 字节顺序修改
//*(WORD*)&commandbuf[10] = ykpoint;
commandbuf[10] = (char)(ykpoint & 0x00ff);
commandbuf[11] = (char)((ykpoint & 0xff00)>>8);
commandbuf[12] = (char)(0xfc + iYkStatus);
commandbuf[13] = CalBuban101Lpc(&commandbuf[4], 9);
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, 15);
break;
}
if(ShmGetDispYkYtFlag())
{
printf("TIP_(%04d): commid =%d ykytpnt=%d, op=%d checked.\n",
getpid(), commid, ykpoint, (buf[9] & 0x7F));
}
}
//===========================以下为指令生成函数=======================
/*!
\brief 寻找并生成下一条命令
\param u_32 portno : RTU端口号
\param i_32 iBuIdx : 间隔装置索引
*/
void MakeBuban101Command(u_32 commid, u_char cmdidx)
{
int i;
DAY_TIME sCurTime;
char commandbuf[MAX_POLLCMD_BUF_LEN];
BUBAN101PORTPARAM *pPortParam;
memset( commandbuf, 0, sizeof( commandbuf ) );
pPortParam = (pBUBAN101PORTPARAM)SioParam[commid].ExtInfo;
switch ( cmdidx )
{
case ASK_LINK: // 请求链路
commandbuf[0] = 0x10;
commandbuf[1] = 0x49;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, 5);
break;
case RST_LINK: // 复位链路
commandbuf[0] = 0x10;
commandbuf[1] = 0x40;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, 5);
break;
case RTU_TIME: // 时间同步
GetLocalTimeEx(&sCurTime);
commandbuf[0] = 0x68;
commandbuf[1] = 15;
commandbuf[2] = 15;
commandbuf[3] = 0x68;
commandbuf[4] = 0x53;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 103;
commandbuf[7] = 1;
commandbuf[8] = 6;
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
sCurTime.mSec = sCurTime.Sec * 1000 + sCurTime.mSec;
commandbuf[12] = sCurTime.mSec % 256;
commandbuf[13] = sCurTime.mSec / 256;
commandbuf[14] = (u_char)sCurTime.Min;
commandbuf[15] = (u_char)sCurTime.Hour;
commandbuf[16] = (u_char)sCurTime.Day;
commandbuf[17] = (u_char)sCurTime.Month;
commandbuf[18] = (u_char)(sCurTime.Year%100);
commandbuf[20] = 0x16;
PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, commandbuf, 21);
break;
case ASK_DI_DATA: // 召唤2级数据YX
for ( i = 0; i < (pPortParam->m_psBaoHu->DiNum+MAX_GROUP_DINUM-1)/MAX_GROUP_DINUM; i++)
{
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x5b;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 100;
commandbuf[7] = 0;
commandbuf[8] = 5;
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
commandbuf[12] = 21 + i;
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, 15);
}
break;
case ASK_AI_DATA: // 召唤2级数据YC
for ( i = 0; i < (pPortParam->m_psBaoHu->AiNum+MAX_GROUP_AINUM-1)/MAX_GROUP_AINUM; i++)
{
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x5b;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 100;
commandbuf[7] = 0;
commandbuf[8] = 5;
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
commandbuf[12] = 29 + i;
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, 15);
}
break;
case ASK_PI_DATA: // 召唤2级数据YM
for ( i = 0; i < (pPortParam->m_psBaoHu->PiNum+MAX_GROUP_PINUM-1)/MAX_GROUP_PINUM; i++)
{
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x5b;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 101;
commandbuf[7] = 0;
commandbuf[8] = 6;
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
if(VER_IEC870_5_101 == pPortParam->RtuVersion)
commandbuf[12] = 1 + i;
else
commandbuf[12] = 2 + i;
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, 15);
}
break;
case ASK_PI: //召唤电度量
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x53;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 101;
commandbuf[7] = 1;
commandbuf[8] = 6;
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
if(VER_IEC870_5_101 == pPortParam->RtuVersion)
commandbuf[12] = 0x45;
else
commandbuf[12] = 0x41;
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, 15);
pPortParam->Initdata = FALSE;
break;
case ASK_ALL_DATA:// 召唤初始化数据
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x53;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 100;
commandbuf[7] = 1;
commandbuf[8] = 6;
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
commandbuf[12] = 20;
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, 15);
pPortParam->Initdata = FALSE;
break;
case ASK_SECOND_DATA:// 召唤2级数据
commandbuf[0] = 0x10;
commandbuf[1] = 0x5b;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, 5);
break;
case ASK_FIRST_DATA: // 召唤1级数据
commandbuf[0] = 0x10;
commandbuf[1] = 0x5a;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, commandbuf, 5);
break;
case ACK: //确认回答
commandbuf[0] = 0x10;
commandbuf[1] = 0x00;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, commandbuf, 5);
break;
case ANS_LINK:
commandbuf[0] = 0x10;
commandbuf[1] = 0x0b;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, commandbuf, 5);
break;
}
}
//生成遥控遥调指令
void MakeBuBan101YkYtCommand( u_32 commid, u_char *buf, int len )
{
// buf[0] --- 端口号(=commid)
// buf[1]
// buf[2]
// buf[3]
// buf[4] --- 控点号
// buf[5]
// buf[6]
// buf[7]
// buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控;
// 遥调:4=选择,5=执行,6=取消,8=急停)
// buf[9] --- 控制状态(1=分到合2=合到分)
// (最高位为1时为返校命令, 1=成功, 0=失败)
// 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口
// 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。
int ykpoint;
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
static int iYkStatus = 0;
BUBAN101PORTPARAM *pPortParam;
pPortParam = (pBUBAN101PORTPARAM)SioParam[commid].ExtInfo;
memset( (char*)commandbuf, 0x00, MAX_POLLCMD_BUF_LEN );
ykpoint = buf[4]+buf[5]*256+buf[6]*65536+buf[7]*16777216;
ykpoint += pPortParam->iYkBaseAddr - 1;
switch(buf[8])
{
case 1:
case 4: // 选择
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x53;
commandbuf[5] = pPortParam->LinkAddr;
switch(pPortParam->YkMode)
{
case CONTROL_SINGAL: // 单点控制
if(VER_IEC870_5_101 != pPortParam->RtuVersion)
commandbuf[6] = 46;
else
commandbuf[6] = 45;
break;
case CONTROL_DOUBLE: // 双点控制
case CONTROL_DIRECT: // 直接控制
commandbuf[6] = 46;//(rtumsg->MsgData[3] == 1) ? 46 : 47;
break;
}
commandbuf[7] = 1;
commandbuf[8] = 6;
commandbuf[9] = pPortParam->LinkAddr;
// wen 2002.11.18 字节顺序修改
commandbuf[10] = (char)(ykpoint & 0x00ff);
commandbuf[11] = (char)((ykpoint & 0xff00)>>8);
if(buf[9] == 1)
{
if( commandbuf[6] != 45 )
{
commandbuf[12] = 0xfc + 2;
iYkStatus = 2;
}
else
{
commandbuf[12] = 0xfc + 1;
iYkStatus = 1;
}
}
else
{
if( commandbuf[6] != 45 )
{
commandbuf[12] = 0xfc + 1;
iYkStatus = 1;
}
else
{
commandbuf[12] = 0xfc;
iYkStatus = 0;
}
}
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, 15);
break;
case 2:
case 5: // 执行
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x53;
commandbuf[5] = pPortParam->LinkAddr;
switch(pPortParam->YkMode )
{
case CONTROL_SINGAL: // 单点控制
if(VER_IEC870_5_101 != pPortParam->RtuVersion)
commandbuf[6] = 46;
else
commandbuf[6] = 45;
break;
case CONTROL_DOUBLE: // 双点控制
case CONTROL_DIRECT: // 直接控制
commandbuf[6] = 46;//(rtumsg->MsgData[3] == 1) ? 46 : 47;
break;
}
commandbuf[7] = 1;
commandbuf[8] = 6;
commandbuf[9] = pPortParam->LinkAddr;
// wen 2002.11.18 字节顺序修改
//*(WORD*)&commandbuf[10] = ykpoint;
commandbuf[10] = (char)(ykpoint & 0x00ff);
commandbuf[11] = (char)((ykpoint & 0xff00)>>8);
commandbuf[12] = (char)(0x7c + iYkStatus);
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, 15);
break;
case 3:
case 6:
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x53;
commandbuf[5] = pPortParam->LinkAddr;
switch(pPortParam->YkMode)
{
case CONTROL_SINGAL: // 单点控制
if(VER_IEC870_5_101 != pPortParam->RtuVersion)
commandbuf[6] = 46;
else
commandbuf[6] = 45;
break;
case CONTROL_DOUBLE: // 双点控制
case CONTROL_DIRECT: // 直接控制
commandbuf[6] = 46;//(rtumsg->MsgData[3] == 1) ? 46 : 47;
break;
}
commandbuf[7] = 1;
commandbuf[8] = 8;
commandbuf[9] = pPortParam->LinkAddr;
// wen 2002.11.18 字节顺序修改
//*(WORD*)&commandbuf[10] = ykpoint;
commandbuf[10] = (char)(ykpoint & 0x00ff);
commandbuf[11] = (char)((ykpoint & 0xff00)>>8);
commandbuf[12] = (char)(0xfc + iYkStatus);
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, 15);
break;
}
if(ShmGetDispYkYtFlag())
{
printf("TIP_(%04d): commid =%d ykytpnt=%d, op=%d checked.\n",
getpid(), commid, ykpoint, (buf[9] & 0x7F));
}
}
//===================以下为POLLING规约常规函数接口======================
/*!
\brief 寻找并生成下一条命令
\param u_32 portno : RTU端口号
\param i_32 iBuIdx : 间隔装置索引
*/
void Buban101FindNextCmd(int commid)
{
int i, iCurCmdIdx;
BUBAN101PORTPARAM *pPortParam;
int framename[BUBAN101_TIMER_CMD_NUM] =
{
// ASK_DI_DATA,
// ASK_AI_DATA,
// ASK_PI_DATA,
ASK_PI,
ASK_ALL_DATA
};
if((commid < 0) || (commid >= GetMaxPort()))
{
return;
}
if(!ShmGetPortFlag(commid, FLAG_OPEN))
{
return;
}
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if(!pPortParam->LinkOk)
{
if(CheckPollCmdBufEmpty(commid) <= 0)
{
return;
}
if(!pPortParam->RstLinkOk)
{
InitBuban101CommandBuffer(commid);
MakeBuban101Command(commid, ASK_LINK);
}
else
{
pPortParam->LinkOkCnt++;
if(pPortParam->LinkOkCnt >= pPortParam->lTimeOutConst)
{
pPortParam->LinkOkCnt = 0;
pPortParam->RstLinkOk = false;
}
}
return;
}
for(i = 0; i < BUBAN101_TIMER_CMD_NUM; i++)
{
if(pPortParam->CmdTime[i].CmdTimerConst )
pPortParam->CmdTime[i].CmdTimerCnt++;
}
if(CheckPollCmdBufEmpty(commid) <= 0)
{
return;
}
if (!pPortParam->Initdata )
{
// IEC-870-5-101中多帧数据轮询
//张掖的东方电子IEC101要求总召唤期间不请求二级数据
//if(VER_IEC870_5_101 == pPortParam->RtuVersion)
// MakeBuban101Command( port, ASK_SECOND_DATA );
return;
}
iCurCmdIdx = pPortParam->CurCmdIdx;
for ( i = 0; i < BUBAN101_TIMER_CMD_NUM; i++ )
{
iCurCmdIdx = (iCurCmdIdx+1) % BUBAN101_TIMER_CMD_NUM;
if ( (pPortParam->CmdTime[iCurCmdIdx].CmdTimerCnt
>= pPortParam->CmdTime[iCurCmdIdx].CmdTimerConst)
&& ( pPortParam->CmdTime[iCurCmdIdx].CmdTimerConst > 0 ))
{
pPortParam->CurCmdIdx = iCurCmdIdx;
MakeBuban101Command(commid, framename[iCurCmdIdx]);
pPortParam->CmdTime[iCurCmdIdx].CmdTimerCnt = 0;
return;
}
}
MakeBuban101Command(commid, ASK_SECOND_DATA);
}
BOOL Buban101FindNextCmdEx(int commid)
{
BOOL bRetVal;
int i, iCurCmdIdx;
BUBAN101PORTPARAM *pPortParam;
int framename[BUBAN101_TIMER_CMD_NUM] =
{
// ASK_DI_DATA,
// ASK_AI_DATA,
// ASK_PI_DATA,
ASK_PI,
ASK_ALL_DATA
};
bRetVal = FALSE;
if((commid < 0) || (commid >= GetMaxPort()))
{
return bRetVal;
}
if(!ShmGetPortFlag(commid, FLAG_OPEN))
{
return bRetVal;
}
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if(!pPortParam->LinkOk)
{
if(CheckPollCmdBufEmpty(commid) <= 0)
{
return bRetVal;
}
if(!pPortParam->RstLinkOk)
{
InitBuban101CommandBuffer(commid);
MakeBuban101Command(commid, ASK_LINK);
bRetVal = TRUE;
}
else
{
pPortParam->LinkOkCnt++;
if(pPortParam->LinkOkCnt >= pPortParam->lTimeOutConst)
{
pPortParam->LinkOkCnt = 0;
pPortParam->RstLinkOk = false;
}
}
return bRetVal;
}
for(i = 0; i < BUBAN101_TIMER_CMD_NUM; i++)
{
if(pPortParam->CmdTime[i].CmdTimerConst )
pPortParam->CmdTime[i].CmdTimerCnt++;
}
if(CheckPollCmdBufEmpty(commid) <= 0)
{
return bRetVal;
}
if (!pPortParam->Initdata )
{
// IEC-870-5-101中多帧数据轮询
//张掖的东方电子IEC101要求总召唤期间不请求二级数据
//if(VER_IEC870_5_101 == pPortParam->RtuVersion)
// MakeBuban101Command( port, ASK_SECOND_DATA );
return bRetVal;
}
iCurCmdIdx = pPortParam->CurCmdIdx;
for ( i = 0; i < BUBAN101_TIMER_CMD_NUM; i++ )
{
iCurCmdIdx = (iCurCmdIdx+1) % BUBAN101_TIMER_CMD_NUM;
if ( (pPortParam->CmdTime[iCurCmdIdx].CmdTimerCnt
>= pPortParam->CmdTime[iCurCmdIdx].CmdTimerConst)
&& ( pPortParam->CmdTime[iCurCmdIdx].CmdTimerConst > 0 ))
{
pPortParam->CurCmdIdx = iCurCmdIdx;
MakeBuban101Command(commid, framename[iCurCmdIdx]);
pPortParam->CmdTime[iCurCmdIdx].CmdTimerCnt = 0;
bRetVal = TRUE;
}
}
if(FALSE == bRetVal)
{
MakeBuban101Command(commid, ASK_SECOND_DATA);
bRetVal = TRUE;
}
return bRetVal;
}
void Buban101SendCmdFormPollCmdBuf(int commid)
{
BYTE fcb = 0x20;
BYTE buf[MAX_MSG_BUF_SIZE];
i_32 len;
BUBAN101PORTPARAM *pPortParam;
if((commid < 0) || (commid >= GetMaxPort()))
{
return;
}
if(!ShmGetPortFlag(commid, FLAG_OPEN))
{
return;
}
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if(pPortParam->m_psBaoHu->ForceWaitFlag
&& pPortParam->m_psBaoHu->ForceWaitCnt)
{
pPortParam->m_psBaoHu->ForceWaitCnt--;
if(pPortParam->m_psBaoHu->ForceWaitCnt == 0)
{
// 清除当前命令
ClearCmdFormPollCmdBuf(commid);
//ClearCmdAllFlag(commid);
}
}
if(pPortParam->m_psBaoHu->SendCmdFlag
&& (pPortParam->m_psBaoHu->RevCmdFlag == 0))
{
pPortParam->m_psBaoHu->RetryTimeCnt++;
if(pPortParam->m_psBaoHu->RetryTimeCnt < pPortParam->m_psBaoHu->RetryTime)
{
return;
}
pPortParam->m_psBaoHu->RetryTimeCnt = 0;
pPortParam->m_psBaoHu->RetryCnt++;
if(pPortParam->m_psBaoHu->RetryCnt > pPortParam->m_psBaoHu->Retry)
{
// 清除当前命令
ClearCmdFormPollCmdBuf(commid);
//ClearCmdAllFlag(commid);
}
else
{
pPortParam->m_psBaoHu->SendCmdFlag = 0;
pPortParam->m_psBaoHu->RevCmdFlag = 0;
pPortParam->m_psBaoHu->ReSendCmdFlag = 1;
}
}
if(pPortParam->m_psBaoHu->SendCmdFlag
&& pPortParam->m_psBaoHu->RevCmdFlag)
{
// 清除当前命令
ClearCmdFormPollCmdBuf(commid);
//ClearCmdAllFlag(commid);
}
if(pPortParam->m_psBaoHu->WaitTime)
{
pPortParam->m_psBaoHu->WaitTimeCnt++;
if(pPortParam->m_psBaoHu->WaitTimeCnt
< pPortParam->m_psBaoHu->WaitTime)
{
return;
}
}
pPortParam->m_psBaoHu->WaitTimeCnt = 0;
if(pPortParam->m_psBaoHu->ReSendCmdFlag)
{
len = ReGetCmdFormPollCmdBuf(commid, buf, sizeof(buf));
}
else
{
len = GetCmdFormPollCmdBuf(commid, buf, sizeof(buf));
}
if(len < 3)
{
return;
}
#ifndef OS_LINUX
if(isUdpSocketExist() == TRUE)
#endif
{
switch(buf[2])
{
case 0x10:
if(PROTOCOL_SLAVE == pPortParam->m_psBaoHu->PortType)
break;
if((buf[3] & 0x40) == 0)
{
buf[5] = CalBuban101Lpc(&buf[3], 2);
break;
}
if(pPortParam->m_psBaoHu->ReSendCmdFlag)
{
pPortParam->CtlByte = ~pPortParam->CtlByte;
}
buf[3] |= ( fcb & pPortParam->CtlByte );
pPortParam->CtlByte = ~pPortParam->CtlByte;
buf[5] = CalBuban101Lpc(&buf[3], 2);
break;
case 0x68:
if(PROTOCOL_SLAVE == pPortParam->m_psBaoHu->PortType)
break;
if(pPortParam->m_psBaoHu->ReSendCmdFlag)
{
pPortParam->CtlByte = ~pPortParam->CtlByte;
}
buf[6] |= ( fcb & pPortParam->CtlByte );
pPortParam->CtlByte = ~pPortParam->CtlByte;
buf[buf[3]+6] = CalBuban101Lpc(&buf[6], buf[3]);
break;
default:
break;
}
SendDataToPort(commid, (char *)&buf[2], len-2);
pPortParam->m_psBaoHu->SendCmdFlag = 1;
pPortParam->m_psBaoHu->ReSendCmdFlag = 0;
pPortParam->m_psBaoHu->RevCmdFlag = 0;
pPortParam->m_psBaoHu->RetryTimeCnt = 0;
}
#ifdef OS_LINUX
if(pPortParam->m_psBaoHu->LastGetCmdBuf == FAST_CMD_TYPE)
#else
if((pPortParam->m_psBaoHu->LastGetCmdBuf == FAST_CMD_TYPE)
|| !isUdpSocketExist())
#endif
{
pPortParam->m_psBaoHu->ForceWaitCnt = BYTE1(buf[0])+BYTE0(buf[1])+TIMER_CNT-1;
pPortParam->m_psBaoHu->ForceWaitCnt /= TIMER_CNT;
if(pPortParam->m_psBaoHu->ForceWaitCnt)
{
pPortParam->m_psBaoHu->ForceWaitFlag = 1;
}
else
{
ClearCmdFormPollCmdBuf(commid); // 清除当前命令
//ClearCmdAllFlag(commid); // 清除当前命令
}
}
}
//===========================指令生成函数结束=========================
//===========================以下为数据处理函数=======================
void Buban101ProcessData(u_32 commid, BUBAN101PORTPARAM *psPortParam, BOOL bProcess)
{
RTUMSG msg;
BUBAN101PORTPARAM *pPortParam;
pPortParam = psPortParam;
if(TRUE == bProcess)
{
msg.PortIdx = (BYTE)commid;
msg.MsgLen = psPortParam->m_iRecvLen;
memcpy(msg.MsgData, psPortParam->m_au8RecvBuf, msg.MsgLen);
msg.MsgData[msg.MsgLen] = CHECK_WHOLE;
msg.MsgData[msg.MsgLen+1] = 0;
// 子站数据处理
if(PROTOCOL_SLAVE == pPortParam->m_psBaoHu->PortType)
{
ProvBuban101dataProcess(commid, &msg);
return;
}
// 主站数据处理
switch(msg.MsgData[0])
{
case 0x68:
Buban101longprocess(&msg);
break;
case 0x10:
Buban101shortprocess(&msg);
break;
case 0xE5:
Buban101NoChanged(&msg);
break;
default:
break;
}
}
}
void Buban101NoChanged(RTUMSG * rtumsg)
{
}
//***************************************************************
//* 接收的数据为固定帧长时的处理程序
//*参数 RTUMSG* rtumsg:接收到的数据信息
//***************************************************************
void Buban101shortprocess(RTUMSG *rtumsg)
{
int framecnt = 0;
int commid;
BOOL bMakeAllDataFlag;
BUBAN101PORTPARAM *pPortParam;
#ifdef _DEBUG_MSG_
char szbuf[256];
#endif
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
// wen 2003.08.11 判断是否发送全数据是在复位刚刚完成时
bMakeAllDataFlag = pPortParam->LinkOk & pPortParam->RstLinkOk;
if((rtumsg->MsgData[1] & 0xc0) == 0xc0)
{
switch(rtumsg->MsgData[1] & 0x0f)
{
case 0x0: //复位链路确认0000
if(!pPortParam->RstLinkOk)
{
MakeBuban101Command(commid, ASK_LINK);
break;
}
else
{
pPortParam->LinkOk = TRUE;
}
if(pPortParam->LinkOk && pPortParam->RstLinkOk)
{
if(!bMakeAllDataFlag)
{
MakeBuban101Command(commid, ASK_ALL_DATA);
}
}
pPortParam->CtlByte = 0xff;
MakeBuban101Command(commid, ACK);
pPortParam->RstLinkOk = TRUE;
break;
case 0x09: //从站请求主站
if(bMakeAllDataFlag)
{
InitBuban101CommandBuffer(commid);
}
MakeBuban101Command(commid, ANS_LINK);
break;
default:
break;
}
return;
}
//子站数据区已满如何处理
if(rtumsg->MsgData[1] & 0x10)
{
;
}
else
{
// wen 2004.03.16 修改一级数据的问询条件,只要有一级数据就问询
//if( bMakeAllDataFlag )
//{
// //请求一级数据
// if ( (rtumsg->MsgData[1] & 0x20) && pPortParam->Initdata )
// MakeBuban101Command ( port, ASK_FIRST_DATA);
//}
if(rtumsg->MsgData[1] & 0x20)
{
MakeBuban101Command(commid, ASK_FIRST_DATA);
}
}
switch(rtumsg->MsgData[1] & 0x0f)
{
case 0x0: //复位链路确认0000
if(pPortParam->RstLinkOk)
{
pPortParam->LinkOk = TRUE;
}
else
{
if(pPortParam->BalanceOrNot == 0)
{
pPortParam->LinkOk = TRUE;
pPortParam->RstLinkOk = TRUE;
}
}
if(pPortParam->LinkOk && pPortParam->RstLinkOk)
{
if(!bMakeAllDataFlag)
{
MakeBuban101Command(commid, ASK_ALL_DATA);
}
}
pPortParam->RstLinkOk = TRUE;
pPortParam->CtlByte = 0xff;
break;
case 0xb: //链路完好1011
MakeBuban101Command(commid, RST_LINK);
break;
case 0x09:
pPortParam->Initdata = TRUE;
break;
default:
break;
}
}
//***************************************************************
//* 接收的数据为可变帧长时的处理程序
//*参数 RTUMSG* rtumsg:接收到的数据信息
//***************************************************************
void Buban101longprocess(RTUMSG *rtumsg)
{
int commid;
BUBAN101PORTPARAM *pPortParam;
#ifdef _DEBUG_MSG_
char szbuf[256];
#endif
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if ((rtumsg->MsgData[4] & 0xc0) != 0xc0)
{
//子站数据区已满如何处理
if( rtumsg->MsgData[4] & 0x10)
{
;
}
else
{
// wen 2004.03.16 修改一级数据的问询条件,只要有一级数据就问询
////请求一级数据
//if( rtumsg->MsgData[4] & 0x20 && pPortParam->Initdata)
// MakeBuban101Command (rtumsg->PortNumber, ASK_FIRST_DATA);
if(rtumsg->MsgData[4] & 0x20)
{
MakeBuban101Command(commid, ASK_FIRST_DATA);
}
}
}
switch (rtumsg->MsgData[6])
{
case 1: // 单点遥信处理
Buban101DiDataProcess( rtumsg, 0 );
break;
case 2: // 单点遥信SOE处理
Buban101SoeDataProcess( rtumsg, 0 );
break;
case 3: // 双点遥信处理
Buban101DiDataProcess( rtumsg, 1 );
break;
case 4: // 双点遥信SOE处理
Buban101SoeDataProcess( rtumsg, 1 );
break;
case 5: // 变压器分接头位置
break;
case 6: // 变压器分接头位置带时标
break;
case 7: // 子站远动终端状态
break;
case 9: // 带品质无时标遥测
Buban101AiWithPzDataProcess( rtumsg, 0 );
break;
case 10: // 带品质带时标遥测
Buban101AiWithPzDataProcess( rtumsg, 1 );
break;
case 20: // 子站传送遥信变位帧
Buban101AutoSendDiProcess( rtumsg );
break;
case 21: // 全遥测数据处理 或变化数据
Buban101AllAiDataProcess( rtumsg );
break;
case 15: // 不带时标电度
Buban101PiDataProcess( rtumsg );
break;
case 16: // 带时标电度
Buban101PiWithTimeDataProcess( rtumsg );
break;
case 17: // 继电保护装置单个事件顺序记录帧
case 18: // 继电保护装置成组记录启动事件顺序
case 19: // 继电保护装置成组输出电路的事件顺序记录
Buban101BaoHuDataProcess( rtumsg );
break;
// wen 2004.05.27 华东101规约修改点(???)
case 30: // 带CP56Time2a时标的单点信息 M_SP_TB_1
Buban101SoeDataProcessWithCP56Time2a( rtumsg, 0 );
break;
case 31: // 带CP56Time2a时标的双点信息 M_DP_TB_1
Buban101SoeDataProcessWithCP56Time2a( rtumsg, 1 );
break;
case 32: // 带CP56Time2a时标的步位置信息 M_ST_TB_1
break;
case 33: // 带CP56Time2a时标的32比特串 M_BO_TB_1
break;
case 34: // 带CP56Time2a时标的测量值, 规一化值 M_ME_TD_1
Buban101AiWithDataProcessWithM_ME_TD_1( rtumsg );
break;
case 35: // 带CP56Time2a时标的测量值, 标度化值 M_ME_TE_1
Buban101AiWithDataProcessWithM_ME_TE_1( rtumsg );
break;
case 36: // 带CP56Time2a时标的测量值, 短浮点数 M_ME_TF_1
Buban101AiWithDataProcessWithM_ME_TF_1( rtumsg );
break;
case 37: // 带CP56Time2a时标的累计量 M_IT_TB_1
Buban101PiWithTimeDataProcessWithM_IT_TB_1( rtumsg );
break;
case 38: // 带CP56Time2a时标的继电保护装置事件 M_EP_TD_1
break;
case 39: // 带CP56Time2a时标的继电保护装置成组启动事件 M_EP_TE_1
break;
case 40: // 带CP56Time2a时标的继电保拌装置成组输出电路信息M_EP_TF_1
break;
case 45:
case 46: // 遥控返校
case 47: // 遥调返校
Buban101YkYtAck( rtumsg );
break;
case 48: // 设定确认
Buban101SetAck( rtumsg );
break;
case 100: // 总召唤确认
Buban101InitdataProecss( rtumsg );
break;
case 101: // 电度结束帧
Buban101PidataEnd( rtumsg );
break;
case 103: // 时间同步确认帧
Buban101SynTime( rtumsg );
break;
default:
#ifdef _DEBUG_MSG_
DebugPrint("接收到不认识的命令,请检查程序.\n");
#endif
break;
}
}
/* Buban101 初始化数据处理 */
void Buban101InitdataProecss(RTUMSG * rtumsg)
{
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
switch(rtumsg->MsgData[8])
{
case 7:
case 9://总召唤确认
break;
case 10://总召唤结束
pPortParam->Initdata = TRUE;
break;
}
}
/* 电度结束帧 */
void Buban101PidataEnd(RTUMSG * rtumsg)
{
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if(rtumsg->MsgData[8] & 0x40)
{
pPortParam->Initdata = TRUE;
return;
}
switch(rtumsg->MsgData[8])
{
case 7://总召唤确认
break;
case 10://电度召唤结束
pPortParam->Initdata = TRUE;
break;
}
}
//设定确认
void Buban101SetAck( RTUMSG *rtumsg)
{
}
//Buban101 遥控遥调返校程序
void Buban101YkYtAck(RTUMSG * rtumsg)
{
int commid;
YKYT_PARAM YkYtParam;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
YkYtParam.m_iYkYtPnt = (rtumsg->MsgData[11]<<8) + rtumsg->MsgData[10];
YkYtParam.m_iYkYtPnt -= pPortParam->iYkBaseAddr;
YkYtParam.m_iYkYtPnt %= 256;
if(rtumsg->MsgData[12] & 0x80) //选择返校
{
YkYtParam.m_iYkYtStep = STEP_YKYT_SELECT;
//此位为肯定或否定确认位
if(rtumsg->MsgData[8] & 0x40)
{
YkYtParam.m_iYkYtOperate = 3;
}
else if(rtumsg->MsgData[8] == 0x07)
{
if(rtumsg->MsgData[6] != 45)
{
switch(rtumsg->MsgData[12] & 0x03)
{
case 1://控分
if(pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate == 2)
{
YkYtParam.m_iYkYtOperate = pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate;
}
else
{
YkYtParam.m_iYkYtOperate = 3;
}
break;
case 2://控合
if(pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate == 1)
{
YkYtParam.m_iYkYtOperate = pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate;
}
else
{
YkYtParam.m_iYkYtOperate = 3;
}
break;
default:
YkYtParam.m_iYkYtOperate = 3;
break;
}
}
else
{
// 控合
if( rtumsg->MsgData[12] & 0x01 )
{
if(pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate == 1)
{
YkYtParam.m_iYkYtOperate = pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate;
}
else
{
YkYtParam.m_iYkYtOperate = 3;
}
}
// 控分
else
{
if(pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate == 2)
{
YkYtParam.m_iYkYtOperate = pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate;
}
else
{
YkYtParam.m_iYkYtOperate = 3;
}
}
}
}
YkYtParam.m_iYkYtUpDown = YKYT_SEND_UP;
SendYkYtCommand2(commid, &YkYtParam);
}
else //执行并完成
{
//此位为肯定或否定确认位
if( ( rtumsg->MsgData[8] & 0x40 ) == 0 )
{
switch( rtumsg->MsgData[8] )
{
case 0x07://执行确认
break;
case 0x0a://执行完成
break;
default:
break;
}
}
}
}
/* Buban101 对时程序 */
void Buban101SynTime(RTUMSG * rtumsg)
{
int commid;
DAY_TIME stime;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if(1 != pPortParam->m_psBaoHu->CheckTime)
{
return;
}
if(rtumsg->MsgData[8] != 0x07)
return;
stime.mSec = (rtumsg->MsgData[13]<<8) + rtumsg->MsgData[12];
stime.Sec = stime.mSec / 1000;
stime.mSec %= 1000;
stime.Min = rtumsg->MsgData[14] & 0x3F;
stime.Hour = rtumsg->MsgData[15] & 0x1F;
stime.Day = rtumsg->MsgData[16] & 0x1F;
stime.Month= rtumsg->MsgData[17] & 0x0F;
stime.Year = (rtumsg->MsgData[18] & 0x7F)+2000;
SetLocalTimeEx(&stime);
}
/* 子站主动传送遥信变位帧 */
void Buban101AutoSendDiProcess(RTUMSG *rtumsg)
{
int i, j, dipnt, len;
DI_DEF pntmsg;
WORD wStatus, wStatusBit;
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
//从站主动上发 变化遥信
//if( ( rtumsg->MsgData[8] & 0x0f ) == 0x03 ) //东方电子继保所使用该报文(表示号20传送原因20)应答总召唤因此将此判断取消jessie in 2003.04.15
//{
// wen 2002.09.06 遥测遥信数据处理过长
//len -= 6;
//for ( i = 10; i < 10 + len; i += 7 )
for ( i = 10; i < 4 + len; i += 7 )
{
dipnt = rtumsg->MsgData[i+1];
dipnt = rtumsg->MsgData[i] + (dipnt<<8) - pPortParam->iDiBaseAddr;
wStatus = rtumsg->MsgData[i+3];
wStatus = (wStatus<<8) + rtumsg->MsgData[i+2];
wStatusBit = rtumsg->MsgData[i+5];
wStatusBit = (wStatusBit<<8) + rtumsg->MsgData[i+4];
for( j = 0; j < 16; j++ )
{
//张掖的变化检出状态为0故取消此判断 jessie in 2004.19
//if( wStatusBit & (0x0001 << j) )
//{
if( wStatus & (0x0001 << j) )
pntmsg.Status = 1;
else
pntmsg.Status = 0;
SetPntMsg(commid, dipnt+j, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS);
//}
}
}
// wen 2005.09.28 修改对主动上送数据的确认应答
// MakeBuban101Command(commid, ACK);
if(pPortParam->BalanceOrNot)
{
if((rtumsg->MsgData[4] & 0xc0) == 0xc0)
{
MakeBuban101Command(commid, ACK);
}
}
//}
}
// Buban101 带品质描述的遥测数据处理
void Buban101AiWithPzDataProcess(RTUMSG * rtumsg, int flag)
{
int i, aipnt, len;
AI_DEF pntmsg;
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
//处理变化遥测
if((rtumsg->MsgData[7] & 0x80)==0)
{
for ( i = 10; i < 4 + len; i += 5 )
{
aipnt = rtumsg->MsgData[i+1];
aipnt = (aipnt<<8) + rtumsg->MsgData[i] - pPortParam->iAiBaseAddr;
pntmsg.RawValue = rtumsg->MsgData[i+3];
pntmsg.RawValue = (pntmsg.RawValue<<8) + rtumsg->MsgData[i+2];
// 品质描述
// rtumsg->MsgData[i+4];
SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE);
// 时标
if(flag)
{
i += 3;
}
}
}
else// 处理遥测全数据
{
aipnt = rtumsg->MsgData[11];
aipnt = (aipnt<<8) + rtumsg->MsgData[10] - pPortParam->iAiBaseAddr;
if( len < 0 )
return;
for ( i = 12; i < len + 4; i+= 3 )
{
pntmsg.RawValue = rtumsg->MsgData[i+1];
pntmsg.RawValue = (pntmsg.RawValue<<8) + rtumsg->MsgData[i];
SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE);
aipnt++;
// 品质描述
// rtumsg->MsgData[i+2];
// 时标
if ( flag )
i += 3;
}
}
}
void Buban101AllAiDataProcess(RTUMSG *rtumsg)
{
int i, aipnt, len;
AI_DEF pntmsg;
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
aipnt = 0;
//处理变化遥测
if((rtumsg->MsgData[7] & 0x80)==0)
{
for ( i = 10; i < len + 4; i+= 4 )
{
aipnt = rtumsg->MsgData[i+1];
aipnt = (aipnt<<8) + rtumsg->MsgData[i] - pPortParam->iAiBaseAddr;
pntmsg.RawValue = rtumsg->MsgData[i+3];
pntmsg.RawValue = (pntmsg.RawValue<<8) + rtumsg->MsgData[i+2];
SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE);
}
return;
}
//处理全遥测
aipnt = rtumsg->MsgData[11];
aipnt = (aipnt<<8) + rtumsg->MsgData[10] - pPortParam->iAiBaseAddr;
if(len < 0)
{
return;
}
for ( i = 12; i < len + 4; i+= 2 )
{
pntmsg.RawValue = rtumsg->MsgData[i+1];
pntmsg.RawValue = (pntmsg.RawValue<<8) + rtumsg->MsgData[i];
SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE);
aipnt++;
}
}
void Buban101DiDataProcess(RTUMSG *rtumsg, int flag)
{
int i, dipnt, len;
DI_DEF pntmsg;
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
//从站主动上发 变化遥信
if( ( rtumsg->MsgData[8] & 0x0f ) == 0x03 )
{
for ( i = 10; i < 4 + len; i += 3 )
{
dipnt = rtumsg->MsgData[i+1];
dipnt = (dipnt<<8) + rtumsg->MsgData[i] - pPortParam->iDiBaseAddr;
if ( flag == 0 )
pntmsg.Status = rtumsg->MsgData[i+2] & 0x1;
else
{
switch ( rtumsg->MsgData[i+2] & 0x3 )
{
case 1:
pntmsg.Status = 1;
break;
case 2:
pntmsg.Status = 0;
break;
default:
pntmsg.Status = 0xff;
break;
}
}
if ( pntmsg.Status != 0xff )
{
SetPntMsg(commid, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS);
}
}
// wen 2005.09.28 修改对主动上送数据的确认应答
if(pPortParam->BalanceOrNot)
{
if((rtumsg->MsgData[4] & 0xc0) == 0xc0)
{
MakeBuban101Command(commid, ACK);
}
}
return;
}
if(rtumsg->MsgData[7] & 0x80)
{
dipnt = rtumsg->MsgData[11];
dipnt = (dipnt<<8) + rtumsg->MsgData[10] - pPortParam->iDiBaseAddr;
for ( i = 12; i < 4 + len; i++,dipnt++ )
{
if ( flag == 0 )
pntmsg.Status = rtumsg->MsgData[i] & 0x1;
else
{
switch ( rtumsg->MsgData[i] & 0x3 )
{
case 1:
pntmsg.Status = 1;
break;
case 2:
pntmsg.Status = 0;
break;
default:
pntmsg.Status = 0xff;
break;
}
}
if(pntmsg.Status != 0xff)
{
SetPntMsg(commid, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS);
}
}
}
else
{
for ( i = 10; i < 4 + len; i += 3 )
{
dipnt = rtumsg->MsgData[i+1];
dipnt = (dipnt<<8) + rtumsg->MsgData[i] - pPortParam->iDiBaseAddr;
if ( flag == 0 )
pntmsg.Status = rtumsg->MsgData[i+2] & 0x1;
else
{
switch ( rtumsg->MsgData[i+2] & 0x3 )
{
case 1:
pntmsg.Status = 1;
break;
case 2:
pntmsg.Status = 0;
break;
default:
pntmsg.Status = 0xff;
break;
}
}
if(pntmsg.Status != 0xff)
{
SetPntMsg(commid, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS);
}
}
}
}
void Buban101SoeDataProcess(RTUMSG *rtumsg, int flag)
{
_int64 i64Millseconds;
time_t iTime;
int i, pnt, len;
char st;
int sec;
DI_DEF pntmsg;
DAY_TIME sm;
struct tm *testtm;
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
for ( i = 10; i < len + 4; i += 6 )
{
pnt = rtumsg->MsgData[i+1];
pnt = (pnt<<8) + rtumsg->MsgData[i] - pPortParam->iDiBaseAddr;
if ( flag == 0 )
st = rtumsg->MsgData[i+2] & 0x01;
else
{
switch ( rtumsg->MsgData[i+2] & 0x3 )
{
case 1:
st = 1;
break;
case 2:
st = 0;
break;
default:
st = 0x0f;
break;
}
}
if ( st == 0x0f )
continue;
sec = rtumsg->MsgData[i+3] + ( rtumsg->MsgData[i+4] << 8 );
pntmsg.SoeTime.mSec = sec % 1000;
pntmsg.SoeTime.Sec = sec / 1000;
pntmsg.SoeTime.Min = (rtumsg->MsgData[i+5] & 0x3f); // 分
GetLocalTimeEx(&sm);
if(abs(pntmsg.SoeTime.Min-sm.Min) > 50)
{
i64Millseconds = SystemTimeToMillseconds(&sm, 0);
if(i64Millseconds > 0)
{
// 减去一小时
iTime = (long)(i64Millseconds/1000) - 3600;
testtm = localtime(&iTime);
sm.Year = testtm->tm_year + 1900;
sm.Month = testtm->tm_mon + 1;
sm.Day = testtm->tm_mday;
sm.Hour = testtm->tm_hour;
sm.Min = testtm->tm_min;
sm.Sec = testtm->tm_sec;
}
}
pntmsg.SoeTime.Hour = sm.Hour;
pntmsg.SoeTime.Day = sm.Day;
pntmsg.SoeTime.Month = sm.Month;
pntmsg.SoeTime.Year = sm.Year;
pntmsg.Status = st;
SetPntMsg(commid, pnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_SOE_TIME);
}
}
void Buban101PiDataProcess( RTUMSG * rtumsg )
{
int i, point, len;
PI_DEF pntmsg;
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
for(i = 10; i < 4 + len; i += 7)
{
point = rtumsg->MsgData[i+1];
point = (point<<8) + rtumsg->MsgData[i] - pPortParam->iPiBaseAddr;
pntmsg.RawValue = (rtumsg->MsgData[i+5]<<24) + (rtumsg->MsgData[i+4]<<16)
+ (rtumsg->MsgData[i+3]<<8) + rtumsg->MsgData[i+2];
SetPntMsg(commid, point, (void *)&pntmsg, PI_PNT_TYPE, PNT_RAWVALUE);
}
}
void Buban101PiWithTimeDataProcess( RTUMSG *rtumsg )
{
int i, point, len;
PI_DEF pntmsg;
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
for ( i = 10; i < 4 + len; i += 10 )
{
point = rtumsg->MsgData[i+1];
point = (point<<8) + rtumsg->MsgData[i] - pPortParam->iPiBaseAddr;
pntmsg.RawValue = (rtumsg->MsgData[i+5]<<24) + (rtumsg->MsgData[i+4]<<16)
+ (rtumsg->MsgData[i+3]<<8) + rtumsg->MsgData[i+2];
SetPntMsg(commid, point, (void *)&pntmsg, PI_PNT_TYPE, PNT_RAWVALUE);
}
}
void Buban101BaoHuDataProcess( RTUMSG *rtumsg )
{
// 该功能不做处理
}
void Buban101DefaultBaoHuDataProcess( RTUMSG *rtumsg )
{
// 该功能不做处理
}
// 新增函数,含有 7 BYTE 的时标
//***************************************************************
//* Buban101 SOE 数据处理(7 bytes 时间) *
//***************************************************************
void Buban101SoeDataProcessWithCP56Time2a( RTUMSG *rtumsg, int flag )
{
_int64 i64Millseconds;
time_t iTime;
int i, pnt, len;
char st;
int sec;
DI_DEF pntmsg;
DAY_TIME sm;
struct tm *testtm;
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
for ( i = 10; i < len + 4; i += 9 )
{
pnt = rtumsg->MsgData[i+1];
pnt = (pnt<<8) + rtumsg->MsgData[i] - pPortParam->iDiBaseAddr;
if(flag == 0)
{
st = rtumsg->MsgData[i+2] & 0x01;
}
else
{
switch ( rtumsg->MsgData[i+2] & 0x3 )
{
case 1:
st = 1;
break;
case 2:
st = 0;
break;
default:
st = 0x0f;
break;
}
}
if(st == 0x0f)
{
continue;
}
sec = rtumsg->MsgData[i+3] + (rtumsg->MsgData[i+4] << 8);
pntmsg.SoeTime.mSec = sec % 1000;
pntmsg.SoeTime.Sec = sec / 1000;
pntmsg.SoeTime.Min = (char)(rtumsg->MsgData[i+5] & 0x3f);
pntmsg.SoeTime.Hour = (char)(rtumsg->MsgData[i+6] & 0x1f);
pntmsg.SoeTime.Day = (char)(rtumsg->MsgData[i+7] & 0x1f);
GetLocalTimeEx(&sm);
if((pntmsg.SoeTime.Day-sm.Day) < 0)
{
i64Millseconds = SystemTimeToMillseconds(&sm, 0);
if(i64Millseconds > 0)
{
// 减去一小时
iTime = (long)(i64Millseconds/1000) - 3600;
testtm = localtime(&iTime);
sm.Year = testtm->tm_year + 1900;
sm.Month = testtm->tm_mon + 1;
sm.Day = testtm->tm_mday;
sm.Hour = testtm->tm_hour;
sm.Min = testtm->tm_min;
sm.Sec = testtm->tm_sec;
}
}
pntmsg.SoeTime.Month = sm.Month;
pntmsg.SoeTime.Year = sm.Year;
pntmsg.Status = st;
SetPntMsg(commid, pnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_SOE_TIME);
}
}
void Buban101AiWithDataProcessWithM_ME_TD_1(RTUMSG * rtumsg)
{
int i, aipnt, len;
AI_DEF pntmsg;
char szbuf[256];
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
//处理变化遥测
for(i = 10; i < 4 + len; i += 12)
{
if( ( i + 12 ) > (4 + len))
{
sprintf(szbuf, ">>>>>WARN(%04d): Commid_%02d (iLen=%d) is not enough in Buban101AiWithDataProcessWithM_ME_TD_1",
getpid(), commid, len);
DebugPrint(szbuf);
break;
}
aipnt = rtumsg->MsgData[i+1];
aipnt = (aipnt<<8) + rtumsg->MsgData[i] - pPortParam->iAiBaseAddr;
pntmsg.RawValue = rtumsg->MsgData[i+3];
pntmsg.RawValue = (pntmsg.RawValue<<8) + rtumsg->MsgData[i+2];
SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE);
// 7字节时标
}
}
void Buban101AiWithDataProcessWithM_ME_TE_1(RTUMSG * rtumsg)
{
Buban101AiWithDataProcessWithM_ME_TD_1(rtumsg);
}
void Buban101AiWithDataProcessWithM_ME_TF_1(RTUMSG * rtumsg)
{
int i, aipnt, len;
AI_DEF pntmsg;
char szbuf[256];
float fValue;
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
//处理变化遥测
for ( i = 10; i < 4 + len; i += 14 )
{
if( ( i + 14 ) > (4 + len))
{
sprintf(szbuf, ">>>>>WARN(%04d): Commid_%02d (iLen=%d) is not enough in Buban101AiWithDataProcessWithM_ME_TF_1",
getpid(), commid, len);
DebugPrint(szbuf);
break;
}
aipnt = rtumsg->MsgData[i+1];
aipnt = (aipnt<<8) + rtumsg->MsgData[i] - pPortParam->iAiBaseAddr;
fValue = *((float *)&rtumsg->MsgData[i+2]);
SequenceRtuToHost((char *)&fValue, sizeof(float));
// 品质描述
// rtumsg->MsgData[i+6];
// 保留2位小数
pntmsg.RawValue = (int)(fValue * 100);
SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE);
// 7字节时标
}
}
//Buban101 电度数据处理with time
void Buban101PiWithTimeDataProcessWithM_IT_TB_1(RTUMSG *rtumsg)
{
int i, point, len;
AI_DEF pntmsg;
char szbuf[256];
int commid;
BUBAN101PORTPARAM *pPortParam;
commid = rtumsg->PortIdx;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
len = (int)rtumsg->MsgData[1];
for(i = 10; i < 4 + len; i += 14)
{
if( ( i + 14 ) > (4 + len))
{
sprintf(szbuf, ">>>>>WARN(%04d): Commid_%02d (iLen=%d) is not enough in Buban101PiWithTimeDataProcessWithM_IT_TB_1",
getpid(), commid, len);
DebugPrint(szbuf);
break;
}
point = rtumsg->MsgData[i+1];
point = (point<<8) + rtumsg->MsgData[i] - pPortParam->iPiBaseAddr;
pntmsg.RawValue = (rtumsg->MsgData[i+5]<<24) + (rtumsg->MsgData[i+4]<<16)
+ (rtumsg->MsgData[i+3]<<8) + rtumsg->MsgData[i+2];
SetPntMsg(commid, point, (void *)&pntmsg, PI_PNT_TYPE, PNT_RAWVALUE);
// 1 BYTE (IV CA CY 顺序号)
// 7 BYTE 时标
}
}
//=========================以下为Buban101转发数据功能=======================//
void ProvBuban101dataProcess(int commid, RTUMSG *rtumsg)
{
// 数据校验错误( 附加字节的第二个字节)
if(rtumsg->MsgData[rtumsg->MsgLen+1] > 0)
{
return;
}
switch(rtumsg->MsgData[0])
{
case 0x68:
ProvBuban101longprocess(commid, rtumsg);
break;
case 0x10://shortframe process
ProvBuban101shortprocess(commid, rtumsg);
break;
default:
break;
}
}
void ProvBuban101shortprocess(int commid, RTUMSG * rtumsg)
{
int framecnt = 0;
BUBAN101PORTPARAM *pPortParam;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
//主站被动发送
if((rtumsg->MsgData[1] & 0xc0) == 0x00)
{
switch(rtumsg->MsgData[1] & 0x0f)
{
case 0x0b://回答链路状态(链路完好)
ProvMakeBuban101Command(commid, RST_LINK);
break;
case 0x00://链路确认
if(pPortParam->RstLinkOk)
{
pPortParam->LinkOk = TRUE;
}
// wen 2005.09.13 链路的确认帧不需要有应答
//ProvMakeBuban101Command(commid, ACK);
break;
default:
break;
}
return;
}
switch(rtumsg->MsgData[1] & 0x0f)
{
case 0x09://链路状态请求
ProvMakeBuban101Command(commid, ANS_LINK);
break;
case 0x00://复位链路
if(pPortParam->BalanceOrNot==0)
{
pPortParam->LinkOk = TRUE;
pPortParam->RstLinkOk = TRUE;
ProvMakeBuban101Command(commid, ACK);
}
else
{
pPortParam->LinkOk = FALSE;
pPortParam->RstLinkOk = TRUE;
ProvMakeBuban101Command(commid, ACK);
//ProvMakeBuban101Command(commid, RST_LINK);
ProvMakeBuban101Command(commid, ASK_LINK);
}
break;
case 0x0a://召唤一级数据
if(pPortParam->LinkOk)
{
ProvMakeBuban101Command(commid, ASK_FIRST_DATA);
}
break;
case 0x0b://召唤二级数据
if(pPortParam->LinkOk)
{
ProvMakeBuban101Command(commid, ASK_SECOND_DATA);
}
break;
default:
break;
}
}
void ProvBuban101longprocess(int commid, RTUMSG * rtumsg)
{
if((rtumsg->MsgData[4] & 0xc0) != 0x40)
{
ProvMakeBuban101Command(commid, ASK_DATA_NO);
}
switch(rtumsg->MsgData[6])
{
case 1: // 单点遥信处理
break;
case 2: // 单点遥信SOE处理
break;
case 3: // 双点遥信处理
break;
case 4: // 单点遥信SOE处理
break;
case 5: // 变压器分接头位置
break;
case 6: // 变压器分接头位置带时标
break;
case 7: // 子站远动终端状态
break;
case 9: // 带品质无时标遥测
break;
case 10: // 带品质带时标遥测
break;
case 21: // 全遥测数据处理 或变化数据
break;
case 15: // 不带时标电度
break;
case 16: // 带时标电度
break;
case 17:
case 18:
case 19: // 保护数据
break;
case 46: // 遥控返校
case 47: // 遥调返校
ProvBuban101YkYtData(commid, rtumsg);
break;
case 100: // 召唤数据
ProvBuban101SendAllData(commid, rtumsg);
break;
case 101: // 召唤电度
ProvBuban101SendPIData(commid, rtumsg);
break;
case 103: // 时间同步确认帧
ProvBuban101ProcessTime(commid, rtumsg);
break;
}
}
//响应分组召唤和总召唤
//总召唤确认(传送原因[8]=0x07,0x09确认; =0x0a 总召唤结束)
void ProvBuban101SendAllData(int commid, RTUMSG * rtumsg)
{
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
int iGroup;
BUBAN101PORTPARAM *pPortParam;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
//分组召唤
if(rtumsg->MsgData[12] != 20)
{
iGroup = rtumsg->MsgData[12] - 20;
//无效组号
if( ( iGroup <= 0 ) || ( iGroup > 12 ) )
{
ProvMakeBuban101Command(commid, ASK_DATA_NO);
return;
}
if(iGroup > 8)
{
iGroup -= 8;
ProvBuban101SendAI(commid, rtumsg, iGroup);
}
else
ProvBuban101SendDI(commid, rtumsg, iGroup);
return;
}
//总召唤
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x00;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 100;
commandbuf[7] = 0;
switch(rtumsg->MsgData[8])
{
case 0x06://激活
commandbuf[8] = 7;
break;
case 0x08://停止激活
default:
commandbuf[8] = 9;
break;
}
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
commandbuf[12] = 0x14;
commandbuf[13] = CalBuban101Lpc(&commandbuf[4], 9);
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 15);
if(rtumsg->MsgData[8] != 0x06)
return;
ProvBuban101SendAI(commid, rtumsg, 0);
ProvBuban101SendDI(commid, rtumsg, 0);
//总召唤结束
ProvMakeBuban101Command(commid, ASK_ALLDATA_END);
pPortParam->m_psBaoHu->DiChange = FALSE;
}
void ProvBuban101SendPIData(int commid, RTUMSG * rtumsg)
{
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
int iGroup = rtumsg->MsgData[12] & 0x3F;
BUBAN101PORTPARAM *pPortParam;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
/*switch((rtumsg->MsgData[12]&0xc0)>>6)
{
case 0x00://无效指令格式
break;
case 0x01://冻结不复位
break;
case 0x02://冻结复位
break;
case 0x03://电能计数器复位
break;
}*/
//分组召唤
if( iGroup != 1 )
{
//无效或者扩展组号
if(( iGroup <= 0 ) || ( iGroup > 5 ))
{
ProvMakeBuban101Command(commid, ASK_DATA_NO);
return;
}
ProvBuban101SendPI(commid, rtumsg, iGroup-1);
return;
}
//总召唤确认
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x00;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 101;
commandbuf[7] = 0;
commandbuf[8] = 7;
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
commandbuf[12] = rtumsg->MsgData[12];
commandbuf[13] = CalBuban101Lpc(&commandbuf[4], 9);
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 15);
ProvBuban101SendPI(commid, rtumsg, 0);
//总召唤结束
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x80;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 101;
commandbuf[7] = 0;
commandbuf[8] = 10;
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
commandbuf[12] = rtumsg->MsgData[12];
commandbuf[13] = CalBuban101Lpc(&commandbuf[4], 9);
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 15);
}
void ProvBuban101ProcessTime(int commid, RTUMSG *rtumsg)
{
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
BUBAN101PORTPARAM *pPortParam;
DAY_TIME sCurTime;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
//传送原因
switch(rtumsg->MsgData[8])
{
case 0x06://激活(对时)
commandbuf[0] = 0x68;
commandbuf[1] = 15;
commandbuf[2] = 15;
commandbuf[3] = 0x68;
commandbuf[4] = 0x53;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 103;
commandbuf[7] = 1;
commandbuf[8] = 7;
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
memcpy(commandbuf+12, rtumsg->MsgData+12, 7);
commandbuf[19] = CalBuban101Lpc(&commandbuf[4], commandbuf[1]);
commandbuf[20] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 21);
// wen 2006.03.29 增加对时
if(1 == pPortParam->m_psBaoHu->CheckTime)
{
sCurTime.mSec = rtumsg->MsgData[12] + (rtumsg->MsgData[13] << 8);
sCurTime.Sec = sCurTime.mSec/1000;
sCurTime.mSec = sCurTime.mSec % 1000;
sCurTime.Min = rtumsg->MsgData[14] & 0x3F;
sCurTime.Hour = rtumsg->MsgData[15] & 0x1F;
sCurTime.Day = rtumsg->MsgData[16] & 0x1F;
sCurTime.Month= rtumsg->MsgData[17] & 0x0F;
sCurTime.Year = (rtumsg->MsgData[18] & 0x7F)+2000;
SetLocalTimeEx(&sCurTime);
}
break;
case 0x07://激活确认
break;
}
}
void ProvBuban101SendPI(int commid, RTUMSG *rtumsg, int iGroupNo)
{
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
WORD wStartAddr;
int iLenth, iSendCount=1;
int i, j, iAllDataCount, iSendNum;
int iNo;
PI_DEF pntmsg;
PROV_PI_PNT *piprovptr;
BUBAN101PORTPARAM *pPortParam;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if(iGroupNo == 0)//总召唤
{
wStartAddr = MAX_GROUP_PINUM*iGroupNo + pPortParam->iPiBaseAddr;
iAllDataCount = pPortParam->m_psBaoHu->PiNum;
iSendCount = (iAllDataCount+MAX_PINUM-1)/MAX_PINUM;
}
else//分组召唤
{
wStartAddr = MAX_GROUP_PINUM*(iGroupNo-1);
iAllDataCount = pPortParam->m_psBaoHu->PiNum - wStartAddr;
wStartAddr += pPortParam->iPiBaseAddr;
if( iAllDataCount > MAX_GROUP_PINUM)
{
iSendCount = 2;
if((iAllDataCount - MAX_GROUP_PINUM)>0)
iAllDataCount = MAX_GROUP_PINUM;
}
}
piprovptr = (PROV_PI_PNT *)pPortParam->m_psBaoHu->PiPtr;
for(i = 0; i < iSendCount; i++)
{
commandbuf[0] = 0x68;
commandbuf[3] = 0x68;
commandbuf[4] = 0x08;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 15;
commandbuf[8] = 37+iGroupNo;
commandbuf[9] = pPortParam->LinkAddr;
//遥测值
if(iAllDataCount>MAX_PINUM)
{
iAllDataCount -= MAX_PINUM;
iSendNum = MAX_PINUM;
}
else
{
iSendNum = iAllDataCount;
}
for(j = 0, iLenth = 10; j < iSendNum; j++, wStartAddr++)
{
commandbuf[iLenth++] = (char)(wStartAddr &0x00ff);
commandbuf[iLenth++] = (char)((wStartAddr &0xff00)>>8);
iNo = wStartAddr - pPortParam->iPiBaseAddr;
pntmsg.RawValue = 0;
GetPntMsg(piprovptr[iNo].PortNo, piprovptr[iNo].PntNo,
(void *)&pntmsg, PI_PNT_TYPE, PNT_RAWVALUE);
piprovptr[iNo].ChangeFlag = FALSE;
commandbuf[iLenth++] = (char)(pntmsg.RawValue & 0x000000ff);
commandbuf[iLenth++] = (char)((pntmsg.RawValue & 0x0000ff00)>>8);
commandbuf[iLenth++] = (char)((pntmsg.RawValue & 0x00ff0000)>>16);
commandbuf[iLenth++] = (char)((pntmsg.RawValue & 0xff000000)>>24);
commandbuf[iLenth++] = (char)(j+1);
}
commandbuf[7] = (BYTE)j;
commandbuf[1] = (char)(iLenth-4);
commandbuf[2] = commandbuf[1];
commandbuf[iLenth++] = CalBuban101Lpc(&commandbuf[4], commandbuf[1]);
commandbuf[iLenth++] = 0x16;
if(iGroupNo != 0)
{
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, iLenth);
}
else
{
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, iLenth);
}
}
}
void ProvBuban101SendAI(int commid, RTUMSG *rtumsg, int iGroupNo)
{
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
WORD wStartAddr;
int iLenth, iSendCount=1;
int i, j, iAllDataCount, iSendNum;
int iNo;
AI_DEF pntmsg;
PROV_AI_PNT *aiprovptr;
BUBAN101PORTPARAM *pPortParam;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if( iGroupNo == 0 )//总召唤
{
wStartAddr = MAX_GROUP_AINUM*iGroupNo + pPortParam->iAiBaseAddr;
iAllDataCount = pPortParam->m_psBaoHu->AiNum;
iSendCount = (iAllDataCount+MAX_AINUM-1)/MAX_AINUM;
}
else//分组召唤
{
wStartAddr = MAX_GROUP_AINUM*(iGroupNo-1);
iAllDataCount = pPortParam->m_psBaoHu->AiNum - wStartAddr;
wStartAddr += pPortParam->iAiBaseAddr;
if(iAllDataCount > MAX_AINUM)
{
iSendCount = 2;
if((iAllDataCount - MAX_GROUP_AINUM) > 0)
{
iAllDataCount = MAX_GROUP_AINUM;
}
}
}
aiprovptr = (PROV_AI_PNT *)pPortParam->m_psBaoHu->AiPtr;
for( i = 0; i < iSendCount; i++ )
{
commandbuf[0] = 0x68;
commandbuf[3] = 0x68;
commandbuf[4] = 0x08;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 21;
commandbuf[8] = rtumsg->MsgData[12];
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = (char)(wStartAddr);
commandbuf[11] = (char)((wStartAddr&0xff00)>>8);
//遥测值
if(iAllDataCount > MAX_AINUM)
{
iAllDataCount -= MAX_AINUM;
iSendNum = MAX_AINUM;
}
else
{
iSendNum = iAllDataCount;
}
iNo = wStartAddr - pPortParam->iAiBaseAddr;
for(j = 0, iLenth = 12; j < iSendNum; j++)
{
GetPntMsg(aiprovptr[iNo+j].PortNo, aiprovptr[iNo+j].PntNo,
&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE);
aiprovptr[iNo+j].ChangeFlag = FALSE;
commandbuf[iLenth++] = (char)(pntmsg.RawValue);
commandbuf[iLenth++] = (char)((pntmsg.RawValue&0xff00)>>8);
}
commandbuf[7] = (BYTE)j;
commandbuf[7] |= 0x80;
commandbuf[1] = commandbuf[2] = (char)(iLenth-4);
commandbuf[iLenth++] = CalBuban101Lpc( &commandbuf[4], commandbuf[1]);
commandbuf[iLenth++] = 0x16;
if(iGroupNo != 0)
{
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, iLenth);
}
else
{
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, iLenth);
}
wStartAddr += MAX_AINUM;
}
}
void ProvBuban101SendDI(int commid, RTUMSG *rtumsg, int iGroupNo)
{
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
WORD wStartAddr;
int iLenth, iSendCount=1;
int i, j, iAllDataCount, iSendNum;
int iNo;
DI_DEF pntmsg;
PROV_DI_PNT *diprovptr;
BUBAN101PORTPARAM *pPortParam;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if(iGroupNo == 0)//总召唤
{
wStartAddr = MAX_GROUP_DINUM*iGroupNo + pPortParam->iDiBaseAddr;
iAllDataCount = pPortParam->m_psBaoHu->DiNum;
iSendCount = (iAllDataCount+MAX_DINUM-1)/MAX_DINUM;
}
else//分组召唤
{
wStartAddr = MAX_GROUP_DINUM*(iGroupNo-1);
iAllDataCount = pPortParam->m_psBaoHu->DiNum - wStartAddr;
wStartAddr += pPortParam->iDiBaseAddr;
if( iAllDataCount > MAX_GROUP_DINUM)
{
iAllDataCount = MAX_GROUP_DINUM;
}
}
diprovptr = (PROV_DI_PNT *)pPortParam->m_psBaoHu->DiPtr;
for(i=0; i<iSendCount; i++)
{
commandbuf[0] = 0x68;
commandbuf[3] = 0x68;
commandbuf[4] = 0x08;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 1;//=3,为双点
commandbuf[8] = rtumsg->MsgData[12];
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = (char)(wStartAddr);
commandbuf[11] = (char)((wStartAddr&0xff00)>>8);
if(iAllDataCount > MAX_DINUM)
{
iAllDataCount -= MAX_DINUM;
iSendNum = MAX_DINUM;
}
else
{
iSendNum = iAllDataCount;
}
iNo = wStartAddr - pPortParam->iDiBaseAddr;
for( j = 0, iLenth = 12; j < iSendNum; j++ )
{
GetPntMsg(diprovptr[iNo+j].PortNo, diprovptr[iNo+j].PntNo,
&pntmsg, DI_PNT_TYPE, PNT_STATUS);
diprovptr[iNo+j].ChangeFlag = FALSE;
commandbuf[iLenth++] = pntmsg.Status;
}
commandbuf[7] = (char)j;
commandbuf[7] |= 0x80;
commandbuf[1] = (char)(iLenth-4);
commandbuf[2] = commandbuf[1];
commandbuf[iLenth++] = CalBuban101Lpc( &commandbuf[4], commandbuf[1]);
commandbuf[iLenth++] = 0x16;
if(iGroupNo != 0)
{
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, iLenth);
}
else
{
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, iLenth);
}
wStartAddr += MAX_DINUM;
}
}
void ProvBuban101YkYtData(int commid, RTUMSG *rtumsg)
{
PROV_DI_PNT *diprovptr;
DI_DEF *diptr;
int ykytcommid, provpnt;
int ykytpnt, ykytop, step;
YKYT_PARAM YkYtParam;
BUBAN101PORTPARAM *pPortParam;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
if(rtumsg->MsgData[8] == 8)
{
step = STEP_YKYT_CANCEL;
}
else
{
if(rtumsg->MsgData[12] & 0x80) //选择返校
{
step = STEP_YKYT_SELECT;
}
else
{
step = STEP_YKYT_EXEC;
}
}
ykytpnt = 0;
ykytop = 3;
if(ShmGetDispYkYtFlag())
{
printf("TIP_(%04d): commid =%d recv ykyt select.\n", getpid(), commid);
}
ykytpnt = (rtumsg->MsgData[11]<<8) + rtumsg->MsgData[10];
ykytpnt -= pPortParam->iYkBaseAddr;
ykytpnt += 1;
//ykytop = ((rtumsg->MsgData[12] & 0x03) == 1) ? 2 : 1;
if(rtumsg->MsgData[6] == 45)
{
// ykytop == 1 控合, == 2 控分
ykytop = ((rtumsg->MsgData[12] & 0x03) == 1) ? 1 : 2;
}
else if(rtumsg->MsgData[6] == 46)
{
ykytop = ((rtumsg->MsgData[12] & 0x03) == 2) ? 1 : 2;
}
else // == 47
{
//step = STEP_YKYT_CANCEL;
MakeProvBuban101YkYtAckMsg(commid, ykytpnt, 3, step);
return;
}
provpnt = FindProvPntFromYkYtPnt(commid, ykytpnt, pPortParam->m_psBaoHu);
if(provpnt < 0) // 控点号错
{
MakeProvBuban101YkYtAckMsg(commid, ykytpnt, 3, step);
}
else
{
diprovptr = (PROV_DI_PNT *)pPortParam->m_psBaoHu->DiPtr;
ykytcommid = diprovptr[provpnt].PortNo;
if(!SioParam[ykytcommid].m_psBaoHu)
{
MakeProvBuban101YkYtAckMsg(commid, ykytpnt, 3, step);
return;
}
if(!SioParam[ykytcommid].m_psBaoHu->DiPtr)
{
MakeProvBuban101YkYtAckMsg(commid, ykytpnt, 3, step);
return;
}
diptr = (DI_DEF *)SioParam[ykytcommid].m_psBaoHu->DiPtr;
// 如果对应点没有控点或者控点不相等
if(!diptr[diprovptr[provpnt].PntNo].CtrlEnable)
{
MakeProvBuban101YkYtAckMsg(commid, ykytpnt, 3, step);
return;
}
if(STEP_YKYT_SELECT == step)
{
if(STEP_YKYT_SELECT == SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iYkYtStep)
{
if(!ProvPortYkYtIsTimeOut(ykytcommid, &SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg))
{
MakeProvBuban101YkYtAckMsg(commid, ykytpnt, 3, step);
return;
}
}
}
SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iProvPntIdx = provpnt;
SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iProvPortIdx = commid;
SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iProvYkYtPointIdx = ykytpnt;
SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iYkYtPointIdx = diptr[diprovptr[provpnt].PntNo].ControlNo;
SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate = ykytop;
// buf[0] --- 端口号(=commid)
// buf[1]
// buf[2]
// buf[3]
// buf[4] --- 控点号
// buf[5]
// buf[6]
// buf[7]
// buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控;
// 遥调:4=选择,5=执行,6=取消,8=急停)
// buf[9] --- 控制状态(1=分到合2=合到分)
// (最高位为1时为返校命令, 1=成功, 0=失败)
//buf[0] = ykytcommid & 0xFF;
//buf[1] = (ykytcommid & 0xFF00) >> 8;
//buf[2] = (ykytcommid & 0xFF0000) >> 16;
//buf[3] = (ykytcommid & 0xFF000000) >> 24;
//buf[4] = diptr[diprovptr[provpnt].PntNo].ControlNo & 0xFF;
//buf[5] = (diptr[diprovptr[provpnt].PntNo].ControlNo & 0xFF00) >> 8;
//buf[6] = (diptr[diprovptr[provpnt].PntNo].ControlNo & 0xFF0000) >> 16;
//buf[7] = (diptr[diprovptr[provpnt].PntNo].ControlNo & 0xFF000000) >> 24;
//buf[8] = STEP_YKYT_SELECT;
//buf[9] = ykytop;
//SendYkYtCommand(ykytcommid, (char *)buf, 10); // 发送遥控遥调命令
YkYtParam.m_iYkYtOperate = ykytop;
YkYtParam.m_iYkYtPnt = diptr[diprovptr[provpnt].PntNo].ControlNo;
YkYtParam.m_iYkYtStep = step;
YkYtParam.m_iYkYtUpDown = YKYT_SEND_DOWN;
SendYkYtCommand2(ykytcommid, &YkYtParam);
if(STEP_YKYT_EXEC == step)
{
MakeProvBuban101YkYtAckMsg(commid, ykytpnt, ykytop, step);
MakeProvBuban101YkYtAckMsg(commid, ykytpnt, ykytop, STEP_YKYT_NOEXEC);
}
}
}
void MakeProvBuban101YkYtAckMsg(int commid, int pnt, int op, int step)
{
int iCount;
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
BUBAN101PORTPARAM *pPortParam;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
memset(commandbuf, 0, sizeof(commandbuf));
iCount = 4;
commandbuf[0] = 0x68;
commandbuf[1] = 0x09;
commandbuf[2] = 0x09;
commandbuf[3] = 0x68;
commandbuf[4] = 0x80;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 46;/*47*/
commandbuf[7] = 1;
// DCS/RCS
switch(op)
{
case 1: // 选择合
commandbuf[12] = 2;
break;
case 2: // 选择分
commandbuf[12] = 1;
break;
case 3: // 选择失败
default:
commandbuf[8] = 0x40;
commandbuf[12] = 0;
break;
}
// 传送原因
if(STEP_YKYT_SELECT == step)
{
commandbuf[8] |= 7;
// DCS/RCS
commandbuf[12] |= 0x80;
}
else if(STEP_YKYT_EXEC == step)
{
commandbuf[8] |= 7;
}
else if(STEP_YKYT_CANCEL == step)
{
commandbuf[8] |= 9;
// DCS/RCS
commandbuf[12] |= 0x80;
}
else// 结束帧
{
commandbuf[8] = 10;
}
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = LOBYTE((WORD)(pnt+pPortParam->iYkBaseAddr));
commandbuf[11] = HIBYTE((WORD)(pnt+pPortParam->iYkBaseAddr));
commandbuf[13] = CalBuban101Lpc(&commandbuf[4], commandbuf[1]);
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 15);
if(ShmGetDispYkYtFlag())
{
printf("TIP_(%04d): commid =%d ykytpnt=%d, op=%d checked.\n", getpid(), commid, pnt, op);
}
}
void ProvBuban101SendClass1(int commid)
{
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
WORD wStartAddr;
int iLenth, iSendCount=1;
int j, iDataNum;
DI_DEF pntmsg;
PROV_DI_PNT *diprovptr;
BUBAN101PORTPARAM *pPortParam;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
// wen 2005.01.15 修改数据信息体起始地址
wStartAddr = pPortParam->iDiBaseAddr;
commandbuf[0] = 0x68;
commandbuf[3] = 0x68;
//commandbuf[4] = 0x08;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 1;//=3,为双点
//commandbuf[8] = 3;
commandbuf[8] = 5;// 应该为被请求数据,而不是突发数据
commandbuf[9] = pPortParam->LinkAddr;
diprovptr = (PROV_DI_PNT *)pPortParam->m_psBaoHu->DiPtr;
for(j = 0, iDataNum = 0, iLenth = 10; j < pPortParam->m_psBaoHu->DiNum; j++)
{
if(diprovptr[j].ChangeFlag)
{
iDataNum++;
commandbuf[iLenth++] = (char)(wStartAddr+j);
commandbuf[iLenth++] = (char)((wStartAddr+j)>>8);
GetPntMsg(diprovptr[j].PortNo, diprovptr[j].PntNo,
&pntmsg, DI_PNT_TYPE, PNT_STATUS);
diprovptr[j].ChangeFlag = FALSE;
commandbuf[iLenth++] = pntmsg.Status;
if(iLenth > 256)
{
break;
}
}
}
if(j >= pPortParam->m_psBaoHu->DiNum)
{
pPortParam->m_psBaoHu->DiChange = FALSE;
}
if(pPortParam->m_psBaoHu->DiChange)
{
commandbuf[4] = 0x28;
}
else
{
commandbuf[4] = 0x08;
}
commandbuf[7] = (char)iDataNum;
commandbuf[1] = (char)(iLenth-4);
commandbuf[2] = commandbuf[1];
commandbuf[iLenth++] = CalBuban101Lpc( &commandbuf[4], commandbuf[1]);
commandbuf[iLenth++] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, iLenth);
}
void ProvBuban101SendClass2(int commid)
{
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
BOOL bHaveData = FALSE;
WORD wStartAddr, wmSec;
int iLenth;
int j, iDataNum;
AI_DEF pntmsg;
SOE_DEF soemsg;
PROV_AI_PNT *aiprovptr;
BUBAN101PORTPARAM *pPortParam;
iDataNum = 0;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
commandbuf[0] = 0x68;
commandbuf[3] = 0x68;
if(pPortParam->m_psBaoHu->DiChange)
{
commandbuf[4] = 0x28;
}
else
{
commandbuf[4] = 0x08;
}
commandbuf[5] = pPortParam->LinkAddr;
//commandbuf[8] = 3;
commandbuf[8] = 5;
commandbuf[9] = pPortParam->LinkAddr;
//SOE 数据
if(ProvHaveSoeData(commid) > 0)
{
// 单点
commandbuf[6] = 2;
bHaveData = TRUE;
iLenth = 10;
// wen 2005.01.15 修改数据信息体起始地址
wStartAddr = pPortParam->iDiBaseAddr;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// wen 2006.07.12 修改soe为单个时数据丢失的问题.
/*
while(ProvAndDelGetSoeData(commid, &soemsg) > 0)
{
iDataNum++;
commandbuf[iLenth++] = (char)(wStartAddr+soemsg.iPntNo);
commandbuf[iLenth++] = (char)((wStartAddr+soemsg.iPntNo)>>8);
commandbuf[iLenth++] = soemsg.bStatus;
wmSec = soemsg.SoeTime.mSec + soemsg.SoeTime.Sec*1000;
commandbuf[iLenth++] = LOBYTE(wmSec);
commandbuf[iLenth++] = HIBYTE(wmSec);
commandbuf[iLenth++] = soemsg.SoeTime.Min;
if(iLenth >= 255)
{
break;
}
}
*/
//===========================================================
while(ProvHaveSoeData(commid) > 0)
{
ProvAndDelGetSoeData(commid, &soemsg);
iDataNum++;
commandbuf[iLenth++] = (char)(wStartAddr+soemsg.iPntNo);
commandbuf[iLenth++] = (char)((wStartAddr+soemsg.iPntNo)>>8);
commandbuf[iLenth++] = soemsg.bStatus;
wmSec = soemsg.SoeTime.mSec + soemsg.SoeTime.Sec*1000;
commandbuf[iLenth++] = LOBYTE(wmSec);
commandbuf[iLenth++] = HIBYTE(wmSec);
commandbuf[iLenth++] = soemsg.SoeTime.Min;
if(iLenth >= 255)
{
break;
}
};
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
}
else
{
// wen 2005.01.15 修改数据信息体起始地址
wStartAddr = pPortParam->iAiBaseAddr;
commandbuf[6] = 21;
//遥测值
aiprovptr = (PROV_AI_PNT *)pPortParam->m_psBaoHu->AiPtr;
for(j = 0, iDataNum = 0, iLenth = 10; j < pPortParam->m_psBaoHu->AiNum; j++)
{
if(aiprovptr[j].ChangeFlag)
{
iDataNum++;
bHaveData = TRUE;
commandbuf[iLenth++] = (char)(wStartAddr+j);
commandbuf[iLenth++] = (char)((wStartAddr+j)>>8);
GetPntMsg(aiprovptr[j].PortNo, aiprovptr[j].PntNo,
&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE);
aiprovptr[j].ChangeFlag = FALSE;
commandbuf[iLenth++] = (char)(pntmsg.RawValue);
commandbuf[iLenth++] = (char)((pntmsg.RawValue&0xff00)>>8);
if(iLenth >= 255)
{
break;
}
}
}
}
if(bHaveData)
{
commandbuf[7] = (char)iDataNum;
commandbuf[1] = (char)(iLenth-4);
commandbuf[2] = commandbuf[1];
commandbuf[iLenth++] = CalBuban101Lpc( &commandbuf[4], commandbuf[1]);
commandbuf[iLenth++] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, iLenth);
}
else
{
if(pPortParam->m_psBaoHu->DiChange)
{
commandbuf[0] = 0x10;
commandbuf[1] = 0x29;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[3] = CalBuban101Lpc(&commandbuf[1], 2);
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 5);
}
else
{
commandbuf[0] = 0xE5;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 1);
}
}
}
void ProvMakeBuban101Command(int commid, u_char cmdidx)
{
u_char commandbuf[MAX_POLLCMD_BUF_LEN];
BUBAN101PORTPARAM *pPortParam;
pPortParam = (BUBAN101PORTPARAM *)SioParam[commid].ExtInfo;
switch(cmdidx)
{
case ASK_LINK: // 请求链路
commandbuf[0] = 0x10;
commandbuf[1] = 0xc9;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[3] = CalBuban101Lpc(&commandbuf[1], 2);
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 5);
break;
case RST_LINK: // 复位链路
commandbuf[0] = 0x10;
commandbuf[1] = 0xc0;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[3] = CalBuban101Lpc(&commandbuf[1], 2);
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 5);
break;
case ASK_SECOND_DATA: // 召唤2级数据
ProvBuban101SendClass2(commid);
break;
case ASK_FIRST_DATA: // 召唤1级数据
ProvBuban101SendClass1(commid);
break;
case ACK: // 确认回答
commandbuf[0] = 0x10;
commandbuf[1] = 0x00;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[3] = CalBuban101Lpc(&commandbuf[1], 2);
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 5);
break;
case ANS_LINK: // 回答链路状态
commandbuf[0] = 0x10;
commandbuf[1] = 0x0b;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[3] = CalBuban101Lpc(&commandbuf[1], 2);
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 5);
break;
case ASK_DATA_NO: // 无所请求的数据
commandbuf[0] = 0x10;
commandbuf[1] = 0x09;
commandbuf[2] = pPortParam->LinkAddr;
commandbuf[3] = CalBuban101Lpc(&commandbuf[1], 2);
commandbuf[4] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 5);
break;
case ASK_ALLDATA_END: // 总召唤结束帧
commandbuf[0] = 0x68;
commandbuf[1] = 9;
commandbuf[2] = 9;
commandbuf[3] = 0x68;
commandbuf[4] = 0x08;
commandbuf[5] = pPortParam->LinkAddr;
commandbuf[6] = 100;
commandbuf[7] = 1;
commandbuf[8] = 10;
commandbuf[9] = pPortParam->LinkAddr;
commandbuf[10] = 0;
commandbuf[11] = 0;
commandbuf[12] = 0x14;
commandbuf[13] = CalBuban101Lpc(&commandbuf[4], 9);
commandbuf[14] = 0x16;
PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, 15);
break;
case RTU_TIME: // 时间同步
break;
case ASK_DI_DATA: // 召唤2级数据YX
break;
case ASK_AI_DATA: // 召唤2级数据YC
break;
case ASK_PI_DATA: // 召唤2级数据YM
break;
case ASK_PI: //召唤电度量
break;
case ASK_ALL_DATA: // 召唤初始化数据
break;
}
}
//===========================转发数据处理结束===============================//
//===========================数据处理函数结束===============================//