//*************************************************************** //* 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 #include #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; iCmdTime[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; im_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; iLinkAddr; 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; } } //===========================转发数据处理结束===============================// //===========================数据处理函数结束===============================//