// 声明包名 dell_system package home; // 导入串口通信库 import com.fazecast.jSerialComm.SerialPort; // 导入 Java 函数式接口 Consumer,用于数据接收回调 import javax.swing.*; import java.util.function.Consumer; // 导入字节数组输出流 import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; /** * 串口服务类 * 负责串口的打开、关闭、数据收发 */ public class SerialPortService { // 串口对象,用于与硬件通信 private SerialPort port; // 标记是否正在捕获数据(线程运行中) private volatile boolean capturing = false; // 标记是否暂停接收数据 private volatile boolean paused = false; // 数据读取线程 private Thread readerThread; private Consumer responseConsumer; // 优化:重用缓冲区,减少内存分配 private byte[] readBuffer = new byte[200]; private ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024); private Consumer dataReceivedCallback; public InputStream getInputStream() { if (port != null && port.isOpen()) { return port.getInputStream(); } return null; } public OutputStream getOutputStream() { if (port != null && port.isOpen()) { return port.getOutputStream(); } return null; } public void setComPortTimeouts(int timeoutMode, int readTimeout, int writeTimeout) { if (port != null && port.isOpen()) { port.setComPortTimeouts(timeoutMode, readTimeout, writeTimeout); } } public void startCapture() { if (dataReceivedCallback != null) { startCapture(dataReceivedCallback); } else { System.err.println("No data received callback set. Please call startCapture(Consumer onReceived) first."); } } /** * 打开串口 * @param portName 串口名称(如 COM3) * @param baud 波特率(如 9600) * @return 是否成功打开 */ public boolean open(String portName, int baud) { // 如果串口已打开,直接返回成功 if (port != null && port.isOpen()) { return true; } // 根据名称获取串口实例 port = SerialPort.getCommPort(portName); // 设置串口参数:波特率、数据位8、停止位1、无校验位 port.setComPortParameters(baud, 8, 1, SerialPort.NO_PARITY); // 修改为半阻塞模式,读超时1ms port.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 1, 0); // 打开串口并返回结果 return port.openPort(); } public void setResponseConsumer(Consumer consumer) { this.responseConsumer = consumer; } /** * 关闭串口 */ public void close() { // 先停止数据接收线程 stopCapture(); // 如果串口已打开,关闭它 if (port != null && port.isOpen()) { port.closePort(); } // 释放串口引用 port = null; } /** * 启动数据接收线程 * @param onReceived 数据接收回调函数,收到数据时调用 */ public void startCapture(Consumer onReceived) { this.dataReceivedCallback = onReceived; if (capturing || port == null || !port.isOpen()) return; capturing = true; paused = false; readerThread = new Thread(() -> { buffer.reset(); long lastReceivedTime = 0; while (capturing && port.isOpen()) { if (paused) { buffer.reset(); int len; do { len = port.readBytes(readBuffer, readBuffer.length); } while (len > 0); try { Thread.sleep(100); } catch (InterruptedException ignore) {} continue; } long currentTime = System.currentTimeMillis(); if (buffer.size() > 0 && (currentTime - lastReceivedTime) >= 20) { byte[] data = buffer.toByteArray(); onReceived.accept(data); if (responseConsumer != null) { responseConsumer.accept(data); } buffer.reset(); } int len = port.readBytes(readBuffer, readBuffer.length); currentTime = System.currentTimeMillis(); if (len > 0) { buffer.write(readBuffer, 0, len); lastReceivedTime = currentTime; } if (len <= 0 && buffer.size() == 0) { try { Thread.sleep(1); } catch (InterruptedException ignore) {} } } if (buffer.size() > 0) { byte[] data = buffer.toByteArray(); onReceived.accept(data); if (responseConsumer != null) { responseConsumer.accept(data); } } }); readerThread.setDaemon(true); readerThread.start(); } /** * 停止数据接收线程 */ public void stopCapture() { // 设置捕获标志为 false,通知线程退出 capturing = false; // 如果线程存在,等待最多500ms确保线程结束 if (readerThread != null) { try { readerThread.join(500); } catch (InterruptedException ignore) {} // 清空线程引用 readerThread = null; } } // 设置暂停状态 public void setPaused(boolean paused) { this.paused = paused; } // 获取当前是否暂停 public boolean isPaused() { return paused; } // 判断串口是否已打开 public boolean isOpen() { return port != null && port.isOpen(); } /** * 发送数据 * @param data 要发送的字节数组 * @return 是否成功发送 */ public boolean send(byte[] data) { if (!isOpen()) { return false; } // 如果串口已初始化且已打开,发送数据并返回结果 return port != null && port.isOpen() && port.writeBytes(data, data.length) > 0; } }