| | |
| | | |
| | | public class SerialPortService { |
| | | |
| | | private SerialPort port; |
| | | private volatile boolean capturing = false; |
| | | private volatile boolean paused = true; |
| | | private Thread readerThread; |
| | | private Consumer<byte[]> responseConsumer; |
| | | |
| | | // 优化:重用缓冲区,减少内存分配 |
| | | private byte[] readBuffer = new byte[200]; |
| | | private ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024); |
| | | private Consumer<byte[]> dataReceivedCallback; |
| | | |
| | | // 新增:协议解析器引用 |
| | | private SerialProtocolParser protocolParser = new SerialProtocolParser(); |
| | | |
| | | // 新增:数据条数计数器 |
| | | public static int receivedDataCount = 0; |
| | | private SerialPort port; |
| | | private volatile boolean capturing = false; |
| | | private volatile boolean paused = true; |
| | | private Thread readerThread; |
| | | private Consumer<byte[]> responseConsumer; |
| | | |
| | | // 其他现有方法保持不变... |
| | | |
| | | /** |
| | | * 获取串口接收的数据条数 |
| | | * 当条数超过1万时自动从1开始重新计数 |
| | | * @return 数据条数字符串 |
| | | */ |
| | | public static String getReceivedDataCount() { |
| | | receivedDataCount++; |
| | | if (receivedDataCount > 10000) { |
| | | receivedDataCount = 1; |
| | | } |
| | | return String.valueOf(receivedDataCount); |
| | | } |
| | | |
| | | public static void setReceivedDataCount(int receivedDataCount) { |
| | | SerialPortService.receivedDataCount = receivedDataCount; |
| | | } |
| | | |
| | | /** |
| | | * 获取协议解析器实例 |
| | | */ |
| | | public SerialProtocolParser getProtocolParser() { |
| | | return protocolParser; |
| | | } |
| | | // 优化:重用缓冲区,减少内存分配 |
| | | private byte[] readBuffer = new byte[200]; |
| | | private ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024); |
| | | private Consumer<byte[]> dataReceivedCallback; |
| | | |
| | | // 新增:协议解析器引用 |
| | | private SerialProtocolParser protocolParser = new SerialProtocolParser(); |
| | | |
| | | // 新增:数据条数计数器 |
| | | public static int receivedDataCount = 0; |
| | | |
| | | // 其他现有方法保持不变... |
| | | |
| | | /** |
| | | * 重置数据条数计数器 |
| | | */ |
| | | public void resetReceivedDataCount() { |
| | | receivedDataCount = 0; |
| | | } |
| | | * 获取串口接收的数据条数 |
| | | * 当条数超过1万时自动从1开始重新计数 |
| | | * @return 数据条数字符串 |
| | | */ |
| | | public static String getReceivedDataCount() { |
| | | receivedDataCount++; |
| | | if (receivedDataCount > 10000) { |
| | | receivedDataCount = 1; |
| | | } |
| | | return String.valueOf(receivedDataCount); |
| | | } |
| | | |
| | | // 以下为原有代码,保持不变... |
| | | public InputStream getInputStream() { |
| | | if (port != null && port.isOpen()) { |
| | | return port.getInputStream(); |
| | | } |
| | | return null; |
| | | } |
| | | public static void setReceivedDataCount(int receivedDataCount) { |
| | | SerialPortService.receivedDataCount = receivedDataCount; |
| | | } |
| | | |
| | | 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 setProtocolParser(SerialProtocolParser parser) { |
| | | this.protocolParser = parser; |
| | | } |
| | | |
| | | /** |
| | | * 启用调试输出,将接收到的数据打印到控制台 |
| | | */ |
| | | public void enableDebugOutput() { |
| | | System.out.println("串口调试输出已启用 - 开始监听串口数据..."); |
| | | } |
| | | /** |
| | | * 获取协议解析器实例 |
| | | */ |
| | | public SerialProtocolParser getProtocolParser() { |
| | | return protocolParser; |
| | | } |
| | | |
| | | /** |
| | | * 获取当前调试状态 |
| | | */ |
| | | public boolean isDebugEnabled() { |
| | | return capturing; |
| | | } |
| | | |
| | | public void startCapture() { |
| | | if (dataReceivedCallback != null) { |
| | | startCapture(dataReceivedCallback); |
| | | } else { |
| | | System.err.println("No data received callback set. Please call startCapture(Consumer<byte[]> onReceived) first."); |
| | | } |
| | | } |
| | | /** |
| | | * 重置数据条数计数器 |
| | | */ |
| | | public void resetReceivedDataCount() { |
| | | receivedDataCount = 0; |
| | | } |
| | | |
| | | /** |
| | | * 打开串口 |
| | | */ |
| | | public boolean open(String portName, int baud) { |
| | | if (port != null && port.isOpen()) { |
| | | return true; |
| | | } |
| | | // 以下为原有代码,保持不变... |
| | | public InputStream getInputStream() { |
| | | if (port != null && port.isOpen()) { |
| | | return port.getInputStream(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | port = SerialPort.getCommPort(portName); |
| | | port.setComPortParameters(baud, 8, 1, SerialPort.NO_PARITY); |
| | | port.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 1, 0); |
| | | protocolParser.start(); |
| | | return port.openPort(); |
| | | } |
| | | |
| | | public void setResponseConsumer(Consumer<byte[]> consumer) { |
| | | this.responseConsumer = consumer; |
| | | } |
| | | public OutputStream getOutputStream() { |
| | | if (port != null && port.isOpen()) { |
| | | return port.getOutputStream(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 关闭串口 |
| | | */ |
| | | public void close() { |
| | | stopCapture(); |
| | | if (port != null && port.isOpen()) { |
| | | port.closePort(); |
| | | } |
| | | port = null; |
| | | } |
| | | public void setComPortTimeouts(int timeoutMode, int readTimeout, int writeTimeout) { |
| | | if (port != null && port.isOpen()) { |
| | | port.setComPortTimeouts(timeoutMode, readTimeout, writeTimeout); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 启动数据接收线程 |
| | | */ |
| | | public void startCapture(Consumer<byte[]> onReceived) { |
| | | this.dataReceivedCallback = onReceived; |
| | | if (capturing || port == null || !port.isOpen()) return; |
| | | capturing = true; |
| | | paused = false; |
| | | /** |
| | | * 设置协议解析器 |
| | | */ |
| | | public void setProtocolParser(SerialProtocolParser parser) { |
| | | this.protocolParser = parser; |
| | | } |
| | | |
| | | readerThread = new Thread(() -> { |
| | | buffer.reset(); |
| | | long lastReceivedTime = 0; |
| | | |
| | | while (capturing && port.isOpen()) { |
| | | long currentTime = System.currentTimeMillis(); |
| | | |
| | | if (buffer.size() > 0 && (currentTime - lastReceivedTime) >= 20) { |
| | | byte[] data = buffer.toByteArray(); |
| | | SystemDebugDialog.appendHexData(data); |
| | | |
| | | // 新增:将数据传递给协议解析器 |
| | | if (protocolParser != null) { |
| | | protocolParser.receiveData(data); |
| | | } |
| | | |
| | | if (!paused) { |
| | | onReceived.accept(data); |
| | | if (responseConsumer != null) { |
| | | responseConsumer.accept(data); |
| | | } |
| | | } |
| | | buffer.reset(); |
| | | } |
| | | /** |
| | | * 启用调试输出,将接收到的数据打印到控制台 |
| | | */ |
| | | public void enableDebugOutput() { |
| | | //System.out.println("串口调试输出已启用 - 开始监听串口数据..."); |
| | | } |
| | | |
| | | int len = port.readBytes(readBuffer, readBuffer.length); |
| | | currentTime = System.currentTimeMillis(); |
| | | /** |
| | | * 获取当前调试状态 |
| | | */ |
| | | public boolean isDebugEnabled() { |
| | | return capturing; |
| | | } |
| | | |
| | | 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(); |
| | | SystemDebugDialog.appendHexData(data); |
| | | |
| | | // 新增:将数据传递给协议解析器 |
| | | if (protocolParser != null) { |
| | | protocolParser.receiveData(data); |
| | | } |
| | | |
| | | if (!paused) { |
| | | onReceived.accept(data); |
| | | if (responseConsumer != null) { |
| | | responseConsumer.accept(data); |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | readerThread.setDaemon(true); |
| | | readerThread.start(); |
| | | } |
| | | public void startCapture() { |
| | | if (dataReceivedCallback != null) { |
| | | startCapture(dataReceivedCallback); |
| | | } else { |
| | | System.err.println("No data received callback set. Please call startCapture(Consumer<byte[]> onReceived) first."); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 停止数据接收线程 |
| | | */ |
| | | public void stopCapture() { |
| | | capturing = false; |
| | | if (readerThread != null) { |
| | | try { readerThread.join(500); } catch (InterruptedException ignore) {} |
| | | readerThread = null; |
| | | } |
| | | } |
| | | /** |
| | | * 打开串口 |
| | | */ |
| | | public boolean open(String portName, int baud) { |
| | | if (port != null && port.isOpen()) { |
| | | return true; |
| | | } |
| | | |
| | | public void setPaused(boolean paused) { |
| | | this.paused = paused; |
| | | } |
| | | port = SerialPort.getCommPort(portName); |
| | | port.setComPortParameters(baud, 8, 1, SerialPort.NO_PARITY); |
| | | port.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 1, 0); |
| | | protocolParser.start(); |
| | | return port.openPort(); |
| | | } |
| | | |
| | | public boolean isPaused() { |
| | | return paused; |
| | | } |
| | | public void setResponseConsumer(Consumer<byte[]> consumer) { |
| | | this.responseConsumer = consumer; |
| | | } |
| | | |
| | | public boolean isOpen() { |
| | | return port != null && port.isOpen(); |
| | | } |
| | | /** |
| | | * 关闭串口 |
| | | */ |
| | | public void close() { |
| | | stopCapture(); |
| | | if (port != null && port.isOpen()) { |
| | | port.closePort(); |
| | | } |
| | | port = null; |
| | | } |
| | | |
| | | /** |
| | | * 发送数据 |
| | | */ |
| | | public boolean send(byte[] data) { |
| | | if (!isOpen()) { |
| | | return false; |
| | | } |
| | | return port != null && port.isOpen() && port.writeBytes(data, data.length) > 0; |
| | | } |
| | | /** |
| | | * 启动数据接收线程 |
| | | */ |
| | | public void startCapture(Consumer<byte[]> 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()) { |
| | | long currentTime = System.currentTimeMillis(); |
| | | |
| | | if (buffer.size() > 0 && (currentTime - lastReceivedTime) >= 20) { |
| | | byte[] data = buffer.toByteArray(); |
| | | SystemDebugDialog.appendHexData(data); |
| | | |
| | | // 新增:将数据传递给协议解析器 - 确保始终执行 |
| | | if (protocolParser != null) { |
| | | protocolParser.receiveData(data); |
| | | } |
| | | |
| | | // 确保数据回调始终执行,不受暂停状态影响 |
| | | if (dataReceivedCallback != null && !paused) { |
| | | dataReceivedCallback.accept(data); |
| | | } |
| | | if (responseConsumer != null && !paused) { |
| | | 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(); |
| | | SystemDebugDialog.appendHexData(data); |
| | | |
| | | // 新增:将数据传递给协议解析器 - 确保始终执行 |
| | | if (protocolParser != null) { |
| | | protocolParser.receiveData(data); |
| | | } |
| | | |
| | | // 确保数据回调始终执行,不受暂停状态影响 |
| | | if (dataReceivedCallback != null && !paused) { |
| | | dataReceivedCallback.accept(data); |
| | | } |
| | | if (responseConsumer != null && !paused) { |
| | | responseConsumer.accept(data); |
| | | } |
| | | } |
| | | }); |
| | | readerThread.setDaemon(true); |
| | | readerThread.start(); |
| | | } |
| | | // 新增:设置暂停状态但不影响协议解析器 |
| | | public void setPaused(boolean paused) { |
| | | this.paused = paused; |
| | | // 注意:不停止协议解析器,只暂停UI回调 |
| | | } |
| | | |
| | | // 新增:单独停止数据捕获而不影响协议解析器 |
| | | public void stopDataCaptureOnly() { |
| | | // 只停止数据回调,不影响协议解析器 |
| | | this.dataReceivedCallback = null; |
| | | this.responseConsumer = null; |
| | | } |
| | | /** |
| | | * 停止数据接收线程 |
| | | */ |
| | | public void stopCapture() { |
| | | capturing = false; |
| | | if (readerThread != null) { |
| | | try { readerThread.join(500); } catch (InterruptedException ignore) {} |
| | | readerThread = null; |
| | | } |
| | | } |
| | | |
| | | |
| | | public boolean isPaused() { |
| | | return paused; |
| | | } |
| | | |
| | | public boolean isOpen() { |
| | | return port != null && port.isOpen(); |
| | | } |
| | | /** |
| | | * 发送数据(优化版本) |
| | | */ |
| | | public boolean send(byte[] data) { |
| | | if (!isOpen()) { |
| | | return false; |
| | | } |
| | | |
| | | // 添加发送前的串口状态检查 |
| | | if (port == null || !port.isOpen()) { |
| | | return false; |
| | | } |
| | | |
| | | try { |
| | | // 添加小延迟,避免连续发送 |
| | | Thread.sleep(2); |
| | | } catch (InterruptedException e) { |
| | | Thread.currentThread().interrupt(); |
| | | return false; |
| | | } |
| | | |
| | | int result = port.writeBytes(data, data.length); |
| | | return result > 0; |
| | | } |
| | | |
| | | } |