资讯动态

IEC-104 报文解析实战:帧结构、ASDU 类型与调试排错指南

发布时间:2026/9/23 17:46:35 来源:尧图企业网站定制
简介这份资料聚焦电力系统 IEC-104 规约的报文解析面向从事电力自动化、SCADA 通信开发与调试的工程师及初学者。内容围绕常用报文类型展开逐字节说明其作用与含义帮助读者在开发中快速定位问题、理解报文规则减少反复查阅标准文档的时间成本。资源包共 11 个文件约 838KB包含 PDF 文档与 HTML 页面两种浏览方式辅以 js 脚本、字体图标及样式文件可直接打开 index.html 在浏览器中查看也可阅读 PDF 版本。目前已有 8257 人学习下载说明其在电力通信领域具有较高的参考价值。读者可借此掌握 104 报文的帧结构、类型标识与传输原因等关键知识点形成从报文捕获到含义解读的完整认知适合作为日常开发调试的速查手册与入门学习材料。1. 为什么一张 IEC-104 报文表能省掉半天抓包很多做电力自动化的工程师第一次接触 104 规约都是在变电站后台和主站对不上点的时候。抓包工具里刷出一屏68开头的十六进制盯着68 0E 00 00 00 00 46 01 03 00 01 00 00 00 00这种串完全不知道从哪看起。IEC-104 本质是 IEC-60870-5-101 的 TCP/IP 封装版本把串口上的 FT1.2 帧塞进 TCP 载荷用 APCI 做链路控制、ASDU 做业务数据。它跑在 2404 端口一个连接就是一条链路主站是控制方RTU 或测控装置是被控方。真正让人头疼的不是协议本身而是报文类型太多总召唤、遥测、遥信、遥控、时钟同步、电度召唤每种 ASDU 的类型标识TypeID不同信息对象地址IOA的编排规则也不同。手里有一份按类型整理好的报文详解配合抓包对照定位问题的时间能从半天压到十几分钟。这篇内容适合刚接手 104 调试的自动化工程师、做规约测试的软件开发者以及需要写 104 主站或从站模拟程序的人。2. IEC-104 帧结构与 APCI 链路层报文拆解2.1 三种帧格式的判别方法104 的 APCI 只有 6 个字节但三种帧格式的区分全在这 6 个字节里。第一个字节固定是0x68第二个字节是 APDU 长度不含启动符和长度字节本身。关键看第 3、4 字节的控制域帧类型控制域第 1 字节特征用途典型报文I 格式bit0 0传输 ASDU 数据68 0E 00 00 00 00 64 01 06 00 01 00 00 00 00 14S 格式bit01, bit10确认收到 I 帧68 04 01 00 00 00U 格式bit01, bit11链路启停、测试68 04 07 00 00 00STARTDT act判别顺序很简单先看控制域第一字节最低位为 0 就是 I 帧为 1 再看次低位为 0 是 S 帧为 1 是 U 帧。U 帧的六种功能码STARTDT、STOPDT、TESTFR 的 act/confirm都落在控制域第一字节的高 6 位。2.2 用 Python 解析 APCI 头部抓包拿到的原始字节流第一步就是把 APCI 剥出来。下面这段代码处理 TCP 流里粘包的情况按长度字段切分 APDUimport struct def parse_apci(data: bytes): 解析 IEC-104 APCI 头部返回帧类型和控制域信息 frames [] offset 0 while offset len(data): if data[offset] ! 0x68: offset 1 continue length data[offset 1] apdu data[offset: offset 2 length] if len(apdu) 2 length: break # 半包等下次数据 ctrl1 apdu[2] if ctrl1 0x01 0: ftype I send_seq (apdu[2] | (apdu[3] 8)) 1 recv_seq (apdu[4] | (apdu[5] 8)) 1 info {type: ftype, tx: send_seq, rx: recv_seq, asdu: apdu[6:]} elif ctrl1 0x03 0x01: info {type: S, rx: (apdu[4] | (apdu[5] 8)) 1} else: info {type: U, func: ctrl1 0xFC} frames.append(info) offset 2 length return frameslength字段只统计控制域加 ASDU 的字节数不含启动符和它自己所以切片时是2 length。I 帧的发送序号和接收序号各占 15 位低字节在前右移一位去掉格式位。U 帧的功能码用ctrl1 0xFC取出高 6 位0x07是 STARTDT act0x0B是 STARTDT con0x13是 STOPDT act0x23是 STOPDT con0x43是 TESTFR act0x83是 TESTFR con。2.3 链路建立与序号确认机制链路刚连上时双方都处于停止状态主站必须先发68 04 07 00 00 00请求激活传输从站回68 04 0B 00 00 00确认后才允许发 I 帧。这个握手不做后面所有总召唤都会被丢弃这是新手最常见的坑。I 帧的序号是 15 位循环0 到 32767。发送方每发一个 I 帧 tx 加一接收方收到后用自己的 rx 记录期望的下一个序号。当接收方累计收到 8 个 I 帧默认参数 k12、w8就要回一个 S 帧确认否则发送方窗口耗尽会停发。调试时如果看到 I 帧发到某个序号后卡住先查 S 帧有没有正常回。提示k 和 w 是可配置参数k 是发送方未确认 I 帧的最大数量w 是收到多少个 I 帧后必须发 S 帧确认。不同厂家默认值可能不同对接前先确认。3. ASDU 类型标识与常用报文实战解析3.1 总召唤与遥测遥信上送总召唤是调试时第一个要跑通的流程。主站发类型标识 100C_IC_NA_1的 ASDU从站回 100 确认然后依次上送类型 1单点遥信、9归一化遥测、11标度化遥测、13短浮点遥测最后再发一个 100 表示总召唤结束。一条典型的单点遥信报文68 0E 00 00 00 00 01 01 03 00 01 00 00 00 00 00。拆开看01是 TypeID单点信息01是可变结构限定词VSQ高 1 位表示是否连续低 7 位是信息对象个数这里 1 个03是传送原因3 表示突发spontaneous00 01是公共地址00 01 00是信息对象地址 IOA最后一个00是遥信值bit0 表示分合。归一化遥测的 TypeID 是 9值是两个字节的有符号数实际工程值 原始值 × 系数。短浮点遥测 TypeID 是 13值占 4 字节IEEE 754 格式直接struct.unpack(f, ...)就能还原。3.2 遥控与时钟同步报文遥控分四步选择、选择确认、执行、执行确认。TypeID 是 45C_SC_NA_1 单点遥控或 46C_DC_NA_1 双点遥控。选择和执行靠传送原因区分6 是激活7 是激活确认8 是停止激活10 是激活终止。def build_control_cmd(ioa: int, value: bool, select: bool): 构造单点遥控 ASDUselectTrue 为选择False 为执行 type_id 45 vsq 0x01 cot 6 if select else 6 # 激活 ca struct.pack(H, 1) ioa_bytes struct.pack(I, ioa)[:3] sco (0x01 if value else 0x00) | (0x80 if select else 0x00) asdu bytes([type_id, vsq, cot]) ca ioa_bytes bytes([sco]) apci bytes([0x68, len(asdu) 4, 0x00, 0x00, 0x00, 0x00]) return apci asduSCO 字节的 bit7 是选择/执行标志1 为选择0 为执行bit0 是合分闸1 为合。时钟同步用 TypeID 103C_CS_NA_1ASDU 里带 7 字节 CP56Time2a 时间前两字节是毫秒后面依次是分、时、日、月、年。3.3 传送原因与公共地址的对应关系传送原因COT是排查问题的关键字段常见值如下COT 值含义典型场景3突发遥信变位主动上送5被请求响应总召唤6激活主站下发命令7激活确认从站确认收到命令10激活终止命令执行完成20响应站召唤总召唤数据公共地址CA一般 2 字节标识不同的 RTU 或装置。如果主站收到数据但点表对不上先核对 CA 和 IOA 是否和点表一致这两个字段错一个数据就映射到别的点位上。4. 104 报文调试排错与性能优化技巧4.1 常见异常报文定位链路建不起来先看 STARTDT 有没有回 confirm。如果主站发了68 04 07 00 00 00但从站没回68 04 0B 00 00 00检查从站是否配置了允许建立连接、端口是否被占用、防火墙是否放行 2404。总召唤超时看从站有没有回类型 100 的激活确认。如果确认回了但数据不上送多半是点表配置为空或 IOA 越界。遥控失败重点看选择确认和执行确认的 COT 是不是 7如果从站回的是否定确认COT47说明命令被拒绝查遥控闭锁或权限配置。序号错乱是另一个高频问题。如果主站收到的 I 帧 rx 序号和本地期望的不一致说明有丢包或重复。104 本身不带重传靠 TCP 保证可靠但 TCP 断开重连后序号会重置主站必须重新发 STARTDT。4.2 用 tcpdump 和 Wireshark 过滤 104 流量现场没有专用工具时tcpdump 加 Wireshark 是最快的组合。在装置侧抓包# 抓取 2404 端口流量保存为 pcap 供 Wireshark 分析 tcpdump -i eth0 -w iec104.pcap tcp port 2404 # 实时查看 104 报文十六进制 tcpdump -i eth0 -X tcp port 2404 and tcp[13] 8 ! 0第一条命令把流量存下来Wireshark 打开后直接能识别 IEC 60870-5-104 协议自动解析出 TypeID、COT、IOA。第二条只抓 PSH 标志置位的包过滤掉纯 ACK减少噪音。Wireshark 里可以用iec60870_asdu.typeid 100这样的过滤器只看总召唤。4.3 批量测试与参数调优做规约测试时经常需要模拟从站批量上送数据。用 Python 起一个简易从站循环构造遥测帧import socket, time, struct def send_measure(sock, ioa, value): 发送短浮点遥测TypeID13 asdu bytes([13, 0x01, 0x03]) struct.pack(H, 1) asdu struct.pack(I, ioa)[:3] asdu struct.pack(f, value) bytes([0]) apci bytes([0x68, len(asdu) 4, 0x00, 0x00, 0x00, 0x00]) sock.send(apci asdu) s socket.create_connection((127.0.0.1, 2404)) for i in range(100): send_measure(s, 0x4001 i, 220.5 i * 0.1) time.sleep(0.05)struct.pack(f, value)把浮点数转成 4 字节小端IOA 取 3 字节。批量发送时注意 k 窗口发太快会触发流控实际测试中每发 8 帧插一个 S 帧确认更稳。参数调优上k 值调大能提高吞吐但增加内存占用w 值调小确认更及时但增加网络开销一般保持默认即可除非链路质量差需要调整。注意模拟从站时公共地址和 IOA 必须和主站点表严格对应否则主站会丢弃或映射错误。测试前先导出点表核对一遍。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价