FileDocCategorySizeDatePackage
NmeaParser.javaAPI DocAndroid 1.5 API14113Wed May 06 22:42:00 BST 2009com.android.internal.location

NmeaParser

public class NmeaParser extends Object
{@hide}

Fields Summary
private static final String
TAG
private static final TimeZone
sUtcTimeZone
private static final float
KNOTS_TO_METERS_PER_SECOND
private final String
mName
private int
mYear
private int
mMonth
private int
mDay
private long
mTime
private long
mBaseTime
private double
mLatitude
private double
mLongitude
private boolean
mHasAltitude
private double
mAltitude
private boolean
mHasBearing
private float
mBearing
private boolean
mHasSpeed
private float
mSpeed
private boolean
mNewWaypoint
private android.location.Location
mLocation
private android.os.Bundle
mExtras
Constructors Summary
public NmeaParser(String name)


       
        mName = name;
    
Methods Summary
private doubleconvertFromHHMM(java.lang.String coord)

        double val = Double.parseDouble(coord);
        int degrees = ((int) Math.floor(val)) / 100;
        double minutes = val - (degrees * 100);
        double dcoord = degrees + minutes / 60.0;
        return dcoord;
    
public android.location.LocationgetLocation()

        return mLocation;
    
public booleanparseSentence(java.lang.String s)

        int len = s.length();
        if (len < 9) {
            return false;
        }
        if (s.charAt(len - 3) == '*") {
            // String checksum = s.substring(len - 4, len);
            s = s.substring(0, len - 3);
        }
        String[] tokens = s.split(",");
        String sentenceId = tokens[0].substring(3, 6);

        int idx = 1;
        try {
            if (sentenceId.equals("GGA")) {
                String time = tokens[idx++];
                String latitude = tokens[idx++];
                String latitudeHemi = tokens[idx++];
                String longitude = tokens[idx++];
                String longitudeHemi = tokens[idx++];
                String fixQuality = tokens[idx++];
                String numSatellites = tokens[idx++];
                String horizontalDilutionOfPrecision = tokens[idx++];
                String altitude = tokens[idx++];
                String altitudeUnits = tokens[idx++];
                String heightOfGeoid = tokens[idx++];
                String heightOfGeoidUnits = tokens[idx++];
                String timeSinceLastDgpsUpdate = tokens[idx++];

                updateTime(time);
                updateLatLon(latitude, latitudeHemi,
                        longitude, longitudeHemi);
                updateAltitude(altitude);
                // updateQuality(fixQuality);
                updateIntExtra("numSatellites", numSatellites);
                updateFloatExtra("hdop", horizontalDilutionOfPrecision);

                if (mNewWaypoint) {
                    mNewWaypoint = false;
                    return true;
                }
            } else if (sentenceId.equals("GSA")) {
                // DOP and active satellites
                String selectionMode = tokens[idx++]; // m=manual, a=auto 2d/3d
                String mode = tokens[idx++]; // 1=no fix, 2=2d, 3=3d
                for (int i = 0; i < 12; i++) {
                    String id = tokens[idx++];
                }
                String pdop = tokens[idx++];
                String hdop = tokens[idx++];
                String vdop = tokens[idx++];

                // TODO - publish satellite ids
                updateFloatExtra("pdop", pdop);
                updateFloatExtra("hdop", hdop);
                updateFloatExtra("vdop", vdop);
            } else if (sentenceId.equals("GSV")) {
                // Satellites in view
                String numMessages = tokens[idx++];
                String messageNum = tokens[idx++];
                String svsInView = tokens[idx++];
                for (int i = 0; i < 4; i++) {
                    if (idx + 2 < tokens.length) {
                        String prnNumber = tokens[idx++];
                        String elevation = tokens[idx++];
                        String azimuth = tokens[idx++];
                        if (idx < tokens.length) {
                            String snr = tokens[idx++];
                        }
                    }
                }
                // TODO - publish this info
            } else if (sentenceId.equals("RMC")) {
                // Recommended minimum navigation information
                String time = tokens[idx++];
                String fixStatus = tokens[idx++];
                String latitude = tokens[idx++];
                String latitudeHemi = tokens[idx++];
                String longitude = tokens[idx++];
                String longitudeHemi = tokens[idx++];
                String speed = tokens[idx++];
                String bearing = tokens[idx++];
                String utcDate = tokens[idx++];
                String magneticVariation = tokens[idx++];
                String magneticVariationDir = tokens[idx++];
                String mode = tokens[idx++];

                if (fixStatus.charAt(0) == 'A") {
                    updateTime(time, utcDate);
                    updateLatLon(latitude, latitudeHemi,
                        longitude, longitudeHemi);
                    updateBearing(bearing);
                    updateSpeed(speed);
                }

                if (mNewWaypoint) {
                    return true;
                }
            } else {
                Log.e(TAG, "Unknown sentence: " + s);
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            // do nothing - sentence will have no effect
            Log.e(TAG, "AIOOBE", e);

            for (int i = 0; i < tokens.length; i++) {
                Log.e(TAG, "Got token #" + i + " = " + tokens[i]);
            }
        }

        return false;
    
private booleanupdateAltitude(java.lang.String altitude)

        if (altitude.length() == 0) {
            return false;
        }
        double alt;
        try {
            alt = Double.parseDouble(altitude);
        } catch (NumberFormatException nfe) {
            Log.e(TAG, "Exception parsing altitude " + altitude + ": " + nfe,
                  nfe);
            return false;
        }

        mHasAltitude = true;
        mAltitude = alt;
        return true;
    
private booleanupdateBearing(java.lang.String bearing)

        float brg;
        try {
            brg = Float.parseFloat(bearing);
        } catch (NumberFormatException nfe) {
            Log.e(TAG, "Exception parsing bearing " + bearing + ": " + nfe,
                  nfe);
            return false;
        }

        mHasBearing = true;
        mBearing = brg;
        return true;
    
private booleanupdateDate(java.lang.String date)

        if (date.length() != 6) {
            return false;
        }
        int month, day, year;
        try {
            day = Integer.parseInt(date.substring(0, 2));
            month = Integer.parseInt(date.substring(2, 4));
            year = 2000 + Integer.parseInt(date.substring(4, 6));
        } catch (NumberFormatException nfe) {
            Log.e(TAG, "Error parsing date " + date);
            return false;
        }

        mYear = year;
        mMonth = month;
        mDay = day;
        return true;
    
private booleanupdateDoubleExtra(java.lang.String name, java.lang.String value)

        double val;
        try {
            val = Double.parseDouble(value);
        } catch (NumberFormatException nfe) {
            Log.e(TAG, "Exception parsing double " + name + ": " + value, nfe);
            return false;
        }
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putDouble(name, val);
        return true;
    
private booleanupdateFloatExtra(java.lang.String name, java.lang.String value)

        float val;
        try {
            val = Float.parseFloat(value);
        } catch (NumberFormatException nfe) {
            Log.e(TAG, "Exception parsing float " + name + ": " + value, nfe);
            return false;
        }
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putFloat(name, val);
        return true;
    
private booleanupdateIntExtra(java.lang.String name, java.lang.String value)

        int val;
        try {
            val = Integer.parseInt(value);
        } catch (NumberFormatException nfe) {
            Log.e(TAG, "Exception parsing int " + name + ": " + value, nfe);
            return false;
        }
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putInt(name, val);
        return true;
    
private booleanupdateLatLon(java.lang.String latitude, java.lang.String latitudeHemi, java.lang.String longitude, java.lang.String longitudeHemi)

        if (latitude.length() == 0 || longitude.length() == 0) {
            return false;
        }

        // Lat/long values are expressed as {D}DDMM.MMMM
        double lat, lon;
        try {
            lat = convertFromHHMM(latitude);
            if (latitudeHemi.charAt(0) == 'S") {
                lat = -lat;
            }
        } catch (NumberFormatException nfe1) {
            Log.e(TAG, "Exception parsing lat/long: " + nfe1, nfe1);
            return false;
        }

        try {
            lon = convertFromHHMM(longitude);
            if (longitudeHemi.charAt(0) == 'W") {
                lon = -lon;
            }
        } catch (NumberFormatException nfe2) {
            Log.e(TAG, "Exception parsing lat/long: " + nfe2, nfe2);
            return false;
        }

        // Only update if both were parsed cleanly
        mLatitude = lat;
        mLongitude = lon;
        return true;
    
private booleanupdateSpeed(java.lang.String speed)

        float spd;
        try {
            spd = Float.parseFloat(speed) * KNOTS_TO_METERS_PER_SECOND;
        } catch (NumberFormatException nfe) {
            Log.e(TAG, "Exception parsing speed " + speed + ": " + nfe, nfe);
            return false;
        }

        mHasSpeed = true;
        mSpeed = spd;
        return true;
    
private booleanupdateTime(java.lang.String time)

        if (time.length() < 6) {
            return false;
        }
        if (mYear == -1) {
            // Since we haven't seen a day/month/year yet,
            // we can't construct a meaningful time stamp.
            // Clean up any old data.
            mLatitude = 0.0;
            mLongitude = 0.0;
            mHasAltitude = false;
            mHasBearing = false;
            mHasSpeed = false;
            mExtras = null;
            return false;
        }

        int hour, minute;
        float second;
        try {
            hour = Integer.parseInt(time.substring(0, 2));
            minute = Integer.parseInt(time.substring(2, 4));
            second = Float.parseFloat(time.substring(4, time.length()));
        } catch (NumberFormatException nfe) {
            Log.e(TAG, "Error parsing timestamp " + time);
            return false;
        }

        int isecond = (int) second;
        int millis = (int) ((second - isecond) * 1000);
        Calendar c = new GregorianCalendar(sUtcTimeZone);
        c.set(mYear, mMonth, mDay, hour, minute, isecond);
        long newTime = c.getTimeInMillis() + millis;

        if (mTime == -1) {
            mTime = 0;
            mBaseTime = newTime;
        }
        newTime -= mBaseTime;

        // If the timestamp has advanced, copy the temporary data
        // into a new Location
        if (newTime != mTime) {
            mNewWaypoint = true;
            mLocation = new Location(mName);
            mLocation.setTime(mTime);
            mLocation.setLatitude(mLatitude);
            mLocation.setLongitude(mLongitude);
            if (mHasAltitude) {
                mLocation.setAltitude(mAltitude);
            }
            if (mHasBearing) {
                mLocation.setBearing(mBearing);
            }
            if (mHasSpeed) {
                mLocation.setSpeed(mSpeed);
            }
            mLocation.setExtras(mExtras);
            mExtras = null;

            mTime = newTime;
            mHasAltitude = false;
            mHasBearing = false;
            mHasSpeed = false;
        }
        return true;
    
private booleanupdateTime(java.lang.String time, java.lang.String date)

        if (!updateDate(date)) {
                return false;
        }
        return updateTime(time);