--- /dev/null
+package tim.prune.load;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import tim.prune.App;
+import tim.prune.data.Field;
+import tim.prune.data.SourceInfo;
+
+/**
+ * Class to handle the loading of Nmea files
+ */
+public class NmeaFileLoader
+{
+ /** App for callback of file loading */
+ private App _app = null;
+
+ /**
+ * Constructor
+ * @param inApp App object
+ */
+ public NmeaFileLoader(App inApp)
+ {
+ _app = inApp;
+ }
+
+ /**
+ * Open the selected file
+ * @param inFile File to open
+ */
+ public void openFile(File inFile)
+ {
+ BufferedReader reader = null;
+ ArrayList<NmeaMessage> messages = new ArrayList<NmeaMessage>();
+ String lastDate = null;
+ try
+ {
+ reader = new BufferedReader(new FileReader(inFile));
+ String currLine = reader.readLine();
+ boolean newSegment = true;
+ while (currLine != null)
+ {
+ // Try to make an NmeaMessage object for each line of file
+ if (currLine.trim().length() > 0)
+ {
+ NmeaMessage message = processGGA(currLine);
+ if (message != null)
+ {
+ if (message.hasFix())
+ {
+ message.setSegment(newSegment);
+ message.setDate(lastDate);
+ // add message to list
+ messages.add(message);
+ }
+ // Start a new segment if fix lost
+ newSegment = !message.hasFix();
+ }
+ else {
+ String date = getDateFromRMC(currLine);
+ if (date != null)
+ {
+ if (lastDate == null && !messages.isEmpty()) {
+ // Backfill first few messages received before the first date
+ for (int m=0; m<messages.size(); m++) {
+ messages.get(m).setDate(date);
+ }
+ }
+ lastDate = date;
+ }
+ }
+ }
+ // Read next line, if any
+ currLine = reader.readLine();
+ }
+ }
+ catch (IOException ioe) {
+ _app.showErrorMessage("error.load.dialogtitle", "error.load.noread");
+ }
+ finally
+ {
+ // close file ignoring errors
+ try {
+ if (reader != null) reader.close();
+ }
+ catch (Exception e) {}
+ }
+ if (messages.size() > 0)
+ {
+ _app.informDataLoaded(getFieldArray(), makeDataArray(messages),
+ null, new SourceInfo(inFile, SourceInfo.FILE_TYPE.NMEA), null);
+ }
+ }
+
+ /**
+ * Process the given GGA sentence and return the message
+ * @param inLine line to process
+ * @return message object
+ */
+ private static NmeaMessage processGGA(String inLine)
+ {
+ // Only consider lines which are long enough and begin with the GPS position sentence
+ if (inLine == null || inLine.length() < 20 || !inLine.startsWith("$GPGGA")) {
+ return null;
+ }
+ // Assume comma delimiter, split into array
+ String[] splitLine = inLine.split(",");
+ if (splitLine != null && splitLine.length >= 10)
+ {
+ return new NmeaMessage(splitLine[2] + splitLine[3], // latitude
+ splitLine[4] + splitLine[5], // longitude
+ splitLine[9], // altitude
+ splitLine[1], // timestamp
+ splitLine[6]); // fix
+ }
+ // Couldn't parse it, return null
+ return null;
+ }
+
+ /**
+ * Process the given MRC sentence and return the date
+ * @param inLine line to process
+ * @return date, if any
+ */
+ private static String getDateFromRMC(String inLine)
+ {
+ // Only consider lines which are long enough and begin with the RMC sentence
+ if (inLine == null || inLine.length() < 20 || !inLine.startsWith("$GPRMC")) {
+ return null;
+ }
+ // Assume comma delimiter, split into array
+ String[] splitLine = inLine.split(",");
+ if (splitLine != null && splitLine.length >= 10)
+ {
+ return splitLine[9]; // date in position 9
+ }
+ // Couldn't parse it, return null
+ return null;
+ }
+
+ /**
+ * Make an object array from the data list
+ * @param inList list of messages
+ * @return object array for loading
+ */
+ private static Object[][] makeDataArray(ArrayList<NmeaMessage> inList)
+ {
+ Object[][] result = new Object[inList.size()][];
+ for (int i=0; i<inList.size(); i++) {
+ result[i] = inList.get(i).getStrings();
+ }
+ return result;
+ }
+
+ /**
+ * @see tim.prune.load.xml.XmlHandler#getFieldArray()
+ */
+ public Field[] getFieldArray()
+ {
+ final Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.ALTITUDE,
+ Field.TIMESTAMP, Field.NEW_SEGMENT};
+ return fields;
+ }
+}