ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

南瑞继保网络103规约解析:变电站对点排障与Python实现

南瑞继保网络103规约解析:变电站对点排障与Python实现 简介南瑞继保网络103规约是电力系统远动通信领域的重要协议资料主要用于远动设备RTU与调度中心或集控站之间的数据交换面向电力自动化工程师、现场调试人员及相关专业学生帮助理解基于IEC 60870-5-103标准并针对国内电网环境优化后的规约设计。资源包仅包含1个doc文档大小约3.38MB便携易读适合离线学习。文档系统梳理了主从通信结构以及遥测、遥信、遥控、遥调四遥功能的报文交互流程覆盖规约层次结构、帧格式、命令帧与应答帧定义、错误检测与恢复策略等实际工程中绕不开的知识点同时介绍了为满足电力系统安全性而引入的身份验证与加密机制以及为提升传输效率采用的报文优化和快速确认手段兼顾兼容性、网络适应性及常见故障处理思路。对于从事入网调试、设备联调或二次开发的人员可借助此文档快速建立对南瑞继保103规约的整体认知框架节省大量翻查标准文献的时间。已有1974人下载学习内容聚焦、实用性强适合作为日常工作与学习的备查资料。1. 南瑞继保网络103规约为什么变电站对点多点绕不开它秋季检修结束后台和PCS-978保护屏对点装置网线插好后台表上保护动作状态却灰着。抓包看到一帧0x68开头的报文既不是IEC 104的远动模型也不是IEC 61850的MMS翻手册才确认这是南瑞继保网络103规约。它把IEC 60870-5-103的ASDU装进TCP/IP帧里为的是把保护动作、软遥信、扰动录波完整送到站控层。后台厂家、调试人员和运维人员都可能被它难住。下面从协议结构讲到排障给你一套能照着接通的路径。先说结论网络103并不是104的某个变种也不是把串口103简单转成网口就完事。它保留了103面向继电保护的信息模型但传输承载变成了类似IEC 104的TCP分帧。这意味着你既不能用传统串口103的轮询思路去调试也不能用104的ASDU解析规则去读报文。理解这一点后面那些“连不上、对不齐、报文乱”的问题就看得懂了。2. 网络103规约的原理串口103的以太网化不是104的变种2.1 103规约与网络103规约的祖孙关系IEC 60870-5-103是个老协议设计给继电保护设备与站控层交换信息。标准里定义了应用层ASDU、链路层FT1.2和物理层。传统串口103用RS232/485或光纤一主一从轮询链路层帧带CRC校验一帧几十字节在低速串口上跑还能应付但到了站控层以太网化之后就不够看了。南瑞继保早期的RCS系列和现在的PCS系列串口103一直是保护管理机的标配。后来变电站全面网络化站控层交换机取代了串口总线主站还想从保护装置拿故障录波、扰动数据、软压板状态这些数据如果继续走串口传输速度会让人崩溃。于是网络103出现了把103的ASDU原样保留外面套一层类似IEC 104的TCP/IP封装。说通俗点就是把原来跑在串口里的“保护语言”原封不动地搬到网线里跑。这个“原封不动”很关键。ASDU里的类型标识、功能类型FUN、信息序号INF以及保护事件、录波数据格式都继承自103标准。所以点表要按103的规则去理而不是按104的遥测遥信表去理。很多第一次接触这个规约的同行拿到抓包文件后下意识用104的解析器去读结果类型标识全是怪值这就是没搞清祖孙关系。网络103没有单独的国标编号常见做法是厂家在104的APCI框架里装入103的ASDU但控制域、传输原因和地址应用都做了裁剪。所以不同厂商的“网络103”在细节上会有差别南瑞继保的不同装置版本之间也可能存在私有差异。遇到这种现象别急着骂程序先到装置说明书里找“网络103规约”那一章。2.2 网络103规约报文的两层结构APCI与ASDU抓包时最常看到的网络103报文形态是0x68启动第二字节为后续长度再往后是控制域、发送/接收序号最后是ASDU。用IEC 104的眼光看这个壳很眼熟但看到ASDU后千万别按104解。APCI负责TCP流里的分帧和序号确认。TCP是流协议没有消息边界0x68和长度字段就是每一帧的边界。控制域通常一字节I帧和S帧靠最低位区分S帧只带APCI确认对方序号不携带ASDU。发送和接收序号各两字节用于检测丢帧和乱序。当后台收到一帧I帧后需要回S帧确认否则装置可能认为链路拥堵而停止上送。ASDU才是报文里真正有业务含义的部分。常见的ASDU头部包括类型标识一字节区分保护事件、遥信、遥测、扰动录波、总召、通用分类等。可变结构限定词低7位表示本帧里信息体个数。传送原因比如启动、停止、激活、确认、响应等。公共地址对应装置里设置的公共地址相当于站内设备编号不是IP地址。功能类型FUN和信息序号INF这是103规约的点表坐标一个FUN/INF组合唯一指向一个保护信号。信息体个数不止一个时一帧ASDU可以携带多个信息元素每个元素按类型标识不同后面跟着不同的状态字、模拟量、时标。解析时不能只读前六字节要根据类型标识跳着读。做对点的时候真正要人工核对的就是FUN/INF和点表描述。下面这张表是常见的网络103 ASDU类型供参考。不同装置型号、不同规约版本会有差异最终以装置说明书里的点表为准。类型标识(hex)常见含义方向典型场景0x01带时标的报文装置→主站保护动作时刻记录0x02带时标的保护事件装置→主站开关变位、保护启动0x07扰动数据装置→主站故障录波传输0x08扰动数据确认主站→装置录波召唤响应0x1E/0x1F带时标的遥信/遥测装置→主站软遥信、模拟量0x0B/0x0F通用分类命令/数据双向定值调阅、总召这张表不是万能解药。南瑞继保早期装置可能使用其他类型标识甚至同一台装置在不同规约版本里对扰动录波的类型标识定义都不一样。我建议在现场每接一个新装置型号先抓十来个样本报文对照说明书确认类型标识后再写解析逻辑。2.3 为什么不是104网络103和104的边界与选型很多人看到TCP端口就以为是IEC 104这是踩坑重灾区。IEC 104用于远动信息模型面向厂站调度以遥测、遥信、遥控、遥调为主。103面向保护信息模型以保护动作事件、故障录波、扰动、通用分类为主。南瑞继保的测控装置和远动装置一般走104或61850保护装置跟后台交换保护信息则用网络103。某些后台软件会把保护装置的网络103通道误配成104通道结果连接正常、握手正常就是报文内容对不上点表。选型上如果只是要常规遥测遥信且告警分辨率需求不高完全没必要上网络103。但如果你要保护动作的详细原因、故障相别、录波数据串口103和104都满足不了。网络103把103的ASDU搬上以太网解决了串口独占线路的问题还让后台能通过TCP主动召唤录波。单凭“能传录波”这一点它就在综自站里占了一个不可替代的位置。这里补一张对比表把边界说透对比项串口103网络103IEC 104物理层RS232/485/光纤以太网TCP/IP以太网TCP/IP链路层FT1.2APCI类104壳APCI应用模型103 ASDU103 ASDU104 ASDU保护事件支持支持更高效不直接支持录波召唤支持但慢支持单文件传输不支持适用对象老站保护管理机网络化综自站保护调度远动上传所以你在后台接装置时接口列表里会同时看到“网络103”和“IEC 104”两个选项。选哪个取决于你对面那台设备是保护还是测控。保护选网络103测控选104两者混用是现场最常见的配置错误。3. 南瑞继保装置侧配置把网络103跑起来的最小参数集3.1 装置IP、端口与规约使能先从面板找参数南瑞继保装置的液晶面板和调试软件都能进入通讯配置菜单。以PCS系列为例路径一般是“系统配置/通讯配置/规约选择”。先把“网络103”选上然后填装置地址。注意这个装置地址和IP不是一回事网络103报文里的公共地址通常取自这里后台连接参数里的公共地址必须跟它保持一致。随后设置装置IP、子网掩码、网关。如果后台和装置在同一个交换机网段内网关可以不填跨三层才需要网关。TCP端口一栏常见默认值是2404或4000但千万别把这个当成标准答案南瑞继保不同项目可能把端口改过。最可靠的办法是直接问现场保护调试人员或者用端口扫描工具对着装置IP扫一遍。常见参数表如下参数常见默认必须核对备注装置IP192.168.1.*是与后台同一个网段子网掩码255.255.255.0是跨网段要改网关取决于交换机视情况跨三层才用TCP端口2404或4000是以装置手册为准规约类型网络103是选错会走104或MMS公共地址1是与主站一致重连延时10秒否现场有时候要加大到30秒我一般先把装置IP用网络调试器直接ping通再谈端口。网络103大多是主站主动连接装置所以装置侧不需要配置客户端只要确认服务端口在监听就行。你可以在后台电脑上用telnet ip port试一下能通说明端口正常不通就查防火墙、交换机和端口号。注意端口最好独立占用不要为了省交换机策略把网络103和104混用同一个端口否则后台软件按104解析时会把103的ASDU读成一堆乱码。3.2 信息点表整理把软遥信映射到FUN/INF网络103信息点表是整套工程最容易出错的地方。点表没对上后续对点会浪费大量时间。从装置说明书附录里找到“网络103规约点表”每个信号都有对应的FUN、INF、ASDU类型和时标格式。在后台数据库里建立点号把装置点表映射到后台点表。样例表如下里面的值只是示例不能直接抄进项目信号描述示例FUN示例INFASDU类型备注保护动作511事件实际值以装置说明书为准保护启动512事件实际值以装置说明书为准断路器位置489遥信实际值以装置说明书为准故障测距605录波实际值以装置说明书为准当你看到后台有报文但点表错乱时先查报文里ASDU的第5和第6字节也就是FUN和INF。这两个字节才是点表坐标。很多后台软件会在数据库里显示“原始值”或“原始地址”把这两个值和点表一对比立刻就能看出是不是错位了。整理点表的标准动作收集装置版本信息和配置文件用厂家提供的点表模板生成后台数据库把FUN/INF填进后台点号的“规约原地址”字段做一次保护试验逐条确认每个信号的FUN/INF与后台描述一致。这里要特别说明软遥信不像硬遥信那样有辅助触点回路它是装置内部逻辑运算后通过ASDU上送的没有物理接线做参考。一旦FUN/INF映射错后台收到的信号可能来自完全另一个间隔而且没有任何告警只能在点表源头查。3.3 主站侧连接参数客户端角色、超时与总召时机后台主站侧一般提供通道参数窗口按“网络103”新建通道时需要填的内容不少。我是这样配初始值的参数推荐值作用说明主站角色TCP客户端主动连装置装置作为服务器等待连接对端IP装置IP连接目标和装置面板一致TCP端口与装置一致端口号公共地址与装置一致ASDU地址过滤不一致会收不到总召连接超时5秒失败判断现场网慢可调到10秒重连间隔10~30秒掉线恢复太短会刷装置日志总召方式连接后发总召初始化同步具体ASDU以手册为准时间同步周期1分钟或手动校时装置时间不准会影响事件时标总召并不是发一次就万事大吉。网络103的总召往往包含多类数据软遥信、压板状态、保护定值摘要、故障录波目录等。不同装置把总召拆成多个ASDU回送主站必须等所有回包结束后再把通道状态标成“正常”。如果只发一次命令然后不管回包是否完整就认为通道通后面会漏掉一堆状态。这里还有一点容易忽略总召过程中会发生变位。后台应该把总召期间收到的变位事件缓存起来等总召结束后再处理否则可能出现“先看到变位后看到总召状态最后把状态又覆盖成旧值”的竞态。很多后台软件处理得并不好现场排查时如果发现信号时有时无优先怀疑总召时序而不是链路质量。4. 主站侧做网络103规约解析一个可直接改的Python最小实现4.1 建立TCP连接并按长度分帧网络103的“壳”处理主站侧要接入网络103第一件事不是解析ASDU而是先把TCP流按帧切开。下面这段Python实现只做连接、收包、按0x68长度分帧是后面解析的基础。我保留了关键注释现场可以直接改IP和端口跑。import socket import struct class Net103Client: def __init__(self, device_ip, device_port, common_addr1, timeout5): self.device_ip device_ip self.device_port device_port self.common_addr common_addr self.timeout timeout self.sock None self.buffer b self.send_seq 0 self.recv_seq 0 def connect(self): # 主站角色主动连接装置 self.sock socket.create_connection( (self.device_ip, self.device_port), self.timeout ) self.sock.settimeout(self.timeout) def receive_frame(self): # 从TCP流中按 0x68 长度 分帧返回完整一帧 while True: if len(self.buffer) 1: self.buffer self.sock.recv(1024) continue if self.buffer[0] ! 0x68: # 首字节不是帧头丢弃一个字节继续找 self.buffer self.buffer[1:] continue if len(self.buffer) 2: self.buffer self.sock.recv(1024) continue payload_len self.buffer[1] frame_len 2 payload_len while len(self.buffer) frame_len: self.buffer self.sock.recv(1024) frame self.buffer[:frame_len] self.buffer self.buffer[frame_len:] return frame这个类只做连接和分帧不解析业务。connect用socket.create_connectionTCP客户端角色主动连装置。receive_frame里四个分支分别处理buffer为空就补数据首字节不是0x68就丢一个字节重新找长度字段还没收齐就继续补凑够一帧就返回剩余数据留在buffer供下一帧使用。为什么不能一读到1024字节就当成一帧因为TCP粘包和半包太常见了。网络103报文内部也可能出现0x68这个字节只有按长度字段切帧才能保证每帧的边界和发送端一致。frame_len 2 payload_len是因为0x68和length字段本身占两字节length以后才是APCI和ASDU。有些厂家实现里length可能包含前两个字节抓包第一眼要确认这个细节否则后面ASDU偏移会差两个字节解析出来全是乱值。4.2 解析ASDU把类型标识、FUN/INF映射成后台可读信号分帧之后下一步是解析APCI和ASDU。按常见网络103布局APCI占前7字节0x68、长度、控制域、发送序号两字节、接收序号两字节ASDU从第7字节开始。下面代码继续挂在Net103Client类里def parse_frame(self, frame): if len(frame) 7 or frame[0] ! 0x68: return None # APCI布局0x68, len, ctrl, send_seq(2), recv_seq(2), asdu... ctrl frame[2] send_seq struct.unpack(H, frame[3:5])[0] recv_seq struct.unpack(H, frame[5:7])[0] asdu frame[7:] if not asdu: return { ctrl: ctrl, send_seq: send_seq, recv_seq: recv_seq, asdu: None, summary: S帧仅确认 } type_id asdu[0] if len(asdu) 0 else None vsq asdu[1] if len(asdu) 1 else None cot asdu[2] if len(asdu) 2 else None common_addr asdu[3] if len(asdu) 3 else None fun asdu[4] if len(asdu) 4 else None inf asdu[5] if len(asdu) 5 else None return { ctrl: ctrl, send_seq: send_seq, recv_seq: recv_seq, type_id: type_id, vsq: vsq, cot: cot, common_addr: common_addr, fun: fun, inf: inf, asdu_hex: asdu.hex() }这段解析把ASDU头部做成字典。type_id是类型标识vsq里低7位是信息体个数cot是传送原因common_addr是公共地址fun和inf是点表坐标。为什么要取这六个字段因为网络103的应用层沿用了103标准ASDU头部结构就是这一套。但注意这个函数只解析到头部信息元素的具体内容还要根据类型标识单独写。比如带时标的事件信息体里有状态字和0x95时间标记录波数据则是二进制幅值不能当文本读。这里有个工程习惯必须提醒解析时一定要保留asdu_hex原始hex。一旦发现点表对不上拿原始hex和装置说明书逐字节比比在后台软件里猜快得多。抓包文件里的原始报文也是同样的道理别只存解析后的结果。接下来做一个简单的点表映射字典POINT_TABLE { (0x51, 0x01): 保护动作, (0x51, 0x02): 保护启动, (0x30, 0x01): 断路器分位, (0x30, 0x02): 断路器合位, } def map_point(fun, inf): return POINT_TABLE.get((fun, inf), None)实际项目的点表可能有上千行建议启动时从CSV加载不要写死在代码里。用FUN/INF作为字典key查询速度最快也最直观。后台工程里那些“开了压板但信号还是灰”的问题很多就是这里映射错了。4.3 发送总召并验证连接最小可用的总召函数解析只是被动接收还要主动发起总召。下面写一个组帧发送函数包含发送序号管理。def send_frame(self, asdu_body): # 组帧APCI ASDU # 控制域0x00表示I帧后面是发送序号和接收序号 apci struct.pack(B, 0x00) apci struct.pack(HH, self.send_seq, self.recv_seq) self.send_seq 2 frame b\x68 bytes([len(apci) len(asdu_body)]) apci asdu_body self.sock.send(frame) def send_general_call(self): # 总召唤的ASDU类型和传送原因在不同版本中不一样 # 这里给出一种常用形态类型标识0x64传送原因0x06后跟公共地址 asdu struct.pack(BBB, 0x64, 0x06, self.common_addr) # 有的版本总召报文里还会有专用信息体以装置说明书为准 self.send_frame(asdu)send_frame负责把长度字段算好并且发送序号每发一帧I帧加2。这个加2是参考I系列帧序号步进规则实际某些私有实现可能每次加1或固定值最稳妥的方法是先抓一帧连接建立后的报文确认。send_general_call是总召总召激活后装置会先回总召确认再分帧上送各类状态。如果装置不回不要连续重复发包先确认公共地址和装置一致再检查总召ASDU类型。4.4 对点时怎么用一个最小验证脚本把上面几段拼成一个简单主程序就能在现场跑对点了。def main(): client Net103Client(192.168.1.100, 2404, common_addr1) client.connect() client.send_general_call() while True: frame client.receive_frame() parsed client.parse_frame(frame) if parsed and parsed[asdu]: name map_point(parsed[fun], parsed[inf]) print( ftype0x{parsed[type_id]:02x} ffun0x{parsed[fun]:02x} finf0x{parsed[inf]:02x} fdesc{name} ) if name 保护动作: break if __name__ __main__: main()这个脚本用途很单一连上装置发总召循环收帧打印FUN/INF和点表描述。跑一遍如果点表里所有信号都能识别说明通道解析是通的。但它还不是成品因为缺少S帧确认、断线重连、变位上送主动推送的处理。正式的后台程序需要一个带状态机的主循环不是几十行代码能替代的。用来验证样本报文足够了。5. 网络103接入排障从连不上到报文乱5个高频坑5.1 坑一TCP端口能通但刚连上就被断开现象后台连接装置端口成功还没收到总召确认socket就超时或收到RST。原因通常有三类装置里规约类型没选对主站角色和装置角色冲突后台发出的第一帧不符合装置期望的启动状态。有些装置在握手后等待主站发总召或启动帧等不到就主动断开。解决先在装置面板确认网络103使能。再抓包看断开前装置有没有发过含ASDU的报文。如果装置一帧不发就直接断多半是等待激活命令这时补发总召。如果用telnet能通但后台连不上检查后台通道参数里的IP和端口有没有填到别的装置上。这种问题用抓包最直观光看后台日志很难定位。5.2 坑二报文里找不到0x68帧头乱现象TCP连接有数据但接收缓冲区第一个字节不是0x68可能是0x00、0x30或0x80。原因往往是对接到了非网络103的服务端口或者后台软件先按104解析发了一个104启动帧而装置返回的是MMS或私有报文。解决先确认后台通道的“规约类型”选的是“网络103”而不是“IEC 104”。再用抓包工具看TCP负载如果负载是ASN.1编码比如0x30开头的一串BER数据那是IEC 61850 MMS不是网络103。还有一种情况是端口复用装置在同一个端口同时监听104和103后台无法区分时必须改用独立端口并在交换机策略里把端口放通。5.3 坑三整帧分界不齐ASDU总是错位现象按0x68和长度切帧后类型标识总是0x10、0x40这些奇怪值对照不了点表。原因网络103的APCI布局和104不完全一样有些实现控制域不止一字节长度字段含义不同。也可能是抓包时把TCP payload中间某个0x68误当成帧头导致后续全部错位。解决用抓包软件确认每一帧TCP段的真实边界在代码里丢弃无法识别的乱码字节。打印每帧hex和长度和长度字段校验。我习惯在分帧器里加一个保护逻辑如果长度字段算出来的帧长超过300字节直接重置buffer防止一条脏数据让内存一直膨胀。要知道103的ASDU虽然可能很大但一般不会超过链路层限制。5.4 坑四保护动作信号上不来但总召有数据现象总召完成后台软遥信都亮了但实际发生保护动作时后台收不到新事件。原因装置的保护事件上送是突发上送主站没有正确确认装置认为链路繁忙就不再发或者后台软件里关闭了“事件上送”开关或者FUN/INF点表里根本没登记这个事件。解决检查收发序号的连续性。主站收到每帧I帧后必须回S帧确认如果确认次数不够装置会停发。把后台软件里的“事件上送”开关打开。再用一个测试按钮触发保护事件观察抓包里有没有0x01或0x02类型标识的ASDU。如果装置根本没上送去查保护面板里的软压板和事件记录。这个坑看起来像通道问题实际上往往是应用层没配对。5.5 坑五录波召唤失败文件传到一半连接断现象点击录波召唤文件传输到30%时socket超时反复失败。原因录波文件会拆成多个ASDU连续传输主站超时设置太短接收缓冲太小或者同时发了多个录波召唤装置丢弃后续请求。解决把socket超时从5秒调到30秒单次只召唤一个文件。接收端把同一个录波文件的ASDU按传输序号追加到临时文件不要等整个文件完成再写盘。抓包时注意文件传输过程中主站有没有及时回S帧确认帧稀疏会导致装置等超时。这个问题更像“传大文件”的并发控制问题和规约本身关系不大但网络103里录波是不可少的功能值得多留时间调。6. 让网络103链路更可靠的最后一个技巧先总召、再录波留一份报文回放6.1 验收链路的标准动作总召之后立刻做一次录波召唤我每次接到带网络103的新站做完参数配置后不会直接逐点对表而是先走一遍固定验收流程。连接建立后发总召等总召回包全部收齐然后手动触发一次录波召唤确认装置能把录波文件完整送到后台最后再做一次保护试验看保护动作事件能不能主动上送。这三步分别对应了被动上送、主动召唤、突发上送三种通信路径只要都通链路基本没有黑匣子。6.2 把抓包当黑匣子的钥匙留一份原始报文回放现场调试时不要只盯着后台人机界面抓包文件才是定位问题的钥匙。我会把0x68开头的原始报文连同时间戳一起导出成txt或cap标注好现场地点、装置型号和规约版本。下次遇到同类问题用第4章的脚本直接回放几分钟就能判断是分帧错还是点表错。对点完成后把报文样本归档这是跑通的证据也是未来翻车时的后悔药。有一回对点前我没先发总召直接对着点表逐点试结果FUN/INF偏移了两个字节折腾了大半天。后来我给自己定下规矩先总召、再录波、后对点顺序不要反。网络103的坑并不深但一定要按它的ASDU逻辑来别拿其他规约的惯性去套。希望帮到你。本文还有配套的精品资源点击获取
返回列表