178 lines
6.5 KiB
C#
178 lines
6.5 KiB
C#
using Microsoft.Win32;
|
||
using Sunny.UI;
|
||
using System;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using TabletTester2025.Services;
|
||
using static OfficeOpenXml.ExcelErrorValue;
|
||
|
||
namespace 片剂四用仪.Views
|
||
{
|
||
public partial class ShowData : Window
|
||
{
|
||
private readonly IPlcService _plc;
|
||
private CancellationTokenSource _cts;
|
||
|
||
public ShowData(IPlcService plc)
|
||
{
|
||
InitializeComponent();
|
||
_plc = plc;
|
||
Loaded += ShowData_Loaded;
|
||
Closing += ShowData_Closing;
|
||
}
|
||
|
||
private async void ShowData_Loaded(object sender, RoutedEventArgs e)
|
||
{
|
||
_cts = new CancellationTokenSource();
|
||
BindAllTextBoxWriteEvents();
|
||
await StartPlcReadLoop(_cts.Token);
|
||
}
|
||
|
||
private void ShowData_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||
{
|
||
_cts?.Cancel();
|
||
}
|
||
|
||
// ====================== 读取 PLC ======================
|
||
private async Task StartPlcReadLoop(CancellationToken token)
|
||
{
|
||
while (!token.IsCancellationRequested)
|
||
{
|
||
try
|
||
{
|
||
foreach (var m in _paramMappings)
|
||
{
|
||
var tb = FindName(m.TextBoxName) as TextBox;
|
||
if (tb == null) continue;
|
||
|
||
if (m.Type == PlcParamType.Int)
|
||
{
|
||
int value = await _plc.ReadIntAsync((ushort)m.Address);
|
||
|
||
Dispatcher.Invoke(() => tb.Text = value.ToString());
|
||
|
||
}
|
||
else
|
||
{
|
||
float value = await _plc.ReadFloatAsync((ushort)m.Address);
|
||
|
||
Dispatcher.Invoke(() => tb.Text = value.ToString("F2"));
|
||
|
||
}
|
||
}
|
||
// 正常循环的Delay,同样处理取消异常
|
||
try
|
||
{
|
||
await Task.Delay(1000, token);
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
// 窗口关闭时的取消异常,正常退出循环
|
||
break;
|
||
}
|
||
|
||
//await Task.Delay(1000, token);
|
||
}
|
||
}
|
||
|
||
// ====================== 写入 PLC ======================
|
||
private void BindAllTextBoxWriteEvents()
|
||
{
|
||
foreach (var m in _paramMappings)
|
||
{
|
||
var tb = FindName(m.TextBoxName) as TextBox;
|
||
if (tb == null) continue;
|
||
|
||
tb.GotFocus += async (s, e) =>
|
||
{
|
||
try
|
||
{
|
||
if (m.Type == PlcParamType.Int)
|
||
{
|
||
if (int.TryParse(tb.Text, out int val))
|
||
await _plc.WriteRegisterAsync((ushort)m.Address, (ushort)val);
|
||
}
|
||
else
|
||
{
|
||
if (double.TryParse(tb.Text, out double val))
|
||
{
|
||
// 弹窗修改值
|
||
if (UIInputDialog.ShowInputDoubleDialog(ref val, UIStyle.Inherited, 3, desc: "请输入值", showMask: false))
|
||
{
|
||
// 更新界面
|
||
tb.Text = val.ToString("F3");
|
||
|
||
// 写入PLC(浮点数双寄存器)
|
||
byte[] bytes = BitConverter.GetBytes(val);
|
||
ushort[] regs = new ushort[2];
|
||
regs[0] = (ushort)BitConverter.ToUInt16(bytes, 2);
|
||
regs[1] = (ushort)BitConverter.ToUInt16(bytes, 0);
|
||
await _plc.WriteRegisterAsync((ushort)m.Address, (ushort)val);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch { }
|
||
};
|
||
}
|
||
}
|
||
|
||
// ====================== 地址映射表 ======================
|
||
private readonly PlcParamMapping[] _paramMappings = new[]
|
||
{
|
||
new PlcParamMapping("txt_HardnessSpeed", 300, PlcParamType.Float),
|
||
new PlcParamMapping("txt_HardnessDisplacement", 310, PlcParamType.Float),
|
||
new PlcParamMapping("txt_HardnessMotorLimit", 298, PlcParamType.Float),
|
||
new PlcParamMapping("txt_HardnessDamageThreshold", 400, PlcParamType.Float),
|
||
|
||
|
||
new PlcParamMapping("txt_BrittlenessTestTime", 410, PlcParamType.Int),
|
||
new PlcParamMapping("txt_PreBrittlenessMass", 412, PlcParamType.Int),
|
||
new PlcParamMapping("txt_PostBrittlenessMass", 414, PlcParamType.Int),
|
||
new PlcParamMapping("txt_WeightLossRate", 416, PlcParamType.Int),
|
||
|
||
new PlcParamMapping("txt_DisintegrationSpeed", 330, PlcParamType.Float),
|
||
new PlcParamMapping("txt_DisintegrationTime", 420, PlcParamType.Int),
|
||
|
||
new PlcParamMapping("txt_DissolutionTime", 430, PlcParamType.Int),
|
||
new PlcParamMapping("txt_DissolutionSamplingInterval", 432, PlcParamType.Int),
|
||
|
||
|
||
new PlcParamMapping("txt_ForceCoefficient", 1320, PlcParamType.Float),
|
||
new PlcParamMapping("txt_ForceProtection", 1322, PlcParamType.Float),
|
||
|
||
new PlcParamMapping("txt_TemperatureDisplay", 1430, PlcParamType.Float),
|
||
|
||
new PlcParamMapping("txt_MaxForceCollect", 72, PlcParamType.Float),//读取
|
||
new PlcParamMapping("txt_ForceDisplay", 1314, PlcParamType.Float),//读取
|
||
new PlcParamMapping("txt_TemperatureCoefficient", 1428, PlcParamType.Float),//读取
|
||
};
|
||
}
|
||
|
||
internal class PlcParamMapping
|
||
{
|
||
public string TextBoxName { get; }
|
||
public int Address { get; }
|
||
public PlcParamType Type { get; }
|
||
|
||
public PlcParamMapping(string textBoxName, int address, PlcParamType type)
|
||
{
|
||
TextBoxName = textBoxName;
|
||
Address = address;
|
||
Type = type;
|
||
}
|
||
}
|
||
|
||
internal enum PlcParamType
|
||
{
|
||
Int,
|
||
Float
|
||
}
|
||
} |