3. 测试数据采集机制

TestStand 的数据采集不是“测试结束后把结果写进数据库”这么简单。它实际上是一条从 Step 执行到结果落库的完整数据链:Step 在运行时产生状态与测量值,Sequence 通过结果容器收集这些数据,附加数据补充上下文,实时数据流则决定哪些数据在测试过程中就被推送出去。理解这条链的每一段,才能设计出可追溯、可查询、可复现的质量数据体系。

Step 结果记录:状态与结果列表

每个 Step 执行后,TestStand 会在结果列表中生成一条记录,核心字段包括 StepName、Status、Error.Code、Error.Msg、StartTime、EndTime、TotalTime 以及 NumericLimit、StringValue、PassFail 等测量相关属性。状态取值通常为 Passed、Failed、Done、Skipped、Terminated、Error。其中 Done 表示执行完成但未做判定,Passed/Failed 才代表判定结果。

结果记录默认写入 RunState.Root.ResultList,可通过 RunState.Root.ResultList[0].TS.SequenceCall.ResultList 逐层访问。若在 Sequence 属性中勾选“Record Results”,则每个 Step 的结果都会进入结果列表;若关闭,则只保留顶层 Sequence 的结果。实际项目中建议对关键测量 Step 开启记录,对纯控制类 Step(如延时、消息弹窗)关闭,以减少数据量。

自定义结果与测量值

当 Step 的默认结果字段不足以表达业务含义时,需要写入自定义结果。常用方式有两种:一是通过 Step.Result 下的自定义属性,例如在 Numeric Limit Test 中增加 Step.Result.MyResult.MeasuredValue;二是通过 RunState.Root.ResultList[0].TS.SequenceCall.ResultList 追加自定义结果对象。

测量值写入时要注意数据类型与单位。例如电压测量应写入 Step.Result.Numeric = 3.301,同时把单位写入 Step.Result.Units = "V",把判定上下限写入 Step.Result.Limits.High = 3.4、Step.Result.Limits.Low = 3.2。这样在报表和数据库中才能还原“测了什么、值是多少、判定依据是什么”。

// 示例:在 Numeric Limit Test 的 Post-Expression 中写入自定义测量值
Step.Result.Numeric = Locals.MeasuredVoltage;
Step.Result.Units = "V";
Step.Result.Limits.Low = 3.2;
Step.Result.Limits.High = 3.4;
Step.Result.MyResult.Channel = "AI0";
Step.Result.MyResult.SampleRate = 10000;

自定义结果建议遵循“业务字段 + 原始值 + 单位 + 通道/条件”的结构。例如 MyResult.Channel 记录物理通道,MyResult.SampleRate 记录采样率,MyResult.Temperature 记录环境温度。这样后续做质量分析时,可以按通道、温度、批次等维度筛选。

附加数据:让结果带上上下文

附加数据(Additional Data)用于记录与测试结果相关但不属于 Step 判定本身的上下文信息,例如产品序列号、工位号、操作员、测试程序版本、夹具编号、环境温湿度、校准有效期等。TestStand 提供 RunState.Root.AdditionalData 容器,可在 ProcessSetup 或 SequenceFileLoad 中写入。

// 示例:在 ProcessSetup 中写入附加数据
RunState.Root.AdditionalData.ProductSN = "SN20240521-001";
RunState.Root.AdditionalData.StationID = "ST-03";
RunState.Root.AdditionalData.Operator = "zhangsan";
RunState.Root.AdditionalData.TestProgramVersion = "1.2.3";
RunState.Root.AdditionalData.FixtureID = "FX-07";
RunState.Root.AdditionalData.CalibrationDue = "2024-12-31";

附加数据与结果记录的关系是“一对多”:一次测试运行对应一组附加数据,而结果列表中有多条 Step 结果。写入数据库时,通常把附加数据放在主表,把 Step 结果放在明细表,通过 RunID 或 BatchID 关联。这样既避免重复存储,又便于按批次追溯。

实时数据流配置

实时数据流解决的是“测试过程中就要看到数据”的需求,例如产线看板、SPC 实时监控、异常报警。TestStand 本身不直接提供消息队列,但可以通过以下方式实现:在 Step 的 Post-Expression 中调用数据库存储过程、写入共享变量、调用 DLL 或使用 TestStand 的 RunState 事件回调。

常见配置方式是在 SequenceFilePostStep 回调中判断当前 Step 是否属于需要实时上报的类型,然后调用外部接口。例如:

// 示例:在 SequenceFilePostStep 回调中推送实时数据
if (Step.Result.Numeric != 0) {
    Locals.Payload = "{"
        + "\"SN\":\"" + RunState.Root.AdditionalData.ProductSN + "\","
        + "\"Step\":\"" + Step.Name + "\","
        + "\"Value\":" + Step.Result.Numeric + ","
        + "\"Unit\":\"" + Step.Result.Units + "\","
        + "\"Status\":\"" + Step.Result.Status + "\""
        + "}";
    // 调用 HTTP 或 MQTT 接口推送 Locals.Payload
}

实时数据流的关键参数包括:推送频率(每个 Step 推送还是按时间间隔批量推送)、失败重试策略、断线缓存、数据格式(JSON/CSV/二进制)。若产线网络不稳定,建议在本地先写入 SQLite 或文本缓存,网络恢复后再补传,避免数据丢失。

数据链整体关系

把上述四部分串起来看:Step 执行产生结果记录,结果记录中可包含自定义测量值;附加数据提供运行级上下文;实时数据流在测试过程中把关键结果推送到外部系统。四者共同构成 TestStand 的数据采集机制。下图展示了这条数据链的流向与落点。

TestStand 测试数据采集链 Step 执行 Numeric Limit Test Pass/Fail 判定 Step 结果记录 Status / Numeric / Units Limits / StartTime / EndTime 自定义结果 MyResult.Channel SampleRate / Temperature 附加数据 ProductSN / StationID Operator / Version 实时数据流 PostStep 回调推送 HTTP / MQTT / 共享变量 质量数据库 / 追溯系统 主表:RunID + 附加数据 明细表:Step 结果 + 自定义测量值 运行时产生 结果容器收集 按 RunID 关联落库

配置要点与常见问题

第一,结果记录开关要按 Step 类型区分。测量类 Step 开启记录,控制类 Step 关闭,避免结果列表膨胀。第二,自定义结果字段命名要统一,建议在项目模板中预定义 MyResult 子属性结构,避免各工程师随意命名。第三,附加数据应在 ProcessSetup 中一次性写入,不要在多个 Step 中重复赋值。第四,实时数据流要设置超时与重试,避免因外部接口阻塞导致测试卡死。第五,数据库写入建议使用事务,先写主表再写明细表,失败时回滚,保证数据一致性。

若使用 TestStand 的 Database Logger,可在 Database Options 中配置“On-The-Fly”模式,使每条 Step 结果执行后立即写入数据库,而不是等整个 Sequence 结束后批量写入。这对产线实时追溯非常关键。
实时数据流推送时,不要直接在 Step 的 Post-Expression 中执行长时间阻塞操作(如等待 HTTP 响应)。建议使用异步调用或写入本地队列,由独立线程消费,否则会拖慢测试节拍。

总结来说,Step 结果记录解决“测了什么、结果如何”,自定义结果解决“业务字段如何表达”,附加数据解决“这次测试的上下文是什么”,实时数据流解决“数据何时到达外部系统”。四者配置得当,才能让 TestStand 的数据真正服务于质量追溯与产线决策。