Using the RXTX Java Library

March 9, 2014

There are several libraries for Java that add support for serial ports, and a few months ago I settled on the RXTX library. Recently their web site disappeared and looking back at the code releases it became apparent that development halted a couple years ago. A few groups are still maintaining packages for the library, and people still use it, so I'll post my installation and helloworld notes.

Archive.org has a mirror of the old RXTX web site:
http://web.archive.org/web/20130117073055/http://rxtx.qbang.org/wiki/index.php/Main_Page

Installation

A Linux installation is trivial since RXTX is in the package repositories:

$ sudo apt-get install librxtx-java

An OS X installation is not so easy. Binaries are available from the official RXTX web site, but they are outdated and not compatible with modern versions of OS X. Compiling from source isn't hard, but there are a few changes that must be made along the way. Assuming you already have Java installed, you'll need to install libtool via Homebrew because the stock libtool supplied by Apple won't work.

Install Homebrew, then install libtool:

$ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)" $ brew install libtool

Download the RXTX 2.2pre2 source and extract the archive. Then edit the configure file, modifying the JAVAINCLUDEDIR line:

Before: JAVAINCLUDEDIR=$JPATH/../../../Headers After: JAVAINCLUDEDIR=/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers

(Make sure the path is valid. It may be different if you installed a different version or distribution of Java than I did.)

Run the configure script:

$ ./configure

Assuming that completed successfully, edit the LIBTOOLC line in the Makefile:

Before: LIBTOOLC = $(GLIBTOOL) --mode=compile $(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(VERBOSE_IOEXCEPTIONS) -c After: LIBTOOLC = $(GLIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(VERBOSE_IOEXCEPTIONS) -c

Compile and copy the resulting files into place:

$ make $ cp RXTXcomm.jar /Library/Java/Extensions/ $ cp i386-apple-darwin13.0.0/librxtxSerial.jnilib /Library/Java/Extensions/

Simple Example

The official RXTX wiki has some good examples. Below is an adaption I made with the explicit goal of being short and to the point. See the official examples for better error handling and other use cases.

The following class has two methods: Use getSerialPorts() to get a List<String> of detected serial ports. Then call establishConnection() to make a connection and create the input/output streams. For example, calling establishConnection("/dev/ttyUSB0", 9600); would connect to /dev/ttyUSB0 with a 9600 8N1 configuration. I also setup a Scanner to make it trivial to parse incoming data.

import gnu.io.*; import java.io.*; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Scanner; public class SerialTest { private SerialPort rs232; private OutputStream rs232ostream; private InputStream rs232istream; private Scanner rs232scanner; public List getSerialPorts() { List list = new ArrayList(); @SuppressWarnings("unchecked") Enumeration ports = CommPortIdentifier.getPortIdentifiers(); while(ports.hasMoreElements()) { CommPortIdentifier port = ports.nextElement(); if(port.getPortType() == CommPortIdentifier.PORT_SERIAL) list.add(port.getName()); } return list; } public Boolean establishConnection(String port, int baudRate) { try { rs232 = (SerialPort) CommPortIdentifier.getPortIdentifier(port).open("Test App", 2000); // app name, timeout rs232.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); rs232ostream = rs232.getOutputStream(); rs232istream = rs232.getInputStream(); rs232scanner = new Scanner(rs232istream); System.out.println("Connected to " + port + " at " + baudRate + " baud."); return true; } catch (Exception e) { System.err.println("Error setting up serial communications with port " + port + "."); System.err.println(e.getClass().toString()); return false; } } // add code that makes use of the input or output streams after calling establishConnection() }