硬件抽象层 (HAL) 与散件模块化演进架构规划
1. 背景与痛点
目前工作站(Edge Collector)强依赖于特定的高度集成色谱主板及其私有协议(GCKC 协议)。该协议存在诸多历史包袱(如 BCD 码编码、单包 96 字节长度限制、事件矩阵双表拆分等),这使得:
- 硬件成本高昂:被单一主板供应商绑定,无法利用市面上性价比更高的通用模块(如 Modbus 温控表、IO 继电器、高精度 ADC 等)。
- 扩展性极差:如果要增加温控通道或外部事件通道,老协议的数据帧根本塞不下,几乎无法平滑升级。
- 开发维护痛苦:大量的代码消耗在复杂的协议拼装与解析中,而不是业务逻辑上。
2. 演进目标
核心战略:在 Go 后端(Collector)中引入硬件抽象层 (HAL)。 将“集成主板”拆解为“通用散件模块”,实现“软件定义硬件”。前端 UI 与核心分析逻辑保持不变,底层根据配置加载不同的硬件驱动。
3. 架构设计 (方案 B:内置驱动架构)
摒弃开发独立协议转换中间件(方案 A)的想法,直接在 Go 后端引擎内部实现设备驱动的解耦,原因在于:
- 避免多级网络跳转,降低延迟,提高数据流稳定性。
- 开发更直接:Go 原生处理并发串口和 TCP/Modbus 能力极强。
3.1 核心抽象接口 (InstrumentDriver)
在 src/edge/internal/hal(计划创建的目录)下定义统一的仪器接口:
3.2 驱动层实现(隔离历史包袱)
核心理念:主程序(Frontend + Backend Core)将彻底消除 Cmd 143、Cmd 128 等概念,所有指令体系仅存在于特定的底层驱动中。
- 老主板驱动 (
driver_gckc_legacy.go):将目前写死在main.go里的Cmd 128、Cmd 143、双表合并逻辑全部剥离到此。这是整个系统中唯一知道 "Cmd" 是什么东西的地方。确保对老设备的完美向后兼容。 - 通用模块化驱动 (
driver_modular.go):当使用散件时启用此驱动。这里完全没有 Cmd 128 或 143 的概念。- 温控:将
SetTemperatures翻译为Modbus RTU Write Multiple Registers (0x10)发送给第三方温控表。 - IO:将
SetEvents翻译为Modbus Write Coil (0x05)发送给继电器模块。 - ADC:从高精度采集卡的独立串口读取微伏/皮安级信号。
- 温控:将
4. 演进实施路线图
Phase 1:解耦准备 (代码重构)
- 在
main.go中剥离硬件协议相关代码。 - 建立
InstrumentDriver接口。 - 将现有的代码平移封装为
LegacyGCKCDriver。 - 验证:确保重构后,连接现有的色谱主板,各项功能(控温、点火、采集)依然正常。
Phase 2:引入首个散件模块 (温控模块试点)
- 采购第三方通用 Modbus 温控模块(如 8 路温控表)。
- 在前端“高级设置”中新增“底层硬件模式”切换开关(A: 原厂主板, B: 散件模块)。
- 编写
ModbusTempDriver。当切换到模式 B 时,温度设定和查询指令直接通过串口发送给温控模块,而其他操作(如事件、点火)暂时仍发给老主板(混合模式),或使用对应的 IO 模块。 - 验证:前端下发 250℃,第三方温控模块成功升温并回传实时温度。
Phase 3:全面模块化与降本
- 逐步替换 IO 模块、EPC 控制模块和信号放大器(ADC 模块)。
- 将各种模块的通信协议集成到
ModularDriver中统一调度。 - 验证:彻底拔掉老色谱主板,整个系统仅靠边缘工控机(Edge Collector)+ USB 转多路 485 HUB + 散件模块 即可完美运行全套色谱分析流程。
5. 预期收益
- 硬件降本:整机 BOM 成本有望断崖式下降。
- 供应链安全:摆脱单一厂商锁定,任何模块坏了都可以用市面上同类标准品替换。
- 产品升维:软件从“定制工具”升级为“通用色谱仪平台底座”,具备赋能其他仪器厂家的潜力。
6. 深入设计:模块化下的关键技术挑战与解决
将“单一高集成主板”拆解为“多厂商散件模块”的过程中,会面临数据同步、配置管理等工程挑战。针对此,HAL 的进阶完善方案如下:
6.1 接口细化与组合模式 (Composition over Inheritance)
不要将所有功能塞进一个庞大的 InstrumentDriver,而是抽象出细粒度的子接口:
TemperatureController:SetTemp(ch, val),ReadTemp()IOController:SetEvent(ch, state),ReadEvent()DetectorADC:StartStream(),StopStream()FlowController (EPC):SetPressure(),ReadFlow()
在“散件模式”下,ModularDriver 实际上是一个聚合器 (Aggregator),它内部持有上述各个子接口的实例。这样无论是 A 厂家的温控搭配 B 厂家的 IO,都可以像搭积木一样在 Go 中自由组合。
6.2 异步数据聚合引擎 (Telemetry Aggregator)
痛点:原厂主板通过 Cmd 143 每秒打包所有状态一次性推送上来。但在散件模式下,各模块的采样率不同(ADC可能 50Hz,温控可能 1Hz,IO可能 2Hz)。 解决方案:在 HAL 层引入数据黑板 (Data Blackboard) 聚合引擎。
- 并发采集:各个子模块的驱动独立运行自己的 Goroutine 进行轮询或事件监听。
- 黑板更新:读到的数据通过读写锁写入后端的共享内存对象(黑板)中。
- 节拍组装:Collector 按照前端需要的固定节拍(如 10Hz)对“黑板”进行数据快照,组装成统一的
telemetryEvent通过 WebSocket 推送给前端。 结果:前端完全无感知底层是单板还是散件。
6.3 硬件拓扑描述文件 (Topology Config)
不能将串口号和波特率硬编码在代码里。需引入 hardware_topology.json 或 .env 结构:
后端启动时解析该拓扑,利用工厂模式(Factory Pattern)动态实例化并挂载对应的子驱动。
6.4 异常隔离与降级 (Fault Tolerance)
由于多模块共存,若某一模块(如气路 EPC)掉线,不应导致整个程序崩溃。
- 独立 Keep-Alive:每个子驱动独立管理自己的断线重连逻辑。
- 状态隔离:某模块超时,仅在对应的
telemetryEvent字段(如Epc[])标记为空或写入告警码,其他模块(如 ADC 和温控)继续运行,并在 UI 上局部标红,实现真正的容错隔离。
