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;
|
2026-04-18 19:00:34 +08:00
|
|
|
|
using System.IO;
|
2026-05-15 10:59:24 +08:00
|
|
|
|
using System.Linq;
|
|
|
|
|
|
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
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly IPlcCommunicationService _plcService;
|
|
|
|
|
|
private readonly ReportService _reportService;
|
|
|
|
|
|
private AppConfig _config;
|
|
|
|
|
|
|
|
|
|
|
|
public ObservableCollection<string> ReferenceLiquids { get; } = new ObservableCollection<string> { "蒸馏水", "甲苯", "乙二醇" };
|
|
|
|
|
|
|
|
|
|
|
|
// ========== 原有属性 ==========
|
|
|
|
|
|
[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;
|
|
|
|
|
|
|
|
|
|
|
|
// ========== 新增属性(补充缺失功能) ==========
|
|
|
|
|
|
// 章节7.5:样品量 (mL)
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private double _sampleVolume = 40.0;
|
|
|
|
|
|
|
|
|
|
|
|
// 章节7.6:排气泡确认
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private bool _bubbleRemoved = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 附录A2:加压测试
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private bool _usePressure = false;
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private double _pressureValue = 0.0; // kPa
|
|
|
|
|
|
|
|
|
|
|
|
// 章节7.1:清洁确认
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private bool _isCleanConfirmed = false;
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private string _cleanerName = "";
|
|
|
|
|
|
|
|
|
|
|
|
// 章节8.1:环境温度校准
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private double _ambientTemperature = 25.0;
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private bool _ambientCalibrated = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 章节1.4:铂反应性确认
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private bool _platinumCompatible = false;
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private string _liquidReactivityNote = "";
|
|
|
|
|
|
|
|
|
|
|
|
// 系统校准模块(章节A3)相关
|
|
|
|
|
|
[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;
|
|
|
|
|
|
|
2026-05-15 10:59:24 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 新增核心参数(实时显示)
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private double _platinumVoltage; // 铂丝电压 U_pt (V)
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private double _standardResistorVoltage; // 标准电阻电压 U_std (V)
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private double _platinumResistance; // 铂丝电阻 R_pt (Ω)
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private double _chamberPressure; // 样品池压力 (kPa)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 当前曲线标题
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private string _curveTitle = "温升曲线";
|
|
|
|
|
|
|
|
|
|
|
|
// 在 ViewModel 中
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private PlotModel _temperatureCurveModel;
|
|
|
|
|
|
|
2026-04-18 19:00:34 +08:00
|
|
|
|
public D7896ViewModel()
|
|
|
|
|
|
{
|
|
|
|
|
|
_config = JsonConfigHelper.LoadConfig();
|
|
|
|
|
|
_plcService = new PlcCommunicationService();
|
|
|
|
|
|
_reportService = new ReportService(_config.TestParameters.ReportOutputPath);
|
|
|
|
|
|
|
|
|
|
|
|
// 加载配置中的默认值
|
|
|
|
|
|
SampleVolume = _config.TestParameters.DefaultSampleVolume;
|
|
|
|
|
|
UsePressure = _config.TestParameters.UsePressure;
|
|
|
|
|
|
PressureValue = _config.TestParameters.DefaultPressure;
|
|
|
|
|
|
SelectedReferenceLiquid = _config.TestParameters.ReferenceLiquid;
|
|
|
|
|
|
ReferenceConductivity = _config.TestParameters.ReferenceConductivity;
|
2026-05-15 10:59:24 +08:00
|
|
|
|
IsCleanConfirmed = true;
|
|
|
|
|
|
BubbleRemoved = true;
|
|
|
|
|
|
PlatinumCompatible = true;
|
|
|
|
|
|
AmbientCalibrated = true;
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== 原有命令 ==========
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private async Task StartTestAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 增加前置条件检查:清洁、气泡、铂兼容性、环境校准、样品量
|
|
|
|
|
|
if (!IsCleanConfirmed)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请确认采样池已清洁干燥(章节7.1)。", "前置条件未满足");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!BubbleRemoved)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请确认已清除铂丝表面气泡(章节7.6)。", "前置条件未满足");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!PlatinumCompatible)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请确认所测液体不与铂发生反应(章节1.4)。", "前置条件未满足");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!AmbientCalibrated)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请先进行环境温度校准(章节8.1)。", "前置条件未满足");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (SampleVolume <= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请输入有效的样品量(≥1 mL)。", "参数错误");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (UsePressure && PressureValue <= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请设置有效的加压值(>0 kPa)。", "参数错误");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (IsTesting)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("测试正在进行中,请稍后...", "提示");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!await _plcService.IsConnectedAsync())
|
|
|
|
|
|
{
|
|
|
|
|
|
var connected = await _plcService.ConnectAsync();
|
|
|
|
|
|
if (!connected)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("无法连接到PLC,请检查配置。", "错误");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Measurements.Clear();
|
|
|
|
|
|
IsTesting = true;
|
|
|
|
|
|
StatusMessage = "开始测试...";
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 1; i <= _config.TestParameters.MeasurementCount; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
CurrentMeasurementIndex = i;
|
|
|
|
|
|
StatusMessage = $"正在执行第 {i} 次测量...";
|
|
|
|
|
|
|
|
|
|
|
|
await _plcService.WriteSingleCoilAsync(_config.PlcRegisterAddresses.StartCommand, true);
|
|
|
|
|
|
await Task.Delay(500);
|
|
|
|
|
|
await _plcService.WriteSingleCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
|
|
|
|
|
|
|
|
|
|
|
|
await Task.Delay(2000);
|
|
|
|
|
|
|
|
|
|
|
|
float lambda = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalConductivity);
|
|
|
|
|
|
float alpha = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalDiffusivity);
|
|
|
|
|
|
float temperature = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.TestTemperature);
|
|
|
|
|
|
|
|
|
|
|
|
if (i == 1) TestTemperature = temperature;
|
2026-05-15 10:59:24 +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();
|
|
|
|
|
|
|
|
|
|
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
Measurements.Add(result);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
StatusMessage = $"第 {i} 次测量完成,λ={lambda:F4} W/m·K";
|
|
|
|
|
|
|
|
|
|
|
|
if (i < _config.TestParameters.MeasurementCount)
|
|
|
|
|
|
{
|
|
|
|
|
|
await Task.Delay(_config.TestParameters.IntervalSeconds * 1000);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-15 10:59:24 +08:00
|
|
|
|
|
2026-04-18 19:00:34 +08:00
|
|
|
|
CalculateAverages();
|
|
|
|
|
|
StatusMessage = "测试完成。";
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
StatusMessage = $"测试出错: {ex.Message}";
|
|
|
|
|
|
MessageBox.Show($"测试过程中发生错误: {ex.Message}", "错误");
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
IsTesting = false;
|
|
|
|
|
|
await _plcService.DisconnectAsync();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-15 10:59:24 +08:00
|
|
|
|
|
|
|
|
|
|
// 模拟获取实时核心参数(实际应从PLC读取)
|
|
|
|
|
|
private async Task UpdateRealTimeParametersAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (await _plcService.IsConnectedAsync())
|
|
|
|
|
|
{
|
|
|
|
|
|
// 示例:从PLC读取这些值(地址需在配置文件中定义)
|
|
|
|
|
|
PlatinumVoltage = await _plcService.ReadFloatAsync(40010); // 假设地址
|
|
|
|
|
|
StandardResistorVoltage = await _plcService.ReadFloatAsync(40012);
|
|
|
|
|
|
PlatinumResistance = await _plcService.ReadFloatAsync(40014);
|
|
|
|
|
|
ChamberPressure = await _plcService.ReadFloatAsync(40016);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
private void GenerateTemperatureCurve(float lambda, float alpha)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 第一次调用时初始化 PlotModel(只创建一次)
|
|
|
|
|
|
if (TemperatureCurveModel == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
TemperatureCurveModel = new PlotModel
|
|
|
|
|
|
{
|
|
|
|
|
|
Title = "温升曲线对比 (10次测量)",
|
|
|
|
|
|
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
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建本次测量的曲线系列(用不同颜色区分)
|
|
|
|
|
|
var series = new LineSeries
|
|
|
|
|
|
{
|
|
|
|
|
|
Title = $"第{CurrentMeasurementIndex}次测量",
|
|
|
|
|
|
Color = GetColorForIndex(CurrentMeasurementIndex),
|
|
|
|
|
|
StrokeThickness = 1.5,
|
|
|
|
|
|
MarkerType = MarkerType.None
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 添加数据点(这里仍用模拟数据,实际应替换为真实采集数据)
|
|
|
|
|
|
// 理论公式:ΔT = (Q/(4πλL)) * ln(t/t0) + C
|
|
|
|
|
|
// 其中 Q 是加热功率,L 是铂丝长度,C 是常数
|
|
|
|
|
|
double Q = 0.01; // 假设 10mW,实际应从电流和电阻计算
|
|
|
|
|
|
double L = 0.04; // 40mm
|
|
|
|
|
|
double constant = 0.2;
|
|
|
|
|
|
for (int i = 0; i <= 200; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
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));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 将本次曲线添加到同一个 Model 中(叠加)
|
|
|
|
|
|
TemperatureCurveModel.Series.Add(series);
|
|
|
|
|
|
TemperatureCurveModel.InvalidatePlot(true);
|
|
|
|
|
|
CurveTitle = $"已完成 {CurrentMeasurementIndex} 次测量";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 辅助方法:根据测量序号返回不同的颜色
|
|
|
|
|
|
private OxyColor GetColorForIndex(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
var colors = new[]
|
|
|
|
|
|
{
|
|
|
|
|
|
OxyColors.Red, OxyColors.Blue, OxyColors.Green, OxyColors.Orange,
|
|
|
|
|
|
OxyColors.Purple, OxyColors.Brown, OxyColors.Pink, OxyColors.Cyan,
|
|
|
|
|
|
OxyColors.Magenta, OxyColors.Olive
|
|
|
|
|
|
};
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void Reset()
|
|
|
|
|
|
{
|
|
|
|
|
|
Measurements.Clear();
|
|
|
|
|
|
AverageThermalConductivity = 0;
|
|
|
|
|
|
AverageThermalDiffusivity = 0;
|
|
|
|
|
|
AverageVolumetricHeatCapacity = 0;
|
|
|
|
|
|
CurrentMeasurementIndex = 0;
|
|
|
|
|
|
StatusMessage = "已重置";
|
|
|
|
|
|
TestDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
2026-05-15 10:59:24 +08:00
|
|
|
|
TemperatureCurveModel = null; // 下次测量会重新初始化
|
2026-04-18 19:00:34 +08:00
|
|
|
|
// 重置确认标志(可根据需要决定是否重置)
|
2026-05-15 10:59:24 +08:00
|
|
|
|
|
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,
|
|
|
|
|
|
["LiquidReactivityNote"] = LiquidReactivityNote
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
string reportPath = await _reportService.GenerateReportAsync(
|
|
|
|
|
|
SampleId,
|
|
|
|
|
|
TestTemperature,
|
|
|
|
|
|
Measurements.ToList(),
|
|
|
|
|
|
AverageThermalConductivity,
|
|
|
|
|
|
AverageThermalDiffusivity,
|
|
|
|
|
|
AverageVolumetricHeatCapacity,
|
|
|
|
|
|
_config.TestParameters,
|
|
|
|
|
|
extraParams
|
|
|
|
|
|
);
|
|
|
|
|
|
MessageBox.Show($"报告已生成:{reportPath}", "成功");
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show($"生成报告失败:{ex.Message}", "错误");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== 新增命令:排气泡确认 ==========
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void ConfirmBubbleRemoved()
|
|
|
|
|
|
{
|
|
|
|
|
|
BubbleRemoved = true;
|
|
|
|
|
|
StatusMessage = "已确认清除气泡。";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== 新增命令:清洁确认 ==========
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void ConfirmClean()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(CleanerName))
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请输入清洁人员姓名。", "提示");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
IsCleanConfirmed = true;
|
|
|
|
|
|
StatusMessage = "已确认采样池清洁干燥。";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== 新增命令:铂兼容性确认 ==========
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void ConfirmPlatinumCompatible()
|
|
|
|
|
|
{
|
|
|
|
|
|
PlatinumCompatible = true;
|
|
|
|
|
|
StatusMessage = "已确认液体与铂兼容。";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== 新增命令:环境温度校准 ==========
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private async Task CalibrateAmbientAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!await _plcService.IsConnectedAsync())
|
|
|
|
|
|
{
|
|
|
|
|
|
await _plcService.ConnectAsync();
|
|
|
|
|
|
}
|
|
|
|
|
|
// 读取PLC当前环境温度(假设寄存器地址可配置)
|
|
|
|
|
|
// 这里简化:让用户手动输入或从PLC读取
|
|
|
|
|
|
// 为了演示,从PLC读取温度
|
|
|
|
|
|
float temp = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.TestTemperature);
|
|
|
|
|
|
AmbientTemperature = temp;
|
|
|
|
|
|
AmbientCalibrated = true;
|
|
|
|
|
|
StatusMessage = $"环境温度校准完成:{AmbientTemperature:F1} °C";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== 新增命令:系统校准(章节A3) ==========
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private async Task PerformSystemCalibrationAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (IsCalibrating)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("校准正在进行中...", "提示");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var result = MessageBox.Show($"将使用参考液 [{SelectedReferenceLiquid}] 进行系统校准。\n请确保传感器已浸入参考液中,并已清除气泡。\n是否继续?", "系统校准", MessageBoxButton.YesNo);
|
|
|
|
|
|
if (result != MessageBoxResult.Yes) return;
|
|
|
|
|
|
|
|
|
|
|
|
IsCalibrating = true;
|
|
|
|
|
|
CalibrationStatus = "正在测量参考液...";
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// 执行一次测量
|
|
|
|
|
|
if (!await _plcService.IsConnectedAsync())
|
|
|
|
|
|
await _plcService.ConnectAsync();
|
|
|
|
|
|
|
|
|
|
|
|
await _plcService.WriteSingleCoilAsync(_config.PlcRegisterAddresses.StartCommand, true);
|
|
|
|
|
|
await Task.Delay(500);
|
|
|
|
|
|
await _plcService.WriteSingleCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
|
|
|
|
|
|
await Task.Delay(2000);
|
|
|
|
|
|
|
|
|
|
|
|
float lambda = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalConductivity);
|
|
|
|
|
|
MeasuredConductivity = lambda;
|
|
|
|
|
|
CalibrationErrorPercent = Math.Abs((lambda - ReferenceConductivity) / ReferenceConductivity * 100);
|
|
|
|
|
|
|
|
|
|
|
|
CalibrationStatus = $"测量值: {MeasuredConductivity:F4} W/m·K, 参考值: {ReferenceConductivity:F4} W/m·K, 误差: {CalibrationErrorPercent:F2}%";
|
|
|
|
|
|
|
|
|
|
|
|
if (CalibrationErrorPercent <= 2.0)
|
|
|
|
|
|
MessageBox.Show($"校准成功!误差 {CalibrationErrorPercent:F2}% 在允许范围内(≤2%)。", "校准结果");
|
|
|
|
|
|
else
|
|
|
|
|
|
MessageBox.Show($"校准警告:误差 {CalibrationErrorPercent:F2}% 超出2%限值,请检查传感器或参考液。", "校准结果", MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
CalibrationStatus = $"校准失败: {ex.Message}";
|
|
|
|
|
|
MessageBox.Show($"校准失败: {ex.Message}", "错误");
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
IsCalibrating = false;
|
|
|
|
|
|
}
|
2026-05-15 10:59:24 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|
2026-05-15 10:59:24 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-04-18 19:00:34 +08:00
|
|
|
|
}
|