381 lines
13 KiB
C#
381 lines
13 KiB
C#
using System;
|
||
using System.Collections.ObjectModel;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
using CommunityToolkit.Mvvm.ComponentModel;
|
||
using CommunityToolkit.Mvvm.Input;
|
||
using ASTM_D7896_Tester.Models;
|
||
using ASTM_D7896_Tester.Services;
|
||
using ASTM_D7896_Tester.Helpers;
|
||
using System.Linq;
|
||
using System.IO;
|
||
|
||
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;
|
||
|
||
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;
|
||
}
|
||
|
||
// ========== 原有命令 ==========
|
||
[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;
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
CalculateAverages();
|
||
StatusMessage = "测试完成。";
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
StatusMessage = $"测试出错: {ex.Message}";
|
||
MessageBox.Show($"测试过程中发生错误: {ex.Message}", "错误");
|
||
}
|
||
finally
|
||
{
|
||
IsTesting = false;
|
||
await _plcService.DisconnectAsync();
|
||
}
|
||
}
|
||
|
||
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");
|
||
|
||
// 重置确认标志(可根据需要决定是否重置)
|
||
// IsCleanConfirmed = false;
|
||
// BubbleRemoved = false;
|
||
// PlatinumCompatible = false;
|
||
// AmbientCalibrated = false;
|
||
}
|
||
|
||
[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;
|
||
}
|
||
}
|
||
} |