Files
HeadgearViewingRange3M/Views/ParameterWindow.xaml.cs
2026-04-01 20:33:23 +08:00

189 lines
7.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
}
}
}