utc = None # UTC date / time in format "mm/dd/yy hh:mm:ss" latitude = 0.0 # Latitude and longitude in format "d.ddddd" longitude = 0.0 precision = 99999 altitude = 0.0 # Altitude in meters altitude_units = 'M' speed = 0 # Speed over ground, knots satellites = 0 # Number of satellites used in solution status = 0 # 0 = no fix, 1 = fix, 2 = dgps fix mode = 0 # 1 = no fix, 2 = 2D, 3 = 3D in_view = 0 # # of satellites in view ss = [None] * 12 # signal strength datum = None def _checksumOk(sentence): """Calculates Checksum for an NMEA Sentenence and returns TRUE if sentence checks.""" # checksums are NOT mandantory on all sentences sum = 0 for c in sentence[1:]: if c == "*": break sum = sum ^ ord(c) return ("%02X" % sum) == sentence[sentence.find("*")+ 1 :] def _process_GGA(sentence): """parses an GGA 'Global Positioning System Fix Data' sentence""" # Documentation from GPSdrive 2.04: # # Gga - Global Positioning System Fix Data # Time, Position And Fix Related Data Fora Gps Receiver. # # 11 # 1 2 3 4 5 6 7 8 9 10 | 12 13 14 15 # | | | | | | | | | | | | | | | # $--Gga,Hhmmss.Ss,Llll.Ll,A,Yyyyy.Yy,A,X,Xx,X.X,X.X,M,X.X,M,X.X,Xxxx*Hh # # Field Number: # 1) Universal Time Coordinated (Utc) # 2) Latitude # 3) N Or S (North Or South) # 4) Longitude # 5) E Or W (East Or West) # 6) Gps Quality Indicator, # 0 - Fix Not Available, # 1 - Gps Fix, # 2 - Differential Gps Fix # 7) Number Of Satellites In View, 00 - 12 # 8) Horizontal Dilution Of Precision # 9) Antenna Altitude Above/Below Mean-Sea-Level (Geoid) # 10) Units Of Antenna Altitude, Meters # 11) Geoidal Separation, The Difference Between The Wgs-84 Earth # Ellipsoid And Mean-Sea-Level (Geoid), "-" Means Mean-Sea-Level # Below Ellipsoid # 12) Units Of Geoidal Separation, Meters # 13) Age Of Differential Gps Data, Time In Seconds Since Last Sc104 # Type 1 Or 9 Update, Null Field When Dgps Is Not Used # 14) Differential Reference Station Id, 0000-1023 # 15) Checksum # # Hu? I see only 14 fields. fields = sentence.split(",") return # time latitude = float(fields[2]) if fields[3]== "S": latitude = -latitude longitude = float(fields[4]) if fields[5] == "W": longitude = -longitude status = int(fields[6]) satellites = int(fields[7]) precision = float(fields[8]) altitude = float(fields[9]) altitude_units = fields[10] #elepsoid_sea = fload(field[11]) #elepsoid_sea_units = field[12] def _process_GSV(sentence): """ Parse GSV 'Sattelites in View' sentence""" # GSV - Satellites in view # # 1 2 3 4 5 6 7 n # | | | | | | | | # $--GSV,x,x,x,x,x,x,x,...*hh # # Field Number: # 1) total number of messages # 2) message number # 3) satellites in view # 4) satellite number # 5) elevation in degrees # 6) azimuth in degrees to true # 7) SNR in dB # more satellite infos like 4)-7) # n) checksum fields = sentence.split(",") def _process_GSA(sentence): """XXX""" # GSA - GPS DOP and active satellites # # 1 2 3 14 15 16 17 18 # | | | | | | | | # $--GSA,a,a,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x.x,x.x,x.x*hh # # Field Number: # 1) Selection mode # A Auto selection of 2D or 3D fix (M = manual) # 2) Mode # 3 3D fix # 3) ID of 1st satellite used for fix # 4) ID of 2nd satellite used for fix # ... # 14) ID of 12th satellite used for fix # 15) PDOP in meters (dilution of precision) # 16) HDOP in meters Horizontal dilution of precision (HDOP) # 17) VDOP in meter Vertical dilution of precision (VDOP)s # 18) checksum # # DOP is an indication of the effect of satellite geometry on # the accuracy of the fix. fields = sentence.split(",") def _proces_GLL(sentence): # GLL - Geographic position, Latitude and Longitude # GLL,4916.45,N,12311.12,W,225444,A # 4916.46,N Latitude 49 deg. 16.45 min. North # 12311.12,W Longitude 123 deg. 11.12 min. West # 225444 Fix taken at 22:54:44 UTC # A Data valid # (Garmin 65 does not include time) fields = sentence.split(",") if fields[6] == "A": latitude = float(fields[1]) if fields[2]== "S": latitude = -latitude longitude = float(fields[3]) if fields[4] == "W": longitude = -longitude fixtime = fields[5] def _process_RMC(sentence): # RMC - Recommended Minimum Navigation Information # 12 # 1 2 3 4 5 6 7 8 9 10 11| # | | | | | | | | | | | | # $--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a*hh # # Field Number: # 1) UTC Time # 2) Status, V = Navigation receiver warning # 3) Latitude # 4) N or S # 5) Longitude # 6) E or W # 7) Speed over ground, knots # 8) Track made good, degrees true # 9) Date, ddmmyy # 10) Magnetic Variation, degrees # 11) E or W # 12) Checksum fields = sentence.split(",") def _process_BOD(sentence): # BOD - Bearing - Waypoint to Waypoint # # 1 2 3 4 5 6 7 # | | | | | | | # $--BOD,x.x,T,x.x,M,c--c,c--c*hh # # Field Number: # 1) Bearing Degrees, TRUE # 2) T = True # 3) Bearing Degrees, Magnetic # 4) M = Magnetic # 5) TO Waypoint # 6) FROM Waypoint # 7) Checksum fields = sentence.split(",") def _process_RMB(sentence): # RMB - Recommended Minimum Navigation Information # 14 # 1 2 3 4 5 6 7 8 9 10 11 12 13| # | | | | | | | | | | | | | | # $--RMB,A,x.x,a,c--c,c--c,llll.ll,a,yyyyy.yy,a,x.x,x.x,x.x,A*hh # # Field Number: # 1) Status, V = Navigation receiver warning # 2) Cross Track error - nautical miles # 3) Direction to Steer, Left or Right # 4) TO Waypoint ID # 5) FROM Waypoint ID # 6) Destination Waypoint Latitude # 7) N or S # 8) Destination Waypoint Longitude # 9) E or W # 10) Range to destination in nautical miles # 11) Bearing to destination in degrees True # 12) Destination closing velocity in knots # 13) Arrival Status, A = Arrival Circle Entered # 14) Checksum fields = sentence.split(",") def _process_RTE(sentence): # $GPRTE Routes # eg. $GPRTE,2,1,c,0,PBRCPK,PBRTO,PTELGR,PPLAND,PYAMBU,PPFAIR,PWARRN,PMORTL,PLISMR*73 # $GPRTE,2,2,c,0,PCRESY,GRYRIE,GCORIO,GWERR,GWESTG,7FED*34 # 1. Number of sentences in sequence # 2. Sentence number # 3. 'c' = Current active route, 'w' = waypoint list starts with destination # 4. waypoint # 5. Name or number of the active route onwards, Names of waypoints in Route fields = sentence.split(",") def _process_GRMM(sentence): # MAP datum fields = sentence.split(",") datum = fields[1] def _process_GRME(sentence): # $PGRME,15.0,M,45.0,M,25.0,M*22 # 15.0,M Estimated horizontal position error in metres (HPE) # 45.0,M Estimated vertical error (VPE) in metres # 25.0,M Overall spherical equivalent position error fields = sentence.split(",") def _process_GRMZ(sentence): # $Pgrmz,93,F,3*21 # 93,F Altitude In Feet # 3 Position Fix Dimensions 2 = User Altitude # 3 = Gps Altitude # This Sentence Shows In Feet, Regardless Of Units Shown On The Display. fields = sentence.split(",") testdata = ["$GPRMB,A,,,,,,,,,,,,V*71", "$GPGGA,171434,5110.876,N,00714.665,E,1,06,1.2,332.5,M,47.1,M,,*4D", "$GPGSA,A,3,,06,,14,17,24,25,30,,,,,2.3,1.2,1.9*3F", "$GPGSV,2,1,08,04,08,028,00,06,58,214,49,09,01,148,00,14,20,238,39*74", "$GPGSV,2,2,08,17,28,133,41,24,33,063,37,25,37,302,43,30,79,082,45*7D", "$PGRME,4.7,M,6.9,M,8.4,M*2E", "$GPGLL,5110.876,N,00714.665,E,171434,A*25", "$PGRMZ,1091,f,3*22", "$PGRMM,WGS 84*06", "$GPBOD,,T,,M,,*47", "$GPRTE,1,1,c,0*07", "$GPRMC,171436,A,5110.876,N,00714.665,E,000.0,071.1,071003,000.1,E*78",] def process_sentence(sentence): sentence = sentence.strip() if not (sentence.startswith("$") and sentence[-3] == "*"): print "NMEA sentence malformed: %r" % sentence elif not _checksumOk(sentence): print "NMEA checksum wrong" else: if sentence.startswith("$GP"): if sentence.startswith("$GPGGA"): _process_GGA(sentence) elif sentence.startswith("$GPGSV"): _process_GSV(sentence) elif sentence.startswith("$GPGSA"): _process_GSA(sentence) elif sentence.startswith("$GPGLL"): _process_GSA(sentence) elif sentence.startswith("$GPRMC"): _process_RMC(sentence) elif sentence.startswith("$GPBOD"): _process_BOD(sentence) elif sentence.startswith("$GPRMB"): _process_RMB(sentence) elif sentence.startswith("$GPRTE"): _process_RTE(sentence) else: print "unknown GPS NEMA sentence %r" % sentence elif sentence.startswith("$PGRM"): if sentence.startswith("$PGRMM"): _process_GRMM(sentence) elif sentence.startswith("$PGRME"): _process_GRME(sentence) elif sentence.startswith("$PGRMZ"): _process_GRMZ(sentence) else: print "unknown vendor specific NEMA sentence %r" % sentence else: print "unknown NEMA sentence %r" % sentence if __name__ == "__main__": for sentence in testdata: process_sentence(sentence)