Files
zijiuqizonghejianyanyi/MainWindow4.xaml.cs

507 lines
18 KiB
C#
Raw Permalink Normal View History

2026-03-11 15:21:27 +08:00
using Modbus.Device;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO.Ports;
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.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using ;
using .Data;
namespace
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow4 : Window
{
private MainWindow _mainWindow;
private MainWindow2 _mainWindow2;
private MainWindow3 _mainWindow3;
private MainWindow4 _mainWindow4;
private ReportWindow4 _reportWindow4;
private bool _wasRunning = false; // 上次检验的运行状态
private bool _recordAdded = false; // 本轮测试是否已插入记录
private DateTime _testStartTime; // 测试开始时间
private TcpClient _tcpClient => ModbusResourceManager.Instance.TcpClient;
private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster;
private const byte SlaveId = 1; // PLC从站地址
private const ushort Address262 = 262; // 32位浮点数float32占2个寄存器
private const ushort Address2506 = 2506; // 32位浮点数float32占2个寄存器
private const ushort Address2502 = 2502; // 32位浮点数float32占2个寄存器
// Modbus通信
private bool _isManualInput = false; // 手动输入标记true=输入中暂停读取false=正常读取
private readonly DispatcherTimer _readTimer;
Function ma;
DataChange c = new DataChange();
public MainWindow4()
{
InitializeComponent();
_readTimer = InitDispatcherTimer();
//InitializeModbusTcp();
BindInputFocusEvents();
}
private void BindInputFocusEvents()
{
// 地址400输入框count
//settingtime.GotFocus += (s, e) => _isManualInput = true; // 获得焦点→暂停读取
//settingtime.LostFocus += (s, e) => _isManualInput = false; // 失去焦点→恢复读取
//// 地址404输入框count2
//count2.GotFocus += (s, e) => _isManualInput = true;
//count2.LostFocus += (s, e) => _isManualInput = false;
//// 地址406输入框count3
//count3.GotFocus += (s, e) => _isManualInput = true;
//count3.LostFocus += (s, e) => _isManualInput = false;
}
private DispatcherTimer InitDispatcherTimer()
{
var timer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(500)
};
timer.Tick += async (s, e) =>
{
if (!_isManualInput && _modbusMaster != null)
{
try
{
await ReadAllPlcDataAsync();
}
catch { }
}
};
return timer;
}
//private void InitializeModbusTcp()
//{
// try
// {
// // 从配置读取PLC连接信息
// string plcIp = "192.168.1.10";
// int plcPort = 502;
// _tcpClient = new TcpClient(plcIp, plcPort);
// _modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);
// _modbusMaster.Transport.ReadTimeout = 3000;
// _modbusMaster.Transport.WriteTimeout = 3000;
// // 初始化定时器
// //InitializeTimers();
// // 初始化数据库
// //InitializeDatabase();
// _readTimer.Start();
// ma = new Function(_modbusMaster);
// }
// catch (Exception ex)
// {
// ShowErrorMsg($"Modbus初始化失败: {ex.Message}");
// }
//}
private async System.Threading.Tasks.Task ReadAllPlcDataAsync()
{
// 检查连接状态
if (_tcpClient == null || !_tcpClient.Connected || _modbusMaster == null)
{
return;
}
// 仅在非手动输入时读取设置地址(避免覆盖输入)
if (!_isManualInput)
{
await ReadAddr262DataAsync();
await System.Threading.Tasks.Task.Delay(50);
await ReadAddr404DataAsync();
await System.Threading.Tasks.Task.Delay(50);
//await ReadAddr406DataAsync();
//await System.Threading.Tasks.Task.Delay(50);
//await ReadAddr130DataAsync();
}
await ReadAddrStatusDataAsync();
}
private async System.Threading.Tasks.Task ReadAddr262DataAsync()
{
try
{
ushort[] registers = await System.Threading.Tasks.Task.Run(() =>
_modbusMaster.ReadHoldingRegisters(1, 1430, 2)
);
if (registers != null)
{
float addr406Value = c.UshortToFloat(registers[1], registers[0]);
Dispatcher.Invoke(() => settingtime.Text = addr406Value.ToString("F2"));
}
}
catch (Exception ex)
{
//ShowErrorMsg($"读取地址406失败{ex.Message}");
}
}
private async System.Threading.Tasks.Task ReadAddr404DataAsync()
{
try
{
ushort[] registers = await System.Threading.Tasks.Task.Run(() =>
_modbusMaster.ReadHoldingRegisters(1, 106, 2)
);
if (registers != null)
{
float addr406Value = c.UshortToFloat(registers[1], registers[0]);
Dispatcher.Invoke(() => settingtime2.Text = addr406Value.ToString("F2"));
}
}
catch (Exception ex)
{
//ShowErrorMsg($"读取地址406失败{ex.Message}");
}
}
private void ShowErrorMsg(string msg)
{
Dispatcher.Invoke(() =>
{
MessageBox.Show(msg, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
});
}
private void Button_Click(object sender, RoutedEventArgs e)
{
OpenQuantitativeSupplyWindow4();
}
private void OpenQuantitativeSupplyWindow4()
{
try
{
SwitchWindow(ref _reportWindow4, () => new ReportWindow4());
}
catch (Exception ex)
{
MessageBox.Show($"打开定量供应检验窗口时出错:{ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
ma.BtnClickFunctionForNew(Function.ButtonType., 100);
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
//ma.BtnClickFunctionForNew(Function.ButtonType.复归型, 103);
ma.BtnClickFunctionForNew(Function.ButtonType., 103);
}
private void Button_Click_3(object sender, RoutedEventArgs e)
{
ma.BtnClickFunctionForNew(Function.ButtonType., 15);
}
private void Button_Click_4(object sender, RoutedEventArgs e)
{
2026-03-16 19:10:33 +08:00
SwitchWindow(ref _mainWindow, () => new MainWindow(), "正在进入定量供应检验", "正在准备定量供应检验页面...");
2026-03-11 15:21:27 +08:00
}
private void Button_Click_5(object sender, RoutedEventArgs e)
{
2026-03-16 19:10:33 +08:00
SwitchWindow(ref _mainWindow2, () => new MainWindow2(), "正在进入负压气密性检验", "正在切换到负压气密性检验页面...");
2026-03-11 15:21:27 +08:00
}
private void Button_Click_6(object sender, RoutedEventArgs e)
{
2026-03-16 19:10:33 +08:00
SwitchWindow(ref _mainWindow3, () => new MainWindow3(), "正在进入正压气密性检验", "正在切换到正压气密性检验页面...");
2026-03-11 15:21:27 +08:00
}
private void Button_Click_7(object sender, RoutedEventArgs e)
{
2026-03-16 19:10:33 +08:00
SwitchWindow(ref _mainWindow4, () => new MainWindow4(), "正在进入排气阀压力测试", "正在切换到排气阀压力测试页面...");
2026-03-11 15:21:27 +08:00
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
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;
}
ma = new Function(_modbusMaster);
ma.BtnClickFunctionForNew(Function.ButtonType., 64);
System.Threading.Tasks.Task.Delay(50);
_readTimer.Start();
_modbusMaster.WriteSingleCoil(1, 61, false);
System.Threading.Tasks.Task.Delay(50);
_modbusMaster.WriteSingleCoil(1, 62, false);
System.Threading.Tasks.Task.Delay(50);
_modbusMaster.WriteSingleCoil(1, 63, false);
System.Threading.Tasks.Task.Delay(50);
_modbusMaster.WriteSingleCoil(1, 64, true);
System.Threading.Tasks.Task.Delay(50);
}
2026-03-16 19:10:33 +08:00
private void SwitchWindow<T>(ref T windowInstance, Func<T> createFunc, string loadingTitle = null, string loadingSubtitle = null) where T : Window, new()
2026-03-11 15:21:27 +08:00
{
// 1. 停止当前窗口的定时器(不释放资源)
_readTimer?.Stop();
// 2. 检查资源是否可用(添加重连机制)
if (_tcpClient == null || !_tcpClient.Connected || _modbusMaster == null)
{
// 尝试重新连接
bool reconnectSuccess = TryReconnect();
if (!reconnectSuccess)
{
MessageBox.Show("TCP连接已断开请重新连接", "提示");
return;
}
}
// 3. 复用窗口实例:不存在则创建,存在则激活
if (windowInstance == null)
{
windowInstance = createFunc();
// 添加窗口关闭事件处理
windowInstance.Closed += (s, args) =>
{
2026-03-16 19:10:33 +08:00
WindowNavigationHelper.RestoreWindow(this, () => _readTimer?.Start());
2026-03-11 15:21:27 +08:00
};
}
2026-03-16 19:10:33 +08:00
// 4. 目标窗口完成首帧渲染后再切换,避免白屏
WindowNavigationHelper.ShowWithoutWhiteFlash(this, windowInstance, loadingTitle, loadingSubtitle);
2026-03-11 15:21:27 +08:00
}
private bool TryReconnect()
{
try
{
string plcIp = "192.168.1.10";
bool initSuccess = Data.ModbusResourceManager.Instance.Init(plcIp, 502);
if (initSuccess)
{
ma = new Function(_modbusMaster);
return true;
}
}
catch (Exception ex)
{
ShowErrorMsg($"重新连接失败:{ex.Message}");
}
return false;
}
private void BtnWrite401_Click(object sender, RoutedEventArgs e)
{
if (!double.TryParse(settingtime.Text.Trim(), out double writeValue) ||
writeValue > short.MaxValue)
{
ShowErrorMsg($"需输入整数(范围:{short.MinValue} ~ {short.MaxValue}");
settingtime.Focus();
return;
}
try
{
//await System.Threading.Tasks.Task.Run(() =>
// _modbusMaster.WriteSingleRegister(SlaveId, Address262, (ushort)writeValue)
//);
ma.WriteToPLCForNew(settingtime.Text.Trim(), 1430, Function.DataType.);
System.Threading.Tasks.Task.Delay(50);
_isManualInput = false; // 写入后恢复读取
//await ReadAddr400DataAsync(); // 刷新显示(确认写入成功)
}
catch (Exception ex)
{
//ShowErrorMsg($"地址400写入失败{ex.Message}");
}
}
private void BtnWrite402_Click(object sender, RoutedEventArgs e)
{
if (!double.TryParse(settingtime2.Text.Trim(), out double writeValue) ||
writeValue > short.MaxValue)
{
ShowErrorMsg($"需输入整数(范围:{short.MinValue} ~ {short.MaxValue}");
settingtime.Focus();
return;
}
try
{
//await System.Threading.Tasks.Task.Run(() =>
// _modbusMaster.WriteSingleRegister(SlaveId, Address262, (ushort)writeValue)
//);
ma.WriteToPLCForNew(settingtime2.Text.Trim(), 106, Function.DataType.);
System.Threading.Tasks.Task.Delay(50);
_isManualInput = false; // 写入后恢复读取
//await ReadAddr400DataAsync(); // 刷新显示(确认写入成功)
}
catch (Exception ex)
{
//ShowErrorMsg($"地址400写入失败{ex.Message}");
}
}
private async System.Threading.Tasks.Task ReadAddrStatusDataAsync()
{
try
{
bool[] result = _modbusMaster?.ReadCoils(0x01, 101, 1);
bool isTestRunning = result != null && result.Length > 0 && result[0];
Dispatcher.Invoke(() =>
{
if (isTestRunning)
{
status.Text = "正在运行";
statusPanel.Background = Brushes.Green;
if (!_wasRunning)
{
_testStartTime = DateTime.Now;
_recordAdded = false; // 测试刚开始,允许插入记录
}
}
else
{
status.Text = "空闲";
statusPanel.Background = Brushes.Blue;
// 状态从“运行”切换到“空闲”,且还没插入记录
if (_wasRunning && !_recordAdded)
{
AddTestRecord(); // 插入记录
_recordAdded = true; // 标记已插入
}
}
_wasRunning = isTestRunning; // 更新上一次状态
});
}
catch (Exception ex)
{
ShowErrorMsg($"读取运行状态失败:{ex.Message}");
}
}
private void AddTestRecord()
{
try
{
// 计算测试时长
TimeSpan duration = DateTime.Now - _testStartTime;
string durationStr = $"{duration.Minutes:00}:{duration.Seconds:00}";
// 获取当前流量值
double currentFlowRate = 0;
if (!string.IsNullOrEmpty(settingtime2.Text) && double.TryParse(settingtime2.Text, out double flow))
{
currentFlowRate = flow;
}
// 获取当前时间
string currentTime = DateTime.Now.ToString("HH:mm");
string currentDate = DateTime.Now.ToString("yy/MM/dd");
// 添加到报表窗口(如果存在或创建)
Dispatcher.Invoke(() =>
{
// 如果窗口不存在,先创建但不显示
if (_reportWindow4 == null)
{
_reportWindow4 = new ReportWindow4();
}
string no = ConfigurationManager.AppSettings["No"]?.ToString();
// 添加记录到窗口(无论窗口是否显示)
_reportWindow4.AddRecord(currentTime, currentDate, currentFlowRate, durationStr, no);
});
}
catch (Exception ex)
{
ShowErrorMsg($"记录测试数据失败:{ex.Message}");
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// 停止定时器
_readTimer?.Stop();
// 停止ViewModel的定时器
if (DataContext is MainViewModel viewModel)
{
viewModel.StopTimer();
}
// 释放Modbus资源
ModbusResourceManager.Instance?.Dispose();
2026-03-16 19:10:33 +08:00
// 延后到当前窗口完成关闭后再统一关停,避免关闭重入。
AppShutdownCoordinator.RequestShutdown();
2026-03-11 15:21:27 +08:00
}
private void Window_Closed(object sender, EventArgs e)
{
2026-03-16 19:10:33 +08:00
// 由应用级关停统一处理其他窗口,避免关闭链路重入。
2026-03-11 15:21:27 +08:00
}
}
}