2017-06-05 62 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提示,即應用程序對設備也不感興趣,因此操作系統可以自由發佈我們也想要的資源。 所以簡而言之,我們需要創建一個線程來監視我們的設備是否連接到系統。