//*************************************************************** //* scadaprotect.cpp * //* aaawen 2004.10.19 * //*************************************************************** #ifdef OS_LINUX #include "baohulib/commport.h" #include "baohulib/serialport.h" #else #include "commport.h" #include "udpcomm.h" #include "display.h" #endif #include #include "scadaprotect.h" #include "buban103.h" extern SIO_PARAM_DEF SioParam[]; extern FUNCTION_CALL *FunCallPtr; extern BYTE SyncWordEB[]; extern void *pvconf_handle; extern void *pvportconf_handle; extern void *pvdataconf_handle; extern char pvDataFileName[256]; extern char IniFilePath[256]; const int gActiveConst = 3; const int gStatusConst = 10; /*! 组织结构:链路(间隔)+装置 */ const char *gpStrScadaProtectConfigInfo[] = { "*******斯凯达内部保护规约开始*******", "模板文件名称=template.csv", "*******斯凯达内部规约结束*******", "", // 结束标志(中间不能含有该空字符串) }; //******************************************************************** //* 读取配置函数 * //*参数:int commid : 端口号 * //******************************************************************** void ScadaProtectReadConfig(int commid) { int i, iMaxPort, iDevId; char szSection[128], entry[256]; char szPortConfig[256], szTemplate[256]; PORTSTATUS sPortStatus; SCADAPROTECTPORTPARAM *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(SCADAPROTECTPORTPARAM)); if(!SioParam[commid].ExtInfo) { sprintf(szSection, "WARN(%04d): commid_%02d ExtInfo=malloc(%d) failed.", _getpid(), commid, sizeof(SCADAPROTECTPORTPARAM)); DebugPrint(szSection); return; } memset(SioParam[commid].ExtInfo, 0, sizeof(SCADAPROTECTPORTPARAM)); pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; // 只有在SioParam[commid].m_psBaoHu非空时,才会运行到这里 pPortParam->m_psBaoHu = SioParam[commid].m_psBaoHu; iMaxPort = GetMaxPort(); pPortParam->m_pPrtPortStatus = (PORTSTATUS *)HEAP_MALLOC(iMaxPort*sizeof(PORTSTATUS)); //memset((void *)pPortParam->m_pPrtPortStatus, 0, GetMaxPort()*sizeof(PORTSTATUS)); for(i=0; im_iActiveTimeCnt = 0; pPortParam->m_iActiveTimeConst = (gActiveConst*1000)/TIMER_CNT; pPortParam->m_iStatusTimeCnt = 0; pPortParam->m_iStatusTimeConst = (gStatusConst*1000)/TIMER_CNT; // sprintf(szSection, "Port%d", commid+1); strcpy(entry, "模板文件名称"); GetPrivateProString(szSection, entry, "template.csv", pPortParam->m_chArrayTempletFileName, sizeof(pPortParam->m_chArrayTempletFileName)-1, szPortConfig); #ifdef OS_LINUX sprintf(szTemplate, "inf/%s", pPortParam->m_chArrayTempletFileName); #else sprintf(szTemplate, "%s/inf/%s", IniFilePath, pPortParam->m_chArrayTempletFileName); #endif InitScadaInfoFromTempletFile(commid, pPortParam, szTemplate, FALSE); // wen 2005.06.22 // 初始化单向链表,链表最大数量为20个 //SingleListInit(&pPortParam->m_sBaoHuData, 20); iDevId = commid<<16; SingleListInitEx(&pPortParam->m_sBaoHuData, 20, iDevId); } //******************************************************************** //* 读取端口数据函数 * //*参数:int commid : 端口号 * //* u_char buf : 数据源缓冲区指针 * //* int len : 数据源长度 * //******************************************************************** void ScadaProtectRecvData(int commid, u_char *buf, int len)// 规约读数据处理 { int i; PROTECTMSGHEAD sMsgHead; SCADAPROTECTPORTPARAM *pPortParam; #ifdef _DEBUG_MSG_ char szbuf[256]; #endif if(IsExtInfoPtr(commid) == FALSE) { return; } pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; for(i=0; im_psBaoHu->m_iRevStatus) { case 0: pPortParam->m_iRecvLen = 0; case 1: case 2: case 3: case 4: case 5: pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; if(buf[i] == SyncWordEB[pPortParam->m_psBaoHu->m_iRevStatus]) { pPortParam->m_psBaoHu->m_iRevStatus++; } else { pPortParam->m_psBaoHu->m_iRevStatus = 50; // 错误数据增加 //SioParam[commid].ErrMsgNum++; } break; case 6: case 7: case 8: case 9: // 功能码 case 10: case 11: case 12: case 13: // 端口号 case 14: case 15: case 16: pPortParam->m_psBaoHu->m_iRevStatus++; pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; break; case 17: // 长 度(长度计算) pPortParam->m_psBaoHu->m_iRevStatus++; pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; memcpy((void *)&sMsgHead, pPortParam->m_achRecvBuf+6, sizeof(PROTECTMSGHEAD)); SequenceNetToHost((char *)&sMsgHead.MsgLen, sizeof(u_32)); if(sMsgHead.MsgLen == 0) { ScadaProtectProcessData(commid, pPortParam, TRUE); #ifndef OS_LINUX if((GetCurPort() == commid) && IsRealDataDisp()) { WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, (BYTE *)pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen); } #endif pPortParam->m_psBaoHu->m_iRevStatus = 0; } else { pPortParam->m_psBaoHu->m_iNeedRevLength = sMsgHead.MsgLen; } break; case 18:// 正确接收数据 pPortParam->m_psBaoHu->m_iNeedRevLength--; pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; if(pPortParam->m_psBaoHu->m_iNeedRevLength > 0) { // wen 2006.04.29 修改数据缺少后的数据同步 if(buf[i] == 0x90) { if(pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen-2] == (char)0xeb) { pPortParam->m_achRecvBuf[0] = (char)0xEB; pPortParam->m_achRecvBuf[1] = (char)0x90; pPortParam->m_psBaoHu->m_iRevStatus = 2; pPortParam->m_iRecvLen = 2; } } break; } ScadaProtectProcessData(commid, pPortParam, TRUE); #ifndef OS_LINUX if((GetCurPort() == commid) && IsRealDataDisp()) { WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, (BYTE *)pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen); } #endif pPortParam->m_psBaoHu->m_iRevStatus = 0; //pPortParam->m_iRecvLen = 0; break; case 19:// 错误接收数据 default: if(buf[i] == 0xEB) { #ifndef OS_LINUX // wen 2004.11.22 增加显示 if((GetCurPort() == commid) && IsRealDataDisp()) { WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, (BYTE *)pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen); } #endif ScadaProtectProcessData(commid, pPortParam, FALSE); SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen; // 从状态1开始 pPortParam->m_achRecvBuf[0] = buf[i]; pPortParam->m_psBaoHu->m_iRevStatus = 1; pPortParam->m_iRecvLen = 1; } else { pPortParam->m_achRecvBuf[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_achRecvBuf, pPortParam->m_iRecvLen); } #endif ScadaProtectProcessData(commid, pPortParam, FALSE); SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen; pPortParam->m_iRecvLen = 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 ScadaProtectTimer(int commid) { RTUMSG rtumsg; PORTSTATUS sPortStatus; SCADAPROTECTPORTPARAM *pPortParam; if(IsExtInfoPtr(commid) == FALSE) { return; } pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; if(PROTOCOL_MASTER == pPortParam->m_psBaoHu->PortType) { return; } ReduceTimeOut(pPortParam); //1. 发送定值数据,保护模拟量,保护开关量 if(SingleListHaveData(&pPortParam->m_sBaoHuData) > 0) { // wen 2006.05.11 将整个RTUMSG结构压入列表 //rtumsg.MsgLen = SingleListGetAndDelData(&pPortParam->m_sBaoHuData, rtumsg.MsgData, sizeof(rtumsg.MsgData)); rtumsg.MsgLen = SingleListGetAndDelData(&pPortParam->m_sBaoHuData, (BYTE *)&rtumsg, sizeof(RTUMSG)); rtumsg.MsgLen -= sizeof(RTUMSGHEAD); if(rtumsg.MsgLen > 0) { // wen 2006.05.11 在此将繁忙标识清空 if((rtumsg.PortIdx >= 0) && (rtumsg.PortIdx < GetMaxPort())) { sPortStatus.bPortIdle = TRUE; sPortStatus.mmid = 0xFFFFFFFF; sPortStatus.timeOut = 0; SetProtectPortIdle(rtumsg.PortIdx, pPortParam, &sPortStatus); } FormatDataAndSend(commid, (PROTECTMSG *)rtumsg.MsgData); return; } } //2. 发送soe数据,保护事件 if(ProvHaveSoeData(commid) > 0) { //printf("scadaprotect have soe data.\n"); if(MakeSoeDataPacket(commid) == TRUE) { return; } } //3. 定时发送网络活动包和通道状态 if(pPortParam->m_iActiveTimeConst > 0) { pPortParam->m_iActiveTimeCnt++; if(pPortParam->m_iActiveTimeCnt > pPortParam->m_iActiveTimeConst) { pPortParam->m_iActiveTimeCnt = 0; MakeNetActivePacket(commid); } } if(pPortParam->m_iStatusTimeConst > 0) { pPortParam->m_iStatusTimeCnt++; if(pPortParam->m_iStatusTimeCnt > pPortParam->m_iStatusTimeConst) { pPortParam->m_iStatusTimeCnt = 0; MakeStatusPacket(commid); } } //Buban103SendCmdFormPollCmdBuf(commid); } //******************************************************************** //* 遥控遥调数据处理函数 * //*参数:int commid : 端口号 * //* u_char buf : 数据源缓冲区指针 * //* int len : 数据源长度 * //******************************************************************** void ScadaProtectYkYtProcess(int commid, u_char *buf, int len) // 遥控遥调处理 { int portno, ykytpnt; int iDirect; //SCADAPROTECTPORTPARAM *pPortParam; // 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; } //******************************************************************** //* 系统退出时规约处理函数 * //*参数:int commid : 端口号 * //******************************************************************** void ScadaProtectExit(int commid) { SCADAPROTECTPORTPARAM *pPortParam; if(SioParam[commid].ExtInfo == NULL) { return; } pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; if(pPortParam->m_pPrtPortStatus != NULL) { HEAP_FREE(pPortParam->m_pPrtPortStatus); pPortParam->m_pPrtPortStatus = NULL; } if(pPortParam->m_psProvDev != NULL) { HEAP_FREE(pPortParam->m_psProvDev); pPortParam->m_psProvDev = NULL; } SingleListDelData(&pPortParam->m_sBaoHuData); } // 该函数用来驱动由转发端口下发到实际装置的保护命令 void ScadaProtectBaoHuCmdProcess(int commid, RTUMSG *rtumsg, BOOL bUpData) { //char szDbg[128]; //int iProvAddr; //PROTECTCONTENTHEAD *ptrProHead; SCADAPROTECTPORTPARAM *pPortParam; pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; // 上行数据 if(MSGTYPE_BAOHU_SCADADATA == rtumsg->MsgType) //if(bUpData == TRUE) { if(pPortParam->m_psProvDev != NULL) { // wen 2006.05.11 将整个RTUMSG结构压入列表 //SingleListAddData(&pPortParam->m_sBaoHuData, rtumsg->MsgData, rtumsg->MsgLen); SingleListAddData(&pPortParam->m_sBaoHuData, (BYTE *)rtumsg, rtumsg->MsgLen+sizeof(RTUMSGHEAD)); } return; } } int ScadaProtectGetBaohuDataBase(int commid, int iProvAddr, GROUPDEF **ppBaoHuDB) { return 0; } /////////////////////////通用函数接口结束/////////////////////////////// ///////////////////////////以下为配置函数接口/////////////////////////// BOOL InitScadaInfoFromTempletFile(int commid, SCADAPROTECTPORTPARAM *psPortParam,\ char *ptrTemplate, BOOL bMaster) { char *ptr; char szBuf[512]; BOOL bVal; HDSFILE hFile; enum Param_Type ParamType; if(bMaster == TRUE) { return FALSE; } hFile = DSOpenFile(ptrTemplate); if(hFile == NULL) { return FALSE; } ParamType = PARAM_NO; while(TRUE) { ptr = DSfgets(szBuf, sizeof(szBuf), hFile); if(!ptr) { break; } // test //DebugPrint(szBuf); if(strstr(ptr, "链路描述") != NULL) { //处理链路参数 ParamType = PARAM_LINK; } else if(strstr(ptr, "设备描述") != NULL) { ParamType = PARAM_DEV; } else if(PARAM_NO == ParamType) { continue; } switch(ParamType) { case PARAM_LINK: bVal = GetProvDevNumFromTemplateFileScada(commid, hFile, psPortParam); if(TRUE == bVal) { if(psPortParam->m_iDevNum > 0) { // test //DebugPrint("malloc provDev."); psPortParam->m_psProvDev = (SCADAPROVDEVDEF *)HEAP_MALLOC(psPortParam->m_iDevNum*sizeof(SCADAPROVDEVDEF)); if(psPortParam->m_psProvDev == NULL) { psPortParam->m_iDevNum = 0; } memset((void *)psPortParam->m_psProvDev, 0, psPortParam->m_iDevNum*sizeof(SCADAPROVDEVDEF)); } } break; case PARAM_DEV: bVal = GetProvDevParamFromTemplateFileScada(commid, hFile, psPortParam); break; default: break; } } DSCloseFile(hFile); return TRUE; } BOOL GetProvDevNumFromTemplateFileScada(int commid, HDSFILE hFile, SCADAPROTECTPORTPARAM *psPortParam) { char *ptr, *ptrSour, *ptrDest; char szBuf[512]; int i, ilen; BOOL bRetVal; ptr = DSfgets(szBuf, sizeof(szBuf), hFile); if(ptr == NULL) { return FALSE; } // test //DebugPrint(szBuf); ptrSour = szBuf; if(strstr(ptrSour, "LINK") == NULL) { return FALSE; } bRetVal = FALSE; for(i=0; i<4; i++) { if(GetParamItem(ptrSour, &ptrDest) == FALSE) { bRetVal = FALSE; break; } *ptrDest = 0; ilen = strlen(ptrSour); switch(i) { case 0:// 链路描述 break; case 1:// 链路标识 break; case 2:// 链路地址 break; case 3:// 装置数量 if(ilen > 0) { psPortParam->m_iDevNum = atoi(ptrSour); bRetVal = TRUE; } break; case 4:// 备用 break; case 5:// 备用 break; case 6:// 地址偏移 break; case 7:// 数据类型 break; case 8:// 写入数据库站号 break; case 9:// 写入数据库起始点号 break; case 10:// 是否判断ASDU号 break; case 11:// 是否处理扰动数据 break; case 12:// 是否屏蔽未配置事件 break; case 13:// 一类数据问询次数(该项不可达,在循环外处理) break; } ptrSour = ptrDest+1; } return bRetVal; } BOOL GetProvDevParamFromTemplateFileScada(int commid, HDSFILE hFile, SCADAPROTECTPORTPARAM *psPortParam) { char *ptr, *ptrSour, *ptrDest; char szBuf[512]; int i, j, ilen, iNum; int iAiNum, iAiStart, iDiStart; int iPiStart, iYkStart, iPntNo; BOOL bRetVal; enum Param_Type ParamType; iAiStart = 0; iDiStart = 0; iPiStart = 0; iYkStart = 0; iAiNum = 0; ParamType = PARAM_NO; for(i=0; im_iDevNum;) { ptr = DSfgets(szBuf, sizeof(szBuf), hFile); if(ptr == NULL) { break; } // test //DebugPrint(szBuf); if(strstr(ptr, "设备描述") != NULL) { i++; iAiNum = 0; ParamType = PARAM_NO; continue; } if(strstr(ptr, "链路描述") != NULL) { break; } ptrSour = ptr; for(j=0; j<8; j++) { if(GetParamItem(ptrSour, &ptrDest) == FALSE) { bRetVal = FALSE; break; } *ptrDest = 0; ilen = strlen(ptrSour); switch(j) { case 0:// 设备描述 break; case 1:// 设备型号 break; case 2:// 设备地址 break; case 3:// 转发地址 if(PARAM_NO != ParamType) { break; } if(ilen > 0) { psPortParam->m_psProvDev[i].m_iProvAddr = atoi(ptrSour); } break; case 4:// 端口号&状态站号&状态点号 if(PARAM_NO != ParamType) { break; } if(ilen > 0) { psPortParam->m_psProvDev[i].m_iRealCommid = atoi(ptrSour); if(GetParamItemEx(ptrSour, &ptr, "&") == FALSE) { psPortParam->m_psProvDev[i].m_iStatusStn = 0; psPortParam->m_psProvDev[i].m_iStatusPnt = 0; break; } ptrSour = ptr+1; if(strlen(ptrSour) > 0) { psPortParam->m_psProvDev[i].m_iStatusStn = atoi(ptrSour); if(GetParamItemEx(ptrSour, &ptr, "&") == FALSE) { psPortParam->m_psProvDev[i].m_iStatusStn = 0; psPortParam->m_psProvDev[i].m_iStatusPnt = 0; break; } ptrSour = ptr+1; if(strlen(ptrSour) > 0) { psPortParam->m_psProvDev[i].m_iStatusPnt = atoi(ptrSour); } } } break; case 5:// 备用 break; case 6:// 数量 if(ilen > 0) { iNum = atoi(ptrSour); } break; case 7:// 数据类型 if(iNum <= 0) { break; } if(ilen > 0) { if(strcmp(ptrSour, "YC") == 0) { ParamType = PARAM_YC; iPntNo = 0; } else if(strcmp(ptrSour, "YX") == 0) { ParamType = PARAM_YX; psPortParam->m_psProvDev[i].m_sYxInfo.m_iPntNum = iNum; psPortParam->m_psProvDev[i].m_sYxInfo.m_iStartPntNo = iDiStart; psPortParam->m_psProvDev[i].m_sYxInfo.m_iStnNo = 0; psPortParam->m_psProvDev[i].m_sYxInfo.m_psDataInfo = NULL; iDiStart += iNum; iPntNo = 0; } else if(strcmp(ptrSour, "YM") == 0) { ParamType = PARAM_YM; iPntNo = 0; } else if(strcmp(ptrSour, "YK") == 0) { ParamType = PARAM_YK; iPntNo = 0; } else if(strcmp(ptrSour, "SYNCTIME") == 0) { ParamType = PARAM_SYNCTIME; iPntNo = 0; } else if(strcmp(ptrSour, "ASDU10") == 0) { ParamType = PARAM_ASDU10; iPntNo = 0; } } break; default: break; } ptrSour = ptrDest+1; } switch(ParamType) { case PARAM_YC: break; case PARAM_YX: break; case PARAM_YM: break; case PARAM_YK: break; case PARAM_SYNCTIME: break; case PARAM_ASDU10: break; default: break; } } return bRetVal; } int FindProtectDevFromPntNoScada(SCADAPROTECTPORTPARAM *psPortParam, int iPntNo, int itype) { int i, ipnt; BOOL bRetVal; DBORIENTATION *pDataUnit; bRetVal = FALSE; if(psPortParam->m_psProvDev == NULL) { return -1; } //printf("psPortParam->m_iDevNum = %d\n", psPortParam->m_iDevNum); for(i=0; im_iDevNum; i++) { switch(itype) { case DI_PNT_TYPE: pDataUnit = &psPortParam->m_psProvDev[i].m_sYxInfo; break; case AI_PNT_TYPE: case PI_PNT_TYPE: default: pDataUnit = NULL; break; } if(pDataUnit == NULL) { continue; } //printf("pDataUnit->m_iStartPntNo=%d, pDataUnit->m_iPntNum=%d\n", // pDataUnit->m_iStartPntNo, pDataUnit->m_iPntNum); ipnt = iPntNo - pDataUnit->m_iStartPntNo; if((ipnt >= 0) && (ipnt < pDataUnit->m_iPntNum)) { break; } } if(i >= psPortParam->m_iDevNum) { return -1; } else { return i; } } /////////////////////////////配置函数接口结束/////////////////////////// void ScadaProtectProvMakeYkYtCommand(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=合到分, 0=失败) // (最高位为1时,为返校命令) // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 } ///////////////////////以下为规约处理函数接口/////////////////////////// //*******************************************************************************/ //* 将客户端到前置机所有的报文从网络字节顺序转换成主机字节顺序函数 */ //*参数:RTUMSG* hostmsg:转换后的主机字节顺序报文 */ //* ORTUMSG* userdata:转换前的网络字节顺序报文 */ //*返回值:无 */ //*******************************************************************************/ void AllNetToHostByteSequence(PROTECTMSG *userdata) { u_32 iOffset; pPROTECTCONTENTHEAD ptrContent; #ifdef _DEBUG_MSG_ char szbuf[256]; #endif SequenceNetToHost((char *)&userdata->MsgType, sizeof(u_32)); SequenceNetToHost((char *)&userdata->PortNumber, sizeof(u_32)); SequenceNetToHost((char *)&userdata->MsgLen, sizeof(u_32)); switch(userdata->MsgType) { case pPFV_PROTECT_BYPASS://保护机到前置机保护数据 ptrContent = (pPROTECTCONTENTHEAD)(userdata->MsgData); //转换保护地址 SequenceNetToHost((char *)&ptrContent->uAddr, sizeof(u_32)); //转换保护操作功能码 SequenceNetToHost((char *)&ptrContent->uFuncCode, sizeof(u_32)); //操作用户 SequenceNetToHost((char *)&ptrContent->ummid, sizeof(u_32)); //保留字节 SequenceNetToHost((char *)&ptrContent->uReserved, sizeof(u_32)); //定值区号 //ptrContent->cFixNo; //CPU 号 //ptrContent->cCPUNo; iOffset = sizeof(PROTECTCONTENTHEAD); switch(ptrContent->uFuncCode) { case hREADFIX://读取定值 case hREADPAI:// 读取保护模拟量 case hREADPDI:// 读取保护开关量 case hQUERYFAULT:// 读取指定故障报告 case hQUERYSELFCHECK:// 读取指定的自检报告 break; case hREADFIXNO://读取定值区号 case hREADPWAVE:// 读取保护波形数据 break; case hWRITEALLFIX:// 修改保护定值 // 起始序号 SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); for(; iOffsetMsgLen;) { // 数据类型 switch(userdata->MsgData[iOffset++] & 0x7F) { case DATATYPE_AI: // 数据值长度(占用位数) iOffset++; // 数值 SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(float)); iOffset += sizeof(float); break; case DATATYPE_DI: // 数据值长度(占用位数) iOffset++; SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(float)); iOffset += sizeof(float); break; case DATATYPE_STRING: // 数据值长度(占用字节数) // 数值 iOffset += userdata->MsgData[iOffset] + 1; break; default: #ifdef _DEBUG_MSG_ sprintf(szbuf, "保护机下发写定值报文格式有错误,无效的数据类型"); DebugPrint(szbuf); #endif userdata->MsgLen = 0; return; } } break; case hWRITESPECIALFIX:// 修改指定的保护定值 for(;iOffsetMsgLen;) { // 定值序号 SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); // 数据类型 switch(userdata->MsgData[iOffset++] & 0x7F) { case DATATYPE_AI: // 数据值长度(占用位数) iOffset++; // 数值 SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(float)); iOffset += sizeof(float); break; case DATATYPE_DI: // 数据值长度(占用位数) iOffset++; SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(float)); iOffset += sizeof(float); break; case DATATYPE_STRING: // 数据值长度(占用字节数) // 数值 iOffset += userdata->MsgData[iOffset] + 1; break; default: #ifdef _DEBUG_MSG_ sprintf(szbuf, "保护机下发写指定定值报文格式有错误,无效的数据类型"); DebugPrint(szbuf); #endif userdata->MsgLen = 0; return; } } break; case hWRITEFIXNO:// 修改保护定值区 break; case hRESETPROTECT:// 保护信号复归 break; case hCHECKTIME:// 单个装置对时 break; case hBROADCASTCHECKTIME:// 保护装置广播对时 break; case hCANCEL:// 保护操作取消 break; } break; case fPFV_NETACTIVE://网络测试包 break; default: break; } } //*******************************************************************************/ //* 将前置机到客户机所有的报文从主机字节顺序转换成网络字节顺序函数 */ //*参数:RTUMSG* userdata:转换前的主机字节顺序报文 */ //* ORTUMSG* hostmsg:转换后的网络字节顺序报文 */ //*返回值:无 */ //*******************************************************************************/ void AllHostToNetByteSequence(PROTECTMSG *userdata) { u_short u_shortLen; u_32 uDataLen, datatype, msgtype, uFuncCode; u_32 iOffset; pPROTECTCONTENTHEAD ptrContent; #ifdef _DEBUG_MSG_ char szbuf[512]; #endif uDataLen = userdata->MsgLen; msgtype = userdata->MsgType; SequenceHostToNet((char *)&userdata->MsgType, sizeof(u_32)); SequenceHostToNet((char *)&userdata->PortNumber, sizeof(u_32)); SequenceHostToNet((char *)&userdata->MsgLen, sizeof(u_32)); switch(msgtype) { case fPFV_PROTECT_BYPASS_ACK://前置机到保护机保护数据 ptrContent = (pPROTECTCONTENTHEAD)(userdata->MsgData); uFuncCode = ptrContent->uFuncCode; //转换保护地址 SequenceHostToNet((char *)&ptrContent->uAddr, sizeof(u_32)); //转换保护操作功能码 SequenceHostToNet((char *)&ptrContent->uFuncCode, sizeof(u_32)); //操作用户 SequenceHostToNet((char *)&ptrContent->ummid, sizeof(u_32)); //保留字节 SequenceHostToNet((char *)&ptrContent->uReserved, sizeof(u_32)); //定值区号 //ptrContent->cFixNo; //CPU 号 //ptrContent->cCPUNo; iOffset = sizeof(PROTECTCONTENTHEAD); switch(uFuncCode) { case hREADINGDATA:// 数据申请中 break; case hFIXDATAWITHNO:// 定值数据带序号 // 定值类型 datatype = userdata->MsgData[iOffset++]; for(;iOffsetMsgData[iOffset], sizeof(WORD)); iOffset += sizeof(WORD); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif } // 定值数据类型 switch(userdata->MsgData[iOffset] & 0x7F) { case DATATYPE_AI: case DATATYPE_DI: iOffset++; if((iOffset + sizeof(float)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(float)); iOffset += sizeof(float); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif } break; case DATATYPE_STRING: iOffset++; // 数据长度(占用字节数) // 数值 if((iOffset + userdata->MsgData[iOffset] + 1) < MAX_RTU_MSG_SIZE) { iOffset += userdata->MsgData[iOffset] + 1; } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif } break; default: userdata->MsgLen = 0; return; } break; case ITEM_ATTR_UNIT:// 量 纲 case ITEM_ATTR_DESCRIPTION:// 描 述 // 数据长度(占用字节数) //userdata->MsgData[iOffset]; // 数值 if((iOffset + userdata->MsgData[iOffset] + 1) < MAX_RTU_MSG_SIZE) { iOffset += userdata->MsgData[iOffset] + 1; } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif } break; case ITEM_ATTR_RATE:// 参 比 case ITEM_ATTR_LIST:// 列 表 default: iOffset = uDataLen; #ifdef _DEBUG_MSG_ sprintf(szbuf, "保护机上行读取定值报文格式有错误,无效的数据类型"); DebugPrint(szbuf); #endif break; } } break; case hPAIDATAWITHNO: // 保护模拟量数据带序号 break; case hPDIDATAWITHNO: // 保护开关量数据带序号 break; case hFIXDATA:// 定值数据 // 定值类型 datatype = userdata->MsgData[iOffset++]; // 起始序号 if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif } for(;iOffsetMsgData[iOffset] & 0x7F) { case DATATYPE_AI: case DATATYPE_DI: iOffset++; // 数值 if((iOffset + sizeof(float)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(float)); iOffset += sizeof(float); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif } break; case DATATYPE_STRING: iOffset++; // 数据长度(占用字节数) // 数值 if((iOffset + sizeof(float)) < MAX_RTU_MSG_SIZE) { iOffset += userdata->MsgData[iOffset] + 1; } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif } break; default: userdata->MsgLen = 0; return; } break; case ITEM_ATTR_UNIT:// 量 纲 case ITEM_ATTR_DESCRIPTION:// 描 述 // 数据长度(占用字节数) // 数值 if((iOffset + userdata->MsgData[iOffset] + 1) < MAX_RTU_MSG_SIZE) { iOffset += userdata->MsgData[iOffset] + 1; } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif } break; case ITEM_ATTR_RATE:// 参 比 case ITEM_ATTR_LIST:// 列 表 default: iOffset = uDataLen; #ifdef _DEBUG_MSG_ sprintf(szbuf, "保护机上行读取定值报文格式有错误,无效的数据类型"); DebugPrint(szbuf); #endif break; } } break; case hREADDATAEND:// 数据申请结束 break; case hNORESPONSE:// 数据申请无响应 break; case hSYSTEMBUSY:// 数据处理繁忙,稍后重试 break; case hFIXNODATA:// 定值区号数据 break; case hPAIDATA:// 保护模拟量数据 // 模拟量类型 datatype = userdata->MsgData[iOffset++]; // 起始序号 if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } for(;iOffsetMsgData[iOffset], sizeof(float)); iOffset += sizeof(float); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; } break; case ITEM_ATTR_UNIT:// 量 纲 case ITEM_ATTR_DESCRIPTION:// 描 述 // 数据长度(占用字节数) // 数值 if((iOffset + userdata->MsgData[iOffset] + 1) < MAX_RTU_MSG_SIZE) { iOffset += userdata->MsgData[iOffset] + 1; } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; } break; case ITEM_ATTR_RATE:// 参 比 case ITEM_ATTR_LIST:// 列 表 default: iOffset = uDataLen; #ifdef _DEBUG_MSG_ sprintf(szbuf, "保护机上行读取保护模拟量报文格式有错误,无效的数据类型"); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } } break; case hPDIDATA:// 保护开关量数据 // 开关量类型 datatype = userdata->MsgData[iOffset++]; // 起始序号 if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } for(; iOffsetMsgData[iOffset] + 1) < MAX_RTU_MSG_SIZE) { iOffset += userdata->MsgData[iOffset] + 1; } else { userdata->MsgLen = 0; } break; case ITEM_ATTR_MINMAXSTEP:// 量 程 case ITEM_ATTR_PRECISION:// 精 度 case ITEM_ATTR_FIGURE:// 因 子 case ITEM_ATTR_RATE:// 参 比 case ITEM_ATTR_LIST:// 列 表 default: iOffset = uDataLen; #ifdef _DEBUG_MSG_ sprintf(szbuf, "保护机上行读取保护开关量报文格式有错误,无效的数据类型"); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } } break; case hPWAVEDATASTART:// 保护波行数据上送开始 break; case hPWAVEDATA:// 保护波行数据 /* //起始序号 if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //采样个数 if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换年 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(WORD)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换月 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(WORD)); iOffset += sizeof(WORD); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换日 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换时 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换分 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换秒 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换微秒 if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //采样时间间隔 if((iOffset + sizeof(float)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(float)); iOffset += sizeof(float); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } for(;iOffsetMsgData[iOffset], sizeof(float)); iOffset += sizeof(float); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } } */ break; case hPWAVEDATAEND:// 保护波行数据上送结束 break; case hPEVENTDATAWITHID:// 带索引号的事件报告数据 //转换年 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换月 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换日 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换时 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换分 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换秒 if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //转换微秒 if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } for(;iOffsetMsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //备注长度 if(userdata->MsgData[iOffset] > 0) { iOffset += userdata->MsgData[iOffset]+1; } else { iOffset++; } } break; case hPEVENTDATAWITHSTRING:// 字符串事件报告数据 for(; iOffsetMsgData[iOffset]; if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); iOffset += sizeof(u_short); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //字符串 if((iOffset + u_shortLen) < MAX_RTU_MSG_SIZE) { iOffset += u_shortLen; } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset + u_shortLen); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } } break; case hWRITEFIXACK:// 保护定值确认 break; case hWRITEFIXNAK:// 保护定值不确认 break; case hWRITEFIXNOACK:// 定值区修改确认 break; case hWRITEFIXNONAK:// 定值区修改不确认 break; } break; case fPFV_NETACTIVE://网络测试包 break; case fPFV_STATUS://前置机状态包 iOffset = 0; //前置机A状态 if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } //前置机B状态 if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) { SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); iOffset += sizeof(u_32); } else { #ifdef _DEBUG_MSG_ sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); DebugPrint(szbuf); #endif userdata->MsgLen = 0; break; } break; default: break; } } void ScadaProtectProcessData(int commid, SCADAPROTECTPORTPARAM *psPortParam, BOOL bProcess) { PROTECTMSG msg; SCADAPROTECTPORTPARAM *pPortParam; /* if(FALSE == GetPortParamPtr(commid, &pPortParam)) { return; } */ pPortParam = psPortParam; if(TRUE == bProcess) { memcpy((void *)&msg, psPortParam->m_achRecvBuf+6, pPortParam->m_iRecvLen-6); AllNetToHostByteSequence(&msg); // 主站数据处理 if(PROTOCOL_MASTER == pPortParam->m_psBaoHu->PortType) { return; } // 主站数据处理 switch(msg.MsgType) { case pPFV_PROTECT_BYPASS:// 保护指令处理 ScadaProtectByPassData(commid, pPortParam, &msg); break; case fPFV_PROTECT_BYPASS_ACK: // 上行保护数据处理 break; case fPFV_NETACTIVE:// 网络活动包 break; default: break; } } } void ReduceTimeOut(SCADAPROTECTPORTPARAM *psPortParam) { int i, iMaxPort; if(psPortParam->m_pPrtPortStatus == NULL) { return; } iMaxPort = GetMaxPort(); for(i=0; im_pPrtPortStatus[i].timeOut > 0) { psPortParam->m_pPrtPortStatus[i].timeOut--; if(psPortParam->m_pPrtPortStatus[i].timeOut <= 0) { psPortParam->m_pPrtPortStatus[i].mmid = 0xFFFFFFFF; psPortParam->m_pPrtPortStatus[i].bPortIdle = TRUE; } } } } BOOL IsProtectPortIdle(int commid, SCADAPROTECTPORTPARAM *psPortParam) { if((commid < 0) || (commid > GetMaxPort())) { return TRUE; } if(psPortParam->m_pPrtPortStatus == NULL) { return TRUE; } return psPortParam->m_pPrtPortStatus[commid].bPortIdle; } BOOL GetProtectPortIdle(int commid, SCADAPROTECTPORTPARAM *psPortParam, PORTSTATUS *pStatus) { if((commid < 0) || (commid > GetMaxPort())) { return FALSE; } if(psPortParam->m_pPrtPortStatus == NULL) { return FALSE; } pStatus->mmid = psPortParam->m_pPrtPortStatus[commid].mmid; pStatus->timeOut = psPortParam->m_pPrtPortStatus[commid].timeOut; pStatus->bPortIdle = psPortParam->m_pPrtPortStatus[commid].bPortIdle; return TRUE; } BOOL SetProtectPortIdle(int commid, SCADAPROTECTPORTPARAM *psPortParam, PORTSTATUS *pStatus) { if((commid < 0) || (commid > GetMaxPort())) { return FALSE; } if(psPortParam->m_pPrtPortStatus == NULL) { return FALSE; } // wen 2005.06.22 在uclinux系统中,初始化时全部为0 /* if(psPortParam->m_pPrtPortStatus[commid].bPortIdle == FALSE) { if(psPortParam->m_pPrtPortStatus[commid].mmid != pStatus->mmid) { return FALSE; } } psPortParam->m_pPrtPortStatus[commid].bPortIdle = pStatus->bPortIdle; psPortParam->m_pPrtPortStatus[commid].mmid = pStatus->mmid; psPortParam->m_pPrtPortStatus[commid].timeOut = pStatus->timeOut; */ //printf("Idle1(port%d): Idle=%d, mmid=%d, timeout=%d\n", commid+1, // pStatus->bPortIdle, pStatus->mmid, pStatus->timeOut); psPortParam->m_pPrtPortStatus[commid].bPortIdle = pStatus->bPortIdle; psPortParam->m_pPrtPortStatus[commid].mmid = pStatus->mmid; psPortParam->m_pPrtPortStatus[commid].timeOut = pStatus->timeOut; //printf("Idle2(port%d): Idle=%d, mmid=%d, timeout=%d\n", commid+1, // psPortParam->m_pPrtPortStatus[commid].bPortIdle, // psPortParam->m_pPrtPortStatus[commid].mmid, // psPortParam->m_pPrtPortStatus[commid].timeOut); return TRUE; } BOOL SetProtectPortIdleEx(int commid, int iBaoHuCommid, PORTSTATUS *pStatus) { SCADAPROTECTPORTPARAM *pPortParam; if((iBaoHuCommid < 0) || (iBaoHuCommid > GetMaxPort())) { return FALSE; } pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[iBaoHuCommid].ExtInfo; if(pPortParam->m_pPrtPortStatus == NULL) { return FALSE; } if((commid < 0) || (commid > GetMaxPort())) { return FALSE; } //printf("Idle1(port%d): Idle=%d, mmid=%d, timeout=%d\n", commid+1, // pStatus->bPortIdle, pStatus->mmid, pStatus->timeOut); pPortParam->m_pPrtPortStatus[commid].bPortIdle = pStatus->bPortIdle; pPortParam->m_pPrtPortStatus[commid].mmid = pStatus->mmid; pPortParam->m_pPrtPortStatus[commid].timeOut = pStatus->timeOut; //printf("Idle2(port%d): Idle=%d, mmid=%d, timeout=%d\n", commid+1, // pPortParam->m_pPrtPortStatus[commid].bPortIdle, // pPortParam->m_pPrtPortStatus[commid].mmid, // pPortParam->m_pPrtPortStatus[commid].timeOut); return TRUE; } void SendResponsetoMMI(int commid, int mmid, u_32 ResponseType, PROTECTMSG *pmsg) { PROTECTMSG mmimsg; pPROTECTCONTENTHEAD ptrProHead, pSourProHead; memset((void*)&mmimsg, 0, sizeof(PROTECTMSG)); mmimsg.MsgType = fPFV_PROTECT_BYPASS_ACK; ptrProHead = (pPROTECTCONTENTHEAD)mmimsg.MsgData; if(pmsg != NULL) { pSourProHead = (pPROTECTCONTENTHEAD)pmsg->MsgData; mmimsg.PortNumber = pmsg->PortNumber; //memcpy(mmimsg.MsgData, rtumsg->MsgData, 10); ptrProHead->cCPUNo = pSourProHead->cCPUNo; ptrProHead->cFixNo = pSourProHead->cFixNo; ptrProHead->uAddr = pSourProHead->uAddr; ptrProHead->uFuncCode = pSourProHead->uFuncCode; ptrProHead->ummid = pSourProHead->ummid; ptrProHead->uReserved = pSourProHead->uReserved; } switch(ResponseType) { case hREADINGDATA: // 数据交互开始 case hREADDATAEND: // 数据交互结束 case hSYSTEMBUSY: // 数据交互繁忙 case hNORESPONSE: // 数据申请无响应 // 操作用户 ptrProHead->ummid = mmid; // 功能码 ptrProHead->uFuncCode = ResponseType; // 保留位 mmimsg.MsgLen = sizeof(PROTECTCONTENTHEAD); break; } if(mmimsg.MsgLen > 0) { // 发送至本端口 //SendDataToPort(commid, (char *)&mmimsg, sizeof(PROTECTMSGHEAD)+mmimsg.MsgLen); FormatDataAndSend(commid, &mmimsg); } } // 将103规约格式转换成scada内部格式,发送到指定的端口 BOOL ScadaProtectConvertToScadaFrameAndSend(int commid) { // SendDataToPort(commid, (char *)&mmimsg, sizeof(PROTECTMSGHEAD)+mmimsg.MsgLen); return TRUE; } // 转换成103规约格式,发送到指定的端口 BOOL ScadaProtectConvertTo103AndSend(int commid, PROTECTMSG *pmsg) { PROTECTCONTENTHEAD *ptrProHead; ptrProHead = (PROTECTCONTENTHEAD *)pmsg->MsgData; switch(ptrProHead->uFuncCode) { // 读取定值 case hREADFIX: break; // 读取定值区号 case hREADFIXNO: break; // 读取保护模拟量 case hREADPAI: break; // 读取保护开关量 case hREADPDI: break; // 读取保护波形数据 case hREADPWAVE: break; // 读取指定故障报告 case hQUERYFAULT: break; // 读取指定的自检报告 case hQUERYSELFCHECK: break; // 修改保护定值 case hWRITEALLFIX: break; // 修改指定的保护定值 case hWRITESPECIALFIX: break; // 保护定值确认 case hWRITEFIXACK: break; // 保护定值不确认 case hWRITEFIXNAK: break; // 修改保护定值区 case hWRITEFIXNO: break; // 定值区修改确认 case hWRITEFIXNOACK: break; // 定值区修改不确认 case hWRITEFIXNONAK: break; // 保护信号复归 case hRESETPROTECT: break; // 单个装置对时 case hCHECKTIME: break; // 保护装置广播对时 case hBROADCASTCHECKTIME: break; // 保护操作取消 case hCANCEL: break; } return TRUE; } void ScadaProtectByPassData(int commid, SCADAPROTECTPORTPARAM *psPortParam, PROTECTMSG *pmsg) { int mmid, port; RTUMSG rtumsg; PORTSTATUS sPortStatus; PROTECTCONTENTHEAD *ptrProHead; SCADAPROTECTPORTPARAM *pPortParam; pPortParam = psPortParam; ptrProHead = (PROTECTCONTENTHEAD *)pmsg->MsgData; port = pmsg->PortNumber; mmid = 0; if(ptrProHead->uFuncCode == hCANCEL) { SendResponsetoMMI(commid, mmid, hREADDATAEND, pmsg); sPortStatus.bPortIdle = TRUE; sPortStatus.mmid = 0xFFFFFFFF; sPortStatus.timeOut = 0; SetProtectPortIdle(port, pPortParam, &sPortStatus); return; } if(GetProtectPortIdle(port, pPortParam, &sPortStatus) == FALSE) { return; } // wen 2005.06.22 Debug //DispPrtPortStatus(commid, pPortParam); if(sPortStatus.bPortIdle == FALSE) { // 数据交互繁忙 SendResponsetoMMI(commid, mmid, hSYSTEMBUSY, pmsg); return; } if((sPortStatus.mmid != 0xffffffff) && (mmid != (int)sPortStatus.mmid)) { // 数据交互繁忙 SendResponsetoMMI(commid, mmid, hSYSTEMBUSY, pmsg); return; } rtumsg.MsgLen = sizeof(PROTECTMSGHEAD)+pmsg->MsgLen; rtumsg.PortIdx = commid; rtumsg.MsgType = MSGTYPE_BAOHU_SCADACMD; memcpy(rtumsg.MsgData, (void *)pmsg, rtumsg.MsgLen); //PutBaohuDataToPort(&rtumsg); SendProtectCmdToDev(port, &rtumsg); sPortStatus.bPortIdle = FALSE; sPortStatus.mmid = mmid; sPortStatus.timeOut = OPERPROTECTTIMEOUT*1000/TIMER_CNT; SetProtectPortIdle(port, pPortParam, &sPortStatus); } BOOL FormatDataAndSend(int commid, PROTECTMSG *pmsg) { int iDataLen; char buf[4096]; iDataLen = 6+sizeof(PROTECTMSGHEAD)+pmsg->MsgLen; if(iDataLen > sizeof(buf)) { return FALSE; } AllHostToNetByteSequence(pmsg); memcpy(buf, SyncWordEB, 6); memcpy(buf+6, (void *)pmsg, iDataLen-6); SendDataToPort(commid, buf, iDataLen); return TRUE; } void MakeInteractionCmd(int commid, int sourcommid, u_32 ResponseFunc, PROTECTCONTENTHEAD *pSourHead, BOOL bBoardCast) { PROTECTMSG msg; pPROTECTCONTENTHEAD ptrProHead; #ifdef _DEBUG_MSG_ char szbuf[256]; #endif msg.MsgLen = 0; memset((void*)&msg, 0, sizeof(PROTECTMSG)); msg.MsgType = fPFV_PROTECT_BYPASS_ACK; msg.PortNumber = sourcommid; ptrProHead = (pPROTECTCONTENTHEAD)msg.MsgData; // 广播命令 if(bBoardCast == TRUE) { ptrProHead->ummid = 0xffffffff; } ptrProHead->uFuncCode = ResponseFunc; ptrProHead->uAddr = pSourHead->uAddr; ptrProHead->ummid = pSourHead->ummid; ptrProHead->cCPUNo = pSourHead->cCPUNo; ptrProHead->cFixNo = pSourHead->cFixNo; ptrProHead->uReserved = 0; switch(ResponseFunc) { case hREADINGDATA: // 数据申请中 case hPWAVEDATASTART: // 保护波行数据上送开始 case hREADDATAEND: // 数据申请结束 case hPWAVEDATAEND: // 保护波行数据上送结束 case hWRITEFIXNAK: // 保护定值不确认 case hWRITEFIXNONAK: // 定值区修改不确认 case hNORESPONSE: // 数据申请无响应 msg.MsgLen = sizeof(PROTECTCONTENTHEAD); break; default: #ifdef _DEBUG_MSG_ sprintf(szbuf, "端口%d 保护应答无效的功能码=%d!!!\n", commid, ResponseFunc); DebugPrint(szbuf); #endif break; } if(msg.MsgLen > 0) { // 发送至本端口 //SendDataToPort(commid, (char *)&msg, sizeof(PROTECTMSGHEAD)+msg.MsgLen); FormatDataAndSend(commid, &msg); } } void MakeNetActivePacket(int commid) { PROTECTMSG msg; msg.PortNumber = commid; msg.MsgType = fPFV_NETACTIVE; msg.MsgLen = 0; //SendDataToPort(commid, (char *)&msg, sizeof(PROTECTMSGHEAD)+msg.MsgLen); FormatDataAndSend(commid, &msg); } void MakeStatusPacket(int commid) { u_32 *puData; PROTECTMSG msg; msg.PortNumber = commid; msg.MsgType = fPFV_STATUS; puData = (u_32 *)msg.MsgData; *puData = 1; //SequenceHostToNet((char *)puData, sizeof(u_32)); *(puData+1) = 0; //SequenceHostToNet((char *)(puData+1), sizeof(u_32)); msg.MsgLen = sizeof(u_32) * 2; //SendDataToPort(commid, (char *)&msg, sizeof(PROTECTMSGHEAD)+msg.MsgLen); FormatDataAndSend(commid, &msg); } BOOL MakeSoeDataPacket(int commid) { WORD *pwValue; u_32 *puValue; int iDevNo, iOffset; SOE_DEF sSoeData; char szExtend[128]; PROTECTMSG msg; PROTECTCONTENTHEAD *pProHead; SCADAPROTECTPORTPARAM *pPortParam; pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; msg.MsgType = fPFV_PROTECT_BYPASS_ACK; ProvAndDelGetSoeData(commid, &sSoeData); iDevNo = FindProtectDevFromPntNoScada(pPortParam, sSoeData.iPntNo, DI_PNT_TYPE); // Debug //printf("commid=%d sSoeData.iPntNo=%d, iDevNo=%d\n", commid, sSoeData.iPntNo, iDevNo); if(iDevNo >= 0) { msg.PortNumber = pPortParam->m_psProvDev[iDevNo].m_iRealCommid-1; pProHead = (PROTECTCONTENTHEAD *)msg.MsgData; pProHead->ummid = 0xFFFFFFFF; pProHead->uAddr = pPortParam->m_psProvDev[iDevNo].m_iProvAddr; pProHead->cCPUNo = (char)0xFF; pProHead->cFixNo = (char)0xFF; pProHead->uFuncCode = hPEVENTDATAWITHID; pProHead->uReserved = 0; iOffset = sizeof(PROTECTCONTENTHEAD); pwValue = (WORD *)&msg.MsgData[iOffset]; *pwValue = sSoeData.SoeTime.Year; *(pwValue+1) = sSoeData.SoeTime.Month; *(pwValue+2) = sSoeData.SoeTime.Day; *(pwValue+3) = sSoeData.SoeTime.Hour; *(pwValue+4) = sSoeData.SoeTime.Min; *(pwValue+5) = sSoeData.SoeTime.Sec; iOffset += sizeof(WORD)*6; puValue = (u_32 *)&msg.MsgData[iOffset]; *puValue = sSoeData.SoeTime.mSec; iOffset += sizeof(u_32); pwValue = (WORD *)&msg.MsgData[iOffset]; // 修改序号为fun+inf //*pwValue = sSoeData.iPntNo - pPortParam->m_psProvDev[iDevNo].m_sYxInfo.m_iStartPntNo + 1; *pwValue = (WORD)(((sSoeData.u8ProvFun<<8) + sSoeData.u8ProvInf) & 0x0000FFFF); if((*pwValue) == 0) { *pwValue = sSoeData.iPntNo - pPortParam->m_psProvDev[iDevNo].m_sYxInfo.m_iStartPntNo + 1; } iOffset += sizeof(WORD); // <<< 修改 // 含有故障序号和相对时间 //if(sSoeData.u8Type == 2) //{ // sprintf(szExtend, "<相对时间[%d],故障序号[%d]>", sSoeData.wRelativeTime, sSoeData.wFaultNo); // msg.MsgData[iOffset] = strlen(szExtend); // memcpy((void *)&msg.MsgData[iOffset+1], szExtend, msg.MsgData[iOffset]); // iOffset += msg.MsgData[iOffset]+1; //} //else //{ // msg.MsgData[iOffset++] = 0; //} if(sSoeData.bStatus == 1) { strcpy(szExtend, "动作"); } else { strcpy(szExtend, "恢复"); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // wen 2005.10.25 增加扩充字符串,用来解析保护事件中的故障参数 // 含有故障序号和相对时间 //if(sSoeData.u8Type == 2) //{ // sprintf(szExtend, "%s <相对时间[%d],故障序号[%d]>", szExtend, sSoeData.wRelativeTime, sSoeData.wFaultNo); //} if(sSoeData.u8Type == 2) { sprintf(szExtend, "%s <相对时间[%d],故障序号[%d]>", szExtend, sSoeData.wRelativeTime, sSoeData.wFaultNo); } else if(sSoeData.u8Type == 3) { sprintf(szExtend, "%s <%s>", szExtend, sSoeData.szMsgEx); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ msg.MsgData[iOffset] = strlen(szExtend); memcpy((void *)&msg.MsgData[iOffset+1], szExtend, msg.MsgData[iOffset]); iOffset += msg.MsgData[iOffset]+1; // >>> 完成 msg.MsgLen = iOffset; FormatDataAndSend(commid, &msg); //发送soe数据 return TRUE; } return FALSE; } //===========================数据处理函数结束========================= //===========================调试函数开始========================= void DispPrtPortStatus(int commid, SCADAPROTECTPORTPARAM *psPortParam) { int i, iMaxPort; char szDbg[128]; iMaxPort = GetMaxPort(); sprintf(szDbg, ">>>commid=%d, MaxPort=%d, PrtPortStatus:", commid, iMaxPort); DebugPrint(szDbg); for(i=0; im_pPrtPortStatus[i].bPortIdle, psPortParam->m_pPrtPortStatus[i].mmid, psPortParam->m_pPrtPortStatus[i].timeOut); DebugPrint(szDbg); } strcpy(szDbg, "<<