做电力远动联调的工程师,基本都碰过这种场景:现场IEC104主站还没完全就绪,站端测控装置却已经上电,调度电话一个接一个地催,后台监控页面上却一个遥测都刷不出来。这时候你最需要的并不是什么高深的算法,而是一台能稳稳扮演从站/服务端角色的模拟器,先把链路、报文和数据点全部验证一遍,让主站先跑起来。我自己从硬件调试转到规约联调,前前后后试过不少软件,也踩了一堆坑,这篇就把我常用的IEC104从站模拟器、仿真器以及配套调试工具的选型思路和实际项目里的操作细节整理出来,给正在做主站开发、验收测试或者现场排查的朋友做个参考。
1. 为什么联调IEC104设备,我强烈建议先搞一台从站模拟器
1.1 从站模拟器在调试链路上到底扮演什么角色
IEC 60870-5-104 是目前电力调度自动化里最常见的远动规约之一,基于TCP/IP承载,默认端口2404。链路两端分别叫主站和从站,主站是客户端,一般跑在调度端或集控中心;从站是服务端,通常部署在变电站的测控装置、RTU、保护管理机里。从站模拟器的核心价值就是把这套“服务端行为”完整地搬到你自己的PC上,不需要真实装置也能让主站把整个流程走一遍。
我在项目里最常用的方式是:把从站模拟器运行在调试笔记本上,配置几个遥信、遥测点,然后把正在开发的主站软件连上去。主站做总召唤,模拟器回数据;主站发遥控,模拟器返回确认;主站要求时钟同步,模拟器也能正确响应。相当于在主站真正进现场之前,先把“假设备”演给你看,所有规约层面的问题都能在这个阶段暴露出来。
1.2 主站模拟器和从站模拟器是两码事,别选反了
很多刚接触的人会把主站模拟器和从站模拟器混为一谈,其实这两类工具的行为模式完全相反。主站模拟器是TCP客户端,主动发起连接、下发总召唤和遥控命令;从站模拟器是TCP服务端,被动监听端口,等主站连接进来之后再做应答。如果你要测试的是后台监控系统这类主站设备,就需要一个从站模拟器;反过来,如果要测试现场测控装置这类从站设备,才需要用主站模拟器。
这个区别有点像打电话:主站是打电话的人,从站是接电话的人。你要是把从站模拟器开成了主站模式,两边都等着对方先说话,结果就是永远握手成功不了。这类问题在项目里很常见,尤其是那种同时提供Client和Server两种模式的工具,一不留神就选错。
1.3 模拟器能直接搞定的三类典型问题
我判断一个调试工具值不值得用,就看它能不能快速解决下面三类问题:
第一类是数据一致性问题。主站显示的遥信点号、遥测值、品质位,跟现场实际是不是对得上。用模拟器可以随意改值、改品质、模拟变位,逐点核对主站的映射关系。
第二类是链路稳定性问题。正式的运行环境里,网络抖动、装置重启、主备切换都是家常便饭。模拟器可以人为制造断连、重连、长时间无报文等场景,验证主站是否能自动恢复。
第三类是规约细节问题。比如ASDU的公共地址是1字节还是2字节、信息体地址从0开始还是从1开始、总召唤结束标志有没有正确上送。这些在纸面上不容易说清,用模拟器结合实际抓包,一眼就能看明白。
2. 几款主流IEC104从站/服务端模拟器横评
2.1 lib60870 自带 server 示例:最硬核但最可靠
lib60870是开源社区里做IEC104协议栈绕不开的一个C库,出自MZ Automation,GitHub上可以直接拿到源码。它本身不是专门的“模拟器软件”,但代码仓库里带了完整的server示例,编译出来就是一个能跑在2404端口上的从站服务端。
我最早接触这个库是因为现场装置里的协议栈就是基于它改的,后来发现直接拿它的server示例做调试反而更稳。编译过程不复杂,CMake配置一下,把examples/server目录编出来就有一个最小可用的从站。缺点也很明显:要改数据点,得修改C代码、重新编译,没有图形界面,对不熟悉编译链的人不太友好。但它的优点是无依赖、跨平台、跑在Linux服务器上特别稳定,适合做长期测试或者二次开发。
2.2 FreyrSCADA 和 CAS 的图形化工具:上手最快
如果说lib60870是硬核路线,那FreyrSCADA和CAS这类Windows图形化工具就是效率路线。FreyrSCADA提供专门的IEC 104客户端和服务端模拟器,界面里可以直接配置数据点、选择ASDU类型、观察连接状态和收发报文,比较适合演示和快速验证。
CAS IEC 104 Server Simulator也是我常用的工具,它的配置逻辑更简单,添加一个点、填好地址和类型,点运行,主站就能连上来。试用版一般有点数或者时间限制,但日常联调足够用。这类工具的好处是省去了写代码的成本,现场同事拿来就会用,不太需要培训。
2.3 Python 脚本快速模拟:适合自动化测试
在某些特殊场景下,你需要精确控制每一个字节的报文,图形化工具有时候反而碍事。这时候我会直接用Python写一个轻量级从站。思路并不复杂:监听2404端口,解析收到的APDU,根据控制域类型回对应的U帧、S帧或I帧,再按ASDU格式组包上报数据。
核心结构可以简化成下面这样:
def build_u_frame(cmd): return bytes([0x68, 0x04, cmd, 0x00, 0x00, 0x00]) # STARTDT ACT = 0x07, STARTDT CON = 0x0B收到主站的启动帧后回一个STARTDT_CON,收到总召唤后就批量上送遥信遥测,最后补一个总召唤结束帧。脚本虽然简陋,但胜在可控,想模拟什么异常报文都行,做自动化回归测试的时候特别好用。如果你熟悉openMUC的Java版本,也可以基于j60870写类似服务端,效果差不多,只是我更习惯用Python快速迭代。
2.4 工具横评小结
| 工具类型 | 界面 | 数据点配置 | 多连接 | 适用场景 |
|---|---|---|---|---|
| lib60870 server示例 | 无界面 | 修改C源码 | 支持 | 协议学习、长期稳定跑、二次开发 |
| FreyrSCADA 服务端模拟器 | Windows图形界面 | 鼠标点击完成 | 支持 | 演示、快速功能验证 |
| CAS IEC 104 Server Simulator | Windows图形界面 | 鼠标点击完成 | 多数版本支持 | 现场快速联调 |
| Python/j60870自研 | 命令行/脚本 | 改代码 | 可控 | 自动化测试、异常注入 |
如果你的预算允许,也可以考虑硬件的规约测试仪。软件模拟器在功能覆盖上已经很接近,但硬件的时序精度、长时间稳定性、多端口并发能力更专业,适合正式的出厂验收。大多数研发和调试场景,软件模拟器完全能扛住,不需要一上来就买昂贵设备。
3. 用模拟器搭最小可用测试环境:关键配置一次说清
3.1 先做一张数据点规划表
不管用哪款模拟器,第一步都是规划数据点。我习惯在配置之前先建一张表,把信息体地址、类型、初始值都列清楚,这样后面在主站侧核对时才有依据。
| 点名 | 信息体地址 | ASDU类型 | 公共地址 | 初始值 |
|---|---|---|---|---|
| 开关合位 | 1 | 单点遥信 M_SP_NA | 100 | 1 |
| 开关分位 | 2 | 单点遥信 M_SP_NA | 100 | 0 |
| 母线电压 | 4001 | 短浮点遥测 M_ME_NC | 100 | 220.5 |
| 累计电量 | 7001 | 累计量 M_IT_NA | 100 | 12345 |
信息体地址一般用3字节,公共地址常用2字节,但具体要看主站侧怎么解析。如果主站用1字节公共地址,而模拟器配成了2字节,ASDU里多出来的那一字节会被当成传送原因,所有数据全部错位。这一点在配置模拟器前先和主站负责同事确认清楚,能省掉后面大量排查时间。
3.2 理解I/S/U帧,模拟器才不会乱回
IEC104的APDU控制域分三类帧。U帧负责启动、停止、测试传输,常见的是STARTDT=0x07、STARTDT_CON=0x0B、STOPDT=0x13、TESTFR=0x43。S帧用于确认接收序号,首字节通常是0x01。I帧是真正的数据帧,首字节最低位为0,携带发送序号和接收序号,后面跟ASDU。
很多从站模拟器“死活连不上”的问题,根源在于没有正确处理U帧。主站连上TCP端口后,第一件事是发STARTDT_ACT,模拟器必须回STARTDT_CON,链路才算进入可传输状态。如果模拟器收到U帧后没有回应,主站侧就会一直卡在启动阶段,看起来TCP端口是通的,但数据一条都上不来。
3.3 ASDU类型标识怎么选
数据点类型的选择直接决定主站能不能正确解析。遥信最常见的是单点信息M_SP_NA,类型标识为1;如果现场是双位置开关,用M_DP_NA,类型标识为3。遥测我喜欢用短浮点M_ME_NC,类型标识13,传输float直接方便;旧系统里也有用归一化值M_ME_NA的,需要额外配置量程系数。
遥控命令里,单点遥控C_SC_NA类型45,双点遥控C_DC_NA类型46,设点命令用C_SE_NC类型50。模拟器收到遥控指令后,通常会回一个“激活确认”传送原因7,执行完再回“结束”传送原因10。如果模拟器不回确认,主站会一直等遥控结果,这也是联调时常见的问题。
3.4 一套可复用的联调验证顺序
按下面的顺序走,一套联调流程基本不会乱:
- 先用通用TCP工具或主站软件连接模拟器的2404端口,确认端口通。
- 主站下发STARTDT_ACT,看模拟器是否返回STARTDT_CON。
- 主站发送总召唤命令,检查模拟器是否上送所有配置的遥信遥测,并返回总召唤结束帧。
- 修改模拟器里某个遥测值,看主站是否收到突遇上送。
- 触发一次开关变位,看主站能否实时刷新并记录事件。
- 主站下发遥控命令,确认模拟器返回激活确认和执行结束。
这套流程在多个现场项目里验证过,能覆盖大部分规约和数据映射问题。
4. 联调现场踩过的坑,附排查思路
4.1 能建立TCP连接,但主站迟迟不显示数据
有次联调,主站软件显示“已连接”,但遥信遥测一栏全部空白。我第一反应是模拟器配错了,结果把报文抓出来一看,主站根本没有发STARTDT_ACT,TCP连接建立后一直在干等。后来查主站配置文件,发现它把对端当成了另一种规约的连接,默认不需要启动帧,导致链路一直没有进入可传输状态。
排查这类问题,我的思路是:先看主站有没有发U帧启动命令;再确认模拟器有没有回U帧确认;如果两边都正常,再往下查ASDU。只要启动帧这一步卡住,后面所有数据都不可能通,所以我会在模拟器日志里专门看连接的启动过程。
4.2 公共地址位数不一致,数据全飘
另一个典型坑是ASDU公共地址的位数。理论上IEC104允许公共地址配成1字节或2字节,具体取决于系统配置。实际项目里,现场装置固件写死了2字节,主站配置却按1字节解析,结果整个ASDU的字段全部错位,遥信值变成品质位,遥测值变成随机数。
这类问题光看界面不容易发现,必须抓包对比。我通常会在Wireshark里过滤2404端口,把主站收到的ASDU逐字节和规约文档对照。如果公共地址字段多了一位,后面所有信息体地址和数值都会往后漂移一个字节,数据必乱。
4.3 I帧序号不连续,引发“假掉线”
IEC104的I帧带有发送序号和接收序号,用来做链路可靠性控制。有的简化模拟器在断线重连后没有重置序号,或者收到主站的S帧确认后没有更新接收序号,继续沿用旧序号发数据。主站一旦发现序号不连续,会认为数据帧丢失或错序,直接丢弃,表现出来就是“模拟器明明在发数据,主站却一直收不到”。
排查时抓包最容易发现:I帧控制域的发送序号如果出现跳变或者突然归零,基本就是序号处理逻辑的问题。好的模拟器会在链路断开重连后自动重置序号,或者在界面上提供手动重置按钮。用lib60870这种成熟的协议栈基本不会踩这个坑,但如果是自己写的脚本模拟器,就一定要处理序号初始化。
4.4 多客户端同时连接,有的模拟器直接拒绝
调度主站常常配置成双前置机,一台主机一台备机,两台会同时连接同一个从站。某些从站模拟器默认只允许一个客户端,第二个连接一上来就会把第一个踢掉,或者干脆停在“已建立TCP但没有任何数据”的状态。现场看到的现象就是:主用前置机数据正常,备用前置机一直连接中,两边来回切换时链路总断。
选型时一定要确认模拟器是否支持多客户端连接。我当时在对比CAS和FreyrSCADA时就特别留意了这一点,后来直接用lib60870的多连接支持才把测试场景完整跑起来。
5. 从站模拟器的进阶玩法:断链、异常注入与多从站
5.1 断链重连测试,验证主站的恢复能力
很多主站软件在实时数据正常时看不出问题,一旦网络断开再恢复,就暴露出各种缺陷:有的不会主动重新连接,有的重连后不重新做总召唤,有的即使连接恢复了数据也不再刷新。从站模拟器可以用来做断链重连测试,方法是让模拟器每隔一段时间主动断开TCP连接,或者暂时停止响应,观察主站能不能自动恢复。
我建议在测试前先用抓包工具留一份完整记录,重点看主站重连后是否重新发起STARTDT、是否做总召唤、模拟器是否正确回应。这个测试在验收阶段几乎必做,很多现场故障都跟重连恢复不完整有关。
5.2 异常报文注入,做规约负向测试
异常注入是模拟器的进阶用法,也是检验主站健壮性的重要手段。常规做法包括:发送长度字段错误的APDU、故意发非法公共地址、把I帧发送序号固定不变、把遥测品质字置为“无效”等。主站对这些异常的处理方式,决定了它在真实复杂网络环境下会不会误报、卡死或者崩溃。
需要说明的是,这类负向测试在电力自动化工程里是标准测试项,目的是验证设备对异常输入的处理能力,属于合规的技术手段。模拟器能够精确控制每一个字节,所以比拿真实装置做这些测试更安全、更高效。
5.3 多从站并发,模拟整个变电站的接入
自动化验收的时候,单台模拟器往往不够用。你可以同时开多个lib60870实例,分别监听2404、2405、2406等不同端口,每个进程对应一个子站;也可以在一台机器上跑多个图形化工具有点麻烦,但用脚本或协议栈的方式会方便很多。主站侧给每个子站配置不同的公共地址,就能模拟出一个小型变电站的多从站接入效果。
我做过一次模拟11个子站的验收测试,用11个lib60870进程跑在同一个Linux服务器上,主站全部正常接入。这种多从站并发方式特别适合验证主站的通道容量、数据刷新性能和长时间稳定性。
6. 不同场景选型指南与个人经验
6.1 现场快速联调,选图形化工具最省事
如果是去现场解决问题,时间紧、环境杂,我强烈建议优先用CAS或FreyrSCADA这类图形化工具。现场同事不一定熟悉编译环境,图形界面里点几下就能把数据点配上,出了问题也方便直接看连接状态。只要能满足点数和连接数的限制,它们基本就是“打开就能用”的调试利器。
6.2 协议学习和自动化测试,用协议栈和脚本
如果你想彻底弄懂IEC104,最好的路径是先编译运行lib60870的server示例,然后配合Wireshark把每一个字节的APCU、ASDU都对照规约文档过一遍。等基础牢固了,再用Python脚本按自己的需求改造,做成自动化测试工具。这条路虽然起步慢,但长期回报最高,项目里遇到规约商量不清的时候,你能自己造一个“任意行为”的模拟器,比任何人都快。
6.3 踩过几次坑之后,我养成的几个习惯
每次联调开始前,我都会先启动抓包工具,把整个调试过程的报文留档。这样即使当场没发现问题,后面也能复盘。模拟器和主站的配置,我都会导出成文本,放到工程目录里和图纸放在一起,方便下次复现。
还有一点是工具不要贪多。我见过有人电脑里装了三四个模拟器,每个都只用了其中一两个功能,反而把自己搞懵。我个人固定用lib60870和CAS这两款,一个管复杂场景,一个管快速联调,已经足够覆盖绝大多数工作。IEC104从站模拟器始终是个调试手段,能在关键时刻帮你把链路和数据说明白,比工具本身是不是“最新版本”重要得多。