Vijeo Citect 7.2 遗留系统数据解耦与采集方案
施耐德电气消防系统数据读取技术方案,基于 Cicode 异步文件桥接(File Bridge)的技术实施白皮书
文档版本:V2.0 (Final)
最后更新:2026-01-05
适用环境:Schneider Vijeo Citect 7.2 / Windows Server
关键词:Cicode, Data Logging, JSON, NodeJS, Legacy System Integration
1. 项目背景与设计思路 (Background & Concept)
1.1 背景与现状 (The Context)
现场运行着一套基于 Vijeo Citect 7.2 的施耐德隧道消防监测系统。通过 citect explore 可知,系统底层通过 variable.dbf 定义了大量 Tag 变量,并归属于 Cluster1 集群。
- 当前痛点:系统是一个封闭的 SCADA 环境。虽然界面(Panel 1 & Panel 2)能够显示 CO2、CH4 等气体的实时读数,但外部的 Node.js 上报服务 无法直接获取这些模拟量(Analog)数据,只能抓取文本报警日志。
- 业务需求:以 5秒/次 的频率,获取界面上红框区域的 10 个气体读数及设备在线状态,并上报至云端。
1.2 核心设计思路 (Design Philosophy)
面对老旧工业软件,采用了 “非侵入式文件桥接” 方案。
我们不尝试破解 Citect 的内存或使用不稳定的 DCOM 接口,而是利用 Citect 自身的脚本引擎,将“内存数据”周期性地固化为 “磁盘文件”。
设计逻辑链:
- 定位:在
variable.dbf中找到数据源头,定位面板展示tag含义。 - 提取:编写 Cicode 脚本从内存“捞取”数据。
- 调度:利用 Event(事件)机制进行周期性触发。
- 执行:关键一步,指定 IO Server 进程负责运行该调度。
- 消费:外部 Node.js 服务只读文件,不碰系统核心。
2. 软件架构解析 (Software Architecture)
本方案在逻辑上分为三层:数据源层 (Citect) -> 中转层 (File System) -> 应用层 (Node.js)。

- Cluster1 的作用:它是 Citect 系统的数据命名空间。我们在
variable.dbf中确认了所有气体变量都属于Cluster1,因此后续所有的 Event 和 Server 配置都必须挂载在Cluster1下,否则找不到变量。
3. 详细实施路线 (Implementation Roadmap)
3.1 变量映射 (Tag Mapping)
通过解析工程根目录下的 variable.dbf,确定了界面数值对应的底层变量名。

- 数据归属:Cluster:
Cluster1/ Type:REAL(浮点型)/ ana:analog(实时读数) - 变量清单:
| 监测项 | FCP Panel 1 变量 | FCP Panel 2 变量 | 备注 |
|---|---|---|---|
| CO2 | GAS_1_ch1_ana |
GAS_2_ch1_ana |
模拟量 |
| CH4 | GAS_1_ch2_ana |
GAS_2_ch2_ana |
模拟量 |
| CO | GAS_1_ch3_ana |
GAS_2_ch3_ana |
模拟量 |
| H2S | GAS_1_ch4_ana |
GAS_2_ch4_ana |
模拟量 |
| O2 | GAS_1_ch5_ana |
GAS_2_ch5_ana |
模拟量 |
| 状态 | IODeviceInfo |
IODeviceInfo |
在线检测 |
3.2 脚本开发 (Cicode Development)
前置操作:在 Windows C 盘根目录下手动新建文件夹 C:\CitectData。(Cicode 无法自动创建文件夹,若无此步,后续操作无效)。
完整代码 (ExportGasToText.ci):
/* * 函数名: ExportGasToText
* 作用: 读取 Cluster1 中的气体变量,封装为 JSON 写入磁盘
* 注意: 需要在 Computer Setup 中赋予 Server 运行权限
*/
FUNCTION ExportGasToText()
INT hFile;
STRING sPath;
STRING sStatus1;
STRING sStatus2;
// 1. 指定输出路径 (文件夹必须预先存在)
sPath = "C:\CitectData\GasRealtime.json";
// 2. 检查设备在线状态 (3 = 状态模式, 返回 "1" 代表在线)
IF IODeviceInfo("GAS_1", 3) = "1" THEN sStatus1 = "true"; ELSE sStatus1 = "false"; END
IF IODeviceInfo("GAS_2", 3) = "1" THEN sStatus2 = "true"; ELSE sStatus2 = "false"; END
// 3. 打开文件 ('w' = 覆盖模式,确保文件不无限增长)
hFile = FileOpen(sPath, "w");
IF hFile <> -1 THEN
// 4. 构建 JSON 字符串
FileWrite(hFile, "{");
// --- Panel 1 ---
FileWrite(hFile, " ^"FCP1^": {");
FileWrite(hFile, " ^"Online^": " + sStatus1 + ",");
FileWrite(hFile, " ^"CO2^": " + RealToStr(GAS_1_ch1_ana, 6, 2) + ",");
FileWrite(hFile, " ^"CH4^": " + RealToStr(GAS_1_ch2_ana, 6, 2) + ",");
FileWrite(hFile, " ^"CO^": " + RealToStr(GAS_1_ch3_ana, 6, 2) + ",");
FileWrite(hFile, " ^"H2S^": " + RealToStr(GAS_1_ch4_ana, 6, 2) + ",");
FileWrite(hFile, " ^"O2^": " + RealToStr(GAS_1_ch5_ana, 6, 2));
FileWrite(hFile, " },");
// --- Panel 2 ---
FileWrite(hFile, " ^"FCP2^": {");
FileWrite(hFile, " ^"Online^": " + sStatus2 + ",");
FileWrite(hFile, " ^"CO2^": " + RealToStr(GAS_2_ch1_ana, 6, 2) + ",");
FileWrite(hFile, " ^"CH4^": " + RealToStr(GAS_2_ch2_ana, 6, 2) + ",");
FileWrite(hFile, " ^"CO^": " + RealToStr(GAS_2_ch3_ana, 6, 2) + ",");
FileWrite(hFile, " ^"H2S^": " + RealToStr(GAS_2_ch4_ana, 6, 2) + ",");
FileWrite(hFile, " ^"O2^": " + RealToStr(GAS_2_ch5_ana, 6, 2));
FileWrite(hFile, " }");
FileWrite(hFile, "}");
FileClose(hFile);
ELSE
// 错误处理: 无法打开文件
TraceMsg("Error: Cannot write to gas data file. Check Folder Path.");
END
END
3.3 任务调度配置 (Events Configuration)
在 Project Editor -> System -> Events 中配置定时器。

- Name:
ExportGasToText - Cluster Name:
Cluster1(此处必须填Cluster1,因为变量都在此集群下。若留空,脚本找不到变量会报错)。 - Time: (留空)
- Period:
00:00:05(5秒周期) - Action:
ExportGasToText()
3.4 进程执行分配 (Computer Setup) —— [至关重要]
逻辑说明:
配置了 Event 只是在数据库里写了一条“规则”,必须指派具体的 Windows 进程(Server)去执行这条规则,否则 Event 永远不会启动。
很多 Citect 开发者的脚本不生效,90% 都是死在这一步:默认情况下,新建的 Event 没有人认领。
操作步骤:
- 运行 Computer Setup Wizard -> Custom Setup。
- 一路 Next 直到 Events Setup 页面。
- Client (客户端):
- ❌ 取消勾选
ExportGasToText。 - 原因:客户端负责显示画面,不应负责后台写文件,避免多台客户端同时写入导致文件锁死。

- Cluster1.IOServer (IO服务器):
- ✅ 必须勾选
ExportGasToText。 - 原因:IO Server 是系统的核心数据引擎,负责处理 Tag 数据,由它来执行写文件最高效、最稳定。
- User Privileges:
- 选择
Default Server User。确保 IO Server 进程有权限在这个电脑上新建和写入文件。
4. 调试与验证 (Validation & Debugging)
完成上述配置后,必须先编译(Compile),然后完全重启 Runtime(不仅是刷新,要关掉重开)。
4.1 验证步骤
- 方法一:黑盒测试(观察结果)
- 直接打开
C:\CitectData\文件夹。 - 观察
GasRealtime.json的 “修改日期”。 - 预期结果:时间戳每 5 秒跳动一次。
- 方法二:白盒测试(逻辑验证)
- 如果文件未自动生成,在 Citect Graphic 画图编辑器中,打开
Startup_Small页面。 - 画一个按钮,Input 设置为
ExportGasToText()。 - 运行并点击按钮。
- 结果分析:
- 若点击按钮生成了文件,但自动运行不生成 -> 说明代码没问题,步骤 3.4 配置有误。
- 若点击按钮也不生成文件 -> 说明 步骤 3.2 代码路径错误 或文件夹不存在。
5. 总结 (Conclusion)
本方案通过标准化的 Citect 开发流程,解决了遗留系统数据封闭的问题。
- 安全性:使用
Cluster1.IOServer单进程写入,避免了文件冲突。 - 可靠性:引入了
IODeviceInfo在线判断,防止断线后上传脏数据。 - 扩展性:基于 JSON 格式,Node.js 端解析灵活,未来增加变量只需修改 Cicode 即可。