@@ -90,7 +90,8 @@ def __init__(self, uart, debug=False):
90
90
self .height_geoid = None
91
91
self .speed_knots = None
92
92
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
94
95
self .isactivedata = None
95
96
self .true_track = None
96
97
self .mag_track = None
@@ -121,16 +122,30 @@ def update(self):
121
122
print (sentence )
122
123
data_type , args = sentence
123
124
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
129
140
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
131
142
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
133
144
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 )
134
149
return True
135
150
136
151
def send_command (self , command , add_checksum = True ):
@@ -241,6 +256,14 @@ def _parse_sentence(self):
241
256
data_type = sentence [1 :delimiter ]
242
257
return (data_type , sentence [delimiter + 1 :])
243
258
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
+
244
267
def _parse_gpgll (self , args ):
245
268
data = args .split ("," )
246
269
if data is None or data [0 ] is None or (data [0 ] == "" ):
@@ -402,7 +425,8 @@ def _parse_gpgga(self, args):
402
425
self .altitude_m = _parse_float (data [8 ])
403
426
self .height_geoid = _parse_float (data [10 ])
404
427
405
- def _parse_gpgsa (self , args ):
428
+ def _parse_gpgsa (self , talker , args ):
429
+ talker = talker .decode ("ascii" )
406
430
data = args .split ("," )
407
431
if data is None or (data [0 ] == "" ):
408
432
return # Unexpected number of params
@@ -412,9 +436,9 @@ def _parse_gpgsa(self, args):
412
436
# Parse 3d fix
413
437
self .fix_quality_3d = _parse_int (data [1 ])
414
438
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 )) )
418
442
419
443
# Parse PDOP, dilution of precision
420
444
self .pdop = _parse_float (data [- 3 ])
@@ -423,9 +447,11 @@ def _parse_gpgsa(self, args):
423
447
# Parse VDOP, vertical dilution of precision
424
448
self .vdop = _parse_float (data [- 1 ])
425
449
426
- def _parse_gpgsv (self , args ):
450
+ def _parse_gpgsv (self , talker , args ):
427
451
# Parse the arguments (everything after data type) for NMEA GPGGA
452
+ # pylint: disable=too-many-branches
428
453
# 3D location fix sentence.
454
+ talker = talker .decode ("ascii" )
429
455
data = args .split ("," )
430
456
if data is None or (data [0 ] == "" ):
431
457
return # Unexpected number of params.
@@ -442,33 +468,54 @@ def _parse_gpgsv(self, args):
442
468
443
469
sat_tup = data [3 :]
444
470
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 ()
460
518
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
472
519
self .satellites_prev = self .satellites
473
520
474
521
0 commit comments