using Microsoft.Win32;
using Modbus.Device;
using Modbus;
using OfficeOpenXml;
using System;
using System.Configuration;
using System.Data.SQLite;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using 口罩泄露定制款;
using static ShanghaiEnvironmentalTechnology.Window5;
namespace ShanghaiEnvironmentalTechnology
{
///
/// 防窒息压力测试窗口(Modbus通信+压力数据处理)
///
public partial class Window3 : Window, IDisposable
{
DataChange c = new DataChange();
#region 寄存器/线圈地址定义(按功能分组)
// 压力设置相关
private readonly ushort _pressureSettingRegisterAddress = 350; // 开阀压差判别(D350)
private readonly ushort _pressureCloseSettingRegisterAddress = 352; // 关阀压差判别(D352)
private readonly ushort _openRegisterAddress = 202; // 开阀压力记录地址
private readonly ushort _closeRegisterAddress = 206; // 关阀压力记录地址
private readonly ushort _pressureRegisterAddress = 1372; // 实时压力读取地址
// 测试控制线圈
private readonly ushort _testStartAddress = 0x0014; // 防窒息压力测试启动(M20)
private readonly ushort _testStopAddress = 0x001E; // 防窒息压力测试停止(M30)
private readonly ushort _calibrationCoilAddress = 0x0048; // 校准线圈(M72)
private bool _lastTestRunningState = false; // 记录上一次的测试运行状态
private bool _isDelayedButtonClickPending = false;
#endregion
#region 私有字段
private TcpClient _tcpClient;
private IModbusMaster _modbusMaster;
private System.Timers.Timer _pressureReadTimer; // 实时压力读取定时器
private System.Timers.Timer _settingReadTimer; // 开阀压力设置定时器
private System.Timers.Timer _settingReadTimer2; // 关阀压力设置定时器
private System.Timers.Timer startTimer; // 启动状态实时定时器
Function fc;
#endregion
public Window3()
{
InitializeComponent();
InitializeModbusTcp();
Loaded += Window_Loaded;
}
#region 初始化与资源释放
///
/// 初始化Modbus连接和定时器
///
private void InitializeModbusTcp()
{
try
{
string plcIp = ConfigurationManager.AppSettings["PLC1_IP"];
int plcPort = int.Parse(ConfigurationManager.AppSettings["PLC1_Port"]);
_tcpClient = new TcpClient(plcIp, plcPort);
_modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);
_modbusMaster.Transport.ReadTimeout = 3000;
_modbusMaster.Transport.WriteTimeout = 3000;
// 初始化定时器
_pressureReadTimer = CreateTimer(1000, OnPressureTimerElapsed);
_settingReadTimer = CreateTimer(1000, OnSettingReadTimerTimerElapsed);
_settingReadTimer2 = CreateTimer(1000, OnSettingReadTimerTimerElapsed2);
startTimer = CreateTimer(200, OnStartTimerElapsed);
fc = new Function(_modbusMaster);
// 初始化数据库
InitializeDatabase();
}
catch (Exception ex)
{
ShowError($"Modbus初始化失败: {ex.Message}");
}
}
///
/// 通用定时器创建方法
///
private System.Timers.Timer CreateTimer(int intervalMs, ElapsedEventHandler elapsedAction)
{
var timer = new System.Timers.Timer(intervalMs)
{
AutoReset = true,
Enabled = true
};
timer.Elapsed += elapsedAction;
return timer;
}
///
/// 实时流量读取定时器(修正跨线程访问UI问题)
///
//private void OnStartTimerElapsed(object sender, ElapsedEventArgs e)
//{
// try
// {
// bool[] result = _modbusMaster?.ReadCoils(0x01, 21, 1);
// bool isTestRunning = result != null && result.Length > 0 && result[0];
// string testStartButtonText = "";
// string ButtonStatus = "";
// string currentLanguage = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
// if (currentLanguage == "en-US")
// {
// testStartButtonText = "Test Start Success";
// ButtonStatus = "Test initiation";
// }
// else if (currentLanguage == "zh-CN")
// {
// testStartButtonText = "测试启动成功";
// ButtonStatus = "测试启动";
// }
// TestStartButton.Dispatcher.Invoke(() =>
// {
// if (isTestRunning)
// {
// btnsetting.IsEnabled = false;
// btnjiaozhun.IsEnabled = false;
// btnsetting2.IsEnabled = false;
// TestStartButton.Content = testStartButtonText;
// TestStartButton.Foreground = Brushes.LightGreen;
// }
// else
// {
// btnsetting.IsEnabled = true;
// btnjiaozhun.IsEnabled = true;
// btnsetting2.IsEnabled = true;
// TestStartButton.Content = ButtonStatus;
// TestStartButton.Foreground = Brushes.White;
// Button_Click_3(sender, new RoutedEventArgs { });
// // 测试结束,延迟1秒调用 Button_Click_3,只调用一次
// lock (this) // 简单锁防止多线程竞争
// {
// if (!_isDelayedButtonClickPending)
// {
// _isDelayedButtonClickPending = true;
// // 延迟1秒执行,避免阻塞定时器线程
// Task.Delay(1000).ContinueWith(_ =>
// {
// // 回到 UI 线程执行 Button_Click_3
// TestStartButton.Dispatcher.Invoke(() =>
// {
// try
// {
// Button_Click_3(sender, new RoutedEventArgs());
// }
// finally
// {
// // 执行完毕后重置标志
// lock (this)
// {
// _isDelayedButtonClickPending = false;
// }
// }
// });
// });
// }
// }
// }
// });
// }
// catch (Exception ex)
// {
// Console.WriteLine($"读取线圈或更新UI失败:{ex.Message}");
// }
//}
private void OnStartTimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
bool[] result = _modbusMaster?.ReadCoils(0x01, 21, 1);
bool isTestRunning = result != null && result.Length > 0 && result[0];
string testStartButtonText = "";
string ButtonStatus = "";
string currentLanguage = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
if (currentLanguage == "en-US")
{
testStartButtonText = "Test Start Success";
ButtonStatus = "Test initiation";
}
else if (currentLanguage == "zh-CN")
{
testStartButtonText = "测试启动成功";
ButtonStatus = "测试启动";
}
TestStartButton.Dispatcher.Invoke(() =>
{
if (isTestRunning)
{
btnsetting.IsEnabled = false;
btnjiaozhun.IsEnabled = false;
btnsetting2.IsEnabled = false;
TestStartButton.Content = testStartButtonText;
TestStartButton.Foreground = Brushes.LightGreen;
// 测试开始:重置下降沿标志,并更新上次状态
_lastTestRunningState = true;
// 注意:不重置 _isDelayedButtonClickPending,因为尚未调度或已调度完成不影响
}
else
{
btnsetting.IsEnabled = true;
btnjiaozhun.IsEnabled = true;
btnsetting2.IsEnabled = true;
TestStartButton.Content = ButtonStatus;
TestStartButton.Foreground = Brushes.White;
// 检测下降沿:上一次为 true,当前为 false
bool isFallingEdge = _lastTestRunningState == true && isTestRunning == false;
// 更新上一次状态
_lastTestRunningState = isTestRunning;
// 仅在下降沿且未调度延迟任务时,调度一次
if (isFallingEdge && !_isDelayedButtonClickPending)
{
_isDelayedButtonClickPending = true;
Task.Delay(0).ContinueWith(_ =>
{
TestStartButton.Dispatcher.Invoke(() =>
{
try
{
Button_Click_3(sender, new RoutedEventArgs());
}
finally
{
_isDelayedButtonClickPending = false;
}
});
});
}
}
});
}
catch (Exception ex)
{
Console.WriteLine($"读取线圈或更新UI失败:{ex.Message}");
}
}
///
/// 释放资源(定时器、TCP连接)
///
public void Dispose()
{
_pressureReadTimer?.Dispose();
_settingReadTimer?.Dispose();
_settingReadTimer2?.Dispose();
_tcpClient?.Close();
_tcpClient?.Dispose();
_modbusMaster = null;
}
///
/// 窗口关闭时释放资源
///
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
Dispose();
}
#endregion
#region 定时器读取逻辑
///
/// 实时压力读取定时器
///
private void OnPressureTimerElapsed(object sender, ElapsedEventArgs e)
{
ReadAndUpdateRegister(
_pressureRegisterAddress,
true,
value => UpdateRealTimerPressureUI(value.ToString())
);
}
///
/// 开阀压力设置定时器(带编辑锁判断)
///
private void OnSettingReadTimerTimerElapsed(object sender, ElapsedEventArgs e)
{
ReadAndUpdateRegister(
_pressureSettingRegisterAddress, false,
value => UpdateSettingUI(value.ToString())
);
}
///
/// 关阀压力设置定时器(带编辑锁判断)
///
private void OnSettingReadTimerTimerElapsed2(object sender, ElapsedEventArgs e)
{
ReadAndUpdateRegister(
_pressureCloseSettingRegisterAddress, false,
value => UpdateSettingUI2(value.ToString())
);
}
///
/// 通用寄存器读取并更新UI,支持16位整数和32位浮点数
///
private void ReadAndUpdateRegister(ushort address, bool isFloat, Action