189 lines
7.7 KiB
C#
189 lines
7.7 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Threading;
|
||
using MembranePoreTester.Communication;
|
||
|
||
namespace MembranePoreTester
|
||
{
|
||
public partial class ParameterWindow : Window
|
||
{
|
||
private readonly IPlcService _plcService;
|
||
private readonly PlcConfiguration _config;
|
||
private DispatcherTimer _autoRefreshTimer;
|
||
|
||
// 文本框映射:(文本框, 地址, 参数名, 是否浮点数)
|
||
private readonly List<(TextBox textBox, ushort address, string name, bool isFloat)> _textBoxMapping = new();
|
||
|
||
public ParameterWindow()
|
||
{
|
||
InitializeComponent();
|
||
_plcService = App.PlcService;
|
||
_config = App.PlcConfig;
|
||
|
||
// 16位整数(灯条、中灯、电机)
|
||
AddMapping(txtUpperLampData1, _config.UpperLampData1, "上灯条数据1", false);
|
||
AddMapping(txtLowerLampData1, _config.LowerLampData1, "下灯条数据1", false);
|
||
AddMapping(txtUpperLampData2, _config.UpperLampData2, "上灯条数据2", false);
|
||
AddMapping(txtLowerLampData2, _config.LowerLampData2, "下灯条数据2", false);
|
||
AddMapping(txtUpperLampData3, _config.UpperLampData3, "上灯条数据3", false);
|
||
AddMapping(txtLowerLampData3, _config.LowerLampData3, "下灯条数据3", false);
|
||
AddMapping(txtUpperLampData4, _config.UpperLampData4, "上灯条数据4", false);
|
||
AddMapping(txtLowerLampData4, _config.LowerLampData4, "下灯条数据4", false);
|
||
AddMapping(txtUpperLampData5, _config.UpperLampData5, "上灯条数据5", false);
|
||
AddMapping(txtLowerLampData5, _config.LowerLampData5, "下灯条数据5", false);
|
||
AddMapping(txtUpperLampData6, _config.UpperLampData6, "上灯条数据6", false);
|
||
AddMapping(txtLowerLampData6, _config.LowerLampData6, "下灯条数据6", false);
|
||
|
||
AddMapping(txtMiddleLamp1, _config.MiddleLamp1, "中灯1", false);
|
||
AddMapping(txtMiddleLamp2, _config.MiddleLamp2, "中灯2", false);
|
||
AddMapping(txtMiddleLamp3, _config.MiddleLamp3, "中灯3", false);
|
||
AddMapping(txtMiddleLamp4, _config.MiddleLamp4, "中灯4", false);
|
||
AddMapping(txtMiddleLamp5, _config.MiddleLamp5, "中灯5", false);
|
||
AddMapping(txtMiddleLamp6, _config.MiddleLamp6, "中灯6", false);
|
||
AddMapping(txtMiddleLamp7, _config.MiddleLamp7, "中灯7", false);
|
||
|
||
AddMapping(txtMotorLimit, _config.MotorLimit, "电机限位", true);
|
||
AddMapping(txtResetCompensation, _config.ResetCompensation, "复位补偿", true);
|
||
|
||
|
||
AddMapping(txtLeftEyeAreaCoeff, _config.LeftEyeAreaCoeff, "左眼面积系数", true);
|
||
AddMapping(txtRightEyeAreaCoeff, _config.RightEyeAreaCoeff, "右眼面积系数", true);
|
||
AddMapping(txtSaveRateCorrectionCoeff, _config.SaveRateCorrectionCoeff, "保存率矫正系数", true);
|
||
|
||
RegisterTextBoxEvents();
|
||
|
||
Loaded += async (s, e) =>
|
||
{
|
||
_autoRefreshTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
|
||
_autoRefreshTimer.Tick += AutoRefreshTimer_Tick;
|
||
_autoRefreshTimer.Start();
|
||
await LoadAllParameters();
|
||
};
|
||
|
||
Closed += (s, e) => _autoRefreshTimer?.Stop();
|
||
}
|
||
|
||
private void AddMapping(TextBox textBox, ushort address, string name, bool isFloat)
|
||
{
|
||
if (textBox != null)
|
||
{
|
||
_textBoxMapping.Add((textBox, address, name, isFloat));
|
||
}
|
||
}
|
||
|
||
private void RegisterTextBoxEvents()
|
||
{
|
||
foreach (var (tb, addr, name, isFloat) in _textBoxMapping)
|
||
{
|
||
tb.LostFocus += async (s, e) =>
|
||
{
|
||
if (float.TryParse(tb.Text, out float value))
|
||
{
|
||
try
|
||
{
|
||
if (isFloat)
|
||
await WriteFloatAsync(addr, value);
|
||
else
|
||
await WriteInt16Async(addr, (ushort)value);
|
||
System.Diagnostics.Debug.WriteLine($"{name} 已写入: {value}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"写入 {name} 失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show($"请输入有效的数值", "输入错误", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||
await UpdateSingleParameter(tb, addr, isFloat);
|
||
}
|
||
};
|
||
}
|
||
}
|
||
|
||
private async void AutoRefreshTimer_Tick(object sender, EventArgs e)
|
||
{
|
||
await Dispatcher.InvokeAsync(async () =>
|
||
{
|
||
foreach (var (tb, addr, name, isFloat) in _textBoxMapping)
|
||
{
|
||
if (!tb.IsFocused)
|
||
{
|
||
try
|
||
{
|
||
if (isFloat)
|
||
{
|
||
float val = await ReadFloatAsync(addr);
|
||
tb.Text = val.ToString("F3");
|
||
}
|
||
else
|
||
{
|
||
ushort val = await ReadInt16Async(addr);
|
||
tb.Text = val.ToString();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"自动刷新 {name} 失败: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
private async Task UpdateSingleParameter(TextBox tb, ushort addr, bool isFloat)
|
||
{
|
||
try
|
||
{
|
||
if (isFloat)
|
||
{
|
||
float val = await ReadFloatAsync(addr);
|
||
tb.Text = val.ToString("F3");
|
||
}
|
||
else
|
||
{
|
||
ushort val = await ReadInt16Async(addr);
|
||
tb.Text = val.ToString();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"更新失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private async Task LoadAllParameters()
|
||
{
|
||
foreach (var (tb, addr, name, isFloat) in _textBoxMapping)
|
||
{
|
||
await UpdateSingleParameter(tb, addr, isFloat);
|
||
}
|
||
}
|
||
|
||
// 16位整数读写
|
||
private async Task<ushort> ReadInt16Async(ushort address)
|
||
{
|
||
var registers = await ((ModbusTcpPlcService)_plcService).ReadHoldingRegistersAsync(address, 1);
|
||
return registers[0];
|
||
}
|
||
|
||
private async Task WriteInt16Async(ushort address, ushort value)
|
||
{
|
||
await ((ModbusTcpPlcService)_plcService).WriteSingleRegisterAsync(address, value);
|
||
}
|
||
|
||
// 32位浮点数读写
|
||
private async Task<float> ReadFloatAsync(ushort address)
|
||
{
|
||
var registers = await ((ModbusTcpPlcService)_plcService).ReadHoldingRegistersAsync(address, 2);
|
||
return ((ModbusTcpPlcService)_plcService).UshortToFloat(registers[1], registers[0]);
|
||
}
|
||
|
||
private async Task WriteFloatAsync(ushort address, float value)
|
||
{
|
||
await ((ModbusTcpPlcService)_plcService).WriteMultipleRegistersAsync(address, value);
|
||
}
|
||
}
|
||
} |