
简介针对电力远动通信领域常见的IEC 60870-5-101/104规约这份资源整合了多款亲测可用的调试工具面向电力自动化运维人员、协议开发及现场调试工程师。包内提供报文解析器、IEC8705报文翻译工具、C浮点数与十六进制转换工具以及Peugeot、PMA、104主站调试模拟等客户端/服务端仿真软件可满足规约报文逐字段解读、链路调试和主站从站模拟等需求有助于快速定位收发异常问题。压缩包共136个文件以dll动态库、pco工程配置、csv报文模板、xml配置及exe可执行为主另有ini、pol、dat等辅助文件整体仅6.8MB便于下载携带。目前已有7993人学习下载经作者实测大部分工具收发数据正常适合正在搭建101/104调试环境或需要对照报文分析的从业者。 搞电力自动化调试的人十有八九都被那一串十六进制报文折磨过。尤其是101和104规约现场通信异常时看着监控后台刷出来的报文根本分不清是装置没上送、主站没解析还是通道里数据就错了。今天聊的这套101、104电力规约报文解析工具就是干这个用的——把链路层到应用层的每一帧数据拆开揉碎告诉你每一字节是什么含义、该不该出现、值对不对直接定位到具体问题。适合配网自动化终端调试、变电站远动信息联调、规约开发自测和主站系统运维的工程师参考省去拿计算器手工按位的日子。这篇文章不聊大而全的理论直接把我实际解析报文时总结出来的帧结构拆解方法、工具选型的取舍思路、动手写解析脚本的步骤以及调现场时踩过的典型坑都整理出来按从思路到落地的顺序展开。1. 整体设计思路为什么解析工具必须先搞清楚前置概念1.1 101和104到底扮演什么角色电力系统里101规约是IEC 60870-5-101标准主要用在串口通道上常见于变电站到调度端的串口远动、配网终端到主站的RS-232/RS-485链路。它是一套完整的链路层加应用层协议报文里既包含链路层的召唤、确认、复位又包含应用层的遥信、遥测、遥控、SOE等信息。104规约则是IEC 60870-5-104标准本质上是把101的应用层数据结构直接搬到TCP/IP网络上传送适合以太网通道核心是利用TCP的可靠传输来承载远动报文同时增加了传输层序号、超时重发机制。这两个规约不是互相替代的关系而是适应不同通信环境的兄弟协议。实际工作中常见的搭配是主站侧通过104网络上收集中站数据中站再通过101串口下接终端设备。也就意味着一个工具如果能同时解析这两种规约你在通道任一端抓到的报文都能看懂。1.2 解析工具解决的核心痛点没有工具之前我自己最头疼的几件事拿到报文后逐字节翻IEC标准文档核对含义效率低容易漏掉细节。104的I帧含有发送序号和接收序号序号错了会引发链路重连但肉眼很难看出序号是否匹配。101链路层的固定帧长/可变帧长结构不同容易搞混控制域里功能码的含义。遥控报文里的品质描述、遥控选择/执行标志位置稍微偏一位整个意思就变了。解析工具的价值就是把“字节”翻译成“人话”。拿到一帧报文直接告诉你是“总召唤命令”还是“单点遥信变位”信息的起始地址是多少数据值是0还是1品质位里是否带IVA无效标志。有了这层翻译和装置说明书、主站转发配置一对照问题出在哪一侧立刻有方向。2. 核心细节解析与实操要点读懂帧头和字节含义2.1 104规约帧结构三步定位法104报文解析的第一步是判断帧类别。所有104帧都以0x68开头第四个字节表示帧长度。核心区分要看控制域第一个八位位组的最低位最低位为0是I帧信息帧用于传输应用数据遥信、遥测、遥控等。最低位为1且第二位为0是S帧监视帧用于确认接收序号不带应用数据。最低位为1且第二位为1是U帧控制帧用于启动、停止、测试链路。实操时我习惯先在Wireshark里用过滤器tcp.port 2404把104流量过滤出来然后肉眼扫控制域字节。一个典型的I帧报文长这样68 0E 06 00 04 00 12 01 04 00 00 00 00 2C 01 06 00 00 00逐个解码68启动字符。0E帧长度后面APDU共14字节含控制域和ASDU。有问题避免模糊内容这里报文的解析继续以规范方式展开控制域三字节06 00 04 00其中06 00表示发送序号04 00表示接收序号均为低位在前。发送序号实际为000613即第3帧I帧接收序号000412即已正确收到序号2及以前的帧。序号乘2的含义是规约里序号计数按字节对计算消息帧序号范围0-32767实际只使用2的倍数。类型标识0x12查表可知是“带时标的单点信息”也就是SOE报文。结构限定词0x01表示后续一个信息体。传送原因0x04 00即“突发”类别。公共地址0x00 0x00主站地址和终端地址都为0现场若配置了地址这里会显示对应编号。信息体地址0x2C 01 06 00低字节在前解析出来是0x0006012C按四字节信息体地址规则高字节00表示信息体地址的高位实际常用三字节地址时信息体地址为0x00062C。这里有个细节坑三字节地址和四字节地址如果不加区分解析结果会差一个数量级。我后来在工具中专门加了“地址宽度”配置项对着装置说明书确认后再解析。2.2 101规约帧结构拆解要点101规约在串口上跑帧分为固定帧长和可变帧长两种。固定帧长10字节启动字符为0x10可变帧长首字节0x68紧接着是长度L注意L后面还会重复一次长度L然后才是控制域、地址、用户数据和校验码。可变帧长结构如下68 L L C A A ...DATA... CS 16L后面重复一次目的就是校验完整性。实际解析时建议先核对L是否等于后续数据字节数再核对校验和CS是否等于控制域、地址、用户数据按字节累加和的低八位。101链路层控制域中的功能码常见取值需要记几个0x43是链路发送确认0x4B是链路召唤命令0x09是复位链路确认0x00是确认帧中的“确认”功能码。地址A为两个字节低字节在前。调101时最容易踩的坑是装置设置为平衡传输方式主站发一个召唤帧后装置直接上送数据不经过确认如果工具还在死等确认帧就会提示超时。必须先确认传输方式再分析链路流程。2.3 遥测、遥信、遥控报文的信息体组织方式104规约数据组织比101规约复杂一层原因在于支持信息体地址连续、信息元素地址连续等特点报文里大量使用“多个信息体堆叠”的结构一个ASDU里可以塞多路遥信或遥测。以常见遥测上送为例类型标识0x09表示测量值归一化值结构限定词0x02说明有两个信息体每个信息体地址占三字节随后是两字节数值。数值的符号位在第15位解析时需要注意补码表示。例如十六进制0x0064对应100表示一次电流100A。如果收到0xFF9C则是-100。品质描述符在遥测里名字叫QDS占一个字节但实际只用了低四位IV无效、NT非当前值、SB被取代、BL被闭锁。现场常见问题就是IV位等于1说明数据无效但链路正常值可能是装置内部的未初始化数据此时不要慌先检查装置面板上的运行状态。遥控报文的组织更讲究。选择命令类型标识0x2E执行命令是0x2D信息体地址是遥控点号随后一个字节是遥控输出状态0x00表示分0x01表示合。这个输出状态必须和选择状态一致否则主站会拒绝执行。我遇到过一次典型问题主站下发的选择命令里输出状态为0x00但执行命令里填了0x01装置侧判定状态不一致遥控不动作排查了半天才从报文解析里看出来。3. 实操过程与核心环节实现手写一个轻量解析脚本3.1 工具链选择与理由目前市面上现成的工具不少国网推广的调试软件、各厂家自带的报文监视工具都带101和104解析功能但往往只能看到简化的消息名称不提供原始字节到结构体的映射。Wireshark是很好的抓包工具自带104解析插件能直接显示I帧、S帧、U帧、ASDU类型但对101串口报文支持很差也不方便处理非标扩展。我选择用Python写轻量解析脚本理由很简单Python处理二进制数据方便使用struct库可以快速解包。可以用scapy库直接解析PCAP文件也可以读取文本格式的十六进制报文。打印输出灵活调试时可以逐步展开。脚本容易扩展后期可以对接自动化测试平台。3.2 核心解析代码框架下面这段脚本覆盖了从原始字节流中判断帧类型、提取ASDU、解析信息体的最小逻辑。它不依赖第三方库所以串口数据抓下来后可以离线跑也可以直接打日志文件批量跑。import struct def parse_104_frame(data: bytes): if len(data) 6: return None if data[0] ! 0x68: return None apdu_len data[1] # 实际长度不匹配时说明粘包/断包返回None让上层做缓冲处理 if apdu_len ! len(data) - 2: print(f帧长不匹配声明{apdu_len}实际{len(data)-2}) return None ctrl data[2] if ctrl 0x01 0: # I帧 send_seq (data[2] | (data[3] 8)) 1 recv_seq (data[4] | (data[5] 8)) 1 print(fI帧, 发送序号{send_seq}, 接收序号{recv_seq}) parse_asdu(data[6:]) elif (ctrl 0x02) 0: print(S帧, 接收确认) else: u_type data[2] 0xFC u_name {0x04: TESTFR, 0x08: STARTDT, 0x40: STOPDT}.get(u_type 0xFC 0x04, UNKNOWN) if u_type 0x04: print(U帧, TESTFR) elif u_type 0x08: print(U帧, STARTDT) elif u_type 0x40: print(U帧, STOPDT) else: print(U帧, 未知) def parse_asdu(asdu: bytes): if len(asdu) 6: return type_id asdu[0] num_objects asdu[1] 0x7F cause asdu[2] | (asdu[3] 8) public_addr asdu[4] | (asdu[5] 8) print(f类型标识{type_id}, 信息体数量{num_objects}, 传送原因{cause}, 公共地址{public_addr})实际用的时候会把信息体按照类型标识分成不同解析函数。比如类型标识0x01是单点遥信信息体地址3字节随后1字节数据位再1字节品质描述。类型标识0x09是归一化测量值信息体地址加2字节数据加1字节品质。类型标识0x64是总召唤命令传送原因是0x06 0x00信息体地址固定是0x00000000。3.3 解析一条实际遥控报文的完整过程模拟一次主站对某配电终端执行遥控合闸的过程。主站抓到的上行报文是总召唤响应下发的是遥控选择帧接着是遥控执行帧。选择帧报文十六进制68 0A 0C 00 04 00 2E 01 01 00 00 03 00 00 01 00 14 00拆解步骤68 0A启动符长度10字节。控制域0C 00 04 00I帧发送序号为0x0C16接收序号为0x0412。类型标识0x2E单点遥控命令。结构限定词0x011个信息体。传送原因0x01 0x00激活自发方式。公共地址0x00 0x03终端公共地址为0x0300低字节在前实际值3。信息体地址0x00 0x00 0x14遥控点号20。遥控状态0x00品质0x00状态为分。执行帧报文68 0A 10 00 06 00 2D 01 01 00 00 03 00 00 14 01 00 00类型标识0x2D遥控状态0x01。发送序号是0x1018接收序号0x0613。注意第6帧到第8帧中间隔了1个S帧说明主站收到了终端的选择确认后又收到了其他遥测上送序号逻辑是连续的链路通信正常。这段解析跑下来问题基本一眼定位。我自己在联调时就把这个脚本的日志打印接到终端串口一边等报文一边看输出效率比在抓包工具里手翻高很多。3.4 串口报文处理与粘包问题101规约跑在串口上最常遇到的就是粘包和半包。处理思路比较固定维护一个环形缓冲区按字节流方式持续接收。检查缓冲区的第一个字节如果是0x68则尝试解析可变帧长如果是0x10则尝试解析固定帧长如果都不是丢弃该字节继续查找帧头。每个帧解析结束后把已消费的字节从缓冲区删除。我再强调一点101的帧长度字段L在可变帧长中会出现两次校验时要同时对比两个L是否一致并和帧体实际长度匹配。很多自定义扩展的101帧就是因为厂家自己改了长度定义导致标准解析失败这个逻辑尤其要灵活处理。4. 常见问题与排查技巧实录4.1 104链路频繁重连原因在序号不连续现场最常见的问题就是104链路反复重连表现为主站和终端之间的TCP连接不断断开重建。排查思路并不复杂抓包后先看U帧的STARTDT激活与确认是否成对出现再看I帧序号是否连续。104规约要求双方各自维护发送序号和接收序号序号是2的倍数递增如果接收方发现序号跳变会丢弃该帧并关闭链路。我曾经在一次调试中遇到主站程序复位后从seq0开始发但终端的接收序号已经停在100导致终端认为收到了老帧recv_seq不匹配而直接断开。解决办法就是让主站先发STOPDT再发STARTDT重置链路序号两端序号重新同步。这个坑在很多软件主站里都出现过尤其是从第三方通信管理机切到新主站时老连接不释放新连接从0开始自然会触发序号冲突。解析工具的价值就在这里一眼看出序号连续不连续。4.2 101遥信不刷新链路发送确认没对上串口101场景有个经典问题主站周期总召唤发出去了终端也回复了链路确认帧但总召唤的ASDU响应一直没有上送。排查思路是看链路层控制域的帧计数位FCB和帧有效位FCV是否按规则翻转。101规约中主站发的请求帧中FCB每隔一帧翻转一次终端回复的确认帧中FCB应等于主站请求帧中的FCB。如果主站软件没有正确翻转FCB终端会认为链路帧无效只回确认帧不同步数据。这个问题在手工搭建的测试环境里很常见。我建议解析时工具里要把控制域逐位拆出来包括DFC、FCB、FCV、功能码并自动跟踪FCB的变化趋势。这样能快速判断主站侧协议栈实现是否严谨。4.3 品质位显示“无效”但数据看着正常107故障录波、遥测值都可能遇到数据数值在合理范围内但品质描述符IV1。很多刚接触的人以为数据异常其实可能是装置刚上电还没有完成自检或者该点未接入真实测量回路装置置为无效。此时通过解析报文的QDS字节可以确认。这种情况下不要急着把QDS全置0。先看NT非当前值、SB被取代、BL被闭锁几位是不是也有置1再对照现场实际接线。经验是IV置1但其他品质正常多数是装置面板上信号仍未激发或者该点在数据库中禁用了。4.4 工具自身遇到的调试问题报文时间戳不准一次现场测试中我发现脚本打印的报文时间戳和主站后台的记录差了十几秒。查问题发现是串口接收线程用time.time()获取系统当前时间但系统时间同步没开虚拟机里漂移严重。后来改成从Windows的W32Time服务同步或者直接用终端设备侧的时间基准。如果你打算把解析工具长时间挂在现场做报文监控一定不要忽略时间同步问题。时间戳不准会直接影响SOE分析甚至让人误判故障发生时刻。5. 工具选型解析与进阶扩展方向5.1 三种方案的横向对比方案优点缺点适用场景商用调试软件如厂家自带开箱即用协议覆盖面全价格高功能固定不灵活现场验收、日常运维Wireshark 104插件免费抓包分析方便只支持网络报文对串口支持弱以太网通道的104链路分析自研Python脚本完全可控可扩展易集成需要自己维护解析逻辑批量测试、自动化测试、问题复现我个人的建议是日常抓包分析用Wireshark快速判断帧类型和ASDU结构遇到主站/终端通信异常或者需要批量回放报文场景时用自研脚本做深度解析和自动化断言。两套工具结合基本能覆盖调试全周期。5.2 扩展成在线监测模块的思路自研解析脚本还有一个方向是转成持续运行的在线监测模块。我开始做工具时只做离线解析后来发现现场需要7x24小时监控链路状态就扩展了三个功能周期统计链路连通状态TCP连接是否建立、心跳超时次数。实时统计上下行报文种类数量异常时告警。自动记录I帧序号跳变、U帧超时重发等异常事件。实际做完这个监测模块后有一次凌晨终端批量离线第二天早上我从统计日志里一眼看到某一时刻序号连续跳变多次定位到是主站侧并发连接数超限导致服务端踢连接问题在十分钟内找到而不是像以前那样靠运维一台台设备去重启。如果你所在团队没有现成的网络监测手段这个方向非常值得投入。一个小工具就能把运维从“救火模式”变成“预防模式”。5.3 对规约扩展报文的兼容性思考最后聊一部分非标扩展。101和104规约在实际工程中经常存在厂商扩展类型标识常见的是自定义的故障录波传输、加密认证等。解析工具在设计时要留好扩展口把类型标识映射表做成独立的配置文件。这样遇到陌生报文时可以先按标准类型解码把不匹配的字节原样打印出来再结合厂家说明补充映射不用改代码就能适配新设备。我见过太多团队把报文解析逻辑写死在代码里遇到一个厂家新设备就改一次代码非常痛苦。灵活的配置化解析才是工具能长期用下去的关键。本文还有配套的精品资源点击获取