parser.py
Go to the documentation of this file.
00001 # Software License Agreement (BSD License)
00002 #
00003 # Copyright (c) 2013, Eric Perko
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions
00008 # are met:
00009 #
00010 #  * Redistributions of source code must retain the above copyright
00011 #    notice, this list of conditions and the following disclaimer.
00012 #  * Redistributions in binary form must reproduce the above
00013 #    copyright notice, this list of conditions and the following
00014 #    disclaimer in the documentation and/or other materials provided
00015 #    with the distribution.
00016 #  * Neither the names of the authors nor the names of their
00017 #    affiliated organizations may be used to endorse or promote products derived
00018 #    from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 # POSSIBILITY OF SUCH DAMAGE.
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     #Get current time in UTC for date information
00046     utc_struct = time.gmtime() #immutable, so cannot modify this one
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 # Need this wrapper because math.radians doesn't auto convert inputs
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     # Check for a valid nmea sentence
00102     if not re.match('^\$GP.*\*[0-9A-Fa-f]{2}$', nmea_sentence):
00103         #print "Regex didn't match"
00104         return False
00105     fields = [field.strip(',') for field in nmea_sentence.split(',')]
00106 
00107     # Ignore the $ and talker ID portions (e.g. GP)
00108     sentence_type = fields[0][3:]
00109 
00110     if not sentence_type in parse_maps:
00111         #print sentence_type
00112         #print "Sentence type not in parse map"
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}


nmea_navsat_driver
Author(s): Eric Perko , Steven Martin
autogenerated on Thu Aug 27 2015 14:11:02