You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现串口无响应时的设备失联提示逻辑?

如何用jssc实现串口设备失联检测

问题描述

程序通过jssc库连接串口设备,需要在设备无响应时显示“设备失联”提示。但当前事件监听器无法触发该提示,启动程序后仅占用串口无任何动作,查阅jssc示例未找到解决方案。现有代码如下:

import jssc.*;
import java.util.ArrayList;

public class ComPortOperation {
    private static SerialPort serialPort;
    private static int baudRate;
    private static String portName;
    private static ArrayList<Integer> codes = new ArrayList<>();
    static int[] dataInt;


    public static void connect(int number) throws SerialPortException {
        System.out.println(MainView.getItemSuperComboBox());
        serialPort = new SerialPort(portName);
        serialPort.openPort();
        serialPort.setParams(baudRate,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_EVEN);
        serialPort.setEventsMask(SerialPort.MASK_RXCHAR);
        serialPort.addEventListener(new SerialPortReader(serialPort));
       
        serialPort.writeIntArray(new int[]{number});
    }

    static class SerialPortReader implements SerialPortEventListener {
        private SerialPort serialPort;

        public SerialPortReader(SerialPort serialPort){
            this.serialPort = serialPort;
        }
        public void serialEvent(SerialPortEvent event) {
            if(!event.isRXCHAR()) {
                System.out.println("No connection"); // never reaches
            }
            try {
                dataInt = serialPort.readIntArray(1, 500);
            } catch (SerialPortException e) {
                System.out.println(e);
            } catch (SerialPortTimeoutException e) {
                e.printStackTrace();
            }
        }
    }
}

解决方案

jssc的MASK_RXCHAR事件仅在串口收到字符时才会触发,没有数据时不会进入serialEvent方法,因此原代码里的!event.isRXCHAR()判断永远不会执行。需要改用心跳+超时检测的逻辑实现失联判断:

修改后的完整代码

import jssc.*;
import java.util.ArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ComPortOperation {
    private static SerialPort serialPort;
    private static int baudRate;
    private static String portName;
    private static ArrayList<Integer> codes = new ArrayList<>();
    static int[] dataInt;
    // 记录最后一次收到设备数据的时间戳
    private static long lastReceivedTime;
    // 超时检测定时器
    private static ScheduledExecutorService statusChecker;
    // 设备失联阈值(单位:毫秒,示例设为5秒)
    private static final int DISCONNECT_THRESHOLD = 5000;

    public static void connect(int number) throws SerialPortException {
        System.out.println(MainView.getItemSuperComboBox());
        serialPort = new SerialPort(portName);
        serialPort.openPort();
        serialPort.setParams(baudRate,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_EVEN);
        serialPort.setEventsMask(SerialPort.MASK_RXCHAR);
        serialPort.addEventListener(new SerialPortReader(serialPort));

        // 初始化时间戳并启动超时检测
        lastReceivedTime = System.currentTimeMillis();
        statusChecker = Executors.newSingleThreadScheduledExecutor();
        // 每隔1秒检查一次设备状态
        statusChecker.scheduleAtFixedRate(ComPortOperation::checkDeviceStatus, 0, 1000, TimeUnit.MILLISECONDS);

        // 发送初始指令
        serialPort.writeIntArray(new int[]{number});
    }

    static class SerialPortReader implements SerialPortEventListener {
        private SerialPort serialPort;

        public SerialPortReader(SerialPort serialPort){
            this.serialPort = serialPort;
        }
        public void serialEvent(SerialPortEvent event) {
            if(event.isRXCHAR()) {
                try {
                    dataInt = serialPort.readIntArray(1, 500);
                    // 收到数据就更新时间戳
                    lastReceivedTime = System.currentTimeMillis();
                } catch (SerialPortException e) {
                    System.out.println("串口读取异常:" + e.getMessage());
                } catch (SerialPortTimeoutException e) {
                    System.out.println("串口读取超时");
                }
            }
        }
    }

    // 检测设备是否失联
    private static void checkDeviceStatus() {
        long currentTime = System.currentTimeMillis();
        if(currentTime - lastReceivedTime > DISCONNECT_THRESHOLD) {
            System.out.println("设备失联");
            // 此处可添加UI提示逻辑,比如更新界面控件
        }
    }

    // 关闭串口时清理资源
    public static void disconnect() throws SerialPortException {
        if(serialPort != null && serialPort.isOpened()) {
            serialPort.closePort();
        }
        if(statusChecker != null && !statusChecker.isShutdown()) {
            statusChecker.shutdown();
        }
    }
}

核心改进说明

  • 新增时间戳记录:每次收到设备数据时更新lastReceivedTime,标记设备在线状态
  • 定时器轮询检测:通过ScheduledExecutorService每隔1秒检查时间戳差值,超过设定阈值则判定设备失联
  • 资源清理:添加disconnect方法,关闭串口时停止定时器,避免内存泄漏

内容的提问来源于stack exchange,提问作者user27167750

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:01:05