using Modbus.Device; using Sunny.UI; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using 全自动水压检测仪; using 全自动水压检测仪.Data; using 全自动水压检测仪.DATA; namespace 全自动水压检测仪 { public partial class Coeffiicientsetting : UIForm { //private Coeffiicientsetting _coeffiicientsetting; private HighTemperatureMode _highTemperatureMode; private NormalTemperatureMode _normalTemperatureMode; private TcpClient _tcpClient => ModbusResourceManager.Instance.TcpClient; private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster; Function ma; DataChange c; private System.Windows.Forms.Timer _readTimer; private bool _isManualInput = false; // 手动输入标记 private bool _isSwitchingWindow = false; // 窗口切换标记,避免并发 private CancellationTokenSource _cts; // 取消令牌,用于异步操作终止 public Coeffiicientsetting() { InitializeComponent(); _cts = new CancellationTokenSource(); InitTimer(); // 初始化定时器 } private System.Windows.Forms.Timer InitTimer() { var timer = new System.Windows.Forms.Timer() { Interval = 1000 }; timer.Tick += async (s, e) => { if (!_isManualInput && _modbusMaster != null) { try { await ReadLeakTestParametersAsync(); } catch { } } }; timer.Start(); return timer; } private class RegisterConfig { public ushort Address { get; set; } // Modbus寄存器地址(ushort类型匹配方法参数) public UITextBox TextBox { get; set; } // 适配SunnyUI的UITextBox控件 public string Format { get; set; } // 数值格式化字符串 public bool IsInteger { get; set; } // 是否为整数类型(新增) } private async Task ReadLeakTestParametersAsync() { // 前置校验:连接状态检查 if (_tcpClient == null || !_tcpClient.Connected || _modbusMaster == null) { return; } try { var registerConfigs = new List { CreateRegisterConfig(394, uiTextBox1, "F2",false), // 控制压力系数 CreateRegisterConfig(1134, uiTextBox3, "F2",false), // 压力保护输入 CreateRegisterConfig(376, uiTextBox2, "F2",false), // 压力上限 CreateRegisterConfig(374, uiTextBox4, "F2",false), // 压力下限 CreateRegisterConfig(1482, uiTextBox8, "F2",false), // 温度系数 CreateRegisterConfig(1176, uiTextBox6, "F2",false), // 出口温度系数 CreateRegisterConfig(1076, uiTextBox7, "F2",false), // 常温液位系数 CreateRegisterConfig(1086, uiTextBox9, "F2",false), // 常温液位上限 CreateRegisterConfig(1084, uiTextBox10, "F2",false), // 常温液位下限 CreateRegisterConfig(1026, uiTextBox12, "F2",false), // 高温液位系数 CreateRegisterConfig(1036, uiTextBox11, "F2",false), // 高温液位上限 CreateRegisterConfig(1034, uiTextBox5, "F2",false), // 高温液位下限 CreateRegisterConfig(300, uiTextBox17, "F2",false), // 高温液位下限 CreateRegisterConfig(408, uiTextBox14, "0",true), // 稳压时间 CreateRegisterConfig(406, uiTextBox15, "0",true), // 通水时间 CreateRegisterConfig(410, uiTextBox13, "0",true), // 排空时间 CreateRegisterConfig(402, uiTextBox16, "0",true) // 温度 }; // 批量处理所有寄存器读取和UI更新 foreach (var config in registerConfigs) { await ReadRegisterAndUpdateUIAsync(config); } } catch (Exception ex) { this.Invoke(new Action(() => { UIMessageBox.ShowError($"读取系数失败:{ex.Message}"); })); } } private RegisterConfig CreateRegisterConfig(int address, UITextBox textBox, string format, bool isInteger) { var config = new RegisterConfig(); config.Address = (ushort)address; // 显式转换为ushort,解决类型不匹配 config.TextBox = textBox; config.Format = format; config.IsInteger = isInteger; // 赋值整数类型标识 return config; } /// /// 通用方法:读取寄存器并更新SunnyUI文本框(核心逻辑复用) /// /// 寄存器配置 private async Task ReadRegisterAndUpdateUIAsync(RegisterConfig config) { ushort[] registers = await Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, config.Address, 2)); if (registers != null && registers.Length >= 2) { this.Invoke(new Action(() => { if (config.IsInteger) { int intValue = (registers[1] << 16) | registers[0]; config.TextBox.Text = intValue.ToString(config.Format); } else { float floatValue = c.UshortToFloat(registers[1], registers[0]); config.TextBox.Text = floatValue.ToString(config.Format); } })); } } private void Coeffiicientsetting_Load(object sender, EventArgs e) { //string plcIp = "192.168.1.10"; string plcIp = "127.0.0.1"; 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); c = new DataChange(); } private void ShowErrorMsg(string msg) { // 判断当前线程是否是UI线程,避免跨线程访问控件异常 if (this.InvokeRequired) { // 跨线程时通过Invoke切换到UI线程执行 this.Invoke(new Action(ShowErrorMsg), msg); return; } // UI线程直接显示错误提示框 MessageBox.Show(msg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } 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 SwitchWindow(ref T windowInstance, Func createFunc) where T : UIForm { _isSwitchingWindow = true; _readTimer?.Stop(); _cts.Cancel(); // 2. 检查资源是否可用(添加重连机制) if (_tcpClient == null || !_tcpClient.Connected || _modbusMaster == null) { // 尝试重新连接 //bool reconnectSuccess = TryReconnect(); //if (!reconnectSuccess) //{ // MessageBox.Show("TCP连接已断开,请重新连接!", "提示"); // return; //} } // 3. 复用窗口实例:不存在则创建,存在则激活 if (windowInstance == null || windowInstance.IsDisposed) { windowInstance = createFunc(); windowInstance.FormClosed += (s, e) => { this.Invoke(new Action(() => { _isSwitchingWindow = false; _cts = new CancellationTokenSource(); _readTimer?.Start(); this.Show(); this.Activate(); })); }; } else { windowInstance.Activate(); return; } this.Hide(); windowInstance.Show(); } private void Coeffiicientsetting_FormClosing(object sender, FormClosingEventArgs e) { _cts.Cancel(); _cts.Dispose(); // 停止定时器 _readTimer?.Stop(); _readTimer?.Dispose(); // 仅用户主动关闭时退出应用 if (e.CloseReason == CloseReason.UserClosing) { ModbusResourceManager.Instance?.Dispose(); Application.Exit(); } } private void Coeffiicientsetting_FormClosed(object sender, FormClosedEventArgs e) { _highTemperatureMode?.Dispose(); _normalTemperatureMode?.Dispose(); } //控制压力系数 private void uiTextBox1_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox1.Text.Trim(), 394, Function.DataType.浮点型); } //压力保护输入 private void uiTextBox3_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox3.Text.Trim(), 1134, Function.DataType.浮点型); } //压力上限 private void uiTextBox2_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox2.Text.Trim(), 376, Function.DataType.浮点型); } //压力下限 private void uiTextBox4_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox4.Text.Trim(), 374, Function.DataType.浮点型); } //温度系数 private void uiTextBox8_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox8.Text.Trim(), 1482, Function.DataType.浮点型); } //出口温度系数 private void uiTextBox6_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox6.Text.Trim(), 1176, Function.DataType.浮点型); } //常温液位系数 private void uiTextBox7_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox7.Text.Trim(), 1076, Function.DataType.浮点型); } //常温液位上限 private void uiTextBox9_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox9.Text.Trim(), 1086, Function.DataType.浮点型); } //常温液位下限 private void uiTextBox10_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox10.Text.Trim(), 1084, Function.DataType.浮点型); } //高温液位系数 private void uiTextBox12_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox12.Text.Trim(), 1026, Function.DataType.浮点型); } //高温液位上限 private void uiTextBox11_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox11.Text.Trim(), 1036, Function.DataType.浮点型); } //高温液位下限 private void uiTextBox5_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox5.Text.Trim(), 1034, Function.DataType.浮点型); } //返回 private void uiButton1_Click(object sender, EventArgs e) { SwitchWindow(ref _normalTemperatureMode, () => new NormalTemperatureMode()); } //稳压时间 private void uiTextBox14_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox14.Text.Trim(), 408, Function.DataType.整形); } //通水时间 private void uiTextBox15_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox15.Text.Trim(), 406, Function.DataType.整形); } //排空时间 private void uiTextBox13_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox13.Text.Trim(), 410, Function.DataType.整形); } //温度 private void uiTextBox16_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox16.Text.Trim(), 402, Function.DataType.整形); } //转速设置 private void uiTextBox17_Click(object sender, EventArgs e) { ma?.WriteToPLCForNew(uiTextBox17.Text.Trim(), 300, Function.DataType.浮点型); } private bool _isWaterCycleOn = false; private bool _isConstantPressureOn = false; private void uiButton2_Click(object sender, EventArgs e) { _isWaterCycleOn = !_isWaterCycleOn; // 切换状态 if (_isWaterCycleOn) { uiButton2.ForeColor = Color.Red; uiButton2.Text = "水循环中"; } else { uiButton2.ForeColor = Color.White; uiButton2.Text = "水循环"; } ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 0);//水循环 } private void uiButton3_Click(object sender, EventArgs e) { _isConstantPressureOn = !_isConstantPressureOn; // 切换状态 if (_isConstantPressureOn) { uiButton3.ForeColor = Color.Red; uiButton3.Text = "恒压启动中"; } else { uiButton3.ForeColor = Color.White; uiButton3.Text = "恒压启动"; } ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 110);//恒压启动 } } }