371 lines
13 KiB
C#
371 lines
13 KiB
C#
using DevExpress.ClipboardSource.SpreadsheetML;
|
||
using NModbus;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Net.Sockets;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Data;
|
||
using System.Windows.Documents;
|
||
using System.Windows.Input;
|
||
using System.Windows.Media;
|
||
using System.Windows.Media.Imaging;
|
||
using System.Windows.Shapes;
|
||
using System.Windows.Threading;
|
||
using 建材不燃性试验炉.Data; // 这是关键
|
||
|
||
namespace 建材不燃性试验炉
|
||
{
|
||
/// <summary>
|
||
/// CofficientSetting.xaml 的交互逻辑
|
||
/// </summary>
|
||
public partial class CofficientSetting : Window
|
||
{
|
||
#region 私有字段
|
||
//状态计时器
|
||
private DispatcherTimer _statusTimer;
|
||
private bool _isManualInput = false; // 手动输入标记:true=输入中(暂停读取),false=正常读取
|
||
|
||
private TcpClient _tcpClient => Data.ModbusResourceManager.Instance?.TcpClient;
|
||
private IModbusMaster _modbusMaster => Data.ModbusResourceManager.Instance?.ModbusMaster;
|
||
|
||
Function ma;
|
||
DataChange c;
|
||
|
||
#endregion
|
||
|
||
#region 构造函数和初始化
|
||
public CofficientSetting()
|
||
{
|
||
InitializeComponent();
|
||
|
||
InitializeTimers();
|
||
}
|
||
|
||
private void InitializeTimers()
|
||
{
|
||
// 状态更新定时器
|
||
_statusTimer = new DispatcherTimer();
|
||
_statusTimer.Interval = TimeSpan.FromSeconds(1);
|
||
_statusTimer.Tick += StatusTimer_Tick;
|
||
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 窗口加载事件
|
||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
|
||
// 连接Modbus设备
|
||
|
||
string plcIp = "192.168.1.10";
|
||
bool initSuccess = Data.ModbusResourceManager.Instance.Init(plcIp, 502);
|
||
if (!initSuccess)
|
||
{
|
||
MessageBox.Show("连接Modbus服务器失败!", "错误");
|
||
this.Close();
|
||
return;
|
||
}
|
||
|
||
// 检查连接状态
|
||
if (_tcpClient == null || !_tcpClient.Connected)
|
||
{
|
||
MessageBox.Show("Modbus连接异常!", "错误");
|
||
this.Close();
|
||
return;
|
||
}
|
||
|
||
// 初始化工具类
|
||
c = new DataChange();
|
||
|
||
// 启动状态定时器
|
||
_statusTimer.Start();
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"初始化失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
this.Close();
|
||
}
|
||
}
|
||
|
||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||
{
|
||
// 停止所有计时器
|
||
_statusTimer?.Stop();
|
||
}
|
||
#endregion
|
||
|
||
#region 定时器事件
|
||
private void StatusTimer_Tick(object sender, EventArgs e)
|
||
{
|
||
// 如果正在手动输入,暂停读取
|
||
if (_isManualInput) return;
|
||
|
||
// 温度和系数更新
|
||
UpdateTemperaturesAndCofficient();
|
||
}
|
||
|
||
private void UpdateTemperaturesAndCofficient()
|
||
{
|
||
try
|
||
{
|
||
// 检查Modbus连接状态
|
||
if (_modbusMaster == null)
|
||
{
|
||
Debug.WriteLine("ModbusMaster为空,跳过更新");
|
||
return;
|
||
}
|
||
|
||
// 检查TCP连接状态
|
||
if (_tcpClient == null || !_tcpClient.Connected)
|
||
{
|
||
Debug.WriteLine("TCP连接断开,跳过更新");
|
||
return;
|
||
}
|
||
|
||
// 一次性读取所有相关寄存器,减少通信次数
|
||
// 定义要读取的寄存器地址范围
|
||
var readTasks = new List<Task>();
|
||
|
||
// 输出电压相关 (D304-D306)
|
||
ReadAndUpdateRegister(304, 2, value =>
|
||
Dispatcher.Invoke(() => txtOutputVoltageCoefficient.Text = value.ToString("F2")));
|
||
|
||
ReadAndUpdateRegister(306, 2, value =>
|
||
Dispatcher.Invoke(() => txtOutputVoltageAnalog.Text = value.ToString("F2")));
|
||
|
||
// 炉内温度相关 (D1226, D1230)
|
||
ReadAndUpdateRegister(1226, 2, value =>
|
||
Dispatcher.Invoke(() => txtFurnaceTempCoefficient.Text = value.ToString("F2")));
|
||
|
||
ReadAndUpdateRegister(1230, 2, value =>
|
||
Dispatcher.Invoke(() => txtFurnaceTempDisplay.Text = value.ToString("F2")));
|
||
|
||
// 样品内温度相关 (D1276, D1280)
|
||
ReadAndUpdateRegister(1276, 2, value =>
|
||
Dispatcher.Invoke(() => txtSampleInnerTempCoefficient.Text = value.ToString("F2")));
|
||
|
||
ReadAndUpdateRegister(1280, 2, value =>
|
||
Dispatcher.Invoke(() => txtSampleInnerTempDisplay.Text = value.ToString("F2")));
|
||
|
||
// 样品外温度相关 (D1328, D1330)
|
||
ReadAndUpdateRegister(1328, 2, value =>
|
||
Dispatcher.Invoke(() => txtSampleOuterTempCoefficient.Text = value.ToString("F2")));
|
||
|
||
ReadAndUpdateRegister(1330, 2, value =>
|
||
Dispatcher.Invoke(() => txtSampleOuterTempDisplay.Text = value.ToString("F2")));
|
||
|
||
// 电压表相关 (D1378, D1380)
|
||
ReadAndUpdateRegister(1378, 2, value =>
|
||
Dispatcher.Invoke(() => txtVoltmeterCoefficient.Text = value.ToString("F2")));
|
||
|
||
ReadAndUpdateRegister(1380, 2, value =>
|
||
Dispatcher.Invoke(() => txtVoltmeterDisplay.Text = value.ToString("F2")));
|
||
|
||
// 电流相关 (D1428, D1430)
|
||
ReadAndUpdateRegister(1428, 2, value =>
|
||
Dispatcher.Invoke(() => txtCurrentCoefficient.Text = value.ToString("F2")));
|
||
|
||
ReadAndUpdateRegister(1430, 2, value =>
|
||
Dispatcher.Invoke(() => txtCurrentDisplay.Text = value.ToString("F2")));
|
||
}
|
||
catch (InvalidOperationException ioex)
|
||
{
|
||
Debug.WriteLine($"Modbus通信错误:{ioex.Message}");
|
||
}
|
||
catch (IOException ioex)
|
||
{
|
||
Debug.WriteLine($"IO错误:{ioex.Message}");
|
||
HandleConnectionLost();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"更新数据时发生未知错误:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void ReadAndUpdateRegister(int address, int count, Action<float> updateAction)
|
||
{
|
||
try
|
||
{
|
||
// 安全检查
|
||
if (_modbusMaster == null || c == null)
|
||
{
|
||
Debug.WriteLine($"ModbusMaster或DataChange为空,地址{address}跳过");
|
||
return;
|
||
}
|
||
|
||
// 读取寄存器
|
||
ushort[] registers = _modbusMaster.ReadHoldingRegisters(1, (ushort)address, (ushort)count);
|
||
|
||
// 空值检查
|
||
if (registers == null || registers.Length < count)
|
||
{
|
||
Debug.WriteLine($"读取地址{address}返回空值或长度不足");
|
||
return;
|
||
}
|
||
|
||
// 转换为浮点数
|
||
float value = c.UshortToFloat(registers[1], registers[0]);
|
||
updateAction?.Invoke(value);
|
||
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"读取地址{address}失败:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void HandleConnectionLost()
|
||
{
|
||
try
|
||
{
|
||
// 停止定时器
|
||
_statusTimer?.Stop();
|
||
|
||
// 显示连接错误
|
||
Dispatcher.Invoke(() =>
|
||
{
|
||
MessageBox.Show("Modbus连接丢失,请检查网络连接!", "连接错误",
|
||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||
|
||
});
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"处理连接丢失时出错:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
#region GotFocus写入事件(带手动输入标记)
|
||
|
||
//输出电压系数D304
|
||
private void txtOutputVoltageCoefficient_GotFocus(object sender, RoutedEventArgs e)
|
||
{
|
||
_isManualInput = true; // 进入手动输入模式
|
||
|
||
// 延迟写入,确保用户有时间修改
|
||
Task.Delay(100).ContinueWith(_ =>
|
||
{
|
||
ma?.WriteToPLCForNew(txtOutputVoltageCoefficient.Text.Trim(), 304,Function.DataType.浮点型);
|
||
_isManualInput = false; // 写入后恢复自动读取
|
||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||
}
|
||
|
||
//炉内温度系数D1226
|
||
private void txtFurnaceTempCoefficient_GotFocus(object sender, RoutedEventArgs e)
|
||
{
|
||
_isManualInput = true;
|
||
Task.Delay(100).ContinueWith(_ =>
|
||
{
|
||
ma?.WriteToPLCForNew(txtFurnaceTempCoefficient.Text.Trim(), 1226, Function.DataType.浮点型);
|
||
_isManualInput = false;
|
||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||
}
|
||
|
||
//样品内温度系数D1276
|
||
private void txtSampleInnerTempCoefficient_GotFocus(object sender, RoutedEventArgs e)
|
||
{
|
||
_isManualInput = true;
|
||
Task.Delay(100).ContinueWith(_ =>
|
||
{
|
||
ma?.WriteToPLCForNew(txtSampleInnerTempCoefficient.Text.Trim(), 1276, Function.DataType.浮点型);
|
||
_isManualInput = false;
|
||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||
}
|
||
|
||
//样品外温度系数D1328
|
||
private void txtSampleOuterTempCoefficient_GotFocus(object sender, RoutedEventArgs e)
|
||
{
|
||
_isManualInput = true;
|
||
Task.Delay(100).ContinueWith(_ =>
|
||
{
|
||
ma?.WriteToPLCForNew(txtSampleOuterTempCoefficient.Text.Trim(), 1328, Function.DataType.浮点型);
|
||
_isManualInput = false;
|
||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||
}
|
||
|
||
//电压表系数D1378
|
||
private void txtVoltmeterCoefficient_GotFocus(object sender, RoutedEventArgs e)
|
||
{
|
||
_isManualInput = true;
|
||
Task.Delay(100).ContinueWith(_ =>
|
||
{
|
||
ma?.WriteToPLCForNew(txtVoltmeterCoefficient.Text.Trim(), 1378, Function.DataType.浮点型);
|
||
_isManualInput = false;
|
||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||
}
|
||
|
||
//电压表系数D1428
|
||
private void txtCurrentCoefficient_GotFocus(object sender, RoutedEventArgs e)
|
||
{
|
||
_isManualInput = true;
|
||
Task.Delay(100).ContinueWith(_ =>
|
||
{
|
||
ma?.WriteToPLCForNew(txtCurrentCoefficient.Text.Trim(), 1428, Function.DataType.浮点型);
|
||
_isManualInput = false;
|
||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
#region 按钮控件
|
||
|
||
private MainWindow _mainWindow;
|
||
//返回
|
||
private void btnReturn_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
SwitchWindow(ref _mainWindow, () => new MainWindow());
|
||
}
|
||
|
||
|
||
private void SwitchWindow<T>(ref T windowInstance, Func<T> createFunc) where T : Window, new()
|
||
{
|
||
// 1. 停止当前窗口的定时器(不释放资源)
|
||
_statusTimer?.Stop();
|
||
|
||
// 2. 复用窗口实例:不存在则创建,存在则激活
|
||
if (windowInstance == null)
|
||
{
|
||
windowInstance = createFunc();
|
||
// 添加窗口关闭事件处理
|
||
windowInstance.Closed += (s, args) =>
|
||
{
|
||
// 窗口关闭时重新启动定时器并显示当前窗口
|
||
_statusTimer?.Start();
|
||
this.Show();
|
||
this.Activate();
|
||
};
|
||
}
|
||
else
|
||
{
|
||
// 激活已存在的窗口(前置显示)
|
||
windowInstance.Activate();
|
||
return;
|
||
}
|
||
|
||
// 3. 切换窗口:隐藏当前窗口,显示目标窗口(非模态)
|
||
this.Hide();
|
||
windowInstance.Show();
|
||
}
|
||
#endregion
|
||
}
|
||
|
||
|
||
|
||
}
|