using LB_VisionProcesses.Communicators;
using RJCP.IO.Ports;
using System.Text;
namespace LB_VisionProcesses.Communicators.Tcom
{
public class UARTPort : BaseCommunicator
{
private RJCP.IO.Ports.SerialPortStream SerialPort = new RJCP.IO.Ports.SerialPortStream();
// 构造函数
public UARTPort(string name = "UART串口")
{
CommunicatorConnections.Add("地址", "COM1");
CommunicatorConnections.Add("端口", "115200");
CommunicatorBrand = CommunicatorBrand.UARTPort;
CommunicatorName = name;
}
///
/// 配置串口参数
///
///
///
///
///
///
public void SetConfigure(string portName, int baudRate = 115200, RJCP.IO.Ports.Parity parity = RJCP.IO.Ports.Parity.None,
int dataBits = 8, RJCP.IO.Ports.StopBits stopBits = RJCP.IO.Ports.StopBits.One)
{
SerialPort.PortName = portName;
SerialPort.BaudRate = baudRate;
SerialPort.Parity = parity;
SerialPort.DataBits = dataBits;
SerialPort.StopBits = stopBits;
SerialPort.NewLine = "\r\n"; // 设置行结束符
SerialPort.ReadTimeout = 500; // 设置读取超时
SerialPort.WriteTimeout = 500; // 设置写入超时
}
public override bool Connect()
{
try
{
Disconnect();
//波特率
int PORT = 0;
if (!int.TryParse(this.CommunicatorConnections["端口"].ToString(), out PORT))
{
Msg = string.Format("端口未设置");
return false;
}
if (!CommunicatorConnections.Contains("地址"))
{
Msg = string.Format("地址未设置");
return false;
}
//串口号
string IP = CommunicatorConnections["地址"].ToString();
if (!SerialPort.IsOpen)
{
SerialPort = new SerialPortStream();
SetConfigure(IP, PORT);
SerialPort.Open();
bConnected = true;
SerialPort.DataReceived += SerialPort_DataReceived;
// 启动心跳线程
heartbeatThread = new Thread(SendHeartbeat);
heartbeatThread.IsBackground = true;
heartbeatThread.Start();
bConnected = true;
return true;
}
else
{
Msg = $"原串口关闭失败无法重新打开";
return false;
}
}
catch (Exception ex)
{
Msg = $"失败,串口已经启动: {ex.Message}";
return false;
}
}
public override bool Disconnect()
{
try
{
bConnected = false;
if (SerialPort == null)
{
SerialPort = new SerialPortStream();
return true;
}
if (SerialPort.IsOpen)
{
SerialPort.DataReceived -= SerialPort_DataReceived;
SerialPort.Close(); // 关闭串口
}
SerialPort = new SerialPortStream();
return true;
}
catch (Exception ex)
{
bConnected = false;
Msg = $"断开串口时出错: {ex.Message}";
return true;
}
}
public override bool SendMessage(byte[] sBytes)
{
strReceiveMsg = string.Empty;
bool bret = false;
if (SerialPort == null || !SerialPort.IsOpen) return bret;
try
{
// 清空缓冲区
SerialPort.DiscardOutBuffer();
//Thread.Sleep(50);
SerialPort.Write(sBytes, 0, sBytes.Length);
bret = true;
}
catch { }
return bret;
}
public override bool SendMessage(string message)
{
strReceiveMsg = string.Empty;
if (bConnected)
{
try
{
//空消息不发送
if (string.IsNullOrEmpty(message) || message.Trim() == "")
return true;
//发送前清空接收消息
strReceiveMsg = string.Empty;
// 清空缓冲区
SerialPort.DiscardOutBuffer();
//Thread.Sleep(50);
byte[] sBytes = BaseCommunicator.strToHexByte(message);
if (sBytes.Length == 0)
SerialPort.Write(message); // 发送消息
else
SerialPort.Write(sBytes, 0, sBytes.Length);
return true;
}
catch (Exception ex)
{
Msg = $"发送消息时出错: {ex.Message}";
return false;
}
}
else
{
Msg = "串口未打开";
return false;
}
}
private readonly System.Collections.Concurrent.ConcurrentQueue _messageQueue = new();
private readonly object _timerLock = new object();
private System.Threading.Timer _aggregateTimer;
private readonly TimeSpan _aggregationInterval = TimeSpan.FromMilliseconds(50); // 50ms聚合窗口
private void SerialPort_DataReceived(object? sender, RJCP.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
if (SerialPort == null || !SerialPort.IsOpen)
return;
if (SerialPort.BytesToRead > 0)
{
byte[] buffer = new byte[SerialPort.BytesToRead];
int bytesRead = SerialPort.Read(buffer, 0, buffer.Length);
string message = BitConverter.ToString(buffer, 0, bytesRead).Replace('-', ' ');
if (!string.IsNullOrEmpty(message))
{
// 将消息加入队列
_messageQueue.Enqueue(message);
// 启动或重置聚合计时器
lock (_timerLock)
{
_aggregateTimer?.Dispose();
_aggregateTimer = new System.Threading.Timer(
AggregateMessages,
null,
_aggregationInterval,
Timeout.InfiniteTimeSpan
);
}
}
}
}
catch (Exception ex)
{
Msg = $"读取串口数据时出错: {ex.Message}";
}
}
private void AggregateMessages(object state)
{
lock (_timerLock)
{
if (_messageQueue.IsEmpty)
return;
// 聚合队列中的所有消息
StringBuilder aggregatedMessage = new StringBuilder();
while (_messageQueue.TryDequeue(out string msg))
{
if (aggregatedMessage.Length > 0)
aggregatedMessage.Append(" ");
aggregatedMessage.Append(msg);
}
// 只触发一次回调
strReceiveMsg = aggregatedMessage.ToString();
if (!string.IsNullOrEmpty(strReceiveMsg))
{
MessageReceived?.Invoke(strReceiveMsg);
TriggerRunMessageReceived?.Invoke(CommunicatorName, strReceiveMsg);
}
}
}
public override string ReceiveMsg()
{
string msg = string.Empty;
for (int i = 0; i <= 3; i++)
{
if (string.IsNullOrEmpty(strReceiveMsg))
Thread.Sleep(50);
else
{
lock (strReceiveMsg)
{
msg += strReceiveMsg;
strReceiveMsg = string.Empty;
}
//串口数据需要使用累加方式
//return msg;
}
}
return msg;
}
}
}