Files
NoBuilding/建材不燃性试验炉/CofficientSetting.xaml.cs

391 lines
13 KiB
C#
Raw Normal View History

2026-01-31 09:14:24 +08:00
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();
2026-02-02 19:39:09 +08:00
ma=new Function(_modbusMaster);
2026-01-31 09:14:24 +08:00
// 启动状态定时器
_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")));
2026-02-02 16:18:52 +08:00
// 炉内温度相关 (D1228, D1230)
ReadAndUpdateRegister(1228, 2, value =>
2026-01-31 09:14:24 +08:00
Dispatcher.Invoke(() => txtFurnaceTempCoefficient.Text = value.ToString("F2")));
ReadAndUpdateRegister(1230, 2, value =>
Dispatcher.Invoke(() => txtFurnaceTempDisplay.Text = value.ToString("F2")));
// 样品内温度相关 (D1276, D1280)
2026-02-02 16:18:52 +08:00
ReadAndUpdateRegister(1278, 2, value =>
2026-01-31 09:14:24 +08:00
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")));
2026-02-02 16:18:52 +08:00
//炉内温度设定
ReadAndUpdateRegister(350, 2, value =>
Dispatcher.Invoke(() => txtFurnaceTempSet.Text = value.ToString("F2")));
2026-01-31 09:14:24 +08:00
}
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());
}
2026-02-02 16:18:52 +08:00
//炉内温度系数D1228
2026-01-31 09:14:24 +08:00
private void txtFurnaceTempCoefficient_GotFocus(object sender, RoutedEventArgs e)
{
_isManualInput = true;
Task.Delay(100).ContinueWith(_ =>
{
2026-02-02 16:18:52 +08:00
ma?.WriteToPLCForNew(txtFurnaceTempCoefficient.Text.Trim(), 1228, Function.DataType.);
2026-01-31 09:14:24 +08:00
_isManualInput = false;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
2026-02-02 16:18:52 +08:00
//样品内温度系数D1278
2026-01-31 09:14:24 +08:00
private void txtSampleInnerTempCoefficient_GotFocus(object sender, RoutedEventArgs e)
{
_isManualInput = true;
Task.Delay(100).ContinueWith(_ =>
{
2026-02-02 16:18:52 +08:00
ma?.WriteToPLCForNew(txtSampleInnerTempCoefficient.Text.Trim(), 1278, Function.DataType.);
2026-01-31 09:14:24 +08:00
_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());
}
2026-02-02 16:18:52 +08:00
//炉内温度设定
private void txtFurnaceTempSet_GotFocus(object sender, RoutedEventArgs e)
{
_isManualInput = true;
Task.Delay(100).ContinueWith(_ =>
{
ma?.WriteToPLCForNew(txtFurnaceTempSet.Text.Trim(), 350, Function.DataType.);
_isManualInput = false;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
2026-01-31 09:14:24 +08:00
#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
2026-02-02 16:18:52 +08:00
2026-01-31 09:14:24 +08:00
}
}