添加项目文件。

This commit is contained in:
xyy
2026-04-18 19:00:34 +08:00
parent 1d8ffa7192
commit 4f85aeee2f
19 changed files with 1084 additions and 0 deletions

View File

@@ -0,0 +1,381 @@
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;
}
}
}

View File

@@ -0,0 +1,26 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace ASTM_D7896_Tester.ViewModels;
public partial class MeasurementResult : ObservableObject
{
[ObservableProperty]
private int _index;
[ObservableProperty]
private double _thermalConductivity; // W/m·K
[ObservableProperty]
private double _thermalDiffusivity; // ×10⁻⁶ m²/s
[ObservableProperty]
private double _volumetricHeatCapacity; // kJ/m³·K (自动计算)
public void CalculateVhc()
{
if (_thermalDiffusivity > 0)
VolumetricHeatCapacity = _thermalConductivity / (_thermalDiffusivity * 1e-6) / 1000.0;
else
VolumetricHeatCapacity = 0;
}
}