mirror of https://github.com/wb2osz/direwolf.git
gpsd 3.23 (API 12) compatibility and cleanups.
This commit is contained in:
parent
5dbe2ce136
commit
42314b7219
|
@ -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 ##
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -1377,10 +1377,15 @@ 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++; }
|
||||||
|
|
||||||
else if (*pfirst == '>' && *plast == '=') { strlcpy (A->g_mfr, "Kenwood TH-D72", sizeof(A->g_mfr)); pfirst++; plast--; }
|
else if (*pfirst == '>' && *plast == '=') { strlcpy (A->g_mfr, "Kenwood TH-D72", sizeof(A->g_mfr)); pfirst++; plast--; }
|
||||||
|
@ -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,14 +4422,14 @@ 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));
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
12
src/dwgpsd.c
12
src/dwgpsd.c
|
@ -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");
|
||||||
|
|
|
@ -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,75 +288,54 @@ 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_INFO);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
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");
|
||||||
|
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.fix = f;
|
||||||
}
|
}
|
||||||
|
info.timestamp = time(NULL);
|
||||||
|
if (s_debug >= 2) {
|
||||||
|
text_color_set(DW_COLOR_DEBUG);
|
||||||
|
dwgps_print ("GPSNMEA: ", &info);
|
||||||
|
}
|
||||||
|
dwgps_set_data (&info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,6 +428,8 @@ static int remove_checksum (char *sent, int quiet)
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|
Loading…
Reference in New Issue