gpsd 3.23 (API 12) compatibility and cleanups.

This commit is contained in:
wb2osz 2022-01-02 02:55:11 +00:00
parent 5dbe2ce136
commit 42314b7219
5 changed files with 106 additions and 73 deletions

View File

@ -17,7 +17,11 @@
- The BEACON configuration now recognizes the SOURCE= option. This replaces the AX.25 source address rather than using the MYCALL value for the channel. This is useful for sending more than 5 analog telemetry channels. Use two, or more, source addresses with up to 5 analog channels each. - The BEACON configuration now recognizes the SOURCE= option. This replaces the AX.25 source address rather than using the MYCALL value for the channel. This is useful for sending more than 5 analog telemetry channels. Use two, or more, source addresses with up to 5 analog channels each.
- For more flexibility, the FX.25 transmit property can now be set individually by channel, rather than having a global setting for all channels. The -X on the command line applies only to channel 0. For other channels you need to add a new line to the configuration file.
> After: "CHANNEL 1" (or other channel)
>
> Add: "FX25TX 1" (or 16 or 32 or 64)
## Version 1.6 -- October 2020 ## ## Version 1.6 -- October 2020 ##

View File

@ -26,6 +26,10 @@
* Establish connections and transfer data in the proper * Establish connections and transfer data in the proper
* order with retries. * order with retries.
* *
* Using the term "data link" is rather unfortunate because it causes
* confusion to someone familiar with the OSI networking model.
* This corresponds to the layer 4 transport, not layer 2 data link.
*
* Description: * Description:
* *
* Typical sequence for establishing a connection * Typical sequence for establishing a connection
@ -824,6 +828,11 @@ static ax25_dlsm_t *get_link_handle (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LE
// Create new data link state machine. // Create new data link state machine.
p = calloc (sizeof(ax25_dlsm_t), 1); p = calloc (sizeof(ax25_dlsm_t), 1);
if (p == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("FATAL ERROR: Out of memory.\n");
exit (EXIT_FAILURE);
}
p->magic1 = MAGIC1; p->magic1 = MAGIC1;
p->start_time = dtime_now(); p->start_time = dtime_now();
p->stream_id = next_stream_id++; p->stream_id = next_stream_id++;
@ -1493,6 +1502,11 @@ void dl_register_callsign (dlq_item_t *E)
} }
r = calloc(sizeof(reg_callsign_t),1); r = calloc(sizeof(reg_callsign_t),1);
if (r == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("FATAL ERROR: Out of memory.\n");
exit (EXIT_FAILURE);
}
strlcpy (r->callsign, E->addrs[0], sizeof(r->callsign)); strlcpy (r->callsign, E->addrs[0], sizeof(r->callsign));
r->chan = E->chan; r->chan = E->chan;
r->client = E->client; r->client = E->client;

View File

@ -1377,9 +1377,14 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
#define isT(c) ((c) == ' ' || (c) == '>' || (c) == ']' || (c) == '`' || (c) == '\'') #define isT(c) ((c) == ' ' || (c) == '>' || (c) == ']' || (c) == '`' || (c) == '\'')
// Last updated Sept. 2016 for TH-D74A // Last Updated Dec. 2021
// This does not change very often but I'm wondering if we could simply parse
// http://www.aprs.org/aprs12/mic-e-types.txt similar to how we use tocalls.txt.
if (isT(*pfirst)) { if (isT(*pfirst)) {
// "legacy" formats.
if (*pfirst == ' ' ) { strlcpy (A->g_mfr, "Original MIC-E", sizeof(A->g_mfr)); pfirst++; } if (*pfirst == ' ' ) { strlcpy (A->g_mfr, "Original MIC-E", sizeof(A->g_mfr)); pfirst++; }
@ -1390,6 +1395,8 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
else if (*pfirst == ']' && *plast == '=') { strlcpy (A->g_mfr, "Kenwood TM-D710", sizeof(A->g_mfr)); pfirst++; plast--; } else if (*pfirst == ']' && *plast == '=') { strlcpy (A->g_mfr, "Kenwood TM-D710", sizeof(A->g_mfr)); pfirst++; plast--; }
else if (*pfirst == ']' ) { strlcpy (A->g_mfr, "Kenwood TM-D700", sizeof(A->g_mfr)); pfirst++; } else if (*pfirst == ']' ) { strlcpy (A->g_mfr, "Kenwood TM-D700", sizeof(A->g_mfr)); pfirst++; }
// ` should be used for message capable devices.
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == ' ') { strlcpy (A->g_mfr, "Yaesu VX-8", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if (*pfirst == '`' && *(plast-1) == '_' && *plast == ' ') { strlcpy (A->g_mfr, "Yaesu VX-8", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '"') { strlcpy (A->g_mfr, "Yaesu FTM-350", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '"') { strlcpy (A->g_mfr, "Yaesu FTM-350", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '#') { strlcpy (A->g_mfr, "Yaesu VX-8G", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '#') { strlcpy (A->g_mfr, "Yaesu VX-8G", sizeof(A->g_mfr)); pfirst++; plast-=2; }
@ -1398,11 +1405,15 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == ')') { strlcpy (A->g_mfr, "Yaesu FTM-100D", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if (*pfirst == '`' && *(plast-1) == '_' && *plast == ')') { strlcpy (A->g_mfr, "Yaesu FTM-100D", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '(') { strlcpy (A->g_mfr, "Yaesu FT2D", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '(') { strlcpy (A->g_mfr, "Yaesu FT2D", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '0') { strlcpy (A->g_mfr, "Yaesu FT3D", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '0') { strlcpy (A->g_mfr, "Yaesu FT3D", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '3') { strlcpy (A->g_mfr, "Yaesu FT5D", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '1') { strlcpy (A->g_mfr, "Yaesu FTM-300D", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == ' ' && *plast == 'X') { strlcpy (A->g_mfr, "AP510", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if (*pfirst == '`' && *(plast-1) == ' ' && *plast == 'X') { strlcpy (A->g_mfr, "AP510", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '(' && *plast == '5') { strlcpy (A->g_mfr, "Anytone D578UV", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' ) { strlcpy (A->g_mfr, "Mic-Emsg", sizeof(A->g_mfr)); pfirst++; } else if (*pfirst == '`' && *(plast-1) == '(' && *plast == '5') { strlcpy (A->g_mfr, "Anytone D578UV", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' ) { strlcpy (A->g_mfr, "Generic Mic-Emsg", sizeof(A->g_mfr)); pfirst++; }
// ' should be used for trackers (not message capable).
else if (*pfirst == '\'' && *(plast-1) == '(' && *plast == '8') { strlcpy (A->g_mfr, "Anytone D878UV", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if (*pfirst == '\'' && *(plast-1) == '(' && *plast == '8') { strlcpy (A->g_mfr, "Anytone D878UV", sizeof(A->g_mfr)); pfirst++; plast-=2; }
@ -1412,13 +1423,13 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
else if (*pfirst == '\'' && *(plast-1) == ':' && *plast == '4') { strlcpy (A->g_mfr, "SCS GmbH & Co. P4dragon DR-7400 modems", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if (*pfirst == '\'' && *(plast-1) == ':' && *plast == '4') { strlcpy (A->g_mfr, "SCS GmbH & Co. P4dragon DR-7400 modems", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '\'' && *(plast-1) == ':' && *plast == '8') { strlcpy (A->g_mfr, "SCS GmbH & Co. P4dragon DR-7800 modems", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if (*pfirst == '\'' && *(plast-1) == ':' && *plast == '8') { strlcpy (A->g_mfr, "SCS GmbH & Co. P4dragon DR-7800 modems", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '\'' ) { strlcpy (A->g_mfr, "McTrackr", sizeof(A->g_mfr)); pfirst++; } else if (*pfirst == '\'' ) { strlcpy (A->g_mfr, "Generic McTrackr", sizeof(A->g_mfr)); pfirst++; }
else if ( *(plast-1) == '\\' ) { strlcpy (A->g_mfr, "Hamhud ?", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if ( *(plast-1) == '\\' ) { strlcpy (A->g_mfr, "Hamhud ?", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if ( *(plast-1) == '/' ) { strlcpy (A->g_mfr, "Argent ?", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if ( *(plast-1) == '/' ) { strlcpy (A->g_mfr, "Argent ?", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if ( *(plast-1) == '^' ) { strlcpy (A->g_mfr, "HinzTec anyfrog", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if ( *(plast-1) == '^' ) { strlcpy (A->g_mfr, "HinzTec anyfrog", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if ( *(plast-1) == '*' ) { strlcpy (A->g_mfr, "APOZxx www.KissOZ.dk Tracker. OZ1EKD and OZ7HVO", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if ( *(plast-1) == '*' ) { strlcpy (A->g_mfr, "APOZxx www.KissOZ.dk Tracker. OZ1EKD and OZ7HVO", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if ( *(plast-1) == '~' ) { strlcpy (A->g_mfr, "OTHER", sizeof(A->g_mfr)); pfirst++; plast-=2; } else if ( *(plast-1) == '~' ) { strlcpy (A->g_mfr, "Unknown OTHER", sizeof(A->g_mfr)); pfirst++; plast-=2; }
} }
/* /*
@ -3486,6 +3497,8 @@ time_t get_timestamp (decode_aprs_t *A, char *p)
time_t ts; time_t ts;
ts = time(NULL); ts = time(NULL);
// FIXME: use gmtime_r instead.
// Besides not being thread safe, gmtime could possibly return null.
ptm = gmtime(&ts); ptm = gmtime(&ts);
pdhm = (void *)p; pdhm = (void *)p;
@ -4211,9 +4224,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
dw_printf("%s:%d: %s\n", __FILE__, __LINE__, emsg); dw_printf("%s:%d: %s\n", __FILE__, __LINE__, emsg);
} }
// TODO: Would like to restrict to even length something like this: ([!-{][!-{]){2,7} e = regcomp (&base91_tel_re, "\\|(([!-{][!-{]){2,7})\\|", REG_EXTENDED);
e = regcomp (&base91_tel_re, "\\|([!-{]{4,14})\\|", REG_EXTENDED);
if (e) { if (e) {
regerror (e, &base91_tel_re, emsg, sizeof(emsg)); regerror (e, &base91_tel_re, emsg, sizeof(emsg));
dw_printf("%s:%d: %s\n", __FILE__, __LINE__, emsg); dw_printf("%s:%d: %s\n", __FILE__, __LINE__, emsg);
@ -4411,20 +4422,20 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
/* /*
* Telemetry data, in base 91 compressed format appears as 2 to 7 pairs * Telemetry data, in base 91 compressed format appears as 2 to 7 pairs
* of base 91 digits, surrounded by | at start and end. * of base 91 digits, ! thru {, surrounded by | at start and end.
*/ */
if (regexec (&base91_tel_re, A->g_comment, MAXMATCH, match, 0) == 0) if (regexec (&base91_tel_re, A->g_comment, MAXMATCH, match, 0) == 0)
{ {
char tdata[30]; /* Should be 4 to 14 characters. */ char tdata[30]; /* Should be even number of 4 to 14 characters. */
//dw_printf("compressed telemetry start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo)); //dw_printf("compressed telemetry start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo));
substr_se (tdata, A->g_comment, match[1].rm_so, match[1].rm_eo); substr_se (tdata, A->g_comment, match[1].rm_so, match[1].rm_eo);
//dw_printf("compressed telemetry data = \"%s\"\n", tdata); //dw_printf("compressed telemetry data = \"%s\"\n", tdata);
telemetry_data_base91 (A->g_src, tdata, A->g_telemetry, sizeof(A->g_telemetry)); telemetry_data_base91 (A->g_src, tdata, A->g_telemetry, sizeof(A->g_telemetry));
@ -4442,6 +4453,8 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
* *
* It surprised me to see this in a MIC-E message. * It surprised me to see this in a MIC-E message.
* MIC-E has resolution of .01 minute so it would make sense to have it as an option. * MIC-E has resolution of .01 minute so it would make sense to have it as an option.
* We also find an example in http://www.aprs.org/aprs12/mic-e-examples.txt
* 'abc123R/'123}FFF.FFFMHztext.../A=123456...!DAO! Mv
*/ */
if (regexec (&dao_re, A->g_comment, MAXMATCH, match, 0) == 0) if (regexec (&dao_re, A->g_comment, MAXMATCH, match, 0) == 0)
@ -4451,7 +4464,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
int a = A->g_comment[match[0].rm_so+2]; int a = A->g_comment[match[0].rm_so+2];
int o = A->g_comment[match[0].rm_so+3]; int o = A->g_comment[match[0].rm_so+3];
//dw_printf("start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo)); dw_printf("DAO start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo));
/* /*
@ -4503,7 +4516,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
*/ */
/* /*
* Here is an interesting case. * Here are a couple situations where it is seen.
* *
* W8SAT-1>T2UV0P:`qC<0x1f>l!Xu\'"69}WMNI EDS Response Unit #1|+/%0'n|!w:X!|3 * W8SAT-1>T2UV0P:`qC<0x1f>l!Xu\'"69}WMNI EDS Response Unit #1|+/%0'n|!w:X!|3
* *
@ -4520,13 +4533,26 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
* Comment earlier points out that MIC-E format has resolution of 0.01 minute, * Comment earlier points out that MIC-E format has resolution of 0.01 minute,
* same as non-compressed format, so the DAO does work out, after thinking * same as non-compressed format, so the DAO does work out, after thinking
* about it for a while. * about it for a while.
* We also find a MIC-E example with !DAO! here: http://www.aprs.org/aprs12/mic-e-examples.txt
*
* Another one:
*
* KS4FUN-12>3X0PRU,W6CX-3,BKELEY,WIDE2*:`2^=l!<0x1c>+/'"48}MT-RTG|%B%p'a|!wqR!|3
*
* MIC-E, Red Cross, Special
* N 38 00.2588, W 122 06.3354
* 0 MPH, course 100, alt 108 ft
* MT-RTG comment
* |%B%p'a| Seq=397, A1=443, A2=610
* !wqR! DAO
* |3 Byonics TinyTrack3
*
*/ */
/* /*
* The spec appears to be wrong. It says '}' is the maximum value when it should be '{'. * The spec appears to be wrong. It says '}' is the maximum value when it should be '{'.
*/ */
if (isdigit91(a)) { if (isdigit91(a)) {
A->g_lat += (a - B91_MIN) * 1.1 / 600000.0 * sign(A->g_lat); A->g_lat += (a - B91_MIN) * 1.1 / 600000.0 * sign(A->g_lat);
} }

View File

@ -1,7 +1,7 @@
// //
// This file is part of Dire Wolf, an amateur radio packet TNC. // This file is part of Dire Wolf, an amateur radio packet TNC.
// //
// Copyright (C) 2013, 2014, 2015, 2020 John Langner, WB2OSZ // Copyright (C) 2013, 2014, 2015, 2020, 2022 John Langner, WB2OSZ
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -60,7 +60,11 @@
// An incompatibility was introduced with version 7 // An incompatibility was introduced with version 7
// and again with 9 and again with 10. // and again with 9 and again with 10.
#if GPSD_API_MAJOR_VERSION < 5 || GPSD_API_MAJOR_VERSION > 11 // release lib version API Raspberry Pi OS
// 3.22 28 11 bullseye
// 3.23 29 12
#if GPSD_API_MAJOR_VERSION < 5 || GPSD_API_MAJOR_VERSION > 12
#error libgps API version might be incompatible. #error libgps API version might be incompatible.
#endif #endif
@ -364,6 +368,10 @@ static void * read_gpsd_thread (void *arg)
default: default:
case MODE_NOT_SEEN: case MODE_NOT_SEEN:
case MODE_NO_FIX: case MODE_NO_FIX:
if (info.fix <= DWFIX_NOT_SEEN) {
text_color_set(DW_COLOR_INFO);
dw_printf ("GPSD: No location fix.\n");
}
if (info.fix >= DWFIX_2D) { if (info.fix >= DWFIX_2D) {
text_color_set(DW_COLOR_INFO); text_color_set(DW_COLOR_INFO);
dw_printf ("GPSD: Lost location fix.\n"); dw_printf ("GPSD: Lost location fix.\n");

View File

@ -144,8 +144,6 @@ int dwgpsnmea_init (struct misc_config_s *pconfig, int debug)
/* /*
* Open serial port connection. * Open serial port connection.
* 4800 baud is standard for GPS.
* Should add an option to allow changing someday.
*/ */
s_gpsnmea_port_fd = serial_port_open (pconfig->gpsnmea_port, pconfig->gpsnmea_speed); s_gpsnmea_port_fd = serial_port_open (pconfig->gpsnmea_port, pconfig->gpsnmea_speed);
@ -264,9 +262,12 @@ static void * read_gpsnmea_thread (void *arg)
} }
dwgps_set_data (&info); dwgps_set_data (&info);
// TODO: doesn't exist yet - serial_port_close(fd); serial_port_close(s_gpsnmea_port_fd);
s_gpsnmea_port_fd = MYFDERROR; s_gpsnmea_port_fd = MYFDERROR;
// TODO: If the open() was in this thread, we could wait a while and
// try to open again. That would allow recovery if the USB GPS device
// is unplugged and plugged in again.
break; /* terminate thread. */ break; /* terminate thread. */
} }
@ -287,74 +288,53 @@ static void * read_gpsnmea_thread (void *arg)
} }
/* Process sentence. */ /* Process sentence. */
// FIXME: Ignore the second letter rather than recognizing only GP... and GN... // TODO: More general: Ignore the second letter rather than recognizing only GP... and GN...
if (strncmp(gps_msg, "$GPRMC", 6) == 0 || if (strncmp(gps_msg, "$GPRMC", 6) == 0 ||
strncmp(gps_msg, "$GNRMC", 6) == 0) { strncmp(gps_msg, "$GNRMC", 6) == 0) {
f = dwgpsnmea_gprmc (gps_msg, 0, &info.dlat, &info.dlon, &info.speed_knots, &info.track); // Here we just tuck away the course and speed.
// Fix and location will be updated by GxGGA.
double ignore_dlat;
double ignore_dlon;
f = dwgpsnmea_gprmc (gps_msg, 0, &ignore_dlat, &ignore_dlon, &info.speed_knots, &info.track);
if (f == DWFIX_ERROR) { if (f == DWFIX_ERROR) {
/* Parse error. Shouldn't happen. Better luck next time. */
/* Parse error. Shouldn't happen. Better luck next time. */ text_color_set(DW_COLOR_ERROR);
text_color_set(DW_COLOR_INFO);
dw_printf ("GPSNMEA: Error parsing $GPRMC sentence.\n"); dw_printf ("GPSNMEA: Error parsing $GPRMC sentence.\n");
dw_printf ("%s\n", gps_msg); dw_printf ("%s\n", gps_msg);
} }
else if (f == DWFIX_2D) {
if (info.fix != DWFIX_2D && info.fix != DWFIX_3D) {
text_color_set(DW_COLOR_INFO);
dw_printf ("GPSNMEA: Location fix is now available.\n");
info.fix = DWFIX_2D; // Don't know if 2D or 3D. Take minimum.
}
info.timestamp = time(NULL);
if (s_debug >= 2) {
text_color_set(DW_COLOR_DEBUG);
dwgps_print ("GPSNMEA: ", &info);
}
dwgps_set_data (&info);
}
else {
if (info.fix == DWFIX_2D || info.fix == DWFIX_3D) {
text_color_set(DW_COLOR_INFO);
dw_printf ("GPSNMEA: Lost location fix.\n");
}
info.fix = f; /* lost it. */
info.timestamp = time(NULL);
if (s_debug >= 2) {
text_color_set(DW_COLOR_DEBUG);
dwgps_print ("GPSNMEA: ", &info);
}
dwgps_set_data (&info);
}
} }
else if (strncmp(gps_msg, "$GPGGA", 6) == 0 || else if (strncmp(gps_msg, "$GPGGA", 6) == 0 ||
strncmp(gps_msg, "$GNGGA", 6) == 0) { strncmp(gps_msg, "$GNGGA", 6) == 0) {
int nsat; int nsat;
f = dwgpsnmea_gpgga (gps_msg, 0, &info.dlat, &info.dlon, &info.altitude, &nsat); f = dwgpsnmea_gpgga (gps_msg, 0, &info.dlat, &info.dlon, &info.altitude, &nsat);
/* Only switch between 2D & 3D. */
/* Let GPRMC handle other changes in fix state and data transfer. */
if (f == DWFIX_ERROR) { if (f == DWFIX_ERROR) {
/* Parse error. Shouldn't happen. Better luck next time. */ /* Parse error. Shouldn't happen. Better luck next time. */
text_color_set(DW_COLOR_INFO); text_color_set(DW_COLOR_ERROR);
dw_printf ("GPSNMEA: Error parsing $GPGGA sentence.\n"); dw_printf ("GPSNMEA: Error parsing $GPGGA sentence.\n");
dw_printf ("%s\n", gps_msg); dw_printf ("%s\n", gps_msg);
} }
else if ((f == DWFIX_3D && info.fix == DWFIX_2D) || else {
(f == DWFIX_2D && info.fix == DWFIX_3D)) { if (f != info.fix) { // Print change in location fix.
text_color_set(DW_COLOR_INFO); text_color_set(DW_COLOR_INFO);
dw_printf ("GPSNMEA: Location fix is now %dD.\n", (int)f); if (f == DWFIX_NO_FIX) dw_printf ("GPSNMEA: Location fix has been lost.\n");
info.fix = f; if (f == DWFIX_2D) dw_printf ("GPSNMEA: Location fix is now 2D.\n");
if (f == DWFIX_3D) dw_printf ("GPSNMEA: Location fix is now 3D.\n");
info.fix = f;
}
info.timestamp = time(NULL);
if (s_debug >= 2) {
text_color_set(DW_COLOR_DEBUG);
dwgps_print ("GPSNMEA: ", &info);
}
dwgps_set_data (&info);
} }
} }
} }
@ -445,9 +425,11 @@ static int remove_checksum (char *sent, int quiet)
* odlon longitude * odlon longitude
* oknots speed * oknots speed
* ocourse direction of travel. * ocourse direction of travel.
* *
* Left undefined if not valid. * Left undefined if not valid.
* *
* Note: RMC does not contain altitude.
*
* Returns: DWFIX_ERROR Parse error. * Returns: DWFIX_ERROR Parse error.
* DWFIX_NO_FIX GPS is there but Position unknown. Could be temporary. * DWFIX_NO_FIX GPS is there but Position unknown. Could be temporary.
* DWFIX_2D Valid position. We don't know if it is really 2D or 3D. * DWFIX_2D Valid position. We don't know if it is really 2D or 3D.
@ -597,10 +579,13 @@ dwfix_t dwgpsnmea_gprmc (char *sentence, int quiet, double *odlat, double *odlon
* *
* Left undefined if not valid. * Left undefined if not valid.
* *
* Note: GGA has altitude but not course and speed so we need to use both.
*
* Returns: DWFIX_ERROR Parse error. * Returns: DWFIX_ERROR Parse error.
* DWFIX_NO_FIX GPS is there but Position unknown. Could be temporary. * DWFIX_NO_FIX GPS is there but Position unknown. Could be temporary.
* DWFIX_2D Valid position. We don't know if it is really 2D or 3D. * DWFIX_2D Valid position. We don't know if it is really 2D or 3D.
* Take more cautious value so we don't try using altitude. * Take more cautious value so we don't try using altitude.
* DWFIX_3D Valid 3D position.
* *
* Examples: $GPGGA,001429.00,,,,,0,00,99.99,,,,,,*68 * Examples: $GPGGA,001429.00,,,,,0,00,99.99,,,,,,*68
* $GPGGA,212407.000,4237.1505,N,07120.8602,W,0,00,,,M,,M,,*58 * $GPGGA,212407.000,4237.1505,N,07120.8602,W,0,00,,,M,,M,,*58
@ -609,9 +594,6 @@ dwfix_t dwgpsnmea_gprmc (char *sentence, int quiet, double *odlat, double *odlon
* *
*--------------------------------------------------------------------*/ *--------------------------------------------------------------------*/
// TODO: in progress...
dwfix_t dwgpsnmea_gpgga (char *sentence, int quiet, double *odlat, double *odlon, float *oalt, int *onsat) dwfix_t dwgpsnmea_gpgga (char *sentence, int quiet, double *odlat, double *odlon, float *oalt, int *onsat)
{ {
char stemp[NMEA_MAX_LEN]; /* Make copy because parsing is destructive. */ char stemp[NMEA_MAX_LEN]; /* Make copy because parsing is destructive. */
@ -708,8 +690,7 @@ dwfix_t dwgpsnmea_gpgga (char *sentence, int quiet, double *odlat, double *odlon
return (DWFIX_ERROR); return (DWFIX_ERROR);
} }
// TODO: num sat... Why would we care?
// TODO: num sat...
/* /*
* We can distinguish between 2D & 3D fix by presence * We can distinguish between 2D & 3D fix by presence