| | |
| | | // 声明包名 dell_system |
| | | // 声明包名 dell_system |
| | | package home; |
| | | |
| | | // 导入串口通信库 |
| | | // 导入串口通信库 |
| | | import com.fazecast.jSerialComm.SerialPort; |
| | | // 导入 Java 函数式接口 Consumer,用于数据接收回调 |
| | | // 导入 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<byte[]> responseConsumer; |
| | | |
| | | |
| | | // 优化:重用缓冲区,减少内存分配 |
| | | // 优化:重用缓冲区,减少内存分配 |
| | | private byte[] readBuffer = new byte[200]; |
| | | private ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024); |
| | | private Consumer<byte[]> dataReceivedCallback; |
| | |
| | | } |
| | | |
| | | /** |
| | | * 打开串口 |
| | | * @param portName 串口名称(如 COM3) |
| | | * @param baud 波特率(如 9600) |
| | | * @return 是否成功打开 |
| | | * 打开串口 |
| | | * @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、无校验位 |
| | | // 设置串口参数:波特率、数据位8、停止位1、无校验位 |
| | | port.setComPortParameters(baud, 8, 1, SerialPort.NO_PARITY); |
| | | // 修改为半阻塞模式,读超时1ms |
| | | // 修改为半阻塞模式,读超时1ms |
| | | port.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 1, 0); |
| | | |
| | | // 打开串口并返回结果 |
| | | // 打开串口并返回结果 |
| | | return port.openPort(); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 关闭串口 |
| | | * 关闭串口 |
| | | */ |
| | | public void close() { |
| | | // 先停止数据接收线程 |
| | | // 先停止数据接收线程 |
| | | stopCapture(); |
| | | // 如果串口已打开,关闭它 |
| | | // 如果串口已打开,关闭它 |
| | | if (port != null && port.isOpen()) { |
| | | port.closePort(); |
| | | } |
| | | // 释放串口引用 |
| | | // 释放串口引用 |
| | | port = null; |
| | | } |
| | | |
| | | /** |
| | | * 启动数据接收线程 |
| | | * @param onReceived 数据接收回调函数,收到数据时调用 |
| | | * 启动数据接收线程 |
| | | * @param onReceived 数据接收回调函数,收到数据时调用 |
| | | */ |
| | | public void startCapture(Consumer<byte[]> onReceived) { |
| | | this.dataReceivedCallback = onReceived; |
| | |
| | | readerThread.start(); |
| | | } |
| | | /** |
| | | * 停止数据接收线程 |
| | | * 停止数据接收线程 |
| | | */ |
| | | public void stopCapture() { |
| | | // 设置捕获标志为 false,通知线程退出 |
| | | // 设置捕获标志为 false,通知线程退出 |
| | | capturing = false; |
| | | // 如果线程存在,等待最多500ms确保线程结束 |
| | | // 如果线程存在,等待最多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 是否成功发送 |
| | | * 发送数据 |
| | | * @param data 要发送的字节数组 |
| | | * @return 是否成功发送 |
| | | */ |
| | | public boolean send(byte[] data) { |
| | | // 如果串口已初始化且已打开,发送数据并返回结果 |
| | | if (!isOpen()) { |
| | | return false; |
| | | } |
| | | // 如果串口已初始化且已打开,发送数据并返回结果 |
| | | return port != null && port.isOpen() && port.writeBytes(data, data.length) > 0; |
| | | } |
| | | } |