This commit is contained in:
GukSang.Jin
2026-05-16 18:17:48 +08:00
3 changed files with 149 additions and 0 deletions

View File

@@ -43,8 +43,10 @@
public ushort DissolutionStartCoil { get; set; }
public ushort Dissolution1StartCoil { get; set; }
public ushort Dissolution1StopCoil { get; set; }
public ushort Dissolution1SampleAckCoil { get; set; }
public ushort Dissolution2StartCoil { get; set; }
public ushort Dissolution2StopCoil { get; set; }
public ushort Dissolution2SampleAckCoil { get; set; }
public ushort Dissolution1Time { get; set; }
public ushort Dissolution2Time { get; set; }
}

View File

@@ -8,6 +8,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using TabletTester2025.Models;
using TabletTester2025.Services;
@@ -35,6 +37,10 @@ namespace TabletTester2025.ViewModels
private DateTime _dissolution2StartTime = DateTime.MinValue;
private bool _isDissolution1Running;
private bool _isDissolution2Running;
private bool _dissolution1SampleRequestActive;
private bool _dissolution2SampleRequestActive;
private bool _isDissolution1SamplePromptOpen;
private bool _isDissolution2SamplePromptOpen;
private string _dissolutionResultChannel = "";
private double _dissolutionResultRate30Min;
private double _dissolutionResultRSquared;
@@ -309,10 +315,16 @@ namespace TabletTester2025.ViewModels
DisintegrationTemp = await _plc.ReadFloatAsync(_plcConfig.DisintegrationTemp);
if (_isDissolution1Running)
{
await CheckDissolutionSampleAsync(1);
updated |= await ReadDissolutionChannelAsync(1);
}
if (_isDissolution2Running)
{
await CheckDissolutionSampleAsync(2);
updated |= await ReadDissolutionChannelAsync(2);
}
UpdateDissolutionClock();
@@ -320,6 +332,129 @@ namespace TabletTester2025.ViewModels
DissolutionPlotModel.InvalidatePlot(true);
}
private async Task CheckDissolutionSampleAsync(int channel)
{
ushort coilAddress = channel == 1
? _plcConfig.Dissolution1SampleAckCoil
: _plcConfig.Dissolution2SampleAckCoil;
if (coilAddress == 0)
{
DissolutionCurveStatus = $"溶出{channel}取样确认线圈未配置";
return;
}
bool sampleConfirmed = await _plc.ReadCoilAsync(coilAddress);
if (sampleConfirmed)
{
SetDissolutionSampleRequestActive(channel, false);
return;
}
if (IsDissolutionSampleRequestActive(channel) || IsDissolutionSamplePromptOpen(channel))
return;
SetDissolutionSampleRequestActive(channel, true);
SetDissolutionSamplePromptOpen(channel, true);
try
{
await ShowDissolutionSampleDialogAsync(channel);
await _plc.WriteCoilAsync(coilAddress, true);
LocalAlarm = $"溶出{channel}已确认取样";
DissolutionCurveStatus = "";
}
catch (Exception ex)
{
SetDissolutionSampleRequestActive(channel, false);
await App.Current.Dispatcher.InvokeAsync(() =>
MessageBox.Show($"溶出{channel}取样确认失败:{ex.Message}", "取样确认失败", MessageBoxButton.OK, MessageBoxImage.Error));
}
finally
{
SetDissolutionSamplePromptOpen(channel, false);
}
}
private bool IsDissolutionSampleRequestActive(int channel)
{
return channel == 1 ? _dissolution1SampleRequestActive : _dissolution2SampleRequestActive;
}
private void SetDissolutionSampleRequestActive(int channel, bool value)
{
if (channel == 1)
_dissolution1SampleRequestActive = value;
else
_dissolution2SampleRequestActive = value;
}
private bool IsDissolutionSamplePromptOpen(int channel)
{
return channel == 1 ? _isDissolution1SamplePromptOpen : _isDissolution2SamplePromptOpen;
}
private void SetDissolutionSamplePromptOpen(int channel, bool value)
{
if (channel == 1)
_isDissolution1SamplePromptOpen = value;
else
_isDissolution2SamplePromptOpen = value;
}
private async Task ShowDissolutionSampleDialogAsync(int channel)
{
bool confirmed = await App.Current.Dispatcher.InvokeAsync(() =>
{
var dialog = new Window
{
Title = $"溶出{channel}取样",
Width = 420,
SizeToContent = SizeToContent.Height,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
ResizeMode = ResizeMode.NoResize,
Background = Brushes.White,
Owner = Application.Current.MainWindow
};
var panel = new StackPanel { Margin = new Thickness(24) };
panel.Children.Add(new TextBlock
{
Text = "请取样分析后,取样结束后点击“确定已取样”继续运行。",
FontSize = 16,
Foreground = new SolidColorBrush(Color.FromRgb(16, 42, 67)),
TextWrapping = TextWrapping.Wrap,
Margin = new Thickness(0, 0, 0, 18)
});
var button = new Button
{
Content = "确定已取样",
Width = 128,
Height = 38,
HorizontalAlignment = System.Windows.HorizontalAlignment.Right,
Background = new SolidColorBrush(Color.FromRgb(21, 101, 169)),
Foreground = Brushes.White,
BorderThickness = new Thickness(0),
FontSize = 15,
FontWeight = System.Windows.FontWeights.SemiBold,
Cursor = System.Windows.Input.Cursors.Hand
};
button.Click += (_, _) =>
{
dialog.DialogResult = true;
dialog.Close();
};
panel.Children.Add(button);
dialog.Content = panel;
return dialog.ShowDialog() == true;
});
if (!confirmed)
throw new InvalidOperationException("取样确认窗口已关闭,未写入确认线圈");
}
private async Task<bool> ReadDissolutionChannelAsync(int channel)
{
ushort registerAddress = channel == 1
@@ -775,6 +910,7 @@ namespace TabletTester2025.ViewModels
Phase = TestPhase.Running;
DissolutionPass = false;
ResetDissolutionChannel(1);
ResetDissolutionSampleState(1);
_dissolution1StartTime = DateTime.Now;
_isDissolution1Running = true;
DissolutionPlotModel.Title = "溶出曲线";
@@ -792,6 +928,7 @@ namespace TabletTester2025.ViewModels
finally
{
_isDissolution1Running = false;
ResetDissolutionSampleState(1);
Phase = _isDissolution2Running ? TestPhase.Running : TestPhase.Idle;
UpdateDissolutionClock();
}
@@ -810,6 +947,7 @@ namespace TabletTester2025.ViewModels
Phase = TestPhase.Running;
DissolutionPass = false;
ResetDissolutionChannel(2);
ResetDissolutionSampleState(2);
_dissolution2StartTime = DateTime.Now;
_isDissolution2Running = true;
DissolutionPlotModel.Title = "溶出曲线";
@@ -827,6 +965,7 @@ namespace TabletTester2025.ViewModels
finally
{
_isDissolution2Running = false;
ResetDissolutionSampleState(2);
Phase = _isDissolution1Running ? TestPhase.Running : TestPhase.Idle;
UpdateDissolutionClock();
}
@@ -857,6 +996,12 @@ namespace TabletTester2025.ViewModels
DissolutionPlotModel.InvalidatePlot(true);
}
private void ResetDissolutionSampleState(int channel)
{
SetDissolutionSampleRequestActive(channel, false);
SetDissolutionSamplePromptOpen(channel, false);
}
private async Task FinalizeDissolutionChannelAsync(int channel)
{
var times = channel == 1 ? _dissolution1Times : _dissolution2Times;

View File

@@ -37,8 +37,10 @@
"DissolutionStartCoil": 40,
"Dissolution1StartCoil": 40,
"Dissolution1StopCoil": 43,
"Dissolution1SampleAckCoil": 44,
"Dissolution2StartCoil": 30,
"Dissolution2StopCoil": 33,
"Dissolution2SampleAckCoil": 34,
"Dissolution1Time": 430,
"Dissolution2Time": 440
},