Files
VacuumPressureMembranePoreS…/ViewModels/BubblePointViewModel.cs
2026-04-14 21:40:09 +08:00

420 lines
14 KiB
C#
Raw Permalink 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.
using MembranePoreTester.Communication;
using MembranePoreTester.Helpers;
using MembranePoreTester.Models;
using Microsoft.Win32;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
namespace MembranePoreTester.ViewModels
{
public class BubblePointViewModel : ViewModelBase
{
private BubblePointRecord _record = new();
private TestLiquid _selectedLiquid;
private bool _isCustomLiquid;
private double _customSurfaceTension = 30.0;
// 添加字段
private readonly IPlcService _plcService;
private readonly PlcConfiguration _plcConfig;
public ICommand ReadPlcCommand { get; }
public BubblePointRecord Record
{
get => _record;
set => SetProperty(ref _record, value);
}
// 初始化,确保 StationId 在读取PLC前已设置
public void Initialize(int stationId)
{
StationId = stationId;
// 延迟读取当前PLC值以确保连接稳定
Task.Run(async () =>
{
await Task.Delay(200);
await ReadCurrentPlcAsync();
await ReadSpeedRateAsync();
});
}
public IReadOnlyList<TestLiquid> Liquids => TestLiquid.Predefined;
public List<string> PressureUnits => new() { "Pa", "cmHg", "psi" };
public List<string> MembraneTypes => new() { "中空纤维膜" };
public TestLiquid SelectedLiquid
{
get => _selectedLiquid;
set
{
if (SetProperty(ref _selectedLiquid, value))
{
Record.Liquid = value;
OnPropertyChanged(nameof(Record.MaxPoreSize));
}
}
}
public bool IsCustomLiquid
{
get => _isCustomLiquid;
set
{
if (SetProperty(ref _isCustomLiquid, value))
{
UpdateCustomLiquid();
}
}
}
public double CustomSurfaceTension
{
get => _customSurfaceTension;
set
{
if (SetProperty(ref _customSurfaceTension, value))
{
UpdateCustomLiquid();
}
}
}
private void UpdateCustomLiquid()
{
if (IsCustomLiquid)
{
Record.Liquid = new TestLiquid
{
Name = "自定义",
SurfaceTension = CustomSurfaceTension
};
OnPropertyChanged(nameof(Record.MaxPoreSize));
}
}
public ICommand CalculateCommand { get; }
public ICommand GenerateReportCommand { get; }
public ICommand OpenPressureCalibCommand { get; }
public ICommand OpenPressureCalibCommand2 { get; }
private System.Windows.Threading.DispatcherTimer _timer; // 添加定时器字段
public BubblePointViewModel()
{
if (IsInDesignMode())
{
return; // 设计时跳过PLC初始化
}
_plcService = App.PlcService;
_plcConfig = App.PlcConfig;
CalculateCommand = new RelayCommand(Calculate);
GenerateReportCommand = new RelayCommand(GenerateReport);
SelectedLiquid = Liquids[0];
Record.SampleType = "中空纤维膜";
ReadPlcCommand = new RelayCommand(async () => await ReadPlcAsync());
SaveCommand = new RelayCommand(SaveToDatabase);
ExportCommand = new RelayCommand(ExportToExcel);
OpenPressureCalibCommand = new RelayCommand(OpenPressureCalibration);
OpenPressureCalibCommand2 = new RelayCommand(OpenPressureCalibration2);
// 启动定时器,每秒读取一次
_timer = new System.Windows.Threading.DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(1);
_timer.Tick += async (s, e) =>
{
if (StationId > 0 && !IsDisposed)
{
await ReadCurrentPlcAsync();
await ReadSpeedRateAsync(); // 新增:读取加压速率
}
};
_timer.Start();
//// 立即读取一次
//Task.Run(async () =>
//{
// await Task.Delay(1000); // 等待2秒确保PLC连接稳定
// await ReadCurrentPlcAsync();
//}
//);
}
// 新增:读取加压速率并赋值给 Record.SpeedRate1
private async Task ReadSpeedRateAsync()
{
try
{
float speedRate = 0;
ushort address = 0;
switch (StationId)
{
case 1:
address = _plcConfig.HPCoeff11;
speedRate = await _plcService.ReadFloatAsync(address);
Record.SpeedRate1 = speedRate.ToString("F3");
break;
case 2:
address = _plcConfig.HPCoeff12;
speedRate = await _plcService.ReadFloatAsync(address);
Record.SpeedRate1 = speedRate.ToString("F3");
break;
case 3:
address = _plcConfig.HPCoeff13;
speedRate = await _plcService.ReadFloatAsync(address);
Record.SpeedRate1 = speedRate.ToString("F3");
break;
}
OnPropertyChanged(nameof(Record));
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"读取加压速率失败: {ex.Message}");
}
}
public override void Dispose()
{
_timer?.Stop();
base.Dispose();
}
private async Task ReadCurrentPlcAsync()
{
await SafeExecuteAsync("ReadCurrentPressure", async () =>
{
if (IsDisposed || _plcService == null) return;
await Task.Delay(100); // 小延迟避免过快读取
float rawPressure = await _plcService.ReadPressureAsync(StationId);
Record.BubbleCurrentPressure = Math.Round(rawPressure, 2);
OnPropertyChanged(nameof(Record.BubbleCurrentPressure));
});
}
private async Task ReadPlcAsync()
{
try
{
double rawPressure = await _plcService.ReadPressureAsync(StationId);
rawPressure = Math.Round((double)rawPressure, 2);
double pressure = rawPressure * _plcConfig.PressureFactor;
// 更新当前压力显示
Record.BubbleCurrentPressure = pressure;
// 同时将泡点压力设为该值(符合涨破测试逻辑)
Record.BubblePointPressure = pressure;
OnPropertyChanged(nameof(Record.BubblePointPressure));
OnPropertyChanged(nameof(Record.BubbleCurrentPressure));
}
catch (Exception ex)
{
MessageBox.Show($"读取PLC失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
public double MaxPoreSize => Record.MaxPoreSize;
private void Calculate()
{
// 触发最大孔径重新计算(通过绑定已自动刷新)
OnPropertyChanged(nameof(Record.MaxPoreSize));
}
private void GenerateReport()
{
ReportGenerator.GenerateBubblePointReport(Record);
}
public void UpdateBubblePointPressure(double pressure)
{
Record.BubblePointPressure = pressure;
OnPropertyChanged(nameof(Record.BubblePointPressure));
OnPropertyChanged(nameof(MaxPoreSize)); // 最大孔径依赖于压力
}
private int _stationId;
public int StationId
{
get => _stationId;
set => SetProperty(ref _stationId, value);
}
// 保存当前记录到数据库
public void SaveToDatabase()
{
var entity = new BubblePointEntity
{
StationId = StationId,
TestDate = Record.TestDate,
Tester = Record.Tester ?? "系统操作员",
SampleType = Record.SampleType ?? "缺省值",
SampleSpec = Record.SampleSpec ?? "缺省值",
RoomTemperature = Record.RoomTemperature,
SoakingTime = Record.SoakingTime,
LiquidName = Record.Liquid?.Name ?? "缺省值",
LiquidSurfaceTension = Record.Liquid?.SurfaceTension ?? 0,
LiquidManufacturer = Record.LiquidManufacturer,
BubblePointPressure = Record.BubblePointPressure,
PressureUnit = Record.PressureUnit,
MaxPoreSize = Record.MaxPoreSize
};
using var db = new AppDbContext();
db.BubblePointRecords.Add(entity);
db.SaveChanges();
MessageBox.Show("保存成功!");
}
public void LoadFromDatabase(int recordId)
{
using var db = new AppDbContext();
var entity = db.BubblePointRecords.Find(recordId);
if (entity == null) return;
Record.SampleType = entity.SampleType ?? "中空纤维膜";
Record.SampleSpec = entity.SampleSpec;
Record.RoomTemperature = entity.RoomTemperature ?? 0;
Record.SoakingTime = entity.SoakingTime ?? 0;
Record.Liquid = TestLiquid.Predefined.FirstOrDefault(l => l.Name == entity.LiquidName)
?? new TestLiquid { Name = entity.LiquidName, SurfaceTension = entity.LiquidSurfaceTension ?? 0 };
Record.LiquidManufacturer = entity.LiquidManufacturer;
Record.BubblePointPressure = entity.BubblePointPressure ?? 0;
Record.PressureUnit = entity.PressureUnit;
Record.TestDate = entity.TestDate;
Record.Tester = entity.Tester;
OnPropertyChanged(nameof(Record));
OnPropertyChanged(nameof(MaxPoreSize)); // 触发界面更新
}
public ICommand SaveCommand { get; }
public ICommand ExportCommand { get; }
private void OpenPressureCalibration()
{
// 弹出确认对话框
var result = MessageBox.Show(
"确定要进行压力校准吗此操作将向PLC写入校准信号。",
"确认校准",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
if (result != MessageBoxResult.Yes)
return;
ushort address = new ushort();
switch (StationId)
{
case 1:
{
address = _plcConfig.High1;
break;
}
case 2:
{
address = _plcConfig.High2;
break;
}
case 3:
{
address = _plcConfig.High3;
break;
}
}
Task.Run(async () =>
{
await _plcService.WriteCoilAsync(address, true);
//MessageBox.Show("校准成功!");
});
}
private void OpenPressureCalibration2()
{
// 弹出确认对话框
var result = MessageBox.Show(
"确定要进行压力校准吗此操作将向PLC写入校准信号。",
"确认校准",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
ushort address = new ushort();
switch (StationId)
{
case 1:
{
address = _plcConfig.Low1;
break;
}
case 2:
{
address = _plcConfig.Low2;
break;
}
case 3:
{
address = _plcConfig.Low3;
break;
}
}
Task.Run(async () =>
{
await _plcService.WriteCoilAsync(address, true);
// MessageBox.Show("校准成功!");
});
}
private void ExportToExcel()
{
var saveFileDialog = new SaveFileDialog
{
Filter = "Excel文件|*.xlsx",
FileName = $"泡点法_工位{StationId}_{DateTime.Now:yyyyMMddHHmmss}.xlsx"
};
if (saveFileDialog.ShowDialog() == true)
{
// 将 Record 转换为 Entity
var entity = new BubblePointEntity
{
StationId = this.StationId,
TestDate = Record.TestDate,
Tester = Record.Tester,
SampleType = Record.SampleType,
SampleSpec = Record.SampleSpec,
RoomTemperature = Record.RoomTemperature,
SoakingTime = Record.SoakingTime,
LiquidName = Record.Liquid?.Name,
LiquidSurfaceTension = Record.Liquid?.SurfaceTension,
LiquidManufacturer = Record.LiquidManufacturer,
BubblePointPressure = Record.BubblePointPressure,
PressureUnit = Record.PressureUnit,
MaxPoreSize = Record.MaxPoreSize
};
ExportHelper.ExportBubblePoint(entity, saveFileDialog.FileName);
MessageBox.Show("导出成功");
}
}
}
}