using Common.Attributes; using System; using System.IO.Ports; using System.Text; using System.Threading; using System.Threading.Tasks; namespace DeviceCommand.Flexible { [ADPCommand] public static class FSerialPort { private static readonly SemaphoreSlim _commLock = new(1, 1); private static SerialPort CreatePort(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits, int sendTimeout,int receiveTimeout) { return new SerialPort(portName, baudRate, parity, dataBits, stopBits) { Encoding = Encoding.UTF8, WriteTimeout = sendTimeout > 0 ? sendTimeout : SerialPort.InfiniteTimeout, ReadTimeout = receiveTimeout > 0 ? receiveTimeout : SerialPort.InfiniteTimeout }; } #region 最常用:只发送字符串 public static async Task SendAsync(string portName,int baudRate,Parity parity,int dataBits,StopBits stopBits,int sendTimeout,int receiveTimeout,string command,CancellationToken ct = default) { await _commLock.WaitAsync(ct); try { using var port = CreatePort( portName, baudRate, parity, dataBits, stopBits, sendTimeout, receiveTimeout); port.Open(); using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct); if (sendTimeout > 0) cts.CancelAfter(sendTimeout); var bytes = port.Encoding.GetBytes(command); await port.BaseStream.WriteAsync(bytes, 0, bytes.Length, cts.Token); await port.BaseStream.FlushAsync(cts.Token); } finally { _commLock.Release(); } } #endregion #region 最常用:发送字符串并读取字符串 public static async Task SendReadAsync(string portName,int baudRate, Parity parity, int dataBits, StopBits stopBits,int sendTimeout, int receiveTimeout,string command,string delimiter = "\n", CancellationToken ct = default) { await _commLock.WaitAsync(ct); try { using var port = CreatePort( portName, baudRate, parity, dataBits, stopBits, sendTimeout, receiveTimeout); port.Open(); // Send var sendBytes = port.Encoding.GetBytes(command); await port.BaseStream.WriteAsync(sendBytes, 0, sendBytes.Length, ct); await port.BaseStream.FlushAsync(ct); // Read delimiter ??= "\n"; var sb = new StringBuilder(); byte[] buffer = new byte[256]; using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct); if (receiveTimeout > 0) cts.CancelAfter(receiveTimeout); while (!cts.Token.IsCancellationRequested) { int read = await port.BaseStream.ReadAsync( buffer, 0, buffer.Length, cts.Token); if (read == 0) break; sb.Append(port.Encoding.GetString(buffer, 0, read)); int index = sb.ToString().IndexOf(delimiter, StringComparison.Ordinal); if (index >= 0) return sb.ToString(0, index).Trim(); } throw new TimeoutException("串口读取超时"); } finally { _commLock.Release(); } } #endregion } }