简介这份PDF聚焦电力系统IEC104规约的典型报文与应用解析面向变电站自动化、调控中心通信及电力系统二次开发人员有助于快速掌握基于以太网的调度通信核心机制。资源依据国网双平面接入调控中心的新规范要求系统梳理了IEC104规约的应用环境、基本规则、五层规约结构、主动传输与问答相结合的传输机制并详细剖析了I格式、S格式、U格式三种帧结构以及测试U帧激活启动、总召I帧与确认S帧等典型报文的字节组成与控制域含义兼顾原理阐述与实际报文解析可直接用于工程调试与协议排障。压缩包内为1个PDF文档大小1.69MB内容精炼且便于查阅。目前已有402人学习适合电力系统开发、运维及协议研究人员作为技术参考。1. 电力系统 IEC104 规约典型报文应用解析双平面接入调试为什么绕不开它进变电站调试最怕的不是装置本身坏而是主站打电话说「104 链路通了但一个遥信都没上来」。抓包文件摆在那满屏十六进制对着 DL/T 634.5104-2002 标准一页页翻半天对不上一个字节这是干过调度数据网的人都有过的经历。这份《电力系统IEC104规约典型报文应用解析》是南瑞集团工程师写的实战解析不空谈协议把双通道互备机制下最常碰到的报文——链路启动、总召、SOE、遥控预置、变化遥测、对时——逐字节拆开讲还附了辛耀中、谢希仁、王首顶的参考文献。适合变电站自动化调试、调度数据网运维、以及刚接触电力二次系统的开发人员。报文这东西玄学成分往往出在序号和位域上这份资料能少走不少弯路。2. 先把链路规则立住IEC104 的应用环境、五层结构与 U/I/S 帧分类2.1 应用环境一台交换机、两台路由器和一个 2404 端口IEC104 在国内对应的就是 DL/T 634.5104-2002 协议跑在 TCP/IP 上典型拓扑是调度主站与变电站之间走以太网互联。中间设备常见的是交换机、路由器、光纤收发器极少数老站还会串协议转换器。变电站双平面接入之后一个 RTU 或测控装置往往要同时面对调度数据网的两个平面通道不再是串口线而是一张网络调试复杂度一下就上来了。做 ARP 和路由排查之前先确认一件事双方是不是都在 TCP 2404 端口上。IEC104 是 C/S 模式站端一般做服务端监听 2404主站做客户端主动连接。很多「链路不通」的现场问题根本不是规约而是端口被防火墙挡了或者光纤收发器只通了一芯。这个基础不牢后面报文解析全白搭。2.2 四条基本规则TCP/IP、平衡方式、C/S 模式与 I 帧计数原论文把基本规则总结成四条调试时每条都得刻在脑子里TCP/IP 传输承载在 TCP 之上可靠交付由 TCP 保证104 只关心 ASDU 的组装和序号。平衡方式通信应用层两端都能主动发 I 帧谁有数据谁上送不像 IEC101 那种严格的主站召唤、从站应答。C/S 模式且端口默认 2404站端 Listen主站 Connect。I 帧计数确认每个 I 帧都带发送序号和接收序号对端用 S 帧确认保证不丢不乱。这四条里最容易忽略的是第二条。串口时代很多人习惯了「主站问、从站答」的问答逻辑上了 104 还按这个思路写程序结果站端该主动上送的 SOE 迟迟不发或者发了主站不确认——不是链路问题是模型没切换过来。104 的「平衡」意味着主站可以不召站端也能主动突发抓包时看到没有请求的 I 帧别觉得奇怪这是正常行为。2.3 规约结构OSI 五层每一层管什么事IEC104 没有把 OSI 七层全用上实际只取了五层。论文里有张结构图调试时可以照着对职责物理层透明的比特流传输对应网线、光模块、光纤收发器。数据链路层把数据组装成帧对应以太网帧和交换机转发。网络层为分组交换网上的不同主机提供通信路径对应 IP 路由。运输层负责把应用程序进程交代的任务传到对端对应 TCP。应用层面向用户的应用数据也就是 ASDU。对调试最有价值的是理解「TCP 只保证字节流可靠不保证业务语义」。I 帧的序号确认机制是在 TCP 之上再叠的一层保险——TCP 丢了包会重传但重传之后 I 帧的顺序、去重、确认还得靠 104 自己的收发序号。所以抓到 TCP 重传并不等于 104 异常但 I 帧序号跳变就一定有问题。2.4 帧格式U 帧、S 帧、I 帧控制域怎么认104 的 APDU 以 0x68 起始第二个字节是长度随后是控制域控制域之后是可选的 ASDU。三种帧的差别全在控制域I 帧编号的信息传输格式控制域 4 字节包含发送序号与接收序号后面一定带 ASDU。遥信遥测、总召、遥控都走 I 帧。S 帧编号的监视功能格式控制域 4 字节只携带接收序号不带 ASDU作用是确认对端 I 帧。U 帧不编号的控制功能格式控制域 4 字节用于链路启动、停止和测试没有序号。帧类型首字节控制域示例是否带 ASDU典型用途U 帧启动6807 00 00 00 或 0B 00 00 00否链路启动与确认U 帧测试6843 00 00 00 或 83 00 00 00否链路保活S 帧6801 00 2 字节接收序号否确认 I 帧I 帧684 字节收发序号是传输业务数据控制域第一字节的 bit0 用来区分类型为 0 时是 I 帧为 1 时再往前看一位区分 S 帧还是 U 帧。这个位判断在写解析程序时几乎是第一行逻辑。U 帧的几个功能码建议直接背下来——07/0B 是启动13/23 是停止43/83 是测试别到现场现推。背熟了抓包时一眼就能看出链路状态机走到哪一步。3. 典型报文逐字节拆解总召、SOE、遥控、遥测、对时怎么读3.1 链路启动68 04 07 00 00 00 与 68 04 0B 00 00 00论文里给的第一个典型报文就是链路启动发送激活传输启动68 04 07 00 00 00接收确认激活传输启动68 04 0B 00 00 000x68 是启动符0x04 表示后面跟 4 个字节控制域。07 是「启动数据传输」的功能位0B 是对端的确认。很多初学者把这两个报文当成「测试帧」其实不是——真正的测试帧是 43/83。07/0B 完成的是 STARTDT 激活与确认它告诉对端我开始发 I 帧了。在这之前发 I 帧对端是可以直接忽略甚至丢弃的。实际抓包时链路启动发生在 TCP 三次握手之后主站先发 07站端回 0B之后才允许总召。如果抓包只看到 TCP 连接建立、没有 07/0B说明应用层还没进入传输阶段多半是站端配置没启用 104 服务或者主站线程没触发启动流程。链路启动是整个会话的地基没见过 0B 不要往下走。3.2 总召与确认64 01 … 14 的 I 帧和 01 00 02 00 的 S 帧链路启动完成后第一件事就是总召。总召是类型标识 0x64100C_IC_NA_1可变结构限定词 0x01传送原因一般为 6激活信息体地址固定为 0QOI 为 0x14十进制 20代表总召唤2136 是分组召唤。论文给的帧结构里特意把 QOI 列出来就是提醒总召不是随便发一个长帧QOI 决定了召唤范围发错范围要么数据不全要么重复上送。站端收到总召并响应后主站会收到 S 帧确认论文里的例子是 68 04 01 00 02 00。这个 S 帧的控制域是 01 00 02 0001 00 是 S 帧标志02 00 是接收序号表示「我已经连续收到你发来的 2 帧」。S 帧本身没有序号所以它不能被确认也不需要被确认I 帧的收发序号各自从 0 开始每发一帧加 1加的是帧数不是字节数。总召之后站端会把全部遥信、遥测按点号顺序上送一遍数据量大的站能持续几秒甚至几分钟。想验证总召是否走完一是看是否收到传送原因为 20总召唤结束的报文二是看之后只剩变化报文和 TESTFR不再有大批量全数据。如果总召没结束就断了下一轮调试得重新做一次总召别指望断点续传。3.3 SOE 报文1E 01 后面那 7 个字节的时标SOE 是带时标的单点遥信类型标识 0x1E30可变结构限定词 0x01 表示一个对象传送原因一般为 3突发。论文里的示例是 8 号遥信变位信息体地址指向 0x000008后面紧跟品质描述 QDS常见 0x00 表示有效再往后是 7 字节 CP56Time2a 时标。这 7 个字节的顺序固定是毫秒低字节、毫秒高字节、分钟、小时、日与星期、月、年。毫秒两个字节合成 059999分钟、小时按十六进制读日与星期共用一字节低 5 位是日高 3 位是星期月是 112年是从 2000 年起算的偏移。时标字段字节位置示例值解析结果毫秒低/高第 1~2 字节00 000 毫秒分钟第 3 字节1C28 分小时第 4 字节1016 时日与星期第 5 字节7A低 5 位 26 日高 3 位星期 3月第 6 字节0B11 月年第 7 字节052005 年SOE 是定位事故最常用的报文时间戳对不对直接决定事件顺序能否还原。常见坑是「日与星期」那个字节——有人把它当两个独立字节读结果日期偏大或者出现非法值 32 日。还有就是把毫秒高低字节读反时间戳差几秒倒还好日期错了就完全没法用。3.4 遥控预置2E 与 82 的含义预置和执行别混遥控预置报文的类型标识是 0x2E46双点命令 C_DC_NA_1传送原因为激活信息体地址 3 字节但遥控号只取低 5 位。论文的例子里遥控号是 4表示第 4 路遥控控制字节 0x82 拆开bit7 是 S/E 位置 1 表示预置Selectbit1 为 1 表示命令值为「合」。所以 82 是「预置合闸」。对应地执行合闸是 02——bit7 变 0Executebit1 保持 1。这里有个容易搞反的点先预置后执行是 104 遥控的固定流程主站必须等到站端返回「预置确认」传送原因 7之后才能发执行命令。有些调试人员在预置没确认时就发执行站端直接丢弃表现就是「遥控超时」。正确顺序应当是选择 82 → 站端确认 → 执行 02 → 站端执行确认 → 返校遥信变位。四步缺一步都算不上一次成功的遥控。3.5 变化遥测类型标识的小九九与字节序论文里给的变化遥测例子是 68 0D 开头类型标识 0x15传送原因 03突发后面是信息体地址和 2 字节遥测值示例值是 6A 6C。这里有一个现实问题标准里 15 这个类型标识对应的其实是累计量但国内不少厂家实现里把它扩展或复用为不带品质描述的测量值。调试时看到 15别急着按标准类型库去套先打开对端点表看它定义的到底是遥测还是累计量。字节序也是坑104 报文整体小端多字节数值低字节在前。示例 6A 6C 按小端读出来是 0x6C6A有些资料按高字节在前标注写的是 0x6A6C对应十进制 27244两种读法数值不一样。换算遥测工程量时还要再乘点表里的系数。很多「数值差好几倍」的现场不是系数错了就是字节序看反了。联调时必须以装置说明书和点表为准别只信抓包工具自动解码。3.6 对时报文0x67 与主站时间同步的时标对时报文的类型标识是 0x67103C_CS_NA_1主站把当前时间按 CP56Time2a 格式下发站端收到后校准本地时钟。论文给的示例毫秒低位 01、毫秒高位 02合成 0x0201 即 513 毫秒分钟 03小时 04日与星期 0x81低 5 位是 1即 1 号高 3 位是 4即星期四月 09年 052005 年。这是联调演示数据现场对时值就是当时的主站时钟。对时报文本身不长但调试时很关键站端所有 SOE 时标最终都以这个对时结果为准。如果对时没下发或者对时失败SOE 时间会越偏越多事故追忆全乱。判断对时是否成功看站端是否回传送原因为 7激活确认的应答。主站先发 06 激活站端回 07 确认这一来一回才算是把时间锁住了。4. 双通道互备下的报文时序I 帧计数、S 帧确认与主备切换4.1 双平面接入意味着两条独立的 TCP 链路国网新规范下变电站按双平面接入调控中心站端设备分别接到调度数据网的 A 平面和 B 平面。IEC104 本身没有规定双通道怎么用工程上常见的做法是两个平面各建一条 TCP 连接各跑一套完整的 104 会话主用通道负责业务备用通道通过 TESTFR 保活。一旦主通道中断备用连接立即可用。因为两条链路是独立会话各自的发送序号、接收序号不能串着用。调试时经常有人问A 平面断了B 平面的序号是不是要接着 A 的序号不是。每条 TCP 连接从 0 开始独立计数主备切换后 B 平面如果已经建立了完整会话直接用 B 自己的序号继续。站端和主站的程序都要按「每个连接一个序号上下文」来设计否则切换瞬间必然乱序出现遥信跳变或者重复 SOE。TESTFR 在双通道里起的是探活作用空闲时每隔一段时间常见 1030 秒发一个 43对端回 83证明这条链路还活着。主通道断了之后备通道因为一直有 TESTFR 保活TCP 连接往往还保持着可以直接切业务不需要重新全量总召。这也是双通道互备比单纯 TCP 重连快的原因——切换成本被平时的保活压得很低。4.2 序号机制发送/接收序号从 0 开始12 帧回一个 S 帧I 帧每发一帧发送序号加 1每收到一帧接收序号加 1。双方互相用对端的发送序号来填自己的接收序号。序号从 0 开始最大到 65535 后回绕为 0判重和确认都按这个序号走。论文提到一个工程经验典型最多接收 12 帧 I 帧回答一个 S 帧。这个 12 不是标准强制值是性能和可靠性的折中。S 帧回得越勤TCP 压力越大空帧占带宽回得越疏对端发送窗口越容易打满。常见装置上这个值在 812 之间可配。遇到两个厂家的装置对接一方按 12 帧回 S 帧另一方按 3 帧就等确认不会冲突——接收方想什么时候回 S 帧是它自己的事只要在序号回绕前别把窗口堵死就行。实际写解析程序时序号的加减要按 65536 取模。有些新手直接做整数累加跑几天后序号从 65535 回绕到 0程序判断「序号变小」就误判为乱序丢包。现场联调如果发现长时间运行后链路频繁复位先查是不是序号取模没做。4.3 主备切换时的报文特征主通道出问题时报文序列大概是这样先是 TCP 层出现重传或 RST接着主站侧 104 会话超时发起重连重连成功后重新 07/0B 握手。如果备用通道一直保活主站可以直接把业务切到备通道不再触发全量总召只把当前状态做一次对点。判断切换是否干净看这几件事切换后有没有出现接收序号突然变小说明对方换了连接上下文有没有重复的 SOE 时间戳有没有总召被重复触发如果备用通道也同时断了恢复后必须做完整总召否则主站内存里的遥信状态和现场实际不一致可能出现「遥信显示正常但遥控被闭锁」的隐患。一个容易忽略的点TCP 层断了104 会话层不一定立刻知道。所以主站和站端都要配链路超时常见是 2 倍的 TESTFR 周期。比如 30 秒探活60 秒判定链路超时。超时判定的快慢直接决定主备切换的 RTO这个参数在分布式调度系统里往往也是考核指标别拍脑袋配。5. IEC104 调试避坑五条真实踩坑记录5.1 现象TCP 已连接却收不到任何遥信遥测链路启动没走完。主站只建了 TCP 连接没发 07或者发了 07 没等 0B 就急着总召。104 的会话层和 TCP 层是两回事TCP ESTABLISHED 不代表 104 会话已建立。解决抓包确认 07 到 0B 握手完成后再发总召。程序上建议状态机里区分「TCP 已连接」和「104 会话已启动」两个状态启动完成前禁止下行业务报文。我见过多次联调现场两边折腾一下午最后发现就是主站少发了一个 07。5.2 现象U 帧的 07/0B 和 43/83 混用链路反复重启不少资料把 07/0B 写成「测试帧」现场照着这个命名去配保活结果主站周期性地发 07 而不是 43站端认为链路被反复重启。解决启动握手用 07/0B空闲探活用 43/83。抓包时看到周期性的 07先怀疑保活功能配错了而不是链路真的在重连。这个坑在双通道互备场景里尤其致命——备通道如果发的是 07 而不是 43站端会一直在「启动-确认」循环里打转主备切换时备通道根本接不住。5.3 现象SOE 时间差 8 小时或者日期完全不对CP56Time2a 的日与星期是同一个字节低 5 位是日、高 3 位是星期有人按两个字节拆日期直接错另外时区没对齐站端和主站的时区不一致SOE 时间整体偏移。解决按位域拆日与星期且主站、站端统一时区。SOE 里带的是本地时间还是 UTC两个厂家常理解不一致联调前先书面确认。这个字段在事故追忆里是核心证据错了真会背锅。5.4 现象遥控预置成功、执行无反应S/E 位用错。82 是预置合02 才是执行合。如果发了 82 之后又发 82或者把 82 当执行发出去站端只做预置不动作指令直接丢。解决严格按「预置激活 → 预置确认 → 执行激活 → 执行确认」四步走。抓包确认传送原因预置是 06确认是 07执行也是 06/07但信息体的 S/E 位不同。调试遥控前先把站端返校报文抓出来看确认它回的到底是预置确认还是执行确认。5.5 现象报文长度和字段对不上抓包工具解析乱104 报文的信息体地址固定 3 字节但有些装置固件或资料里按 2 字节写还有的厂家把公共地址做成 1 字节。两种实现混接就会长度错位工具解析必然乱。解决先确认双方的公共地址长度和信息体地址长度配置一致再谈报文内容。抓包工具解析乱码时先按 68 后的长度字节手工数一遍 ASDU 长度别全信工具。我碰过一台老装置公共地址配成 1 字节主站按 2 字节解所有遥信地址全偏了一位排查了整整两天。6. 从抓包到反推配置验证双通道和点表的一套习惯6.1 用 Wireshark 的 IEC 104 过滤器先分帧Wireshark 对 104 有现成的 dissector过滤关键字是iec104。先按帧类型过滤iec104.u_format看 U 帧iec104.i_format看 I 帧iec104.s_format看 S 帧。启动阶段就看 U 帧业务阶段就看 I 帧思路一下清晰很多。不要一上来就盯着十六进制面板先让工具把帧分类再对可疑帧逐字节核。6.2 用总召报文反推点表总召开始后站端按点号顺序上送全部遥信遥测。抓一段完整总召数一数不同类型标识的 I 帧数量能大致估出站端配置了多少遥信、多少遥测。再用最后一帧的发送序号减第一帧的发送序号能算出总召数据总量。这个数字和点表一对就能发现漏配、错配。我一般会用一段简单的 Python 脚本把抓包里的 I 帧序号提取出来算差值比在 Wireshark 里手数可靠。import re frames [] # 每项: (发送序号, 接收序号, 类型标识) for line in open(iec104.txt, encodingutf-8): if I-frame not in line: continue nums re.findall(rsend\s*(\d).*recv\s*(\d).*typeId\s*(\d), line) if nums: frames.append(tuple(map(int, nums[0]))) if frames: first, last frames[0], frames[-1] total (last[0] - first[0] 1) % 65536 print(I帧数量(近似):, total) print(首帧类型:, first[2], 末帧类型:, last[2])这段脚本从 Wireshark 导出的文本行里匹配 I 帧的发送序号、接收序号和类型标识最后用首尾发送序号差估算总召期间的总帧数。输入文件是 Wireshark 的「导出为纯文本」格式每行包含 I-frame、send、recv、typeId 等字段实际字段名可能因版本略有差异用之前先打开文件校对正则。超过 65536 帧的总召差值要按 65536 取模脚本里已经处理。6.3 我现在的调试顺序去一个新站我固定走四步先抓 30 秒 U 帧确认启动和保活正常再触发一次总召确认全数据上送顺序和类型接着做一次遥控预置和执行验证 S/E 位最后做一次对时并等 SOE验证时间戳解析。四个都过了才敢动点表。这套顺序是当年在调度数据网联调时被坑出来的——早期我上来就遥控结果连启动都没走完白白折腾半天。从那以后每到一个新站我都强制自己先走一遍「U 帧 → 总召 → 遥控 → 对时」的固定流程链路侧的问题先清零再谈业务。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?