00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 import re
00034 import time
00035 import calendar
00036 import math
00037
00038 def convert_latitude(field):
00039 return float(field[0:2])+float(field[2:])/60.0
00040
00041 def convert_longitude(field):
00042 return float(field[0:3])+float(field[3:])/60.0
00043
00044 def convert_time(nmea_utc):
00045
00046 utc_struct = time.gmtime()
00047 utc_list = list(utc_struct)
00048 hours = int(nmea_utc[0:2])
00049 minutes = int(nmea_utc[2:4])
00050 seconds = int(nmea_utc[4:6])
00051 utc_list[3] = hours
00052 utc_list[4] = minutes
00053 utc_list[5] = seconds
00054 unix_time = calendar.timegm(tuple(utc_list))
00055 return unix_time
00056
00057 def convert_status_flag(status_flag):
00058 if status_flag == "A":
00059 return True
00060 elif status_flag == "V":
00061 return False
00062 else:
00063 return False
00064
00065 def convert_knots_to_mps(knots):
00066 return float(knots)*0.514444444444
00067
00068
00069 def convert_deg_to_rads(degs):
00070 return math.radians(float(degs))
00071
00072 """Format for this is a sentence identifier (e.g. "GGA") as the key, with a
00073 tuple of tuples where each tuple is a field name, conversion function and index
00074 into the split sentence"""
00075 parse_maps = {
00076 "GGA": [
00077 ("fix_type", int, 6),
00078 ("latitude", convert_latitude, 2),
00079 ("latitude_direction", str, 3),
00080 ("longitude", convert_longitude, 4),
00081 ("longitude_direction", str, 5),
00082 ("altitude", float, 9),
00083 ("mean_sea_level", float, 11),
00084 ("hdop", float, 8),
00085 ("num_satellites", int, 7),
00086 ("utc_time", convert_time, 1),
00087 ],
00088 "RMC": [
00089 ("utc_time", convert_time, 1),
00090 ("fix_valid", convert_status_flag, 2),
00091 ("latitude", convert_latitude, 3),
00092 ("latitude_direction", str, 4),
00093 ("longitude", convert_longitude, 5),
00094 ("longitude_direction", str, 6),
00095 ("speed", convert_knots_to_mps, 7),
00096 ("true_course", convert_deg_to_rads, 8),
00097 ]
00098 }
00099
00100 def parse_nmea_sentence(nmea_sentence):
00101
00102 if not re.match('^\$GP.*\*[0-9A-Fa-f]{2}$', nmea_sentence):
00103
00104 return False
00105 fields = [field.strip(',') for field in nmea_sentence.split(',')]
00106
00107
00108 sentence_type = fields[0][3:]
00109
00110 if not sentence_type in parse_maps:
00111
00112
00113 return False
00114
00115 parse_map = parse_maps[sentence_type]
00116
00117 parsed_sentence = {}
00118 for entry in parse_map:
00119 parsed_sentence[entry[0]] = entry[1](fields[entry[2]])
00120
00121 return {sentence_type: parsed_sentence}