JavaSerial Tutorial

Using the JavaSerial library is very straightforward.  Everything revolves around the SerialPort class.  This class represents a serial port on the system, and all of the associated settings with it.  So, let’s go and get a SerialPort object. Whenever you create a new SerialPort object, there are two exceptions that could be thrown and that you must look out for. These are NoSuchPortException, which is thrown when you try to open a serial port that doesn’t exist, and NotASerialPortException, which is thrown when you have opened up some thing that is not a serial port.  Here’s the basic example:

import com.rm5248.serial.NoSuchPortException;
import com.rm5248.serial.NotASerialPortException;
import com.rm5248.serial.SerialPort;

public class SerialTest {

	public static void main(String[] args) {
		try {
			//This would be COM1, COM2, etc on Windows
			SerialPort s = new SerialPort( "/dev/ttyUSB0" );
		} catch (NoSuchPortException e) {
			System.err.println( "Oh no!  That port doesn't exist!" );
		} catch (NotASerialPortException e) {
			System.err.println( "Oh no!  That's not a serial port!" );
		}

	}

}

The reason that these two exceptions exist like this is so that what port to open is more free-formed.  The standard Java comm API requires more set-up, whereas this way is closer to the native way of doing it.  This also allows for opening up a serial port by opening a symlink.

Note that when we create a new serial port, we can also specify the baud rate, the number of stop bits, flow control, and parity.  We can also specify what control lines were are interested in.  Many times, we don’t care about the control lines, and so we can open up the serial port like this:

new SerialPort( "/dev/ttyUSB0", SerialPort.
    NO_CONTROL_LINE_CHANGE );

This is an optimization to allow fewer threads to be created, as each SerialPort requires a separate thread in order to parse the serial change events.  You can set what events you are interested in with a bitwise-OR of CONTROL_LINE_XXX_CHANGE fields.

As of version 0.11, there is now a builder class that you can use to create the serial port in an easy manner.

try {
    SerialPortBuilder builder = new SerialPortBuilder();
    builder.setBaudRate( BaudRate.B115200 )
        .setPort( "/dev/ttyUSB0" )
        .setStopBits(SerialPort.StopBits.STOPBITS_2 )
        .setParity(SerialPort.Parity.EVEN);
    SerialPort port = builder.build();
} catch (NoSuchPortException ex) {
    System.err.println( "Oh no!  That port doesn't exist!" );
} catch (NotASerialPortException ex) {
    System.err.println( "Oh no!  That's not a serial port!" );
}

Now that we have our SerialPort object, we can get the InputStream and OutputStream of the object, and begin merrily writing and reading away.

		InputStream is = s.getInputStream();
		OutputStream os = s.getOutputStream();

		try {
			os.write( "Hello!".getBytes() );
		} catch (IOException e) {
			e.printStackTrace();
		}

We can also get and set the state of the lines on the serial port.

		try {
			SerialLineState state = s.getSerialLineState();

			System.out.println( state );

			//This will toggle the DTR line
			state.dataTerminalReady = !state.dataTerminalReady;
			s.setSerialLineState( state );
		} catch (IOException e) {
			e.printStackTrace();
		}

We can set up a callback function which will fire when the state of the serial lines changes.  This is only used if you do not say NO_CONTROL_LINE_CHANGE when opening the serial port.

		s.setSerialChangeListener( new SerialChangeListener() {

			@Override
			public void serialStateChanged(SerialLineState state) {
				System.out.println( "The state of the serial lines was changed! " );
				System.out.println( "   New state: " + state );
			}
		});

Finally, when we are all done, we can close our serial port.

s.close();

Native Libraries

As of JavaSerial 0.5, the native code to interface with the serial port is extracted automatically from the JAR file.  All previous versions must have the java.library.path property set.

You can set the location and the name of the library to load with the following system properties:

com.rm5248.javaserial.lib.path - The directory to look in for the javaserial.[dll|so]
com.rm5248.javaserial.lib.name - The name of the library to load(default:javaserial)

Major Differences between this and the Java Comm API:

  • JavaSerial is based around input streams and output streams, not around events on the serial port.
  • All settings use enums to set properties, which means that version 5 (or later) of Java is required.  As of JavaSerial 0.5, the classes are compiled for Java 7.  If you need an earlier version, you will have to compile the project yourself.

3 responses to “JavaSerial Tutorial

  1. Pingback: JavaSerial 0.5 | RM Programming Utilities

Leave a Reply

Your email address will not be published. Required fields are marked *