using Common.Attributes; //using DeviceCommand.Interface; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.IO.Ports; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Windows; using static Common.Attributes.ATSCommandAttribute; namespace DeviceCommand.Base { [ATSCommand] [DeviceCategory("全部驱动")] // 添加分类属性 public class Serial_Port { public string PortName { get; set; } = "COM1"; public int BaudRate { get; set; } = 9600; public int DataBits { get; set; } = 8; public StopBits StopBits { get; set; } = StopBits.One; public Parity Parity { get; set; } = Parity.None; public int ReadTimeout { get; set; } = 3000; public int WriteTimeout { get; set; } = 3000; public SerialPort _SerialPort { get; set; } = new SerialPort(); /// /// 创建并配置串口实例 /// /// 串口名称(如"COM1") /// 波特率 /// 数据位,配置默认值:8 /// 停止位,配置默认值:StopBits.One /// 校验位(根据设备需求设置),配置默认值:Parity.None /// 读取超时 /// 写入超时 public Serial_Port CreateDevice(string portName, int baudRate , int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None , int readTimeout = 3000, int writeTimeout = 3000) { PortName = portName; BaudRate = baudRate; DataBits = dataBits; StopBits = stopBits; Parity = parity; ReadTimeout = readTimeout; WriteTimeout = writeTimeout; return this; } /// /// 修改串口实例参数 /// /// 串口实例 /// 串口名称(如"COM1") /// 波特率 /// 数据位 /// 停止位 /// 校验位(根据设备需求设置) /// 读取超时 /// 写入超时 public static void ChangeDeviceConfig(Serial_Port serialPort, string PortName, int BaudRate , int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None , int ReadTimeout = 3000, int WriteTimeout = 3000) { // 更新配置串口实例参数 serialPort.PortName = PortName; // 串口名称(如"COM1") serialPort.BaudRate = BaudRate; // 波特率 //serialPort.ReadTimeout = ReadTimeout; //serialPort.WriteTimeout = WriteTimeout; serialPort.Parity = parity; // 校验位(根据设备需求设置) serialPort.DataBits = dataBits; // 数据位 serialPort.StopBits = stopBits; // 停止位 if (ReadTimeout > 0) serialPort.ReadTimeout = ReadTimeout; // 读取超时 if (WriteTimeout > 0) serialPort.WriteTimeout = WriteTimeout;// 写入超时 } /// /// 串口连接 /// /// 串口实例 /// 支持中途取消发送指令 public static async Task ConnectAsync(Serial_Port serialPort, CancellationToken ct = default) { if (serialPort._SerialPort.PortName != serialPort.PortName || serialPort._SerialPort.BaudRate != serialPort.BaudRate || serialPort._SerialPort.Parity != serialPort.Parity || serialPort._SerialPort.DataBits != serialPort.DataBits || serialPort._SerialPort.StopBits != serialPort.StopBits || serialPort._SerialPort.ReadTimeout != serialPort.ReadTimeout || serialPort._SerialPort.WriteTimeout != serialPort.WriteTimeout) { // 关闭现有连接并重新配置 serialPort._SerialPort.Close(); //更新串口配置 serialPort._SerialPort.PortName = serialPort.PortName; serialPort._SerialPort.BaudRate = serialPort.BaudRate; serialPort._SerialPort.Parity = serialPort.Parity; serialPort._SerialPort.DataBits = serialPort.DataBits; serialPort._SerialPort.StopBits = serialPort.StopBits; serialPort._SerialPort.ReadTimeout = serialPort.ReadTimeout; serialPort._SerialPort.WriteTimeout = serialPort.WriteTimeout; // 重新打开串口 serialPort._SerialPort.Open(); } else { // 检查串口是否已打开 if (!serialPort._SerialPort.IsOpen) { // 打开串口 serialPort._SerialPort.Open(); } } return true; } /// /// 串口关闭 /// /// 串口实例 public static void Close(Serial_Port serialPort) { if (serialPort._SerialPort.IsOpen) { // 关闭串口连接 serialPort._SerialPort.Close(); //Console.WriteLine("串口已关闭"); } } /// /// 串口发送byte类型数据信息 /// /// 串口实例 /// 发送的数据信息为byte类型 /// 支持中途取消发送指令 public static async Task SendAsync(Serial_Port serialPort, byte[] bytes, CancellationToken ct = default) { if (!serialPort._SerialPort.IsOpen) return; // 获取写入超时时间 var timeoutMs = serialPort.WriteTimeout; if (timeoutMs <= 0) { serialPort._SerialPort.Write(bytes, 0, bytes.Length); // 向串口写入字节数据 return; } var sendTask = Task.Run(() => { // 向串口写入字节数据 serialPort._SerialPort.Write(bytes, 0, bytes.Length); }, ct); var timeoutTask = Task.Delay(timeoutMs, ct); var completedTask = await Task.WhenAny(sendTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException($"串口通讯异常:写入操作在 {timeoutMs} ms内未完成"); } await sendTask; //if (serialPort._SerialPort.IsOpen) //{ //try //{ // // 异步发送数据到串口 // await Task.Run(() => // { // serialPort._SerialPort.Write(bytes, 0, bytes.Length); // 向串口写入字节数据 // }, ct); //} //catch (Exception ex) //{ // // 异常处理 // //Console.WriteLine($"发送数据失败: {ex.Message}"); // MessageBox.Show($"串口发送数据失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); //} //} //else //{ // //Console.WriteLine("串口未打开"); // MessageBox.Show($"串口未打开", "错误", MessageBoxButton.OK, MessageBoxImage.Error); //} } /// /// 串口发送字符串类型数据信息 /// /// 串口实例 /// 发送的数据信息为字符串类型 /// 支持中途取消发送指令 public static async Task SendAsync(Serial_Port serialPort, string str, CancellationToken ct = default) { if (!serialPort._SerialPort.IsOpen) return; // 将字符串转换为字节数组 byte[] bytes = Encoding.UTF8.GetBytes(str); // 获取写入超时时间 var timeoutMs = serialPort.WriteTimeout; if (timeoutMs <= 0) { serialPort._SerialPort.Write(bytes, 0, bytes.Length); return; } var sendTask = Task.Run(() => { // 向串口写入字节数据 serialPort._SerialPort.Write(bytes, 0, bytes.Length); }, ct); var timeoutTask = Task.Delay(timeoutMs, ct); var completedTask = await Task.WhenAny(sendTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException($"串口通讯异常:写入操作在 {timeoutMs} ms内未完成"); } await sendTask; } /// /// 串口读取byte类型数据信息 /// /// 串口实例 /// 读取的数据信息为byte数组类型 /// 支持中途取消发送指令 public static async Task ReadAsync(Serial_Port serialPort, byte[] buffer, CancellationToken ct = default) { if (!serialPort._SerialPort.IsOpen) return null; int bytesRead = 0; // 获取写入超时时间 var timeoutMs = serialPort.ReadTimeout; if (timeoutMs <= 0) { return await ReadByte(serialPort, buffer, ct); //while (bytesRead < buffer.Length) //{ // if (serialPort._SerialPort.BytesToRead > 0) // { // bytesRead += serialPort._SerialPort.Read(buffer, bytesRead, buffer.Length - bytesRead); // } //} //return buffer; } //var readTask = Task.Run(() => //{ // while (bytesRead < buffer.Length) // { // if (serialPort._SerialPort.BytesToRead > 0) // { // bytesRead += serialPort._SerialPort.Read(buffer, bytesRead, buffer.Length - bytesRead); // } // } //}, ct); var readTask = ReadByte(serialPort, buffer, ct); var timeoutTask = Task.Delay(timeoutMs, ct); var completedTask = await Task.WhenAny(readTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException($"串口通讯异常:读取操作在 {timeoutMs} ms内未完成"); } return buffer; //try //{ // // 异步读取串口数据 // await Task.Run(() => // { // while (bytesRead < buffer.Length) // { // if (serialPort._SerialPort.BytesToRead > 0) // { // bytesRead += serialPort._SerialPort.Read(buffer, bytesRead, buffer.Length - bytesRead); // } // } // }, ct); //} //catch (Exception ex) //{ // //Console.WriteLine($"读取数据失败: {ex.Message}"); // MessageBox.Show($"读取串口数据失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); // return null; //} //return buffer; } public static async Task ReadByte(Serial_Port serialPort, byte[] buffer, CancellationToken ct) { int bytesRead = 0; while (bytesRead < buffer.Length) { if (serialPort._SerialPort.BytesToRead > 0) { bytesRead += serialPort._SerialPort.Read(buffer, bytesRead, buffer.Length - bytesRead); } } return buffer; } /// /// 串口读取字符串类型数据信息 /// /// 串口实例 /// 读取的数据信息为字符串类型,string delimiter = "\n" /// 支持中途取消发送指令 public static async Task ReadAsync(Serial_Port serialPort, string delimiter = "\n", CancellationToken ct = default) { if (!serialPort._SerialPort.IsOpen) return null; // 获取写入超时时间 var timeoutMs = serialPort.ReadTimeout; if (timeoutMs <= 0) { return await ReadDefaultString(serialPort, delimiter, ct); } var readTask = ReadDefaultString(serialPort, delimiter, ct); var timeoutTask = Task.Delay(timeoutMs, ct); var completedTask = await Task.WhenAny(readTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException($"串口通讯异常:读取操作在 {timeoutMs} ms内未完成"); } return await readTask; //try //{ // // 异步读取串口数据 // await Task.Run(() => // { // while (true) // { // if (ct.IsCancellationRequested) // return; // if (serialPort._SerialPort.BytesToRead > 0) // { // bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length); // memoryStream.Write(buffer, 0, bytesRead); // data = Encoding.UTF8.GetString(memoryStream.ToArray()); // int lineEndIndex = data.IndexOf(delimiter); // // 找到分隔符,则返回数据 // if (lineEndIndex >= 0) // { // data = data.Substring(0, lineEndIndex).Trim(); // return; // } // } // } // }, ct); //} //catch (Exception ex) //{ // //Console.WriteLine($"读取串口数据失败: {ex.Message}"); // MessageBox.Show($"读取串口数据失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); // return null; //} //return data; } private static async Task ReadDefaultString(Serial_Port serialPort, string delimiter, CancellationToken ct) { delimiter ??= "\n"; MemoryStream memoryStream = new(); byte[] buffer = new byte[2048]; int bytesRead = 0; string data = string.Empty; // 异步读取串口数据 await Task.Run(() => { while (true) { if (ct.IsCancellationRequested) return; if (serialPort._SerialPort.BytesToRead > 0) { bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length); memoryStream.Write(buffer, 0, bytesRead); data = Encoding.UTF8.GetString(memoryStream.ToArray()); int lineEndIndex = data.IndexOf(delimiter); // 找到分隔符,则返回数据 if (lineEndIndex >= 0) { data = data.Substring(0, lineEndIndex).Trim(); return; } } } }, ct); return data; } /// /// 串口读取字符串类型数据信息 /// /// 串口实例 /// 读取的数据信息为字符串类型,string delimiter /// 支持中途取消发送指令 public static async Task ReadStrAsync(Serial_Port serialPort, string delimiter, CancellationToken ct = default) { if (!serialPort._SerialPort.IsOpen) { return null; // 串口未打开,返回 null } // 获取写入超时时间 var timeoutMs = serialPort.ReadTimeout; if (timeoutMs <= 0) { return await ReadString(serialPort, delimiter, ct); } var readTask = ReadString(serialPort, delimiter, ct); var timeoutTask = Task.Delay(timeoutMs, ct); var completedTask = await Task.WhenAny(readTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException($"串口通讯异常:读取操作在 {timeoutMs} ms内未完成"); } return await readTask; ////delimiter ??= "\n"; // 默认分隔符为换行符 //MemoryStream memoryStream = new(); //byte[] buffer = new byte[2048]; //int bytesRead; //string data = string.Empty; //// 异步读取串口数据 //await Task.Run(() => //{ // while (true) // { // if (ct.IsCancellationRequested) // return; // if (serialPort._SerialPort.BytesToRead > 0) // { // // 从串口读取数据 // bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length); // memoryStream.Write(buffer, 0, bytesRead); // // 获取当前已读取的数据 // data = Encoding.UTF8.GetString(memoryStream.ToArray()); // // 查找分隔符 // int delimiterIndex = data.IndexOf(delimiter); // if (delimiterIndex >= 0) // { // // 如果找到分隔符,则返回读取到的字符串 // data = data.Substring(0, delimiterIndex).Trim(); // return; // } // } // } //}, ct); //try //{ // // 异步读取串口数据 // await Task.Run(() => // { // while (true) // { // if (ct.IsCancellationRequested) // return; // if (serialPort._SerialPort.BytesToRead > 0) // { // // 从串口读取数据 // bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length); // memoryStream.Write(buffer, 0, bytesRead); // // 获取当前已读取的数据 // data = Encoding.UTF8.GetString(memoryStream.ToArray()); // // 查找分隔符 // int delimiterIndex = data.IndexOf(delimiter); // if (delimiterIndex >= 0) // { // // 如果找到分隔符,则返回读取到的字符串 // data = data.Substring(0, delimiterIndex).Trim(); // return; // } // } // } // }, ct); //} //catch (Exception ex) //{ // //Console.WriteLine($"读取串口数据时发生错误: {ex.Message}"); // MessageBox.Show($"读取串口数据时发生错误: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); // return null; //} //return data; // 如果没有数据返回,返回 null } private static async Task ReadString(Serial_Port serialPort, string delimiter, CancellationToken ct) { //delimiter ??= "\n"; MemoryStream memoryStream = new(); byte[] buffer = new byte[2048]; int bytesRead = 0; string data = string.Empty; // 异步读取串口数据 await Task.Run(() => { while (true) { if (ct.IsCancellationRequested) return; if (serialPort._SerialPort.BytesToRead > 0) { bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length); memoryStream.Write(buffer, 0, bytesRead); data = Encoding.UTF8.GetString(memoryStream.ToArray()); int lineEndIndex = data.IndexOf(delimiter); // 找到分隔符,则返回数据 if (lineEndIndex >= 0) { data = data.Substring(0, lineEndIndex).Trim(); return; } } } }, ct); return data; } /// /// 串口连接 /// /// 取消令牌 /// 连接结果 public async Task ConnectAsync(CancellationToken ct = default) { return await ConnectAsync(this, ct); } /// /// 断开串口连接 /// public void Disconnect() { Close(this); } /// /// 发送字符串到串口 /// /// 要发送的字符串 /// 取消令牌 public async Task SendStringAsync(string str, CancellationToken ct = default) { await SendAsync(this, str, ct); } /// /// 接收字符串直到遇到指定分隔符 /// /// 分隔符 /// 取消令牌 /// 接收到的字符串 public async Task ReceiveStringToAsync(string delimiter, CancellationToken ct = default) { return await ReadAsync(this, delimiter, ct); } } }