Changeset 1167 in josm


Ignore:
Timestamp:
Dec 23, 2008 2:32:30 PM (4 years ago)
Author:
stoecker
Message:

added better NMEA reader. Closes bug #1448

Location:
trunk/src/org/openstreetmap/josm
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java

    r1146 r1167  
    119119                } 
    120120    } 
     121         
     122        private void showNmeaInfobox(boolean success, NmeaReader r) { 
     123                String msg = tr("Coordinates imported: ") + r.getNumberOfCoordinates() + "\n" + 
     124                tr("Malformed sentences: ") + r.getParserMalformed() + "\n" + 
     125                tr("Checksum errors: ") + r.getParserChecksumErrors() + "\n"; 
     126                if(!success) // don't scare the user unneccessarily 
     127                        msg += tr("Unknown sentences: ") + r.getParserUnknown() + "\n"; 
     128                msg += tr("Zero coordinates: ") + r.getParserZeroCoordinates(); 
     129                if(success) {    
     130                        JOptionPane.showMessageDialog( 
     131                                Main.parent, msg, 
     132                                tr("NMEA import success"),JOptionPane.INFORMATION_MESSAGE); 
     133                } else { 
     134                        JOptionPane.showMessageDialog( 
     135                                Main.parent, msg, 
     136                                tr("NMEA import faliure!"),JOptionPane.ERROR_MESSAGE); 
     137                } 
     138        } 
    121139 
    122140        private void openFileAsNmea(File file) throws IOException, FileNotFoundException { 
     
    124142                if (ExtensionFileFilter.filters[ExtensionFileFilter.NMEA].acceptName(fn)) { 
    125143                        NmeaReader r = new NmeaReader(new FileInputStream(file), file.getAbsoluteFile().getParentFile()); 
    126                         r.data.storageFile = file; 
    127                         GpxLayer gpxLayer = new GpxLayer(r.data, fn); 
    128                         Main.main.addLayer(gpxLayer); 
    129                         if (Main.pref.getBoolean("marker.makeautomarkers", true)) { 
    130                                 MarkerLayer ml = new MarkerLayer(r.data, tr("Markers from {0}", fn), file, gpxLayer); 
    131                                 if (ml.data.size() > 0) { 
    132                                         Main.main.addLayer(ml); 
     144                        if(r.getNumberOfCoordinates()>0) { 
     145                                r.data.storageFile = file; 
     146                                GpxLayer gpxLayer = new GpxLayer(r.data, fn); 
     147                                Main.main.addLayer(gpxLayer); 
     148                                if (Main.pref.getBoolean("marker.makeautomarkers", true)) { 
     149                                        MarkerLayer ml = new MarkerLayer(r.data, tr("Markers from {0}", fn), file, gpxLayer); 
     150                                        if (ml.data.size() > 0) { 
     151                                                Main.main.addLayer(ml); 
     152                                        } 
    133153                                } 
    134154                        } 
    135  
     155                        showNmeaInfobox(r.getNumberOfCoordinates()>0, r); 
    136156                } else { 
    137157                        throw new IllegalStateException(); 
  • trunk/src/org/openstreetmap/josm/data/gpx/WayPoint.java

    r813 r1167  
    3535         * Convert the time stamp of the waypoint into seconds from the epoch 
    3636         */ 
     37        public final static SimpleDateFormat GPXTIMEFMT =  
     38                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); // ignore timezone 
     39         
    3740        public void setTime() { 
    3841                if (! attr.containsKey("time")) { 
    3942                        return; 
    4043                } 
    41                 SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); // ignore timezone 
    42                 Date d = f.parse(attr.get("time").toString(), new ParsePosition(0)); 
     44                Date d = GPXTIMEFMT.parse(attr.get("time").toString(), new ParsePosition(0)); 
    4345                if (d != null /* parsing ok */) { 
    4446                        time = d.getTime() / 1000.0; /* ms => seconds */ 
  • trunk/src/org/openstreetmap/josm/io/NmeaReader.java

    r1056 r1167  
    88import java.io.InputStream; 
    99import java.io.InputStreamReader; 
     10import java.text.ParsePosition; 
     11import java.text.SimpleDateFormat; 
    1012import java.util.ArrayList; 
    1113import java.util.Arrays; 
    1214import java.util.Collection; 
     15import java.util.Date; 
    1316 
    1417import org.openstreetmap.josm.data.coor.LatLon; 
     
    2023 * Read a nmea file. Based on information from 
    2124 * http://www.kowoma.de/gps/zusatzerklaerungen/NMEA.htm 
    22  *  
     25 * 
    2326 * @author cbrill 
    2427 */ 
     
    3336                GPGGA("$GPGGA"), 
    3437                /** SA = satellites active. */ 
    35                 GPGSA("$GPGSA"); 
     38                GPGSA("$GPGSA"), 
     39                /** Course over ground and ground speed */ 
     40                GPVTG("$GPVTG"); 
    3641 
    3742                private final String type; 
     
    5055        } 
    5156 
    52         private static final int TYPE = 0; 
     57        // GPVTG 
     58        public static enum GPVTG { 
     59                COURSE(1),COURSE_REF(2), // true course 
     60                COURSE_M(3), COURSE_M_REF(4), // magnetic course 
     61                SPEED_KN(5), SPEED_KN_UNIT(6), // speed in knots 
     62                SPEED_KMH(7), SPEED_KMH_UNIT(8), // speed in km/h 
     63                REST(9); // version-specific rest 
     64 
     65                public final int position; 
     66 
     67                GPVTG(int position) { 
     68                        this.position = position; 
     69                } 
     70        } 
    5371 
    5472        // The following only applies to GPRMC 
     
    5674                TIME(1), 
    5775                /** Warning from the receiver (A = data ok, V = warning) */ 
    58                 RECEIVER_WARNING(2),  
    59                 WIDTH_NORTH(3), WIDTH_NORTH_NAME(4),  
    60                 LENGTH_EAST(5), LENGTH_EAST_NAME(6), 
    61                 /** Speed in knots */ 
    62                 SPEED(7), COURSE(8), DATE(9), 
    63                 /** magnetic declination */ 
    64                 MAGNETIC_DECLINATION(10), UNKNOWN(11), 
     76                RECEIVER_WARNING(2), 
     77                WIDTH_NORTH(3), WIDTH_NORTH_NAME(4), // Latitude, NS 
     78                LENGTH_EAST(5), LENGTH_EAST_NAME(6), // Longitude, EW 
     79                SPEED(7), COURSE(8), DATE(9),           // Speed in knots 
     80                MAGNETIC_DECLINATION(10), UNKNOWN(11),  // magnetic declination 
    6581                /** 
    6682                 * Mode (A = autonom; D = differential; E = estimated; N = not valid; S 
    6783                 * = simulated) 
    68                  *  
     84                 * 
    6985                 * @since NMEA 2.3 
    7086                 */ 
     
    86102                 */ 
    87103                QUALITY(6), SATELLITE_COUNT(7), 
    88                 /** HDOP (horizontal dilution of precision) */ 
    89                 HDOP(8), 
    90                 /** height above NN (above geoid) */ 
    91                 HEIGHT(9), HEIGHT_UNTIS(10), 
    92                 /** height geoid - height ellipsoid (WGS84) */ 
    93                 HEIGHT_2(11), HEIGHT_2_UNTIS(12); 
     104                HDOP(8), // HDOP (horizontal dilution of precision) 
     105                HEIGHT(9), HEIGHT_UNTIS(10), // height above NN (above geoid) 
     106                HEIGHT_2(11), HEIGHT_2_UNTIS(12), // height geoid - height ellipsoid (WGS84) 
     107                GPS_AGE(13),// Age of differential GPS data 
     108                REF(14); // REF station 
    94109 
    95110                public final int position; 
    96  
    97111                GPGGA(int position) { 
    98112                        this.position = position; 
     
    100114        } 
    101115 
    102         // The following only applies to GPGGA 
    103116        public static enum GPGSA { 
    104117                AUTOMATIC(1), 
    105                 /** 1 = not fixed, 2 = 2D fixed, 3 = 3D fixed) */ 
    106                 FIX_TYPE(2), 
     118                FIX_TYPE(2), // 1 = not fixed, 2 = 2D fixed, 3 = 3D fixed) 
    107119                // PRN numbers for max 12 satellites 
    108                 PRN_1(3), PRN_2(4), PRN_3(5), PRN_4(6), PRN_5(7), PRN_6(8), PRN_7(9), PRN_8( 
    109                         10), PRN_9(11), PRN_10(12), PRN_11(13), PRN_12(14), 
    110                 /** PDOP (precision) */ 
    111                 PDOP(15), 
    112                 /** HDOP (horizontal precision) */ 
    113                 HDOP(16), 
    114                 /** VDOP (vertical precision) */ 
    115                 VDOP(17), ; 
     120                PRN_1(3), PRN_2(4), PRN_3(5), PRN_4(6), PRN_5(7), PRN_6(8), 
     121                PRN_7(9), PRN_8(10), PRN_9(11), PRN_10(12), PRN_11(13), PRN_12(14), 
     122                PDOP(15),   // PDOP (precision) 
     123                HDOP(16),   // HDOP (horizontal precision) 
     124                VDOP(17), ; // VDOP (vertical precision) 
    116125 
    117126                public final int position; 
    118  
    119127                GPGSA(int position) { 
    120128                        this.position = position; 
     
    124132        public GpxData data; 
    125133 
     134//  private final static SimpleDateFormat GGATIMEFMT = 
     135//      new SimpleDateFormat("HHmmss.SSS"); 
     136        private final static SimpleDateFormat RMCTIMEFMT = 
     137                new SimpleDateFormat("ddMMyyHHmmss.SSS"); 
     138 
     139        // functons for reading the error stats 
     140        public NMEAParserState ps; 
     141 
     142        public int getParserUnknown() { 
     143                return ps.unknown; 
     144        } 
     145        public int getParserZeroCoordinates() { 
     146                return ps.zero_coord; 
     147        } 
     148        public int getParserChecksumErrors() { 
     149                return ps.checksum_errors; 
     150        } 
     151        public int getParserMalformed() { 
     152                return ps.malformed; 
     153        } 
     154        public int getNumberOfCoordinates() { 
     155                return ps.success; 
     156        } 
     157 
    126158        public NmeaReader(InputStream source, File relativeMarkerPath) { 
     159 
     160                // create the data tree 
    127161                data = new GpxData(); 
    128162                GpxTrack currentTrack = new GpxTrack(); 
    129                 Collection<WayPoint> currentTrackSeg = new ArrayList<WayPoint>(); 
    130                 currentTrack.trackSegs.add(currentTrackSeg); 
    131163                data.tracks.add(currentTrack); 
    132164 
    133                 BufferedReader rd; 
    134                 String nmeaWithChecksum; 
    135  
    136165                try { 
    137                         rd = new BufferedReader(new InputStreamReader(source)); 
    138                         while ((nmeaWithChecksum = rd.readLine()) != null) { 
    139                                 String[] nmeaAndChecksum = nmeaWithChecksum.split("\\*"); 
    140                                 String nmea = nmeaAndChecksum[0]; 
    141                                 // XXX: No need for it: String checksum = nmeaAndChecksum[1]; 
    142                                 String[] e = nmea.split(","); 
    143                                 if (e.length == 0) { 
    144                                     continue; 
    145                                 } 
    146                                 if (NMEA_TYPE.GPRMC.equals(e[TYPE])) { 
    147                                         LatLon latLon = parseLatLon(e); 
    148                                         if (latLon == null) { 
    149                                                 continue; 
     166                        BufferedReader rd = 
     167                                new BufferedReader(new InputStreamReader(source)); 
     168 
     169                        StringBuffer sb = new StringBuffer(1024); 
     170                        int loopstart_char = rd.read(); 
     171                        if(loopstart_char == -1) {// zero size file 
     172                                //TODO tell user about the problem? 
     173                                return; 
     174                        } 
     175                        sb.append((char)loopstart_char); 
     176                        ps = new NMEAParserState(); 
     177                        ps.p_Date="010100"; // TODO date problem 
     178                        while(true) { 
     179                                // don't load unparsable files completely to memory 
     180                                if(sb.length()>=1020) sb.delete(0, sb.length()-1); 
     181                                int c = rd.read(); 
     182                                if(c=='$') { 
     183                                        ParseNMEASentence(sb.toString(), ps); 
     184                                        sb.delete(0, sb.length()); 
     185                                        sb.append('$'); 
     186                                } else if(c == -1) { 
     187                                        // EOF: add last WayPoint if it works out 
     188                                        ParseNMEASentence(sb.toString(),ps); 
     189                                        break; 
     190                                } else sb.append((char)c); 
     191                        } 
     192                        rd.close(); 
     193                        Object[] wparr = ps.waypoints.toArray(); 
     194                        currentTrack.trackSegs.add(ps.waypoints); 
     195                        data.recalculateBounds(); 
     196 
     197                } catch (final IOException e) { 
     198                        // TODO tell user about the problem? 
     199                } 
     200        } 
     201        private class NMEAParserState { 
     202                protected Collection<WayPoint> waypoints = new ArrayList<WayPoint>(); 
     203                protected String p_Time; 
     204                protected String p_Date; 
     205                protected WayPoint p_Wp; 
     206 
     207                protected int success = 0; // number of successfully parsend sentences 
     208                protected int malformed = 0; 
     209                protected int checksum_errors = 0; 
     210                protected int unknown = 0; 
     211                protected int zero_coord = 0; 
     212        } 
     213 
     214        // Parses split up sentences into WayPoints which are stored 
     215        // in the collection in the NMEAParserState object. 
     216        // Returns true if the input made sence, false otherwise. 
     217        private boolean ParseNMEASentence(String s, NMEAParserState ps) { 
     218                try { 
     219                        if(s.equals("")) throw(null); 
     220 
     221                        // checksum check: 
     222                        // the bytes between the $ and the * are xored; 
     223                        // if there is no * or other meanities it will throw 
     224                        // and result in a malformed packet. 
     225                        String[] chkstrings = s.split("\\*"); 
     226                        byte[] chb = chkstrings[0].getBytes(); 
     227                        int chk=0; 
     228                        for(int i = 1; i < chb.length; i++) chk ^= chb[i]; 
     229                        if(Integer.parseInt(chkstrings[1].substring(0,2),16) != chk) { 
     230                                //System.out.println("Checksum error"); 
     231                                ps.checksum_errors++; 
     232                                ps.p_Wp=null; 
     233                                return false; 
     234                        } 
     235                        // now for the content 
     236                        String[] e = chkstrings[0].split(","); 
     237                        String accu; 
     238 
     239                        WayPoint currentwp = ps.p_Wp; 
     240                        String currentDate = ps.p_Date; 
     241 
     242                        // handle the packet content 
     243                        if(e[0].equals("$GPGGA")) { 
     244                                // Position 
     245                                LatLon latLon = parseLatLon( 
     246                                                e[GPGGA.LATITUDE_NAME.position], 
     247                                                e[GPGGA.LONGITUDE_NAME.position], 
     248                                                e[GPGGA.LATITUDE.position], 
     249                                                e[GPGGA.LONGITUDE.position] 
     250                                        ); 
     251                                if(latLon==null) throw(null); // malformed 
     252 
     253                                if((latLon.lat()==0.0) && (latLon.lon()==0.0)) { 
     254                                        ps.zero_coord++; 
     255                                        return false; 
     256                                } 
     257 
     258                                // time 
     259                                accu = e[GPGGA.TIME.position]; 
     260                                Date d = RMCTIMEFMT.parse(currentDate+accu, new ParsePosition(0)); 
     261                                if (d == null) throw(null); // malformed 
     262 
     263                                if((ps.p_Time==null) || (currentwp==null) || !ps.p_Time.equals(accu)) { 
     264                                        // this node is newer than the previous, create a new waypoint. 
     265                                        // no matter if previous WayPoint was null, we got something 
     266                                        // better now. 
     267                                        ps.p_Time=accu; 
     268                                        currentwp = new WayPoint(latLon); 
     269                                } 
     270                                if(!currentwp.attr.containsKey("time")) { 
     271                                        // As this sentence has no complete time only use it 
     272                                        // if there is no time so far 
     273                                        String gpxdate = WayPoint.GPXTIMEFMT.format(d); 
     274                                        currentwp.attr.put("time", gpxdate); 
     275                                } 
     276                                // elevation 
     277                                accu=e[GPGGA.HEIGHT_UNTIS.position]; 
     278                                if(accu.equals("M")) { 
     279                                                // Ignore heights that are not in meters for now 
     280                                                accu=e[GPGGA.HEIGHT.position]; 
     281                                                if(!accu.equals("")) { 
     282                                                Double.parseDouble(accu); 
     283                                                // if it throws it's malformed; this should only happen if the 
     284                                                // device sends nonstandard data. 
     285                                                if(!accu.equals("")) currentwp.attr.put("ele", accu); 
    150286                                        } 
    151                                         WayPoint currentWayPoint = new WayPoint(latLon); 
    152                                         currentTrackSeg.add(currentWayPoint); 
    153                                 } 
    154                         } 
    155                         rd.close(); 
    156                 } catch (final IOException e) { 
    157                         System.out.println("Error reading file"); 
    158                 } 
    159  
    160         } 
    161  
    162         private LatLon parseLatLon(String[] e) throws NumberFormatException { 
    163             // If the array looks bogus don't try to get valuable information from it 
    164             // But remember that the array is stripped of checksum and GPRMC is only 12 elements and split strips empty trailing elements   
    165             if (e.length < 10) { 
    166                 return null; 
    167             } 
    168         String widthNorth = e[GPRMC.WIDTH_NORTH.position].trim(); 
    169                 String lengthEast = e[GPRMC.LENGTH_EAST.position].trim(); 
    170                 if ("".equals(widthNorth) || "".equals(lengthEast)) { 
    171                         return null; 
    172                 } 
     287                                } 
     288                                // number of sattelites 
     289                                accu=e[GPGGA.SATELLITE_COUNT.position]; 
     290                                int sat = 0; 
     291                                if(!accu.equals("")) { 
     292                                        sat = Integer.parseInt(accu); 
     293                                        currentwp.attr.put("sat", accu); 
     294                                } 
     295                                // h-dilution 
     296                                accu=e[GPGGA.HDOP.position]; 
     297                                if(!accu.equals("")) { 
     298                                        Double.parseDouble(accu); 
     299                                        currentwp.attr.put("hdop", accu); 
     300                                } 
     301                                // fix 
     302                                accu=e[GPGGA.QUALITY.position]; 
     303                                if(!accu.equals("")) { 
     304                                        int fixtype = Integer.parseInt(accu); 
     305                                        switch(fixtype) { 
     306                                        case 0: 
     307                                                currentwp.attr.put("fix", "none"); 
     308                                                break; 
     309                                        case 1: 
     310                                                if(sat < 4) currentwp.attr.put("fix", "2d"); 
     311                                                else currentwp.attr.put("fix", "3d"); 
     312                                                break; 
     313                                        case 2: 
     314                                                currentwp.attr.put("fix", "dgps"); 
     315                                                break; 
     316                                        default: 
     317                                                break; 
     318                                        } 
     319                                } 
     320                        } else if(e[0].equals("$GPVTG")) { 
     321                                // COURSE 
     322                                accu = e[GPVTG.COURSE_REF.position]; 
     323                                if(accu.equals("T")) { 
     324                                        // other values than (T)rue are ignored 
     325                                        accu = e[GPVTG.COURSE.position]; 
     326                                        if(!accu.equals("")) { 
     327                                                Double.parseDouble(accu); 
     328                                                currentwp.attr.put("course", accu); 
     329                                        } 
     330                                } 
     331                                // SPEED 
     332                                accu = e[GPVTG.SPEED_KMH_UNIT.position]; 
     333                                if(accu.startsWith("K")) { 
     334                                        accu = e[GPVTG.SPEED_KMH.position]; 
     335                                        if(!accu.equals("")) { 
     336                                                double speed = Double.parseDouble(accu); 
     337                                                speed /= 3.6; // speed in m/s 
     338                                                currentwp.attr.put("speed", Double.toString(speed)); 
     339                                        } 
     340                                } 
     341                        } else if(e[0].equals("$GPGSA")) { 
     342                                // vdop 
     343                                accu=e[GPGSA.VDOP.position]; 
     344                                if(!accu.equals("")) { 
     345                                        Double.parseDouble(accu); 
     346                                        currentwp.attr.put("vdop", accu); 
     347                                } 
     348                                // hdop 
     349                                accu=e[GPGSA.HDOP.position]; 
     350                                if(!accu.equals("")) { 
     351                                        Double.parseDouble(accu); 
     352                                        currentwp.attr.put("hdop", accu); 
     353                                } 
     354                                // pdop 
     355                                accu=e[GPGSA.PDOP.position]; 
     356                                if(!accu.equals("")) { 
     357                                        Double.parseDouble(accu); 
     358                                        currentwp.attr.put("pdop", accu); 
     359                                } 
     360                        } 
     361                        else if(e[0].equals("$GPRMC")) { 
     362                                // coordinates 
     363                                LatLon latLon = parseLatLon( 
     364                                                e[GPRMC.WIDTH_NORTH_NAME.position], 
     365                                                e[GPRMC.LENGTH_EAST_NAME.position], 
     366                                                e[GPRMC.WIDTH_NORTH.position], 
     367                                                e[GPRMC.LENGTH_EAST.position] 
     368                                        ); 
     369                                if(latLon==null) throw(null); 
     370                                if((latLon.lat()==0.0) && (latLon.lon()==0.0)) { 
     371                                        ps.zero_coord++; 
     372                                        return false; 
     373                                } 
     374                                // time 
     375                                currentDate = e[GPRMC.DATE.position]; 
     376                                String time = e[GPRMC.TIME.position]; 
     377 
     378                                Date d = RMCTIMEFMT.parse(currentDate+time, new ParsePosition(0)); 
     379                                if (d == null) throw(null); 
     380 
     381                                if((ps.p_Time==null) || (currentwp==null) || !ps.p_Time.equals(time)) { 
     382                                        // this node is newer than the previous, create a new waypoint. 
     383                                        ps.p_Time=time; 
     384                                        currentwp = new WayPoint(latLon); 
     385                                } 
     386                                // time: this sentence has complete time so always use it. 
     387                                String gpxdate = WayPoint.GPXTIMEFMT.format(d); 
     388                                currentwp.attr.put("time", gpxdate); 
     389                                // speed 
     390                                accu = e[GPRMC.SPEED.position]; 
     391                                if(!accu.equals("") && !currentwp.attr.containsKey("speed")) { 
     392                                        double speed = Double.parseDouble(accu); 
     393                                        speed *= 0.514444444; // to m/s 
     394                                        currentwp.attr.put("speed", Double.toString(speed)); 
     395                                } 
     396                                // course 
     397                                accu = e[GPRMC.COURSE.position]; 
     398                                if(!accu.equals("") && !currentwp.attr.containsKey("course")) { 
     399                                        Double.parseDouble(accu); 
     400                                        currentwp.attr.put("course", accu); 
     401                                } 
     402 
     403                                // TODO fix? 
     404                                // * Mode (A = autonom; D = differential; E = estimated; N = not valid; S 
     405                                // * = simulated) 
     406                                // * 
     407                                // * @since NMEA 2.3 
     408                                // 
     409                                //MODE(12); 
     410                        } else { 
     411                                ps.unknown++; 
     412                                return false; 
     413                        } 
     414                        ps.p_Date = currentDate; 
     415                        if(ps.p_Wp != currentwp) { 
     416                                if(ps.p_Wp!=null) { 
     417                                        ps.p_Wp.setTime(); 
     418                                } 
     419                                ps.p_Wp = currentwp; 
     420                                ps.waypoints.add(currentwp); 
     421                                ps.success++; 
     422                                return true; 
     423                        } 
     424                        return true; 
     425 
     426                } catch(Exception x) { 
     427                        // out of bounds and such 
     428                        //System.out.println("Malformed line: "+s.toString().trim()); 
     429                        ps.malformed++; 
     430                        ps.p_Wp=null; 
     431                        return false; 
     432                } 
     433        } 
     434 
     435        private LatLon parseLatLon(String ew, String ns, String dlat, String dlon) 
     436                throws NumberFormatException { 
     437                String widthNorth = dlat.trim(); 
     438                String lengthEast = dlon.trim(); 
     439 
     440                // return a zero latlon instead of null so it is logged as zero coordinate 
     441                // instead of malformed sentence 
     442                if(widthNorth.equals("")&&lengthEast.equals("")) return new LatLon(0.0,0.0); 
    173443 
    174444                // The format is xxDDLL.LLLL 
     
    177447                // LL.LLLL (double) latidude 
    178448                int latdegsep = widthNorth.indexOf('.') - 2; 
    179                 if (latdegsep < 0) { 
    180                         return null; 
    181                 } 
     449                if (latdegsep < 0) return null; 
     450 
    182451                int latdeg = Integer.parseInt(widthNorth.substring(0, latdegsep)); 
    183452                double latmin = Double.parseDouble(widthNorth.substring(latdegsep)); 
    184453                double lat = latdeg + latmin / 60; 
    185                 if ("S".equals(e[GPRMC.WIDTH_NORTH_NAME.position])) { 
     454                if ("S".equals(ns)) { 
     455                        if(!ew.equals("N")) return null; 
    186456                        lat = -lat; 
    187                 }        
     457                } 
    188458 
    189459                int londegsep = lengthEast.indexOf('.') - 2; 
    190                 if (londegsep < 0) { 
    191                         return null; 
    192                 } 
     460                if (londegsep < 0) return null; 
     461 
    193462                int londeg = Integer.parseInt(lengthEast.substring(0, londegsep)); 
    194463                double lonmin = Double.parseDouble(lengthEast.substring(londegsep)); 
    195464                double lon = londeg + lonmin / 60; 
    196                 if ("W".equals(e[GPRMC.LENGTH_EAST_NAME.position])) { 
     465                if ("W".equals(ew)) { 
     466                        if(!ew.equals("E")) return null; 
    197467                        lon = -lon; 
    198468                } 
    199                  
    200469                return new LatLon(lat, lon); 
    201470        } 
Note: See TracChangeset for help on using the changeset viewer.