FEATURED · 精选文章

实用IEC104模拟器:从协议原理到SCADA联调实战

发布时间 / 2026/9/2 19:02:58
来源 / 创域科博编辑部
栏目 / 资讯中心
实用IEC104模拟器:从协议原理到SCADA联调实战 简介面向电力系统自动化与SCADA领域开发者IEC104模拟器以源码形式提供主站IEC104NAMaster与从站IEC104NASlave两大组件支持多种操作码模拟可用来测试从站设备兼容性、验证主站控制逻辑也能在没有真实RTU的环境下完成联调排错。压缩包共198个文件以C源码为主包含34个头文件和28个cpp源文件同时附带可执行exe、动态库dll及工程配置文件便于直接编译运行或二次开发整体大小约26.68MB。资源发布后已有3731人学习下载。开放源代码使读者既能深入理解IEC104协议在TCP/IP上的实现细节也可按需修改通信行为、扩展自定义功能适合协议学习、教学实验和项目预研。尤其对需要快速搭建测试环境的工程师这套主从站模拟器能显著降低真机依赖提升调试效率。 这段时间一直在折腾电力自动化相关的调试工作手头最常用的就是一个IEC104模拟器支持多种操作码从最基本的遥信遥测上报到遥控下发、总召唤、电度召唤基本都覆盖了实测下来非常顺手。如果你也正在做SCADA系统联调、变电站后台测试、或者规约转换装置验证那么这个模拟器一定能帮上大忙。这篇博文我从协议本身、操作码体系、模拟器搭建到问题排查完整写一遍希望能帮你少踩几个坑。1. 为什么需要一个实用可靠的IEC104模拟器1.1 现场调试最容易被卡住的环节做电力自动化的人都有这种体验现场设备还没进场或者设备已经有电但还没完全调试好但后台SCADA等着联调调度端又催着要数据。这个时候如果没有模拟器整个联调进度就卡死了。我们总不能拿一堆真机去挨个触发信号测流程成本太高效率太低。IEC104模拟器解决的就是这个“空窗期”问题。它可以在一台普通电脑上模拟出成百上千个遥信、遥测点以规定的协议格式上报给主站。你也可以把它当做一个测控装置来用接收主站下发的遥控命令返回确认和结束帧完整走一遍控制流程。很多朋友一开始觉得模拟器很简单无非是发帧收帧的事但实际上操作码支持是否全面、时序参数是否标准、异常处理是否到位都直接影响你的调试进度。还有一个容易被忽略的点模拟器在自动化测试中的作用。回归测试、压力测试、边界条件测试这些用真机很难做但用模拟器可以随时构造各种数据组合和异常场景。比如我测试主站对遥测越限告警的处理能力时用模拟器一次性把几百个点的数值同时推到阈值之上真机很难做到这个效果。1.2 模拟器到底替你省了什么事我用这个模拟器最直接的感受省掉了一大半的人工协调成本。以前做联调测一个遥控点就要等现场人员在设备端操作一次一来一回可能半天就过去了。用模拟器之后我自己在电脑上就把遥控流程跑通了然后再拿真机做一次确认测试就行联调周期可以压缩一半以上。另外一个很省心的地方是数据一致性检查。模拟器可以按配置的地址范围自动生成连续的点位数据主站侧哪些点没配、哪些点地址对不上一比对就能发现。这在数据接入量大的场景下比人工逐点核对快太多了准确率也高得多。2. 协议要点和操作码体系2.1 帧结构中的关键字段先把IEC104的基础打牢。IEC104是IEC 60870-5-104规约承载在TCP/IP之上默认端口是2404。链路层的数据单元叫APDU应用协议数据单元由APCI应用协议控制信息和ASDU应用服务数据单元两部分组成。APCI里最关键的几个东西启动字符0x68表示这一帧是IEC104报文。长度字段一个字节表示后续APDU的长度有效范围是4到253。控制域I帧使用发送序号和接收序号各占3位每序号都乘以2存储在控制域中S帧只包含接收序号用于应答U帧用于启动、停止、测试等控制。ASDU部分包含类型标识Type ID、可变结构限定词VSQ、传送原因COT、公共地址Common Address、信息对象地址IOA以及具体的信息元素。其中类型标识就是我们常说的“操作码”决定了这一帧数据的含义和结构。举个例子单点遥信的Type ID是1M_SP_NA_1双点遥信是3M_DP_NA_1归一化遥测是9M_ME_NA_1短路浮点遥测是13M_ME_NC_1单点遥控是45C_SC_NA_1双点遥控是46C_DC_NA_1总召唤是100C_IC_NA_1。模拟器支持多少种操作码决定了你能用它模拟多少种业务场景。2.2 操作码类型标识分类与使用场景从用途上可以把操作码分成几大类第一类是监视方向的数据上报包括遥信、遥测、电度等。单点遥信M_SP_NA_1、双点遥信M_DP_NA_1、归一化遥测M_ME_NA_1、标度化遥测M_ME_NB_1、短浮点遥测M_ME_NC_1是最常见的。现在变电站里多数模拟量都用短浮点传输直接把工程值转成float塞进去就行省去了归一化系数的换算麻烦。第二类是带时标的报文比如M_SP_TB_1类型30、M_ME_TD_1类型21、M_ME_TF_1类型31。带时标数据主要用于SOE记录、故障波形分析、事故追忆等场合模拟器需要正确解析CP56Time2a格式的时标字段否则主站侧显示的变位时间会完全不对。第三类是控制方向的命令包括单点遥控C_SC_NA_1、双点遥控C_DC_NA_1、设点命令C_SE_NC_1、升降命令C_RC_NA_1等。遥控命令在模拟器侧需要正确响应“执行”和“取消”并且按照协议要求返回确认帧和结束帧。我见过不少人在这个环节翻车模拟器只回了一次确认没回结束帧导致主站一直认为命令还没完成。第四类是系统命令比如总召唤C_IC_NA_1、电度召唤C_CI_NA_1、时钟同步C_CS_NA_1类型103。总召唤和时钟同步是调试中最常用的系统命令模拟器必须支持否则主站侧的“对时”和“全数据刷新”两个基础功能就废了。2.3 重要的时序参数除了操作码之外IEC104的时序参数也很关键。协议里定义了t0连接建立超时、t1发送/接收超时、t2确认超时需小于t1、t3测试帧发送周期、k最大发送未确认帧数、w最大接收未确认帧数。模拟器配置中如果这些参数设置不合理常常会出现连接正常建立后不久就反复断开的情况。我建议调试时先按标准的参数来比如t010秒t115秒t210秒t320秒k12w8。等协议流程稳定了再去修改参数测试主站侧的边界处理能力。3. 模拟器功能拆解与选型思路3.1 核心功能清单一个真正“可用”的IEC104模拟器至少得具备下面这些能力支持被动监听和主动连接两种模式。被动监听时模拟器作为服务端主站主动连接上来主动连接时模拟器作为客户端去连接主站。这两种模式都要支持因为实际项目里两种场景都有。点位配置要灵活。能按信息体地址批量生成点位也能单独修改单个点位的属性比如遥信的通断状态、遥测的实时数值、电度的累积值等。我看过一些模拟器点位只能手动一个一个加调试几百个点的时候真的会疯掉。操作码覆盖要全。至少覆盖上面提到的四类常见操作码最好还能支持类型标识不连续、信息体地址不连续等非标配置这样才可以模拟出各种“不守规矩”的现场设备。报文日志要详细。每条收发报文都要能查看原始十六进制数据并且最好有解析结果方便定位问题。没有报文日志的模拟器出了问题你完全无从下手。3.2 操作码支持的实现方式自己写IEC104模拟器的时候操作码支持的核心在于ASDU的编解码模块。每一种类型标识对应的信息体结构都不一样需要单独写解析和封装逻辑。比如短浮点遥测M_ME_NC_1信息体包括信息对象地址3字节、IEEE 754浮点值4字节、品质描述符1字节总共8字节。而单点遥信M_SP_NA_1信息体只包含信息对象地址3字节和品质描述符1字节总共4字节。如果模拟器没有按类型标识区分处理盲目套用统一格式主站侧收到的数据大概率解析不了。品质描述符Quality Descriptor也值得注意。第三位是“当前值”标志第四位是“替代值”标志第五位是“溢出”标志这些标志如果配置不当可能让主站把正常数据当成无效数据丢弃。模拟器最好能允许手工控制这些标志位方便测试主站对数据品质的处理逻辑。3.3 怎么判断一个模拟器“可用”判断模拟器好不好的最直接办法是拿一个已经确认无误的主站工具做联调测试。如果主站能正常收到全部点位数据遥控流程能完整走通并且长时间运行不产生非法帧那基本就能判定模拟器是“亲测可用”的了。另外可以关注模拟器的扩展能力。比如是否支持脚本自定义报文是否支持按条件自动改变数据值是否支持多客户端连接。这些扩展能力决定了模拟器是只能做基础联调还是能做深度故障模拟测试。我现在的习惯是拿到一个新的模拟器先做三件套验证。第一步用协议分析仪表抓包确认帧格式正确第二步用成熟主站工具或者之前项目里验证过的解析库接收数据确认报文可解析第三步连续运行24小时观察是否有内存泄漏、连接中断、序号错乱等问题。三步都过了我才敢把模拟器用到正式项目里去。4. 实操搭建并跑通一个IEC104模拟器4.1 环境和部署我用的是Python环境下的一套开源IEC104框架配合自己封装的上层业务逻辑整体部署非常简单一台普通笔记本就能跑起来不需要特殊硬件。前提是你电脑上得有Python 3.8以上的环境最好再装一个好用的IDE比如VS Code或者PyCharm。搭建步骤大概是这样python -m venv iec104_env source iec104_env/bin/activate # Windows下执行 iec104_env\Scripts\activate pip install iec104-python装好后写一个基础服务端脚本监听2404端口等待主站连接。核心代码片段如下from lib60870 import * def main(): server Server() # 配置连接参数 server.set_connection_timeout(10) server.set_send_timeout(15) server.set_acknowledge_timeout(10) # 绑定信息体处理回调 server.set_connection_request_handler(connection_handler) server.set_asdu_received_handler(asdu_handler) server.start() while True: time.sleep(1) if __name__ __main__: main()这里我用了lib60870的开源库它封装了IEC104的链路层核心逻辑包括连接状态机、序号管理、定时器处理等。直接对接业务回调函数就能在不动底层协议的前提下完成模拟器的业务逻辑控制。4.2 配置要点和测试流程模拟器启动后重点配置的是公共地址和信息体地址。公共地址Common Address是主站和子站之间约定的站址标识信息体地址IOA是具体点位地址通常按间隔区分。比如间隔1的遥信从1025开始遥测从2049开始间隔2的遥信从3073开始依次类推。我在配置点位时习惯用一个CSV文件导入后批量生成数据点点号,类型,地址,初值 1,单点遥信,1025,0 2,单点遥信,1026,1 3,短浮点遥测,2049,220.5 4,短浮点遥测,2050,100.2 5,双点遥控,4097,0 6,单点遥控,4098,0配置好后启动模拟器用主站侧发起连接。整个联调流程一般是这样的主站发起TCP连接模拟器接受连接后主站发送U帧的STARTDT激活指令模拟器回STARTDT确认连接就进入数据传输状态。在这个状态下主站发出总召唤命令C_IC_NA_1类型100模拟器收到后先回一个总召唤确认帧然后把所有点位数据按顺序发送一遍最后发送一个总召唤结束帧。主站侧收到结束帧后就知道数据已经全部上送完毕。这里有一个细节要特别强调总召唤的流程必须是“确认-数据-结束”三步顺序不能乱也不能少。我见过有些模拟器只回了确认帧数据也发了但忘了发结束帧结果主站侧一直显示“总召唤进行中”数据刷新不正常。排查了好久才发现是这个原因。4.3 用主站侧验证数据模拟器是否完全正常最终得靠主站侧来验证。我常用的方法是用另一台电脑装一个IEC104主站客户端连接模拟器地址然后比对点位数据。验证的维度有这么几个数据数量是否对得上。主站侧收到的遥信、遥测点数是否和模拟器配置的点数一致有无缺失、重复或地址错乱。数值是否正确。模拟器设置的初始值是否正确传到主站画面小数点位数是否符合预期品质描述符是否正常。遥控流程是否完整。在主站侧手动触发一个遥控命令观察模拟器是否依次返回“选择确认”“执行确认”“结束”等帧时序是否合规。时标是否准确。带时标的报文主站侧显示的SOE时间是否和模拟器设置的时间一致。这里要注意时区问题CP56Time2a时标默认是本地时间如果模拟器和主站不在同一时区时间会差出好几个小时看着就是“对不齐”。5. 常见问题与排查技巧实录5.1 连接建立后又立刻断开这是最常见的问题之一。现象是主站连接模拟器的2404端口TCP能建连但马上就被断开或者无法进入数据传输状态。排查顺序建议这样来抓包看有没有收到STARTDT激活帧。如果主站根本没发STARTDT激活那可能是主站侧配置的规约参数不对或者主站还没有进入“启动”流程。如果收到了激活帧但模拟器没回确认检查模拟器的连接回调逻辑是否处理了STARTDT帧有没有正确调用了应答API。如果激活确认已发送但仍然断开检查t1超时参数。如果主站的t2参数比模拟器的t1参数还大就可能出现主站还没发送确认模拟器已经判定超时而断开了。我遇到过一次比较隐蔽的情况模拟器是多线程跑的连接线程和数据处理线程共用同一个收发缓冲导致并发冲突报文发出去了但序号是错的主站一校验序号不连续直接判定链路故障断开。这种问题用抓包工具看单条报文看不出毛病必须看序号连续性才能发现。5.2 总召唤数据不完整有时候主站发起总召唤模拟器响应了但数据总是少一部分。这个时候要重点检查VSQ可变结构限定词字段的设置。VSQ的最高位表示是否连续寻址低位表示信息体数目。如果模拟器把连续寻址标志置为1但实际发送的信息体地址不连续主站按连续地址解析数据就会错位或者丢弃。正确的做法是如果点位地址是连续的可以启用连续寻址一条ASDU装多个信息体效率更高如果点位地址不连续必须把连续寻址标志置为0每个信息体都带完整地址。这个细节看似简单但确实会让很多人卡住尤其是从别的规约转过来的调试人员容易习惯性地用分组方式处理。5.3 遥控流程总是报错遥控命令调试出错主要看几个方面先看遥控选择命令Select的返回。主站发C_SC_NA_1选择命令模拟器回C_SC_NA_1确认然后主站发执行命令模拟器再回C_SC_NA_1确认最后还要回一个结束帧说明执行结果。如果模拟器只回了一次确认没有回结束帧主站侧就会显示“命令执行超时”。我建议模拟器在处理遥控命令时把选择、执行、结束三个阶段分开打日志每收到一个阶段帧就打印一条记录这样排查主站下发异常时非常高效。另外注意遥控命令的传送原因COT是有讲究的。选择命令的COT通常是6激活确认帧的COT是7激活确认。如果模拟器把确认帧的COT写成了其他值主站会认为这个确认帧不是针对遥控命令的响应直接忽略掉那整个遥控流程就断了。5.4 时标错乱和数据品质被置为无效时标错乱绝大多数原因是CP56Time2a字段的时区或者毫秒值解析错误。我曾经debug过一个案例模拟器在生成时标时直接把毫秒值按十六进制写入而协议里毫秒值是二进制编码结果主站侧显示的时间秒数差了半分钟。这个坑用肉眼在十六进制报文里完全看不出来必须对照协议文档逐位解析。数据品质被置为无效则多半是品质描述符Quality的低两位被写成了非0值。IEC104中品质描述符的低两位表示有效性默认0是“有效”1是“无效”2是“替代值”3是“故障值”。模拟器在初始化遥测点时如果没显式把品质清0可能会继承内存中的随机值导致主站侧收到大量无效数据。所以模拟器代码里一定要显式设置每个数据点的品质字段。写在最后的一点心得这些东西看着都不难但实际跑起来小毛病特别多。我最初在项目里用模拟器的时候光总召唤结束帧就踩过好几次坑主站侧数据总是不刷新最后抓包才发现是对端没返回结束帧。后来我就养成了一个习惯不管用哪个模拟器第一个测试用例永远是“总召唤三帧流程”。确认帧、数据帧、结束帧一个不能少顺序坚决不能乱。第二件事就是抓包工具一定要备好不要嫌麻烦。IEC104联调遇到问题百分之九十都能靠抓包定位。模拟器报文的十六进制看多了你对协议帧结构的敏感度也会提升这对做电力自动化调试的人来说特别重要。希望这篇内容能帮到你下次用模拟器调试的时候能少走一点弯路早点下班。本文还有配套的精品资源点击获取
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻