package aimax.osm.gps; import gnu.io.CommPortIdentifier; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; import java.io.File; import java.io.IOException; import java.util.Enumeration; /** * Reads GPS data from a NMEA stream via a serial port connection. * To compile and run this class, download the rs232 serial port library * from http://www.rxtx.org/ and install it correctly. * One possibility is, to add the jar-file * to the class path (project properties, add jar), to store the DDL * locally (e.g. in project-root/lib), and start the application with * VM argument -Djava.library.path=lib. * @author Ruediger Lunde */ public class NmeaSerialPortReader extends NmeaReader { public static int TIMEOUT = 2000; // 2 seconds public static int BAUDRATE = 38400; private SerialPort sPort; private SerialPortEventListener sPortListener; private String portname; public NmeaSerialPortReader() { sPortListener = new SerialPortEventListener() { public void serialEvent(SerialPortEvent event) { if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) { readFromStream(false); } } }; } /** * Specifies the name of the serial port to be used for the * next connection to be opened. */ public void selectPortName(String portname) { this.portname = portname; } /** * Returns the name of the selected serial port. */ public String getSelectedPortName() { return portname; } /** * Opens the stream if it is not already open. If no port * name is selected, all serial ports are scanned. */ public void openStream() throws Exception { if (sPort != null) return; if (findSerialPort()) { sPort.addEventListener(sPortListener); sPort.notifyOnDataAvailable(true); } else if (portname != null) { throw new IOException("Serial port " + portname + " not found."); } else { throw new IOException("No serial port with NMEA messages found."); } } /** Closes the stream and also the serial port. */ public void closeStream() throws IOException { if (sPort != null) { sPort.removeEventListener(); //sPort.notifyOnDataAvailable(false); sPort.close(); sPort = null; super.closeStream(); } } /** Searches for a serial port providing NMEA messages. */ private boolean findSerialPort() throws Exception { Enumeration portList = CommPortIdentifier.getPortIdentifiers(); while (portList.hasMoreElements()) { CommPortIdentifier pid = (CommPortIdentifier) portList.nextElement(); if (pid.getPortType() == CommPortIdentifier.PORT_SERIAL && (portname == null || pid.getName().equals(portname))) { sPort = (SerialPort) pid.open("NmeaSerialPortReader", TIMEOUT); //System.out.println("\n" + pid.getName()); sPort.setSerialPortParams(BAUDRATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); inputStream = sPort.getInputStream(); Thread.sleep(TIMEOUT); int avail = inputStream.available(); if (avail > 0) { //Thread.sleep(TIMEOUT); StringBuffer buffer = new StringBuffer(); int value; while ((value = inputStream.read()) != -1 && buffer.length() < 500) { buffer.append((char) value); } //System.out.println(sPort.getName() + ": " + buffer.toString() + "\n"); if (buffer.toString().contains("$GPGGA")) { portname = pid.getName(); return true; } } sPort.close(); sPort = null; } } return false; } ///////////////////////////////////////////////////////////////// // Simple test program... public static void main(String[] args) { try { NmeaSerialPortReader reader = new NmeaSerialPortReader(); reader.openStream(); NmeaMessageListener consoleLogger = new NmeaMessageListener() { public void messageReceived(String buffer) { System.out.print(buffer); } }; MessageToFileListener fileLogger = new MessageToFileListener(); reader.addListener(consoleLogger); reader.addListener(fileLogger); fileLogger.openFile(new File("nmeaout.txt")); } catch (Exception e) { e.printStackTrace(); } } }