420 lines
14 KiB
C#
420 lines
14 KiB
C#
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("导出成功");
|
||
}
|
||
}
|
||
}
|
||
} |