104规约

名字委婉点 2014-12-04 03:52:44
104规约可变帧报文打包代码
...全文
752 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
ksx_120999 2016-04-20
  • 打赏
  • 举报
回复
好东西,顶一个,一起分享。。。
  • 打赏
  • 举报
回复
简直恐怖,有Java的代码吗?
名字委婉点 2014-12-09
  • 打赏
  • 举报
回复
引用 2 楼 xjq2003 的回复:

//设置遥测APCI
void CMainFrame::SetYCAPCI()
{
 memset(byteAPDUYC,0,sizeof(byteAPDUYC));//初始化
 //计算报头字节 
 //////////////////APCI//////////////////////////////////////////////////////
 byteAPDUYC[0] = 0x68;//报头字
 byteAPDUYC[1] = 0xFA;//APDU长度,最大253 计算**
     
 byteAPDUYC[2] = 0x12;//1 8位控制域 低位  00000010
 byteAPDUYC[3] = 0x00;//2 8位控制域 高位  00000000  
    // 0000000000000010 I格式发送帧计数
 byteAPDUYC[4] = 0x02;//3 8位控制域 低位 00000010
 byteAPDUYC[5] = 0x00;//4 8位控制域 高位 00000000
    // 0000000000000010 I格式接收帧计数
 /////////////////////ASDU////////////////////////////////////////////////
 byteAPDUYC[6] = 0x15;//标识符 遥测
 //可变帧限定词 10111100 第一位1表示连续,如果为0表示非连续
 byteAPDUYC[7] = 0xBC;//计算** 0111100 60个数据
 //传送原因
 byteAPDUYC[8] = 0x14;//响应总召唤 传送原因
 byteAPDUYC[9] = 0x00;//响应总召唤 传送原因
}


//发送遥信数据
void CMainFrame::SendYXData()
{
 //总遥信个数
 int iYXByteCout = dbm.yxsum;
 //APDU个数
 int iAPDUCout = 0;
 //最后一帧APDU字节数
 int iLastAPDUCout = 0;
 //最大遥信字节数
 int iMaxYx = 127;
 //得到APDU个数
 iAPDUCout = iYXByteCout / iMaxYx;
 //得到最后一帧APDU字节数
 iLastAPDUCout = iYXByteCout % iMaxYx;
    //循环组APDU
 for(int w=0;w<iAPDUCout;w++)
 {
  SetYXAPCI();
  //计算公共地址 ASDU地址
  BYTE *pXXTDZ = new byte[2]; 
  memcpy(pXXTDZ, &dbm.r_yx[w*iMaxYx].NU, 2); 
  //给公共地址赋值
  byteAPDU[10] =pXXTDZ[0]; //ASDU地址 可能要累加计算** (低位在前,高位在后)2A 75
  byteAPDU[11] =pXXTDZ[1];
  //释放临存公共地址的空间
  free(pXXTDZ); 
  //信息体
  //如果SQ=0,表示非连续数据,一个三字节信息地址,一个一字节遥信数据
  //如果SQ=1,表示连续数据,用公用地址,然后连续一个字节遥信数据
  int iIndex = 0;//累加号
  for(int i=(w*iMaxYx);i<((w+1)*iMaxYx);i++)
  {
   byteAPDU[12+iIndex] = (BYTE)dbm.r_yx[i].val;
   iIndex++;
  }
  //校验和CS
  byteAPDU[12+iIndex] = 0x89;
  //结束标识
  byteAPDU[13+iIndex] = 0x16;
  //发送
  if(m_pMListenSocket->CheckpClientSocket(m_pMListenSocket->m_pClientSocket))
  { 
   //SetSendBufData(byteAPDU,sizeof(byteAPDU));
   m_pMListenSocket->m_pClientSocket->SendTo(byteAPDU,141,atoi(strPort),strIP);
   Sleep(100);
  }
 }
 //最后一个APDU组包
    SetYXAPCI();
 //计算APDU长度
 int ilastLen = iLastAPDUCout+10;
 BYTE *pAPDULEN = new byte[1];
 memcpy(pAPDULEN, &ilastLen, 1); 
    byteAPDU[1] = pAPDULEN[0]; 
 //计算可变帧限定词
    BYTE *pAPDULENKB = new byte[1];
 memcpy(pAPDULENKB, &iLastAPDUCout, 1); 
    byteAPDU[7] =(pAPDULENKB[0]|0x80);//高位补1
    free(pAPDULENKB);
    //计算公共地址 ASDU地址
 BYTE *pXXTDZ = new byte[2]; 
 memcpy(pXXTDZ, &dbm.r_yx[iAPDUCout*iMaxYx].NU, 2);
 //给公共地址赋值
 byteAPDU[10] =pXXTDZ[0]; //ASDU地址 可能要累加计算** (低位在前,高位在后)2A 75
 byteAPDU[11] =pXXTDZ[1];
 //释放临存公共地址的空间
 free(pXXTDZ);
 int iIndex = 0;//顺序号
 for(int i=(iAPDUCout*iMaxYx);i<iYXByteCout;i++)
 {
  byteAPDU[12+iIndex] = (BYTE)dbm.r_yx[i].val;
  iIndex++;
 }
 //校验和CS
    byteAPDU[12+iIndex] = pAPDULEN[0];//CS校验和 
 free(pAPDULEN);
 //结束标识
 byteAPDU[13+iIndex] =0x16;
 //发送
 if(m_pMListenSocket->CheckpClientSocket(m_pMListenSocket->m_pClientSocket))
 {
  //SetSendBufData(byteAPDU,sizeof(byteAPDU));
    m_pMListenSocket->m_pClientSocket->SendTo(byteAPDU,sizeof(byteAPDU),atoi(strPort),strIP);
  Sleep(100);
 }
}
引用 2 楼 xjq2003 的回复:

//设置遥测APCI
void CMainFrame::SetYCAPCI()
{
 memset(byteAPDUYC,0,sizeof(byteAPDUYC));//初始化
 //计算报头字节 
 //////////////////APCI//////////////////////////////////////////////////////
 byteAPDUYC[0] = 0x68;//报头字
 byteAPDUYC[1] = 0xFA;//APDU长度,最大253 计算**
     
 byteAPDUYC[2] = 0x12;//1 8位控制域 低位  00000010
 byteAPDUYC[3] = 0x00;//2 8位控制域 高位  00000000  
    // 0000000000000010 I格式发送帧计数
 byteAPDUYC[4] = 0x02;//3 8位控制域 低位 00000010
 byteAPDUYC[5] = 0x00;//4 8位控制域 高位 00000000
    // 0000000000000010 I格式接收帧计数
 /////////////////////ASDU////////////////////////////////////////////////
 byteAPDUYC[6] = 0x15;//标识符 遥测
 //可变帧限定词 10111100 第一位1表示连续,如果为0表示非连续
 byteAPDUYC[7] = 0xBC;//计算** 0111100 60个数据
 //传送原因
 byteAPDUYC[8] = 0x14;//响应总召唤 传送原因
 byteAPDUYC[9] = 0x00;//响应总召唤 传送原因
}


//发送遥信数据
void CMainFrame::SendYXData()
{
 //总遥信个数
 int iYXByteCout = dbm.yxsum;
 //APDU个数
 int iAPDUCout = 0;
 //最后一帧APDU字节数
 int iLastAPDUCout = 0;
 //最大遥信字节数
 int iMaxYx = 127;
 //得到APDU个数
 iAPDUCout = iYXByteCout / iMaxYx;
 //得到最后一帧APDU字节数
 iLastAPDUCout = iYXByteCout % iMaxYx;
    //循环组APDU
 for(int w=0;w<iAPDUCout;w++)
 {
  SetYXAPCI();
  //计算公共地址 ASDU地址
  BYTE *pXXTDZ = new byte[2]; 
  memcpy(pXXTDZ, &dbm.r_yx[w*iMaxYx].NU, 2); 
  //给公共地址赋值
  byteAPDU[10] =pXXTDZ[0]; //ASDU地址 可能要累加计算** (低位在前,高位在后)2A 75
  byteAPDU[11] =pXXTDZ[1];
  //释放临存公共地址的空间
  free(pXXTDZ); 
  //信息体
  //如果SQ=0,表示非连续数据,一个三字节信息地址,一个一字节遥信数据
  //如果SQ=1,表示连续数据,用公用地址,然后连续一个字节遥信数据
  int iIndex = 0;//累加号
  for(int i=(w*iMaxYx);i<((w+1)*iMaxYx);i++)
  {
   byteAPDU[12+iIndex] = (BYTE)dbm.r_yx[i].val;
   iIndex++;
  }
  //校验和CS
  byteAPDU[12+iIndex] = 0x89;
  //结束标识
  byteAPDU[13+iIndex] = 0x16;
  //发送
  if(m_pMListenSocket->CheckpClientSocket(m_pMListenSocket->m_pClientSocket))
  { 
   //SetSendBufData(byteAPDU,sizeof(byteAPDU));
   m_pMListenSocket->m_pClientSocket->SendTo(byteAPDU,141,atoi(strPort),strIP);
   Sleep(100);
  }
 }
 //最后一个APDU组包
    SetYXAPCI();
 //计算APDU长度
 int ilastLen = iLastAPDUCout+10;
 BYTE *pAPDULEN = new byte[1];
 memcpy(pAPDULEN, &ilastLen, 1); 
    byteAPDU[1] = pAPDULEN[0]; 
 //计算可变帧限定词
    BYTE *pAPDULENKB = new byte[1];
 memcpy(pAPDULENKB, &iLastAPDUCout, 1); 
    byteAPDU[7] =(pAPDULENKB[0]|0x80);//高位补1
    free(pAPDULENKB);
    //计算公共地址 ASDU地址
 BYTE *pXXTDZ = new byte[2]; 
 memcpy(pXXTDZ, &dbm.r_yx[iAPDUCout*iMaxYx].NU, 2);
 //给公共地址赋值
 byteAPDU[10] =pXXTDZ[0]; //ASDU地址 可能要累加计算** (低位在前,高位在后)2A 75
 byteAPDU[11] =pXXTDZ[1];
 //释放临存公共地址的空间
 free(pXXTDZ);
 int iIndex = 0;//顺序号
 for(int i=(iAPDUCout*iMaxYx);i<iYXByteCout;i++)
 {
  byteAPDU[12+iIndex] = (BYTE)dbm.r_yx[i].val;
  iIndex++;
 }
 //校验和CS
    byteAPDU[12+iIndex] = pAPDULEN[0];//CS校验和 
 free(pAPDULEN);
 //结束标识
 byteAPDU[13+iIndex] =0x16;
 //发送
 if(m_pMListenSocket->CheckpClientSocket(m_pMListenSocket->m_pClientSocket))
 {
  //SetSendBufData(byteAPDU,sizeof(byteAPDU));
    m_pMListenSocket->m_pClientSocket->SendTo(byteAPDU,sizeof(byteAPDU),atoi(strPort),strIP);
  Sleep(100);
 }
}
有c#的例子代码吗。。。
xjq2003 2014-12-09
  • 打赏
  • 举报
回复

//设置遥测APCI
void CMainFrame::SetYCAPCI()
{
 memset(byteAPDUYC,0,sizeof(byteAPDUYC));//初始化
 //计算报头字节 
 //////////////////APCI//////////////////////////////////////////////////////
 byteAPDUYC[0] = 0x68;//报头字
 byteAPDUYC[1] = 0xFA;//APDU长度,最大253 计算**
     
 byteAPDUYC[2] = 0x12;//1 8位控制域 低位  00000010
 byteAPDUYC[3] = 0x00;//2 8位控制域 高位  00000000  
    // 0000000000000010 I格式发送帧计数
 byteAPDUYC[4] = 0x02;//3 8位控制域 低位 00000010
 byteAPDUYC[5] = 0x00;//4 8位控制域 高位 00000000
    // 0000000000000010 I格式接收帧计数
 /////////////////////ASDU////////////////////////////////////////////////
 byteAPDUYC[6] = 0x15;//标识符 遥测
 //可变帧限定词 10111100 第一位1表示连续,如果为0表示非连续
 byteAPDUYC[7] = 0xBC;//计算** 0111100 60个数据
 //传送原因
 byteAPDUYC[8] = 0x14;//响应总召唤 传送原因
 byteAPDUYC[9] = 0x00;//响应总召唤 传送原因
}


//发送遥信数据
void CMainFrame::SendYXData()
{
 //总遥信个数
 int iYXByteCout = dbm.yxsum;
 //APDU个数
 int iAPDUCout = 0;
 //最后一帧APDU字节数
 int iLastAPDUCout = 0;
 //最大遥信字节数
 int iMaxYx = 127;
 //得到APDU个数
 iAPDUCout = iYXByteCout / iMaxYx;
 //得到最后一帧APDU字节数
 iLastAPDUCout = iYXByteCout % iMaxYx;
    //循环组APDU
 for(int w=0;w<iAPDUCout;w++)
 {
  SetYXAPCI();
  //计算公共地址 ASDU地址
  BYTE *pXXTDZ = new byte[2]; 
  memcpy(pXXTDZ, &dbm.r_yx[w*iMaxYx].NU, 2); 
  //给公共地址赋值
  byteAPDU[10] =pXXTDZ[0]; //ASDU地址 可能要累加计算** (低位在前,高位在后)2A 75
  byteAPDU[11] =pXXTDZ[1];
  //释放临存公共地址的空间
  free(pXXTDZ); 
  //信息体
  //如果SQ=0,表示非连续数据,一个三字节信息地址,一个一字节遥信数据
  //如果SQ=1,表示连续数据,用公用地址,然后连续一个字节遥信数据
  int iIndex = 0;//累加号
  for(int i=(w*iMaxYx);i<((w+1)*iMaxYx);i++)
  {
   byteAPDU[12+iIndex] = (BYTE)dbm.r_yx[i].val;
   iIndex++;
  }
  //校验和CS
  byteAPDU[12+iIndex] = 0x89;
  //结束标识
  byteAPDU[13+iIndex] = 0x16;
  //发送
  if(m_pMListenSocket->CheckpClientSocket(m_pMListenSocket->m_pClientSocket))
  { 
   //SetSendBufData(byteAPDU,sizeof(byteAPDU));
   m_pMListenSocket->m_pClientSocket->SendTo(byteAPDU,141,atoi(strPort),strIP);
   Sleep(100);
  }
 }
 //最后一个APDU组包
    SetYXAPCI();
 //计算APDU长度
 int ilastLen = iLastAPDUCout+10;
 BYTE *pAPDULEN = new byte[1];
 memcpy(pAPDULEN, &ilastLen, 1); 
    byteAPDU[1] = pAPDULEN[0]; 
 //计算可变帧限定词
    BYTE *pAPDULENKB = new byte[1];
 memcpy(pAPDULENKB, &iLastAPDUCout, 1); 
    byteAPDU[7] =(pAPDULENKB[0]|0x80);//高位补1
    free(pAPDULENKB);
    //计算公共地址 ASDU地址
 BYTE *pXXTDZ = new byte[2]; 
 memcpy(pXXTDZ, &dbm.r_yx[iAPDUCout*iMaxYx].NU, 2);
 //给公共地址赋值
 byteAPDU[10] =pXXTDZ[0]; //ASDU地址 可能要累加计算** (低位在前,高位在后)2A 75
 byteAPDU[11] =pXXTDZ[1];
 //释放临存公共地址的空间
 free(pXXTDZ);
 int iIndex = 0;//顺序号
 for(int i=(iAPDUCout*iMaxYx);i<iYXByteCout;i++)
 {
  byteAPDU[12+iIndex] = (BYTE)dbm.r_yx[i].val;
  iIndex++;
 }
 //校验和CS
    byteAPDU[12+iIndex] = pAPDULEN[0];//CS校验和 
 free(pAPDULEN);
 //结束标识
 byteAPDU[13+iIndex] =0x16;
 //发送
 if(m_pMListenSocket->CheckpClientSocket(m_pMListenSocket->m_pClientSocket))
 {
  //SetSendBufData(byteAPDU,sizeof(byteAPDU));
    m_pMListenSocket->m_pClientSocket->SendTo(byteAPDU,sizeof(byteAPDU),atoi(strPort),strIP);
  Sleep(100);
 }
}
xjq2003 2014-12-09
  • 打赏
  • 举报
回复
104规约的报文帧分为三类:I帧、S帧和U帧。I帧称为信息帧,长度一定大于6个字节,被称作长帧,用于传输数据;S帧称为确认帧,长度只有6个字节,被称作短帧,用于确认接收的I帧;U帧称为控制帧,长度只有6个字节,也被称作短帧,用于控制启动/停止/测试。 长帧报文分为APCI和ASDU两个部分,而短帧报文只有APCI部分。APCI的6个字节是这样构成的: 起动字符68H,1个字节; 后面的报文长度,1个字节(最大253); 控制域位组,4个字节。 I帧的4字节控制域位组规定为:字节1和字节2为发送序号,字节3和字节4为接收序号。需注意两点:1、由于字节1和字节3的最低位固定为0,不用于构成序号,所以在计算序号时,要先转换为十进制数值,再除以2;2、由于低位字节在前、高位字节在后,所以计算时要先做颠倒。 S帧的字节1固定为01H,字节2固定为00H,字节3和字节4为接收序号。计算时仍要注意以上两点。 U帧的字节2、3、4均固定为00H,字节1包含TESTFR,STARTDT和STOPDT三种功能,同时只能激活其中的一种功能。启动 (STARTDT)和停止(STOPDT)都是由主站发起的,先由主站发送生效报文,子站随后确认。而主站和子站都可发送测试(TESTFR)报文,由另一方确认。 STARTDT:68 04 07 00 00 00(生效); 68 04 0B 00 00 00(确认) STOPDT:68 04 13 00 00 00(生效); 68 04 23 00 00 00(确认) TESTFR:68 04 43 00 00 00(生效); 68 04 83 00 00 00(确认) (ASDU部分) 只有I帧才有ASDU部分。ASDU是由数据单元标识符和信息体两部分构成的。 数据单元标识符包括: 类型标识,1个字节; 可变结构限定词,1个字节; 传送原因,2个字节; ASDU公共地址,2个字节。 信息体包括: 信息对象地址,3个字节; 信息元素集,若干字节; 时标,7个字节(可选)。 可变结构限定词是ASDU的第二个字节,其最高位=0表示后续的信息体的地址是不连续的,=1表示后续的信息体的地址是连续的。其余7位表示信息体的数量。 在101中信息对象地址使用2个字节,地址范围为1...65535。104使用3个字节的地址,范围为1...16777215。 各字节的具体定义需要查相应资料。 ==================================================== 目前我国电厂、变电站远动系统普遍采用基于电路的独立64kbit/s专线通道进行串口通信,串口通信协议多数为IEC60870-5-101和DNP3。0等,这些协议遵循基于ISO参考模型的增强性能结构(EPA),仅用了OSI模型7层中的3层(物理层、链路层、应用层)来实现数据传输。随着网络技术的迅猛发展和变电站IEC61850标准的逐步推广,为满足网络技术在电力系统中的应用,通过网络传输远动信息,以欧洲大型电力巨头公司(ABB,SIEMENS,ALSTOM)为首的IEC国际电工委员会在IEC60870-5-101基本远动任务配套标准[1~5]的基础上制定了IEC60870-5-104远动传输规约[6],采用平衡传输模式通过TCP/IP协议实现网络传输远动信息,适用于调度主站(中心站)EMS系统和子站(远方站)RTU或计算机监控系统之间采用专用Intranet网络进行通讯[7~9]。   1IEC60870-5-104远动规约分析   IEC60870-5-104规约标准定义了开放的TCP/IP接口的使用,包含一个由传输IEC60870-5-101ASDU的远动设备构成的局域网的例子。包含不同广域网类型,例如X。25、帧中继、综合范围数据网络ISDN(integratedservicedatanetwork)等的路由器可通过公共的TCP/IP——局域网接口互联,图1所示为一个冗余的主站配置与一个非冗余的主站配置。   IEC60870-5-104规约使用的参考模型源于开放式系统互联的ISO-OSI参考模型,只采用其中的5层,它处于应用层协议的位置。基于TCP/IP的应用层协议很多,每一种应用层协议都对应着一个网络端口号。IEC60870-5-104规约在传输层采用TCP协议,其对应的网络端口号为2404,其结构如图2所示。   图1一般体系结构   根据IEC60870-5-101从IEC60870-5-5中选取的应用功能 初始化 用户进程   从IEC60870-5-101和IEC60870-5-104中选取的ASDU 应用层   (第7层)   APCI(应用规约控制信息)   传输接口(用户到TCP的接口)   TCP/IP协议子集(RFC2200) 传输层(第4层)   网络层(第3层)   链路层(第2层)   物理层(第1层)   注:第5,6层未用   图2IEC60870-5-104规约的网络参考模型   由图2可见,IEC60870-5-104实际上是将IEC60870-5-101与TCP/IP(TransmissionControlProtocol/InternetProtoc01)/InternetProtoc01)提供的网络传输功能相结合,使得IEC60870-5-101在TCP/IP内各种网络类型均可使用,包括X。25、FR(帧中继)、ATM(异步传输模式)和ISDN(综合业务数据网)。   IEC60870-5-104规定一个APDU报文最长为255个字节(包括启动字符和长度标识),所以APDU的最大长度为253,APDU长度包括APCI的4个控制域8位位组和ASDU,因此ASDU的最大长度为249,这一规定限制了一个APDU报文最多能发送121个不带品质描述的归一化测量值或243个不带时标的单点遥信信息,如果子站RTU或监控西统采集的信息量超过此数目,则须分成多个APDU进行发送。应用规约数据单元结构如图3所示。   启动字符68H   APDU长度(最大253)   控制域8位位组1   控制域8位位组2   控制域8位位组3   控制域8位位组4   IEC60870-5-101和IEC60870-5-104中定义的ASDU   图3应用规约数据单元结构   APDU控制域定义了保护报文不至丢失和重复传送的控制信息、报文传送启停、传输连接的监视等,包括4个8位位组,根据其定义,将APDU分为3种报文格式,即I格式(编号的信息传输)、S格式(编号的监视功能)、U格式(未编号的控制功能)。   2IEC60870-5-104规约在直调厂站中的应用   2.1规约通信方案   随着电力通信网络技术的发展及为满足南方电网未来10至15年的电网安全运行和电力市场运作的要求,新EMS系统数据采集范围将覆盖南方电网内所有500kV厂站,现有的串行通信已不满足日益增加的数据容量、高速率数据通信要求。为了更好的推广和规范南方电力系统IEC60870-5-104协议的使用,在经过充分论证和研究的基础上,由南网总调组织制订了DL634。5。104-2002远动传输规约配套标准《南方电网实施细则》[10],根据南方电网的实际情况,对DL634。5。104-2002中的报文类型及参数的选用作了适当的规定,并扩充定义了部分报文。   图4调度主站与子站通信结构图   南网总调新EMS系统基于IEC61970标准,应用快速数据采集的SCADA和数据存储访问的数据库技术,对网内全部500kV厂站RT[J实现网络通信。调度主站EMS系统通过一路调度数据网及一路2M专线通道与子站RT[J实现通信,如图4所示。调度主站与子站RTIJ通信是一种典型的C/S模式,即被控站(子站RTU)是服务器端,控制站(调度主站)是客户机端,传输层使用TCP协议,固定端口2404。   图4中,数据采集系统模式具有灵活、合理的运行切换方式,能根据统计的子站RTU通道的误码率和投退状态选择较好的通道作为传输主通道其它通道作为备用通道,不仅满足了负荷管理系统可靠性、可维护性、可扩充性要求,同时也提高了系统的实时性。   2.2规约通信实施过程   TCP连接的建立过程。调度主站作为客户端不断向子站RTU发出连接请求,一旦连接请求被接收,则应监测TCP连接的状态,以便TCP连接被关闭后重新发出连接请求。每次连接被建立后,主站与子站RTU应将发送和接收序号清零,并且子站只有在接收到主站STARTDT后,才能响应数据召唤及循环上送数据,但在接收STARTDT前,子站对遥控、遥调等命令仍然进行响应。   变化遥测数据上送过程。按照南网细则要求,总调对接入的500kV厂站遥测量统一使用类型标识36,即采用带7位长时标的浮点数。   总召唤过程。主站向子站发送总召唤命令(类型标识100,传送原因6),子站回应确认(类型标识100,传送原因7),然后子站向主站发送单点遥信(类型标识1),全遥测数据(类型标识13,不带时标的浮点数),最后向主站发送总召唤结束命令(类型标识100,传送原因10,表示执行结束)。   子站事件主送上送过程。当子站发生突发事件,将根据现场具体情况向主站发送以下报文:单点遥信(类型标识1,传送原因3),SOE(类型标识30,传送原因3)。   遥控、遥调过程。单点设值:主站发送遥调命令(类型标识48,归一化值,传送原因6),子站执行确认(类型标识48,传送原因7)。多点设置:主站发送遥调命令(类型标识136,传送原因6),子站执行确认(类型标识136,传送原因7)。单点遥控:分为预置和执行两步操作,首先主站发送遥控预置命令(类型标识45,传送原因6),子站收到遥控预置命令后确认(类型标识45,传送原因7),然后主站发送遥控执行命令(类型标识45,传送原因6),子站收到遥控执行命令后确认(类型标识45,传送原因7),遥控命令具体流程如图5所示。   图5遥控命令执行过程图   计划曲线下发过程。南网细则对IEC60870-5-104规约中类型标识进行了扩充,规定用类型标识137来实现对子站的曲线下发,采用带长时标的多点设点命令下发计划值,给每个计划值分配一个固定地址,从0时0分开始到23时55分,一共288个量,具体流程见图6。主站发送计划曲线(类型标识137,传送原因6),子站接收到计划曲线后以镜像报文确认(类型标识137,传送原因7)。   图6计划曲线下发流程   时钟同步,时差召唤过程。主站发出时钟同步命令(类型标识103,传送原因6),子站收到同步命令后确认(类型标识103,传送原因7),然后将时差以变化遥测数据上送(类型标识36,传送原因3)。   分组召唤过程。南网细则定义1到8组是遥信,9到12组是遥测数据。分组召唤结束后子站以确认报文(类型标识100,传送原因10)上送主站。   远方复位进程。主站发出复位进程命令(类型标识105,传送原因6),子站收到复位命令后确认(类型标识105,传送原因7)。   2.3规约报文传送过程中存在的问题和解决方案   由于IEC60870-5-104规约本身不涉及到安全传输机制,而通过调度数据网传输远动信息过程中,如何保证调度主站与子站RTU之间报文的安全传输成为当前需要考虑和解决的问题。IECTC-57技术委员会第15工作组正在着手制定IECTS6235-1标准[11],该标准目的是为解决IEC60870-5系列标准中的数据通信安全问题,目前该标准仍在征集与讨论过程中。   根据电监会5号令一《电力二次系统安全防护规定》的要求,电力二次系统的安全防护规定须坚持安全分区、网络专用、横向隔离、纵向认证的原则[12],及电力二次系统安全防护总体方案要求,调度中心、发电厂、变电站在生产控制大区与广域网的纵向连接处应当设置经过国家制定部门检测认证的电力专用纵向加密认证装置或者加密认证网关及相应措施,实现双向身份认证、数据加密和访问控制[13],重点抵御病毒、黑客通过各种形式发起的恶意破坏和攻击,尤其是集团式攻击,保护电力实时闭环监控系统及调度数据网络的安全,防止由此导致电力二次系统的崩溃或瘫痪,继而造成一次系统事故或大面积停电事故。   为保障生产控制大区与广域网纵向数据传输过程中的数据机密性、完整性和真实性,根据实际情况,南网总调选择在调度主站和所直接采集信息的500kV子站两侧电力控制系统的内部局域网与电力调度数据网络的路由器之间部署纵向加密认证装置,如图7示。   图7主站与子站两侧配置纵向加密装置图   由第1节中可知,APDIJ分为3种报文格式,其中I格式包含ASDU,这部分远动信息需要加密,因此,需要对I格式报文进行加密以及对发送方的身份进行认证;而对于S格式和U格式,由于其中不含ASDU,因此在报文发送过程中不涉及到必要的加密信息,只需要对报文发送方进行身份认证。对于工格式报文,由于包含ASDU,首先对整个数据包进行加密,产生加密信息包P,然后通过MAC计算,将生成的MAC与APDU一起打包发送,接受方在收到发送方送出的报文后,首先对报文的完整性和发送者的身份进行验证,然后对信息包P解密,得到ASDU。报文的加密和认证过程如图8所示。   图8报文加密与认证过程图   2.4主站与子站网络通信报文的安全传输过程   图9调度主站与子站通信数据包流程图   纵向加密认证装置基于链路层的数据访问控制原理,支持透明接入和加密两种工作模式并采用过滤技术,提供应用层的安全访问控制机制。根据上述对远动信息报文的加密和认证过程后,经过验证,这种安全机制在不影响原有报文传送结构的前提下在实际应用中实现了端到端的选择性保护,保证电力实时数据传输的实时性、安全性、可靠性。调度主站与子站之间网络通信数据包流程图如图9所示。   2.5纵向加密认证装置的应用情况   目前包括国电南瑞、电科院等国内厂家的纵向加密认证装置均通过了相关部门的测试,南瑞科技有限公司开发的Netkeeper--2000纵向加密认证装置已在南网总调、花都变电站、广东省电力调度通信中心及广州、佛山地调投入试运行。上述装置自投运以来,运行情况稳定,根据用户设定的控制策略实现了主站对子站端数据集中的统一管理和运行监测、记录,达到了预期效果。   3结束语   本文详细介绍了基于TCP/IP的IEC60870-5-104远动通信协议在总调直调厂站中的具体应用及扩充,针对IEC60870-5-104规约本身并没有考虑网络传输信息安全问题,围绕如何保证电力实时传输数据过程中信息的机密性、完整性和真实性三方面的I司题,对调度主站EMS系统与子站RTU或计算机监控系统之间报文传输的各种安全因素进行分析,并根据工程实践,提出了一种满足实际需要的安全通信模式。

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧