/*******************************************************************************
* Copyright (c) 2011, 2016 Eurotech and/or its affiliates
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eurotech
*******************************************************************************/
package org.eclipse.kura.linux.position;
/**
* Implements NMEA sentences parser functions.
*
*/
public class NMEAParser {
private int m_fixQuality;
private String m_timeNmea;
private String m_dateNmea;
private double m_longNmea;
private double m_latNmea;
private double m_speedNmea;
private double m_altNmea;
private double m_trackNmea;
private double m_DOPNmea;
private double m_PDOPNmea;
private double m_HDOPNmea;
private double m_VDOPNmea;
private int m_3DfixNmea;
private int m_nrSatellites;
private static boolean m_validPosition;
/**
* Fill the fields of GPS position depending of the type of the sentence
*
* @param sentence
* most recent sentence String from GPS modem
*/
public void parseSentence(String sentence) {
// first remove the end "*"+chksum
int starpos = sentence.indexOf('*');
String s_sentence = sentence.substring(0, starpos);
String[] tokens = s_sentence.split(",");
/*
* Starting from 4.0 NMEA specs the GPS device can send messages representing different talkers
*
* $GP = GPS
* $GS = Glonass
* $GN = GNSS, that is GPS + Glonass + possibly others
*/
if (!tokens[0].startsWith("$G")) {
// Not a valid token. Return.
return;
}
if (tokens[0].endsWith("GGA")) {
if (tokens.length > 9) {
m_validPosition = true;
if (!tokens[1].isEmpty()) {
this.m_timeNmea = tokens[1];
} else {
m_validPosition = false;
}
if (!tokens[2].isEmpty()) {
this.m_latNmea = convertPositionlat(tokens[2], tokens[3]);
} else {
m_validPosition = false;
}
if (!tokens[4].isEmpty()) {
this.m_longNmea = convertPositionlon(tokens[4], tokens[5]);
} else {
m_validPosition = false;
}
if (!tokens[6].isEmpty()) {
this.m_fixQuality = Integer.parseInt(tokens[6]);
if (this.m_fixQuality == 0) {
m_validPosition = false;
}
} else {
m_validPosition = false;
}
if (!tokens[7].isEmpty()) {
this.m_nrSatellites = Integer.parseInt(tokens[7]);
} else {
m_validPosition = false;
}
if (!tokens[8].isEmpty()) {
this.m_DOPNmea = Double.parseDouble(tokens[8]);
} else {
m_validPosition = false;
}
if (!tokens[9].isEmpty()) {
this.m_altNmea = Double.parseDouble(tokens[9]);
} else {
m_validPosition = false;
}
} else {
m_validPosition = false;
}
} else if (tokens[0].endsWith("GLL")) {
if (tokens.length > 5) {
m_validPosition = true;
if (!tokens[1].isEmpty()) {
this.m_latNmea = convertPositionlat(tokens[1], tokens[2]);
} else {
m_validPosition = false;
}
if (!tokens[3].isEmpty()) {
this.m_longNmea = convertPositionlon(tokens[3], tokens[4]);
} else {
m_validPosition = false;
}
if (!tokens[5].isEmpty()) {
this.m_timeNmea = tokens[5];
} else {
m_validPosition = false;
}
if (!tokens[6].isEmpty()) { // check validity
if (!new String("A").equals(tokens[6])) {
m_validPosition = false;
}
} else {
m_validPosition = false;
}
} else {
m_validPosition = false;
}
} else if (tokens[0].endsWith("RMC")) {
if (tokens.length > 8) {
m_validPosition = true;
if (!tokens[1].isEmpty()) {
this.m_timeNmea = tokens[1];
}
if (!tokens[2].isEmpty()) { // check validity
if (!new String("A").equals(tokens[2])) {
m_validPosition = false;
}
} else {
m_validPosition = false;
}
if (!tokens[3].isEmpty()) {
this.m_latNmea = convertPositionlat(tokens[3], tokens[4]);
} else {
m_validPosition = false;
}
if (!tokens[5].isEmpty()) {
this.m_longNmea = convertPositionlon(tokens[5], tokens[6]);
} else {
m_validPosition = false;
}
if (!tokens[7].isEmpty()) {
this.m_speedNmea = Double.parseDouble(tokens[7]) / 1.94384449; // conversion speed in knots to m/s :
// 1
}
// m/s = 1.94384449 knots
if (!tokens[8].isEmpty()) {
this.m_trackNmea = Double.parseDouble(tokens[8]);
}
if (!tokens[9].isEmpty()) {
this.m_dateNmea = tokens[9];
} else {
m_validPosition = false;
}
} else {
m_validPosition = false;
}
} else if (tokens[0].endsWith("GSA")) {
if (tokens.length > 5) {
m_validPosition = true;
if (!tokens[2].isEmpty()) {
this.m_3DfixNmea = Integer.parseInt(tokens[2]);
if (this.m_3DfixNmea == 1) {
m_validPosition = false;
}
} else {
m_validPosition = false;
}
int index = tokens.length - 3;
if (!tokens[index].isEmpty()) {
this.m_PDOPNmea = Double.parseDouble(tokens[index]);
} else {
m_validPosition = false;
}
if (!tokens[index + 1].isEmpty()) {
this.m_HDOPNmea = Double.parseDouble(tokens[index + 1]);
} else {
m_validPosition = false;
}
if (!tokens[index + 2].isEmpty()) {
this.m_VDOPNmea = Double.parseDouble(tokens[index + 2]);
} else {
m_validPosition = false;
}
} else {
m_validPosition = false;
}
} else if (tokens[0].endsWith("VTG")) {
if (tokens.length > 7 && !tokens[7].isEmpty()) {
this.m_speedNmea = Double.parseDouble(tokens[7]) * 0.277777778; // conversion km/h in m/s : 1 km/h ->
// 0,277777778 m/s;
}
}
}
double convertPositionlat(String pos, String direction) {
double floatLatDegrees = 0;
double floatLatMinutes = 0;
String s;
if (pos.length() < 6) {
return 0;
}
// This copies the arrays to temporary arrays
s = pos.substring(0, 2);
floatLatDegrees = Double.parseDouble(s);
s = pos.substring(2);
floatLatMinutes = Double.parseDouble(s);
floatLatDegrees = floatLatDegrees + floatLatMinutes / 60;
if (direction.contains("S")) {
floatLatDegrees = floatLatDegrees * -1;
}
return floatLatDegrees;
}
double convertPositionlon(String pos, String direction) {
double floatLonDegrees = 0;
double floatLonMinutes = 0;
String s;
if (pos.length() < 6) {
return 0;
}
// This copies the arrays to temporary arrays
s = pos.substring(0, 3);
floatLonDegrees = Double.parseDouble(s);
s = pos.substring(3);
floatLonMinutes = Double.parseDouble(s);
floatLonDegrees = floatLonDegrees + floatLonMinutes / 60;
if (direction.contains("W")) {
floatLonDegrees = floatLonDegrees * -1;
}
return floatLonDegrees;
}
public String get_timeNmea() {
return this.m_timeNmea;
}
public int get_fixQuality() {
return this.m_fixQuality;
}
public String get_dateNmea() {
return this.m_dateNmea;
}
public double get_longNmea() {
return this.m_longNmea;
}
public double get_latNmea() {
return this.m_latNmea;
}
public double get_speedNmea() {
return this.m_speedNmea;
}
public double get_altNmea() {
return this.m_altNmea;
}
public double get_trackNmea() {
return this.m_trackNmea;
}
public double get_DOPNmea() {
return this.m_DOPNmea;
}
public double get_PDOPNmea() {
return this.m_PDOPNmea;
}
public double get_HDOPNmea() {
return this.m_HDOPNmea;
}
public double get_VDOPNmea() {
return this.m_VDOPNmea;
}
public int get_3DfixNmea() {
return this.m_3DfixNmea;
}
public int get_nrSatellites() {
return this.m_nrSatellites;
}
public boolean is_validPosition() {
return m_validPosition;
}
}