Ticket #675: josm-nmea-support.patch

File josm-nmea-support.patch, 8.3 KB (added by egore@…, 17 years ago)

This adds support for parsing NMEA-0183 files

  • src/org/openstreetmap/josm/actions/OpenAction.java

     
    1717
    1818import org.openstreetmap.josm.Main;
    1919import org.openstreetmap.josm.data.osm.DataSet;
     20import org.openstreetmap.josm.gui.layer.GpxLayer;
    2021import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    21 import org.openstreetmap.josm.gui.layer.GpxLayer;
    2222import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
     23import org.openstreetmap.josm.io.GpxReader;
     24import org.openstreetmap.josm.io.NmeaReader;
    2325import org.openstreetmap.josm.io.OsmReader;
    24 import org.openstreetmap.josm.io.GpxReader;
    2526import org.xml.sax.SAXException;
    2627
    2728/**
     
    5556                try {
    5657                        if (asGpxData(file.getName()))
    5758                                openFileAsGpx(file);
     59                        else if (asNmeaData(file.getName()))
     60                                openFileAsNmea(file);
    5861                        else
    5962                                openAsData(file);
    6063                } catch (SAXException x) {
     
    102105                }
    103106    }
    104107
     108        private void openFileAsNmea(File file) throws IOException, FileNotFoundException {
     109                String fn = file.getName();
     110                if (ExtensionFileFilter.filters[ExtensionFileFilter.NMEA].acceptName(fn)) {
     111                        NmeaReader r = new NmeaReader(new FileInputStream(file), file.getAbsoluteFile().getParentFile());
     112                        r.data.storageFile = file;
     113                        GpxLayer gpxLayer = new GpxLayer(r.data, fn);
     114                        Main.main.addLayer(gpxLayer);
     115                        if (Main.pref.getBoolean("marker.makeautomarkers", true)) {
     116                                MarkerLayer ml = new MarkerLayer(r.data, tr("Markers from {0}", fn), file, gpxLayer);
     117                                if (ml.data.size() > 0) {
     118                                        Main.main.addLayer(ml);
     119                                }
     120                        }
    105121
     122                } else {
     123                        throw new IllegalStateException();
     124                }
     125    }
     126
    106127        private boolean asGpxData(String fn) {
    107128                return ExtensionFileFilter.filters[ExtensionFileFilter.GPX].acceptName(fn);
    108129        }
    109130
     131        private boolean asNmeaData(String fn) {
     132                return ExtensionFileFilter.filters[ExtensionFileFilter.NMEA].acceptName(fn);
     133        }
    110134
     135
    111136}
  • src/org/openstreetmap/josm/actions/ExtensionFileFilter.java

     
    2020
    2121        public static final int OSM = 0;
    2222        public static final int GPX = 1;
     23        public static final int NMEA = 2;
    2324       
    2425        public static ExtensionFileFilter[] filters = {
    2526                new ExtensionFileFilter("osm,xml", "osm", tr("OSM Server Files (.osm .xml)")),
    2627                new ExtensionFileFilter("gpx,gpx.gz", "gpx", tr("GPX Files (.gpx .gpx.gz)")),
     28                new ExtensionFileFilter("nmea", "nmea", tr("NMEA-0183 Files (.nmea)")),
    2729        };
    2830
    2931        /**
  • src/org/openstreetmap/josm/io/NmeaReader.java

     
     1//License: GPL. Copyright 2008 by Christoph Brill
     2
     3package org.openstreetmap.josm.io;
     4
     5import java.io.BufferedReader;
     6import java.io.File;
     7import java.io.IOException;
     8import java.io.InputStream;
     9import java.io.InputStreamReader;
     10import java.text.ParseException;
     11import java.text.SimpleDateFormat;
     12import java.util.ArrayList;
     13import java.util.Calendar;
     14import java.util.Collection;
     15import java.util.Date;
     16
     17import org.openstreetmap.josm.data.coor.LatLon;
     18import org.openstreetmap.josm.data.gpx.GpxData;
     19import org.openstreetmap.josm.data.gpx.GpxTrack;
     20import org.openstreetmap.josm.data.gpx.WayPoint;
     21
     22/**
     23 * Read a nmea file. Based on information from
     24 * http://www.kowoma.de/gps/zusatzerklaerungen/NMEA.htm
     25 *
     26 * @author cbrill
     27 */
     28public class NmeaReader {
     29
     30        /** Handler for the different types that NMEA speaks. */
     31        public static enum NMEA_TYPE {
     32
     33                /** RMC = recommended minimum sentence C. */
     34                GPRMC("$GPRMC"),
     35                /** GPS positions. */
     36                GPGGA("$GPGGA"),
     37                /** SA = satellites active. */
     38                GPGSA("$GPGSA");
     39
     40                private final String type;
     41
     42                NMEA_TYPE(String type) {
     43                        this.type = type;
     44                }
     45
     46                public String getType() {
     47                return this.type;
     48        }
     49
     50                public boolean equals(String type) {
     51                        return this.type.equals(type);
     52                }
     53        }
     54
     55        private static final int TYPE = 0;
     56       
     57        // The following only applies to GPRMC
     58        public static enum GPRMC {
     59                TIME(1),
     60                /** Warning from the receiver (A = data ok, V = warning) */
     61                RECEIVER_WARNING(2),
     62                WIDTH_NORTH(3),
     63                WIDTH_NORTH_NAME(4),
     64                LENGTH_EAST(5),
     65                LENGTH_EAST_NAME(6),
     66                /** Speed in knots */
     67                SPEED(7),
     68                COURSE(8),
     69                DATE(9),
     70                /** magnetic declination */
     71                MAGNETIC_DECLINATION(10),
     72                UNKNOWN(11),
     73                /** Mode (A = autonom; D = differential; E = estimated; N = not valid; S = simulated)
     74                 * @since NMEA 2.3 */
     75                MODE(12);
     76
     77                public final int position;
     78
     79                GPRMC(int position) {
     80                        this.position = position;
     81                }
     82        }
     83
     84        // The following only applies to GPGGA
     85        public static enum GPGGA {
     86                TIME(1),
     87                LATITUDE(2),
     88                LATITUDE_NAME(3),
     89                LONGITUDE(4),
     90                LONGITUDE_NAME(5),
     91                /** Quality (0 = invalid, 1 = GPS, 2 = DGPS, 6 = estimanted (@since NMEA 2.3)) */
     92                QUALITY(6),
     93                SATELLITE_COUNT(7),
     94                /** HDOP (horizontal dilution of precision) */
     95                HDOP(8),
     96                /** height above NN (above geoid) */
     97                HEIGHT(9),
     98                HEIGHT_UNTIS(10),
     99                /** height geoid - height ellipsoid (WGS84) */
     100                HEIGHT_2(11),
     101                HEIGHT_2_UNTIS(12);
     102
     103                public final int position;
     104
     105                GPGGA(int position) {
     106                        this.position = position;
     107                }
     108        }
     109
     110        // The following only applies to GPGGA
     111        public static enum GPGSA {
     112                AUTOMATIC(1),
     113                /** 1 = not fixed, 2 = 2D fixed, 3 = 3D fixed) */
     114                FIX_TYPE(2),
     115                // PRN numbers for max 12 satellites
     116                PRN_1(3),
     117                PRN_2(4),
     118                PRN_3(5),
     119                PRN_4(6),
     120                PRN_5(7),
     121                PRN_6(8),
     122                PRN_7(9),
     123                PRN_8(10),
     124                PRN_9(11),
     125                PRN_10(12),
     126                PRN_11(13),
     127                PRN_12(14),
     128                /** PDOP (precision) */
     129                PDOP(15),
     130                /** HDOP (horizontal precision) */
     131                HDOP(16),
     132                /** VDOP (vertical precision) */
     133                VDOP(17),
     134                ;
     135               
     136                public final int position;
     137
     138                GPGSA(int position) {
     139                        this.position = position;
     140                }
     141        }
     142
     143        public GpxData data;
     144
     145        public NmeaReader(InputStream source, File relativeMarkerPath) {
     146                data = new GpxData();
     147                GpxTrack currentTrack = new GpxTrack();
     148                Collection<WayPoint> currentTrackSeg = new ArrayList<WayPoint>();
     149                currentTrack.trackSegs.add(currentTrackSeg);
     150                data.tracks.add(currentTrack);
     151
     152                BufferedReader rd;
     153                String nmeaWithChecksum;
     154
     155                Calendar lastKnownDate = null;
     156                try {
     157                        rd = new BufferedReader(new InputStreamReader(source));
     158                        while ((nmeaWithChecksum = rd.readLine()) != null) {
     159                                String[] nmeaAndChecksum = nmeaWithChecksum.split("\\*");
     160                                String nmea = nmeaAndChecksum[0];
     161                                String checksum = nmeaAndChecksum[1];
     162                                String[] e = nmea.split(",");
     163                                if (NMEA_TYPE.GPGGA.equals(e[TYPE])) {
     164                                        WayPoint currentWayPoint = new WayPoint(parseLatLon(e));
     165
     166                                        if (lastKnownDate != null) {
     167                                                try {
     168                                                        Date time;
     169                                                        if (e[GPGGA.TIME.position].contains(".")) {
     170                                                                time = new SimpleDateFormat("HHmmss.SSS").parse(e[GPGGA.TIME.position]);
     171                                                        } else {
     172                                                                time = new SimpleDateFormat("HHmmss").parse(e[GPGGA.TIME.position]);
     173                                                        }
     174                                                        Calendar cal = Calendar.getInstance();
     175                                                        cal.setTime(time);
     176                                                        cal.set(lastKnownDate.get(Calendar.YEAR), lastKnownDate.get(Calendar.MONTH), lastKnownDate.get(Calendar.DAY_OF_MONTH));
     177                                                        currentWayPoint.time = cal.getTimeInMillis() / 1000.0;
     178                        } catch (ParseException e1) {
     179                                e1.printStackTrace();
     180                        }
     181                                        }
     182                                        currentTrackSeg.add(currentWayPoint);
     183                                } else if (NMEA_TYPE.GPRMC.equals(e[TYPE])) {
     184                                        try {
     185                            Date date = new SimpleDateFormat("ddMMyy").parse(e[GPRMC.DATE.position]);
     186                            lastKnownDate = Calendar.getInstance();
     187                            lastKnownDate.setTime(date);
     188                    } catch (ParseException e1) {
     189                        // Don't care
     190                    }
     191                                }
     192                        }
     193                        rd.close();
     194                } catch (final IOException e) {
     195                        System.out.println("Error reading file");
     196                }
     197
     198        }
     199
     200        private LatLon parseLatLon(String[] e) {
     201            return new LatLon(Double.parseDouble(e[GPGGA.LATITUDE.position]), Double.parseDouble(e[GPGGA.LONGITUDE.position]));
     202    }
     203}