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; } } }