content: package aimax.osm.gps;
  
  import java.io.File;
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Maintains a connection to a GPS via a NMEA stream, decodes the
   * position messages and publishes the obtained position informations.
   * <p>To run this class, download the rs232 serial port library from
   * http://www.rxtx.org, install it correctly, and rename file
   * <code>NmeaSerialPortReader.txt</code> in package <code>aimax.osm.gps</code>
   * to <code>NmeaSerialPortReader.class</code>.
   * One possible choice for installation 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 <code>-Djava.library.path=lib</code>.</p>
   * @author Ruediger Lunde
   */
  public class GpsLocator implements NmeaReader.NmeaMessageListener {
  
  	private NmeaReader nmeaReader;
  	private NmeaReader nmeaSerialPortReader;
  	private GpsFix currPosition;
  	private List<GpsPositionListener> listeners;
  	
  	/** Creates a new locator. */
  	public GpsLocator() {
  		currPosition = new GpsFix(false, 0.0f, 0.0f);
  		listeners = new ArrayList<>();
  	}
  	
  	/**
  	 * Sets the data source for the locator to a file reader.
  	 */
  	public void openSerialPortConnection() {
  		closeConnection();
  		if (nmeaSerialPortReader == null)
  			nmeaSerialPortReader = NmeaReaderFactory.instance().createSerialPortReader();
  		if (nmeaSerialPortReader != null) {
  			try {
  				nmeaSerialPortReader.openStream();
  				nmeaReader = nmeaSerialPortReader;
  				nmeaReader.addListener(this);
  			} catch (Exception e) {
  				e.printStackTrace();
  			}
  		}
  	}
  	
  	/**
  	 * Sets the data source for the locator to a file reader.
  	 */
  	public void openFileConnection(File file) {
  		closeConnection();
  		try {
  			nmeaReader = NmeaReaderFactory.instance().createFileReader(file);
  			if (nmeaReader != null) {
  				nmeaReader.addListener(this);
  				nmeaReader.openStream();
  			}
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  	}
  	
  	public boolean isConnected() {
  		return nmeaReader != null;
  	}
  	
  	public void closeConnection() {
  		if (isConnected()) {
  			try {
  				nmeaReader.removeListener(this);
  				nmeaReader.closeStream();
  				nmeaReader = null;
  			} catch (Exception e) {
  				e.printStackTrace();
  			}
  		}
  	}
  	
  	/**
  	 * Can be used, to check, whether the connection was opened
  	 * successfully (result != null).
  	 */
  	public NmeaReader getNmeaReader() {
  		return nmeaReader;
  	}
  	
  	public void addGpsPositionListener(GpsPositionListener listener) {
  		listeners.add(listener);
  	}
  	
  	public void removeGpsPositionListener(GpsPositionListener listener) {
  		listeners.remove(listener);
  	}
  	
  	/** Returns the last valid position which was provided by the NMEA stream. */
  	public GpsFix getCurrPosition() {
  		return currPosition;
  	}
  	
  	/**
  	 * Parses the position data currently in buffer, updates the
  	 * the current position and informs all interested listeners.
  	 */
  	public void messageReceived(String message) {
  		if (message.startsWith("$GPGGA")) {
  		// System.out.println(buffer.toString());
  		// idx:   1          2         3 4          5 6 7  8    9         11   12 14
  		// $GPGGA,120007.000,5056.2197,N,02406.0867,W,0,00,99.9,12787.4,M,62.0,M,,0000*7B (NL-402U)
  		// $GPGGA,103131.000,4824.2758,N,00959.9357,E,1,06,1.3,458.5,M,43.9,M,,0000*54
  		// $GPGGA,044944,4824.3044,N,00959.9409,E,1,05,3.1,451.0,M,46.8,M,,*4E
  			String[] mparts = message.split(",");
  			if (mparts.length != 15)
  				return;
  			boolean posOK = true;
  			float lat;
  			float lon;
  			
  			if (mparts[6].equals("0"))
  				posOK = false;
  			
  			float deg = Float.parseFloat(mparts[2].substring(0, 2));
  			float min = Float.parseFloat(mparts[2].substring(2));
  			lat = deg + min / 60.0f;
  			if (mparts[3].equals("S"))
  				lat = -lat;
  			
  			deg = Float.parseFloat(mparts[4].substring(0, 3));
  			min = Float.parseFloat(mparts[4].substring(3));
  			lon = deg + min / 60.0f;
  			if (mparts[5].equals("W"))
  				lon = -lon;
  			currPosition = new GpsFix(posOK, lat, lon);
  			//System.out.println(currPosition);
  			for (GpsPositionListener listener : listeners)
  				listener.positionUpdated(currPosition);
  		}
  	}
  	
  	
  	/////////////////////////////////////////////////////////////////
  	// Simple test program...
  	
  	public static void main(String[] args) {
  		try {
  			GpsLocator locator = new GpsLocator();
  			locator.addGpsPositionListener(System.out::println);
  			//locator.openFileConnection(new File("nmeaout.txt"));
  			locator.openSerialPortConnection();
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  	}
  }
  
  