diff options
author | Gary E. Miller <gem@rellim.com> | 2019-04-22 18:20:51 -0700 |
---|---|---|
committer | Gary E. Miller <gem@rellim.com> | 2019-04-22 18:20:51 -0700 |
commit | 2e261f2ad561bd03206f8e9d1f6fddf838f4a9ce (patch) | |
tree | 000d249247a903dc722c75fe7988293a0013d31a /pseudonmea.c | |
parent | a421c9c58555e38d026aa670e9d26d976be81bf4 (diff) | |
download | gpsd-2e261f2ad561bd03206f8e9d1f6fddf838f4a9ce.tar.gz |
pseudonmea: Fix potential rounding errors. Combine code.
Time could be ouput as: $GPGGA,205660.00. Changes no regressions,
but I have seen the error.
Combine 5 cases of time code into one function.
Diffstat (limited to 'pseudonmea.c')
-rw-r--r-- | pseudonmea.c | 97 |
1 files changed, 43 insertions, 54 deletions
diff --git a/pseudonmea.c b/pseudonmea.c index 7eef32e5..12e8be2c 100644 --- a/pseudonmea.c +++ b/pseudonmea.c @@ -47,30 +47,45 @@ static char *f_str(double f, const char *fmt, char *buf) return buf; } +/* convert UTC to time str (hh:mm:ss) and tm */ +static void utc_to_hhmmss(timestamp_t time, char *buf, ssize_t buf_sz, + struct tm *tm) +{ + double integral; + double fractional; + time_t integral_time; + unsigned frac; + + if (0 == isfinite(time)) { + buf[0] = '\0'; + return; + } + + /* round to 100ths */ + fractional = modf(time + 0.005, &integral); + integral_time = (time_t)integral; + frac = (unsigned)(fractional * 100.0); + + (void)gmtime_r(&integral_time, tm); + + (void)snprintf(buf, buf_sz, "%02d%02d%02d.%02d", + tm->tm_hour, tm->tm_min, tm->tm_sec, frac); + return; +} + /* Dump a $GPGGA. * looks like this is only called from net_ntrip.c */ void gpsd_position_fix_dump(struct gps_device_t *session, char bufp[], size_t len) { + struct tm tm; char time_str[20]; char lat_str[BUF_SZ]; char lon_str[BUF_SZ]; - if (0 != isfinite(session->gpsdata.fix.time)) { - struct tm tm; - double integral; - double fractional = modf(session->gpsdata.fix.time, &integral); - time_t integral_time = (time_t)integral; - - (void)gmtime_r(&integral_time, &tm); + utc_to_hhmmss(session->gpsdata.fix.time, time_str, sizeof(time_str), &tm); - (void)snprintf(time_str, sizeof(time_str), - "%02d%02d%05.2f", - tm.tm_hour, tm.tm_min, tm.tm_sec + fractional); - } else { - time_str[0] = '\0'; - } if (session->gpsdata.fix.mode > MODE_NO_FIX) { (void)snprintf(bufp, len, "$GPGGA,%s,%s,%c,%s,%c,%d,%02d,", @@ -115,25 +130,17 @@ static void gpsd_transit_fix_dump(struct gps_device_t *session, char lon_str[BUF_SZ]; char speed_str[BUF_SZ]; char track_str[BUF_SZ]; + struct tm tm; - if (0 != isfinite(session->gpsdata.fix.time)) { - struct tm tm; - double integral; - double fractional = modf(session->gpsdata.fix.time, &integral); - time_t integral_time = (time_t)integral; - - (void)gmtime_r(&integral_time, &tm); - + utc_to_hhmmss(session->gpsdata.fix.time, time_str, sizeof(time_str), &tm); + if ('\0' != time_str[0]) { tm.tm_mon++; tm.tm_year %= 100; - (void)snprintf(time_str, sizeof(time_str), - "%02d%02d%05.2f", - tm.tm_hour, tm.tm_min, tm.tm_sec + fractional); + (void)snprintf(time2_str, sizeof(time2_str), "%02d%02d%02d", tm.tm_mday, tm.tm_mon, tm.tm_year); } else { - time_str[0] = '\0'; time2_str[0] = '\0'; } (void)snprintf(bufp, len, @@ -278,19 +285,12 @@ static void gpsd_binary_quality_dump(struct gps_device_t *session, 0 != isfinite(session->gpsdata.fix.epy) && 0 != isfinite(session->gpsdata.fix.time)) { + struct tm tm; char time_str[20]; char epv_str[BUF_SZ]; - struct tm tm; - double integral; - double fractional = modf(session->gpsdata.fix.time, &integral); - time_t integral_time = (time_t)integral; - - (void)gmtime_r(&integral_time, &tm); - - (void)snprintf(time_str, sizeof(time_str), - "%02d%02d%05.2f", - tm.tm_hour, tm.tm_min, tm.tm_sec + fractional); + (void)utc_to_hhmmss(session->gpsdata.fix.time, + time_str, sizeof(time_str), &tm); bufp2 = bufp + strlen(bufp); str_appendf(bufp, len, @@ -307,30 +307,19 @@ static void gpsd_binary_quality_dump(struct gps_device_t *session, static void gpsd_binary_time_dump(struct gps_device_t *session, char bufp[], size_t len) { - struct tm tm; - double integral; - time_t integral_time; if (MODE_NO_FIX < session->newdata.mode && 0 != isfinite(session->gpsdata.fix.time)) { + struct tm tm; + char time_str[20]; - double fractional = modf(session->newdata.time, &integral); - integral_time = (time_t) integral; - (void)gmtime_r(&integral_time, &tm); - /* - * We pin this report to the GMT/UTC timezone. This may be technically - * incorrect; our sources on ZDA suggest that it should report local - * timezone. But no GPS we've ever seen actually does this, because it - * would require embedding a location-to-TZ database in the receiver. - * And even if we could do that, it would make our regression tests - * break any time they were run in a timezone different from the one - * where they were generated. - */ + utc_to_hhmmss(session->gpsdata.fix.time, time_str, sizeof(time_str), + &tm); + /* There used to be confusion, but we now know NMEA times are UTC, + * when available. */ (void)snprintf(bufp, len, - "$GPZDA,%02d%02d%05.2f,%02d,%02d,%04d,00,00", - tm.tm_hour, - tm.tm_min, - (double)tm.tm_sec + fractional, + "$GPZDA,%s,%02d,%02d,%04d,00,00", + time_str, tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900); |