Fix ttgrid corner and various cleanups.

This commit is contained in:
wb2osz 2022-02-25 22:29:07 +00:00
parent 4f6ca0d389
commit e108147655
14 changed files with 270 additions and 92 deletions

View File

@ -1283,13 +1283,26 @@ static int parse_location (char *e)
lat0 = tt_config.ttloc_ptr[ipat].grid.lat0;
lat9 = tt_config.ttloc_ptr[ipat].grid.lat9;
double yrange = lat9 - lat0;
y = atof(ystr);
m_latitude = lat0 + y * (lat9-lat0) / (pow(10., strlen(ystr)) - 1.);
double user_y_max = round(pow(10., strlen(ystr)) - 1.); // e.g. 999 for 3 digits
m_latitude = lat0 + yrange * y / user_y_max;
#if 0
dw_printf ("TTLOC_GRID LAT min=%f, max=%f, range=%f\n", lat0, lat9, yrange);
dw_printf ("TTLOC_GRID LAT user_y=%f, user_y_max=%f\n", y, user_y_max);
dw_printf ("TTLOC_GRID LAT min + yrange * user_y / user_y_range = %f\n", m_latitude);
#endif
lon0 = tt_config.ttloc_ptr[ipat].grid.lon0;
lon9 = tt_config.ttloc_ptr[ipat].grid.lon9;
double xrange = lon9 - lon0;
x = atof(xstr);
m_longitude = lon0 + x * (lon9-lon0) / (pow(10., strlen(xstr)) - 1.);
double user_x_max = round(pow(10., strlen(xstr)) - 1.);
m_longitude = lon0 + xrange * x / user_x_max;
#if 0
dw_printf ("TTLOC_GRID LON min=%f, max=%f, range=%f\n", lon0, lon9, xrange);
dw_printf ("TTLOC_GRID LON user_x=%f, user_x_max=%f\n", x, user_x_max);
dw_printf ("TTLOC_GRID LON min + xrange * user_x / user_x_range = %f\n", m_longitude);
#endif
m_dao[2] = e[0];
m_dao[3] = e[1];
@ -1972,6 +1985,7 @@ static const struct {
/* Latitude comes out ok, 37.9137 -> 55.82 min. */
/* Longitude -81.1254 -> 8.20 min */
{ "B21234*A67979#", "679", "12", "7A", "", "", "12.3400", "56.1200", "!TB2!" },
{ "B533686*A67979#", "679", "12", "7A", "", "", "37.9222", "81.1143", "!TB5!" },
// TODO: should test other coordinate systems.

View File

@ -886,7 +886,7 @@ void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alev
decode_aprs_t A;
decode_aprs (&A, pp, 0);
decode_aprs (&A, pp, 0, 0);
// Temp experiment to see how different systems set the RR bits in the source and destination.
// log_rr_bits (&A, pp);

View File

@ -350,8 +350,9 @@ void ax25_delete (packet_t this_p)
* strict - True to enforce rules for packets sent over the air.
* False to be more lenient for packets from IGate server.
*
* Messages from an IGate server can have longer
* addresses after qAC. Up to 9 observed so far.
* Packets from an IGate server can have longer
* addresses after qAC. Up to 9 observed so far.
* The SSID can be 2 alphanumeric characters, not just 1 to 15.
*
* We can just truncate the name because we will only
* end up discarding it. TODO: check on this.
@ -740,6 +741,7 @@ packet_t ax25_dup (packet_t copy_from)
* alphanumeric characters for the SSID.
* We also get messages like this from a server.
* KB1POR>APU25N,TCPIP*,qAC,T2NUENGLD:...
* K1BOS-B>APOSB,TCPIP,WR2X-2*:...
*
* 2 (extra true) will complain if * is found at end.
*
@ -1983,6 +1985,7 @@ void ax25_format_addrs (packet_t this_p, char *result)
}
ax25_get_addr_with_ssid (this_p, AX25_SOURCE, stemp);
// FIXME: For ALL strcat: Pass in sizeof result and use strlcat.
strcat (result, stemp);
strcat (result, ">");

View File

@ -2397,10 +2397,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,
*/
/*
* DIGIPEAT from-chan to-chan alias-pattern wide-pattern [ OFF|DROP|MARK|TRACE | NOID=alias ]
* DIGIPEAT from-chan to-chan alias-pattern wide-pattern [ OFF|DROP|MARK|TRACE | ATGP=alias ]
*
* NOID is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters.
* The via path starts out as HOP7-7,HOP7-7 and we do not want tracing so it does not fill up.
* ATGP is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters.
* DO NOT put this in the User Guide. On a need to know basis.
*/
@ -2527,8 +2526,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
p_digi_config->preempt[from_chan][to_chan] = PREEMPT_TRACE;
t = split(NULL,0);
}
else if (strncasecmp(t, "NOID=", 5) == 0) {
strlcpy (p_digi_config->noid[from_chan][to_chan], t+5, sizeof(p_digi_config->noid[from_chan][to_chan]));;
else if (strncasecmp(t, "ATGP=", 5) == 0) {
strlcpy (p_digi_config->atgp[from_chan][to_chan], t+5, sizeof(p_digi_config->atgp[from_chan][to_chan]));;
t = split(NULL,0);
}
}
@ -3221,7 +3220,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
t = split(NULL,0);
if (t == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Missing latitude for TTGRID command.\n", line);
dw_printf ("Line %d: Missing minimum latitude for TTGRID command.\n", line);
continue;
}
tl->grid.lat0 = parse_ll(t,LAT,line);
@ -3231,7 +3230,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
t = split(NULL,0);
if (t == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Missing longitude for TTGRID command.\n", line);
dw_printf ("Line %d: Missing minimum longitude for TTGRID command.\n", line);
continue;
}
tl->grid.lon0 = parse_ll(t,LON,line);
@ -3241,7 +3240,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
t = split(NULL,0);
if (t == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Missing latitude for TTGRID command.\n", line);
dw_printf ("Line %d: Missing maximum latitude for TTGRID command.\n", line);
continue;
}
tl->grid.lat9 = parse_ll(t,LAT,line);
@ -3251,13 +3250,16 @@ void config_init (char *fname, struct audio_s *p_audio_config,
t = split(NULL,0);
if (t == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Missing longitude for TTGRID command.\n", line);
dw_printf ("Line %d: Missing maximum longitude for TTGRID command.\n", line);
continue;
}
tl->grid.lon0 = parse_ll(t,LON,line);
tl->grid.lon9 = parse_ll(t,LON,line);
/* temp debugging */
// dw_printf ("CONFIG TTGRID min %f %f\n", tl->grid.lat0, tl->grid.lon0);
// dw_printf ("CONFIG TTGRID max %f %f\n", tl->grid.lat9, tl->grid.lon9);
//for (j=0; j<p_tt_config->ttloc_len; j++) {
// dw_printf ("debug ttloc %d/%d %s\n", j, p_tt_config->ttloc_size,
// p_tt_config->ttloc_ptr[j].pattern);

View File

@ -1,7 +1,7 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2017 John Langner, WB2OSZ
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2017, 2022 John Langner, WB2OSZ
//
// 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
@ -140,6 +140,11 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen);
*
* quiet - Suppress error messages.
*
* third_party - True when parsing a third party header.
* (decode_aprs is called recursively.)
* This is mostly found when an IGate transmits a message
* that came via APRS-IS.
*
* Outputs: A-> g_symbol_table, g_symbol_code,
* g_lat, g_lon,
* g_speed_mph, g_course, g_altitude_ft,
@ -151,16 +156,19 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen);
*
*------------------------------------------------------------------*/
void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, int third_party)
{
//dw_printf ("DEBUG decode_aprs quiet=%d, third_party=%d\n", quiet, third_party);
char dest[AX25_MAX_ADDR_LEN];
//char dest[AX25_MAX_ADDR_LEN];
unsigned char *pinfo;
int info_len;
info_len = ax25_get_info (pp, &pinfo);
//dw_printf ("DEBUG decode_aprs info=\"%s\"\n", pinfo);
memset (A, 0, sizeof (*A));
A->g_quiet = quiet;
@ -200,16 +208,26 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
if (*pinfo == '}') {
//dw_printf ("DEBUG decode_aprs recursively process third party header\n");
// This must not be strict because the addresses in third party payload doesn't
// need to adhere to the AX.25 address format (i.e. 6 upper case alphanumeric.)
// SSID can be 2 alphanumeric characters.
// Addresses can include lower case, e.g. q contruct.
// e.g. WR2X-2>APRS,WA1PLE-13*:}
// K1BOS-B>APOSB,TCPIP,WR2X-2*:@122015z4221.42ND07111.93W&/A=000000SharkRF openSPOT3 MMDVM446.025 MA/SW
packet_t pp_payload = ax25_from_text ((char*)pinfo+1, 0);
if (pp_payload != NULL) {
decode_aprs (A, pp_payload, quiet);
decode_aprs (A, pp_payload, quiet, 1); // 1 means used recursively
ax25_delete (pp_payload);
return;
}
else {
strlcpy (A->g_msg_type, "Third Party Header: Unable to parse payload.", sizeof(A->g_msg_type));
ax25_get_addr_with_ssid (pp, AX25_SOURCE, A->g_src);
ax25_get_addr_with_ssid (pp, AX25_DESTINATION, dest);
ax25_get_addr_with_ssid (pp, AX25_DESTINATION, A->g_dest);
}
}
@ -218,7 +236,10 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
*/
ax25_get_addr_with_ssid (pp, AX25_SOURCE, A->g_src);
ax25_get_addr_with_ssid (pp, AX25_DESTINATION, dest);
ax25_get_addr_with_ssid (pp, AX25_DESTINATION, A->g_dest);
//dw_printf ("DEBUG decode_aprs source=%s, dest=%s\n", A->g_src, A->g_dest);
/*
* Report error if the information part contains a nul character.
@ -260,7 +281,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
break;
default:
decode_tocall (A, dest);
decode_tocall (A, A->g_dest);
break;
}
@ -316,7 +337,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
break;
case ':': /* Message: for one person, a group, or a bulletin. */
case ':': /* "Message" (special APRS meaning): for one person, a group, or a bulletin. */
/* Directed Station Query */
/* Telemetry metadata. */
@ -402,7 +423,17 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
if (A->g_symbol_table == ' ' || A->g_symbol_code == ' ') {
symbols_from_dest_or_src (*pinfo, A->g_src, dest, &A->g_symbol_table, &A->g_symbol_code);
// A symbol on a "message" makes no sense and confuses people.
// Third party too. Set from the payload.
// Maybe eliminate for a couple others.
//dw_printf ("DEBUG decode_aprs@end1 third_party=%d, symbol_table=%c, symbol_code=%c, *pinfo=%c\n", third_party, A->g_symbol_table, A->g_symbol_code, *pinfo);
if (*pinfo != ':' && *pinfo != '}') {
symbols_from_dest_or_src (*pinfo, A->g_src, A->g_dest, &A->g_symbol_table, &A->g_symbol_code);
}
//dw_printf ("DEBUG decode_aprs@end2 third_party=%d, symbol_table=%c, symbol_code=%c, *pinfo=%c\n", third_party, A->g_symbol_table, A->g_symbol_code, *pinfo);
}
} /* end decode_aprs */
@ -410,8 +441,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
void decode_aprs_print (decode_aprs_t *A) {
char stemp[200];
//char tmp2[2];
char stemp[500];
double absll;
char news;
int deg;
@ -419,11 +449,10 @@ void decode_aprs_print (decode_aprs_t *A) {
char s_lat[30];
char s_lon[30];
int n;
char symbol_description[100];
/*
* First line has:
* - message type
* - packet type
* - object name
* - symbol
* - manufacturer/application
@ -432,28 +461,53 @@ void decode_aprs_print (decode_aprs_t *A) {
*/
strlcpy (stemp, A->g_msg_type, sizeof(stemp));
//dw_printf ("DEBUG decode_aprs_print stemp1=%s\n", stemp);
if (strlen(A->g_name) > 0) {
strlcat (stemp, ", \"", sizeof(stemp));
strlcat (stemp, A->g_name, sizeof(stemp));
strlcat (stemp, "\"", sizeof(stemp));
}
//dw_printf ("DEBUG decode_aprs_print stemp2=%s\n", stemp);
//dw_printf ("DEBUG decode_aprs_print symbol_code=%c=0x%02x\n", A->g_symbol_code, A->g_symbol_code);
if (A->g_symbol_code != ' ') {
symbols_get_description (A->g_symbol_table, A->g_symbol_code, symbol_description, sizeof(symbol_description));
char symbol_description[100];
symbols_get_description (A->g_symbol_table, A->g_symbol_code, symbol_description, sizeof(symbol_description));
//dw_printf ("DEBUG decode_aprs_print symbol_description_description=%s\n", symbol_description);
strlcat (stemp, ", ", sizeof(stemp));
strlcat (stemp, symbol_description, sizeof(stemp));
}
//dw_printf ("DEBUG decode_aprs_print stemp3=%s mfr=%s\n", stemp, A->g_mfr);
if (strlen(A->g_mfr) > 0) {
strlcat (stemp, ", ", sizeof(stemp));
strlcat (stemp, A->g_mfr, sizeof(stemp));
if (strcmp(A->g_dest, "APRS") == 0) {
strlcat (stemp, "\nUse of \"APRS\" in the destination field is obsolete.", sizeof(stemp));
strlcat (stemp, " You can help to improve the quality of APRS signals.", sizeof(stemp));
strlcat (stemp, "\nTell the sender (", sizeof(stemp));
strlcat (stemp, A->g_src, sizeof(stemp));
strlcat (stemp, ") to use the proper product code from", sizeof(stemp));
strlcat (stemp, " http://www.aprs.org/aprs11/tocalls.txt", sizeof(stemp));
}
else {
strlcat (stemp, ", ", sizeof(stemp));
strlcat (stemp, A->g_mfr, sizeof(stemp));
}
}
//dw_printf ("DEBUG decode_aprs_print stemp4=%s\n", stemp);
if (strlen(A->g_mic_e_status) > 0) {
strlcat (stemp, ", ", sizeof(stemp));
strlcat (stemp, A->g_mic_e_status, sizeof(stemp));
}
//dw_printf ("DEBUG decode_aprs_print stemp5=%s\n", stemp);
if (A->g_power > 0) {
char phg[100];
@ -1120,7 +1174,7 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
char sym_table_id;
} *p;
char dest[10];
char dest[12];
int ch;
int n;
int offset;
@ -1379,7 +1433,7 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
// Last Updated Dec. 2021
// This does not change very often but I'm wondering if we could simply parse
// This does not change very often but I'm wondering if we could parse
// http://www.aprs.org/aprs12/mic-e-types.txt similar to how we use tocalls.txt.
if (isT(*pfirst)) {
@ -1511,13 +1565,18 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
* :xxxxxxxxx:EQNS. Telemetry metadata, Equation Coefficients
* :xxxxxxxxx:BITS. Telemetry metadata, Bit Sense/Project Name
* :xxxxxxxxx:? Directed Station Query
* :xxxxxxxxx:ack Message acknowledged (received)
* :xxxxxxxxx:rej Message rejected (unable to accept)
* :xxxxxxxxx:ackNNNN Message acknowledged (received)
* :xxxxxxxxx:rejNNNNN Message rejected (unable to accept)
*
* :xxxxxxxxx: ... Message with no message number.
* (Text may not contain the { character because
* it indicates beginning of optional message number.)
* :xxxxxxxxx: ... {num Message with message number.
* :xxxxxxxxx: ... {NNNNN Message with message number, 1 to 5 alphanumeric.
* :xxxxxxxxx: ... {mm} Message with new style message number.
* :xxxxxxxxx: ... {mm}aa Message with new style message number and ack.
*
*
* Reference: See new message id style: http://www.aprs.org/aprs11/replyacks.txt
*
*------------------------------------------------------------------*/
@ -1528,8 +1587,10 @@ static void aprs_message (decode_aprs_t *A, unsigned char *info, int ilen, int q
char dti; /* : */
char addressee[9];
char colon; /* : */
char message[73]; /* 0-67 characters for message */
/* Optional { followed by 1-5 characters for message number */
char message[256-1-9-1]; /* Officially up to 67 characters for message text. */
/* Relaxing seemingly arbitrary restriction here; it doesn't need to fit on a punched card. */
/* Wouldn't surprize me if others did not pay attention to the limit. */
/* Optional { followed by 1-5 alphanumeric characters for message number */
/* If the first character is '?' it is a Directed Station Query. */
} *p;
@ -1651,25 +1712,84 @@ static void aprs_message (decode_aprs_t *A, unsigned char *info, int ilen, int q
/* ack or rej? Message number is required for these. */
else if (strncmp(p->message,"ack",3) == 0) {
else if (strncasecmp(p->message,"ack",3) == 0) {
if (strncmp(p->message,"ack",3) != 0) {
text_color_set(DW_COLOR_ERROR);
dw_printf("ERROR: \"%s\" must be lower case \"ack\"\n", p->message);
}
strlcpy (A->g_message_number, p->message + 3, sizeof(A->g_message_number));
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "ACK message %s for \"%s\"", A->g_message_number, addressee);
if (strlen(A->g_message_number) == 0) {
text_color_set(DW_COLOR_ERROR);
dw_printf("ERROR: Message number is missing after \"ack\".\n");
}
if (strlen(A->g_message_number) >= 3 && A->g_message_number[2] == '}') A->g_message_number[2] = '\0';
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "\"%s\" ACKnowledged message number \"%s\" from \"%s\"", A->g_src, A->g_message_number, addressee);
A->g_message_subtype = message_subtype_ack;
}
else if (strncmp(p->message,"rej",3) == 0) {
else if (strncasecmp(p->message,"rej",3) == 0) {
if (strncmp(p->message,"rej",3) != 0) {
text_color_set(DW_COLOR_ERROR);
dw_printf("ERROR: \"%s\" must be lower case \"rej\"\n", p->message);
}
strlcpy (A->g_message_number, p->message + 3, sizeof(A->g_message_number));
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "REJ message %s for \"%s\"", A->g_message_number, addressee);
if (strlen(A->g_message_number) == 0) {
text_color_set(DW_COLOR_ERROR);
dw_printf("ERROR: Message number is missing after \"rej\".\n");
}
if (strlen(A->g_message_number) >= 3 && A->g_message_number[2] == '}') A->g_message_number[2] = '\0';
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "\"%s\" REJected message number \"%s\" from \"%s\"", A->g_src, A->g_message_number, addressee);
A->g_message_subtype = message_subtype_ack;
}
/* message number is optional here. */
// Message to a particular station or a bulletin.
// message number is optional here.
// Test cases. Wrap in third party too.
// A>B::WA1XYX-15:Howdy y'all
// A>B::WA1XYX-15:Howdy y'all{12345
// A>B::WA1XYX-15:Howdy y'all{12}
// A>B::WA1XYX-15:Howdy y'all{12}34
// A>B::WA1XYX-15:Howdy y'all{toolong
// X>Y:}A>B::WA1XYX-15:Howdy y'all
// X>Y:}A>B::WA1XYX-15:Howdy y'all{12345
// X>Y:}A>B::WA1XYX-15:Howdy y'all{12}
// X>Y:}A>B::WA1XYX-15:Howdy y'all{12}34
// X>Y:}A>B::WA1XYX-15:Howdy y'all{toolong
else {
// Look for message number.
char *pno = strchr(p->message, '{');
if (pno != NULL) {
*pno = '\0';
int mlen = strlen(pno+1);
if (mlen < 1 || mlen > 5) {
text_color_set(DW_COLOR_ERROR);
dw_printf("Message number \"%s\" has length outside range of 1 to 5.\n", pno+1);
}
strlcpy (A->g_message_number, pno+1, sizeof(A->g_message_number));
// TODO: Complain if not alphanumeric.
char ack[8] = "";
if (mlen >= 3 && A->g_message_number[2] == '}') {
// New (1999) style.
A->g_message_number[2] = '\0';
strlcpy (ack, A->g_message_number + 3, sizeof(ack));
}
if (strlen(ack) > 0) {
// With ACK. Message number should be 2 characters.
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message, number \"%s\", from \"%s\" to \"%s\", with ACK for \"%s\"", A->g_message_number, A->g_src, addressee, ack);
}
else {
// Message number can be 1-5 characters.
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message, number \"%s\", from \"%s\" to \"%s\"", A->g_message_number, A->g_src, addressee);
}
}
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message %s for \"%s\"", A->g_message_number, addressee);
else {
// No message number.
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message, with no number, from \"%s\" to \"%s\"", A->g_src, addressee);
}
A->g_message_subtype = message_subtype_message;
/* No location so don't use process_comment () */
@ -2389,10 +2509,12 @@ static void aprs_telemetry (decode_aprs_t *A, char *info, int ilen, int quiet)
static void aprs_user_defined (decode_aprs_t *A, char *info, int ilen)
{
if (strncmp(info, "{tt", 3) == 0) { // Historical. Should probably use DT.
if (strncmp(info, "{tt", 3) == 0 || // Historical.
strncmp(info, "{DT", 3) == 0) { // Official after registering {D*
aprs_raw_touch_tone (A, info, ilen);
}
else if (strncmp(info, "{mc", 3) == 0) { // Historical. Should probably use DM.
else if (strncmp(info, "{mc", 3) == 0 || // Historical.
strncmp(info, "{DM", 3) == 0) { // Official after registering {D*
aprs_morse_code (A, info, ilen);
}
else if (info[0] == '{' && info[1] == USER_DEF_USER_ID && info[2] == USER_DEF_TYPE_AIS) {
@ -4993,7 +5115,7 @@ int main (int argc, char *argv[])
ax25_safe_print ((char *)pinfo, info_len, 1); // Display non-ASCII to hexadecimal.
dw_printf ("\n");
decode_aprs (&A, pp, 0); // Extract information into structure.
decode_aprs (&A, pp, 0, 0); // Extract information into structure.
decode_aprs_print (&A); // Now print it in human readable format.
@ -5014,7 +5136,7 @@ int main (int argc, char *argv[])
if (pp != NULL) {
decode_aprs_t A;
decode_aprs (&A, pp, 0); // Extract information into structure.
decode_aprs (&A, pp, 0, 0); // Extract information into structure.
decode_aprs_print (&A); // Now print it in human readable format.

View File

@ -26,9 +26,11 @@ typedef struct decode_aprs_s {
char g_src[AX25_MAX_ADDR_LEN];
char g_msg_type[60]; /* APRS data type. Telemetry descriptions get pretty long. */
char g_dest[AX25_MAX_ADDR_LEN];
char g_msg_type[80]; /* APRS data type description. Telemetry descriptions get pretty long. */
/* Putting msg in the name was a poor choice because */
/* "message" has a specific meaning. Rename it someday. */
/* "message" has a specific meaning. Rename it to data_type someday. FIXME */
char g_symbol_table; /* The Symbol Table Identifier character selects one */
/* of the two Symbol Tables, or it may be used as */
@ -77,7 +79,9 @@ typedef struct decode_aprs_s {
message_subtype_directed_query
} g_message_subtype; /* Various cases of the overloaded "message." */
char g_message_number[8]; /* Message number. Should be 1 - 5 characters if used. */
char g_message_number[8]; /* Message number. Should be 1 - 5 alphanumeric characters if used. */
/* Addendum 1.1 has new format {mm} or {mm}aa with only two */
/* characters for message number and an ack riding piggyback. */
float g_speed_mph; /* Speed in MPH. */
/* The APRS transmission uses knots so watch out for */
@ -140,7 +144,7 @@ typedef struct decode_aprs_s {
extern void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet);
extern void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, int third_party);
extern void decode_aprs_print (decode_aprs_t *A);

View File

@ -73,7 +73,7 @@
static packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, char *mycall_xmit,
regex_t *uidigi, regex_t *uitrace, int to_chan, enum preempt_e preempt, char *noid, char *type_filter);
regex_t *uidigi, regex_t *uitrace, int to_chan, enum preempt_e preempt, char *atgp, char *type_filter);
/*
@ -176,7 +176,7 @@ void digipeater (int from_chan, packet_t pp)
save_audio_config_p->achan[to_chan].mycall,
&save_digi_config_p->alias[from_chan][to_chan], &save_digi_config_p->wide[from_chan][to_chan],
to_chan, save_digi_config_p->preempt[from_chan][to_chan],
save_digi_config_p->noid[from_chan][to_chan],
save_digi_config_p->atgp[from_chan][to_chan],
save_digi_config_p->filter_str[from_chan][to_chan]);
if (result != NULL) {
dedupe_remember (pp, to_chan);
@ -203,7 +203,7 @@ void digipeater (int from_chan, packet_t pp)
save_audio_config_p->achan[to_chan].mycall,
&save_digi_config_p->alias[from_chan][to_chan], &save_digi_config_p->wide[from_chan][to_chan],
to_chan, save_digi_config_p->preempt[from_chan][to_chan],
save_digi_config_p->noid[from_chan][to_chan],
save_digi_config_p->atgp[from_chan][to_chan],
save_digi_config_p->filter_str[from_chan][to_chan]);
if (result != NULL) {
dedupe_remember (pp, to_chan);
@ -246,7 +246,7 @@ void digipeater (int from_chan, packet_t pp)
*
* preempt - Option for "preemptive" digipeating.
*
* noid - No tracing if this matches alias prefix.
* atgp - No tracing if this matches alias prefix.
* Hack added for special needs of ATGP.
*
* filter_str - Filter expression string or NULL.
@ -267,7 +267,7 @@ void digipeater (int from_chan, packet_t pp)
static packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, char *mycall_xmit,
regex_t *alias, regex_t *wide, int to_chan, enum preempt_e preempt, char *noid, char *filter_str)
regex_t *alias, regex_t *wide, int to_chan, enum preempt_e preempt, char *atgp, char *filter_str)
{
char source[AX25_MAX_ADDR_LEN];
int ssid;
@ -483,22 +483,34 @@ static packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, ch
err = regexec(wide,repeater,0,NULL,0);
if (err == 0) {
// Special hack added for ATGP to behave like UIFLOOD NOID in some TNCs.
// More than 8 digipeater hops are required so tracing is disabled.
// Special hack added for ATGP to behave like some combination of options in some old TNC
// so the via path does not continue to grow and exceed the 8 available positions.
if (strlen(noid) > 0 && strncasecmp(repeater, noid, strlen(noid)) == 0) {
if (strlen(atgp) > 0 && strncasecmp(repeater, atgp, strlen(atgp)) == 0) {
if (ssid >= 1 && ssid <= 7) {
packet_t result;
// Usual routine for digipeater.
result = ax25_dup (pp);
assert (result != NULL);
if (ssid == 1) {
ssid = ssid - 1;
ax25_set_ssid(result, r, ssid); // could be zero.
if (ssid == 0) {
ax25_set_h (result, r);
}
ax25_set_ssid(result, r, ssid-1); // could be zero.
// Now remove all used digi addresses, insert own, and mark it used.
///////////////////////////////////////////// LOOK HERE/////////////////////////////////////////////
while (ax25_get_num_addr(result) >= 3 && ax25_get_h(result,AX25_REPEATER_1) == 1) {
ax25_remove_addr (result, AX25_REPEATER_1);
}
ax25_insert_addr (result, AX25_REPEATER_1, mycall_xmit);
ax25_set_h (result, AX25_REPEATER_1);
return (result);
}
}
@ -620,7 +632,7 @@ static int failed;
static enum preempt_e preempt = PREEMPT_OFF;
static char config_noid[AX25_MAX_ADDR_LEN] = "HOP";
static char config_atgp[AX25_MAX_ADDR_LEN] = "HOP";
static void test (char *in, char *out)
@ -686,7 +698,7 @@ static void test (char *in, char *out)
//TODO: Add filtering to test.
// V
result = digipeat_match (0, pp, mycall, mycall, &alias_re, &wide_re, 0, preempt, config_noid, NULL);
result = digipeat_match (0, pp, mycall, mycall, &alias_re, &wide_re, 0, preempt, config_atgp, NULL);
if (result != NULL) {
@ -928,18 +940,18 @@ int main (int argc, char *argv[])
preempt = PREEMPT_OFF; // Shouldn't make a difference here.
test ( "W1ABC>TEST51,HOP7-7,HOP7-7:stuff1",
"W1ABC>TEST51,HOP7-6,HOP7-7:stuff1");
"W1ABC>TEST51,WB2OSZ-9*,HOP7-6,HOP7-7:stuff1");
test ( "W1ABC>TEST52,HOP7-1,HOP7-7:stuff2",
"W1ABC>TEST52,HOP7*,HOP7-7:stuff2");
test ( "W1ABC>TEST52,ABCD*,HOP7-1,HOP7-7:stuff2",
"W1ABC>TEST52,WB2OSZ-9*,HOP7-7:stuff2");
test ( "W1ABC>TEST52,HOP7*,HOP7-7:stuff3",
"W1ABC>TEST52,HOP7*,HOP7-6:stuff3");
"W1ABC>TEST52,WB2OSZ-9*,HOP7-6:stuff3");
test ( "W1ABC>TEST52,HOP7*,HOP7-1:stuff4",
"W1ABC>TEST52,HOP7,HOP7*:stuff4");
"W1ABC>TEST52,WB2OSZ-9*:stuff4");
test ( "W1ABC>TEST52,HOP7,HOP7*:stuff",
test ( "W1ABC>TEST52,HOP7,HOP7*:stuff5",
"");

View File

@ -1,5 +1,4 @@
#ifndef DIGIPEATER_H
#define DIGIPEATER_H 1
@ -38,11 +37,10 @@ struct digi_config_s {
enum preempt_e { PREEMPT_OFF, PREEMPT_DROP, PREEMPT_MARK, PREEMPT_TRACE } preempt[MAX_CHANS][MAX_CHANS];
// NOID is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters.
// The via path starts out as HOP7-7,HOP7-7 and we do not want tracing so it does not fill up.
// ATGP is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters.
// DO NOT put this in the User Guide. On a need to know basis.
char noid[MAX_CHANS][MAX_CHANS][AX25_MAX_ADDR_LEN];
char atgp[MAX_CHANS][MAX_CHANS][AX25_MAX_ADDR_LEN];
char *filter_str[MAX_CHANS+1][MAX_CHANS+1];
// NULL or optional Packet Filter strings such as "t/m".

View File

@ -299,7 +299,7 @@ int main (int argc, char *argv[])
text_color_init(t_opt);
text_color_set(DW_COLOR_INFO);
//dw_printf ("Dire Wolf version %d.%d (%s) Beta Test 4\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "D", __DATE__);
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "E", __DATE__);
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
@ -322,6 +322,7 @@ int main (int argc, char *argv[])
#if __WIN32__
//setlinebuf (stdout); setvbuf???
SetConsoleCtrlHandler ((PHANDLER_ROUTINE)cleanup_win, TRUE);
#else
setlinebuf (stdout);
@ -1425,7 +1426,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
// we still want to decode it for logging and other processing.
// Just be quiet about errors if "-qd" is set.
decode_aprs (&A, pp, q_d_opt);
decode_aprs (&A, pp, q_d_opt, 0);
if ( ! q_d_opt ) {

View File

@ -410,19 +410,25 @@ struct rs *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigne
return NULL; /* Can't have more roots than symbol values! */
rs = (struct rs *)calloc(1,sizeof(struct rs));
if (rs == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("FATAL ERROR: Out of memory.\n");
exit (EXIT_FAILURE);
}
rs->mm = symsize;
rs->nn = (1<<symsize)-1;
rs->alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1));
rs->alpha_to = (DTYPE *)calloc((rs->nn+1),sizeof(DTYPE));
if(rs->alpha_to == NULL){
free(rs);
return NULL;
text_color_set(DW_COLOR_ERROR);
dw_printf ("FATAL ERROR: Out of memory.\n");
exit (EXIT_FAILURE);
}
rs->index_of = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1));
rs->index_of = (DTYPE *)calloc((rs->nn+1),sizeof(DTYPE));
if(rs->index_of == NULL){
free(rs->alpha_to);
free(rs);
return NULL;
text_color_set(DW_COLOR_ERROR);
dw_printf ("FATAL ERROR: Out of memory.\n");
exit (EXIT_FAILURE);
}
/* Generate Galois field lookup tables */
@ -446,14 +452,13 @@ struct rs *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigne
}
/* Form RS code generator polynomial from its roots */
rs->genpoly = (DTYPE *)malloc(sizeof(DTYPE)*(nroots+1));
rs->genpoly = (DTYPE *)calloc((nroots+1),sizeof(DTYPE));
if(rs->genpoly == NULL){
free(rs->alpha_to);
free(rs->index_of);
free(rs);
return NULL;
text_color_set(DW_COLOR_ERROR);
dw_printf ("FATAL ERROR: Out of memory.\n");
exit (EXIT_FAILURE);
}
rs->fcr = fcr;
rs->fcr = fcr;
rs->prim = prim;
rs->nroots = nroots;

View File

@ -107,6 +107,7 @@ void hex_dump (unsigned char *p, int len)
offset = 0;
while (len > 0) {
n = len < 16 ? len : 16;
// FIXME: Is there some reason not to use dw_printf here?
printf (" %03x: ", offset);
for (i=0; i<n; i++) {
printf (" %02x", p[i]);

View File

@ -121,6 +121,7 @@ void latitude_to_str (double dlat, int ambiguity, char *slat)
// Assumes slat can hold 8 characters + nul.
// Degrees must be exactly 2 digits, with leading zero, if needed.
// FIXME: Should pass in sizeof slat and use snprintf
sprintf (slat, "%02d%s%c", ideg, smin, hemi);
if (ambiguity >= 1) {
@ -197,6 +198,7 @@ void longitude_to_str (double dlong, int ambiguity, char *slong)
// Assumes slong can hold 9 characters + nul.
// Degrees must be exactly 3 digits, with leading zero, if needed.
// FIXME: Should pass in sizeof slong and use snprintf
sprintf (slong, "%03d%s%c", ideg, smin, hemi);
/*
@ -372,6 +374,7 @@ void latitude_to_nmea (double dlat, char *slat, char *hemi)
ideg++;
}
// FIXME: Should pass in sizeof slat and use snprintf
sprintf (slat, "%02d%s", ideg, smin);
} /* end latitude_to_str */
@ -433,6 +436,7 @@ void longitude_to_nmea (double dlong, char *slong, char *hemi)
ideg++;
}
// FIXME: Should pass in sizeof slong and use snprintf
sprintf (slong, "%03d%s", ideg, smin);
} /* end longitude_to_nmea */

View File

@ -235,7 +235,7 @@ int pfilter (int from_chan, int to_chan, char *filter, packet_t pp, int is_aprs)
pfstate.is_aprs = is_aprs;
if (is_aprs) {
decode_aprs (&pfstate.decoded, pp, 1);
decode_aprs (&pfstate.decoded, pp, 1, 0);
}
next_token(&pfstate);

View File

@ -352,10 +352,22 @@ void symbols_init (void)
char stuff[200];
int j;
// Feb. 2022 - Noticed that some lines have - rather than =.
// LD = LIght Rail or Subway (new Aug 2014)
// SD = Seaport Depot (new Aug 2014)
// DIGIPEATERS
// /# - Generic digipeater
// 1# - WIDE1-1 digipeater
#define GOOD_LINE(x) (strlen(x) > 6 && \
(x[COL1_OVERLAY] == '/' || x[COL1_OVERLAY] == '\\' || isupper(x[COL1_OVERLAY]) || isdigit(x[COL1_OVERLAY])) \
&& x[COL2_SYMBOL] >= '!' && x[COL2_SYMBOL] <= '~' \
&& x[COL3_SP] == ' ' && x[COL4_EQUAL] == '=' && x[COL5_SP] == ' ' && x[COL6_DESC] != ' ')
&& x[COL3_SP] == ' ' \
&& (x[COL4_EQUAL] == '=' || x[COL4_EQUAL] == '-') \
&& x[COL5_SP] == ' ' \
&& x[COL6_DESC] != ' ')
if (new_sym_ptr != NULL) {
return; /* was called already. */