nz.co.fortytwo.freeboard.server.GPXProcessor.java Source code

Java tutorial

Introduction

Here is the source code for nz.co.fortytwo.freeboard.server.GPXProcessor.java

Source

/*
 * Copyright 2012,2013 Robert Huitema robert@42.co.nz
 * 
 * This file is part of FreeBoard. (http://www.42.co.nz/freeboard)
 * 
 * FreeBoard is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * FreeBoard is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with FreeBoard. If not, see <http://www.gnu.org/licenses/>.
 */
package nz.co.fortytwo.freeboard.server;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;

import nz.co.fortytwo.freeboard.server.util.Constants;
import nz.co.fortytwo.freeboard.server.util.SGImplify;
import nz.co.fortytwo.freeboard.server.util.Util;

import org.alternativevision.gpx.GPXParser;
import org.alternativevision.gpx.beans.GPX;
import org.alternativevision.gpx.beans.Track;
import org.alternativevision.gpx.beans.TrackPoint;
import org.alternativevision.gpx.beans.Waypoint;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

/**
 * Churns through incoming nav data and creates a GPX file
 * Uses code from http://gpxparser.alternativevision.ro to do GPX parsing
 * Various strategies limit the amount of data collected
 * 
 * Writes to USB drive /tracks if one is found
 * Writes to freeboard/tracks if no drive is found
 * 
 * @author robert
 * 
 */
public class GPXProcessor extends FreeboardProcessor implements Processor, FreeboardHandler {

    private static final String CURRENT = "current";
    private static final double TOLERANCE = 0.000025; // About 3M out of line?
    private static Logger logger = Logger.getLogger(GPXProcessor.class);
    private File gpxFile;
    private File gpxDir;
    private GPX gpx;
    private Track currentTrack;
    private int count = 0;
    private int triggerCount = 60;

    public GPXProcessor() {

        try {
            String gpxDirStr = Util.getConfig(null).getProperty(Constants.TRACKS_RESOURCE);
            File usb = Util.getUSBFile();
            if (usb != null) {
                gpxDir = new File(usb, gpxDirStr);
                // write out every minute
                triggerCount = 60;
            } else {
                gpxDir = new File(gpxDirStr);
            }
            FileUtils.forceMkdir(gpxDir);
            gpxFile = new File(gpxDir, Util.getConfig(null).getProperty(Constants.TRACK_CURRENT));
            if (gpxFile.exists()) {
                try {
                    gpx = new GPXParser().parseGPX(gpxFile);
                } catch (Exception e) {
                    // may be unreadable
                    logger.error(e.getMessage(), e);
                }
            }
            if (gpx == null) {
                gpx = new GPX();
            }
            for (Track t : gpx.getTracks()) {
                if (CURRENT.equals(t.getName())) {
                    currentTrack = t;
                    break;
                }
            }
            if (currentTrack == null) {
                currentTrack = new Track();
                currentTrack.setName(CURRENT);
                gpx.addTrack(currentTrack);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

    }

    public void process(Exchange exchange) {
        if (exchange.getIn().getBody() == null)
            return;

        @SuppressWarnings("unchecked")
        HashMap<String, Object> map = exchange.getIn().getBody(HashMap.class);

        handle(map);

    }

    private void writeGPX(GPX gpx, File file) {
        try {
            new GPXParser().writeGPX(gpx, file);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

    }

    //@Override
    public HashMap<String, Object> handle(HashMap<String, Object> map) {
        // <trkpt lat="-41.19408333" lon="173.24741667"><ele>2376</ele><time>2007-10-14T10:09:57Z</time></trkpt>
        if (map.containsKey(Constants.LAT) && map.containsKey(Constants.LON)) {
            // check if they are worth saving
            double newLat = (Double) map.get(Constants.LAT);
            double newLon = (Double) map.get(Constants.LON);
            // write out to gpx track
            TrackPoint tp = new TrackPoint();
            tp.setElevation(0.0);
            tp.setTime(new Date());
            tp.setLatitude(newLat);
            tp.setLongitude(newLon);
            currentTrack.getTrackPoints().add(tp);

            // we count every occurrence, an easy way to count time!
            count++;
        }
        // write out every 60 points, eg 1 min at 1 sec GPS data, or 60sec to usb
        if (count > triggerCount) {
            count = 0;
            // simplify here
            currentTrack.setTrackPoints(SGImplify.simplifyLine2D(TOLERANCE, currentTrack.getTrackPoints()));
            // if its still too long, truncate and archive
            if (currentTrack.getTrackPoints().size() > 1100) {
                // write out the first 1000
                ArrayList<Waypoint> points = currentTrack.getTrackPoints();

                Waypoint[] oldPoints = Arrays.copyOfRange(points.toArray(new Waypoint[0]), 0, 1000);
                GPX oldGpx = new GPX();
                Track oldTrack = new Track();
                ArrayList<Waypoint> newPoints = new ArrayList<Waypoint>();
                newPoints.addAll(Arrays.asList(oldPoints));

                oldTrack.setTrackPoints(newPoints);
                oldGpx.addTrack(oldTrack);

                String fileName = Util.sdf.format(new Date());
                oldTrack.setName(CURRENT + " " + fileName);
                writeGPX(oldGpx, new File(gpxDir, fileName + ".gpx"));

                points.removeAll(newPoints);
                currentTrack.setTrackPoints(points);
            }

            writeGPX(gpx, gpxFile);

        }
        return map;
    }

}