进入工业自动化行业后,我接触到了OQC环节。在为 要求非常高的海外科技企业 做项目过程中,我总结出以下几个问题:

  1. 客户节奏快,压缩交付周期,代码质量容易失控
  2. 初级工程师能力不足,导致对高级软件工程师依赖过重,被迫长期承担基础性支持工作
  3. 开发周期长,人力投入大,有些项目需要全程驻场,随时响应

为了应对这些问题,我设计了一个专注于OQC的低代码平台。

这个低代码 OQC 项目的目标是降低软件工程师的直接参与度,让售后工程师、客户技术负责人等非软件背景人员,通过简单培训,就能使用图形界面完成测试流程配置。复杂流程或定制化功能可由软件工程师通过插件形式提供支持,如算法模块、定制报表等。

核心设计理念是职责解耦,提升效率,让工程师聚焦在更有价值的任务上。

它的核心目标是:

  1. 尽可能减少修改代码的工作量 —— 减少流程中代码变更的频率和范围,降低引入新错误的风险,缩短测试上线周期
  2. 可以让初级工程师承担更多任务,减少对高级工程师的依赖 —— 实现人员能力结构的优化,使高阶人力聚焦在架构设计与复杂逻辑实现,释放更多产测支持能力给初级岗位
  3. 可以减少软件工程师常年驻场的情况,释放人力资源 —— 降低一线响应对高成本人力的依赖,使工程师能并行支持更多项目,提升团队整体产能

架构设计总览 Link to heading

本架构遵循关注点分离(Separation of Concerns, SoC)依赖倒置原则(Dependency Inversion Principle, DIP)。上层策略(如流程管理)不依赖于下层具体实现(如HTTP请求发送),二者都依赖于抽象的统一接口和共享数据上下文。

graph TD; %% 1. 定义所有节点 User["User configures flow via UI / 用户通过UI配置流程"]; FlowTemplate["Flow Template (JSON) / 流程模板 (JSON)"]; UserAction["User/Device triggers test / 用户或设备触发测试"]; SlotManager["L0: Slot Manager / 槽位管理器"]; FC["L1: Flow Controller / 流程控制器"]; EC[("L1: ExecutionContext / 执行上下文")]; Interpreter["L2: Interpreter / 解释器"]; ModuleHttp["L3: HttpModule / HTTP模块"]; ModuleSerial["L3: SerialModule / 串口模块"]; ModuleEtc["L3: ...More Modules / ...更多模块"]; %% 2. 定义连接关系 User --> FlowTemplate; UserAction --> SlotManager; SlotManager -- "1. Create Instance / 创建实例" --> FC; FC -- "Uses / 使用" --> Interpreter; Interpreter -- "Dispatches to / 分发给" --> ModuleHttp; Interpreter -- "Dispatches to / 分发给" --> ModuleSerial; Interpreter -- "Dispatches to" --> ModuleEtc; FC -- "3. Report Result / 报告结果" --> SlotManager; %% 3. 数据流 FlowTemplate -. "as Blueprint / 作为蓝图" .-> FC; FC -. "Owns & Manages / 拥有并管理" .-> EC; ModuleHttp <-. "Reads/Writes / 读/写" .-> EC; ModuleSerial <-. "Reads/Writes / 读/写" .-> EC; ModuleEtc <-. "Reads/Writes / 读/写" .-> EC; %% 4. 视觉分组 subgraph " " direction LR subgraph "User & System Interaction / 用户与系统交互" User; FlowTemplate; end subgraph "Core Execution Architecture / 核心执行架构" SlotManager; FC; EC; Interpreter; ModuleHttp; ModuleSerial; ModuleEtc; end end %% 5. 样式定义 classDef layer0 fill:#e3f2fd,stroke:#333; classDef layer1 fill:#e8f5e9,stroke:#333; classDef layer2 fill:#fff3e0,stroke:#333; classDef layer3 fill:#f3e5f5,stroke:#333; classDef data fill:#ffebee,stroke:#c62828,stroke-width:2px; class SlotManager layer0; class FC,EC layer1; class Interpreter layer2; class ModuleHttp,ModuleSerial,ModuleEtc layer3; class EC data;

界面原型与交互验证 (UI Prototype & Interaction Validation) Link to heading

为了验证低代码平台的关键理念——即便是非技术人员也能通过直观的UI进行测试流程配置,我使用 Electron 快速开发了一个用户界面原型。虽然此原型仅包含前端交互逻辑,未集成后端业务,但已充分展示了我们设想的配置体验。

工作台界面 (Workbench UI) Link to heading

该界面旨在提供测试槽位(Slot)的实时状态监控,以便用户直观了解每个测试工位的运行情况和结果。

Workbench UI

图1:工作台界面,展示测试槽位实时状态

流程设计界面 (Flow Design UI) Link to heading

在最初的设计构想中,我们曾考虑采用传统的流程图(Flowchart)形式进行配置。但在深入考量用户体验、实现复杂度和后期维护成本后,我们调整了策略,计划通过 Compose Multiplatform 实现一种可拖拽的列表式配置界面。这种方式能更高效地管理线性或简单分支流程,同时降低用户的学习曲线和开发难度。

Flow Designer UI Concept

图2:流程设计界面概念原型,基于可拖拽列表


跨平台技术选型考量 (Cross-Platform Technology Selection) Link to heading

为了确保未来实现能够满足工业领域对跨平台、高性能和部署便捷性的需求,我对多种主流的跨平台技术方案进行了深入对比和评估。

我们对比分析了 Electron、Flutter、Tauri 以及 Compose Multiplatform 等主流方案。最终,我们决定采用 Compose Multiplatform 作为前端UI框架,搭配 Rust 作为高性能的后端逻辑和计算引擎。这一组合的核心优势在于:

  • Compose Multiplatform (前端): 提供了现代化的声明式UI范式,能够以接近原生的性能,高效构建适用于桌面(macOS、Windows、Linux)、Android甚至iOS的界面,大幅提升开发效率和一致性。
  • Rust (后端): 凭借其出色的内存安全、并发性能和与底层硬件的紧密结合能力,非常适合处理工业自动化中对稳定性、实时性和数据吞吐量有高要求的核心逻辑,且能编译为跨平台的原生可执行文件。
  • 整体优势: 该组合不仅能完美支持项目对macOS、Windows、Linux多平台(包括ARM和x86架构)的兼容性要求,还在开发效率、运行时性能和长期可维护性之间取得了最佳平衡。

更多关于跨平台框架的详细对比和选择 Compose Multiplatform 的原因,请参考我的另一篇文章:《跨平台开发框架对比:Compose Multiplatform, Flutter, Tauri, Electron》

组件职责详解 Link to heading

1. ExecutionContext(执行上下文) Link to heading

  • 别名The CipherValueHolderFlowContext
  • 核心职责:作为单个测试流程实例的 单一事实来源(Single Source of Truth),独立、隔离地承载流程的全部动态数据。
  • 生命周期:随 Flow Controller 创建而创建,随其销毁而销毁,一一对应,完全隔离。
  • 结构设想
    • global:只读,全局信息,例如产品SN、工位编号、操作员ID。
    • steps:Map类型,键为节点ID,值为对应节点的输出结果,用于结果追溯与引用。
    • transient:临时变量区,例如循环计数器、内部标记。
  • 工作机制
    • 写入:模块执行完毕后由 Flow Controller 写入至 steps[currentNodeId]
    • 读取:模块通过路径表达式(如 steps.node-123.voltage)访问所需数据。
    • 变量插值:例如 context.interpolate("http://.../${global.sn}"),用于动态填充字符串。
  • 设计目的
    • 解耦节点间数据依赖,各节点仅依赖统一上下文接口。
    • 可调试性强:可完整序列化为JSON,回溯流程状态。
    • 可恢复性高:支持持久化至数据库或Redis,实现断点续传。

2. Module Interpreter(模块解释器) Link to heading

  • 别名ModuleNodeHandlerAdapter
  • 核心职责:执行一项原子任务,包括外设通信、计算、条件判断等。
  • 统一接口定义run(config, context) -> Promise<ResultObject>
    • config:节点静态配置项(如串口号、URL等)。
    • context:流程上下文引用,用于数据读取与写入。
    • ResultObject:标准输出格式 { status, output, error }
  • 工作机制
    1. Interpreter 调用。
    2. 读取 configcontext 所需参数。
    3. 执行任务。
    4. 输出结果封装为 ResultObject
  • 设计目的
    • 实现功能的模块化与可插拔性。
    • 将外部I/O与逻辑实现隔离,核心系统不涉底层实现。
    • 模块可复用:可在不同流程中重复使用而无需改写。

3. Interpreter(解释器) Link to heading

  • 核心职责:根据节点类型将任务委托至对应模块执行。
  • 内部结构:类型注册表(如 { 'http': HttpModuleInstance })。
  • 工作机制
    1. 接收 Flow Controller 指令 execute(node, context)
    2. 解析 node.type,定位注册模块。
    3. 调用相应模块的 run(config, context) 方法。
    4. 返回标准化结果给 Flow Controller
  • 设计目的
    • 解耦流程控制器与模块类型,控制器不处理模块映射。
    • 所有节点执行通过统一入口,便于加入日志、性能监控、错误处理等通用逻辑。

4. Flow Controller(流程控制器) Link to heading

  • 核心职责:驱动单个测试流程实例的调度执行。
  • 生命周期:由 Slot Manager 创建,完成任务后返回结果并自行销毁。
  • 工作机制
    1. 初始化:接收 FlowTemplate 与初始数据(如SN)。
    2. 创建专属 ExecutionContext
    3. 解析流程图,生成执行计划(线性或拓扑序)。
    4. 执行循环:
      • 将节点与 context 传入 Interpreter 执行。
      • 接收 ResultObject,分析 status
      • 若成功:写入 ExecutionContext 并继续。
      • 若失败:根据流程定义跳转、重试或中止。
      • 若为判断节点:基于 output 选择下一路径。
    5. 终结流程后,提取最终数据,上报 Slot Manager
  • 设计目的
    • 控制层逻辑封装完整,包括顺序、分支、循环与错误处理。
    • 每个实例独立运行,支持高并发任务分发与调度。

5. Slot Manager(槽位管理器) Link to heading

  • 核心职责:统一管理所有测试流程实例,维护Slot资源与状态。
  • 工作机制
    1. 监听测试请求(来自用户或设备)。
    2. 分配空闲 Slot,记录其状态。
    3. 创建并启动 Flow Controller,传入模板与初始数据。
    4. 接收任务完成信号,记录并处理结果。
    5. 清理流程实例,释放 Slot 资源。
  • 设计目的
    • 作为执行引擎与外部交互的分界线,避免系统耦合UI或协议层。
    • 提供并发控制与Slot状态管理能力,支撑大规模任务运行。