This commit is contained in:
wxt
2026-01-16 12:00:16 +08:00
parent a582b9b609
commit da979e6d0a
4 changed files with 8 additions and 2533 deletions

9
.gitignore vendored
View File

@@ -360,4 +360,11 @@ MigrationBackup/
.ionide/ .ionide/
# Fody - auto-generated XML schema # Fody - auto-generated XML schema
FodyWeavers.xsd FodyWeavers.xsd
/WindowsFormsApp1/Properties/Resources.resx
/WindowsFormsApp1/Properties/Settings.settings
/全自动水压检测仪/HighTemperatureMode.resx
/全自动水压检测仪/HighTemperatureMode.cs
/全自动水压检测仪/HighTemperatureMode.Designer.cs
/全自动水压检测仪/HighTemperatureMode.cs
/全自动水压检测仪/HighTemperatureMode.cs

File diff suppressed because it is too large Load Diff

View File

@@ -1,424 +0,0 @@
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 .Data;
using .DATA;
namespace
{
public partial class HighTemperatureMode : 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 HighTemperatureMode()
{
InitializeComponent();
_cts = new CancellationTokenSource();
InitTimer(); // 初始化定时器
InitTimerForSecond(); // 初始化定时器
}
private System.Windows.Forms.Timer InitTimer()
{
var timer = new System.Windows.Forms.Timer()
{
Interval = 500
};
timer.Tick += async (s, e) =>
{
if (!_isManualInput && _modbusMaster != null)
{
try
{
await ReadLeakTestParametersAsync();
}
catch { }
}
};
timer.Start();
return timer;
}
private System.Windows.Forms.Timer InitTimerForSecond()
{
var timer = new System.Windows.Forms.Timer()
{
Interval = 500
};
timer.Tick += async (s, e) =>
{
if (!_isManualInput && _modbusMaster != null)
{
try
{
await ReadLeakTestParametersAsyncForSecond();
}
catch { }
}
};
timer.Start();
return timer;
}
private async Task ReadLeakTestParametersAsync()
{
// 前置校验:连接状态检查
if (_tcpClient == null || !_tcpClient.Connected || _modbusMaster == null)
{
return;
}
try
{
uiLabel5.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
uiLabel3.Text = ReadModbusInt(80).ToString();//测试步
uiLabel28.Text = ReadModbusFloat(1130).ToString("F2");//实时压力
uiLabel12.Text = ReadModbusFloat(1030).ToString("F2");//高温实时液位
uiLabel25.Text = ReadModbusInt(82).ToString();//计时s
uiLabel9.Text = ReadModbusInt(84).ToString();//计时min
uiLabel31.Text = ReadModbusInt(86).ToString();//计时h
uiLabel14.Text = ReadModbusFloat(100).ToString("F2");//初始压力
uiLabel19.Text = ReadModbusFloat(102).ToString("F2");//结束压力
uiLabel22.Text = ReadModbusFloat(104).ToString("F2");//压差
uiLabel34.Text = ReadModbusFloat(1480).ToString("F2");//箱体温度
uiLabel38.Text = ReadModbusFloat(1180).ToString("F2");//出口温度
//await UpdateUiWithModbusFloatAsync(400, val => uiTextBox1.Text = val.ToString("F2"));//读取压力设置
//await UpdateUiWithModbusIntAsync(406, val => uiTextBox2.Text = val.ToString());//读取通水时间设置
//await UpdateUiWithModbusIntAsync(408, val => uiTextBox3.Text = val.ToString());//读取稳压时间设置
//await UpdateUiWithModbusIntAsync(410, val => uiTextBox4.Text = val.ToString());//读取排空时间设置
//await UpdateUiWithModbusIntAsync(404, val => uiTextBox5.Text = val.ToString());//读取测试保压时间设置
//await UpdateUiWithModbusIntAsync(402, val => uiTextBox6.Text = val.ToString());//读取温度设置
//常温指示
bool[] conditionStatus = _modbusMaster?.ReadCoils(1, 32, 1);
if (conditionStatus[0])
{
uiLight1.State = UILightState.Off;
}
else
{
uiLight1.State = UILightState.On;
}
//启动测试
bool[] testStatus = _modbusMaster?.ReadCoils(1, 80, 1);
if (testStatus[0])
{
uiButton2.Text = "测试中";
uiButton2.ForeColor = System.Drawing.Color.Black;
}
else
{
uiButton2.Text = "启动测试";
uiButton2.ForeColor = System.Drawing.Color.White;
}
}
catch (Exception ex)
{
this.Invoke(new Action(() =>
{
UIMessageBox.ShowError($"读取系数失败:{ex.Message}");
}));
}
}
private async Task ReadLeakTestParametersAsyncForSecond()
{
// 前置校验:连接状态检查
if (_tcpClient == null || !_tcpClient.Connected || _modbusMaster == null)
{
return;
}
try
{
await UpdateUiWithModbusFloatAsync(400, val => uiTextBox1.Text = val.ToString("F2"));//读取压力设置
await UpdateUiWithModbusIntAsync(406, val => uiTextBox2.Text = val.ToString());//读取通水时间设置
await UpdateUiWithModbusIntAsync(408, val => uiTextBox3.Text = val.ToString());//读取稳压时间设置
await UpdateUiWithModbusIntAsync(410, val => uiTextBox4.Text = val.ToString());//读取排空时间设置
await UpdateUiWithModbusIntAsync(404, val => uiTextBox5.Text = val.ToString());//读取测试保压时间设置
await UpdateUiWithModbusIntAsync(402, val => uiTextBox6.Text = val.ToString());//读取温度设置
}
catch (Exception ex)
{
this.Invoke(new Action(() =>
{
UIMessageBox.ShowError($"读取系数失败:{ex.Message}");
}));
}
}
private float ReadModbusFloat(ushort startAddress)
{
var registers = _modbusMaster?.ReadHoldingRegisters(1, startAddress, 2);
return registers?.Length >= 2 ? c.UshortToFloat(registers[1], registers[0]) : 0;
}
private int ReadModbusInt(ushort startAddress)
{
var registers = _modbusMaster?.ReadHoldingRegisters(1, startAddress, 2);
if (registers?.Length >= 2)
{
// 根据实际整数拼接规则调整这里默认用两个ushort拼接为int可根据实际协议修改
return (int)((registers[1] << 16) | registers[0]);
}
return 0; // 读取失败返回默认值
}
private async Task UpdateUiWithModbusFloatAsync(ushort startAddress, Action<float> updateAction)
{
var registers = await Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, startAddress, 2));
if (registers?.Length >= 2)
{
float value = c.UshortToFloat(registers[1], registers[0]);
Invoke(new Action(() => updateAction.Invoke(value)));
}
}
private async Task UpdateUiWithModbusIntAsync(ushort startAddress, Action<int> updateAction)
{
var registers = await Task.Run(() => _modbusMaster?.ReadHoldingRegisters(1, startAddress, 2));
if (registers?.Length >= 2)
{
int value = (int)((registers[1] << 16) | registers[0]);
Invoke(new Action(() => updateAction.Invoke(value)));
}
}
//常温模式
private void uiButton11_Click(object sender, EventArgs e)
{
//FormManager.Instance.SwitchTo<NormalTemperatureMode>();
bool result = UIMessageBox.ShowAsk("确认是否切换常温模式", true, UIMessageDialogButtons.Ok);
if (result)
{
//_modbusMaster?.WriteSingleCoil(1, 30, false);
SwitchWindow(ref _normalTemperatureMode, () => new NormalTemperatureMode());
}
else
{
return;
}
}
//系数页
private void uiButton14_Click(object sender, EventArgs e)
{
//FormManager.Instance.SwitchTo<Coeffiicientsetting>();
SwitchWindow(ref _coeffiicientsetting, () => new Coeffiicientsetting());
}
private void HighTemperatureMode_Load(object sender, EventArgs 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;
}
_modbusMaster?.WriteSingleCoil(1, 30, true);
Thread.Sleep(50);
ma = new Function(_modbusMaster);
c = new DataChange();
}
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<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 HighTemperatureMode_FormClosing(object sender, FormClosingEventArgs e)
{
// 停止定时器
_readTimer?.Stop();
_readTimer?.Dispose();
// 仅用户主动关闭时退出应用
if (e.CloseReason == CloseReason.UserClosing)
{
ModbusResourceManager.Instance?.Dispose();
Application.Exit();
}
}
private void HighTemperatureMode_FormClosed(object sender, FormClosedEventArgs e)
{
_coeffiicientsetting?.Dispose();
_normalTemperatureMode?.Dispose();
}
//进气阀
private void uiButton5_Click(object sender, EventArgs e)
{
ma?.BtnClickFunctionForNew(Function.ButtonType., 14);
}
//测试高压阀
private void uiButton6_Click(object sender, EventArgs e)
{
ma?.BtnClickFunctionForNew(Function.ButtonType., 8);
}
//空气抽气阀
private void uiButton8_Click(object sender, EventArgs e)
{
ma?.BtnClickFunctionForNew(Function.ButtonType., 7);
}
//高温水箱加水阀
private void uiButton9_Click(object sender, EventArgs e)
{
ma?.BtnClickFunctionForNew(Function.ButtonType., 12);
}
//高温抽水阀
private void uiButton7_Click(object sender, EventArgs e)
{
ma?.BtnClickFunctionForNew(Function.ButtonType., 5);
}
//高温回水阀
private void uiButton10_Click(object sender, EventArgs e)
{
ma?.BtnClickFunctionForNew(Function.ButtonType., 10);
}
//系统排气
private void uiButton13_Click(object sender, EventArgs e)
{
ma?.BtnClickFunctionForNew(Function.ButtonType., 70);
}
//升温阀
private void uiButton12_Click(object sender, EventArgs e)
{
}
//压力设定
private void uiTextBox1_Click(object sender, EventArgs e)
{
ma?.WriteToPLCForNew(uiTextBox1.Text.Trim(), 400, Function.DataType.);
}
//稳压时间设定
private void uiTextBox3_Click(object sender, EventArgs e)
{
ma?.WriteToPLCForNew(uiTextBox3.Text.Trim(), 408, Function.DataType.);
}
//测试保压时间设定
private void uiTextBox5_Click(object sender, EventArgs e)
{
ma?.WriteToPLCForNew(uiTextBox5.Text.Trim(), 404, Function.DataType.);
}
//通水时间设定
private void uiTextBox2_Click(object sender, EventArgs e)
{
ma?.WriteToPLCForNew(uiTextBox2.Text.Trim(), 406, Function.DataType.);
}
//排空时间设定
private void uiTextBox4_Click(object sender, EventArgs e)
{
ma?.WriteToPLCForNew(uiTextBox4.Text.Trim(), 410, Function.DataType.);
}
//温度设定
private void uiTextBox6_Click(object sender, EventArgs e)
{
ma?.WriteToPLCForNew(uiTextBox6.Text.Trim(), 402, Function.DataType.);
}
}
}

View File

@@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>