📄 gpsdriver.java
字号:
/***********************************************************************
* 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 + -