492 lines
18 KiB
C#
492 lines
18 KiB
C#
using Modbus.Device;
|
||
using Sunny.UI;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Data;
|
||
using System.Diagnostics;
|
||
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 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();
|
||
// 只创建定时器,不在构造器中启动,避免在 Load 前访问未初始化的资源(如 c / _modbusMaster)
|
||
_readTimer = 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 { }
|
||
}
|
||
};
|
||
|
||
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;
|
||
|
||
// 确保 UI 已可用
|
||
if (!this.IsHandleCreated || this.IsDisposed) return;
|
||
|
||
try
|
||
{
|
||
var registerConfigs = new List<RegisterConfig>
|
||
{
|
||
CreateRegisterConfig(2394, uiTextBox1, "F2",false), // 控制压力系数
|
||
CreateRegisterConfig(3134, uiTextBox3, "F2",false), // 压力保护输入
|
||
//CreateRegisterConfig(2376, uiTextBox2, "F2",false), // 压力上限
|
||
//CreateRegisterConfig(2374, uiTextBox4, "F2",false), // 压力下限
|
||
CreateRegisterConfig(3482, uiTextBox8, "F2",false), // 温度系数
|
||
CreateRegisterConfig(3176, uiTextBox6, "F2",false), // 出口温度系数
|
||
CreateRegisterConfig(3076, uiTextBox7, "F2",false), // 常温液位系数
|
||
CreateRegisterConfig(3086, uiTextBox9, "F2",false), // 常温液位上限
|
||
CreateRegisterConfig(3084, uiTextBox10, "F2",false), // 常温液位下限
|
||
CreateRegisterConfig(3026, uiTextBox12, "F2",false), // 高温液位系数
|
||
CreateRegisterConfig(3036, uiTextBox11, "F2",false), // 高温液位上限
|
||
CreateRegisterConfig(3034, uiTextBox5, "F2",false), // 高温液位下限
|
||
CreateRegisterConfig(2300, uiTextBox17, "F2",false), // 转速
|
||
CreateRegisterConfig(2402, uiTextBox16, "F2",false), // 温度
|
||
|
||
|
||
CreateRegisterConfig(2408, uiTextBox14, "0",true), // 稳压时间
|
||
CreateRegisterConfig(2406, uiTextBox15, "0",true), // 通水时间
|
||
CreateRegisterConfig(2410, uiTextBox13, "0",true), // 排空时间
|
||
CreateRegisterConfig(2414, uiTextBox2, "0",true), // 延迟记录初始值时间
|
||
|
||
|
||
|
||
};
|
||
|
||
// 批量处理所有寄存器读取和UI更新
|
||
foreach (var config in registerConfigs)
|
||
{
|
||
await ReadRegisterAndUpdateUIAsync(config);
|
||
}
|
||
|
||
await ReadButtonStatusAsync();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_readTimer?.Stop();
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通用方法:读取寄存器并更新SunnyUI文本框(核心逻辑复用)
|
||
/// </summary>
|
||
/// <param name="config">寄存器配置</param>
|
||
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 async Task ReadButtonStatusAsync()
|
||
{
|
||
try
|
||
{
|
||
// 读取水循环状态 - 地址0
|
||
bool[] waterStatus = await Task.Run(() =>
|
||
_modbusMaster?.ReadCoils(1, 10000, 1));
|
||
|
||
// 读取恒压启动状态 - 地址110
|
||
bool[] pressureStatus = await Task.Run(() =>
|
||
_modbusMaster?.ReadCoils(1, 10110, 1));
|
||
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
// 更新水循环按钮
|
||
if (waterStatus != null && waterStatus.Length > 0)
|
||
{
|
||
bool isWaterOn = waterStatus[0];
|
||
uiButton2.ForeColor = isWaterOn ? Color.Red : Color.White;
|
||
uiButton2.Text = isWaterOn ? "水循环中" : "水循环";
|
||
}
|
||
|
||
// 更新恒压启动按钮
|
||
if (pressureStatus != null && pressureStatus.Length > 0)
|
||
{
|
||
bool isPressureOn = pressureStatus[0];
|
||
uiButton3.ForeColor = isPressureOn ? Color.Red : Color.White;
|
||
uiButton3.Text = isPressureOn ? "恒压启动中" : "恒压启动";
|
||
}
|
||
}));
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"[错误] 更新按钮状态失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
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();
|
||
|
||
// 在 Load 完成 Modbus 初始化与 DataChange 初始化后再启动读定时器
|
||
//_readTimer?.Start();
|
||
}
|
||
|
||
|
||
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)
|
||
{
|
||
MessageBox.Show($"重新连接失败:{ex.Message}");
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
private void SwitchWindow<T>(ref T windowInstance, Func<T> 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)
|
||
{
|
||
_normalTemperatureMode?.Dispose();
|
||
}
|
||
|
||
|
||
//控制压力系数
|
||
private void uiTextBox1_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox1.Text.Trim(), 2394, Function.DataType.浮点型);
|
||
}
|
||
//压力保护输入
|
||
private void uiTextBox3_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox3.Text.Trim(), 3134, Function.DataType.浮点型);
|
||
}
|
||
|
||
|
||
//压力上限
|
||
//private void uiTextBox2_Click(object sender, EventArgs e)
|
||
//{
|
||
// ma?.WriteToPLCForNew(uiTextBox2.Text.Trim(), 2376, Function.DataType.浮点型);
|
||
//}
|
||
|
||
//压力下限
|
||
//private void uiTextBox4_Click(object sender, EventArgs e)
|
||
//{
|
||
// ma?.WriteToPLCForNew(uiTextBox4.Text.Trim(), 2374, Function.DataType.浮点型);
|
||
//}
|
||
|
||
//温度系数
|
||
private void uiTextBox8_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox8.Text.Trim(), 3482, Function.DataType.浮点型);
|
||
}
|
||
|
||
//出口温度系数
|
||
private void uiTextBox6_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox6.Text.Trim(), 3176, Function.DataType.浮点型);
|
||
}
|
||
//常温液位系数
|
||
private void uiTextBox7_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox7.Text.Trim(), 3076, Function.DataType.浮点型);
|
||
}
|
||
//常温液位上限
|
||
private void uiTextBox9_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox9.Text.Trim(), 3086, Function.DataType.浮点型);
|
||
}
|
||
//常温液位下限
|
||
private void uiTextBox10_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox10.Text.Trim(), 3084, Function.DataType.浮点型);
|
||
}
|
||
//高温液位系数
|
||
private void uiTextBox12_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox12.Text.Trim(), 3026, Function.DataType.浮点型);
|
||
}
|
||
//高温液位上限
|
||
private void uiTextBox11_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox11.Text.Trim(), 3036, Function.DataType.浮点型);
|
||
}
|
||
//高温液位下限
|
||
private void uiTextBox5_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox5.Text.Trim(), 3034, Function.DataType.浮点型);
|
||
}
|
||
|
||
//返回
|
||
private void uiButton1_Click(object sender, EventArgs e)
|
||
{
|
||
SwitchWindow(ref _normalTemperatureMode, () => new NormalTemperatureMode());
|
||
//this.Close();
|
||
}
|
||
//稳压时间
|
||
private void uiTextBox14_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox14.Text.Trim(), 2408, Function.DataType.整形);
|
||
}
|
||
//通水时间
|
||
private void uiTextBox15_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox15.Text.Trim(), 2406, Function.DataType.整形);
|
||
}
|
||
//排空时间
|
||
private void uiTextBox13_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox13.Text.Trim(), 2410, Function.DataType.整形);
|
||
}
|
||
//温度
|
||
private void uiTextBox16_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox16.Text.Trim(), 2402, Function.DataType.整形);
|
||
}
|
||
|
||
//转速设置
|
||
private void uiTextBox17_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox17.Text.Trim(), 2300, Function.DataType.浮点型);
|
||
}
|
||
|
||
//水循环
|
||
private void uiButton2_Click(object sender, EventArgs e)
|
||
{
|
||
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10000);
|
||
}
|
||
|
||
//恒压启动
|
||
private void uiButton3_Click(object sender, EventArgs e)
|
||
{
|
||
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10110);
|
||
}
|
||
|
||
//延迟记录初始值时间
|
||
private void uiTextBox2_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox2.Text.Trim(), 2414, Function.DataType.整形);
|
||
}
|
||
|
||
#region
|
||
//常温抽水
|
||
private void uiButton4_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10006);
|
||
}
|
||
//高温抽水
|
||
private void uiButton13_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10005);
|
||
}
|
||
//常温加水
|
||
private void uiButton5_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10013);
|
||
}
|
||
//高温加水
|
||
private void uiButton11_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10012);
|
||
}
|
||
//高压进阀
|
||
private void uiButton12_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10008);
|
||
}
|
||
//高压出阀
|
||
private void uiButton7_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10001);
|
||
}
|
||
//空气抽气
|
||
private void uiButton10_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10007);
|
||
}
|
||
//常温回水
|
||
private void uiButton8_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10010);
|
||
}
|
||
//高温回水
|
||
private void uiButton9_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 10009);
|
||
}
|
||
#endregion
|
||
|
||
private void Coeffiicientsetting_Shown(object sender, EventArgs e)
|
||
{
|
||
if (_modbusMaster != null)
|
||
{
|
||
//_readtimer = InitTimer();
|
||
_readTimer.Start();
|
||
}
|
||
}
|
||
}
|
||
} |