1174 lines
42 KiB
C#
1174 lines
42 KiB
C#
using Modbus.Device;
|
||
using NET_HRF4826;
|
||
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
|
||
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.Tasks;
|
||
using System.Windows.Forms;
|
||
using 薄膜气体透过率测试仪;
|
||
using 薄膜气体透过率测试仪.Data;
|
||
|
||
|
||
namespace 薄膜气体透过率测试仪
|
||
{
|
||
public partial class TestScreen : UIForm
|
||
{
|
||
#region 私有字段
|
||
|
||
private TcpClient _tcpClient => ModbusResourceManager.Instance.TcpClient;
|
||
private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster;
|
||
|
||
#endregion
|
||
|
||
private CoefficientForm _coefficientForm;
|
||
private MiopahReport _miopahReport;
|
||
private TianpaReport _tianpaReport;
|
||
private TrendChart _trendChart;
|
||
private Form1 _Form1;
|
||
|
||
|
||
private System.Windows.Forms.Timer _readtimer;
|
||
private Stopwatch pressStopwatch;
|
||
private const int LONG_PRESS_THRESHOLD = 1000; // 1000毫秒=1秒
|
||
|
||
Function ma;
|
||
DataChange c = new DataChange();
|
||
|
||
Timer Timer;
|
||
private List<lineData> data;
|
||
protected List<MiopahReportRecord> miopahReports = new List<MiopahReportRecord>();
|
||
protected List<TianpaReportRecord> tianpaReports = new List<TianpaReportRecord>();
|
||
|
||
private bool _isMiopahAdded = false; // Miopah(true状态)是否已添加
|
||
private bool _isTianpaAdded = false; // Tianpa(false状态)是否已添加
|
||
//private readonly object _lockObj = new object(); // 线程锁,防止并发冲突
|
||
|
||
|
||
|
||
public TestScreen()
|
||
{
|
||
InitializeComponent();
|
||
|
||
pressStopwatch = new Stopwatch();
|
||
|
||
Timer = new Timer();
|
||
Timer.Tick += Timer_Tick;
|
||
Timer.Interval = 1000;
|
||
Timer.Start();
|
||
|
||
InitTimer();
|
||
data = new List<lineData>();
|
||
|
||
}
|
||
|
||
//private void Timer_Tick(object sender, EventArgs e)
|
||
//{
|
||
// bool[] buttonStatus = _modbusMaster.ReadCoils(1, 20, 1);
|
||
// if (buttonStatus[0])
|
||
// {
|
||
// try
|
||
// {
|
||
// ushort[] location = _modbusMaster.ReadHoldingRegisters(1, 300, 12);
|
||
// float value1 = c.UshortToFloat(location[1], location[0]);//f
|
||
// float value2 = c.UshortToFloat(location[3], location[2]);//f
|
||
// float value3 = c.UshortToFloat(location[5], location[4]);//f
|
||
// float value4 = c.UshortToFloat(location[7], location[6]);//f
|
||
// float value5 = c.UshortToFloat(location[9], location[8]);//f
|
||
// float value6 = c.UshortToFloat(location[11], location[10]);//f
|
||
|
||
|
||
// MiopahReportRecord r = new MiopahReportRecord()
|
||
// {
|
||
// Num1 = miopahReports.Count + 1,
|
||
// Createtime1 = DateTime.Now,
|
||
// Volume1 = value1,
|
||
// Area1 = value2,
|
||
// Temperature1 = value3,
|
||
// Thickness1 = value4,
|
||
// MolGTR = value5,
|
||
// MolP = value6,
|
||
|
||
// };
|
||
|
||
// AddMiopah(r);
|
||
// }
|
||
|
||
// catch (Exception ex)
|
||
// {
|
||
// ShowError($"采集数据失败:{ex.Message}");
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// try
|
||
// {
|
||
// ushort[] location = _modbusMaster.ReadHoldingRegisters(1, 300, 12);
|
||
// float value7 = c.UshortToFloat(location[1], location[0]);//f
|
||
// float value8 = c.UshortToFloat(location[3], location[2]);//f
|
||
// float value9 = c.UshortToFloat(location[5], location[4]);//f
|
||
// float value10 = c.UshortToFloat(location[7], location[6]);//f
|
||
// float value11 = c.UshortToFloat(location[9], location[8]);//f
|
||
// float value12 = c.UshortToFloat(location[11], location[10]);//f
|
||
|
||
|
||
// TianpaReportRecord s = new TianpaReportRecord()
|
||
// {
|
||
// Num2 = tianpaReports.Count + 1,
|
||
// Createtime2 = DateTime.Now,
|
||
// Volume2 = value7,
|
||
// Area2 = value8,
|
||
// Temperature2 = value9,
|
||
// Thickness2 = value10,
|
||
// CM3GTR = value11,
|
||
// CM3P = value12,
|
||
|
||
// };
|
||
|
||
// AddTianpa(s);
|
||
// }
|
||
|
||
// catch (Exception ex)
|
||
// {
|
||
// ShowError($"采集数据失败:{ex.Message}");
|
||
// }
|
||
// }
|
||
//}
|
||
|
||
private void Timer_Tick(object sender, EventArgs e)
|
||
{
|
||
try
|
||
{
|
||
|
||
ushort[] time = _modbusMaster.ReadHoldingRegisters(1, 0, 1);
|
||
int valuetime = time[0];
|
||
uiLabel45.Text = valuetime.ToString();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Timer?.Stop();
|
||
//ShowError($"采集数据失败:{ex.Message}");
|
||
|
||
}
|
||
|
||
try
|
||
{
|
||
//bool buttonStatus = false;
|
||
//bool Load = true;
|
||
bool[] buttonStatus = _modbusMaster.ReadCoils(1, 20, 1);
|
||
if (buttonStatus == null || buttonStatus.Length == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
bool[] Load = _modbusMaster.ReadCoils(1, 12, 1);
|
||
if (Load == null || Load.Length == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 3. 状态为true:采集Miopah(仅未添加时执行)
|
||
if (!buttonStatus[0] && !Load[0] /*buttonStatus&& Load*/)
|
||
{
|
||
_isTianpaAdded = false;
|
||
|
||
if (!_isMiopahAdded)
|
||
{
|
||
|
||
ushort[] location = _modbusMaster.ReadHoldingRegisters(1, 300, 12);
|
||
if (location == null || location.Length < 12)
|
||
{
|
||
return;
|
||
}
|
||
float value1 = c.UshortToFloat(location[1], location[0]);
|
||
float value2 = c.UshortToFloat(location[3], location[2]);
|
||
float value3 = c.UshortToFloat(location[5], location[4]);
|
||
float value4 = c.UshortToFloat(location[7], location[6]);
|
||
float value5 = c.UshortToFloat(location[9], location[8]);
|
||
float value6 = c.UshortToFloat(location[11], location[10]);
|
||
//int value1 = 1;
|
||
//int value2 = 2;
|
||
//int value3 = 3;
|
||
//int value4 = 4;
|
||
//int value5 = 5;
|
||
//int value6 = 6;
|
||
|
||
MiopahReportRecord r = new MiopahReportRecord()
|
||
{
|
||
Num1 = miopahReports.Count + 1,
|
||
Createtime1 = DateTime.Now,
|
||
Volume1 = value1,
|
||
Area1 = value2,
|
||
Temperature1 = value3,
|
||
Thickness1 = value4,
|
||
MolGTR = value5,
|
||
MolP = value6,
|
||
};
|
||
AddMiopah(r);
|
||
|
||
_isMiopahAdded = true;
|
||
}
|
||
}
|
||
else if (buttonStatus[0] && !Load[0] /*!buttonStatus&&Load*/)
|
||
{
|
||
_isMiopahAdded = false;
|
||
|
||
if (!_isTianpaAdded)
|
||
{
|
||
ushort[] location = _modbusMaster.ReadHoldingRegisters(1, 300, 12);
|
||
if (location == null || location.Length < 12)
|
||
{
|
||
return;
|
||
}
|
||
|
||
float value7 = c.UshortToFloat(location[1], location[0]);
|
||
float value8 = c.UshortToFloat(location[3], location[2]);
|
||
float value9 = c.UshortToFloat(location[5], location[4]);
|
||
float value10 = c.UshortToFloat(location[7], location[6]);
|
||
float value11 = c.UshortToFloat(location[9], location[8]);
|
||
float value12 = c.UshortToFloat(location[11], location[10]);
|
||
//int value7 = 1;
|
||
//int value8 = 2;
|
||
//int value9 = 3;
|
||
//int value10 = 4;
|
||
//int value11 = 5;
|
||
//int value12 = 6;
|
||
|
||
|
||
TianpaReportRecord s = new TianpaReportRecord()
|
||
{
|
||
Num2 = tianpaReports.Count + 1,
|
||
Createtime2 = DateTime.Now,
|
||
Volume2 = value7,
|
||
Area2 = value8,
|
||
Temperature2 = value9,
|
||
Thickness2 = value10,
|
||
CM3GTR = value11,
|
||
CM3P = value12,
|
||
};
|
||
AddTianpa(s);
|
||
_isTianpaAdded = true;
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Timer?.Stop();
|
||
//ShowError($"采集数据失败:{ex.Message}");
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
private void AddMiopah(MiopahReportRecord report)
|
||
{
|
||
miopahReports.Add(report);
|
||
}
|
||
|
||
private void AddTianpa(TianpaReportRecord report)
|
||
{
|
||
tianpaReports.Add(report);
|
||
}
|
||
|
||
private System.Windows.Forms.Timer InitTimer()
|
||
{
|
||
var timer = new System.Windows.Forms.Timer()
|
||
{
|
||
Interval = 1000,
|
||
};
|
||
timer.Tick += async (s, e) =>
|
||
{
|
||
if (_modbusMaster != null)
|
||
{
|
||
try
|
||
{
|
||
await ReadDataAsync();
|
||
}
|
||
catch { }
|
||
}
|
||
};
|
||
return timer;
|
||
|
||
}
|
||
|
||
private async System.Threading.Tasks.Task ReadDataAsync()
|
||
{
|
||
try
|
||
{
|
||
if (_modbusMaster == null || _tcpClient == null || !_tcpClient.Connected)
|
||
{
|
||
return;
|
||
}
|
||
// await ReadFloatAsync(0, 1, uiLabel45, "FO", "");//脱气进行时间
|
||
var tasks = new List<Task>
|
||
{
|
||
|
||
ReadFloatAsync(22,1,uiLabel44,"F0",""),//测试进行时间
|
||
ReadFloatAsync(1034,2,uiLabel9,"F1",""),//高压室压力
|
||
|
||
ReadDWordAsync(1140, uiLabel10, "D", ""),
|
||
//ReadFloatAsync(1140,1,uiLabel10,"F0",""),//低压室压力
|
||
|
||
ReadFloatAsync(120,2,uiLabel12,"F2",""),//斜率1
|
||
ReadFloatAsync(122,2,uiLabel14,"F2",""),//斜率2
|
||
ReadFloatAsync(308,2,uiLabel22,"F4",""),//气体透过率
|
||
ReadFloatAsync(310,2,uiLabel20,"F9",""),//气体透过系数
|
||
ReadFloatAsync(1218,2,uiLabel3,"F1",""),//腔体温度
|
||
|
||
ReadAndUpdateFloatAsync(218,2,uiTextBox1,"F4",""),//低压室体积
|
||
ReadAndUpdateFloatAsync(224,2,uiTextBox2,"F6",""),//试验面积
|
||
ReadAndUpdateFloatAsync(222,2,uiTextBox3,"F2",""),//试验温度
|
||
ReadAndUpdateFloatAsync(226,2,uiTextBox5,"F6",""),//试样厚度
|
||
ReadAndUpdateFloatAsync(200,1,uiTextBox8,"F0",""),//脱气时间
|
||
ReadAndUpdateFloatAsync(202,1,uiTextBox7,"F0",""),//采样间隔时间
|
||
|
||
ReadtimeAsync(),//实时时间
|
||
|
||
ReadStartStopStatusAsync()
|
||
|
||
|
||
|
||
};
|
||
await Task.WhenAll(tasks);
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_readtimer?.Stop();
|
||
Timer?.Stop();
|
||
ShowError($"读取数据失败:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
private void addLineChart(lineData trendData)
|
||
{
|
||
// data.Add(new lineData
|
||
// {
|
||
// X = DateTime.Now.ToString("ss"),
|
||
// //Y = new Random().Next(01, 100)
|
||
// Y = new Random().Next(01, 100)
|
||
// });
|
||
if (trendData == null) return;
|
||
|
||
data.Add(trendData);
|
||
|
||
}
|
||
|
||
|
||
private async Task ReadStartStopStatusAsync()
|
||
{
|
||
try
|
||
{
|
||
bool[] registers = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 1, 1);
|
||
});
|
||
//bool[] registers = await Task.Run(async () =>
|
||
|
||
// await _modbusMaster?.ReadCoilsAsync(1, 1, 1)
|
||
//);
|
||
|
||
if (registers != null && registers.Length >= 1)
|
||
{
|
||
bool value = registers[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (value)
|
||
{
|
||
uiButton4.ForeColor = System.Drawing.Color.Red;
|
||
uiButton4.Text = "测试停止";
|
||
|
||
try
|
||
{
|
||
//lock (_lockObj)
|
||
//{
|
||
// 1. 读取趋势图数据(地址3100)
|
||
ushort[] valueY = _modbusMaster.ReadHoldingRegisters(1, 3100, 2);
|
||
if (valueY != null && valueY.Length >= 2)
|
||
{
|
||
float value13 = c.UshortToFloat(valueY[1], valueY[0]);
|
||
lineData trendData = new lineData
|
||
{
|
||
X = DateTime.Now.ToString("HH:mm:ss"),
|
||
Y = value13
|
||
};
|
||
_trendChart?.AddChart(trendData);
|
||
}
|
||
//}
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ShowError($"添加趋势图数据失败:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
else
|
||
{
|
||
uiButton4.ForeColor = System.Drawing.Color.White;
|
||
uiButton4.Text = "测试开始";
|
||
}
|
||
}));
|
||
}
|
||
|
||
bool[] registers2 = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 0, 1);
|
||
});
|
||
if (registers2 != null && registers2.Length >= 1)
|
||
{
|
||
bool value = registers2[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (value)
|
||
{
|
||
uiButton2.ForeColor = System.Drawing.Color.Red;
|
||
uiButton2.Text = "脱气停止";
|
||
}
|
||
else
|
||
{
|
||
uiButton2.ForeColor = System.Drawing.Color.White;
|
||
uiButton2.Text = "脱气";
|
||
}
|
||
}));
|
||
}
|
||
|
||
bool[] registers3 = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 50, 1);
|
||
});
|
||
if (registers3 != null && registers3.Length >= 1)
|
||
{
|
||
bool value = registers3[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (value)
|
||
{
|
||
uiButton5.ForeColor = System.Drawing.Color.Red;
|
||
}
|
||
else
|
||
{
|
||
uiButton5.ForeColor = System.Drawing.Color.Black;
|
||
}
|
||
}));
|
||
}
|
||
|
||
bool[] registers4 = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 51, 1);
|
||
});
|
||
if (registers4 != null && registers4.Length >= 1)
|
||
{
|
||
bool value = registers4[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (value)
|
||
{
|
||
uiButton6.ForeColor = System.Drawing.Color.Red;
|
||
}
|
||
else
|
||
{
|
||
uiButton6.ForeColor = System.Drawing.Color.Black;
|
||
}
|
||
}));
|
||
}
|
||
|
||
bool[] registers5 = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 52, 1);
|
||
});
|
||
if (registers5 != null && registers5.Length >= 1)
|
||
{
|
||
bool value = registers5[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (value)
|
||
{
|
||
uiButton7.ForeColor = System.Drawing.Color.Red;
|
||
}
|
||
else
|
||
{
|
||
uiButton7.ForeColor = System.Drawing.Color.Black;
|
||
}
|
||
}));
|
||
}
|
||
|
||
bool[] registers6 = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 53, 1);
|
||
});
|
||
if (registers6 != null && registers6.Length >= 1)
|
||
{
|
||
bool value = registers6[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (value)
|
||
{
|
||
uiButton8.ForeColor = System.Drawing.Color.Red;
|
||
}
|
||
else
|
||
{
|
||
uiButton8.ForeColor = System.Drawing.Color.Black;
|
||
}
|
||
}));
|
||
}
|
||
|
||
bool[] registers7 = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 54, 1);
|
||
});
|
||
if (registers7 != null && registers7.Length >= 1)
|
||
{
|
||
bool value = registers7[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (value)
|
||
{
|
||
uiButton9.ForeColor = System.Drawing.Color.Red;
|
||
}
|
||
else
|
||
{
|
||
uiButton9.ForeColor = System.Drawing.Color.Black;
|
||
}
|
||
}));
|
||
}
|
||
|
||
bool[] registers8 = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 55, 1);
|
||
});
|
||
if (registers8 != null && registers8.Length >= 1)
|
||
{
|
||
bool value = registers8[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (value)
|
||
{
|
||
uiButton10.ForeColor = System.Drawing.Color.Red;
|
||
}
|
||
else
|
||
{
|
||
uiButton10.ForeColor = System.Drawing.Color.Black;
|
||
}
|
||
}));
|
||
}
|
||
|
||
bool[] registers9 = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 2, 1);
|
||
});
|
||
if (registers9 != null && registers9.Length >= 1)
|
||
{
|
||
bool value = registers9[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (value)
|
||
{
|
||
uiButton12.ForeColor = System.Drawing.Color.Red;
|
||
}
|
||
else
|
||
{
|
||
uiButton12.ForeColor = System.Drawing.Color.White;
|
||
}
|
||
}));
|
||
}
|
||
|
||
bool[] registes10 = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 20, 1);
|
||
});
|
||
if (registes10 != null && registes10.Length >= 1)
|
||
{
|
||
bool value = registes10[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (!value)
|
||
{
|
||
uiSwitch1.Active = false;
|
||
uiLabel18.Text = "L";
|
||
uiLabel16.Text = "[mol/(m²*s*Pa)]";
|
||
uiLabel17.Text = "[mol*m/(m²*s*Pa)]";
|
||
}
|
||
else
|
||
{
|
||
uiSwitch1.Active = true;
|
||
uiLabel18.Text = "cm³";
|
||
uiLabel16.Text = "[cm³/(m²*d*0.1MPa)]";
|
||
uiLabel17.Text = "[cm³*cm/(m²*s*0.1MPa)]";
|
||
}
|
||
}));
|
||
}
|
||
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ShowError($"读取失败:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
private async Task ReadtimeAsync()
|
||
{
|
||
try
|
||
{
|
||
|
||
string currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||
|
||
// 跨线程更新UI(异步方法中仍需检查Invoke,避免跨线程异常)
|
||
if (uiLabel5.InvokeRequired)
|
||
{
|
||
uiLabel5.Invoke(new Action(() =>
|
||
{
|
||
uiLabel5.Text = currentTime;
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
uiLabel5.Text = currentTime;
|
||
}
|
||
|
||
// 等待1秒再更新(异步等待,不阻塞UI线程)
|
||
await Task.Delay(1000);
|
||
|
||
}
|
||
|
||
catch (Exception ex)
|
||
{
|
||
uiLabel5.Text = $"错误:{ex.Message}";
|
||
}
|
||
}
|
||
|
||
private async Task ReadFloatAsync(int address, int length, Label control, string format, string unit)
|
||
{
|
||
// 空值校验:避免传入空控件导致后续Invoke报错
|
||
if (control == null)
|
||
{
|
||
//System.Diagnostics.Debug.WriteLine($"读取地址{address}失败:目标Label控件为空");
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
ushort[] registers = await Task.Run(async () =>
|
||
{
|
||
// 双重空值校验:避免_modbusMaster为空导致调用异常
|
||
if (_modbusMaster == null) return null;
|
||
return await _modbusMaster.ReadHoldingRegistersAsync(1, (ushort)address, (ushort)length);
|
||
});
|
||
|
||
// 场景1:读取到2个及以上寄存器 → 解析为浮点型数据(占2个16位寄存器)
|
||
if (registers != null && registers.Length >= 2)
|
||
{
|
||
// c.UshortToFloat:将2个16位无符号寄存器转换为32位浮点型
|
||
float value = c.UshortToFloat(registers[1], registers[0]);
|
||
// WinForm中UI控件只能由创建它的主线程修改,否则会抛出跨线程异常
|
||
if (control.InvokeRequired)
|
||
{
|
||
control.Invoke(new Action(() =>
|
||
{
|
||
control.Text = $"{value.ToString(format)}{unit}";
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
// 若当前已是UI线程,直接更新
|
||
control.Text = $"{value.ToString(format)}{unit}";
|
||
}
|
||
}
|
||
// 场景2:读取到1个寄存器 → 解析为整型数据(占1个16位寄存器)
|
||
else if (registers != null && registers.Length >= 1)
|
||
{
|
||
// 直接取第一个寄存器的值作为整型数据
|
||
int value = registers[0];
|
||
|
||
// 同样通过Control.Invoke保证UI线程安全更新
|
||
if (control.InvokeRequired)
|
||
{
|
||
control.Invoke(new Action(() =>
|
||
{
|
||
control.Text = $"{value.ToString(format)}{unit}";
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
control.Text = $"{value.ToString(format)}{unit}";
|
||
}
|
||
}
|
||
// 场景3:registers为null或长度为0 → 无有效数据,不执行更新(静默处理)
|
||
else if (registers == null || registers.Length == 0)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"读取地址{address}失败:未获取到有效寄存器数据");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ShowError($"读取地址{address}失败:{ex.Message}\n异常堆栈:{ex.StackTrace}");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
private async Task ReadDWordAsync(int startAddress, Label control, string format = "D", string unit = "")
|
||
{
|
||
if (control == null) return;
|
||
|
||
try
|
||
{
|
||
// 32位 DWord 占用 2 个连续寄存器
|
||
ushort[] registers = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null) return null;
|
||
return await _modbusMaster.ReadHoldingRegistersAsync(1, (ushort)startAddress, 2);
|
||
});
|
||
|
||
if (registers != null && registers.Length >= 2)
|
||
{
|
||
// 将两个16位寄存器组合成32位有符号整数
|
||
// 注意寄存器顺序:通常是 低16位在前(D1140),高16位在后(D1141)
|
||
int value = (registers[1] << 16) | registers[0];
|
||
|
||
// 如果是有符号整数且为负数,需要做符号扩展
|
||
// 但 Modbus 通常用 UInt32 传输,所以直接用 int 转换即可
|
||
|
||
if (control.InvokeRequired)
|
||
{
|
||
control.Invoke(new Action(() =>
|
||
{
|
||
control.Text = $"{value.ToString(format)}{unit}";
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
control.Text = $"{value.ToString(format)}{unit}";
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ShowError($"读取DWord地址{startAddress}失败:{ex.Message}");
|
||
}
|
||
}
|
||
private async Task ReadAndUpdateFloatAsync(int address, int length, Sunny.UI.UITextBox control, string format, string unit)
|
||
{
|
||
// 空值校验:避免传入空控件导致后续Invoke报错
|
||
if (control == null)
|
||
{
|
||
//System.Diagnostics.Debug.WriteLine($"读取地址{address}失败:目标Label控件为空");
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
ushort[] registers = await Task.Run(async () =>
|
||
{
|
||
// 双重空值校验:避免_modbusMaster为空导致调用异常
|
||
if (_modbusMaster == null) return null;
|
||
return await _modbusMaster.ReadHoldingRegistersAsync(1, (ushort)address, (ushort)length);
|
||
});
|
||
|
||
// 场景1:读取到2个及以上寄存器 → 解析为浮点型数据(占2个16位寄存器)
|
||
if (registers != null && registers.Length >= 2)
|
||
{
|
||
float value = c.UshortToFloat(registers[1], registers[0]);
|
||
|
||
// Control.Invoke:判断是否跨线程,若跨线程则切换到UI线程更新控件
|
||
if (control.InvokeRequired)
|
||
{
|
||
control.Invoke(new Action(() =>
|
||
{
|
||
control.Text = $"{value.ToString(format)}{unit}";
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
// 若当前已是UI线程,直接更新
|
||
control.Text = $"{value.ToString(format)}{unit}";
|
||
}
|
||
}
|
||
// 场景2:读取到1个寄存器 → 解析为整型数据(占1个16位寄存器)
|
||
else if (registers != null && registers.Length >= 1)
|
||
{
|
||
// 直接取第一个寄存器的值作为整型数据
|
||
int value = registers[0];
|
||
|
||
// 同样通过Control.Invoke保证UI线程安全更新
|
||
if (control.InvokeRequired)
|
||
{
|
||
control.Invoke(new Action(() =>
|
||
{
|
||
control.Text = $"{value.ToString(format)}{unit}";
|
||
}));
|
||
}
|
||
else
|
||
{
|
||
control.Text = $"{value.ToString(format)}{unit}";
|
||
}
|
||
}
|
||
// 场景3:registers为null或长度为0 → 无有效数据,不执行更新(静默处理)
|
||
else if (registers == null || registers.Length == 0)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"读取地址{address}失败:未获取到有效寄存器数据");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
|
||
ShowError($"读取地址{address}失败:{ex.Message}\n异常堆栈:{ex.StackTrace}");
|
||
}
|
||
}
|
||
|
||
|
||
private void ShowError(string msg) => MessageBox.Show(msg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
|
||
|
||
private void TestScreen_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);
|
||
|
||
_readtimer = InitTimer();
|
||
if (_modbusMaster != null)
|
||
{
|
||
_readtimer.Start();
|
||
}
|
||
}
|
||
|
||
private void SwitchWindow<T>(ref T windowInstance, Func<T> createFunc) where T : UIForm
|
||
{
|
||
//1.停止当前窗口的定时器(不释放资源)
|
||
//_readtimer?.Stop();
|
||
Timer?.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) =>
|
||
{
|
||
// 窗口关闭时重新启动定时器并显示当前窗口
|
||
//_readtimer?.Start();
|
||
//this.Show();
|
||
this.Activate();
|
||
};
|
||
}
|
||
else
|
||
{
|
||
// 激活已存在的窗口(前置显示)
|
||
windowInstance.Activate();
|
||
return;
|
||
}
|
||
|
||
// 4. 切换窗口:隐藏当前窗口,显示目标窗口(非模态)
|
||
this.Hide();
|
||
windowInstance.Show(); // 使用 Show() 而不是 ShowDialog()
|
||
}
|
||
|
||
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)
|
||
{
|
||
ShowError($"重新连接失败:{ex.Message}");
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//系数页
|
||
private void uiButton3_Click(object sender, EventArgs e)
|
||
{
|
||
//SwitchWindow(ref _coefficientForm, () => new CoefficientForm());
|
||
}
|
||
|
||
private void uiTextBox1_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox1.Text.Trim(), 218, Function.DataType.浮点型, 4);//低压室体积
|
||
System.Threading.Tasks.Task.Delay(50);
|
||
}
|
||
|
||
private void uiTextBox2_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox2.Text.Trim(), 224, Function.DataType.浮点型, 6);//低压室面积
|
||
System.Threading.Tasks.Task.Delay(50);
|
||
}
|
||
|
||
private void uiTextBox3_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox3.Text.Trim(), 222, Function.DataType.浮点型);//试验温度
|
||
System.Threading.Tasks.Task.Delay(50);
|
||
}
|
||
|
||
private void uiTextBox5_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox5.Text.Trim(), 226, Function.DataType.浮点型, 6);//试样厚度
|
||
System.Threading.Tasks.Task.Delay(50);
|
||
}
|
||
|
||
private void uiTextBox7_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox7.Text.Trim(), 202, Function.DataType.整形);//采样间隔时间
|
||
System.Threading.Tasks.Task.Delay(50);
|
||
}
|
||
|
||
private void uiTextBox8_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox8.Text.Trim(), 200, Function.DataType.整形);//脱气时间
|
||
System.Threading.Tasks.Task.Delay(50);
|
||
}
|
||
|
||
private void uiButton4_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 1);//测试开始
|
||
|
||
}
|
||
|
||
private void uiButton2_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 0);//脱气
|
||
}
|
||
|
||
private void uiButton5_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 50);//气源阀
|
||
}
|
||
|
||
private void uiButton6_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 51);//隔断阀
|
||
}
|
||
|
||
private void uiButton7_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 52);//放空阀
|
||
}
|
||
|
||
private void uiButton8_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 53);//低压阀
|
||
}
|
||
|
||
private void uiButton9_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 54);//排气阀
|
||
}
|
||
|
||
private void uiButton10_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 55);//真空泵
|
||
}
|
||
|
||
private void uiButton12_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 2);//排气
|
||
}
|
||
|
||
private void uiSwitch1_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 20);//输出单位切换
|
||
}
|
||
|
||
private void TestScreen_FormClosing(object sender, FormClosingEventArgs e)
|
||
{
|
||
_readtimer?.Stop();
|
||
_readtimer?.Dispose();
|
||
Timer?.Stop();
|
||
Timer?.Dispose();
|
||
|
||
// 仅用户主动关闭时退出应用
|
||
if (e.CloseReason == CloseReason.UserClosing)
|
||
{
|
||
ModbusResourceManager.Instance?.Dispose();
|
||
Application.Exit();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
//秒帕记录
|
||
private void uiButton11_Click(object sender, EventArgs e)
|
||
{
|
||
SwitchWindow(ref _miopahReport, () => new MiopahReport(miopahReports));
|
||
}
|
||
//天帕记录
|
||
private void uiButton13_Click(object sender, EventArgs e)
|
||
{
|
||
SwitchWindow(ref _tianpaReport, () => new TianpaReport(tianpaReports));
|
||
}
|
||
|
||
|
||
private void SwitchForm<T>(ref T windowInstance, Func<T> createFunc) where T : UIForm
|
||
{
|
||
// 检查是否为 null 或已释放
|
||
if (windowInstance == null || windowInstance.IsDisposed)
|
||
{
|
||
// 确保完全释放
|
||
windowInstance?.Dispose();
|
||
windowInstance = createFunc();
|
||
|
||
// 窗口关闭时标记为已释放(不需要重置为 null)
|
||
windowInstance.FormClosed += (s, args) =>
|
||
{
|
||
// Form 的 Dispose 会被自动调用
|
||
};
|
||
|
||
windowInstance.Show();
|
||
}
|
||
else
|
||
{
|
||
// 窗口已存在且未释放
|
||
if (windowInstance.WindowState == FormWindowState.Minimized)
|
||
{
|
||
windowInstance.WindowState = FormWindowState.Normal;
|
||
}
|
||
windowInstance.BringToFront();
|
||
windowInstance.Activate();
|
||
}
|
||
}
|
||
private void uiButton1_Click(object sender, EventArgs e)
|
||
{
|
||
|
||
SwitchForm(ref _trendChart, () => new TrendChart(data));
|
||
}
|
||
|
||
private void uiButton3_MouseDown(object sender, MouseEventArgs e)
|
||
{
|
||
if (e.Button == MouseButtons.Left)
|
||
{
|
||
pressStopwatch.Restart();
|
||
}
|
||
}
|
||
|
||
private void uiButton3_MouseUp(object sender, MouseEventArgs e)
|
||
{
|
||
if (e.Button == MouseButtons.Left)
|
||
{
|
||
pressStopwatch.Stop();
|
||
if (pressStopwatch.ElapsedMilliseconds >= LONG_PRESS_THRESHOLD)
|
||
{
|
||
// 执行长按操作
|
||
EnterFunction();
|
||
}
|
||
//else
|
||
//{
|
||
// // 执行点击操作(可选)
|
||
// ClickFunction();
|
||
//}
|
||
}
|
||
}
|
||
|
||
private void EnterFunction()
|
||
{
|
||
// 长按后进入的功能
|
||
SwitchWindow(ref _coefficientForm, () => new CoefficientForm());
|
||
}
|
||
|
||
private void uiButton14_Click(object sender, EventArgs e)
|
||
{
|
||
SwitchForm(ref _Form1, () => new Form1());
|
||
}
|
||
}
|
||
public class lineData
|
||
{
|
||
public string X { get; set; }
|
||
public float Y { get; set; }
|
||
}
|
||
public class MiopahReportRecord
|
||
{
|
||
public int? Num1 { get; set; }//m编号
|
||
public DateTime? Createtime1 { get; set; }//m日期时间
|
||
public float? Volume1 { get; set; } //m低压体积
|
||
public float? Area1 { get; set; }//m渗透面积
|
||
public float? Temperature1 { get; set; }//m试验温度
|
||
public float? Thickness1 { get; set; }//T试验厚度
|
||
public float? MolGTR { get; set; }//MolGTR
|
||
public float? MolP { get; set; }//MolP
|
||
|
||
|
||
}
|
||
|
||
public class TianpaReportRecord
|
||
{
|
||
public int? Num2 { get; set; }//T编号
|
||
public DateTime? Createtime2 { get; set; }//T日期时间
|
||
public float? Volume2 { get; set; } //T低压体积
|
||
public float? Area2 { get; set; }//T渗透面积
|
||
public float? Temperature2 { get; set; }//T试验温度
|
||
public float? Thickness2 { get; set; }//T试验厚度
|
||
public float? CM3GTR { get; set; }//CM3GTR
|
||
public float? CM3P { get; set; }//CM3P
|
||
|
||
}
|
||
|
||
|
||
}
|