@@ -90,7 +90,8 @@ def __init__(self, uart, debug=False):
9090 self .height_geoid = None
9191 self .speed_knots = None
9292 self .track_angle_deg = None
93- self .sats = None
93+ self ._sats = None # Temporary holder for information from GSV messages
94+ self .sats = None # Completed information from GSV messages
9495 self .isactivedata = None
9596 self .true_track = None
9697 self .mag_track = None
@@ -121,16 +122,30 @@ def update(self):
121122 print (sentence )
122123 data_type , args = sentence
123124 data_type = bytes (data_type .upper (), "ascii" )
124- # return sentence
125- if data_type in (
126- b"GPGLL" ,
127- b"GNGLL" ,
128- ): # GLL, Geographic Position – Latitude/Longitude
125+ (talker , sentence_type ) = GPS ._parse_talker (data_type )
126+
127+ # Check for all currently known GNSS talkers
128+ # GA - Galileo
129+ # GB - BeiDou Systems
130+ # GI - NavIC
131+ # GL - GLONASS
132+ # GP - GPS
133+ # GQ - QZSS
134+ # GN - GNSS / More than one of the above
135+ if talker not in (b"GA" , b"GB" , b"GI" , b"GL" , b"GP" , b"GQ" , b"GN" ):
136+ # It's not a known GNSS source of data
137+ return True
138+
139+ if sentence_type == b"GLL" : # Geographic position - Latitude/Longitude
129140 self ._parse_gpgll (args )
130- elif data_type in ( b"GPRMC" , b"GNRMC" ) : # RMC, minimum location info
141+ elif sentence_type == b"RMC" : # Minimum location info
131142 self ._parse_gprmc (args )
132- elif data_type in ( b"GPGGA" , b"GNGGA" ) : # GGA, 3d location fix
143+ elif sentence_type == b"GGA" : # 3D location fix
133144 self ._parse_gpgga (args )
145+ elif sentence_type == b"GSV" : # Satellites in view
146+ self ._parse_gpgsv (talker , args )
147+ elif sentence_type == b"GSA" : # GPS DOP and active satellites
148+ self ._parse_gpgsa (talker , args )
134149 return True
135150
136151 def send_command (self , command , add_checksum = True ):
@@ -241,6 +256,14 @@ def _parse_sentence(self):
241256 data_type = sentence [1 :delimiter ]
242257 return (data_type , sentence [delimiter + 1 :])
243258
259+ @staticmethod
260+ def _parse_talker (data_type ):
261+ # Split the data_type into talker and sentence_type
262+ if data_type [0 ] == b"P" : # Proprietary codes
263+ return (data_type [:1 ], data_type [1 :])
264+
265+ return (data_type [:2 ], data_type [2 :])
266+
244267 def _parse_gpgll (self , args ):
245268 data = args .split ("," )
246269 if data is None or data [0 ] is None or (data [0 ] == "" ):
@@ -402,7 +425,8 @@ def _parse_gpgga(self, args):
402425 self .altitude_m = _parse_float (data [8 ])
403426 self .height_geoid = _parse_float (data [10 ])
404427
405- def _parse_gpgsa (self , args ):
428+ def _parse_gpgsa (self , talker , args ):
429+ talker = talker .decode ("ascii" )
406430 data = args .split ("," )
407431 if data is None or (data [0 ] == "" ):
408432 return # Unexpected number of params
@@ -412,9 +436,9 @@ def _parse_gpgsa(self, args):
412436 # Parse 3d fix
413437 self .fix_quality_3d = _parse_int (data [1 ])
414438 satlist = list (filter (None , data [2 :- 4 ]))
415- self .sat_prns = {}
416- for i , sat in enumerate ( satlist , 1 ) :
417- self .sat_prns [ "gps{} " .format (i )] = _parse_int (sat )
439+ self .sat_prns = []
440+ for sat in satlist :
441+ self .sat_prns . append ( "{}{} " .format (talker , _parse_int (sat )) )
418442
419443 # Parse PDOP, dilution of precision
420444 self .pdop = _parse_float (data [- 3 ])
@@ -423,9 +447,11 @@ def _parse_gpgsa(self, args):
423447 # Parse VDOP, vertical dilution of precision
424448 self .vdop = _parse_float (data [- 1 ])
425449
426- def _parse_gpgsv (self , args ):
450+ def _parse_gpgsv (self , talker , args ):
427451 # Parse the arguments (everything after data type) for NMEA GPGGA
452+ # pylint: disable=too-many-branches
428453 # 3D location fix sentence.
454+ talker = talker .decode ("ascii" )
429455 data = args .split ("," )
430456 if data is None or (data [0 ] == "" ):
431457 return # Unexpected number of params.
@@ -442,33 +468,54 @@ def _parse_gpgsv(self, args):
442468
443469 sat_tup = data [3 :]
444470
445- satdict = {}
446- for i in range (len (sat_tup ) / 4 ):
447- j = i * 4
448- key = "gps{}" .format (i + (4 * (self .mess_num - 1 )))
449- satnum = _parse_int (sat_tup [0 + j ]) # Satellite number
450- satdeg = _parse_int (sat_tup [1 + j ]) # Elevation in degrees
451- satazim = _parse_int (sat_tup [2 + j ]) # Azimuth in degrees
452- satsnr = _parse_int (sat_tup [3 + j ]) # signal-to-noise ratio in dB
453- value = (satnum , satdeg , satazim , satsnr )
454- satdict [key ] = value
455-
456- if self .sats is None :
457- self .sats = {}
458- for satnum in satdict :
459- self .sats [satnum ] = satdict [satnum ]
471+ satlist = []
472+ timestamp = time .monotonic ()
473+ for i in range (len (sat_tup ) // 4 ):
474+ try :
475+ j = i * 4
476+ value = (
477+ # Satellite number
478+ "{}{}" .format (talker , _parse_int (sat_tup [0 + j ])),
479+ # Elevation in degrees
480+ _parse_int (sat_tup [1 + j ]),
481+ # Azimuth in degrees
482+ _parse_int (sat_tup [2 + j ]),
483+ # signal-to-noise ratio in dB
484+ _parse_int (sat_tup [3 + j ]),
485+ # Timestamp
486+ timestamp ,
487+ )
488+ satlist .append (value )
489+ except ValueError :
490+ # Something wasn't an int
491+ pass
492+
493+ if self ._sats is None :
494+ self ._sats = []
495+ for value in satlist :
496+ self ._sats .append (value )
497+
498+ if self .mess_num == self .total_mess_num :
499+ # Last part of GSV message
500+ if len (self ._sats ) == self .satellites :
501+ # Transfer received satellites to self.sats
502+ if self .sats is None :
503+ self .sats = {}
504+ else :
505+ # Remove all satellites which haven't
506+ # been seen for 30 seconds
507+ timestamp = time .monotonic ()
508+ old = []
509+ for i in self .sats :
510+ sat = self .sats [i ]
511+ if (timestamp - sat [4 ]) > 30 :
512+ old .append (i )
513+ for i in old :
514+ self .sats .pop (i )
515+ for sat in self ._sats :
516+ self .sats [sat [0 ]] = sat
517+ self ._sats .clear ()
460518
461- try :
462- if self .satellites < self .satellites_prev :
463- for i in self .sats :
464- try :
465- if int (i [- 2 ]) >= self .satellites :
466- del self .sats [i ]
467- except ValueError :
468- if int (i [- 1 ]) >= self .satellites :
469- del self .sats [i ]
470- except TypeError :
471- pass
472519 self .satellites_prev = self .satellites
473520
474521
0 commit comments