401 lines
13 KiB
C#
401 lines
13 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 List<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];
|
|
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();
|
|
}
|
|
|
|
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()
|
|
{
|
|
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);
|
|
});
|
|
}
|
|
|
|
private void OpenPressureCalibration2()
|
|
{
|
|
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);
|
|
});
|
|
}
|
|
|
|
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("导出成功");
|
|
}
|
|
}
|
|
}
|
|
} |