/* * protect_simu.c * * Created on: 2013-5-27 * Author: Administrator */ #include "protect_simu.h" #include "rtdb.h" #include "shmbuff.h" #include "glbtypes.h" #include "glbsem.h" #include "stime.h" #include "general_function.h" #include "protect_61850.h" #include "protect_inter.h" //--------------------------------------------------------------------------------- //下面是保护相关模拟函数 //--------------------------------------------------------------------------------- #if 1 #include "iniparser.h" static int ycSpace = 500; static int yxSpace = 1000; static int sjbg1Num=1; static int sjbgSpace = 10*1000; static int gzbgSpace = 30*1000; static int atcjSpace = 20*1000; static int harmonSpace = 2*1000; static int ycNum=55;//CLZType_Buffer_YC_NUM*2;//54; static int sDeviceType = 131; static int sHarmonNum = 600; #define PROTECT_SIMU_YX_NUM 160 static DZ_VAL_TYPE sDzUser; static DZ_VAL_TYPE sDzSys; static ST_DOUBLE sYkYxSendTime=0.0; static ST_UCHAR sYkYxIndex=0; static ST_UCHAR sYkYxVal=1; static void protect_simul_send_yxburst_index( int yxIndex, unsigned char val ); static void protect_simul_set_datatype( DateType *date ); static int protect_write_cmd( unsigned char cmd) { unsigned char sendBuf[256]={0}; int iLoop; sendBuf[0] = 0x68; sendBuf[1] = 6; sendBuf[2] = cmd; sendBuf[3] = 0; sendBuf[4] = 1; sendBuf[5] = 0; sendBuf[6] = 1; sendBuf[7] = 0; sendBuf[8] = 0; for( iLoop=2; iLoop<8;iLoop++ ) { sendBuf[8] += sendBuf[iLoop]; } rtdb_protect_write_cmd( sendBuf ); return 0; } /************************************************************************/ /* 向保护程序发送命令,通用,自己添加用户数据长度 */ /************************************************************************/ ST_RET protect_write_cmd_genral( ST_INT linkIndex, unsigned char type, ST_UCHAR *data, ST_UCHAR dataLen ) { ST_UCHAR sendAsdu[256]; ST_RET ret; ST_INT iLoop; if( data == NULL ) { dataLen = 0; } sendAsdu[0] = 0x68; sendAsdu[1] = (ST_UCHAR)(0x6+dataLen); //长度 sendAsdu[2] = type; sendAsdu[3] = (ST_UCHAR)linkIndex; //地址 sendAsdu[4] = 1; //总帧数 sendAsdu[5] = 0; sendAsdu[6] = 1; //当前帧数 sendAsdu[7] = 0; //data if( dataLen > 0 ) { memcpy( sendAsdu+8, data, dataLen ); } dataLen += 8; sendAsdu[dataLen] = 0; //校验 for( iLoop=2; iLoopdzNum = PROTECT_SIMUL_USER_DZ_NUM; pucDz->dzSec = pucCmd[7]; for(iLoop=0; iLoopdzValBuff[4*iLoop] = iLoop; pucDz->dzValBuff[4*iLoop+1] = 0; pucDz->dzValBuff[4*iLoop+2] = 0; pucDz->dzValBuff[4*iLoop+3] = 0; pucDz->dzType[iLoop] = 5; } #if 0 //cbt modified 2019.5.28 CRCC认证修改定值校验码 //累加和 for (sum = 0,iLoop=3; iLoopdzValBuff[4*iLoop]; } memcpy( pucDz->dzValBuff+8, &sum, 4 ); #else //累加和 for (sum = 0,iLoop=0; iLoopdzValBuff[4*iLoop];//每个定值前3个字节为0,只加第4个字节 } pucDz->checkSum = sum; #endif //返回 memcpy( sendBuf, pucCmd, 10 ); sendBuf[9] -= sendBuf[8]; sendBuf[8] = 0; //返回成功 rtdb_protect_write_cmd( (unsigned char *)sendBuf ); } static void protect_simul_return_cmd_dz_sys_call( const unsigned char *pucCmd ) { unsigned char sendBuf[256]={0}; int iLoop; unsigned int sum; DZ_VAL_TYPE *pucDz; //设置定值区定值 inf_shm_get_addr_dz_prot_send(&pucDz); pucDz->dzNum = PROTECT_SIMUL_SYS_DZ_NUM; pucDz->dzSec = pucCmd[7]; for(iLoop=0; iLoopdzNum; iLoop++ ) { pucDz->dzValBuff[4*iLoop] = iLoop; pucDz->dzValBuff[4*iLoop+1] = 0; pucDz->dzValBuff[4*iLoop+2] = 0; pucDz->dzValBuff[4*iLoop+3] = 0; pucDz->dzType[iLoop] = 5; } #if 0 //cbt modified 2019.5.28 CRCC认证修改定值校验码 //累加和 for (sum = 0,iLoop=3; iLoopdzNum; iLoop++ ) { sum += pucDz->dzValBuff[4*iLoop]; } memcpy( pucDz->dzValBuff+8, &sum, 4 ); #else //累加和 for (sum = 0,iLoop=0; iLoopdzNum; iLoop++ )//取消前4个固定定值,即整定时间、校验码、定值区号和显示方式。校验码计算从第一个定值开始 { sum += pucDz->dzValBuff[4*iLoop];//每个定值前3个字节为0,只加第4个字节 } pucDz->checkSum = sum; #endif //返回 memcpy( sendBuf, pucCmd, 10 ); sendBuf[9] -= sendBuf[8]; sendBuf[8] = 0; //返回成功 rtdb_protect_write_cmd( (unsigned char *)sendBuf ); } //cbt add 2019.5.29 测试 修改定值 计算校验码是否正确 static void protect_simul_return_cmd_dz_set( const unsigned char *pucCmd ) { //unsigned char sendBuf[256]={0}; int iLoop, sum; DZ_VAL_TYPE *pucDz; //获取定值区定值 inf_shm_get_addr_dz_prot_recv(&pucDz); //累加和 for (sum = 0,iLoop=0; iLoop<4*pucDz->dzNum; iLoop++ )//取消前4个固定定值,即整定时间、校验码、定值区号和显示方式。校验码计算从第一个定值开始 { sum += pucDz->dzValBuff[iLoop]; } if( sum != pucDz->checkSum ) { //校验不符合 printf("Error. protect simul Recv upsend dz num=%d, caculate sum is 0x%lX, but send is 0x%lX.\n", pucDz->dzNum, sum, pucDz->checkSum ); //result = 3; } /* //返回 memcpy( sendBuf, pucCmd, 10 ); sendBuf[9] -= sendBuf[8]; sendBuf[8] = 0; //返回成功 rtdb_protect_write_cmd( (unsigned char *)sendBuf ); */ } static void protect_simul_return_cmd_yk( const ST_UCHAR *pucCmd ) { unsigned char sendBuf[256]={0}; memcpy( sendBuf, pucCmd, 11 ); sendBuf[1]++; sendBuf[11] = sendBuf[10]; sendBuf[10] = 0; //返回成功 //sMsSleep( 500 ); rtdb_protect_write_cmd( (unsigned char *)sendBuf ); //这里再模拟发送一个遥信 if( 3 == sendBuf[8] ) { sYkYxIndex = sendBuf[8]; sYkYxVal = sendBuf[9]; sYkYxSendTime= sGetMsTime() + 5*1000 + rand()%15 * 1000.0; } else { protect_simul_send_yxburst_index( sendBuf[8], sendBuf[9] ); } } static void protect_simul_return_cmd_vercall( const ST_UCHAR *pucCmd ) { unsigned char sendBuf[256]={0}; int iLoop,pos=0; memcpy( sendBuf, pucCmd, 9 ); //cbt modified 2021.3.29 保护上送的装置信息中的遥信数量改为2字节 pos = 8; sendBuf[pos++] = (ST_UCHAR)sDeviceType; //devtype sendBuf[pos++] = 'W'; sendBuf[pos++] = 'K'; sendBuf[pos++] = 'X'; sendBuf[pos++] = '_'; sendBuf[pos++] = '8'; sendBuf[pos++] = '9'; sendBuf[pos++] = '2'; sendBuf[pos++] = 0; sendBuf[pos++] = 0x12; //crc sendBuf[pos++] = 0x34; sendBuf[pos++] = 0x40; //ver sendBuf[pos++] = 0x01; //cbt modified 2021.3.29 保护上送的装置信息中的遥信数量改为2字节 //sendBuf[pos++] = PROTECT_SIMU_YX_NUM;//100;//protect_dev_info.yxNum = asdu[ucPos++]; sendBuf[pos++] = (ST_UCHAR)((PROTECT_SIMU_YX_NUM>>8)&0xff); sendBuf[pos++] = (ST_UCHAR)(PROTECT_SIMU_YX_NUM&0xff); sendBuf[pos++] = 20;//protect_dev_info.dzyxcfgNum = asdu[ucPos++]; sendBuf[pos++] = PROTECT_SIMUL_USER_DZ_NUM;//protect_dev_info.dzUsrNum = asdu[ucPos++]; sendBuf[pos++] = PROTECT_SIMUL_SYS_DZ_NUM;//cbt modified 2019.5.28 由22改为PROTECT_SIMUL_SYS_DZ_NUM //22;//protect_dev_info.dzSysNum = asdu[ucPos++]; sendBuf[pos++] = 23;//protect_dev_info.ddNum = asdu[ucPos++]; sendBuf[pos++] = (ST_UCHAR)sDeviceType;//装置类型 sendBuf[pos++] = 0x01; //dlq sendBuf[pos++] = 0x02; sendBuf[pos++] = 0x03; sendBuf[pos++] = 0x04; sendBuf[pos++] = 50; //frequence sendBuf[pos++] = (ST_UCHAR)ycNum; //ycNum sendBuf[pos] = 0;//校验码 for (iLoop=2; iLoopLBTime) ); pstWT->DeviceType = 1; pstWT->ChannelNum = 7; for( tmp=0; tmpChannelNum; tmp++ ) { if ((1+tmp)%3 == 0)//测试0类型的录波通道 { pstWT->ChannelData[tmp].Type = 0; } else { pstWT->ChannelData[tmp].Type = (ST_UCHAR)(1+tmp); } pstWT->ChannelData[tmp].Mode =1; pstWT->ChannelData[tmp].SampleNumber = 80; pstWT->ChannelData[tmp].XiShu = 1; pstWT->ChannelData[tmp].Length = 80*50; pstWT->ChannelData[tmp].RatioValue1 = 220; pstWT->ChannelData[tmp].RatioValue2 = 100; for( iLoop=0; iLoop<(int)(pstWT->ChannelData[tmp].Length); iLoop++ ) { pstWT->ChannelData[tmp].Data[iLoop] = (40+iLoop+10*tmp)%80 - 40; } } //填充数组量录波 //cbt add 2019.5.22 数字量录波缓冲区整合到 波形缓冲区里面,所以单独取 数字量录波缓冲区 就不需要了 //inf_shm_get_addr_fhlb_digital( &pstDigital); pstDigital = &(pstWT->DigitalData); pstDigital->Number = 18; for( iLoop=0; iLoopNumber; iLoop++ ) { pstDigital->Type[iLoop] = (ST_UCHAR)(iLoop+1); } pstDigital->Data[0] = 0; tmp = 0; for( iLoop=1; iLoop<(int)(pstWT->ChannelData[0].Length); iLoop++ ) { if( 0 == iLoop%160 ) { tmp *= 2; tmp++; if( (int)tmp >= (1<Number) ) { //超范围后清0 tmp = 0; } } pstDigital->Data[iLoop] = tmp; } rtdb_protect_write_cmd( (unsigned char *)pucCmd ); } static void protect_simul_read_cmds( const ST_UCHAR *pucCmd ) { //收到从接口来的命令 unsigned char cmdType,sendBuf[256]={0}; int iLoop; //判断校验是否满足要求 cmdType = pucCmd[2]; switch( cmdType ) { case 1: printf(">>Recv YX call from interact %d.\n", pucCmd[3] ); protect_simul_return_cmd_yxcall( pucCmd ); break; case 2: printf(">>Recv user-DZ call from interact %d.\n", pucCmd[3] ); protect_simul_return_cmd_dz_user_call( pucCmd ); break; case 3: printf(">>Recv user-sys-DZ call from interact %d.\n", pucCmd[3] ); protect_simul_return_cmd_dz_sys_call( pucCmd ); break; case 5: case 6: //写用户定值 printf(">>Recv user-sys-DZ set from interact %d.\n", pucCmd[3] ); protect_simul_return_cmd_dz_set(pucCmd); break; case 9: printf(">>Recv YK from interact %d.\n", pucCmd[3] ); protect_simul_return_cmd_yk( pucCmd ); break; case 11: printf(">>Recv FHLB call from interact %d.\n", pucCmd[3] ); protect_simul_return_cmd_fhlb( pucCmd ); break; case 12: printf(">>Recv VER call from interact.\n"); protect_simul_return_cmd_vercall( pucCmd ); break; case 18: //更新镜像文件 printf(">>Recv SYSFile renew from interact.\n"); memcpy( sendBuf, pucCmd, 9 ); sendBuf[8] = 0; //devAddr sendBuf[9] = 0; for (iLoop=2; iLoop<9; iLoop++ ) { sendBuf[9] += sendBuf[iLoop]; } sendBuf[1] = 7; rtdb_protect_write_cmd( sendBuf ); break; case PROTOCOL_DATA_TYPE_SYSTIME: PRINT_LOG("protect_simu recv commcpu systime request cmd\n"); if (pucCmd[8]!=1)//方向不对 { return; } { ST_UINT32 Sec=0; ST_UINT32 milSec = 0; #if defined(_WIN32) SYSTEMTIME sysTime; #endif /* _WIN32 */ #if defined(sun) || defined(linux) struct timeval tp; struct timezone tzp; #endif /* defined(sun) || defined(linux) */ #if defined(_WIN32) /* VC++, 32-Bit */ Sec = ( ST_ULONG )time( NULL ); GetSystemTime(& sysTime ); milSec = sysTime.wMilliseconds; #endif /* _WIN32 */ #if defined(sun) || defined(linux) gettimeofday (& tp, & tzp ); Sec = tp.tv_sec; milSec = tp.tv_usec / 1000; #endif /* defined(sun) || defined(linux) */ memcpy( sendBuf, pucCmd, 9 ); sendBuf[8] = 2;//返回时间,方向为2 sendBuf[9] = SYSTIME_SOURCE_TYPE_CODEB;//时钟源,3表示B码 memcpy(sendBuf+10, &Sec,4); memcpy(sendBuf+14,&milSec,4); sendBuf[18]=0;//校验码 for (iLoop=2; iLoop<18; iLoop++ ) { sendBuf[18] += sendBuf[iLoop]; } sendBuf[1] = 16;//长度(不算前两个字节和校验码字节) rtdb_protect_write_cmd( sendBuf ); } break; default: printf(">>Recv cmdtype=%d unknown.\n", cmdType ); break; } } static void protect_simul_set_datatype( DateType *date ) { ST_UCHAR cp56[8]={11,22,33, 22,11, 5, 6, 8}; function_get_local_cp56time( cp56 ); date->Msecond = cp56[0]+cp56[1]*0x100; date->Minute = cp56[2]; date->Hour = cp56[3]; date->Date = cp56[4]; date->Month = cp56[5]; date->Year = 2000+cp56[6]; } #if 0 static void protect_simul_send_goose( void ) { ST_DOUBLE nowTime; static ST_DOUBLE gooseTime=0; nowTime = sGetMsTime(); //nowTime = 0; if( nowTime > gooseTime ) { static ST_UCHAR dpi=1; gooseTime = nowTime+2*1000; gw61850gse_data_value_change(1,0,101,&dpi); gw61850gse_check_and_send( ); if( dpi == 1 ) { dpi = 2; } else { dpi = 1; } } } #endif static void protect_simul_send_l2( void ) { ST_DOUBLE nowTime; static ST_DOUBLE l2Time=0; CLZBuffType *pucClz; GdbLLBuffType *pGdbLL=NULL; if( 0 == ycSpace ) return; nowTime = sGetMsTime(); //nowTime = 0; inf_shm_get_addr_clz(&pucClz); if( nowTime > l2Time ) { ST_UCHAR cp56[8]; ST_INT iLoop; static ST_UCHAR status=0x55, loopCount=0; function_get_local_cp56time( cp56 ); l2Time = nowTime + ycSpace; //写二级数据命令不发命令,接口实时读循环缓冲 //protect_write_cmd_l2( ); //修改指针(需要判断是否覆盖读指针?) //pucClz->WriteIP = ( pucClz->WriteIP+1)%CLZLISTLEN;//cbt modified 2021.3.17 应该写完再更新 写指针 pucClz->WriteIP = ( pucClz->WriteIP)%CLZLISTLEN; protect_simul_set_datatype( &(pucClz->Buffer[pucClz->WriteIP].Time) ); pucClz->Buffer[pucClz->WriteIP].DeviceType = sDeviceType;//cbt add 2021.3.17 添加装置类型 #if 1 if( ycNum > CLZType_Buffer_YC_NUM )//超过最大个数55个 { if( 0 == loopCount%2)//非遥测后续帧 { pucClz->Buffer[pucClz->WriteIP].Number = (CLZType_Buffer_YC_NUM*2);//buffer.Number存储一次和二次的个数之和 pucClz->Buffer[pucClz->WriteIP].Buffer[0].Reserve = 0;//一次值的Reserve,即偏移量 pucClz->Buffer[pucClz->WriteIP].Buffer[CLZType_Buffer_YC_NUM].Reserve = 0;//二次值的Reserve,即偏移量 } else//遥测后续帧 { pucClz->Buffer[pucClz->WriteIP].Number = (ST_UCHAR)(( (ycNum-CLZType_Buffer_YC_NUM)%(CLZType_Buffer_YC_NUM+1) ) * 2); pucClz->Buffer[pucClz->WriteIP].Buffer[0].Reserve = CLZType_Buffer_YC_NUM;//一次值的Reserve,即偏移量 pucClz->Buffer[pucClz->WriteIP].Buffer[CLZType_Buffer_YC_NUM].Reserve = CLZType_Buffer_YC_NUM;//二次值的Reserve,即偏移量 } } else { pucClz->Buffer[pucClz->WriteIP].Number = ycNum*2; pucClz->Buffer[pucClz->WriteIP].Buffer[0].Reserve = 0; } for( iLoop=0; iLoopBuffer[pucClz->WriteIP].Number; iLoop++ ) { if (iLoop<(pucClz->Buffer[pucClz->WriteIP].Number/2))//一次值 { pucClz->Buffer[pucClz->WriteIP].Buffer[iLoop].Mode = 0; pucClz->Buffer[pucClz->WriteIP].Buffer[iLoop].Type = 1;//cbt add pucClz->Buffer[pucClz->WriteIP].Buffer[iLoop].Value = (float) (iLoop+1+10*loopCount); } else//cbt add 2021.3.17 添加二次值 { pucClz->Buffer[pucClz->WriteIP].Buffer[iLoop].Mode = 1; pucClz->Buffer[pucClz->WriteIP].Buffer[iLoop].Type = 1;//cbt add pucClz->Buffer[pucClz->WriteIP].Buffer[iLoop].Value = (float) ((iLoop+1+10*loopCount)*27.5); } } for( iLoop=0; iLoopBuffer[pucClz->WriteIP].RunStatus[iLoop] = status; } //更改IO开入、开出 for( iLoop=0; iLoopBuffer[pucClz->WriteIP].KaiRuStatus_IO[iLoop] = status; } for( iLoop=0; iLoopBuffer[pucClz->WriteIP].KaiChuStatus_IO[iLoop] = status; } for( iLoop=0; iLoopBuffer[pucClz->WriteIP].KaiRuStatus_GS[iLoop] = status; } for( iLoop=0; iLoopBuffer[pucClz->WriteIP].KaiChuStatus_GS[iLoop] = status; } loopCount++; if( loopCount %2 == 0 ) { status ^= (1<<(loopCount%8)); //loopCount = 0; } if( loopCount>6000 ) loopCount=0; #else if( ycNum > 30 ) { if( 0 == loopCount%2) { pucClz->Buffer[pucClz->WriteIP].Number = 30; pucClz->Buffer[pucClz->WriteIP].Buffer[0].Reserve = 0; } else { pucClz->Buffer[pucClz->WriteIP].Number = (ST_UCHAR)( (ycNum-30)%30 ); pucClz->Buffer[pucClz->WriteIP].Buffer[0].Reserve = 30; } } else { pucClz->Buffer[pucClz->WriteIP].Number = ycNum; pucClz->Buffer[pucClz->WriteIP].Buffer[0].Reserve = 0; } for( iLoop=0; iLoopBuffer[pucClz->WriteIP].Number; iLoop++ ) { pucClz->Buffer[pucClz->WriteIP].Buffer[iLoop].Mode = 0; pucClz->Buffer[pucClz->WriteIP].Buffer[iLoop].Value = (float) (iLoop+1+10*loopCount); } for( iLoop=0; iLoop<4; iLoop++) { pucClz->Buffer[pucClz->WriteIP].RunStatus[iLoop] = status; } //更改IO开入、开出 for( iLoop=0; iLoop<16; iLoop++) { pucClz->Buffer[pucClz->WriteIP].KaiRuStatus_IO[iLoop] = status; } for( iLoop=0; iLoop<8; iLoop++) { pucClz->Buffer[pucClz->WriteIP].KaiChuStatus_IO[iLoop] = status; } for( iLoop=0; iLoop<20; iLoop++) { pucClz->Buffer[pucClz->WriteIP].KaiRuStatus_GS[iLoop] = status; pucClz->Buffer[pucClz->WriteIP].KaiChuStatus_GS[iLoop] = status; } loopCount++; if( loopCount %2 == 0 ) { status ^= (1<<(loopCount%8)); //loopCount = 0; } if( loopCount>6000 ) loopCount=0; #endif pucClz->WriteIP = ( pucClz->WriteIP+1)%CLZLISTLEN;//cbt modified 2021.3.17 应该写完再更新 写指针 if(loopCount%2) { //cbt add 2021.5.17 添加供电臂联络信号的模拟上送 inf_shm_get_addr_gdb_ll( &pGdbLL ); if(pGdbLL) { for (iLoop=0;iLoopgdbLianluo[iLoop] = iLoop+loopCount;//有遥测后续帧时每次加2,无遥测后续帧时每次加1 } pGdbLL->isUse = 1; } } } } static void protect_simul_send_groupSoe( void ) { ST_DOUBLE nowTime; static ST_DOUBLE gzTime=0; GroupSoeReportType *pstFRT; int iLoop, jLoop,tmp; if( 0 == gzbgSpace ) return; nowTime = sGetMsTime(); //nowTime = 0; inf_shm_get_addr_groupSoe( &pstFRT ); if( nowTime > gzTime+2000 )//cbt modified 2021.7.6 在故障报告产生之后100ms之后再产生成组事件报告 { //WaveType *pstWT; gzTime = nowTime + gzbgSpace; pstFRT->WriteIP = (pstFRT->WriteIP)%GROUP_SOE_NUM; #if 0 //成组事件报告的故障报告部分没有,体现为动作标识为0并且故障电量个数为0 //cbt add 2019.5.22 数字量录波缓冲区整合到 波形缓冲区里面 //pDigi = pucDigital->Buffer+pstFRT->WriteIP; pDigi = &(pstFRT->Buffer[pstFRT->WriteIP].WaveValue.DigitalData); pstFRT->Buffer[pstFRT->WriteIP].DLQNo = 0x1234; pstFRT->Buffer[pstFRT->WriteIP].ParameterNumber = 20; tmp = (int)gzTime; for (iLoop=0; iLoopBuffer[pstFRT->WriteIP].ParameterNumber; iLoop++ ) { pstFRT->Buffer[pstFRT->WriteIP].DataBuffer[iLoop].Value = (float)(tmp%1000 + 10*iLoop); pstFRT->Buffer[pstFRT->WriteIP].DataBuffer[iLoop].Mode = 1;//0;//默认是一次,(0:1次,1:2次) pstFRT->Buffer[pstFRT->WriteIP].DataBuffer[iLoop].Type = 32+iLoop; } pstFRT->Buffer[pstFRT->WriteIP].DeviceType = sDeviceType; //1; cbt modified2019.5.22,装置类型采用simulate.ini配置的装置类型 pstFRT->Buffer[pstFRT->WriteIP].DongZuoIP = 0x80; //cbt add 2019.6.13 封装重合闸标识 pstFRT->Buffer[pstFRT->WriteIP].ChongZha = 3; protect_simul_set_datatype( &(pstFRT->Buffer[pstFRT->WriteIP].FaultDate) ); pstFRT->Buffer[pstFRT->WriteIP].HasWave =1; #else memset(&(pstFRT->Buffer[pstFRT->WriteIP]),0,sizeof(GroupSoeItemType)); pstFRT->Buffer[pstFRT->WriteIP].DLQNo = 0x1234; pstFRT->Buffer[pstFRT->WriteIP].ParameterNumber = 0; pstFRT->Buffer[pstFRT->WriteIP].DeviceType = sDeviceType; //1; cbt modified2019.5.22,装置类型采用simulate.ini配置的装置类型 pstFRT->Buffer[pstFRT->WriteIP].DongZuoIP = 0; protect_simul_set_datatype( &(pstFRT->Buffer[pstFRT->WriteIP].FaultDate) ); pstFRT->Buffer[pstFRT->WriteIP].HasWave =0; #endif pstFRT->Buffer[pstFRT->WriteIP].SoeNumber = 12; //cbt modified 2019.6.12 1个改为10个 for (iLoop=0;iLoopBuffer[pstFRT->WriteIP].SoeNumber;iLoop++) { pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeCode = 2000+iLoop; pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeTime = 100+iLoop; protect_simul_set_datatype( &(pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeDate) ); pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeParaNum = iLoop%SOE_VALUE_NUM; for (jLoop=0;(jLoopBuffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeValue[jLoop].Mode = 1;//0;//默认是一次,(0:1次,1:2次) pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeValue[jLoop].Type = 32+jLoop;//保护事件的模拟量类型码从2000开始 pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeValue[jLoop].Value = (float)((jLoop+1)*27.5); } //其余9个soe全部填的是0 } /* cbt modified 2021.7.2 成组事件报告无录波 pstWT = &( pstFRT->Buffer[pstFRT->WriteIP].WaveValue ); protect_simul_set_datatype( &(pstWT->LBTime) ); pstWT->DeviceType = sDeviceType; pstWT->ChannelNum = 7; for( jLoop=0; jLoopChannelNum; jLoop++ ) { if ((1+jLoop)%3 == 0)//测试0类型的录波通道 { pstWT->ChannelData[jLoop].Type =0; } else { pstWT->ChannelData[jLoop].Type =1+jLoop; } pstWT->ChannelData[jLoop].Mode =1; pstWT->ChannelData[jLoop].SampleNumber = 80; pstWT->ChannelData[jLoop].XiShu = 1; pstWT->ChannelData[jLoop].Length = 80*50; for( iLoop=0; iLoop<(int)(pstWT->ChannelData[0].Length); iLoop++ ) { pstWT->ChannelData[jLoop].Data[iLoop] = (40 + 40*jLoop + iLoop)%80 - 40; } } //填充数组量录波 pDigi->Number = 18; for( iLoop=0; iLoopNumber; iLoop++ ) { pDigi->Type[iLoop] = (ST_UCHAR)(iLoop+1); } pDigi->Data[0] = 0; tmp = 0; for( iLoop=1; iLoop<(int)(pstWT->ChannelData[0].Length); iLoop++ ) { if( 0 == iLoop%160 ) { tmp *= 2; tmp++; if( tmp >= (1<Number) ) { //超范围后清0 tmp = 0; } } pDigi->Data[iLoop] = tmp; } */ pstFRT->WriteIP = (pstFRT->WriteIP+1)%GROUP_SOE_NUM; } } static void protect_simul_send_gzbg( void ) { ST_DOUBLE nowTime; static ST_DOUBLE gzTime=0; static ST_UINT32 paramBase=0;//测试 故障报告 参数值依次加1 FaultReportType *pstFRT; int iLoop, jLoop,tmp; //DigitalBuffType *pucDigital; DigitalChlType *pDigi; if( 0 == gzbgSpace ) return; nowTime = sGetMsTime(); //nowTime = 0; inf_shm_get_addr_gzbg( &pstFRT ); //inf_shm_get_addr_digital( &pucDigital );//cbt add 2019.5.22 数字量录波缓冲区整合到 波形缓冲区里面,所以单独取 数字量录波缓冲区 就不需要了 if( nowTime > gzTime ) { WaveType *pstWT; gzTime = nowTime + gzbgSpace; pstFRT->WriteIP = (pstFRT->WriteIP)%FAULT_NUM; //cbt add 2019.5.22 数字量录波缓冲区整合到 波形缓冲区里面 //pDigi = pucDigital->Buffer+pstFRT->WriteIP; pDigi = &(pstFRT->Buffer[pstFRT->WriteIP].WaveValue.DigitalData); pstFRT->Buffer[pstFRT->WriteIP].DLQNo = 0x1234; pstFRT->Buffer[pstFRT->WriteIP].ParameterNumber = 20; tmp = (int)gzTime; paramBase++; for (iLoop=0; iLoopBuffer[pstFRT->WriteIP].ParameterNumber; iLoop++ ) { pstFRT->Buffer[pstFRT->WriteIP].DataBuffer[iLoop].Value = (float)(paramBase%1000 + 1*iLoop); pstFRT->Buffer[pstFRT->WriteIP].DataBuffer[iLoop].Mode = 1;//0;//默认是一次,(0:1次,1:2次) pstFRT->Buffer[pstFRT->WriteIP].DataBuffer[iLoop].Type = /*32+*/(131+(61*iLoop))%256; } pstFRT->Buffer[pstFRT->WriteIP].DeviceType = sDeviceType; //1; cbt modified2019.5.22,装置类型采用simulate.ini配置的装置类型 pstFRT->Buffer[pstFRT->WriteIP].DongZuoIP = 0x80; //cbt add 2019.6.13 封装重合闸标识 pstFRT->Buffer[pstFRT->WriteIP].ChongZha = 3; protect_simul_set_datatype( &(pstFRT->Buffer[pstFRT->WriteIP].FaultDate) ); pstFRT->Buffer[pstFRT->WriteIP].HasWave =1; pstFRT->Buffer[pstFRT->WriteIP].SoeNumber = 12; //cbt modified 2019.6.12 1个改为10个 for (iLoop=0;iLoopBuffer[pstFRT->WriteIP].SoeNumber;iLoop++) { pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeCode = 2000+iLoop; pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeTime = 100+iLoop; protect_simul_set_datatype( &(pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeDate) ); pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeParaNum = iLoop%SOE_VALUE_NUM; for (jLoop=0;(jLoop<(iLoop%SOE_VALUE_NUM));jLoop++) { pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeValue[jLoop].Mode = 1;//0;//默认是一次,(0:1次,1:2次) pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeValue[jLoop].Type = 32+jLoop;//保护事件的模拟量类型码从2000开始 pstFRT->Buffer[pstFRT->WriteIP].SoeBuffer[iLoop].SoeValue[jLoop].Value = (float)((jLoop+1)*27.5); } //其余9个soe全部填的是0 } pstWT = &( pstFRT->Buffer[pstFRT->WriteIP].WaveValue ); protect_simul_set_datatype( &(pstWT->LBTime) ); pstWT->DeviceType = sDeviceType; pstWT->ChannelNum = 7; for( jLoop=0; jLoopChannelNum; jLoop++ ) { if ((1+jLoop)%3 == 0)//测试0类型的录波通道 { pstWT->ChannelData[jLoop].Type =0; } else { pstWT->ChannelData[jLoop].Type =1+jLoop; } pstWT->ChannelData[jLoop].Mode =1; pstWT->ChannelData[jLoop].SampleNumber = 80; pstWT->ChannelData[jLoop].XiShu = 1; pstWT->ChannelData[jLoop].Length = 80*50; for( iLoop=0; iLoop<(int)(pstWT->ChannelData[0].Length); iLoop++ ) { pstWT->ChannelData[jLoop].Data[iLoop] = (40 + 40*jLoop + iLoop+paramBase)%80 - 40;//test 录波每次不同 } } //填充数组量录波 pDigi->Number = 18; for( iLoop=0; iLoopNumber; iLoop++ ) { pDigi->Type[iLoop] = (ST_UCHAR)(iLoop+1); } pDigi->Data[0] = 0; tmp = 0; for( iLoop=1; iLoop<(int)(pstWT->ChannelData[0].Length); iLoop++ ) { if( 0 == iLoop%160 ) { tmp *= 2; tmp++; if( tmp >= (1<Number) ) { //超范围后清0 tmp = 0; } } pDigi->Data[iLoop] = tmp; } pstFRT->WriteIP = (pstFRT->WriteIP+1)%FAULT_NUM; } } static void protect_simul_send_sjbg( ST_UCHAR type ) { ST_DOUBLE nowTime; static ST_DOUBLE sjTime=3000;//for 保护事件 static ST_DOUBLE operTime = 3000;//for 操作事件 static ST_UINT32 sjParamBase=0;//测试 保护事件 参数值依次加1 if (type == 0)//保护事件 { SoeBufferType *pstSoe; if( 0 == sjbgSpace ) return; nowTime = sGetMsTime(); //nowTime = 0; inf_shm_get_addr_sjbg( &pstSoe ); if( nowTime > sjTime ) { int iLoop; sjTime = nowTime + sjbgSpace; sjParamBase++; for( iLoop=0; iLoopWriteIP = (pstSoe->WriteIP+0)%SOE_SUM_NUM; protect_simul_set_datatype( &(pstSoe->Buffer[pstSoe->WriteIP].SoeDate) ); pstSoe->Buffer[pstSoe->WriteIP].SoeCode = (unsigned short)(1013+iLoop); pstSoe->Buffer[pstSoe->WriteIP].SoeTime = 100+iLoop; pstSoe->Buffer[pstSoe->WriteIP].SoeParaNum = 1; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[0].Mode = 1; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[0].Type =1; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[0].Value = (float)(sjParamBase+iLoop); pstSoe->WriteIP = (pstSoe->WriteIP+1)%SOE_SUM_NUM; } } } else if (type ==1) { OperReportType *pstSoe; if( 0 == sjbgSpace ) return; nowTime = sGetMsTime(); //nowTime = 0; inf_shm_get_addr_operbg( &pstSoe ); if( nowTime > operTime ) { int iLoop; operTime = nowTime + sjbgSpace; for( iLoop=0; iLoopWriteIP = (pstSoe->WriteIP+0)%OperReportNUM; protect_simul_set_datatype( &(pstSoe->Buffer[pstSoe->WriteIP].SoeDate) ); pstSoe->Buffer[pstSoe->WriteIP].SoeCode = (unsigned short)(5005+iLoop); pstSoe->Buffer[pstSoe->WriteIP].SoeTime = 100; pstSoe->Buffer[pstSoe->WriteIP].SoeParaNum = 2; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[0].Mode = 1; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[0].Type = 1; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[0].Value = 200; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[1].Mode = 1; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[1].Type = 2; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[1].Value = 300; //pstSoe->Buffer[pstSoe->WriteIP].addressID = sDeviceId + pstSoe->WriteIP%sDeviceNum; pstSoe->WriteIP = (pstSoe->WriteIP+1)%OperReportNUM; } } } } static void protect_simul_send_zjbg( void ) { ST_DOUBLE nowTime; static ST_DOUBLE sjTime=5000; CheckReportType *pstSoe; if( 0 == sjbgSpace ) return; nowTime = sGetMsTime(); //nowTime = 0; inf_shm_get_addr_zjbg( &pstSoe ); if( nowTime > sjTime ) { sjTime = nowTime + sjbgSpace; pstSoe->WriteIP = (pstSoe->WriteIP+0)%CheckReportNUM; protect_simul_set_datatype( &(pstSoe->Buffer[pstSoe->WriteIP].SoeDate) ); pstSoe->Buffer[pstSoe->WriteIP].SoeCode = 5; pstSoe->Buffer[pstSoe->WriteIP].SoeTime = 100; pstSoe->Buffer[pstSoe->WriteIP].SoeParaNum = 1; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[0].Mode = 1; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[0].Type =1; pstSoe->Buffer[pstSoe->WriteIP].SoeValue[0].Value = 500; pstSoe->WriteIP = (pstSoe->WriteIP+1)%CheckReportNUM; } } static void protect_simul_send_yxburst( void ) { ST_DOUBLE nowTime; static ST_DOUBLE yxTime=100; YaoXinStrucType *pstYx; static int iLoop=0; static char status=0; if( 0 == yxSpace ) return; nowTime = sGetMsTime(); //nowTime = 0; inf_shm_get_addr_yxbur( &pstYx ); if( nowTime > yxTime ) { yxTime = nowTime + yxSpace; pstYx->WriteIP = (pstYx->WriteIP)%YaoXin_NUM; protect_simul_set_datatype( &(pstYx->Buffer[pstYx->WriteIP].ChangeDate) ); if (iLoop%2==0)//cbt add 2021.3.22 同时产生遥信变位和装置事件 { pstYx->Buffer[pstYx->WriteIP].ObjectNo = iLoop/2+1; } else { pstYx->Buffer[pstYx->WriteIP].ObjectNo = iLoop/2+141;//141~160为装置事件 } iLoop++; if( iLoop > 40 ) { iLoop=0; } pstYx->Buffer[pstYx->WriteIP].Status = status+1; status = !status; pstYx->WriteIP = (pstYx->WriteIP+1)%YaoXin_NUM; } } static void protect_simul_send_yxburst_index( int yxIndex, unsigned char val ) { ST_DOUBLE nowTime; YaoXinStrucType *pstYx; nowTime = sGetMsTime(); //nowTime = 0; inf_shm_get_addr_yxbur( &pstYx ); pstYx->WriteIP = (pstYx->WriteIP)%YaoXin_NUM; protect_simul_set_datatype( &(pstYx->Buffer[pstYx->WriteIP].ChangeDate) ); pstYx->Buffer[pstYx->WriteIP].ObjectNo = yxIndex; pstYx->Buffer[pstYx->WriteIP].Status = val; pstYx->WriteIP = (pstYx->WriteIP+1)%YaoXin_NUM; } static void protect_simul_send_yxburst_yk_return( void ) { ST_DOUBLE nowTime; if( 10 > sYkYxSendTime ) return; nowTime = sGetMsTime(); if( nowTime > sYkYxSendTime ) { protect_simul_send_yxburst_index( sYkYxIndex, sYkYxVal ); sYkYxSendTime = 0.0; } } static void protect_simul_send_atcj( unsigned char ifSendCmd ) { //主动发送AT测距命令, 或者对AT测距召唤命令,回答数据 if( ifSendCmd ) { ST_DOUBLE nowTime; static ST_DOUBLE atTime=1000; struct{ unsigned char CallType; //命令类型,取值范围0x21——0x2F unsigned char SPOT; //本变电所的编号(可选,保护不使用置0) unsigned char stationDev; //接收命令的AT或分区所装置的地址 unsigned char unused; //预留1字节,置0 unsigned char stationIP[4]; //命令所要发给的AT或分区所的IP,如192.168.3.101,则stationIP[0]=192,stationIP[3]=101。 } ATGC_CmdBufType; //要数据结构 nowTime = sGetMsTime(); if( nowTime > atTime && atcjSpace ) { atTime = nowTime + atcjSpace; ATGC_CmdBufType.CallType = 0x21; ATGC_CmdBufType.SPOT = 100; ATGC_CmdBufType.stationDev = 110; ATGC_CmdBufType.stationIP[0] = 192; ATGC_CmdBufType.stationIP[1] = 168; ATGC_CmdBufType.stationIP[2] = 1; ATGC_CmdBufType.stationIP[3] = 72; protect_write_cmd_genral(0, 25, (unsigned char *)&ATGC_CmdBufType, sizeof(ATGC_CmdBufType) ); } } else { //返回数据 //接收其它所的数据 struct{ unsigned char DataType; //数据类型,取值范围0x31——0x3F unsigned char SPOT; //发送本数据的分区或AT所的编号(可选,保护不使用置0) unsigned char stationDev; //接收数据的变电所装置的地址 unsigned char unused; //预留1字节,置0 unsigned char stationIP[4]; //命令所要发给的变电所的IP //ATGC_GZBufType CommData; //通信数据 unsigned char data[8]; } ATGC_DataBufType; ATGC_DataBufType.DataType = 0x31; ATGC_DataBufType.SPOT = 110; ATGC_DataBufType.stationDev = 100; ATGC_DataBufType.stationIP[0] = 192; ATGC_DataBufType.stationIP[1] = 168; ATGC_DataBufType.stationIP[2] = 1; ATGC_DataBufType.stationIP[3] = 72; protect_write_cmd_genral(0, 25, (unsigned char *)&ATGC_DataBufType, sizeof(ATGC_DataBufType) ); } } static void protect_simul_send_harmon( void ) { ST_DOUBLE nowTime; static ST_DOUBLE harmonTime=0; HarmonBuffType *pucClz; if( 0 == harmonSpace ) return; nowTime = sGetMsTime(); //nowTime = 0; inf_shm_get_addr_harmon(&pucClz); if( nowTime > harmonTime ) { ST_INT iLoop; static ST_UCHAR loopCount=0; harmonTime = nowTime + harmonSpace; //写二级数据命令不发命令,接口实时读循环缓冲 //protect_write_cmd_l2( ); //修改指针(需要判断是否覆盖读指针?) pucClz->WriteIP = ( pucClz->WriteIP+1)%HARMON_BUFF_NUM; pucClz->Buffer[pucClz->WriteIP].Number = sHarmonNum; for( iLoop=0; iLoopBuffer[pucClz->WriteIP].Number; iLoop++ ) { pucClz->Buffer[pucClz->WriteIP].HarmonData[iLoop].Quality = 0; pucClz->Buffer[pucClz->WriteIP].HarmonData[iLoop].Value = (float) (iLoop+1+10*loopCount); } loopCount++; if( loopCount>6000 ) loopCount=0; } } static void protect_simul_init_cfg( void ) { static int isInit=0; dictionary * ini ; int iLoop; DZ_VAL_TYPE *pucDz; if( isInit ) return; isInit = 1; //初始化 ini = iniparser_load("./cfg/simulate.ini"); if( NULL == ini ) return; ycSpace = iniparser_getint(ini, "YC:space", 500, 0); harmonSpace = iniparser_getint(ini, "YC:harmon", 3000, 0); yxSpace = iniparser_getint(ini, "YX:space", 1000, 0); sjbg1Num = iniparser_getint(ini, "SJBG:number", 1, 0); sjbgSpace = iniparser_getint(ini, "SJBG:space", 10000, 0); gzbgSpace = iniparser_getint(ini, "GZBG:space", 30000, 0); sDeviceType = iniparser_getint(ini, "DEVICE:typeCode", 131, 0); iniparser_freedict( ini ); //设置定值区定值 pucDz = &sDzUser; pucDz->dzNum = PROTECT_SIMUL_USER_DZ_NUM; pucDz->dzSec = 0; for(iLoop=0; iLoopdzNum; iLoop++ ) { pucDz->dzValBuff[4*iLoop] = iLoop; pucDz->dzValBuff[4*iLoop+1] = 0; pucDz->dzValBuff[4*iLoop+2] = 0; pucDz->dzValBuff[4*iLoop+3] = 0; pucDz->dzType[iLoop] = 5; } pucDz = &sDzSys; pucDz->dzNum = PROTECT_SIMUL_SYS_DZ_NUM; pucDz->dzSec = 9; for(iLoop=0; iLoopdzNum; iLoop++ ) { pucDz->dzValBuff[4*iLoop] = iLoop; pucDz->dzValBuff[4*iLoop+1] = 0; pucDz->dzValBuff[4*iLoop+2] = 0; pucDz->dzValBuff[4*iLoop+3] = 0; pucDz->dzType[iLoop] = 5; } return; } #if 0 ST_THREAD_RET ST_THREAD_CALL_CONV protect_simul_handle( ST_THREAD_ARG arg ) #else ST_THREAD_RET protect_simul_handle( ST_THREAD_ARG arg ) #endif { unsigned char pucCmd[256]; protect_simul_init_cfg( ); //while ( 1) { int ret; ret = rtdb_protect_read_cmd(pucCmd); if( ret ) { //没有命令 } else { //处理命令 protect_simul_read_cmds( pucCmd ); } //模拟发送GOOSE //protect_simul_send_goose( ); protect_simul_send_l2( ); protect_simul_send_gzbg( ); protect_simul_send_groupSoe( ); protect_simul_send_sjbg(0); protect_simul_send_zjbg(); protect_simul_send_yxburst( ); protect_simul_send_sjbg(1); protect_simul_send_yxburst_yk_return(); protect_simul_send_atcj( 1 ); protect_simul_send_harmon( ); //sMsSleep(10); } return SD_SUCCESS; } #endif