我正在使用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());
  }
}

最佳答案

基本上拔下设备有时不关闭设备(大多数情况下在Windows操作系统中无效)会使操作系统处于不一致状态。卸下设备后,您需要进行清理。请注意,即使设备已卸下,关闭端口也非常重要。我们可能会将返回值保留为close。这向OS暗示了该应用也不对设备感兴趣,因此OS可以自由释放我们也想要的资源。
简而言之,我们需要创建一个线程,该线程将监视我们的设备是否连接到系统。

07-28 00:58
查看更多