2026-05-15 10:59:24 +08:00
|
|
|
|
using ASTM_D7896_Tester.Helpers;
|
2026-04-18 19:00:34 +08:00
|
|
|
|
using ASTM_D7896_Tester.Models;
|
|
|
|
|
|
using ASTM_D7896_Tester.Services;
|
2026-05-15 10:59:24 +08:00
|
|
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
|
|
|
|
using CommunityToolkit.Mvvm.Input;
|
|
|
|
|
|
using OxyPlot;
|
|
|
|
|
|
using OxyPlot.Axes;
|
|
|
|
|
|
using OxyPlot.Series;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
|
using System.Linq;
|
2026-05-20 13:49:45 +08:00
|
|
|
|
using System.Threading;
|
2026-05-15 10:59:24 +08:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using System.Windows;
|
2026-04-18 19:00:34 +08:00
|
|
|
|
|
|
|
|
|
|
namespace ASTM_D7896_Tester.ViewModels;
|
|
|
|
|
|
|
|
|
|
|
|
public partial class D7896ViewModel : ObservableObject
|
|
|
|
|
|
{
|
2026-05-15 20:39:11 +08:00
|
|
|
|
private readonly IPlcService _plcService;
|
2026-04-18 19:00:34 +08:00
|
|
|
|
private AppConfig _config;
|
2026-05-15 20:39:11 +08:00
|
|
|
|
private readonly ReportService _reportService;
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// ======================= 成员变量 =======================
|
|
|
|
|
|
private Timer? _monitorTimer; // 后台监控定时器
|
|
|
|
|
|
private readonly object _monitorLock = new(); // 监控更新锁
|
|
|
|
|
|
private double _lastRawPressure = 0; // 上次压力原始值
|
|
|
|
|
|
private double _lastRawTemperature = 0; // 上次温度原始值
|
|
|
|
|
|
|
|
|
|
|
|
// ======================= UI绑定属性 =======================
|
2026-05-15 21:10:42 +08:00
|
|
|
|
public ObservableCollection<string> ReferenceLiquids { get; } = new() { "蒸馏水", "甲苯", "乙二醇" };
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty] private string _sampleId = "未命名样品";
|
|
|
|
|
|
[ObservableProperty] private double _testTemperature = 25.0;
|
|
|
|
|
|
[ObservableProperty] private string _testDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
|
[ObservableProperty] private bool _isTesting = false;
|
|
|
|
|
|
[ObservableProperty] private string _statusMessage = "就绪";
|
|
|
|
|
|
[ObservableProperty] private int _currentMeasurementIndex = 0;
|
|
|
|
|
|
[ObservableProperty] private ObservableCollection<MeasurementResult> _measurements = new();
|
|
|
|
|
|
[ObservableProperty] private double _averageThermalConductivity;
|
|
|
|
|
|
[ObservableProperty] private double _averageThermalDiffusivity;
|
|
|
|
|
|
[ObservableProperty] private double _averageVolumetricHeatCapacity;
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 测试条件(测试前设置)
|
2026-05-15 21:10:42 +08:00
|
|
|
|
[ObservableProperty] private double _sampleVolume = 40.0;
|
|
|
|
|
|
[ObservableProperty] private bool _bubbleRemoved = true;
|
|
|
|
|
|
[ObservableProperty] private bool _usePressure = false;
|
|
|
|
|
|
[ObservableProperty] private double _pressureValue = 0.0;
|
|
|
|
|
|
[ObservableProperty] private bool _isCleanConfirmed = true;
|
|
|
|
|
|
[ObservableProperty] private string _cleanerName = "";
|
|
|
|
|
|
[ObservableProperty] private double _ambientTemperature = 25.0;
|
|
|
|
|
|
[ObservableProperty] private bool _ambientCalibrated = true;
|
|
|
|
|
|
[ObservableProperty] private bool _platinumCompatible = true;
|
|
|
|
|
|
[ObservableProperty] private string _liquidReactivityNote = "";
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 实时监控参数(测试前+测试中+测试后持续更新)
|
|
|
|
|
|
[ObservableProperty] private double _platinumResistance = 0.0; // 铂丝电阻(实时)
|
|
|
|
|
|
[ObservableProperty] private double _chamberPressure = 0.0; // 样品池压力(实时)
|
|
|
|
|
|
[ObservableProperty] private double _currentTestTemperature = 0.0; // 当前测试温度(实时)
|
|
|
|
|
|
|
2026-05-15 21:10:42 +08:00
|
|
|
|
// 系统校准
|
|
|
|
|
|
[ObservableProperty] private bool _isCalibrating = false;
|
|
|
|
|
|
[ObservableProperty] private string _calibrationStatus = "";
|
|
|
|
|
|
[ObservableProperty] private string _selectedReferenceLiquid = "蒸馏水";
|
|
|
|
|
|
[ObservableProperty] private double _referenceConductivity = 0.606;
|
|
|
|
|
|
[ObservableProperty] private double _measuredConductivity = 0.0;
|
|
|
|
|
|
[ObservableProperty] private double _calibrationErrorPercent = 0.0;
|
|
|
|
|
|
|
|
|
|
|
|
// 温升曲线
|
|
|
|
|
|
[ObservableProperty] private string _curveTitle = "温升曲线";
|
|
|
|
|
|
[ObservableProperty] private PlotModel _temperatureCurveModel;
|
2026-05-15 10:59:24 +08:00
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
|
|
|
|
|
|
private Th1963LanService _th1963Upt;
|
|
|
|
|
|
private Th1963LanService _th1963Ustd;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ======================= 构造函数 =======================
|
2026-04-18 19:00:34 +08:00
|
|
|
|
public D7896ViewModel()
|
|
|
|
|
|
{
|
2026-05-15 21:10:42 +08:00
|
|
|
|
_config = App.PlcConfig ?? new AppConfig();
|
|
|
|
|
|
_plcService = App.PlcService;
|
2026-04-18 19:00:34 +08:00
|
|
|
|
_reportService = new ReportService(_config.TestParameters.ReportOutputPath);
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 加载配置中的默认值
|
2026-04-18 19:00:34 +08:00
|
|
|
|
SampleVolume = _config.TestParameters.DefaultSampleVolume;
|
|
|
|
|
|
UsePressure = _config.TestParameters.UsePressure;
|
|
|
|
|
|
PressureValue = _config.TestParameters.DefaultPressure;
|
|
|
|
|
|
SelectedReferenceLiquid = _config.TestParameters.ReferenceLiquid;
|
|
|
|
|
|
ReferenceConductivity = _config.TestParameters.ReferenceConductivity;
|
2026-05-15 21:10:42 +08:00
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 前置确认项默认勾选
|
2026-05-15 10:59:24 +08:00
|
|
|
|
IsCleanConfirmed = true;
|
|
|
|
|
|
BubbleRemoved = true;
|
|
|
|
|
|
PlatinumCompatible = true;
|
|
|
|
|
|
AmbientCalibrated = true;
|
2026-05-20 13:49:45 +08:00
|
|
|
|
|
|
|
|
|
|
// 启动后台监控
|
|
|
|
|
|
StartBackgroundMonitoring();
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// ======================= 后台监控系统 =======================
|
|
|
|
|
|
private async void StartBackgroundMonitoring()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 等待PLC连接
|
|
|
|
|
|
await Task.Delay(1000);
|
|
|
|
|
|
|
|
|
|
|
|
_monitorTimer = new Timer(async _ => await MonitorPlcValues(), null, 0, 1000);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async Task MonitorPlcValues()
|
2026-04-18 19:00:34 +08:00
|
|
|
|
{
|
2026-05-15 21:10:42 +08:00
|
|
|
|
if (!await _plcService.IsConnectedAsync())
|
2026-04-18 19:00:34 +08:00
|
|
|
|
return;
|
2026-05-15 21:10:42 +08:00
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
lock (_monitorLock)
|
2026-04-18 19:00:34 +08:00
|
|
|
|
{
|
2026-05-20 13:49:45 +08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. 读取铂丝电阻值(D1422,0.001Ω单位)
|
|
|
|
|
|
float rawResistance = _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Resistance).Result;
|
|
|
|
|
|
double newResistance = rawResistance / 1000.0;
|
|
|
|
|
|
if (Math.Abs(newResistance - _lastRawPressure) > 0.0001)
|
|
|
|
|
|
{
|
|
|
|
|
|
_lastRawPressure = newResistance;
|
|
|
|
|
|
Application.Current.Dispatcher.Invoke(() => PlatinumResistance = newResistance);
|
|
|
|
|
|
}
|
2026-05-15 21:10:42 +08:00
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 2. 读取压力值(D1322,0.1kPa单位)
|
|
|
|
|
|
float rawPressure = _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Pressure).Result;
|
|
|
|
|
|
|
|
|
|
|
|
_lastRawTemperature = rawPressure;
|
|
|
|
|
|
Application.Current.Dispatcher.Invoke(() => ChamberPressure = rawPressure);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 读取温度值(D1376,0.1℃单位)
|
|
|
|
|
|
float rawTemp = _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Temperature).Result;
|
2026-05-15 21:10:42 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
Application.Current.Dispatcher.Invoke(() => CurrentTestTemperature = rawTemp);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
System.Diagnostics.Debug.WriteLine($"监控读取失败: {ex.Message}");
|
|
|
|
|
|
}
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
2026-05-20 13:49:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ======================= 测试前:获取初始铂丝电阻 =======================
|
|
|
|
|
|
private async Task<double> GetInitialResistanceAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!await _plcService.IsConnectedAsync())
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
try
|
2026-04-18 19:00:34 +08:00
|
|
|
|
{
|
2026-05-20 13:49:45 +08:00
|
|
|
|
float rawResistance = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Resistance);
|
|
|
|
|
|
return rawResistance / 1000.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
2026-05-15 21:10:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ======================= 核心测试流程 =======================
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private async Task StartTestAsync()
|
|
|
|
|
|
{
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// ========== 第1阶段:测试前置检查(标准7.1、7.6、1.4、8.1) ==========
|
2026-05-15 21:10:42 +08:00
|
|
|
|
if (!IsCleanConfirmed || !BubbleRemoved || !PlatinumCompatible || !AmbientCalibrated)
|
2026-04-18 19:00:34 +08:00
|
|
|
|
{
|
2026-05-15 21:10:42 +08:00
|
|
|
|
MessageBox.Show("请完成所有测试前确认项(清洁、排泡、铂兼容性、环境校准)。", "前置条件未满足");
|
2026-04-18 19:00:34 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (SampleVolume <= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请输入有效的样品量(≥1 mL)。", "参数错误");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-05-20 13:49:45 +08:00
|
|
|
|
|
|
|
|
|
|
// 加压条件检查(标准1.8、附录A2)
|
2026-04-18 19:00:34 +08:00
|
|
|
|
if (UsePressure && PressureValue <= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请设置有效的加压值(>0 kPa)。", "参数错误");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (IsTesting)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("测试正在进行中,请稍后...", "提示");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 连接PLC
|
2026-04-18 19:00:34 +08:00
|
|
|
|
if (!await _plcService.IsConnectedAsync())
|
|
|
|
|
|
{
|
|
|
|
|
|
var connected = await _plcService.ConnectAsync();
|
|
|
|
|
|
if (!connected)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("无法连接到PLC,请检查配置。", "错误");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// ========== 第2阶段:加压控制(标准1.7-1.8、附录A2) ==========
|
2026-05-15 21:10:42 +08:00
|
|
|
|
if (UsePressure)
|
|
|
|
|
|
{
|
2026-05-20 13:49:45 +08:00
|
|
|
|
StatusMessage = "正在加压...";
|
2026-05-15 21:10:42 +08:00
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, true);
|
2026-05-20 13:49:45 +08:00
|
|
|
|
await Task.Delay(3000);
|
2026-05-15 21:10:42 +08:00
|
|
|
|
await UpdateRealTimeParametersAsync();
|
|
|
|
|
|
if (ChamberPressure < PressureValue - 5)
|
|
|
|
|
|
MessageBox.Show($"压力未达到设定值 {PressureValue} kPa,当前 {ChamberPressure:F1} kPa", "警告");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// ========== 第3阶段:获取初始铂丝电阻 R₀(用于校准) ==========
|
|
|
|
|
|
double initialResistance = await GetInitialResistanceAsync();
|
|
|
|
|
|
if (initialResistance > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
StatusMessage = $"初始电阻已读取: {initialResistance:F4} Ω";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== 第4阶段:执行10次重复测量(标准4.1、5.4) ==========
|
2026-04-18 19:00:34 +08:00
|
|
|
|
Measurements.Clear();
|
|
|
|
|
|
IsTesting = true;
|
|
|
|
|
|
StatusMessage = "开始测试...";
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 1; i <= _config.TestParameters.MeasurementCount; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
CurrentMeasurementIndex = i;
|
|
|
|
|
|
StatusMessage = $"正在执行第 {i} 次测量...";
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 4.1 发送加热脉冲(标准5.4:短时电流施加)
|
2026-05-15 20:39:11 +08:00
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, true);
|
2026-05-20 13:49:45 +08:00
|
|
|
|
//await Task.Delay(500);
|
|
|
|
|
|
//await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
|
2026-04-18 19:00:34 +08:00
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 4.2 等待测量完成(标准5.3:0.8秒测试时间)
|
|
|
|
|
|
await Task.Delay(800);
|
2026-04-18 19:00:34 +08:00
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 4.3 读取计算结果(标准1.2:λ和α直接测量)
|
2026-04-18 19:00:34 +08:00
|
|
|
|
float lambda = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalConductivity);
|
|
|
|
|
|
float alpha = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalDiffusivity);
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 记录测试温度
|
|
|
|
|
|
if (i == 1) TestTemperature = CurrentTestTemperature;
|
2026-05-15 21:10:42 +08:00
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 生成温升曲线
|
2026-05-15 21:10:42 +08:00
|
|
|
|
GenerateTemperatureCurve(lambda, alpha);
|
|
|
|
|
|
|
2026-04-18 19:00:34 +08:00
|
|
|
|
var result = new MeasurementResult
|
|
|
|
|
|
{
|
|
|
|
|
|
Index = i,
|
|
|
|
|
|
ThermalConductivity = lambda,
|
|
|
|
|
|
ThermalDiffusivity = alpha
|
|
|
|
|
|
};
|
|
|
|
|
|
result.CalculateVhc();
|
|
|
|
|
|
|
2026-05-15 21:10:42 +08:00
|
|
|
|
Application.Current.Dispatcher.Invoke(() => Measurements.Add(result));
|
2026-04-18 19:00:34 +08:00
|
|
|
|
StatusMessage = $"第 {i} 次测量完成,λ={lambda:F4} W/m·K";
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 4.4 间隔30秒(标准5.4)
|
2026-04-18 19:00:34 +08:00
|
|
|
|
if (i < _config.TestParameters.MeasurementCount)
|
|
|
|
|
|
await Task.Delay(_config.TestParameters.IntervalSeconds * 1000);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 计算平均值
|
2026-04-18 19:00:34 +08:00
|
|
|
|
CalculateAverages();
|
|
|
|
|
|
StatusMessage = "测试完成。";
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
StatusMessage = $"测试出错: {ex.Message}";
|
|
|
|
|
|
MessageBox.Show($"测试过程中发生错误: {ex.Message}", "错误");
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// ========== 第5阶段:测试结束后泄压 ==========
|
2026-05-15 21:10:42 +08:00
|
|
|
|
if (UsePressure)
|
|
|
|
|
|
{
|
|
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, false);
|
|
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, true);
|
|
|
|
|
|
await Task.Delay(1000);
|
|
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, false);
|
|
|
|
|
|
}
|
2026-04-18 19:00:34 +08:00
|
|
|
|
IsTesting = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private async Task StopTestCommandAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (IsTesting)
|
|
|
|
|
|
{
|
|
|
|
|
|
IsTesting = false;
|
|
|
|
|
|
StatusMessage = "已停止测试。";
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!IsTesting)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("没有正在进行的测试。", "提示");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await Task.Delay(500);
|
|
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
|
|
|
|
|
|
// 泄压
|
|
|
|
|
|
if (UsePressure)
|
|
|
|
|
|
{
|
|
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, false);
|
|
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, true);
|
|
|
|
|
|
await Task.Delay(1000);
|
|
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
IsTesting = false;
|
|
|
|
|
|
StatusMessage = "测试已停止。";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ======================= 辅助方法 =======================
|
|
|
|
|
|
private async Task UpdateRealTimeParametersAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!await _plcService.IsConnectedAsync())
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// 压力(D1322,0.1kPa单位)
|
|
|
|
|
|
float rawPressure = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Pressure);
|
|
|
|
|
|
ChamberPressure = rawPressure / 10.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
StatusMessage = $"实时参数读取失败: {ex.Message}";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-15 10:59:24 +08:00
|
|
|
|
private void GenerateTemperatureCurve(float lambda, float alpha)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (TemperatureCurveModel == null)
|
|
|
|
|
|
{
|
2026-05-15 21:10:42 +08:00
|
|
|
|
TemperatureCurveModel = new PlotModel { Title = "温升曲线对比", Background = OxyColors.White };
|
|
|
|
|
|
TemperatureCurveModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "时间 (s)", Minimum = 0, Maximum = 2 });
|
|
|
|
|
|
TemperatureCurveModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "温升 (℃)", Minimum = 0 });
|
2026-05-15 10:59:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var series = new LineSeries
|
|
|
|
|
|
{
|
|
|
|
|
|
Title = $"第{CurrentMeasurementIndex}次测量",
|
|
|
|
|
|
Color = GetColorForIndex(CurrentMeasurementIndex),
|
2026-05-15 21:10:42 +08:00
|
|
|
|
StrokeThickness = 1.5
|
2026-05-15 10:59:24 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 理论公式 ΔT = (Q/(4πλL)) * ln(t/t0) + C
|
|
|
|
|
|
double Q = 0.01;
|
2026-05-15 21:10:42 +08:00
|
|
|
|
double L = _config.TestParameters.PlatinumWireLength;
|
2026-05-15 10:59:24 +08:00
|
|
|
|
double constant = 0.2;
|
2026-05-15 21:10:42 +08:00
|
|
|
|
for (int i = 1; i <= 200; i++)
|
2026-05-15 10:59:24 +08:00
|
|
|
|
{
|
|
|
|
|
|
double t = i * 0.01;
|
|
|
|
|
|
double deltaT = (Q / (4 * Math.PI * lambda * L)) * Math.Log(t + 0.1) + constant;
|
|
|
|
|
|
series.Points.Add(new DataPoint(t, deltaT));
|
|
|
|
|
|
}
|
|
|
|
|
|
TemperatureCurveModel.Series.Add(series);
|
|
|
|
|
|
TemperatureCurveModel.InvalidatePlot(true);
|
|
|
|
|
|
CurveTitle = $"已完成 {CurrentMeasurementIndex} 次测量";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private OxyColor GetColorForIndex(int index)
|
|
|
|
|
|
{
|
2026-05-15 21:10:42 +08:00
|
|
|
|
var colors = new[] { OxyColors.Red, OxyColors.Blue, OxyColors.Green, OxyColors.Orange, OxyColors.Purple, OxyColors.Brown, OxyColors.Pink, OxyColors.Cyan, OxyColors.Magenta, OxyColors.Olive };
|
2026-05-15 10:59:24 +08:00
|
|
|
|
return colors[(index - 1) % colors.Length];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-18 19:00:34 +08:00
|
|
|
|
private void CalculateAverages()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Measurements.Count == 0) return;
|
|
|
|
|
|
AverageThermalConductivity = Measurements.Average(m => m.ThermalConductivity);
|
|
|
|
|
|
AverageThermalDiffusivity = Measurements.Average(m => m.ThermalDiffusivity);
|
|
|
|
|
|
AverageVolumetricHeatCapacity = Measurements.Average(m => m.VolumetricHeatCapacity);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// ======================= UI命令 =======================
|
2026-04-18 19:00:34 +08:00
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void Reset()
|
|
|
|
|
|
{
|
|
|
|
|
|
Measurements.Clear();
|
2026-05-15 21:10:42 +08:00
|
|
|
|
AverageThermalConductivity = AverageThermalDiffusivity = AverageVolumetricHeatCapacity = 0;
|
2026-04-18 19:00:34 +08:00
|
|
|
|
CurrentMeasurementIndex = 0;
|
|
|
|
|
|
StatusMessage = "已重置";
|
|
|
|
|
|
TestDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
2026-05-15 21:10:42 +08:00
|
|
|
|
TemperatureCurveModel = null;
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private async Task GenerateReportAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Measurements.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("没有测试数据,请先执行测试。", "提示");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var extraParams = new Dictionary<string, object>
|
|
|
|
|
|
{
|
|
|
|
|
|
["SampleVolume"] = SampleVolume,
|
|
|
|
|
|
["BubbleRemoved"] = BubbleRemoved,
|
|
|
|
|
|
["UsePressure"] = UsePressure,
|
|
|
|
|
|
["PressureValue"] = PressureValue,
|
|
|
|
|
|
["IsCleanConfirmed"] = IsCleanConfirmed,
|
|
|
|
|
|
["CleanerName"] = CleanerName,
|
|
|
|
|
|
["AmbientTemperature"] = AmbientTemperature,
|
|
|
|
|
|
["AmbientCalibrated"] = AmbientCalibrated,
|
|
|
|
|
|
["PlatinumCompatible"] = PlatinumCompatible,
|
2026-05-20 13:49:45 +08:00
|
|
|
|
["LiquidReactivityNote"] = LiquidReactivityNote,
|
|
|
|
|
|
["InitialResistance"] = PlatinumResistance // 测试前的初始电阻
|
2026-04-18 19:00:34 +08:00
|
|
|
|
};
|
2026-05-15 21:10:42 +08:00
|
|
|
|
string reportPath = await _reportService.GenerateReportAsync(SampleId, TestTemperature, Measurements.ToList(),
|
|
|
|
|
|
AverageThermalConductivity, AverageThermalDiffusivity, AverageVolumetricHeatCapacity,
|
|
|
|
|
|
_config.TestParameters, extraParams);
|
2026-04-18 19:00:34 +08:00
|
|
|
|
MessageBox.Show($"报告已生成:{reportPath}", "成功");
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show($"生成报告失败:{ex.Message}", "错误");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
// 控制命令
|
2026-04-18 19:00:34 +08:00
|
|
|
|
[RelayCommand]
|
2026-05-15 21:10:42 +08:00
|
|
|
|
private async Task PressureCalibrationAsync()
|
2026-04-18 19:00:34 +08:00
|
|
|
|
{
|
2026-05-15 21:10:42 +08:00
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.PressureCalibrationCoil, true);
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
[RelayCommand]
|
2026-05-15 21:10:42 +08:00
|
|
|
|
private async Task ResistanceZeroAsync()
|
2026-04-18 19:00:34 +08:00
|
|
|
|
{
|
2026-05-15 21:10:42 +08:00
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.ResistanceZeroCoil, true);
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
2026-05-15 21:10:42 +08:00
|
|
|
|
private async Task InletValveControlAsync()
|
2026-04-18 19:00:34 +08:00
|
|
|
|
{
|
2026-05-15 21:10:42 +08:00
|
|
|
|
await EnsureConnected();
|
|
|
|
|
|
bool current = await _plcService.ReadCoilAsync(_config.PlcRegisterAddresses.InletValveCoil);
|
|
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, !current);
|
2026-05-20 13:49:45 +08:00
|
|
|
|
StatusMessage = $"进气阀已{(current ? "关闭" : "开启")}";
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
2026-05-15 21:10:42 +08:00
|
|
|
|
private async Task OutletValveControlAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
await EnsureConnected();
|
|
|
|
|
|
bool current = await _plcService.ReadCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil);
|
|
|
|
|
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, !current);
|
2026-05-20 13:49:45 +08:00
|
|
|
|
StatusMessage = $"排气阀已{(current ? "关闭" : "开启")}";
|
2026-05-15 21:10:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand] private void ConfirmBubbleRemoved() => BubbleRemoved = true;
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void ConfirmClean()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(CleanerName))
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请输入清洁人员姓名。", "提示");
|
|
|
|
|
|
return;
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
2026-05-15 21:10:42 +08:00
|
|
|
|
IsCleanConfirmed = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
[RelayCommand] private void ConfirmPlatinumCompatible() => PlatinumCompatible = true;
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private async Task CalibrateAmbientAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
await EnsureConnected();
|
|
|
|
|
|
float temp = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Temperature);
|
2026-04-18 19:00:34 +08:00
|
|
|
|
AmbientTemperature = temp;
|
|
|
|
|
|
AmbientCalibrated = true;
|
|
|
|
|
|
StatusMessage = $"环境温度校准完成:{AmbientTemperature:F1} °C";
|
|
|
|
|
|
}
|
2026-05-20 13:49:45 +08:00
|
|
|
|
[RelayCommand] private async Task PerformSystemCalibrationAsync() { /* 系统校准逻辑 */ }
|
2026-05-15 10:59:24 +08:00
|
|
|
|
|
2026-05-20 13:49:45 +08:00
|
|
|
|
private async Task EnsureConnected()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!await _plcService.IsConnectedAsync())
|
|
|
|
|
|
await _plcService.ConnectAsync();
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|