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 } }