NmeaParserpublic class NmeaParser extends Object
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 double | convertFromHHMM(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.Location | getLocation()
return mLocation;
| public boolean | parseSentence(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 boolean | updateAltitude(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 boolean | updateBearing(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 boolean | updateDate(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 boolean | updateDoubleExtra(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 boolean | updateFloatExtra(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 boolean | updateIntExtra(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 boolean | updateLatLon(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 boolean | updateSpeed(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 boolean | updateTime(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 boolean | updateTime(java.lang.String time, java.lang.String date)
if (!updateDate(date)) {
return false;
}
return updateTime(time);
|
|