Search code examples
javajavafxevent-handlingserial-portlistener

Send data received on serial port to JavaFX controller


I'm trying to read data from the serial port and display it in a JavaFX controller. I'm using jSerialComm to read data from the serial port. This is their example:

public final class MessageListener implements SerialPortMessageListener {
    @Override
    public int getListeningEvents() { return SerialPort.LISTENING_EVENT_DATA_RECEIVED; }

    @Override
    public byte[] getMessageDelimiter() { return new byte[] { (byte) 0x03}; }

    @Override
    public boolean delimiterIndicatesEndOfMessage() { return true; }

    @Override
    public void serialEvent(SerialPortEvent event) {
        byte[] delimitedMessage = event.getReceivedData();
        System.out.println("Received the following delimited message: " + new String(delimitedMessage));
    }
}

The serial event is then attached to a com port:

static public void main(String[] args) {
    SerialPort comPort = SerialPort.getCommPorts()[0];

    comPort.setBaudRate(1200);
    comPort.openPort();
    comPort.addDataListener(new MessageListener());
}

In the serialEvent method, data is printed in the console. How can I send the data received in this event to a JavaFX controller?


Solution

  • It's not really clear what you're asking: you already have all the pieces.

    I'm not familiar with jSerialComm (in particular how it manages threading), but your JavaFX application will look like this:

    public class MyApp extends Application {
        private SerialPort comPort;
    
        public static void main(String[] args) {
            Application.launch(args);
        }
    
        @Override
        public void init() {
            comPort = SerialPort.getCommPorts()[0];
    
            comPort.setBaudRate(1200);
            comPort.openPort();
        }
    
        @Override
        public void start(Stage stage) {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("/path/to/fxml/file"));
            Parent root = loader.load();
            MyControllerClass controller = loader.getController();
    
            SerialPortMessageListener listener = new SerialPortMessageListener() {
                @Override
                public int getListeningEvents() { return SerialPort.LISTENING_EVENT_DATA_RECEIVED; }
    
                @Override
                public byte[] getMessageDelimiter() { return new byte[] { (byte)0x03}; }
    
                @Override
                public boolean delimiterIndicatesEndOfMessage() { return true; }
    
                @Override
                public void serialEvent(SerialPortEvent event) {
                    byte[] delimitedMessage = event.getReceivedData();
                    Platform.runLater(() -> controller.processData(new String(delimitedMessage)));
                }
            }
    
            Scene scene = new Scene(root);
            stage.setScene(scene);
            stage.show();
        }
    
        @Override
        public void stop() {
            // shut down comPort
        }
    }
    

    and

    public class MyControllerClass {
        @FXML
        private TextArea textArea;
    
        public void processData(String data) {
            textArea.appendText(data);
        }
    
        // other controller stuff
    }