2017-06-05 184 views
0

我正在使用JSSC串行端口包在我的应用程序和连接到串行端口的设备之间交换数据。我做了一个简单的应用程序,它可以发送识别信息到设备并打印回应。我希望它能抵抗连接错误(例如在通信期间拔掉电缆后)。JSSC - 断开连接会导致阻塞串行端口

操作顺序初始化 - >打开 - > IDN - >关闭完美。 当我在打开端口后拔下电缆时,我无法发送消息(对我来说似乎是合乎逻辑的)并关闭了端口(没有什么东西可以关闭了,所以我也明白了)。

一开始我很惊讶我再次插上电缆后无法关闭端口,但我发现在每次连接设备后,OS会给它一个不同的号码,JSSC库用它来处理端口。幸运的是,事实证明,只需在重新连接后打开端口即可解决所有问题,因为应用程序可以再次发送消息。

不幸的是,当端口被打开时有更多的断开/连接电缆的尝试出现问题。每次尝试后,应用程序的运行速度越来越慢,以至于无法再发送消息的状态结束。另一件事是,在这种状态下,所有串口(不仅是我试图与之通信的那一个)都被阻塞,我甚至无法通过终端类应用程序访问它们。

所以,问题是:

我怎样才能让应用程序是连接中断性不阻塞端口和松动的表现?

我想这可能是关于某种资源,内存管理等,但是我对这些东西的了解还不足以自己解决问题。

执行通信的:

import jssc.SerialPort; 
import jssc.SerialPortEvent; 
import jssc.SerialPortEventListener; 
import jssc.SerialPortException; 

class Connection implements SerialPortEventListener { 
    private static final int SERIAL_PORT_BAUD_RATE = 9600; 
    private static final int SERIAL_PORT_DATA_BITS_NUMBER = 8; 
    private static final int SERIAL_PORT_STOP_BITS_NUMBER = 1; 
    private static final int SERIAL_PORT_PARITY = 0; 

    private SerialPort serialPort; 
    private String portName; 

    public Connection(String portName) { 
    this.portName = portName; 
    } 

    public void open() throws SerialPortException { 
    serialPort = new SerialPort(portName); 
    serialPort.openPort(); 
    serialPort.setParams(SERIAL_PORT_BAUD_RATE, 
      SERIAL_PORT_DATA_BITS_NUMBER, 
      SERIAL_PORT_STOP_BITS_NUMBER, 
      SERIAL_PORT_PARITY); 
    serialPort.addEventListener(this); 
    } 

    public void close() throws SerialPortException { 
    if (serialPort != null) { 
     serialPort.closePort(); 
    } 
    } 

    public void simpleMessage() throws SerialPortException { 
    if (serialPort != null) { 
     serialPort.writeString("IDN"); 
    } 
    } 

    @Override 
    public void serialEvent(SerialPortEvent serialPortEvent) { 
    if (serialPortEvent.getEventType() == SerialPortEvent.RXCHAR) { 
     try { 
     System.out.println(serialPort.readString()); 
     } catch (SerialPortException e) { 
     System.out.println("Error while reading a string."); 
     } 
    } 
    } 
} 

主类:

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Scene; 
import javafx.scene.layout.Pane; 
import javafx.stage.Stage; 
import java.io.IOException; 

public class MainApplication extends Application{ 
    public static void main(String [] args) { 
    Application.launch(); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
    Pane rootPane = null; 
    FXMLLoader loader = new FXMLLoader(); 
    loader.setLocation(MainApplication.class.getResource("front.fxml")); 

    try{ 
     rootPane = loader.load(); 
    } catch (IOException exception) { 
     exception.printStackTrace(); 
    } 

    Scene scene = new Scene(rootPane); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
    primaryStage.setOnCloseRequest(event -> { 
     Platform.exit(); 
     System.exit(0); 
    }); 
    } 
} 

FXML代码:

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.layout.StackPane?> 
<?import javafx.scene.control.Button?> 
<?import javafx.scene.layout.VBox?> 

<StackPane fx:id="rootPane" 
      xmlns="http://javafx.com/javafx/8.0.60" 
      xmlns:fx="http://javafx.com/fxml/1" 
      fx:controller="FrontController"> 
    <VBox> 
     <Button text="Init" onAction="#init"/> 
     <Button text="Open" onAction="#openPort"/> 
     <Button text="Close" onAction="#closePort"/> 
     <Button text="IDN" onAction="#idn"/> 
     <Button text="Get Ports" onAction="#getPorts"/> 
     <Button text="Is opened?" onAction="#isPortOpen"/> 
    </VBox> 
</StackPane> 

控制器:

import javafx.fxml.FXML; 
import jssc.SerialPortException; 
import jssc.SerialPortList; 
import java.util.Arrays; 

public class FrontController { 

    private Connection connection; 

    @FXML 
    private void init() { 
    String portName = "COM4"; 
    connection = new Connection(portName); 
    } 

    @FXML 
    private void openPort() { 
    try { 
     connection.open(); 
    } catch (SerialPortException e) { 
     e.printStackTrace(); 
    } 
    } 

    @FXML 
    private void closePort() { 
    try { 
     connection.close(); 
    } catch (SerialPortException e) { 
     e.printStackTrace(); 
    } 
    } 

    @FXML 
    private void idn() { 
    try { 
     connection.idnMessage(); 
    } catch (SerialPortException e) { 
     e.printStackTrace(); 
    } 
    } 

    @FXML 
    private void getPorts() { 
    System.out.println(Arrays.toString(SerialPortList.getPortNames())); 
    } 

    @FXML 
    private void isPortOpen() { 
    System.out.println(connection.getSerialPort().isOpened()); 
    } 
} 

回答

0

基本上在没有关闭的情况下拔掉设备(实际上大多数时间在windows操作系统中)会使操作系统处于不一致的状态。当设备被移除时,您需要清理干净。请注意,即使设备已被移除,关闭端口也非常重要。我们可能会留下接近的回报价值。这给了OS提示,即应用程序对设备也不感兴趣,因此操作系统可以自由发布我们也想要的资源。 所以简而言之,我们需要创建一个线程来监视我们的设备是否连接到系统。