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

📄 nmeaparser.java

📁 j2me的1套UI框架,可以帮助开发者迅速的开发j2me应用程序.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package org.j4me.bluetoothgps;

import org.j4me.logging.*;

/**
 * Parses chunks of data from a GPS device.
 */
class NMEAParser {
    private static final String DOLLAR_SIGN_GPGSA = "$GPGSA";
    private static final String DOLLAR_SIGN_GPGGA = "$GPGGA";
    private static final String DOLLAR_SIGN_GPRMC = "$GPRMC";

    /**
     * Size of the string buffer. This should be a little more than the size of
     * the byte array plus 80 (the max size of an NMEA sentence).
     */
    public static final short OUTPUT_BUFFER_MAX_SIZE = 2048;

    /**
     * The maximum size of a sentence according to the NMEA standards is 82. We
     * will use 128 to be safe.
     */
    private static final short MAX_SENTENCE_SIZE = 128;

    /**
     * Sentence characters
     */
    private static final byte SENTENCE_START = '$';
    private static final byte CHECKSUM_START = '*';
    private static final byte SENTENCE_END = '\n';
    private static final byte DELIMITER = ',';

    /**
     * There was not enough to process
     */
    public static final short TYPE_NOTHING_TO_PROCESS = -1;

    /**
     * No type
     */
    public static final short TYPE_NONE = 0;

    /**
     * Type GPRMC.
     */
    public static final short TYPE_GPRMC = 1;

    /**
     * Type GPGGA.
     */
    public static final short TYPE_GPGGA = 2;

    /**
     * Type GPGSA.
     */
    public static final short TYPE_GPGSA = 4;

    /**
     * TYPE_GPRMC | TYPE_GPGGA | TYPE_GPGSA
     */
    public static final short ALL_TYPES_MASK = 7;

    /**
     * The current data read from the GPS device
     */
    private byte[] data = new byte[OUTPUT_BUFFER_MAX_SIZE];

    /**
     * The length of <code>data</code>
     */
    private int dataLength = 0;
    
    /**
     * The record being built
     */
    private GPSRecord record = null;

    /**
     * Holds a record to be processed
     */
    private GPSRecord recordBuffer = null;

    /**
     * Cosntructor. Initialize the output buffer and record
     *
     */
    public NMEAParser() {
        record = new GPSRecord();
    }

    /**
     * Append the output to the output buffer. The size of the output must
     * always be less than {@link #OUTPUT_BUFFER_MAX_SIZE}.
     *
     * @param output - the output in bytes
     * @param size - the size of the output
     */
    private void append(byte[] output, int size)
    {
    	// Allocate a new buffer if we got so much data that it will
    	// contain all our information and the buffer from before can
    	// be discarded to save the overhead of processing it.
        if ( dataLength + size >= data.length )
        {
        	flush();
        }
        
        // Append output to data left over from a past append().
        int start = 0;
        int length = size;
        
        if ( size > data.length )
        {
        	start = size - data.length;
        	length = size - start;
        }
        
        System.arraycopy( output, start, data, dataLength, length );
        dataLength += size;
    }

    /**
     * Flush the buffer.
     */
    public void flush()
    {
    	dataLength = 0;
    }

    /**
     * Append the output and parse it. The size of the output must always be
     * less than {@link #OUTPUT_BUFFER_MAX_SIZE}.
     *
     * @param output - the output to parse in bytes
     * @param size - the size of the output
     * @return a integer to indicate which sentences were parsed
     */
    public int parse(byte[] output, int size) {
        append(output, size);
        return doParse();
    }

    /**
     * Parse the data from the Bluetooth GPS device into NMEA sentences.
     *
     * @return a integer to indicate which sentences were parsed
     */
    private int doParse() {
        int parsedSentenceTypes = TYPE_NONE;

        // If there is hardly anything in the buffer, there won't be a
        // NMEA sentence, so don't bother processing it.
        if (dataLength < 40) {
            return TYPE_NONE;
        }

        // Set the current index to be the
        int currentIndex = dataLength - 1;

        // True if the current sentence is the last sentence in the buffer
        boolean isLastSentence = true;

        // Index of the start of the last sentence
        int lastSentenceStart = -1;

        // While there are characters left to process
        while (currentIndex > 0)
        {
            // Find the start of the last NMEA sentence.
            int sentenceStart = lastIndexOf( data, SENTENCE_START, currentIndex );

            // Did we find the start of a sentence?
            if (sentenceStart != -1)
            {
                // We found the start of a sentence, look for the end.
                int sentenceEnd = indexOf( data, SENTENCE_END, sentenceStart, dataLength );
            	
                // Did we find the sentence end?
                if (sentenceEnd != -1)
                {
                    // Look for the first delimitter to get the sentence type.
                	// (i.e. String.indexOf(DELIMITER, sentenceStart))
                    int sentenceTypeEnd = indexOf( data, DELIMITER, sentenceStart, sentenceEnd );

                    // If we found the type end and the sentence end is within
                    // this sentence, then process the sentence. By checking that the
                    // sentence end is less than the current index then we
                    // handle the the case that we have a buffer left of
                    // "$GPRMC,45667,V,4354.788"
                    // and the first chunch of the new chars does not end the
                    // same sentence
                    // but instead starts a new one.
                    if ((sentenceTypeEnd != -1) && (sentenceEnd <= currentIndex)) {
                        try {
                            String type = new String(data, sentenceStart, sentenceTypeEnd - sentenceStart);
                            
                            if ((type.equals(DOLLAR_SIGN_GPRMC)) &&
                                    ((parsedSentenceTypes & TYPE_GPRMC) == 0)) {
                                parsedSentenceTypes = parsedSentenceTypes |
                                    processSentence(data, sentenceStart, sentenceEnd, TYPE_GPRMC);
                            } else if ((type.equals(DOLLAR_SIGN_GPGGA)) &&
                                    ((parsedSentenceTypes & TYPE_GPGGA) == 0)) {
                                parsedSentenceTypes = parsedSentenceTypes |
                                	processSentence(data, sentenceStart, sentenceEnd, TYPE_GPGGA);
                            } else if ((type.equals(DOLLAR_SIGN_GPGSA)) &&
                                    ((parsedSentenceTypes & TYPE_GPGSA) == 0)) {
                                parsedSentenceTypes = parsedSentenceTypes |
                                	processSentence(data, sentenceStart, sentenceEnd, TYPE_GPGSA);
                            }
                        } catch (Throwable t) {
                            Log.warn("processSentence: dataLength=" + dataLength +
                            		 ", Start=" + sentenceStart + 
                            		 ", End=" + sentenceEnd, t);

                            // We are kind of screwed at this point so just return
                            // what we have and flush the buffer.
                            flush();

                            return parsedSentenceTypes;
                        }

                        // move the current position
                        currentIndex = sentenceStart - 1;

                        // Check if we have a complete record. If so we do
                        // not need to keep working with this buffer
                        if (parsedSentenceTypes == ALL_TYPES_MASK) {
                            break;
                        }
                    } else {
                        // This sentence is bunk, so just skip it
                        currentIndex = sentenceStart - 1;
                    }
                } else {
                    // If this is the last sentence in the buffer, then keep the
                    // index of the start so that we do not delete it.
                    if (isLastSentence) {
                        lastSentenceStart = sentenceStart;
                    }

                    currentIndex = sentenceStart - 1;
                }
            } else {
                break;
            }

            // Once we have completed an iteration, set the last sentence flag
            // to false
            isLastSentence = false;
        } // while

        // Throw away everything that has already been parsed.
        if ( lastSentenceStart < 0 )
        {
        	// Processed everything.  No partial sentence left at the end.
        	flush();
        }
        else
        {
        	// Keep the partial last sentence.
        	dataLength -= lastSentenceStart;
            System.arraycopy( data, lastSentenceStart, data, 0, dataLength );
        }

        // If we parsed any of the sentences that we care about, put the record
        // in the buffer.
        if (parsedSentenceTypes != 0) {
            // Put the record in the record buffer
        	setRecordBuffer( record );

            // Create a new record from the existing record
            record = new GPSRecord(record);
        }

        return parsedSentenceTypes;
    }

    /**
     * Looks for the first occurance of a byte <code>b</code> in <code>array</code> between
     * [<code>fromIndex</code>, <code>stopIndex</code>).
     * 
     * @param array is the data to scan.
     * @param b is the byte to match.
     * @param fromIndex is the first index into array to check.
     * @param stopIndex is one past the last index into array to check.
     * @return The first index where <code>b</code> was found; -1 if it was not
     *  found. 
     */
    protected static int indexOf (byte[] array, byte b, int fromIndex, int stopIndex)
    {
        for ( int position = fromIndex; position < stopIndex; position++ )
        {
        	if ( array[position] == b )
        	{
        		return position;
        	}
        }
        
        // If we made it here, b was not found.
        return -1;
    }
    
    /**
     * Looks for the last occurance of a byte <code>b</code> in <code>array</code> going
     * backwards from <code>fromIndex</code>.

⌨️ 快捷键说明

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