工厂的质量检测软件,长期处于重复造轮子的状态。

无论测什么产品、用什么仪器,有几件事永远跑不掉——连接设备、发送指令、取回数据、判定结果。Catalytic 将这些共性能力抽象为平台层,差异部分通过配置和插件扩展。


核心问题:什么是不变的? Link to heading

设计平台之前,需要先明确一个问题:不管项目如何变化,什么是始终不变的?

答案很清晰:

  • 总要连接仪器、发送指令、接收数据
  • 总要按既定流程顺序执行步骤
  • 总要判断结果是否合格
  • 总要处理超时、异常、重试
  • 总要记录数据、生成报告

无论测什么产品、用什么仪器,这些事情都跑不掉。

变化的部分是:仪器型号、测试参数、流程顺序、检查规则。

因此架构思路清晰:把不变的部分沉淀为引擎,把变化的部分推到配置层。

graph TD
    A[项目 A] -->|不同配置| P[Catalytic 平台]
    B[项目 B] -->|不同配置| P
    C[项目 C] -->|不同配置| P
    P --> E[同一套引擎]

三层架构:各司其职 Link to heading

确定方向之后,架构自然分成三层。

graph TD
    subgraph UI["UI 层 (Kotlin Compose Multiplatform)"]
        U1[配置操作]
        U2[状态监控]
        U3[日志展示]
    end

    subgraph Host["Host 层 (C# / .NET)"]
        H1[插件加载]
        H2[设备通讯]
        H3[gRPC 服务]
    end

    subgraph Engine["Engine 层 (Rust)"]
        E1[状态机]
        E2[流程调度]
        E3[规则判定]
        E4[数据持久化]
    end

    subgraph Plugins["插件层"]
        P1[通讯插件\nTCP / UDP / 串口]
        P2[处理器插件\n报告 / MES 对接]
    end

    UI <-->|gRPC / Protobuf| Host
    Host <-->|FFI C ABI| Engine
    Host --> Plugins

每一层的技术选择都是职责驱动,而非偏好驱动:

  • Engine 用 Rust:引擎承担状态机、并发调度、逻辑判定,要求稳定可预测。同时以二进制形式分发,核心逻辑得到保护。
  • Host 用 C#:仪器厂商的 SDK 生态在 .NET 里最成熟,插件开发者大概率是做仪器通讯的工程师,C# 对他们的门槛最低。
  • UI 用 Compose Multiplatform:一套代码覆盖 macOS / Windows / Linux,工厂环境不一定都是 Windows。

三层之间的核心原则是边界清晰

  • Engine 不处理任何 IO,只负责业务逻辑
  • Host 不持有任何业务状态,只负责通讯与桥接
  • UI 不直接操作业务数据,只负责呈现与交互

插件系统:契约固定,实现自由 Link to heading

插件是平台扩展性的核心。

设计插件系统时,面临一个选择:插件实例是共享的还是隔离的?

表面上看,共享更省资源,隔离更安全。但这个问题的本质是:插件是有状态的还是无状态的?

  • 无状态插件:接收输入,处理,返回结果,自身不保留任何数据。共享实例没有风险。
  • 有状态插件:内部维护缓存、连接池、配置快照。共享实例会引入 Slot 间的隐式耦合。

框架层面的决策是:永远共享插件实例,但不强制插件无状态。 插件是否维护内部状态由开发者决定,复杂度由引入者承担。

框架约束的是架构边界与通讯契约,不约束实现方式:

graph LR
    subgraph 框架约束
        A[插件注册方式]
        B[调用契约]
        C[结果回传格式]
        D[生命周期事件]
    end

    subgraph 开发者自由
        E[内部是否有状态]
        F[用什么库]
        G[如何实现逻辑]
    end

    框架约束 --> H[稳定的协作基础]
    开发者自由 --> I[无限的扩展可能]

插件分两种类型:

Communicator(通讯插件):负责与仪器通信,TCP、UDP、串口、VISA 等协议各自独立实现,互不干扰。

Processor(处理器插件):负责复杂业务逻辑,报告生成、MES 数据上报、上位机遥控接入,均通过此类插件实现。


多 Slot 并行 Link to heading

工厂产线通常有多个测试工位同时运行,每个 Slot 是一个完全独立的运行环境:

graph TD
    subgraph Engine
        subgraph Slot1["Slot 1"]
            S1A[状态机]
            S1B[变量池]
            S1C[步骤结果]
        end
        subgraph Slot2["Slot 2"]
            S2A[状态机]
            S2B[变量池]
            S2C[步骤结果]
        end
        subgraph Slot3["Slot 3"]
            S3A[状态机]
            S3B[变量池]
            S3C[步骤结果]
        end
    end

各 Slot 持有独立的状态机与变量池,一个 Slot 的测试结果与运行状态不影响其他 Slot。


测试步骤:两种执行模式 Link to heading

每个测试步骤有两种执行模式,对应两种不同的业务场景:

flowchart TD
    S[测试步骤] --> M{执行模式}

    M -->|Engine Controlled| EC[引擎控制模式]
    M -->|Host Controlled| HC[Host 控制模式]

    EC --> EC1[引擎发指令给仪器]
    EC1 --> EC2[等待响应]
    EC2 --> EC3[解析数据]
    EC3 --> EC4[判定 Pass/Fail]

    HC --> HC1[引擎将控制权交给 Host]
    HC1 --> HC2[Host 执行复杂逻辑\n报告生成 / MES上报 / 等待操作员]
    HC2 --> HC3[Host 提交结果给引擎]
    HC3 --> EC4

引擎控制模式适合标准仪器测试步骤:发指令、收数据、判定结果。

Host 控制模式适合复杂业务步骤:生成报告、上传数据、等待人工确认。控制权完全交给 Host 层,引擎只等待最终结果。


配置可迁移 Link to heading

配置文件可导出为 JSON,在不同机台之间迁移。

导出内容包含:设备类型定义、测试步骤、检查规则。

不包含:设备实例的物理地址、槽位绑定关系——这些是机台级别的配置,每台机器独立设置。

划分依据是:流程是通用的,连接是具体的。 同一套测试流程可在不同机台复用,但每台机台接的仪器地址不同。


最后 Link to heading

Catalytic 目前仍在持续开发中。

这篇文章记录的是设计思路,不是实现细节。每一个决策背后,都先想清楚问题是什么、边界在哪里,然后找最简单的方案解决它。

工业软件领域有大量重复劳动等待被自动化,这是 Catalytic 存在的理由。