1. 从 CODESYS 到数据落库:RealPLC Agent 到底解决了什么问题
搞工控的应该都有过这种时刻:现场一台汇川 PLC 跑得好好的,程序里几十上百个变量,客户突然说要记录温度、压力、电机启停状态,还得按小时汇总存数据库。这时候你打开 CODESYS,翻出各种通信库、Modbus 映射表、OPC UA 配置,一圈折腾下来半天没了,变量一改还得重新对地址。RealPLC Agent 这个工具解决的恰恰就是这段最枯燥的衔接工作——把 CODESYS 工程里的变量结构直接吃进来,自动生成采集配置,让数据从 PLC 变量表一路顺到 MySQL 表里。
这篇内容适合三类人看:第一类是刚接触 CODESYS 的电气工程师,手上的项目用的是汇川或者类似支持 CODESYS 平台的控制器,想把运行数据存起来但不知道从哪下手;第二类是做过组态或 SCADA、现在想换成更轻量采集方案的老手,需要一份能直接抄的配置清单;第三类是自动化集成商的技术负责人,评估这个方案能不能嵌进自己的交付流程里。整篇不讲空泛概念,重点放在 CODESYS 侧的符号配置怎么摆、库文件怎么生成、RealPLC Agent 怎么读变量、数据怎么进 MySQL,以及那些文档里不会写、只有踩过才明白的细节。
我先把这个方案的边界说清楚,免得你照着做却发现方向不对。RealPLC Agent 不是替代 CODESYS 编程的,它不参与逻辑控制,只负责采集和转发。你的 PLC 逻辑该在 CODESYS 里写还在 CODESYS 里写,Agent 只是站在旁边“旁听”变量值。它读取变量的方式依赖 CODESYS 暴露出来的符号信息,所以符号配置这一步是整个链路的地基。地基建歪了,后面怎么调都是白费。
从数据流的角度看,整条链路是这样的:CODESYS 里定义全局变量并生成符号信息,RealPLC Agent 通过通信协议(常见是 Modbus TCP、ADS 或 OPC UA,具体看你的 PLC 支持哪个)拿到变量值,然后按配置写入 MySQL。中间任何一个环节的命名、类型、地址对不上,都会卡住。热词里出现的“plc-recorder 读取 codesys 变量”“mysql 的 alongwu 第三方库”这些,其实都是同一条链路的不同环节标签,从业者在搜索这些词的时候,真实诉求基本都是“我想让变量值稳定落库,但某一步卡住了”。
这个方案的典型优势有三点。部署成本低,不需要上一整套 SCADA 组态软件,一台工控机或者树莓派级别的设备就能跑。配置可读性强,采集点用变量名而不是裸地址来表达,维护的时候看得懂。改动响应快,PLC 侧加了变量,只需要更新符号配置再同步一次,不用大动干戈重新画通信映射表。这三点决定了它在中小规模数据采集场景里比传统方案更省事,尤其是那种几十到几百个采集点、需要按时入库但不要求毫秒级实时性的项目。
2. 核心原理拆解:符号配置、变量寻址与数据通道
2.1 CODESYS 符号配置为什么是整条链路的起点
CODESYS 的变量在程序里是以符号名存在的,比如GVL_Tank.fTemperature,但在通信层面上,PLC 只认地址。要让外部工具按符号名取值,就必须有一份“符号到地址”的映射,这份映射就是符号配置的产物。你可以把它理解成一本电话簿:Agent 想找“张三”,电话簿告诉它“张三的号码是 4001”,于是它拨 4001。没有这本簿子,Agent 只能挨个号码问“你是谁”,效率低到没法用。
CODESYS 生成符号信息一般走两个途径。一个是在工程里启用符号配置(Symbol Configuration),勾选需要对外暴露的变量,然后编译生成.xml或类似格式的符号描述文件。另一个是通过 OPC UA 服务器功能直接对外发布变量节点,Agent 连上后遍历节点树。两条路各有取舍,前者适合变量固定、结构清晰的场景,后者适合变量会动态增减、希望自动发现的场景。汇川 PLC 的 CODESYS 工程两种都支持,但实测下来,中小企业项目里符号配置那条路更稳,因为它不依赖 PLC 侧的 OPC UA 授权和额外资源占用。
这里有个非常关键的坑:符号配置里能勾的变量,必须是在“全局变量列表”(GVL)里定义的,局部变量(比如函数块内部的VAR)默认不会出现在符号配置的可选清单里。我见过不少人把采集点写在某个功能块内部,然后纳闷为什么符号配置里找不到——不是工具的问题,是变量作用域的问题。解决办法很简单,把需要采集的变量统一挪到 GVL 里,或者通过功能块的输出引脚引出到全局变量。
2.2 变量类型与字节对齐的隐藏影响
符号配置里每个变量都带着数据类型和偏移地址,数据类型决定了占多少字节,偏移地址决定了从哪个位置开始读。听起来很直白,但字节对齐这件事会咬人。CODESYS 在排布变量时,为了访问效率会对某些类型做对齐处理,比如一个BOOL后面跟一个REAL,REAL可能会从 4 字节边界开始,导致中间空出几个字节。如果你的 Agent 侧是按“连续读取 N 个字节然后按顺序解析”的粗暴逻辑,这些空隙就会被当成变量值读错。
正确的做法是让 Agent 严格按照符号配置里给出的偏移和长度逐个取值,而不是自己算连续区间。RealPLC Agent 在实际使用中就是按符号表逐项寻址的,这样即使有空隙也不影响。但如果你用的是自己写的脚本去读,就一定要解析符号文件里的偏移字段,别偷懒用累加。我一般会在符号配置生成后,用记事本打开看一眼,确认Offset和Size字段和预期一致,尤其注意BOOL密集排布的区域。
另一个常见类型是字符串。CODESYS 里STRING默认长度是 80 字节,WSTRING是 160 字节,而且末尾有固定的结束符。采集字符串类型变量时,字节数算错就会把后面的变量值一起吃进来。如果只是采集数值类变量,建议干脆不要暴露字符串,省得给自己找麻烦。真要采字符串,就在 CODESYS 侧先处理好,比如截断到固定长度或者转成数值编码。
2.3 通信方式的选型逻辑
从 PLC 到 Agent 这一段,可选的方式主要有三种:Modbus TCP、OPC UA、以及厂商私有的 ADS 类协议。选哪个不是拍脑袋,要看你手上 PLC 的具体型号和授权情况。
| 通信方式 | 适用场景 | 优点 | 局限 |
|---|---|---|---|
| Modbus TCP | 变量已映射到保持寄存器 | 通用性强,几乎所有 PLC 支持 | 需要手工维护寄存器地址映射,变量名丢失 |
| OPC UA | 变量需按名访问,结构较复杂 | 保留符号名,支持类型信息 | PLC 侧需支持并开启,资源占用相对高 |
| 私有 ADS | 同品牌生态内 | 读取效率高,支持符号寻址 | 跨品牌兼容性差 |
RealPLC Agent 对这三种都有对应的连接配置,实际选型时我的建议是:如果 PLC 本身支持 OPC UA 或者有配套的符号寻址通道,优先用它,因为符号名能一直保留到入库,出问题好排查。如果只能用 Modbus TCP,那就要在 CODESYS 侧多花功夫做寄存器映射,把变量地址整理成一张对照表,后期维护成本会明显上升。汇川 PLC 在很多型号上对符号寻址支持得不错,这也是热词里“汇川 plc codesys”频繁出现的原因——大家用这个组合,恰好是因为它在这条链路上比较顺。
2.4 数据落库:MySQL 表结构与写入节奏
数据进了 Agent 之后,最终要落到 MySQL。这里的核心设计点是表结构怎么定、写入频率怎么控。表结构我一般分两种思路:宽表模式和窄表模式。
宽表模式是一行对应一个采样时刻,每个变量占一列,比如ts, temp1, press1, motor_status...。优点是查询直观,一个时间段的数据一条 SQL 就出来了。缺点是变量增减要改表结构,采集点多了列数爆炸。窄表模式是一行对应一个“时刻 + 变量名 + 值”,优点是变量增减不用动表结构,灵活。缺点是查询和聚合要写得更绕,单点数据量大时行数膨胀得快。
对于采集点相对固定、数量在几十个以内的项目,我倾向宽表,简单直接。对于采集点会持续增加、或者变量来自多个设备的情况,窄表更合适。RealPLC Agent 的写入配置里通常允许你指定表名和字段映射,具体用哪种模式由你在 MySQL 侧建表时决定,Agent 只负责按映射写数据。
写入节奏上也要控制。别让 Agent 每个 PLC 扫描周期都往数据库写一次,那样数据库很快就被冲垮。合理的做法是按时间间隔批量写入,比如 1 秒或 5 秒一批,或者按变化触发写入——只有值变了才落库。变化触发能大幅减少无效数据量,但对“值长时间不变但需要证明设备在线”的场景不友好,这时候可以加一条心跳记录,每隔固定时间写一行时间戳。
3. 手把手实操:从零打通采集链路
3.1 CODESYS 侧的准备工作
第一步是在 CODESYS 工程里把要采集的变量集中到全局变量列表。新建一个 GVL,命名要有规律,比如GVL_Data,然后把你关心的变量都放进去。命名我强烈建议用英文加下划线,别用中文或者拼音缩写,因为后面 Agent 侧、数据库字段都会引用这个名,中文在跨系统传递时容易出编码问题。变量名要表达含义,temp1这种就不如Tank1_Temperature清晰。
第二步是打开符号配置。在工程树里找到 Symbol Configuration 对象,双击进入,勾选刚才那个 GVL,然后勾选需要对外暴露的具体变量。这里有一个细节:如果你希望 Agent 能读到变量的类型信息,要把“支持 OPC UA”或对应选项打开,这样生成的符号描述里会带类型元数据。全部勾好后编译工程,符号文件会跟着生成,路径一般在工程目录下的某个子文件夹里,文件名类似Symbols.xml。
第三步是确认 PLC 侧的通信端口已经开放。如果是 Modbus TCP,CODESYS 里要添加 Modbus TCP Slave 设备并配置寄存器映射;如果是 OPC UA,要在 PLC 设置里启用服务器并设置端口。这一步经常被忽略,结果是 Agent 那边连接一直超时。我的习惯是配置完先用一个通用的调试工具连一下,确认端口通、有响应,再去配 Agent,这样能把问题域缩小到一半。
3.2 生成库文件与符号描述的处理
热词里“codesys 如何生成库文件”问的人不少,这里要分清楚:库文件(Library)和符号描述文件是两回事。库文件是给 CODESYS 工程编译用的.library文件,里面封装的是功能块和函数;符号描述文件是给外部工具读变量用的结构化描述。RealPLC Agent 需要的是后者,不是前者。有些人把“生成库文件”理解成要给 Agent 生成一个专用库,这是误解。
如果你确实需要生成 CODESYS 库文件(比如想把某段逻辑封装复用到多个工程),流程是:新建一个 Library 类型的工程,把功能块写好,然后在工程属性里设置版本号和命名空间,最后编译输出.library。这个库给自己的工程用,和 Agent 采集没有直接关系,别把它当成采集链路的必要步骤。Agent 要的是符号配置编译后产出的那个 XML 或类似结构,路径找对就行。
拿到符号描述文件后,可以直接用文本编辑器打开检查。里面每个变量应该能看到名字、数据类型、偏移、大小这几项。我一般会拿它和 Excel 里的采集点清单对一遍,确认没有遗漏、没有多余的变量。这个对照动作花不了几分钟,但能省掉后面调试时的大量猜谜时间。
3.3 RealPLC Agent 的连接配置
Agent 侧的配置一般分三块:连接参数、变量映射、数据输出。连接参数这块,你要填 PLC 的 IP、端口、协议类型,以及超时和重试次数。超时别设太短,工业现场网络抖动是常态,设个 3 到 5 秒比较合适,重试 2 到 3 次。协议类型要和 PLC 侧开放的方式一致,选错了连不上。
变量映射这块,Agent 通常支持导入符号描述文件自动生成映射,或者你手工填变量名和对应地址。有自动导入就用自动导入,省事且不易错。导入后逐项核对变量名和数据类型,重点检查BOOL、REAL、INT这几类最常用的类型有没有映射对。如果发现某个变量类型显示为未知,多半是符号描述里缺类型信息,回 CODESYS 侧把对应选项打开重新编译。
数据输出这块,填 MySQL 的连接信息、目标表名、字段映射关系。字段名和变量名的对应关系建议保持一定规则,比如变量Tank1_Temperature对应字段tank1_temperature,全小写加下划线,方便写 SQL 时不用加引号。时区也要注意,Agent 和 MySQL 如果时区设置不一致,写进去的时间戳会漂,这个后面问题排查章节细说。
3.4 MySQL 表结构的建立与验证
建表这件事,给出一个宽表模式的参考结构:
CREATE TABLE plc_data ( id BIGINT AUTO_INCREMENT PRIMARY KEY, ts DATETIME(3) NOT NULL, tank1_temperature FLOAT, tank1_pressure FLOAT, motor1_status TINYINT, line_speed FLOAT, INDEX idx_ts (ts) );ts字段用DATETIME(3)保留毫秒精度,因为工业数据对时间顺序比较敏感。给ts加索引是必须的,否则按时间段查询会全表扫描。数值型字段用FLOAT还是DOUBLE看你精度要求,一般FLOAT够用;状态类用TINYINT省空间。
表建好后,先不急着让 Agent 大规模写入。手工插一行测试数据,然后用查询语句确认能查出来、时间字段显示正常。再启动 Agent 小批量采集,观察数据是不是按预期落进来。我会盯着看几分钟的表数据,确认数值没有明显异常(比如温度显示成几万、状态位一直是乱值),这些往往是类型或字节序没对上导致的。确认无误后再放开采集频率。
3.5 从测试到上线的过渡检查
上线前有一套我必做的检查清单。PLC 侧:符号配置的变量和实际采集需求逐条核对,确认没有把调试用的临时变量也勾进去。Agent 侧:连接断开重连是否正常工作,可以手工拔一下网线再插上,看 Agent 能否自动恢复采集。数据库侧:确认存储空间够用,按每天的数据量估算一下能存多久,必要时上分区表或定期清理策略。
还有一个容易漏的点是权限。Agent 用的数据库账号要有目标表的INSERT权限,不要图省事给 root。账号权限最小化是基本习惯,采集账号只给采集表的写权限即可,改数据、删数据的权限都不给。这样即使 Agent 配置出问题,也不会误伤其他数据。
4. 踩坑实录:常见问题与排查技巧
4.1 连接类问题速查
连接不上是最高频的问题,我把常见的几种和排查路径整理成表。
| 现象 | 可能原因 | 排查动作 |
|---|---|---|
| 连接超时 | IP 或端口填错、防火墙拦截 | ping 通 PLC,用调试工具测端口 |
| 连接成功但读不到变量 | 符号描述未导入或变量未勾选 | 检查符号配置,重新编译生成 |
| 读取值全为零 | 地址偏移对不上、字节序错 | 核对符号文件里的偏移字段 |
| 读到的值是乱码 | 类型解析错误、字符串处理不当 | 检查变量类型映射 |
| 间歇性断连 | 网络抖动、PLC 负载高 | 增大超时和重试,检查网络质量 |
有一类问题特别隐蔽:PLC 上电顺序导致的连接失败。如果 Agent 比 PLC 先启动,Agent 初次连接时 PLC 还没就绪,连接直接失败,之后如果 Agent 没有重连逻辑,就一直挂着不动了。解决办法是让 Agent 具备周期性重连能力,或者给 Agent 配置启动延迟,等 PLC 起来再连。这个细节在文档里通常一笔带过,但在无人值守的现场是会出大事的。
4.2 变量读取异常的处理思路
变量读到了但值不对,这一类问题的排查要按“先看类型、再看偏移、最后看字节序”的顺序来。类型问题最常见,比如把REAL当INT解析,读出来就是一个莫名其妙的大整数。偏移问题次之,通常是符号描述和实际 PLC 程序版本不一致导致的——你改了 CODESYS 工程但没重新生成符号文件,Agent 还在用旧映射,偏移自然就错位了。字节序问题相对少,但跨品牌设备时会出现,大端小端没对齐,浮点数读出来就是科学计数法里的怪值。
我处理这类问题的习惯是拿单个变量做“单位测试”。先只配置一个变量,用已知的物理值去验证,比如手动把某个温度变量设成 25.0,看 Agent 读出来是不是 25.0。一个变量通了,再逐步加量。这样能把问题定位到具体变量,而不是在一堆变量里大海捞针。
4.3 数据库写入的典型故障
数据写不进 MySQL,先分清楚是连接问题还是 SQL 问题。连接问题看账号密码、端口、网络;SQL 问题看表名、字段名、数据类型是否匹配。有一个坑是字段名和 MySQL 保留字撞车,比如字段名叫order或者key,不写反引号就会报语法错误。避开这种命名,或者建表时统一用反引号包裹字段名。
时区问题是另一个高频坑。MySQL 默认时区可能是 UTC,而 Agent 写入用的是本地时间,两边差 8 小时,查出来的数据时间全对不上。解决办法是统一时区,要么在 MySQL 连接串里指定时区,要么把服务器和 Agent 都设成同一时区。我一般在 Agent 侧把时间统一转成 UTC 再写,查询时再按需转成本地时间,这样跨时区部署也不会乱。
写入性能方面,如果发现数据库写入延迟越来越高,检查两件事:一是是否每来一个值就单独写一次,改成批量写;二是表上是不是有太多索引拖慢了插入,只保留查询必需的索引。数据量大的项目,可以考虑先写入临时表再定期归档到主表,减少主表的写压力。
4.4 CODESYS 侧改动的同步问题
PLC 程序改动是常态,改了变量之后,符号配置和 Agent 映射都得跟着更新。这里的坑在于“忘了同步”这个动作。我见过不止一次,工程师在 CODESYS 里加了新变量、改了旧变量,但符号文件没重新生成,Agent 那边还是老配置,结果新变量采不到,旧变量采到的是错位的值。所以流程上要定一个规矩:任何涉及采集变量的改动,都必须走“改程序—重新编译符号—更新 Agent 映射—验证数据”这四步,少一步都不行。
如果采集点数量大,手工同步映射很费时,可以考虑把符号描述文件的解析和 Agent 配置生成做成脚本自动化。符号文件本身是结构化的文本,写个脚本按需提取变量名和地址,生成 Agent 的配置文件,变量一多就能体现出价值。这一步属于进阶优化,项目稳定运行后再做也不迟。
4.5 长时间运行的稳定性维护
采集系统跑起来容易,稳定跑几个月不容易。长期运行我关注几个指标:Agent 进程内存占用是否持续增长,数据库表数据量是否超出预期,采集延迟是否逐渐变大。内存持续增长通常是连接句柄或者日志缓存没释放,定期重启能缓解但治标不治本,得看 Agent 是否有对应的日志级别设置,把调试日志关掉能省不少内存。
数据量控制上,设定一个保留策略,比如只保留最近 90 天的明细数据,更早的做聚合归档。聚合表按小时或按天存平均值、最大值、最小值,这样既保留了趋势,又控制了主表规模。这个策略在建表阶段就该想好,别等数据堆到几个 G 才动手,那时清理和迁移都麻烦。
日志这块也值得说一句。Agent 的日志要分级,正常运行只记错误和关键事件,调试时才开详细日志。日志文件要设滚动策略,不然一个日志文件涨到几个 G,排查时打开都卡。我一般按天滚动,保留最近两周,够用又不会占太多空间。
5. 关于这套方案的选型体会与扩展方向
说到选型,我的实际体会是:RealPLC Agent 这类轻量采集工具最适合的场景是采集点规模中等、实时性要求不苛刻、团队没有专职 SCADA 维护人员的项目。如果你的项目要求毫秒级响应、需要复杂的报警联动和画面组态,那还是老老实实上完整的 SCADA 系统,工具和需求要匹配,硬用小马拉大车只会让后期维护痛苦。
汇川 PLC 配合 CODESYS 再用这套方案做采集,在我经手的几个项目里跑得比较顺,核心原因就是符号寻址这条链路打通之后,变量名的可读性一直保留到数据库,出了问题能一路追溯回去。相比之下,纯 Modbus 寄存器映射的方案,一旦变量多了,维护成本会指数上升。
后续如果要把这套东西做得更完善,我会往两个方向扩展。一个是采集侧的自动化同步,把 CODESYS 符号文件的解析和 Agent 配置生成脚本化,变量改动后一键同步。另一个是消费侧的可视化,数据进了 MySQL 之后,用 Grafana 之类的工具直接看图,省去自己写查询页面的功夫。这两步做完,一个中小规模的 PLC 数据采集与展示链路就完整了,投入不大,覆盖面却挺广。数据库类库那些第三方封装(比如热词里提到的 alongwu 那类)可以作为快速接入的辅助,但底层还是建议先理解原生连接和 SQL 写法,依赖封装能提速,理解原理才能排错。