using Modbus.Device; using System; using System.Configuration; using System.Net.Sockets; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Threading; using 自救器呼吸器综合检验仪.Data; namespace 自救器呼吸器综合检验仪 { public partial class ParameterSettingsWindow : Window { private MainWindow _mainWindow; private MainWindow2 _mainWindow2; private MainWindow3 _mainWindow3; private MainWindow4 _mainWindow4; private readonly DispatcherTimer _readTimer; private bool _isManualInput = false; // 手动输入标记:true=输入中(暂停读取),false=正常读取 private TcpClient _tcpClient => ModbusResourceManager.Instance.TcpClient; private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster; Function ma; DataChange c = new DataChange(); public ParameterSettingsWindow() { InitializeComponent(); LoadCurrentSettings(); _readTimer = InitDispatcherTimer(); } private void EnsureWindowedLayout() { WindowState = WindowState.Normal; Width = 1024; Height = 600; Rect workArea = SystemParameters.WorkArea; Left = workArea.Left + (workArea.Width - Width) / 2; Top = workArea.Top + (workArea.Height - Height) / 2; } 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 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(); } } // 加载当前设置 private void LoadCurrentSettings() { // 这里可以连接实际的数据源来加载当前设置 // 目前使用默认值 } // 保存按钮点击事件 //private void SaveButton_Click(object sender, RoutedEventArgs e) //{ // try // { // // 验证并保存所有参数 // if (ValidateParameters()) // { // SaveParameters(); // MessageBox.Show("参数保存成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information); // } // } // catch (Exception ex) // { // MessageBox.Show($"保存参数时出错:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); // } //} // 重置按钮点击事件 private void ResetButton_Click(object sender, RoutedEventArgs e) { var result = MessageBox.Show("确定要重置所有参数吗?", "确认重置", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) { ResetToDefaults(); } } // 返回按钮点击事件 private void ReturnButton_Click(object sender, RoutedEventArgs e) { SwitchWindow(ref _mainWindow, () => new MainWindow()); } private void SwitchWindow(ref T windowInstance, Func 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) => { WindowNavigationHelper.RestoreWindow(this, () => _readTimer?.Start()); }; } else { WindowNavigationHelper.ShowWithoutWhiteFlash(this, windowInstance); return; } WindowNavigationHelper.ShowWithoutWhiteFlash(this, windowInstance); } // 添加重连方法 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 async System.Threading.Tasks.Task ReadAddr262DataAsync() { try { ushort[] registers3 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 1428, 2) ); if (registers3 != null) { float addr406Value = c.UshortToFloat(registers3[1], registers3[0]); Dispatcher.Invoke(() => txtPressureDiffCoefficient.Text = addr406Value.ToString("F2")); } ushort[] registers4 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 484, 2) ); if (registers4 != null) { float addr406Value = c.UshortToFloat(registers4[1], registers4[0]); Dispatcher.Invoke(() => txtUpperLimit.Text = addr406Value.ToString("F2")); } ushort[] registers5 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 482, 2) ); if (registers5 != null) { float addr406Value = c.UshortToFloat(registers5[1], registers5[0]); Dispatcher.Invoke(() => txtLowerLimit.Text = addr406Value.ToString("F2")); } ushort[] registers6 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 490, 2) ); if (registers6 != null) { float addr406Value = c.UshortToFloat(registers6[1], registers6[0]); Dispatcher.Invoke(() => txtLargeFlowCoefficient2.Text = addr406Value.ToString("F2")); } ushort[] registers7 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 492, 2) ); if (registers7 != null) { float addr406Value = c.UshortToFloat(registers7[1], registers7[0]); Dispatcher.Invoke(() => txtSmallFlowCoefficient2.Text = addr406Value.ToString("F2")); } ushort[] registers8 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 1328, 2) ); if (registers8 != null) { float addr406Value = c.UshortToFloat(registers8[1], registers8[0]); Dispatcher.Invoke(() => txtLargeFlowCoefficient.Text = addr406Value.ToString("F2")); } ushort[] registers9 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 1378, 2) ); if (registers9 != null) { float addr406Value = c.UshortToFloat(registers9[1], registers9[0]); Dispatcher.Invoke(() => txtSmallFlowCoefficient.Text = addr406Value.ToString("F2")); } ushort[] registers10 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 308, 2) ); if (registers10 != null) { float addr406Value = c.UshortToFloat(registers10[1], registers10[0]); Dispatcher.Invoke(() => txtQualityThreshold.Text = addr406Value.ToString("F2")); } ushort[] registers11 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 330, 2) ); if (registers11 != null) { int addr406Value = registers11[0]; Dispatcher.Invoke(() => txtExhaustTime.Text = addr406Value.ToString("F0")); } ushort[] registers12 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 326, 1) ); if (registers12 != null) { //float addr406Value = c.UshortToFloat(registers12[1], registers12[0]); int addr406Value = registers12[0]; Dispatcher.Invoke(() => txtPositiveError.Text = addr406Value.ToString("F0")); } ushort[] registers13 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 316, 1) ); if (registers13 != null) { //float addr406Value = c.UshortToFloat(registers13[1], registers13[0]); float addr406Value = registers13[0]; Dispatcher.Invoke(() => txtNegativeError.Text = addr406Value.ToString("F0")); } ushort[] registers14 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 324, 1) ); if (registers14 != null) { int addr406Value = registers14[0]; Dispatcher.Invoke(() => txtPositivePIDTime.Text = addr406Value.ToString("F0")); } ushort[] registers15 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 314, 1) ); if (registers15 != null) { int addr406Value = registers15[0]; Dispatcher.Invoke(() => txtNegativePIDTime.Text = addr406Value.ToString("F0")); } ushort[] registers16 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 328, 1) ); if (registers16 != null) { int addr406Value = registers16[0]; Dispatcher.Invoke(() => txtPositiveDelay.Text = addr406Value.ToString("F0")); } ushort[] registers17 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 318, 1) ); if (registers17 != null) { int addr406Value = registers17[0]; Dispatcher.Invoke(() => txtNegativeDelay.Text = addr406Value.ToString("F0")); } ushort[] registers18 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 292, 2) ); if (registers18 != null) { float addr406Value = c.UshortToFloat(registers18[1], registers18[0]); Dispatcher.Invoke(() => txtPositivePIDPressure.Text = addr406Value.ToString("F2")); } ushort[] registers19 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 290, 2) ); if (registers19 != null) { float addr406Value = c.UshortToFloat(registers19[1], registers19[0]); Dispatcher.Invoke(() => txtNegativePIDPressure.Text = addr406Value.ToString("F2")); } ushort[] registers20 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 1430, 2) ); if (registers20 != null) { float addr406Value = c.UshortToFloat(registers20[1], registers20[0]); Dispatcher.Invoke(() => pressureDiff.Text = addr406Value.ToString("F2")); } ushort[] registers21 = await System.Threading.Tasks.Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, 1330, 2) ); if (registers21 != null) { float addr406Value = c.UshortToFloat(registers21[1], registers21[0]); Dispatcher.Invoke(() => flow.Text = addr406Value.ToString("F2")); } // ushort[] registers22 = await System.Threading.Tasks.Task.Run(() => //_modbusMaster?.ReadHoldingRegisters(1, 390, 2) //); // if (registers22 != null) // { // int addr406Value = registers22[0]; // Dispatcher.Invoke(() => setsound.Text = addr406Value.ToString("F0")); // } } catch (Exception ex) { //ShowErrorMsg($"读取地址406失败:{ex.Message}"); } } private void ShowErrorMsg(string msg) { Dispatcher.Invoke(() => { MessageBox.Show(msg, "错误", MessageBoxButton.OK, MessageBoxImage.Error); }); } private void Window_Loaded(object sender, RoutedEventArgs e) { EnsureWindowedLayout(); 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(); } private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { // 停止定时器 _readTimer?.Stop(); // 停止ViewModel的定时器 if (DataContext is MainViewModel viewModel) { viewModel.StopTimer(); } // 释放Modbus资源 ModbusResourceManager.Instance?.Dispose(); // 延后到当前窗口完成关闭后再统一关停,避免关闭重入。 AppShutdownCoordinator.RequestShutdown(); } private void Window_Closed(object sender, EventArgs e) { // 由应用级关停统一处理其他窗口,避免关闭链路重入。 } // 重置为默认值 private void ResetToDefaults() { txtPressureDiffCoefficient.Text = "0.00"; txtUpperLimit.Text = "0.0"; txtLowerLimit.Text = "0.0"; txtLargeFlowCoefficient.Text = "0.00"; txtSmallFlowCoefficient.Text = "0.00"; //txtYear.Text = "0"; //txtMonth.Text = "0"; //txtDay.Text = "0"; //txtHour.Text = "0"; //txtMinute.Text = "0"; //txtSecond.Text = "0"; txtQualityThreshold.Text = "0.00"; txtExhaustTime.Text = "0"; txtPositiveError.Text = "0"; txtNegativeError.Text = "0"; txtPositivePIDTime.Text = "0"; txtNegativePIDTime.Text = "0"; txtPositiveDelay.Text = "0"; txtNegativeDelay.Text = "0"; txtPositivePIDPressure.Text = "0.00"; txtNegativePIDPressure.Text = "0.00"; } private void txtPressureDiffCoefficient_TouchDown(object sender, System.Windows.Input.TouchEventArgs e) { ma.WriteToPLCForNew(txtPressureDiffCoefficient.Text.Trim(), 1428, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void Button_Click(object sender, RoutedEventArgs e) { ma.BtnClickFunctionForNew(Function.ButtonType.复归型, 1301); } private void txtLargeFlowCoefficient2_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtLargeFlowCoefficient2.Text.Trim(), 490, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtSmallFlowCoefficient2_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtSmallFlowCoefficient2.Text.Trim(), 492, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtPressureDiffCoefficient_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtPressureDiffCoefficient.Text.Trim(), 1428, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtUpperLimit_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtUpperLimit.Text.Trim(), 484, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtLowerLimit_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtLowerLimit.Text.Trim(), 482, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtLargeFlowCoefficient_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtLargeFlowCoefficient.Text.Trim(), 1328, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtSmallFlowCoefficient_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtSmallFlowCoefficient.Text.Trim(), 1378, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void Button_Click_1(object sender, RoutedEventArgs e) { ma.BtnClickFunctionForNew(Function.ButtonType.复归型, 1300); } private void txtQualityThreshold_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtQualityThreshold.Text.Trim(), 308, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtExhaustTime_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtExhaustTime.Text.Trim(), 330, Function.DataType.整形); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtPositiveError_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtPositiveError.Text.Trim(), 326, Function.DataType.整形); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } //private async void Button_Click_2(object sender, RoutedEventArgs e) //{ // ma.BtnClickFunctionForNew(Function.ButtonType.切换型, 24); // bool[] b = await _modbusMaster.ReadCoilsAsync(1, 24, 1); // if (b != null && b.Length > 0) // { // if (!b[0]) // { // closesound.Content = "关闭语音"; // } // else // { // closesound.Content = "开启语音"; // } // } //} private void Button_Click_3(object sender, RoutedEventArgs e) { ma.BtnClickFunctionForNew(Function.ButtonType.切换型, 25); } //private void setsound_GotFocus(object sender, RoutedEventArgs e) //{ // ma.WriteToPLCForNew(setsound.Text.Trim(), 390, Function.DataType.整形); // System.Threading.Tasks.Task.Delay(50); // _isManualInput = false; // 写入后恢复读取 // t0.Focus(); //} private void txtNegativeError_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtNegativeError.Text.Trim(), 316, Function.DataType.整形); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtPositivePIDTime_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtPositivePIDTime.Text.Trim(), 324, Function.DataType.整形); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtNegativePIDTime_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtNegativePIDTime.Text.Trim(), 314, Function.DataType.整形); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtPositiveDelay_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtPositiveDelay.Text.Trim(), 328, Function.DataType.整形); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtNegativeDelay_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtNegativeDelay.Text.Trim(), 318, Function.DataType.整形); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtPositivePIDPressure_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtPositivePIDPressure.Text.Trim(), 292, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } private void txtNegativePIDPressure_GotFocus(object sender, RoutedEventArgs e) { ma.WriteToPLCForNew(txtNegativePIDPressure.Text.Trim(), 290, Function.DataType.浮点型); System.Threading.Tasks.Task.Delay(50); _isManualInput = false; // 写入后恢复读取 t0.Focus(); } //private void pressureDiff2_GotFocus(object sender, RoutedEventArgs e) //{ //} /// /// 保存 AppSettings 配置到配置文件 /// /// 配置键名 /// 配置值 /// 是否保存成功 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; } } } }