Skip to content

Commit e52d879

Browse files
committed
Added all functions. They still need testing
1 parent 358d7d5 commit e52d879

File tree

1 file changed

+136
-56
lines changed

1 file changed

+136
-56
lines changed

adafruit_gps.py

+136-56
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ def _parse_float(nmea_data):
7070
return None
7171
return float(nmea_data)
7272

73+
def _parse_str(nmea_data):
74+
if nmea_data is None or nmea_data == '':
75+
return None
76+
return str(nmea_data)
77+
7378
# lint warning about too many attributes disabled
7479
#pylint: disable-msg=R0902
7580
class GPS:
@@ -83,18 +88,20 @@ def __init__(self, uart, debug=False):
8388
self.latitude = None
8489
self.longitude = None
8590
self.fix_quality = None
91+
self.fix_quality_3d = None
8692
self.satellites = None
8793
self.horizontal_dilution = None
8894
self.altitude_m = None
8995
self.height_geoid = None
90-
self.velocity_knots = None
9196
self.speed_knots = None
97+
self.speed_kmh = None
9298
self.track_angle_deg = None
9399
self.total_mess_num = None
94100
self.mess_num = None
95-
self.gps0 = None
96-
self.gps1 = None
97-
self.gps2 = None
101+
self.sats = None
102+
self.isactivedata = None
103+
self.true_track = None
104+
self.mag_track = None
98105
self.debug = debug
99106

100107
def update(self):
@@ -115,11 +122,18 @@ def update(self):
115122
data_type, args = sentence
116123
data_type = bytes(data_type.upper(), "ascii")
117124
#return sentence
118-
if data_type == b'GPGGA': # GGA, 3d location fix
119-
self._parse_gpgga(args)
120-
elif data_type == b'GPRMC': # RMC, minimum location info
125+
126+
if data_type == b'GPGLL': # GLL, Geographic Position – Latitude/Longitude
127+
self._parse_gpgll(args)
128+
elif data_type == b'GPRMC': # RMC, minimum location info
121129
self._parse_gprmc(args)
122-
elif data_type == b'GPGSV':
130+
elif data_type == b'GPVTG': # VTG, Track Made Good and Ground Speed
131+
self._parse_gpvtg(args)
132+
elif data_type == b'GPGGA': # GGA, 3d location fix
133+
self._parse_gpgga(args)
134+
elif data_type == b'GPGSA': # GSA, GPS DOP and active satellites
135+
self._parse_gpgsa(args)
136+
elif data_type == b'GPGSV': # GSV, Satellites in view
123137
self._parse_gpgsv(args)
124138
return True
125139

@@ -143,6 +157,10 @@ def send_command(self, command, add_checksum=True):
143157
def has_fix(self):
144158
"""True if a current fix for location information is available."""
145159
return self.fix_quality is not None and self.fix_quality >= 1
160+
161+
@property
162+
def has_3d_fix(self):
163+
return self.fix_quality_3d is not None and self.fix_quality_3d >= 2
146164

147165
@property
148166
def datetime(self):
@@ -179,15 +197,22 @@ def _parse_sentence(self):
179197
data_type = sentence[1:delineator]
180198
return (data_type, sentence[delineator+1:])
181199

182-
183-
def _parse_gpgga(self, args):
184-
# Parse the arguments (everything after data type) for NMEA GPGGA
185-
# 3D location fix sentence.
200+
def _parse_gpgll(self, args):
186201
data = args.split(',')
187-
if data is None or len(data) != 14:
188-
return # Unexpected number of params.
189-
# Parse fix time.
190-
time_utc = int(_parse_float(data[0]))
202+
if data is None or len(data) < 11 or data[0] is None:
203+
return # Unexpected number of params.
204+
205+
# Parse latitude and longitude.
206+
self.latitude = _parse_degrees(data[0])
207+
if self.latitude is not None and \
208+
data[1] is not None and data[1].lower() == 's':
209+
self.latitude *= -1.0
210+
self.longitude = _parse_degrees(data[2])
211+
if self.longitude is not None and \
212+
data[3] is not None and data[3].lower() == 'w':
213+
self.longitude *= -1.0
214+
215+
time_utc = int(_parse_int(data[4]))
191216
if time_utc is not None:
192217
hours = time_utc // 10000
193218
mins = (time_utc // 100) % 100
@@ -199,23 +224,10 @@ def _parse_gpgga(self, args):
199224
self.timestamp_utc.tm_mday, hours, mins, secs, 0, 0, -1))
200225
else:
201226
self.timestamp_utc = time.struct_time((0, 0, 0, hours, mins,
202-
secs, 0, 0, -1))
203-
# Parse latitude and longitude.
204-
self.latitude = _parse_degrees(data[1])
205-
if self.latitude is not None and \
206-
data[2] is not None and data[2].lower() == 's':
207-
self.latitude *= -1.0
208-
self.longitude = _parse_degrees(data[3])
209-
if self.longitude is not None and \
210-
data[4] is not None and data[4].lower() == 'w':
211-
self.longitude *= -1.0
212-
# Parse out fix quality and other simple numeric values.
213-
self.fix_quality = _parse_int(data[5])
214-
self.satellites = _parse_int(data[6])
215-
self.horizontal_dilution = _parse_float(data[7])
216-
self.altitude_m = _parse_float(data[8])
217-
self.height_geoid = _parse_float(data[10])
218-
227+
secs, 0, 0, -1))
228+
# Parse data active or void
229+
self.isactivedata = _parse_str(data[5])
230+
219231
def _parse_gprmc(self, args):
220232
# Parse the arguments (everything after data type) for NMEA GPRMC
221233
# minimum location fix sentence.
@@ -275,43 +287,111 @@ def _parse_gprmc(self, args):
275287
self.timestamp_utc = time.struct_time((year, month, day, 0, 0,
276288
0, 0, 0, -1))
277289

290+
def _parse_gpvtg(self, args):
291+
data = args.split(',')
292+
293+
# Parse true track made good (degrees)
294+
self.true_track = _parse_float(data[0])
295+
296+
# Parse magnetic track made good
297+
self.mag_track = _parse_float(data[2])
298+
299+
# Parse speed
300+
self.speed_knots = _parse_float(data[4])
301+
self.speed_kmh = _parse_float(data[6])
302+
303+
def _parse_gpgga(self, args):
304+
# Parse the arguments (everything after data type) for NMEA GPGGA
305+
# 3D location fix sentence.
306+
data = args.split(',')
307+
if data is None or len(data) != 14:
308+
return # Unexpected number of params.
309+
# Parse fix time.
310+
time_utc = int(_parse_float(data[0]))
311+
if time_utc is not None:
312+
hours = time_utc // 10000
313+
mins = (time_utc // 100) % 100
314+
secs = time_utc % 100
315+
# Set or update time to a friendly python time struct.
316+
if self.timestamp_utc is not None:
317+
self.timestamp_utc = time.struct_time((
318+
self.timestamp_utc.tm_year, self.timestamp_utc.tm_mon,
319+
self.timestamp_utc.tm_mday, hours, mins, secs, 0, 0, -1))
320+
else:
321+
self.timestamp_utc = time.struct_time((0, 0, 0, hours, mins,
322+
secs, 0, 0, -1))
323+
# Parse latitude and longitude.
324+
self.latitude = _parse_degrees(data[1])
325+
if self.latitude is not None and \
326+
data[2] is not None and data[2].lower() == 's':
327+
self.latitude *= -1.0
328+
self.longitude = _parse_degrees(data[3])
329+
if self.longitude is not None and \
330+
data[4] is not None and data[4].lower() == 'w':
331+
self.longitude *= -1.0
332+
# Parse out fix quality and other simple numeric values.
333+
self.fix_quality = _parse_int(data[5])
334+
self.satellites = _parse_int(data[6])
335+
self.horizontal_dilution = _parse_float(data[7])
336+
self.altitude_m = _parse_float(data[8])
337+
self.height_geoid = _parse_float(data[10])
338+
339+
def _parse_gpgsa(self, args):
340+
data = args.split(',')
341+
if data is None:
342+
return # Unexpected number of params
343+
344+
# Parse selection mode
345+
self.sel_mode = _parse_str(data[0])
346+
# Parse 3d fix
347+
self.fix_quality_3d = _parse_int(data[1])
348+
sats = list(filter(None, data[2:-4]))
349+
satdict = {}
350+
for i in range(len(sats)):
351+
satdict["self.gps{}".format(i)] = _parse_int(sats[i])
352+
353+
globals().update(satdict)
354+
355+
# Parse PDOP, dilution of precision
356+
self.pdop = _parse_float(data[-3])
357+
# Parse HDOP, horizontal dilution of precision
358+
self.hdop = _parse_float(data[-2])
359+
# Parse VDOP, vertical dilution of precision
360+
self.vdop = _parse_float(data[-1])
361+
278362
def _parse_gpgsv(self, args):
279363
# Parse the arguments (everything after data type) for NMEA GPGGA
280364
# 3D location fix sentence.
281365
data = args.split(',')
282366
if data is None:
283367
return # Unexpected number of params.
368+
284369
# Parse number of messages
285370
self.total_mess_num = _parse_int(data[0]) # Total number of messages
286371
# Parse message number
287372
self.mess_num = _parse_int(data[1]) # Message number
288373
# Parse number of satellites in view
289374
self.satellites = _parse_int(data[2]) # Number of satellites
290-
"""
291-
if self.satellites > 0:
292-
self.has_fix = 1
293-
"""
375+
try:
376+
satlist
377+
except NameError:
378+
satlist = [None] * self.total_mess_num
379+
380+
sat_tup = data[3:]
294381

295-
sats = data[3:]
296382
satdict = {}
297-
for i in range(len(sats) / 4):
383+
for i in range(len(sat_tup) / 4):
298384
j = i*4
299-
key = "self.gps{}".format(i)
300-
satnum = _parse_int(sats[0+j]) # Satellite number
301-
satdeg = _parse_int(sats[1+j]) # Elevation in degrees
302-
satazim = _parse_int(sats[2+j]) # Azimuth in degrees
303-
satsnr = _parse_int(sats[3+j]) # SNR (signal-to-noise ratio) in dB
385+
key = "gps{}".format(i)
386+
satnum = _parse_int(sat_tup[0+j]) # Satellite number
387+
satdeg = _parse_int(sat_tup[1+j]) # Elevation in degrees
388+
satazim = _parse_int(sat_tup[2+j]) # Azimuth in degrees
389+
satsnr = _parse_int(sat_tup[3+j]) # SNR (signal-to-noise ratio) in dB
304390
value = (satnum, satdeg, satazim, satsnr)
305391
satdict[key] = value
306-
"""
307-
params = {'self': self}
308-
for k, v in satdict.items():
309-
exec("%s=%s" % (k, v), params, params)
310-
"""
311-
globals().update(satdict)
312-
# Should be self.gps0, self.gps1, self.gps2, etc
313-
# Each should be a tuple with 4 values
314-
# gpsx[0] = satellite number
315-
# gpsx[1] = elevation in degrees
316-
# gpsx[2] = azimuth in degrees to true
317-
# gpsx[3] = Signal-to-noise ratio in dB
392+
393+
satlist[self.mess_num-1] = satdict
394+
satlist = list(filter(None, satlist))
395+
self.sats = {}
396+
for satdict in satlist:
397+
self.sats.update(satdict)

0 commit comments

Comments
 (0)