stdgps.java

来自「A Java Framework for connecting to and e」· Java 代码 · 共 366 行

JAVA
366
字号
package com.libGPS4j2me.devices.StdGPS;

import com.libGPS4j2me.devices.StdGPS.DataRecord;
import com.libGPS4j2me.devices.StdGPS.exceptions.EmptyBufferException;
import com.libGPS4j2me.devices.StdGPS.exceptions.ParseException;
import com.libGPS4j2me.devices.StdGPS.exceptions.UnsupportedTypeException;
import com.libGPS4j2me.devices.StdGPS.log.Logger;
import com.libGPS4j2me.devices.StdGPS.parser.Parser;

import com.libGPS4j2me.GPS;

import java.io.IOException;
import java.util.Vector;
import java.io.InputStreamReader;

import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;

/**
 * Main class for communication with serial GPS receiver. Use this class to access StdGPS
 * receiver from other classes.
 *
 *
 * @author Loreto Parisi
 * @version 1.0
 */
public class StdGPS extends GPS implements Runnable {

    /** A human-readable description of the GPS-unit. */
	protected String description;

	protected boolean isPosition;
	protected boolean isTime;
	protected boolean isDate;

    /** A vector containing references to all the GarminListeners. */
	protected Vector StdGPSListeners;

   /**
	* Time in ms to wait until resume to receive.
	*/
	private static final long RECEIVE_BREAK = 2000;

   /**
	* Time in ms to wait until retry to read() the stream.
	*/
	private static final long READ_BREAK = 500;

	/**
	 * Character which indicates end of line in data send by serial device.
	 */
	private static final int LINE_DELIMITER = 13;

	/**
	 * Buffers parsed record.
	 */
	private DataRecordBuffer buffer;

	/**
	 * Connection to serial device.
	 */
	private StreamConnection connection;

	/**
	 * Input reader to read data send by serial device.
	 */
	private InputStreamReader reader;

	/**
	 * Receiving happens in separate thread.
	 */
	private Thread runner;

	/**
	 * URL used to connect to serial device.
	 */
	private String url;

	/**
	 * Creates new GPS serial receiver.
	 *
	 * @param url
	 *            URL of serial device to connect to.
	 */
	public StdGPS(String url) {

		this.url = url;
		this.buffer = new DataRecordBuffer();
		StdGPSListeners = new Vector();
		isPosition = false;
		isDate = false;
		isTime = false;
	}

	/**
	 * Establishes a serial connection (specified in url) and
	 * opens an input stream.
	 *
	 * @throws IOException
	 *             If error occurs while establishing bluetooth connection or
	 *             opening input stream
	 */
	private synchronized void connect() throws IOException {
		connection = (StreamConnection) Connector.open(url, Connector.READ);
		reader = new InputStreamReader(connection.openInputStream());
	}

	/**
	 * Closes input stream and bluetooth connection as well as sets the
	 * corresponding objects to null.
	 */
	private synchronized void disconnect() {
		try {
			if (reader != null)
				reader.close();
			if (connection != null)
				connection.close();
		} catch (IOException e) {
			// Ignore.
		}
		reader = null;
		connection = null;
	}

	/**
	 *
	 * @return The currently stored record.
	 * @throws EmptyBufferException
	 *             If no record has been stored yet.
	 */
	public DataRecord getRecord() throws EmptyBufferException {
		return buffer.getRecord();
	}

	/**
	 * @return True, if connected and input stream opened
	 */
	public synchronized boolean isConnected() {
		return connection != null && reader != null;
	}

	/**
	 * Reads in records sent by the StdGPS receiver. When a supported record has
	 * been received notifies to Listeners.
	 */
	public void run() {
		// Marker that indicates start of one cycle of records.
		int startType = Parser.TYPE_START;
		// Type of currently parsed record.
		int type = Parser.TYPE_NA;
		// Storage.
		DataRecord record = new DataRecord();

		while (Thread.currentThread() == runner) {
			try {

				// If not connected try to connect again.
				if (!isConnected())
                	connect();

                // Verify that the GPS stream is ready to be read
				if(!reader.ready()) {
					try {
						Thread.sleep(READ_BREAK);
					} catch(InterruptedException ie) {}
					continue;
				}

				String output = new String();
				int input;
				// Read one line and try to parse it. If successfull put parsed
				// record in buffer.
				while ((input = reader.read()) != LINE_DELIMITER)
					output += (char) input;


				//output = output.substring(1, output.length() - 1);
				try {
					log("Parsing NMEA:" + output);
					type = Parser.parse(output, record);
					buffer.putRecord(record);
				}
				// Is being thrown when a record is parsed that has an
				// unsupported type.
				catch (UnsupportedTypeException ue) {
					// Type is not supported.
					log("Type exception: " + ue.getMessage());
					type = Parser.TYPE_NA;
				}
				// Error while parsing (supported) record.
				catch (ParseException pe) {
					log("Parse exception: " + pe.getMessage());
					pe.printStackTrace();
				}

				// Examine only if valid type was parsed.
				if (type != Parser.TYPE_NA) {
					// notify DataRecord avaiable
					log("FireDataRecord.");
					fireDataRecord(record);
					firePositionData(new PositionDataRecord(record));
					fireTimeData(new TimeDataRecord(record));
					// Reset storage
					record = new DataRecord();

					if (type == startType) {
						disconnect();
						// Reset start marker.
						startType = Parser.TYPE_START;
						// Reset startType and storage.
						record = new DataRecord();
						try {
							Thread.sleep(RECEIVE_BREAK);
						} catch (InterruptedException e) {
							log("Exception: " + e.getMessage());
						}
					}
					// Set start marker.
					else if (startType == Parser.TYPE_START) {
						startType = type;
					}
				}
				try {
					//artificial wait
					Thread.sleep(RECEIVE_BREAK);
					} catch (InterruptedException e) {}
					// close GPS connection
					log("Disconnecting...");
					disconnect();
			}
			// Most severe type of exception. Either thrown while connecting or
			// while reading. Wait some time before continuing.
			catch (IOException ie) {
				try {
					Thread.sleep(RECEIVE_BREAK);
				} catch (InterruptedException e) {
					log("IO exception: " + e.getMessage());
				}
				ie.printStackTrace();
			}
		}
	}

   	/**
	 * Starts receving of data (if not yet started).
	 */
	public void start() {

		if (runner == null) {
        	runner = new Thread(this);
			runner.start();
		}
	}

	/**
     * Utility function for debug purposes.
     */
	private void log(String message) {

		System.out.println("StdGPS: " + message);
		System.out.flush();
	}

	/** Makes a request for accessing Position data to the GPS.
	 * Data will be returned to all listeners through the IGPSlistener-interface.
	 */
	public void requestPosition() {

		isPosition = true;
		if (runner == null) {
			runner = new Thread(this);
			runner.start();
		}
	}

	/** Makes a request for accessing Time data to the GPS.
	 * Data will be returned to all listeners through the IGPSlistener-interface.
	 */
	public void requestTime() {

		isTime = true;
		if (runner == null) {
			runner = new Thread(this);
			runner.start();
		}
	}

	/** Makes a request for accessing Date data to the GPS.
         * Data will be returned to all listeners through the IGPSlistener-interface.
         */
	public void requestDate() {

		isDate = true;
		if (runner == null) {
			runner = new Thread(this);
			runner.start();
		}
	}

	/** Stops communication with GPS.
	 *
	 */
	public void shutdown(boolean b) {

		runner = null;
		disconnect();
	}

    /**
	 * Requests a descriptive string from the GPS. Should be formatted for human-reading.
	 * The string should be constructed by every GPS-implementation upon startup.
     * Not implemented here. Not to use here.
     */
	public String getDescription() { return null; }

	/**
	 * Asks the GPS to transmit all the waypoints in it's memory. The result will be returned through the WaypointListener-interface.
	 * Throws a FeatureNotSupportException if it isn't possible to do this on the GPS.
     * Not implemented here. Not to use here.
	 */
	public void requestWaypoints() {}

	/**
	 * Asks the GPS to transmit all the waypoints in it's memory. The result will be returned through the WaypointListener-interface.
	 * Throws a FeatureNotSupportException if it isn't possible to do this on the GPS.
     * Not implemented here. Not to use.
	 */
	public void requestTracks() {}

	/**
	 * Asks the GPS to either start or stop transmitting data periodically. <br/>
	 * The data will be the that which is accessible through the IGPSlistener-interface.
	 * Throws a FeatureNotSupportException if it isn't possible to do this on the GPS.
     * Not implemented here. Not to use here.
	 */
	public  void setAutoTransmit(boolean t) {}

	/**
	 * Adds the specified StdGPSListener to receive all packets sent from the GPS.
	 */
	public void addStdGPSListener(StdGPSListener l) {
		// Only allow a listener to be registered once.
		if (StdGPSListeners.contains(l))
			return;
		StdGPSListeners.addElement(l);
		return;
	}

	/**
	 * Removes the specified StdGPSListener from the list of listeners.
	 */
	public void removeStdGPSListener(StdGPSListener l) {
		while (StdGPSListeners.removeElement(l)) {}
		return;
	}

	/**
	 * Goes through the list of StdGPSListeners and transmits r to them.
	 */
	protected void fireDataRecord(DataRecord r) {
		for (int i = 0 ; i < StdGPSListeners.size() ; i++) {
			((StdGPSListener) StdGPSListeners.elementAt(i)).DataRecordReceived(r);
		}
	}
}

⌨️ 快捷键说明

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