Files
zijiuqizonghejianyanyi/MainWindow2.xaml.cs
2026-03-11 15:21:27 +08:00

752 lines
25 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 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 MainWindow2 : Window
{
private MainWindow _mainWindow;
private MainWindow2 _mainWindow2;
private MainWindow3 _mainWindow3;
private MainWindow4 _mainWindow4;
private ReportWindow2 _reportWindow2;
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 = 310; // 32位浮点数float32占2个寄存器
private bool _isManualInput = false; // 手动输入标记true=输入中暂停读取false=正常读取
private readonly DispatcherTimer _readTimer;
Function ma;
DataChange c = new DataChange();
public MainWindow2()
{
InitializeComponent();
_readTimer = InitDispatcherTimer();
//InitializeModbusTcp();
BindInputFocusEvents();
}
private void BindInputFocusEvents()
{
// 地址400输入框count
settingtime.GotFocus += (s, e) => _isManualInput = true; // 获得焦点→暂停读取
settingtime.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();
// 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 System.Threading.Tasks.Task.Delay(50);
await ReadAddr416DataAsync();
await System.Threading.Tasks.Task.Delay(50);
await ReadAddr1301DataAsync();
await System.Threading.Tasks.Task.Delay(50);
await ReadAddr4161DataAsync();
}
await ReadAddrStatusDataAsync();
}
private async System.Threading.Tasks.Task ReadAddr262DataAsync()
{
try
{
if (_tcpClient == null || !_tcpClient.Connected)
{
ShowErrorMsg("Modbus连接已断开请重新连接设备。");
return;
}
ushort[] registers = await System.Threading.Tasks.Task.Run(() =>
_modbusMaster?.ReadHoldingRegisters(1, Address262, 2)
);
if (registers != null)
{
float addr406Value = c.UshortToFloat(registers[1], registers[0]);
Dispatcher.Invoke(() => settingtime.Text = addr406Value.ToString("F0"));
}
}
catch (Exception ex)
{
//ShowErrorMsg($"读取地址406失败{ex.Message}");
}
}
private async System.Threading.Tasks.Task ReadAddr404DataAsync()
{
try
{
// 检查连接
if (_tcpClient == null || !_tcpClient.Connected)
{
ShowErrorMsg("Modbus连接已断开请重新连接设备。");
return;
}
ushort[] registers = await System.Threading.Tasks.Task.Run(() =>
_modbusMaster?.ReadHoldingRegisters(1, 312, 1)
);
if (registers != null)
{
int addr406Value = registers[0];
Dispatcher.Invoke(() => settingtime2.Text = addr406Value.ToString("F0"));
}
}
catch (Exception ex)
{
//ShowErrorMsg($"读取地址406失败{ex.Message}");
}
}
private async System.Threading.Tasks.Task ReadAddr130DataAsync()
{
try
{
if (_tcpClient == null || !_tcpClient.Connected)
{
ShowErrorMsg("Modbus连接已断开请重新连接设备。");
return;
}
ushort[] registers = _modbusMaster.ReadHoldingRegisters(1, 82, 1);
if (registers != null)
{
int addr406Value = registers[0];
Dispatcher.Invoke(() => min2.Text = addr406Value.ToString("F0"));
}
await Task.CompletedTask;
}
catch (Exception ex)
{
//ShowErrorMsg($"读取地址406失败{ex.Message}");
}
}
private async System.Threading.Tasks.Task ReadAddr406DataAsync()
{
try
{
if (_tcpClient == null || !_tcpClient.Connected)
{
ShowErrorMsg("Modbus连接已断开请重新连接设备。");
return;
}
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(() => min.Text = addr406Value.ToString("F2"));
}
}
catch (Exception ex)
{
//ShowErrorMsg($"读取地址406失败{ex.Message}");
}
}
private async System.Threading.Tasks.Task ReadAddr416DataAsync()
{
try
{
if (_tcpClient == null || !_tcpClient.Connected)
{
ShowErrorMsg("Modbus连接已断开请重新连接设备。");
return;
}
ushort[] registers = await System.Threading.Tasks.Task.Run(() =>
_modbusMaster.ReadHoldingRegisters(1, 1100, 2)
);
if (registers != null)
{
float addr406Value = c.UshortToFloat(registers[1], registers[0]);
Dispatcher.Invoke(() => min3.Text = addr406Value.ToString("F2"));
}
}
catch (Exception ex)
{
//ShowErrorMsg($"读取地址406失败{ex.Message}");
}
}
private async System.Threading.Tasks.Task ReadAddr1301DataAsync()
{
try
{
if (_tcpClient == null || !_tcpClient.Connected)
{
ShowErrorMsg("Modbus连接已断开请重新连接设备。");
return;
}
ushort[] registers = await System.Threading.Tasks.Task.Run(() =>
_modbusMaster?.ReadHoldingRegisters(1, 1102, 2)
);
if (registers != null)
{
float addr406Value = c.UshortToFloat(registers[1], registers[0]);
Dispatcher.Invoke(() => min4.Text = addr406Value.ToString("F2"));
}
}
catch (Exception ex)
{
//ShowErrorMsg($"读取地址406失败{ex.Message}");
}
}
private async System.Threading.Tasks.Task ReadAddr4161DataAsync()
{
try
{
if (_tcpClient == null || !_tcpClient.Connected)
{
ShowErrorMsg("Modbus连接已断开请重新连接设备。");
return;
}
ushort[] registers = await System.Threading.Tasks.Task.Run(() =>
_modbusMaster.ReadHoldingRegisters(1, 1106, 2)
);
if (registers != null)
{
float addr406Value = c.UshortToFloat(registers[1], registers[0]);
Dispatcher.Invoke(() => min5.Text = addr406Value.ToString("F2"));
}
}
catch (Exception ex)
{
//ShowErrorMsg($"读取地址406失败{ex.Message}");
}
}
private async System.Threading.Tasks.Task ReadAddrStatusDataAsync()
{
try
{
bool[] result = _modbusMaster?.ReadCoils(0x01, 81, 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 ShowErrorMsg(string msg)
{
Dispatcher.Invoke(() =>
{
MessageBox.Show(msg, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
});
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//ma.BtnClickFunctionForNew(Function.ButtonType.切换型, 170);
OpenQuantitativeSupplyWindow2();
}
private void OpenQuantitativeSupplyWindow2()
{
try
{
SwitchWindow(ref _reportWindow2, () => new ReportWindow2());
}
catch (Exception ex)
{
MessageBox.Show($"打开定量供应检验窗口时出错:{ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
ma.BtnClickFunctionForNew(Function.ButtonType., 80);
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
//ma.BtnClickFunctionForNew(Function.ButtonType.复归型, 83);
ma.BtnClickFunctionForNew(Function.ButtonType., 83);
}
private void Button_Click_3(object sender, RoutedEventArgs e)
{
ma.BtnClickFunctionForNew(Function.ButtonType., 84);
}
private void Button_Click_4(object sender, RoutedEventArgs e)
{
SwitchWindow(ref _mainWindow, () => new MainWindow());
}
private void Button_Click_5(object sender, RoutedEventArgs e)
{
SwitchWindow(ref _mainWindow2, () => new MainWindow2());
}
private void Button_Click_6(object sender, RoutedEventArgs e)
{
SwitchWindow(ref _mainWindow3, () => new MainWindow3());
}
private void Button_Click_7(object sender, RoutedEventArgs e)
{
SwitchWindow(ref _mainWindow4, () => new MainWindow4());
}
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., 62);
System.Threading.Tasks.Task.Delay(50);
_readTimer.Start();
_modbusMaster.WriteSingleCoil(1, 61, false);
System.Threading.Tasks.Task.Delay(50);
_modbusMaster.WriteSingleCoil(1, 62, true);
System.Threading.Tasks.Task.Delay(50);
_modbusMaster.WriteSingleCoil(1, 63, false);
System.Threading.Tasks.Task.Delay(50);
_modbusMaster.WriteSingleCoil(1, 64, false);
System.Threading.Tasks.Task.Delay(50);
}
private void SwitchWindow<T>(ref T windowInstance, Func<T> createFunc) where T : Window, new()
{
// 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) =>
{
// 窗口关闭时重新启动定时器并显示当前窗口
_readTimer?.Start();
//this.Show();
this.Activate();
};
}
else
{
// 激活已存在的窗口(前置显示)
windowInstance.Activate();
//return;
}
// 4. 切换窗口:隐藏当前窗口,显示目标窗口(非模态)
this.Hide();
windowInstance.Show(); // 使用 Show() 而不是 ShowDialog()
}
// 添加重连方法
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 (!short.TryParse(settingtime.Text.Trim(), out short writeValue) ||
writeValue < short.MinValue || 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(), 310, 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 (!short.TryParse(settingtime2.Text.Trim(), out short writeValue) ||
writeValue < short.MinValue || 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(), 312, Function.DataType.);
System.Threading.Tasks.Task.Delay(50);
_isManualInput = false; // 写入后恢复读取
//await ReadAddr400DataAsync(); // 刷新显示(确认写入成功)
}
catch (Exception ex)
{
//ShowErrorMsg($"地址400写入失败{ex.Message}");
}
}
private void AddTestRecord()
{
try
{
// 计算测试时长
TimeSpan duration = DateTime.Now - _testStartTime;
string durationStr = $"{duration.Minutes:00}:{duration.Seconds:00}";
// 获取当前流量值
double startPress = 0, endPress = 0, diffPress = 0, ProtectTime = 0;
if (!string.IsNullOrEmpty(min3.Text) && double.TryParse(min3.Text, out double flow))
{
startPress = flow;
}
if (!string.IsNullOrEmpty(min4.Text) && double.TryParse(min4.Text, out double flow2))
{
endPress = flow2;
}
if (!string.IsNullOrEmpty(min5.Text) && double.TryParse(min5.Text, out double flow5))
{
diffPress = flow5;
}
if (!string.IsNullOrEmpty(min2.Text) && double.TryParse(min2.Text, out double flow3))
{
ProtectTime = flow3;
}
// 获取当前时间
string currentTime = DateTime.Now.ToString("HH:mm");
string currentDate = DateTime.Now.ToString("yy/MM/dd");
// 添加到报表窗口(如果存在)
Dispatcher.Invoke(() =>
{
// 如果窗口不存在,先创建但不显示
if (_reportWindow2 == null)
{
_reportWindow2 = new ReportWindow2();
}
string No = ConfigurationManager.AppSettings["No"]?.ToString();
// 添加记录到窗口(无论窗口是否显示)
_reportWindow2.AddRecord(currentTime, currentDate, startPress, endPress, diffPress, ProtectTime,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();
// 确保应用程序完全退出
Application.Current.Shutdown();
}
private void Window_Closed(object sender, EventArgs e)
{
// 清理其他窗口实例
//_mainWindow2?.Close();
_mainWindow3?.Close();
_mainWindow4?.Close();
_mainWindow?.Close();
_reportWindow2?.Close();
}
//private void number_GotFocus(object sender, RoutedEventArgs e)
//{
//}
//private void pressureDiff2_GotFocus(object sender, RoutedEventArgs e)
//{
// SaveAppSetting("No", pressureDiff2.Text);
//}
//public bool SaveAppSetting(string key, string value)
//{
// try
// {
// // 1. 获取当前程序的配置文件路径(编译后的 exe.config
// string configPath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
// // 2. 加载配置文件ExeConfigurationFileMap 指定配置路径)
// ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap { ExeConfigFilename = configPath };
// Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
// // 3. 处理 appSettings 节点
// if (config.AppSettings.Settings[key] == null)
// {
// // 键不存在 → 新增配置
// config.AppSettings.Settings.Add(key, value);
// }
// else
// {
// // 键已存在 → 更新配置
// config.AppSettings.Settings[key].Value = value;
// }
// // 4. 保存配置(重要!否则修改不生效)
// config.Save(ConfigurationSaveMode.Modified);
// // 5. 刷新 ConfigurationManager 缓存(可选,让后续读取能立即获取新值)
// ConfigurationManager.RefreshSection("appSettings");
// return true;
// }
// catch (Exception ex)
// {
// // 捕获异常(如权限不足、文件被占用等)
// MessageBox.Show($"保存配置失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
// return false;
// }
//}
}
public class TestRecordForNegativePressure
{
public int Id { get; set; }
public string Time { get; set; }
public string Date { get; set; }
public double StartPress { get; set; } // 供氧流量L/min
public double EndPress { get; set; } // 测试时长
public double DiffPress { get; set; } // 测试时长
public DateTime CreateTime { get; set; }
public double ProtectTime { get; set; }
public string No { get; set; }
}
}