SSPC-Tester/Docs/开发文档.md
2026-07-08 15:29:30 +08:00

705 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 固态功率控制器动态参数测试系统 — 开发文档
> 版本 v1.3 更新:**2026-07-08 14:58:50 +08:00** 技术栈:**C# + WPF + .NET 8** 口径:**以当前仓库代码为准**
>
> 本文档描述当前仓库的真实结构、配置方式、核心流程和维护约定。
> 若文档与代码冲突,以代码实现为准,并应同步回写本文档。
---
## 0. 开发约束
对本项目进行新增、修改、排障时,默认遵守以下原则:
1. **分层隔离优先**UI 只依赖 ViewModel / Service / Logic不直接依赖具体设备驱动。
2. **接口先行**SSPC、电源、负载、DAQ、安全 DIO 一律经 `SSPCTester.Devices.Interfaces` 暴露,真假驱动由配置决定。
3. **按设备粒度切换 Mock/Real**:当前不再是“一个全局 `MockMode` 管全部设备”,而是每类设备都有自己的 `UseMock`
4. **配置分层加载**:程序先读内置默认值,再读 `appsettings.json`,最后读 `%LOCALAPPDATA%\SSPCTester\settings.json`
5. **测试态独占**:进入测试后只展示当前项目,禁止切换其他项目,设备连接由测试态独占。
6. **文档随代码更新**:涉及接口、项目结构、运行方式、持久化格式变化时,要同步更新本文档。
---
## 1. 项目背景
### 1.1 被测对象
固态功率控制器SSPC用于智能配电场景。本项目按 **24 路** 输出通道建模,通过软件控制每路导通/关断,并测量:
- 基础通断状态
- 开启/关断曲线与时间参数
- 功率损耗与效率
- 保护功能测试结果
### 1.2 当前测试台硬件
| 部件 | 型号 | 作用 | 当前代码状态 |
|---|---|---|---|
| 工控机 | Windows x64 | 运行 WPF 主程序 | 已支持 |
| 被测件 SSPC | 24 路 | 控制 24 路导通/关断 | 已有 `SspcModbus` |
| 程控电源 | UDP5080-100 | 输入端电压/电流读取、输出开关控制 | 已有真实驱动 |
| 可编程负载 | IT8733P / IT8702P | 输出端电压/电流/功率读取、输入开关控制 | 已有真实驱动 |
| 高速采集卡 | PCIe8586 | 曲线波形采集 | 已有 `Pcie8586Daq` |
| 安全 DIO 卡 | PCI2312 | 急停输入读取、报警灯输出控制 | 已有 `Pci2312SafetyDio` |
| 示波器 | Tektronix MDO3024 | 线下校准基准 | 不纳入软件控制 |
### 1.3 当前实现事实
- SSPC 24 路通过 **3 个 Modbus 模块 × 每模块 8 路** 映射。
- 采集卡实现已经统一为 **PCIe8586**,不再使用旧文档中的 `PCIe9318` 命名。
- 真假设备切换已经演进为 **每类设备独立 `UseMock`**
- 主程序启动后会按配置自动连接 SSPC、电源、负载、DAQ、PCI2312。
- 新增设备安全监控链路:后台轮询 PCI2312 急停输入,触发后接通报警输出,并向 SSPC、电源、负载发送安全关断指令。
- 根目录脚本 `run.ps1` / `publish.ps1` 已是当前标准运行入口。
---
## 2. 当前功能范围
主流程如下:
```text
新建/打开项目
-> 填写项目信息 / 勾选测试项
-> 进入测试态
-> 执行基础测试 / 曲线测试 / 功率损耗 / 保护功能
-> 生成 PDF / Word 报告
```
### 2.1 四大模块
| 模块 | 当前实现 | 状态 |
|---|---|---|
| 基础测试 | 24 路逐路开/关、读电压电流、判定稳态关断 | 已实现 |
| 开启与关断曲线 | 支持开通/关断波形采集、指标计算、独立曲线视窗、波形落盘 | 已实现 |
| 功率损耗 | 使用 UDP5080 读输入端IT87xx 读输出端功率/电压/电流 | 已实现 |
| 保护功能 | 固定保护项、自动获取/人工观测数据记录、人工判别结果 | 已实现 |
### 2.2 设备安全与急停报警
当前代码新增了独立于“保护功能测试页”的**运行时设备安全链路**
- 硬件连接:`PCI2312` 通过厂商 `PCI2312_64.dll` 以 P/Invoke 方式接入,使用 DI 通道读取急停状态,使用 DO 通道控制报警灯。
- 后台监控:`SafetyMonitorService.Start()` 在主窗口初始化后启动,按 `Devices:Pci2312:PollIntervalMs` 周期轮询急停输入。
- 硬件急停:当配置的 DI 通道达到有效电平时,程序写入报警 DO并依次执行 SSPC 全通道关断、电源输出关闭、负载输入关闭。
- 软件急停:主窗口顶部“报警急停”按钮调用 `TriggerSoftwareEmergencyAsync()`,走同一套报警灯和设备关断链路。
- 状态重置:报警灯点亮后按钮变为“状态重置”。若硬件急停 DI 仍有效重置会被拒绝DI 复位后才关闭报警输出并恢复监控状态。
控制链路如下:
```text
PCI2312 DI 急停输入 / UI 软件急停按钮
-> SafetyMonitorService
-> PCI2312 DO 报警灯输出
-> ISspc.TurnOffAsync(1..24)
-> IPowerSupply.OutputAsync(false) // UDP5080 :OUTput OFF
-> ILoad.InputAsync(false) // IT8702P INP OFF
-> UI 状态、日志和报警灯图标同步刷新
```
注意:这是软件侧联动安全链路,用于快速下发关断和报警指令;现场仍应保留硬件级急停/互锁作为最终安全边界。
### 2.3 指标口径
当前计算与判定主要围绕以下指标:
- `1.1` 开启时间:到达输入电压 90% 的时间
- `1.2` 关闭时间:下降到输入电压 10% 的时间
- `1.5` 上升/下降时间10%~90% 或 90%~10% 时间
- `1.9` 电压降:`Vin - Vout`
- `1.10 / 1.13` 功率损耗、效率
- `1.14+` 保护功能相关触发条件、实测/观测值与人工判别结果
阈值定义和最终判断以 `Project.CurveThresholds` 与各页结果模型为准。
---
## 3. 技术栈
| 用途 | 当前选型 | 说明 |
|---|---|---|
| UI | WPF + .NET 8 | `net8.0-windows`x64 |
| MVVM | `CommunityToolkit.Mvvm` | `ObservableObject` / `RelayCommand` |
| 配置 | `Microsoft.Extensions.Configuration` | JSON + 用户设置覆盖 |
| DI / Host | `Microsoft.Extensions.Hosting` | 启动时装配所有服务 |
| Modbus | `NModbus` | SSPC 串口控制 |
| 串口 | `System.IO.Ports` | SSPC/部分设备底层通信 |
| TCP Socket | `System.Net.Sockets.TcpClient` | UDP5080 / IT87xx SCPI-RAW 通信 |
| 原生驱动 | P/Invoke + 厂商 DLL | PCIe8586 / PCI2312 接入 |
| 波形绘制 | `ScottPlot` / `ScottPlot.WPF` | 曲线页与报告插图 |
| 报告 | `QuestPDF` + `DocumentFormat.OpenXml` | PDF 与 Word 双实现 |
| Web 预览 | `Microsoft.Web.WebView2` | 报告页 PDF 预览 |
| 日志 | Serilog | Debug + 文件输出 |
---
## 4. 解决方案结构
### 4.1 分层
```text
UI (WPF / XAML / ViewModel)
-> Logic (测试流程 / 计算 / 报告 / 存储)
-> Devices.Interfaces (统一设备接口)
-> Devices.Drivers.Mock / Real (具体驱动)
```
依赖方向始终是 **上层只依赖下层抽象**
例如 UI 只拿到 `ISspc`,不直接感知背后是 `MockSspc` 还是 `SspcModbus`
### 4.2 当前解决方案
```text
SSPCTester.sln
├── SSPCTester.UI/ # WPF 主程序(启动项)
│ ├── Views/ # 页面与窗口
│ ├── ViewModels/ # MVVM 视图模型
│ ├── Controls/ # 自定义控件(含曲线控件)
│ ├── Resources/ # Tokens / Controls / Icons
│ ├── Converters/ # 状态与颜色转换
│ └── Services/ # 用户设置、应用配置等
├── SSPCTester.Logic/ # 业务层
│ ├── Testing/ # 测试模块与运行器
│ ├── Calculation/ # 曲线/功率计算纯函数
│ ├── Report/ # PDF/Word 报告实现
│ ├── Storage/ # 项目与波形持久化
│ └── Models/ # 项目、结果、阈值、枚举
├── SSPCTester.Devices/ # 设备抽象与驱动
│ ├── Interfaces/ # ISspc / IPowerSupply / ILoad / IDaq / ISafetyDio
│ ├── Drivers/Mock/ # Mock 驱动
│ ├── Drivers/Real/ # 真设备驱动
│ ├── Drivers/ConfigurableDevices.cs # 按设备切换 Mock/Real
│ ├── Protocol/ # 协议辅助
│ └── Config/ # 设备配置模型
├── SSPCTester.Tests/ # xUnit 测试
├── SSPCTester.Seed/ # 示例项目/种子数据生成
└── Docs/PCIe8586驱动接入资料/src/Pcie8586.Driver/
# 采集卡独立驱动类库,被 Devices/Tests 引用
```
### 4.3 关键脚本
- `run.ps1`:发布 UI、可选执行单测、可选灌入种子数据、最后启动发布产物
- `publish.ps1`:单独发布 WPF 程序
- `SSPCTester.Seed/WriteQualifiedProjects.ps1`:生成演示项目
---
## 5. 配置与驱动切换
### 5.1 配置加载顺序
程序启动时配置来源按优先级叠加:
1. 内置默认配置
2. `SSPCTester.UI/appsettings.json`
3. `%LOCALAPPDATA%\SSPCTester\settings.json`
用户在设置页修改的路径、报告格式等,最终写到用户目录,不回写仓库里的 `appsettings.json`
### 5.2 当前切换策略
当前采用 **每类设备独立切换**
- `Devices:Sspc:UseMock`
- `Devices:PowerSupply:UseMock`
- `Devices:Load:UseMock`
- `Devices:Daq:UseMock`
- `Devices:Pci2312:UseMock`
`Devices:MockMode` 仅保留兼容旧配置用途,不应再作为新逻辑入口。
### 5.3 当前 `appsettings.json` 节选
```json
{
"Devices": {
"MockMode": false,
"Sspc": {
"UseMock": false,
"AutoConnect": true,
"PortName": "COM1",
"BaudRate": 9600,
"ModuleAddresses": [1, 2, 3]
},
"PowerSupply": {
"UseMock": false,
"AutoConnect": true,
"Host": "192.168.6.5",
"Port": 5025
},
"Load": {
"UseMock": false,
"AutoConnect": true,
"Host": "192.168.200.100",
"Port": 30000
},
"Daq": {
"UseMock": false,
"AutoConnect": true,
"LogicalDeviceId": 0,
"ChannelCount": 1,
"InputRange": "PlusMinus5V",
"ClockDivider": 1000,
"PreTriggerMs": 3,
"PostTriggerMs": 100,
"Channels": [
{ "PhysicalChannel": 0, "Role": "OutputVoltage", "Name": "输出电压", "Scale": 1.0, "Offset": 0.0, "IsCalibrated": true },
{ "PhysicalChannel": 1, "Role": "Unconfigured", "Name": "CH1", "Scale": 1.0, "Offset": 0.0, "IsCalibrated": false }
]
},
"Pci2312": {
"Enabled": true,
"UseMock": false,
"AutoConnect": true,
"DeviceId": 0,
"EmergencyInputChannel": 0,
"EmergencyInputActiveHigh": true,
"AlarmOutputChannel": 0,
"AlarmOutputActiveHigh": true,
"PollIntervalMs": 100
}
},
"Storage": {
"ProjectsRoot": "%LOCALAPPDATA%\\SSPCTester\\Projects"
},
"Report": {
"SavePath": "%LOCALAPPDATA%\\SSPCTester\\Reports",
"Format": "Pdf"
}
}
```
---
## 6. 设备接口
所有设备接口均为异步接口,默认支持 `CancellationToken`
### 6.1 公共连接接口
```csharp
public interface IDeviceConnection
{
bool IsConnected { get; }
string DisplayName { get; }
Task<bool> ConnectAsync(CancellationToken ct = default);
Task DisconnectAsync();
event EventHandler<bool>? ConnectionChanged;
}
```
### 6.2 SSPC
```csharp
public interface ISspc : IDeviceConnection
{
int ChannelCount { get; }
Task TurnOnAsync(int physicalSlot, CancellationToken ct = default);
Task TurnOffAsync(int physicalSlot, CancellationToken ct = default);
Task FlashAsync(int physicalSlot, int milliseconds, CancellationToken ct = default);
Task<bool> GetChannelStateAsync(int physicalSlot, CancellationToken ct = default);
Task<ChannelMeasurement> ReadMeasurementAsync(int physicalSlot, CancellationToken ct = default);
Task<IReadOnlyList<ChannelMeasurement>> ReadMeasurementsAsync(CancellationToken ct = default);
}
```
### 6.3 电源
```csharp
public interface IPowerSupply : IDeviceConnection
{
Task SetVoltageAsync(double volts, CancellationToken ct = default);
Task SetCurrentLimitAsync(double amps, CancellationToken ct = default);
Task OutputAsync(bool on, CancellationToken ct = default);
Task<(double volts, double amps)> ReadAsync(CancellationToken ct = default);
Task<string> QueryIdentityAsync(CancellationToken ct = default);
}
```
### 6.4 负载
```csharp
public readonly record struct PowerReading(double Volts, double Amps, double Watts);
public interface ILoad : IDeviceConnection
{
Task SetModeAsync(LoadMode mode, CancellationToken ct = default);
Task SetValueAsync(double value, CancellationToken ct = default);
Task InputAsync(bool on, CancellationToken ct = default);
Task<(double volts, double amps)> ReadAsync(CancellationToken ct = default);
Task<PowerReading> ReadPowerAsync(CancellationToken ct = default);
Task<string> QueryIdentityAsync(CancellationToken ct = default);
}
```
### 6.5 DAQ
```csharp
public interface IDaq : IDeviceConnection
{
Task<IReadOnlyList<DaqDeviceDescriptor>> EnumerateDevicesAsync(CancellationToken ct = default);
Task<CurveData> CaptureAsync(int[] channels, int sampleRateHz, double durationSec, CancellationToken ct = default);
Task<double[]> ReadInstantAsync(int[] channels, CancellationToken ct = default);
Task<CurveData> CaptureAroundActionAsync(
DaqActionCaptureRequest request,
Func<CancellationToken, Task> action,
CancellationToken ct = default);
event EventHandler<CurveSample>? SampleReceived;
}
```
`CaptureAroundActionAsync()` 是当前曲线测试的核心接口:
先进入预采集,再在触发点附近执行开关动作,以得到统一对齐的波形。
### 6.6 安全 DIO
```csharp
public interface ISafetyDio : IDeviceConnection
{
Task<bool> ReadInputAsync(int channel, CancellationToken ct = default);
Task WriteOutputAsync(int channel, bool on, CancellationToken ct = default);
}
```
当前真实实现为 `Pci2312SafetyDio`
- `ConnectAsync()` 调用 `PCI2312_CreateDevice(DeviceId)` 创建设备句柄。
- `ReadInputAsync(channel)` 调用 `PCI2312_GetDeviceDI()` 读取 0~15 路 DI。
- `WriteOutputAsync(channel, on)` 维护 16 路 DO 状态数组,并调用 `PCI2312_SetDeviceDO()` 一次性写出。
- `DisconnectAsync()` 调用 `PCI2312_ReleaseDevice()` 释放句柄。
`ConfigurableSafetyDio``Devices:Pci2312:UseMock``MockSafetyDio``Pci2312SafetyDio` 间切换。PCI2312 是否参与自动连接由 `Devices:Pci2312:Enabled``Devices:Pci2312:AutoConnect` 共同决定。
---
## 7. 核心业务逻辑
### 7.1 测试模块统一入口
`Logic/Testing` 中已经落地:
```csharp
public interface ITestModule
{
string Name { get; }
Task RunAsync(TestContext ctx, IProgress<TestProgress> progress, CancellationToken ct);
}
```
`TestContext` 当前持有:
- `Project`
- `ISspc`
- `IPowerSupply`
- `ILoad`
- `IDaq`
`TestRunner` 依据 `Project.Selection` 串行执行模块。
设备安全监控不属于 `ITestModule`,不会进入项目测试结果,也不会由 `TestRunner` 调度;它由 UI 层 `SafetyMonitorService` 在程序运行期持续维护。
### 7.2 浏览态 / 测试态
当前程序已实现两种应用状态:
- **浏览态**:左侧树显示全部项目,可自由切换
- **测试态**
- 只显示当前项目
- 顶部展示“测试进行中”状态条
- 可中止测试
- 设备连接视为当前项目独占
这一逻辑由 `MainViewModel.AppState` 控制。
### 7.3 基础测试
当前基础测试实现采用 `ISspc.ReadMeasurementAsync()` 直接读取每路电压/电流:
```text
TurnOnAsync(ch)
-> Delay
-> ReadMeasurementAsync(ch)
-> 记录 VoltageOn / CurrentOn
-> TurnOffAsync(ch)
-> WaitForStableOffAsync(ch)
-> 根据导通和关断稳态结果判定 Pass / Fail
```
说明:
- 不是旧文档中的 `Daq.ReadInstant()` 方案
- “关断是否稳定”通过 `BasicTestCriteria.WaitForStableOffAsync()` 判定
### 7.4 曲线测试
当前代码存在两套相关逻辑:
1. **Logic 模块批处理**`CurveTest.cs`
- 一次完成开通与关断两段采集
- 适用于测试模块整体执行
2. **UI 曲线页交互**`CurveTestViewModel`
- 已拆成两个独立按钮:
- `开启曲线测试`
- `关断曲线测试`
- 开/关曲线各自保存、各自绘图、各自维护视窗范围
当前页与弹窗的“起点 / 终点 / 默认”已经拆成两套独立状态:
- `RisingViewStartMs` / `RisingViewEndMs`
- `FallingViewStartMs` / `FallingViewEndMs`
这些值会写回 `CurveResultRow` 并持久化。
状态规则:
- 两半都没做:`Untested`
- 只完成一半:`Measured`
- 两半都完成后:才根据 4 个指标判 `Pass / Fail`
### 7.5 功率损耗
当前正式实现采用:
- `UDP5080` 读取输入端 `Vin / Iin`
- `IT87xx` 读取输出端 `Vout / Iout / Pout`
这是当前在用方案。
仓库中仍保留旧的 `PowerTestLegacy`DAQ 思路),但未作为正式模块注册。
### 7.6 保护功能
当前保护功能页和逻辑层已经按固定保护项落地,结果由 `ProtectRow` 持久化。`ProtectTestPlan` 负责初始化和刷新固定测试项:
- `跳闸`:触发条件默认 `1.5×额定电流`
- `短路`:触发条件默认 `输出短路`
- `过温`:触发条件默认 `≥85℃`
- `过压`:触发条件默认 `≥32V`
- `欠压`:触发条件默认 `≤22V`
- `限流`:触发条件默认 `≥1.2A`
保护功能数据分为两类:
- **自动获取**:对 `跳闸`、`过压`、`欠压`、`限流` 等可由电源读数支撑的项目,页面提供“测”按钮,调用 `IPowerSupply.ReadAsync()` 获取当前电压/电流并写入 `MeasuredValue`
- **人工观测**:对 `短路`、`过温` 等需要现场动作、仪表或人员观察的项目,由操作人员在 `MeasuredValue`、`Trigger` 等字段中填写观测记录。
判定口径:
- 最终判别标准为**人工判别**,不由程序自动计算合格/不合格。
- `JudgeMode` 默认值为 `人工判别`
- `Status` 由操作人员在表格中选择 `合格` / `不合格` / `未判定`
- `ProtectTest.RunAsync()` 只负责刷新测量值和进度状态;若某项已经被人工判定为 `Pass``Fail`,运行批量测试时会保留该人工判定结果。
### 7.7 设备安全监控
`SafetyMonitorService` 是当前急停/报警链路的中心,依赖:
- `ISafetyDio`:读取急停 DI、写报警灯 DO。
- `ISspc`:触发急停后逐路执行 `TurnOffAsync(1..24)`
- `IPowerSupply`:触发急停后执行 `OutputAsync(false)`,真实 UDP5080 命令为 `:OUTput OFF`
- `ILoad`:触发急停后执行 `InputAsync(false)`,真实 IT8702P 命令为 `INP OFF`
- `UiLogSink`:写入 UI 日志,便于现场追踪急停动作。
启动链路:
```text
App.ConfigureServices()
-> 注册 MockSafetyDio / Pci2312SafetyDio / ConfigurableSafetyDio
-> 注册 SafetyMonitorService
-> MainViewModel.Initialize()
-> ConnectConfiguredDevicesAsync()
-> SafetyMonitorService.Start()
```
运行链路:
```text
Timer(PollIntervalMs代码中限制 50~10000ms)
-> 自动连接 PCI2312若启用 AutoConnect
-> ReadInputAsync(EmergencyInputChannel)
-> 按 EmergencyInputActiveHigh 解释有效电平
-> 触发 HandleEmergencyAsync()
```
急停处理具有防重入保护:`_gate` 和 `_handlingEmergency` 避免重复并发关断。每个设备的关断失败会单独记录日志,不阻断后续设备的关断尝试。
主窗口顶部状态区会展示:
- 报警灯动态图标:绑定 `AlarmLampActive`
- 急停/重置按钮:绑定 `ToggleEmergencyAlarmCommand`
- 安全状态文本:来自 `SafetyMonitorService.StatusText / DetailText`
- 设备面板中的 `报警/急停` 连接状态:来自 `ISafetyDio.IsConnected`
### 7.8 报告
当前报告支持:
- PDF
- Word
- PDF + Word
报告特性:
- 基于项目与勾选项动态生成
- 曲线插图由 `CurveImageRenderer` 生成
- 报告文件名不是固定 `report.docx`,而是动态解析后输出
- 报告页通过 `WebView2` 预览 PDF
---
## 8. 数据存储
### 8.1 项目目录
每个项目一个目录,目录根路径由 `Storage:ProjectsRoot` 决定。
典型内容:
- `project.json`
- `curves/`
- 生成出的 PDF / Word 报告
### 8.2 项目对象
`Project` 当前持久化内容包括:
- DUT 信息
- 测试站点信息
- 测试项勾选
- 报告配置
- 基础测试、曲线测试、功率损耗、保护功能结果
- 曲线阈值
- 四页测试说明文本
### 8.3 波形存储格式
波形不是简单的 JSON而是
- `curves/*.bin`float32 二进制采样数据
- `curves/*.json`:元数据
元数据包含:
- 采样率
- 触发点位置
- 通道角色/名称/单位
- 标定参数
### 8.4 旧数据兼容
`CurveResultRow` 中保留了旧字段:
- `ViewStartMs`
- `ViewEndMs`
新逻辑优先使用:
- `RisingViewStartMs / RisingViewEndMs`
- `FallingViewStartMs / FallingViewEndMs`
缺失时会回退到旧字段,兼容老项目。
---
## 9. 运行与发布
### 9.1 本地运行
推荐命令:
```powershell
PowerShell -ExecutionPolicy Bypass -File .\run.ps1
```
该脚本默认行为:
1. `dotnet publish` UI 到 `publish\win-x64`
2. 可选执行测试
3. 可选执行种子数据生成
4. 直接启动 `publish\win-x64\SSPCTester.UI.exe`
### 9.2 常用参数
- `-Test`:执行 `SSPCTester.Tests`
- `-Seed`:执行 `SSPCTester.Seed`
- `-CleanSeed`:清空项目目录后重新灌入种子数据
- `-NoLaunch`:只发布不启动
### 9.3 发布
推荐命令:
```powershell
PowerShell -ExecutionPolicy Bypass -File .\publish.ps1
```
当前默认发布参数是:
- `Release`
- `win-x64`
- `SelfContained = true`
- `SingleFile = false`
说明:
- 当前脚本明确没有走 WPF 单文件发布默认方案
- 发布时会检查 `ACTS1000_64.dll` 是否存在
- PCI2312 真设备模式还需要 `PCI2312_64.dll` 可由进程加载;当前发布脚本未做该 DLL 的存在性检查
### 9.4 运行环境
源码构建至少需要:
- Windows x64
- .NET 8 SDK x64
- WebView2 Runtime
- 真卡模式下的 PCIe8586 / PCI2312 厂商驱动与 x64 DLL
若只运行现成发布版,则至少需要满足发布产物依赖和本机驱动/DLL 条件。
---
## 10. 当前状态与后续工作
### 10.1 已完成
- WPF 主程序骨架、主题资源、页面导航
- 浏览态 / 测试态切换
- 项目新建、加载、保存
- 基础测试、曲线测试、功率损耗、保护功能页和结果记录
- PDF / Word 报告生成
- 真/假设备可按设备粒度切换
- 实际 SSPC / 电源 / 负载 / PCIe8586 / PCI2312 驱动接入代码
- PCI2312 急停输入轮询、报警输出、软件急停、状态重置和设备关断联动
### 10.2 待统一 / 待完善
- 功率损耗旧版 `PowerTestLegacy` 仍在仓库,后续应明确去留
- 曲线弹窗窗口已实现,但当前主页面尚未提供入口按钮
- 报告生成对新旧曲线视窗字段的使用口径后续建议统一
- PCI2312 真设备链路需要在现场确认 DI/DO 接线、电平有效性、报警灯供电方式和 DLL 随发布产物部署方式
---
## 11. 风险与注意事项
1. **DAQ 仍是最高风险点**:厂商 DLL、设备 ID、采样参数、输入量程和触发时序都依赖现场。
2. **Modbus 地址和端口仍需现场核实**:虽然当前实现已支持 3 模块映射,但设备地址/串口号应视现场配置为准。
3. **电源与负载真实驱动已接入,但控制命令支持度需按实物验证**
4. **PCI2312 急停报警链路依赖现场接线和 DLL 部署**DI/DO 通道号、高/低有效配置、报警灯供电、`PCI2312_64.dll` 位数和搜索路径都必须逐项核实。
5. **软件安全链路不能替代硬件安全回路**`SafetyMonitorService` 通过轮询和软件命令下发关断,适合作为上位机联动保护;最终急停/互锁仍应由硬件电气回路兜底。
6. **状态重置必须确认急停输入已复位**:当前代码在 DI 仍有效时拒绝关闭报警灯,避免误复位。
7. **所有长流程应贯穿 `CancellationToken`**,中止后优先保证设备回到安全状态。
8. **示波器不纳入软件控制**,仅作为线下校准基准。
9. **任何涉及数据模型持久化格式的修改,都要考虑旧项目兼容**
---
## 12. 维护建议
1. 改接口前,先同步修改 `Devices.Interfaces`、实现类、DI 装配和本文档。
2. 改项目结构前,先检查 `run.ps1`、`publish.ps1`、`Seed`、测试项目是否受影响。
3. 改曲线页前,注意当前已经有“主页面 + 弹窗 + 报告图”的三处视窗相关逻辑。
4. 改报告前,确认 `ReportViewModel`、`Logic/Report`、`WebView2` 预览链路同时保持可用。
5. 改设备安全链路前,先确认 `ISafetyDio`、`Pci2312SafetyDio`、`ConfigurableSafetyDio`、`SafetyMonitorService`、主窗口急停按钮和设置页 PCI2312 配置同步调整。
6. 若发现文档内容再次与代码偏离,应优先更新本文档,而不是继续在过时约束上开发。