⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gpsdriver.java

📁 JavaGPS enables access to GPS devices from any Java application. Provides Java API, NMEA0183 parser,
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************
 *  J a v a G P S - GPS access library and Java API                    *
 *  Copyright (C) 2001 Ulrich Walther                                  *
 *                                                                     *
 *  This program is free software; you can redistribute it and/or      *
 *  modify it under the terms of the GNU General Public License as     *
 *  published by the Free Software Foundation; either version 2 of     *
 *  the License, or (at your option) any later version.                *
 *                                                                     *
 *  This program is distributed in the hope that it will be useful,    *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of     *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   *
 *  General Public License for more details.                           *
 *                                                                     *
 *  You should have received a copy of the GNU General Public          *
 *  License along with this program; if not, write to the Free         *
 *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,     *
 *  MA 02111-1307 USA                                                  *
 ***********************************************************************/

package org.iu.gps;

import java.io.*;
import java.util.*;
import javax.comm.*;
import java.lang.reflect.*;

// Read NMEA-0183 messages, perform checksum calculation + parse GPGGA (GPS position) msg.
// 10.11.1999 UW [Uli Walther]: created
// 16.11.1999 UW: cleanup, added NMEATokenizer and NMEA classes
// 05.2000 & 06.2000: parse all GPS messages + proprietary GARMIN messages
// 07.2000: add age of values in GPS info

/**
 *  This class realizes access to GPS devices over a serial line (NMEA0183
 *  message format). GPSDriver has the following features: - auto-detection of
 *  the GPS device's serial line - logging of GPS information into a file -
 *  playback of previously logged GPS information (application transparent;
 *  application thinks data comes from GPS)
 *
 *@author    walther
 */
public class GPSDriver implements Runnable, Serializable {
	final static int[] baudRates = {2400, 4800, 9600, 19200};
	String port;
	int baudRate;

	String buffer;

	InputStream inputStream = null;
	OutputStream outputStream = null;
	OutputStream logStream = null;
	OutputStream logRawStream = null;
	SerialPort serialPort = null;
	Thread gpsThread = null;
	Thread replayThread = null;
	Thread logThread = null;

	boolean logInput;
	boolean logRawInput;
	boolean replayMode;
	boolean readMode;
	boolean gpsMode;

	GPSLog gpsLog;
	GPSLog gpsReplayLog;
	GPSInfo gpsInfo;
	GPSInfo tmpInfo;
	boolean gpsInfoUpdated;
	int gpsParsedMessages;
	boolean simulate;
	boolean verbose;

	// GPS listeners
	Vector listeners = null;


	/**
	 *  Creates a new GPSDriver instance, open and listening on the given serial
	 *  port with the specified baudRate.
	 *
	 *@param  port           Symbolic name of serial port to listen on (/dev/ttySX
	 *      on UN*X, or COMx: on Win32)
	 *@param  baudRate       Baudrate to use in communication with the GPS device
	 *@exception  Exception  Exception
	 *@throws  Exception     Throws various exceptions if comm. cannot be
	 *      established, or if the port does not exist.
	 */
	public GPSDriver( String port, int baudRate ) throws Exception
	{
		this();

		System.out.println( "Using port " + port + " to receive GPS messages.\n\n" );

		setupGPS( port, baudRate );
	}


	/**
	 *  Creates a close GPSDriver instance.
	 */
	public GPSDriver()
	{
		listeners = new Vector();
	}


	/**
	 *  Returns the list of all known serial ports.
	 *
	 *@return    List of ports.
	 */
	public static String[] getPortList()
	{
		Vector v = new Vector();
		Enumeration portList = CommPortIdentifier.getPortIdentifiers();

		while ( portList.hasMoreElements() )
		{
			CommPortIdentifier portId = ( CommPortIdentifier ) portList.nextElement();
			//System.out.println(portId.getName());
			if ( portId.getPortType() == CommPortIdentifier.PORT_SERIAL )
			{
				v.add( portId.getName() );
			}
		}

		return ( String[] ) v.toArray( new String[v.size()] );
	}


	/**
	 *  Returns the list of all known baud rates.
	 *
	 *@return    List of Baud rates.
	 */
	public static int[] getBaudrateList()
	{
		return baudRates;
	}


	/**
	 *  The main program for the GPSDriver class
	 *
	 *@param  arg            The command line arguments
	 *@exception  Exception  Exception
	 */
	public static void main( String[] arg ) throws Exception
	{
        System.out.println("The following serial ports are available:");
        String[] ports = getPortList();
        for (int i=0; i<ports.length; i++)
            System.out.println( ports[i] );

        System.out.println("The following baud rates are available:");
        int[] bauds = getBaudrateList();
        for (int i=0; i<bauds.length; i++)
            System.out.println( bauds[i] );

        System.out.println("\n\nStarting autodetection of GPS device...\n");

		new GPSDriver().open( GPSDriver.detect() );
	}


	/**
	 *  Tries to find the serial line + baudRate to which a GPS is connected to.
	 *
	 *@return    GPS configuration, or null if no GPS was found.
	 */
	public static Configuration detect()
	{
		String[] ports = getPortList();

		GPSDriver gps = new GPSDriver();

		// loop through all possible ports & baudrates
		for ( int i = 0; i < ports.length; i++ )
		{
			for ( int k = 0; k < baudRates.length; k++ )
			{
				try
				{
					gps.close();
				}
				catch ( Exception e )
				{
					continue;
				}

				try
				{
					gps.setupGPS( ports[i], baudRates[k] );
				}
				catch ( Exception e )
				{
					continue;
				}

				long t1 = System.currentTimeMillis();

				while ( System.currentTimeMillis() - t1 < 5000 )
				{
					if ( gps.isAlive() )
					{
						// found GPS

						try
						{
							gps.close();
						}
						catch ( Exception e )
						{
						}

						Configuration cfg = new Configuration();
						cfg.port = ports[i];
						cfg.baudRate = baudRates[k];
						return cfg;
					}

					try
					{
						Thread.currentThread().sleep( 500 );
					}
					catch ( Exception e )
					{
					}

				}
			}
		}

		// unfortunately we couldn't detect any GPS...
		return null;
	}


	/**
	 *  Normalize GPS Information: convert from degrees/minutes to degrees only
	 *  representation, convert from the GPS ellipsoid, and fill in the
	 *  GaussKrueger coordinates
	 *
	 *@param  gi  GPSInfo to normalize.
	 */
	public static void normGPSInfo( GPSInfo gi )
	{
		try
		{
			// convert from deg/min to degrees
			gi.latitude = normLatLong( gi.latitude );
			gi.longitude = normLatLong( gi.longitude );

			// convert from ellipsoid GPS uses
//			XY c = new COORD(100).translate(false,gi.latitude,gi.longitude,28);
			XY c = COORD.translate( 28, 100, gi.latitude, gi.longitude );
			gi.latitude = c.x;
			gi.longitude = c.y;
			// convert coordinates to German Gauss-Krueger system
			XY gk = COORD.convertToGaussKrueger( gi.latitude, gi.longitude );
			gi.X = gk.x;
			gi.Y = gk.y;
			gi.XAge = gi.latitudeAge;
			gi.YAge = gi.longitudeAge;
		}
		catch ( Exception e )
		{
		}
	}


	/**
	 *  Method
	 *
	 *@param  c  Parameter
	 *@return    Returned Value
	 */
	public static double normLatLong( double c )
	{
		double deg = Math.floor( c * 1e-2 );
		double min = c - deg * 1e2;
		//System.out.println("deg="+deg+" min="+min+" c="+c);
		return deg + min / 60.0;
	}


	// Expects 6-letter UTC and returns # of seconds
	static long utcToSeconds( String utc )
	{
		return Integer.parseInt( utc.substring( 0, 2 ) ) * 3600 +
				Integer.parseInt( utc.substring( 2, 4 ) ) * 60 +
				Integer.parseInt( utc.substring( 4, 6 ) );
	}


	/**
	 *  Simulate a GPS device that returns the given GPSInfo. Note: Disables
	 *  hardware and replay modes.
	 *
	 *@param  gi  GPSInfo to use.
	 */

	public void setSimulationInfo( GPSInfo gi )
	{
		disableHardware();
		disableReplay();

		gpsInfo = gi;
		processListeners();
	}


	/**
	 *  Sets the current GPSInfo to the given position. The rest of the GPSInfo
	 *  fields are set to default values. Note: This is a convenience method for
	 *  setSimulationInfo(...)
	 *
	 *@param  lat  Latitude to use for simulation.
	 *@param  lon  Longitude to use for simulation.
	 */
	public void setSimulationPosition( double lat, double lon )
	{
		GPSInfo gi = new GPSInfo();
	}


	/**
	 *  Setup the GPS hardware.
	 *
	 *@param  port        Serial port.
	 *@param  baudRate    Baud rate of GPS device.
	 *@throws  Exception
	 */
	public void setupGPS( String port, int baudRate ) throws Exception
	{
		close();

		this.port = port;
		this.baudRate = baudRate;

		buffer = new String();
		try
		{
			//            serialPort = (SerialPort) portId.open("GPSDaemon", 2000);
			serialPort = ( SerialPort ) CommPortIdentifier.getPortIdentifier( port ).open( "GPSDriver", 60 );
		}
		catch ( PortInUseException e )
		{
		}

		try
		{
			inputStream = serialPort.getInputStream();
			//			inputStream = new FileInputStream( "_log.txt" );
			outputStream = serialPort.getOutputStream();
		}
		catch ( IOException e )
		{
		}
		/*
	  try
	  {
	  serialPort.addEventListener(this);
	  }
	  catch (TooManyListenersException e)
	  {
	  System.out.print("Error: unable to listen on serial line!");
	  //System.exit(-1);
	  }
	  serialPort.notifyOnDataAvailable(true);
	   */
		try
		{
			serialPort.setSerialPortParams( baudRate,
					SerialPort.DATABITS_8,
					SerialPort.STOPBITS_1,
					SerialPort.PARITY_NONE );
		}
		catch ( UnsupportedCommOperationException e )
		{
			System.out.println( "Warning: cannot program serial line parameters!" );
		}

		// configure GPS
		try
		{
			// GARMIN GPS25: enable all output messages
			//outputStream.write( new String("$PGRMO,,3"+((char)13)+((char)10)).getBytes() );
			outputStream.write( NMEA.addCheckSum( "$PGRMO,,3" ).getBytes() );

			// trigger GPS to send current configuration
			//outputStream.write( new String("$PGRMCE,"+((char)13)+((char)10)).getBytes() );
			outputStream.write( NMEA.addCheckSum( "$PGRMCE," ).getBytes() );
			// default configuration string is:
			// $PGRMC,A,218.8,100,6378137.000,298.257223563,0.0,0.0,0.0,A,3,1,1,4,30

			// GARMIN GPS25: set to German earth datum (parameter 3=27)
			outputStream.write( new String( "$PGRMC,A,,27,,,,,,A,3,1,1,4,30" + ( ( char ) 13 ) + ( ( char ) 10 ) ).getBytes() );
			//outputStream.write( NMEA.addCheckSum("$PGRMC,A,,100,,,,,,A,3,1,1,4,30").getBytes() );
		}
		catch ( IOException e )
		{
			System.out.println( "Warning: cannot configure GPS" );
		}

		gpsInfoUpdated = false;
		gpsParsedMessages = 0;

		enableHardware();

		//gpsThread = new Thread(this,"gpsThread");
		//gpsThread.start();
	}


	/**
	 *  Return the current GPS configuration.
	 *
	 *@return    Configuration
	 */
	public Configuration getConfiguration()
	{
		Configuration cfg = new Configuration();
		cfg.port = port;
		cfg.baudRate = baudRate;
		return cfg;
	}


	/**
	 *  Checks if the GPS is alive according to the following definition: There
	 *  have been more than 5 valid NMEA messages on the current serial line. This
	 *  method can be used to search for the serial port.
	 *
	 *@return    True if GPS is alive, false otherwise.
	 */
	public boolean isAlive()
	{
		if ( gpsMode )
		{
			return gpsParsedMessages > 5;
		}
		else if ( replayMode )
		{
			return true;
		}
		else
		{
			return false;
		}
	}


	/**
	 *  Obtain the current GPS information.
	 *
	 *@return    GPS information.
	 */
	public GPSInfo getGPSInfo()
	{
		return gpsInfo;
		/*
		try
		{
			GPSInfo gi = (GPSInfo)gpsInfo.clone();
			normGPSInfo( gi );
			return gi;
		}
		catch (Exception e)
		{
			return null;
		}
		*/
	}


	/**
	 *  Open the GPSDevice using the given configuration.
	 *
	 *@param  cfg         Configuration.
	 *@throws  Exception  If comm. to GPS cannot be established.
	 */
	public void open( Configuration cfg ) throws Exception
	{
		simulate = false;

		setupGPS( cfg.port, cfg.baudRate );
	}


	/**
	 *  Open GPSDevice using an input stream to replay logged GPS information.
	 *
	 *@param  logStream   Input stream with logged GPS information.
	 *@throws  Exception  If the stream is in error.
	 */
	public void open( InputStream logStream ) throws Exception
	{
		simulate = true;

		inputStream = logStream;

		gpsInfoUpdated = false;
		gpsParsedMessages = 0;

		gpsThread = new Thread( this, "gpsthread" );
		gpsThread.start();
	}


	/**
	 *  Enables replay from a previously logged stream. Automatically detects raw
	 *  and our internal log formats.
	 *
	 *@param  logStream   Stream with logged information.
	 *@throws  Exception  In case the stream cannnot be opened or the format cannot
	 *      be detected, an IllegalArgumentException is thrown.
	 */
	public void enableReplay( InputStream logStream ) throws Exception
	{
		disableHardware();
		gpsReplayLog = GPSLog.load( logStream );
		if ( gpsReplayLog == null )
		{
			throw new IllegalArgumentException( "logStream cannot be opened." );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -