491 lines
16 KiB
C#
491 lines
16 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.Globalization;
|
||
using System.IO.Ports;
|
||
using System.Linq;
|
||
using System.Net.Sockets;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Forms;
|
||
using 外科辅料和患者防护罩激光抗性测试仪.Data;
|
||
|
||
namespace 外科辅料和患者防护罩激光抗性测试仪
|
||
{
|
||
public partial class ManualDebugForm : UIForm
|
||
{
|
||
#region 私有字段
|
||
private TcpClient _tcpClient => ModbusResourceManager.Instance.TcpClient;
|
||
private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster;
|
||
#endregion
|
||
|
||
Function ma;
|
||
DataChange c = new DataChange();
|
||
|
||
private System.Windows.Forms.Timer _readTimer;
|
||
private bool _isManualInput = false;
|
||
|
||
public ManualDebugForm()
|
||
{
|
||
InitializeComponent();
|
||
|
||
InitComboBoxPattern();
|
||
|
||
InitTimer();
|
||
}
|
||
|
||
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 ReadTestParametersAsync();
|
||
}
|
||
catch { }
|
||
}
|
||
};
|
||
timer.Start();
|
||
return timer;
|
||
}
|
||
|
||
private async System.Threading.Tasks.Task ReadTestParametersAsync()
|
||
{
|
||
if (_tcpClient == null || !_tcpClient.Connected || _modbusMaster == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
ushort[] Ray = await System.Threading.Tasks.Task.Run(() =>
|
||
_modbusMaster?.ReadHoldingRegisters(1, 250, 2)
|
||
);
|
||
|
||
if (Ray != null && Ray.Length >= 2)
|
||
{
|
||
float Value = c.UshortToFloat(Ray[1], Ray[0]);
|
||
this.Invoke(new Action(() => uiTextBox1.Text = Value.ToString("F1")));
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
this.Invoke(new Action(() =>
|
||
Debug.WriteLine($"读取系数失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)));
|
||
}
|
||
|
||
try
|
||
{
|
||
bool[] registers1 = await Task.Run(async () =>
|
||
{
|
||
if (_modbusMaster == null)
|
||
return null;
|
||
return await _modbusMaster?.ReadCoilsAsync(1, 20, 1);
|
||
});
|
||
if (registers1 != null && registers1.Length >= 1)
|
||
{
|
||
bool value = registers1[0];
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (value)
|
||
{
|
||
uiLight3.State = UILightState.On;
|
||
|
||
|
||
}
|
||
else
|
||
{
|
||
uiLight3.State = UILightState.Off;
|
||
}
|
||
}));
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"读取状态失败: {ex.Message}");
|
||
}
|
||
|
||
try
|
||
{
|
||
ushort[] Ray2 = await System.Threading.Tasks.Task.Run(() =>
|
||
_modbusMaster?.ReadHoldingRegisters(1, 102, 2)
|
||
);
|
||
|
||
if (Ray2 != null && Ray2.Length >= 2)
|
||
{
|
||
float Value2 = c.UshortToFloat(Ray2[1], Ray2[0]);
|
||
this.Invoke(new Action(() => uiLabel33.Text = Value2.ToString("F1")));
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
this.Invoke(new Action(() =>
|
||
Debug.WriteLine($"读取系数失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
private void ManualDebugForm_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;
|
||
}
|
||
ma = new Function(_modbusMaster);
|
||
|
||
//_readTimer = InitTimer();
|
||
//if (_modbusMaster != null)
|
||
//{
|
||
// _readTimer.Start();
|
||
//}
|
||
_modbusMaster?.WriteSingleRegister(1, 2, 0);
|
||
|
||
this.FormClosed += (s, args) =>
|
||
{
|
||
// 当子窗体关闭时,显示主窗体
|
||
Application.OpenForms["MainForm"]?.Show();
|
||
};
|
||
|
||
initPort();
|
||
uiComboBox1.SelectedIndex = 0;
|
||
}
|
||
|
||
private void InitComboBoxPattern()
|
||
{
|
||
// 清空原有选项(可选,避免重复添加)
|
||
//Combox_pattern.Items.Clear();
|
||
|
||
// 定义需要添加的选项数组
|
||
string[] options = {
|
||
"环境空气 (21%)",
|
||
"富氧环境 (60%)",
|
||
"富氧环境 (98%)",
|
||
"无氧环境/灭火 (0%)"
|
||
};
|
||
uiComboBox1.Items.AddRange(options);
|
||
|
||
}
|
||
|
||
private void ManualDebugForm_FormClosed(object sender, FormClosedEventArgs e)
|
||
{
|
||
foreach (Form form in Application.OpenForms)
|
||
{
|
||
if (form.Name == "MainForm" || form.Text.Contains("主界面"))
|
||
{
|
||
form.Show();
|
||
form.Activate(); // 激活窗体
|
||
break;
|
||
}
|
||
}
|
||
|
||
Disconnect();
|
||
}
|
||
|
||
private void uiButton5_Click(object sender, EventArgs e)
|
||
{
|
||
this.Close();//返回主页面
|
||
}
|
||
|
||
private void ToggleButtonWithText(UIButton button, ref bool state, string onText, string offText)
|
||
{
|
||
state = !state;
|
||
button.ForeColor = state ? Color.Red : Color.White;
|
||
button.Text = state ? onText : offText;
|
||
}
|
||
|
||
bool isbt1on = false;
|
||
//bool isbt4on = false;
|
||
bool isbt2on=false;
|
||
bool isbt3on = false;
|
||
#region 按钮
|
||
private void uiButton1_Click(object sender, EventArgs e)
|
||
{
|
||
ToggleButtonWithText(uiButton1, ref isbt1on, "混氧中", "手动混氧");
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 101);//混氧开关
|
||
}
|
||
|
||
private void uiButton4_Click(object sender, EventArgs e)
|
||
{
|
||
//ToggleButtonWithText(uiButton4, ref isbt4on, "光斑运行中", "⚫ 光斑开关");
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 250);//光斑开关
|
||
}
|
||
|
||
private void uiButton2_Click(object sender, EventArgs e)
|
||
{
|
||
ToggleButtonWithText(uiButton2, ref isbt2on, "开灯中", "💡 灯开关");
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 11);//灯开关
|
||
}
|
||
|
||
private void uiButton3_Click(object sender, EventArgs e)
|
||
{
|
||
ToggleButtonWithText(uiButton3, ref isbt3on, "灭火中", "🚨 灭火");
|
||
ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 99);//灭火
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
private void uiComboBox1_SelectedIndexChanged(object sender, EventArgs e)
|
||
{
|
||
ushort selectedIndex = ushort.Parse(uiComboBox1.SelectedIndex.ToString());
|
||
_modbusMaster?.WriteSingleRegister(1, 10, selectedIndex);//下拉框
|
||
}
|
||
|
||
private void uiTextBox1_Click(object sender, EventArgs e)
|
||
{
|
||
ma?.WriteToPLCForNew(uiTextBox1.Text.Trim(), 250, Function.DataType.浮点型);
|
||
}
|
||
|
||
private void ManualDebugForm_FormClosing(object sender, FormClosingEventArgs e)
|
||
{
|
||
if (_readTimer != null)
|
||
{
|
||
_readTimer.Stop();
|
||
_readTimer.Dispose();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
private string _serialBuffer = "";
|
||
SerialPort serialPort = null;
|
||
private System.Windows.Forms.Timer _powerMeterTimer;
|
||
private readonly object _serialLock = new object();
|
||
private bool _isSerialPortAvailable = false;
|
||
private void initPort()
|
||
{
|
||
|
||
lock (_serialLock)
|
||
{
|
||
try
|
||
{
|
||
// 创建串口对象
|
||
serialPort = new SerialPort();
|
||
serialPort.PortName = "COM2";
|
||
serialPort.BaudRate = 38400;
|
||
serialPort.DataBits = 8;
|
||
serialPort.Parity = Parity.None;
|
||
serialPort.StopBits = StopBits.One;
|
||
serialPort.NewLine = "\r\n";
|
||
|
||
// 设置数据接收事件
|
||
serialPort.DataReceived += SerialPort_DataReceived;
|
||
|
||
serialPort.Open();
|
||
|
||
_isSerialPortAvailable = true;
|
||
|
||
_powerMeterTimer = new System.Windows.Forms.Timer();
|
||
_powerMeterTimer.Interval = 200; // 100ms读取一次
|
||
_powerMeterTimer.Tick += PowerMeterTimer_Tick;
|
||
_powerMeterTimer.Start();
|
||
|
||
|
||
//SendCommand("S01");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"串口连接失败:{ex.Message}");
|
||
_isSerialPortAvailable = false;
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
|
||
|
||
// 串口数据接收事件
|
||
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
if (serialPort == null || !serialPort.IsOpen) return;
|
||
|
||
string data = serialPort.ReadExisting();
|
||
_serialBuffer += data; // 添加到缓冲区
|
||
|
||
// 检查是否有完整的行(以\r\n结尾)
|
||
int newLineIndex;
|
||
while ((newLineIndex = _serialBuffer.IndexOf("\r\n")) >= 0)
|
||
{
|
||
// 提取一行完整数据
|
||
string line = _serialBuffer.Substring(0, newLineIndex);
|
||
|
||
// 移除已处理的部分
|
||
_serialBuffer = _serialBuffer.Substring(newLineIndex + 2);
|
||
|
||
if (!string.IsNullOrEmpty(line))
|
||
{
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
ProcessPowerMeterData(line);
|
||
}));
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"串口数据接收错误: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void ProcessPowerMeterData(string data)
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrEmpty(data)) return;
|
||
|
||
string trimmedLine = data.Trim();
|
||
Debug.WriteLine($"处理完整数据行: '{trimmedLine}'");
|
||
|
||
// 处理功率值(浮点数)
|
||
if (double.TryParse(trimmedLine, NumberStyles.Float, CultureInfo.InvariantCulture, out double powerValue))
|
||
{
|
||
if (powerValue < 1000) // 功率值通常小于1000W
|
||
{
|
||
uiTextBox5.Text = $"{powerValue:F3} W";
|
||
_waitingResponse = false; // 收到响应,可以发送下一个命令
|
||
}
|
||
}
|
||
|
||
// S01命令的响应可能是空的,但我们也需要处理
|
||
else if (string.IsNullOrEmpty(trimmedLine))
|
||
{
|
||
Debug.WriteLine("收到空响应(可能是S01的响应)");
|
||
_waitingResponse = false; // 收到响应
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"处理功率计数据错误: {ex.Message}");
|
||
_waitingResponse = false; // 出错也重置标志
|
||
}
|
||
}
|
||
|
||
private int _commandCounter = 0;
|
||
private bool _waitingResponse = false; // 添加这个变量
|
||
|
||
private void PowerMeterTimer_Tick(object sender, EventArgs e)
|
||
{
|
||
if (_isSerialPortAvailable && serialPort != null && serialPort.IsOpen && !_waitingResponse)
|
||
{
|
||
if (_commandCounter == 0)
|
||
{
|
||
SendCommand("GD"); // 读取功率
|
||
}
|
||
else if (_commandCounter == 1)
|
||
{
|
||
SendCommand("GSC0"); // 读取校准系数
|
||
}
|
||
|
||
_waitingResponse = true; // 标记为等待响应
|
||
_commandCounter++;
|
||
if (_commandCounter >= 2) _commandCounter = 0; // 2个命令循环(去掉了S01)
|
||
}
|
||
}
|
||
// 发送命令到功率计
|
||
private void SendCommand(string command)
|
||
{
|
||
try
|
||
{
|
||
if (serialPort == null || !serialPort.IsOpen) return;
|
||
|
||
lock (_serialLock)
|
||
{
|
||
string fullCommand = command.ToUpper() + "\r\n";
|
||
serialPort.Write(fullCommand);
|
||
Debug.WriteLine($"发送命令: {command}");
|
||
|
||
// 超时保护(2秒)
|
||
Task.Delay(2000).ContinueWith(t =>
|
||
{
|
||
if (_waitingResponse)
|
||
{
|
||
Debug.WriteLine($"命令超时重置: {command}");
|
||
_waitingResponse = false;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"发送命令失败: {ex.Message}");
|
||
_waitingResponse = false; // 出错时重置
|
||
}
|
||
}
|
||
|
||
private void Disconnect()
|
||
{
|
||
_isSerialPortAvailable = false;
|
||
|
||
if (_powerMeterTimer != null)
|
||
{
|
||
_powerMeterTimer.Stop();
|
||
_powerMeterTimer.Dispose();
|
||
_powerMeterTimer = null;
|
||
}
|
||
|
||
try
|
||
{
|
||
if (serialPort != null && serialPort.IsOpen)
|
||
{
|
||
SendCommand("S00"); // 停止连续输出
|
||
}
|
||
}
|
||
catch { }
|
||
|
||
Task.Run(() =>
|
||
{
|
||
lock (_serialLock)
|
||
{
|
||
try
|
||
{
|
||
if (serialPort != null)
|
||
{
|
||
if (serialPort.IsOpen)
|
||
{
|
||
serialPort.Close();
|
||
}
|
||
serialPort.Dispose();
|
||
serialPort = null;
|
||
}
|
||
//WriteToLog("功率计已断开连接");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
//WriteToLog($"断开连接异常:{ex.Message}");
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
}
|
||
}
|