hero-image

New Version: Current Monitor v1.1.0


Current Monitor 发布了 v1.1.0。这个版本的改动集中在一件事上:让 GDDAQ 联动不再依赖”数据有没有被写到磁盘”。为此新增了一整套进程内存读取方式——由一个 root 辅助进程每秒从 GDDAQ 进程里直接读出运行状态、轮次号与数据目录;围绕这条新数据源,轮次跟随、文件落点、断线恢复和手动接管的语义也都重新梳理了一遍。

Current Monitor 是配合”創鴻 DM4D-An-Rs”高精度盘面表的双通道电流实时监控软件:Modbus RTU 读取、电荷积分、双轴绘图、CSV 记录。v1.1.0 于 2026 年 9 月 23 日发布,9 月 24 日补充了 GDDAQ 版本选择项。

v1.1 带来了什么

v1.0.0v1.1.0
GDDAQ 状态来源仅 run.logrun.log + 进程内存(root 辅助进程)
同轮次重启识别依赖数据文件更新,延迟约一个写盘周期内存方式无需等写盘,仍有 1 s 轮询间隔
轮次选择日志方式取最大编号,另需手动填 Run Number全自动,手动 Run Number 项已移除
电流数据位置数据目录下的 CurrentData/数据目录上一级的 CurrentData/run_XXXXX.csv
轮次切换需先停再启轮次号或目录变化时自动切换到新 CSV
断线判定进程消失即停止连续 3 秒无有效状态才停止;恢复后自动续记
GDDAQ 版本无新增 GDDAQ Version(GDDAQ-CAEN (20260709))
手动接管直接操作即可需确认后才退出联动
代码规模3,738 行4,959 行

采集内核(Modbus 帧校验、电荷积分、过滤、绘图)在本版保持不变,改动几乎全部落在联动层。

为什么光靠 run.log 不够

run.log 方式的问题不在解析,而在时序:它只能看到已经落盘的东西。

  • GDDAQ 在同一轮次文件夹里重新开始取数时,往往不会再写一行 Start:。程序只能退而求其次,用”数据文件比 run.log 更新”来推断重启。
  • 这个推断要等一次数据写盘,识别天然滞后一个写盘周期。
  • 如果某段取数很短,还没来得及产生可识别的文件更新,这一段就整段漏记——对以 mC 计量的电荷数据来说,漏记比误记更难事后补救。

内存方式的思路很直接:GDDAQ 自己一定知道”现在在不在取数、是第几轮、存到哪个目录”,那就去问它本人,不绕道磁盘。

内存检测:怎么从别人的进程里读出状态

启用 Process Memory (root) 后,程序会拉起一个辅助进程,每秒读一次 GDDAQ 的内存,把结果原子写成一个 JSON 状态文件,主界面只负责读这个文件。

几个值得说明的设计取舍:

辅助进程就是本程序自身的一个 root 副本。 命令形如 sudo <本程序> --gddaq-mem-helper -o <状态文件> --stop-file <标志文件> -i 1 --gddaq-version ...。这个副本在导入 PyQt5 / numpy 之前就进入了纯标准库的守护循环,好处有三个:root 下运行的代码面最小(最小提权原则);打包后的可执行程序自带解释器,目标机器不需要装 python3;也不需要额外附带任何外部脚本。代价是 onefile 打包时 root 副本要先自解压,首次启动会多花几秒。

只读内存,不 attach。 打开 /proc/<pid>/mem 以 O_RDONLY 读取,不使用 ptrace,因此不会暂停 GDDAQ——取数期间读状态,不会给束流实验塞进一次莫名的停顿。

先找对象,再读字段。 程序优先从目标进程自己的 ELF 符号表里取 vtable 符号地址,在可写内存区(栈、堆、匿名映射)中定位 MainWindow 实例,然后按偏移读出 QString 形式的目录、前缀与轮次号;偏移漂移时还有一层启发式兜底,扫描失败会带原因写进状态文件,同一错误去重,不刷屏。

密码与权限。 sudo 密码只经 sudo -S 的 stdin 传给子进程,不写日志、不保存,用完即释放引用;认证失败允许重试,最多 3 次;取消勾选时先删停止标志让辅助进程自行退出,卡死才用信号兜底。

轮次跟随与数据落点

手动填 Run Number 这一项被彻底移除了。现在轮次是自动跟随的:run.log 方式取编号最大的子文件夹,内存方式直接跟随 GDDAQ 的实际运行号。

电流数据统一追加到数据目录上一级的 CurrentData/ 里:

/home/rnb/Data/202605ams/
├── raw/                         ← Data Directory
│   └── 0048/
│       └── run.log
└── CurrentData/
    └── run_00048.csv             ← 电流数据

旧版日志方式写在 raw/CurrentData/ 里的文件不会自动搬迁或合并,需要的话请手动处理。

轮次号或数据根目录一旦变化,程序会先关掉旧 CSV、再打开新 CSV;日志方式如果发现新轮次还没有有效的 Start:,会停止旧记录并等待。两种方式都采用追加语义,与 DAQ_Master 的行为一致。

由此引出一条使用建议:每轮取数尽量用新的编号。复用同一编号会把多段电流数据追加进同一个 CSV,事后对应数据的成本远高于改一个编号。

断线与恢复的边界

联动最怕两种情况:该停的时候没停,以及不该停的时候停了。v1.1.0 把边界写清楚了:

情况行为
确认 GDDAQ 已退出停止联动记录,状态栏红色提示;辅助进程仍在时可自动继续跟随
暂时读不到有效状态短暂失败期间继续记录;连续 3 秒无有效状态后,在下一次轮询停止并报警
有效状态恢复以追加方式自动恢复记录
辅助进程退出停止记录并提示 memory helper exited,需取消再重新勾选(不反复索取密码)

这里有个容易被耍花招的细节:重复读到同一份旧状态、或持续收到错误状态,都不会延长这 3 秒等待期。否则一个卡在旧快照上的辅助进程,能让”已经停止的取数”永远看起来还在跑。

日志方式的重启检测也补上了警示:当程序通过”数据文件更新”识别出同轮次重启时,会提示可能存在漏记的短段,并记一条 WARNING。

手动接管

联动期间启停由外部程序控制,但人始终可以接管:手动启动前会请求确认退出联动;手动停止时,如果外部 DAQ 仍在取数,同样会请求确认。确认后程序退出联动模式,取消则保持原状。联动本身仍然只能停止它自己启动的运行,手动跑起来的记录不会被外部信号误杀——这条语义从 v1.0.0 延续下来。

GDDAQ 版本:一句实话

内存读取依赖 GDDAQ 二进制内部的对象布局,所以新增了 GDDAQ Version。目前适配目标是 GDDAQ-CAEN (20260709),其偏移来自对这一版二进制的实测。这个选项只在内存方式、且联动未开启时可改(避免运行中换版本导致读到错位的字段),选择在当前会话内保留。

必须说明的是:同一版本重新编译,内部布局也可能变化,版本名相同不代表一定兼容。若日志里出现内存读取异常,先在源码目录用诊断命令确认偏移是否还成立,再决定要不要用这一模式。

升级与兼容性

  • 运行依赖不变(numpy / matplotlib / PyQt5 / pyserial),Windows 7 兼容版本的依赖钉不变。
  • 内存方式需要监控机上 sudo 可用;日志方式依旧零额外权限,是默认选项。
  • 打包流程照旧可用。内存辅助进程是程序自身的 root 副本,onefile 模式下首轮状态文件约需 2–5 秒就绪,程序最长等待 8 秒。
  • /tmp/daq_status.txt 的对接契约完全不变,DAQ_Master 侧零改动。
  • 平台支持仍是 Linux(≥ glibc 2.17)与 Windows(≥ 7);GDDAQ 联动仅限 Linux。

获取与参与

Releases 页提供 Linux x86-64 单文件可执行程序,兼容 CentOS 7、Ubuntu 18+ 等主流发行版。

本文由AI生成。