@@ -62,8 +62,7 @@ class AS_GPS(object):
62
62
# https://stackoverflow.com/questions/9847213/how-do-i-get-the-day-of-week-given-a-date-in-python?noredirect=1&lq=1
63
63
# Adapted for Python 3 and Pyboard RTC format.
64
64
@staticmethod
65
- def _week_day (year , month , day ):
66
- offset = [0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 ]
65
+ def _week_day (year , month , day , offset = [0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 ]):
67
66
aux = year - 1700 - (1 if month <= 2 else 0 )
68
67
# day_of_week for 1700/1/1 = 5, Friday
69
68
day_of_week = 5
@@ -137,12 +136,13 @@ def __init__(self, sreader, local_offset=0, fix_cb=lambda *_ : None, cb_mask=RMC
137
136
138
137
#####################
139
138
# Data From Sentences
140
- # Time. Ignore http://www.gpsinformation.org/dale/nmea.htm, hardware
141
- # returns a float.
142
- self .utc = [0 , 0 , 0.0 ] # [h: int, m: int, s: float]
143
- self .local_time = [0 , 0 , 0.0 ] # [h: int, m: int, s: float]
144
- self .date = [0 , 0 , 0 ] # [dd: int, mm: int, yy: int]
139
+ # Time. http://www.gpsinformation.org/dale/nmea.htm indicates seconds
140
+ # is an integer. However hardware returns a float, but the fractional
141
+ # part is always zero. So treat seconds value as an integer. For
142
+ # precise timing use PPS signal and as_tGPS library.
145
143
self .local_offset = local_offset # hrs
144
+ self ._rtcbuf = [0 ]* 8 # Buffer for RTC setting
145
+ self .epoch_time = 0 # Integer secs since epoch (Y2K under MicroPython)
146
146
147
147
# Position/Motion
148
148
self ._latitude = [0 , 0.0 , 'N' ] # (°, mins, N/S)
@@ -202,7 +202,6 @@ def _update(self, line):
202
202
if not self ._crc_check (line , segs [- 1 ]):
203
203
self .crc_fails += 1 # Update statistics
204
204
return None
205
-
206
205
self .clean_sentences += 1 # Sentence is good but unparsed.
207
206
segs [0 ] = segs [0 ][1 :] # discard $
208
207
segs = segs [:- 1 ] # and checksum
@@ -258,47 +257,33 @@ def _fix(self, gps_segments, idx_lat, idx_long):
258
257
self ._fix_time = self ._get_time ()
259
258
return True
260
259
261
- # Set timestamp. If time/date not present retain last reading (if any).
262
- def _set_timestamp (self , utc_string ):
263
- if not utc_string :
264
- return False
265
- # Possible timestamp found
266
- try :
267
- self .utc [0 ] = int (utc_string [0 :2 ]) # h
268
- self .utc [1 ] = int (utc_string [2 :4 ]) # mins
269
- self .utc [2 ] = float (utc_string [4 :]) # secs from chip is a float
270
- return True
271
- except ValueError :
272
- return False
273
- for idx in range (3 ):
274
- self .local_time [idx ] = self .utc [idx ]
275
- return True
276
-
277
260
# A local offset may exist so check for date rollover. Local offsets can
278
261
# include fractions of an hour but not seconds (AFAIK).
279
- def _set_date (self , date_string ):
280
- if not date_string :
262
+ def _set_date_time (self , utc_string , date_string ):
263
+ if not date_string or not utc_string :
281
264
return False
282
265
try :
266
+ hrs = int (utc_string [0 :2 ]) # h
267
+ mins = int (utc_string [2 :4 ]) # mins
268
+ secs = int (utc_string [4 :6 ]) # secs from chip is a float but FP is always 0
283
269
d = int (date_string [0 :2 ]) # day
284
270
m = int (date_string [2 :4 ]) # month
285
271
y = int (date_string [4 :6 ]) + 2000 # year
286
- except ValueError : # Bad Date stamp value present
272
+ except ValueError : # Bad date or time strings
287
273
return False
288
- hrs = self .utc [0 ]
289
- mins = self .utc [1 ]
290
- secs = self .utc [2 ]
291
- wday = self ._week_day (y , m , d ) - 1
292
- t = self ._mktime ((y , m , d , hrs , mins , int (secs ), wday , 0 , 0 ))
274
+ wday = self ._week_day (y , m , d )
275
+ t = self ._mktime ((y , m , d , hrs , mins , int (secs ), wday - 1 , 0 , 0 ))
276
+ self .epoch_time = t # This is the fundamental datetime reference.
277
+ # Need local time for setting Pyboard RTC in interrupt context
293
278
t += int (3600 * self .local_offset )
294
- y , m , d , hrs , mins , * _ = self ._localtime (t ) # Preserve float seconds
295
- y -= 2000
296
- self .local_time [ 0 ] = hrs
297
- self .local_time [ 1 ] = mins
298
- self .local_time [ 2 ] = secs
299
- self .date [ 0 ] = d
300
- self .date [ 1 ] = m
301
- self .date [ 2 ] = y
279
+ y , m , d , hrs , mins , secs , * _ = self ._localtime (t )
280
+ self . _rtcbuf [ 0 ] = y
281
+ self ._rtcbuf [ 1 ] = m
282
+ self ._rtcbuf [ 2 ] = d
283
+ self ._rtcbuf [ 3 ] = wday
284
+ self ._rtcbuf [ 4 ] = hrs
285
+ self ._rtcbuf [ 5 ] = mins
286
+ self ._rtcbuf [ 6 ] = secs
302
287
return True
303
288
304
289
########################################
@@ -313,10 +298,8 @@ def _set_date(self, date_string):
313
298
314
299
def _gprmc (self , gps_segments ): # Parse RMC sentence
315
300
self ._valid &= ~ RMC
316
- # UTC Timestamp.
317
- if not self ._set_timestamp (gps_segments [1 ]):
318
- return False # Bad Timestamp value present
319
- if not self ._set_date (gps_segments [9 ]):
301
+ # UTC Timestamp and date.
302
+ if not self ._set_date_time (gps_segments [1 ], gps_segments [9 ]):
320
303
return False
321
304
322
305
# Check Receiver Data Valid Flag
@@ -356,12 +339,6 @@ def _gprmc(self, gps_segments): # Parse RMC sentence
356
339
357
340
def _gpgll (self , gps_segments ): # Parse GLL sentence
358
341
self ._valid &= ~ GLL
359
- # UTC Timestamp.
360
- try :
361
- self ._set_timestamp (gps_segments [5 ])
362
- except ValueError : # Bad Timestamp value present
363
- return False
364
-
365
342
# Check Receiver Data Valid Flag
366
343
if gps_segments [6 ] != 'A' : # Invalid. Don't update data
367
344
return True # Correctly parsed
@@ -391,18 +368,12 @@ def _gpvtg(self, gps_segments): # Parse VTG sentence
391
368
def _gpgga (self , gps_segments ): # Parse GGA sentence
392
369
self ._valid &= ~ GGA
393
370
try :
394
- # UTC Timestamp
395
- self ._set_timestamp (gps_segments [1 ])
396
-
397
371
# Number of Satellites in Use
398
372
satellites_in_use = int (gps_segments [7 ])
399
-
400
373
# Horizontal Dilution of Precision
401
374
hdop = float (gps_segments [8 ])
402
-
403
375
# Get Fix Status
404
376
fix_stat = int (gps_segments [6 ])
405
-
406
377
except ValueError :
407
378
return False
408
379
@@ -647,9 +618,28 @@ def speed_string(self, unit=KPH):
647
618
return sform .format (speed , 'knots' )
648
619
return sform .format (speed , 'km/h' )
649
620
650
- def time (self , local = True ):
651
- t = self .local_time if local else self .utc
652
- return '{:02d}:{:02d}:{:06.3f}' .format (* t )
621
+ # Return local time (hrs: int, mins: int, secs:float)
622
+ @property
623
+ def local_time (self ):
624
+ t = self .epoch_time + int (3600 * self .local_offset )
625
+ _ , _ , _ , hrs , mins , secs , * _ = self ._localtime (t )
626
+ return hrs , mins , secs
627
+
628
+ @property
629
+ def date (self ):
630
+ t = self .epoch_time + int (3600 * self .local_offset )
631
+ y , m , d , * _ = self ._localtime (t )
632
+ return d , m , y - 2000
633
+
634
+ @property
635
+ def utc (self ):
636
+ t = self .epoch_time + int (3600 * self .local_offset )
637
+ _ , _ , _ , hrs , mins , secs , * _ = self ._localtime (t )
638
+ return hrs , mins , secs
639
+
640
+ def time_string (self , local = True ):
641
+ hrs , mins , secs = self .local_time if local else self .utc
642
+ return '{:02d}:{:02d}:{:02d}' .format (hrs , mins , secs )
653
643
654
644
def date_string (self , formatting = MDY ):
655
645
day , month , year = self .date
0 commit comments