mirror of https://github.com/wb2osz/direwolf.git
decode_aprs can now process KISS or AX.25 frames as sequences of hexadecimal numbers.
This commit is contained in:
parent
3ce981c196
commit
be7ee8211e
|
@ -14,6 +14,8 @@ This is a snapshot of ongoing development towards version of 1.5. Some features
|
|||
|
||||
- New document ***Bluetooth-KISS-TNC.pdf*** explaining how to use KISS over Bluetooth.
|
||||
|
||||
- decode_aprs utility can now accept KISS frames and AX.25 frames as series of two digit hexadecimal numbers.
|
||||
|
||||
### Bugs Fixed: ###
|
||||
|
||||
- Little spelling errors in messages ????
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
# Makefile for Linux version of Dire Wolf.
|
||||
#
|
||||
|
||||
|
||||
|
||||
|
||||
APPS := direwolf decode_aprs text2tt tt2text ll2utm utm2ll aclients atest log2gpx gen_packets ttcalc
|
||||
|
||||
all : $(APPS) direwolf.desktop direwolf.conf
|
||||
|
@ -259,6 +262,16 @@ endif
|
|||
CFLAGS += -DUSE_ALSA
|
||||
LDFLAGS += -lasound
|
||||
|
||||
ifeq ($(wildcard /usr/include/pthread.h),)
|
||||
$(error /usr/include/pthread.h does not exist. Install it with "sudo apt-get install libc6-dev" or "sudo yum install libc6-dev" )
|
||||
endif
|
||||
|
||||
ifneq ($(USE_ALSA),)
|
||||
ifeq ($(wildcard /usr/include/alsa/asoundlib.h),)
|
||||
$(error /usr/include/alsa/asoundlib.h does not exist. Install it with "sudo apt-get install libasound2-dev" or "sudo yum install libasound2-dev" )
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
# Enable GPS if header file is present.
|
||||
# Finding libgps.so* is more difficult because it
|
||||
|
@ -355,7 +368,9 @@ tocalls-symbols :
|
|||
|
||||
# Separate application to decode raw data.
|
||||
|
||||
decode_aprs : decode_aprs.c dwgpsnmea.o dwgps.o dwgpsd.o serial_port.o symbols.o ax25_pad.o textcolor.o fcs_calc.o latlong.o log.o telemetry.o tt_text.o misc.a
|
||||
# First two use .c rather than .o because they depend on DECAMAIN definition.
|
||||
|
||||
decode_aprs : decode_aprs.c kiss_frame.c dwgpsnmea.o dwgps.o dwgpsd.o serial_port.o symbols.o ax25_pad.o textcolor.o fcs_calc.o latlong.o log.o telemetry.o tt_text.o misc.a
|
||||
$(CC) $(CFLAGS) -DDECAMAIN -o $@ $^ $(LDFLAGS)
|
||||
|
||||
|
||||
|
@ -638,7 +653,8 @@ install-conf : direwolf.conf
|
|||
cp -n telemetry-toolkit/telem-*.conf ~
|
||||
ifneq ($(wildcard $(HOME)/Desktop),)
|
||||
@echo " "
|
||||
@echo "This will add a desktop icon on some systems:"
|
||||
@echo "This will add a desktop icon on some systems."
|
||||
@echo "This is known to work on Raspberry Pi but might not be compatible with other desktops."
|
||||
@echo " "
|
||||
@echo " make install-rpi"
|
||||
@echo " "
|
||||
|
|
|
@ -430,7 +430,9 @@ install-conf : direwolf.conf
|
|||
|
||||
# Separate application to decode raw data.
|
||||
|
||||
decode_aprs : decode_aprs.c dwgpsnmea.o dwgps.o dwgpsd.o serial_port.o symbols.o ax25_pad.o textcolor.o fcs_calc.o latlong.o log.o telemetry.o tt_text.o
|
||||
# First two use .c rather than .o because they depend on DECAMAIN definition.
|
||||
|
||||
decode_aprs : decode_aprs.c kiss_frame.c dwgpsnmea.o dwgps.o dwgpsd.o serial_port.o symbols.o ax25_pad.o textcolor.o fcs_calc.o latlong.o log.o telemetry.o tt_text.o
|
||||
$(CC) $(CFLAGS) -DDECAMAIN -o $@ $^ -lm
|
||||
|
||||
# Convert between text and touch tone representation.
|
||||
|
|
|
@ -159,7 +159,9 @@ tocalls-symbols :
|
|||
|
||||
# Separate application to decode raw data.
|
||||
|
||||
decode_aprs : decode_aprs.c dwgpsnmea.o dwgps.o serial_port.o symbols.o ax25_pad.o textcolor.o fcs_calc.o latlong.o log.o telemetry.o tt_text.c regex.a misc.a geotranz.a
|
||||
# First two use .c rather than .o because they depend on DECAMAIN definition.
|
||||
|
||||
decode_aprs : decode_aprs.c kiss_frame.c dwgpsnmea.o dwgps.o serial_port.o symbols.o ax25_pad.o textcolor.o fcs_calc.o latlong.o log.o telemetry.o tt_text.o regex.a misc.a geotranz.a
|
||||
$(CC) $(CFLAGS) -DDECAMAIN -o decode_aprs $^
|
||||
|
||||
|
||||
|
|
50
ax25_pad.c
50
ax25_pad.c
|
@ -760,12 +760,18 @@ int ax25_parse_addr (int position, char *in_addr, int strict, char *out_addr, in
|
|||
maxlen = strict ? 6 : (AX25_MAX_ADDR_LEN-1);
|
||||
p = in_addr;
|
||||
i = 0;
|
||||
for (p = in_addr; isalnum(*p); p++) {
|
||||
for (p = in_addr; *p != '\0' && *p != '-'; p++) {
|
||||
if (i >= maxlen) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("%sAddress is too long. \"%s\" has more than %d characters.\n", position_name[position], in_addr, maxlen);
|
||||
return 0;
|
||||
}
|
||||
if ( ! isalnum(*p)) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("%sAddress, \"%s\" contains character other than letter or digit in character position %d.\n", position_name[position], in_addr, (int)(long)(p-in_addr)+1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_addr[i++] = *p;
|
||||
out_addr[i] = '\0';
|
||||
if (strict && islower(*p)) {
|
||||
|
@ -1257,13 +1263,22 @@ void ax25_get_addr_with_ssid (packet_t this_p, int n, char *station)
|
|||
return;
|
||||
}
|
||||
|
||||
memset (station, 0, 7);
|
||||
for (i=0; i<6; i++) {
|
||||
unsigned char ch;
|
||||
// At one time this would stop at the first space, on the assumption we would have only trailing spaces.
|
||||
// Then there was a forum discussion where someone encountered the address " WIDE2" with a leading space.
|
||||
// In that case, we would have returned a zero length string here.
|
||||
// Now we return exactly what is in the address field and trim trailing spaces.
|
||||
// This will provide better information for troubleshooting.
|
||||
|
||||
ch = (this_p->frame_data[n*7+i] >> 1) & 0x7f;
|
||||
if (ch <= ' ') break;
|
||||
station[i] = ch;
|
||||
for (i=0; i<6; i++) {
|
||||
station[i] = (this_p->frame_data[n*7+i] >> 1) & 0x7f;
|
||||
}
|
||||
station[6] = '\0';
|
||||
|
||||
for (i=5; i>=0; i--) {
|
||||
if (station[i] == ' ')
|
||||
station[i] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
ssid = ax25_get_ssid (this_p, n);
|
||||
|
@ -1322,13 +1337,22 @@ void ax25_get_addr_no_ssid (packet_t this_p, int n, char *station)
|
|||
return;
|
||||
}
|
||||
|
||||
memset (station, 0, 7);
|
||||
for (i=0; i<6; i++) {
|
||||
unsigned char ch;
|
||||
// At one time this would stop at the first space, on the assumption we would have only trailing spaces.
|
||||
// Then there was a forum discussion where someone encountered the address " WIDE2" with a leading space.
|
||||
// In that case, we would have returned a zero length string here.
|
||||
// Now we return exactly what is in the address field and trim trailing spaces.
|
||||
// This will provide better information for troubleshooting.
|
||||
|
||||
ch = (this_p->frame_data[n*7+i] >> 1) & 0x7f;
|
||||
if (ch <= ' ') break;
|
||||
station[i] = ch;
|
||||
for (i=0; i<6; i++) {
|
||||
station[i] = (this_p->frame_data[n*7+i] >> 1) & 0x7f;
|
||||
}
|
||||
station[6] = '\0';
|
||||
|
||||
for (i=5; i>=0; i--) {
|
||||
if (station[i] == ' ')
|
||||
station[i] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
} /* end ax25_get_addr_no_ssid */
|
||||
|
|
214
decode_aprs.c
214
decode_aprs.c
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||
//
|
||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015 John Langner, WB2OSZ
|
||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2017 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
|
||||
|
@ -4583,6 +4583,14 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
|
|||
*
|
||||
* WB2OSZ-1>APN383,qAR,N1EDU-2:!4237.14NS07120.83W#PHG7130Chelmsford, MA
|
||||
*
|
||||
* New for 1.5:
|
||||
*
|
||||
* Also allow hexadecimal bytes for raw AX.25 or KISS. e.g.
|
||||
*
|
||||
* 00 82 a0 ae ae 62 60 e0 82 96 68 84 40 40 60 9c 68 b0 ae 86 40 e0 40 ae 92 88 8a 64 63 03 f0 3e 45 4d 36 34 6e 65 2f 23 20 45 63 68 6f 6c 69 6e 6b 20 31 34 35 2e 33 31 30 2f 31 30 30 68 7a 20 54 6f 6e 65
|
||||
*
|
||||
* If it begins with 00 or C0 (which would be impossible for AX.25 address) process as KISS.
|
||||
* Also print these formats.
|
||||
*
|
||||
* Outputs: stdout
|
||||
*
|
||||
|
@ -4614,11 +4622,16 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
|
|||
* TODO: To make it more useful,
|
||||
* - Remove any leading timestamp.
|
||||
* - Remove any "qA*" and following from the path.
|
||||
* - Handle non-APRS frames properly.
|
||||
*
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
#if DECAMAIN
|
||||
|
||||
#include "kiss_frame.h"
|
||||
|
||||
|
||||
|
||||
/* Stub for stand-alone decoder. */
|
||||
|
||||
void nmea_send_waypoint (char *wname_in, double dlat, double dlong, char symtab, char symbol,
|
||||
|
@ -4627,11 +4640,48 @@ void nmea_send_waypoint (char *wname_in, double dlat, double dlong, char symtab,
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: hex_dump is currently in server.c and we don't want to drag that in.
|
||||
// Someday put it in a more reasonable place, with other general utilities, and remove the private copy here.
|
||||
|
||||
|
||||
static void hex_dump (unsigned char *p, int len)
|
||||
{
|
||||
int n, i, offset;
|
||||
|
||||
offset = 0;
|
||||
while (len > 0) {
|
||||
n = len < 16 ? len : 16;
|
||||
dw_printf (" %03x: ", offset);
|
||||
for (i=0; i<n; i++) {
|
||||
dw_printf (" %02x", p[i]);
|
||||
}
|
||||
for (i=n; i<16; i++) {
|
||||
dw_printf (" ");
|
||||
}
|
||||
dw_printf (" ");
|
||||
for (i=0; i<n; i++) {
|
||||
dw_printf ("%c", isprint(p[i]) ? p[i] : '.');
|
||||
}
|
||||
dw_printf ("\n");
|
||||
p += 16;
|
||||
offset += 16;
|
||||
len -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do we have two hexadecimal digits followed by whitespace or end of line?
|
||||
|
||||
#define ISHEX2(x) (isxdigit(x[0]) && isxdigit(x[1]) && (x[2] == '\0' || isspace(x[2])))
|
||||
|
||||
#define MAXLINE 9000
|
||||
#define MAXBYTES 3000
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
char stuff[300];
|
||||
char stuff[MAXLINE];
|
||||
unsigned char bytes[MAXBYTES];
|
||||
int num_bytes;
|
||||
char *p;
|
||||
packet_t pp;
|
||||
|
||||
|
@ -4686,38 +4736,150 @@ int main (int argc, char *argv[])
|
|||
|
||||
text_color_set(DW_COLOR_REC);
|
||||
dw_printf("\n%s\n", stuff);
|
||||
|
||||
pp = ax25_from_text(stuff, 1);
|
||||
if (pp != NULL)
|
||||
{
|
||||
decode_aprs_t A;
|
||||
|
||||
// log directory option someday?
|
||||
decode_aprs (&A, pp, 0);
|
||||
// Do we have monitor format, KISS, or AX.25 frame?
|
||||
|
||||
//Print it all out in human readable format.
|
||||
p = stuff;
|
||||
while (isspace(*p)) p++;
|
||||
|
||||
decode_aprs_print (&A);
|
||||
if (ISHEX2(p)) {
|
||||
|
||||
/*
|
||||
* Perform validity check on each address.
|
||||
* This should print an error message if any issues.
|
||||
*/
|
||||
(void)ax25_check_addresses(pp);
|
||||
// Collect a bunch of hexadecimal numbers.
|
||||
|
||||
// Send to log file?
|
||||
num_bytes = 0;
|
||||
|
||||
// if (logdir != NULL && *logdir != '\0') {
|
||||
// log_write (&A, pp, logdir);
|
||||
// }
|
||||
while (ISHEX2(p) && num_bytes < MAXBYTES) {
|
||||
|
||||
ax25_delete (pp);
|
||||
bytes[num_bytes++] = strtoul(p, NULL, 16);
|
||||
p += 2;
|
||||
while (isspace(*p)) p++;
|
||||
}
|
||||
|
||||
if (num_bytes == 0 || *p != '\0') {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("Parse error around column %d.\n", (int)(long)(p - stuff) + 1);
|
||||
dw_printf("Was expecting only space separated 2 digit hexadecimal numbers.\n\n");
|
||||
continue; // next line
|
||||
}
|
||||
|
||||
// If we have 0xC0 at start, remove it and expect same at end.
|
||||
|
||||
if (bytes[0] == FEND) {
|
||||
|
||||
if (bytes[1] != 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("Was expecting to find 00 after the initial C0.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bytes[num_bytes-1] == FEND) {
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
dw_printf("Removing KISS FEND characters at beginning and end.\n");
|
||||
int n;
|
||||
for (n = 0; n < num_bytes-1; n++) {
|
||||
bytes[n] = bytes[n+1];
|
||||
}
|
||||
num_bytes -= 2;
|
||||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
dw_printf("Removing KISS FEND character at beginning. Was expecting another at end.\n");
|
||||
int n;
|
||||
for (n = 0; n < num_bytes-1; n++) {
|
||||
bytes[n] = bytes[n+1];
|
||||
}
|
||||
num_bytes -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (bytes[0] == 0) {
|
||||
|
||||
// Treat as KISS. Undo any KISS encoding.
|
||||
|
||||
unsigned char kiss_frame[MAXBYTES];
|
||||
int kiss_len = num_bytes;
|
||||
|
||||
memcpy (kiss_frame, bytes, num_bytes);
|
||||
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("--- KISS frame ---\n");
|
||||
hex_dump (kiss_frame, kiss_len);
|
||||
|
||||
// Put FEND at end to keep kiss_unwrap happy.
|
||||
// Having one at the begining is optional.
|
||||
|
||||
kiss_frame[kiss_len++] = FEND;
|
||||
|
||||
// In the more general case, we would need to include
|
||||
// the command byte because it could be escaped.
|
||||
// Here we know it is 0, so we take a short cut and
|
||||
// remove it before, rather than after, the conversion.
|
||||
|
||||
num_bytes = kiss_unwrap (kiss_frame + 1, kiss_len - 1, bytes);
|
||||
}
|
||||
|
||||
// Treat as AX.25.
|
||||
|
||||
alevel_t alevel;
|
||||
memset (&alevel, 0, sizeof(alevel));
|
||||
|
||||
pp = ax25_from_frame(bytes, num_bytes, alevel);
|
||||
if (pp != NULL) {
|
||||
char addrs[120];
|
||||
unsigned char *pinfo;
|
||||
int info_len;
|
||||
decode_aprs_t A;
|
||||
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("--- AX.25 frame ---\n");
|
||||
ax25_hex_dump (pp);
|
||||
dw_printf ("-------------------\n");
|
||||
|
||||
ax25_format_addrs (pp, addrs);
|
||||
text_color_set(DW_COLOR_DECODED);
|
||||
dw_printf ("%s:", addrs);
|
||||
|
||||
info_len = ax25_get_info (pp, &pinfo);
|
||||
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_print (&A); // Now print it in human readable format.
|
||||
|
||||
(void)ax25_check_addresses(pp); // Errors for invalid addresses.
|
||||
|
||||
ax25_delete (pp);
|
||||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("Could not construct AX.25 frame from bytes supplied!\n\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// Normal monitoring format.
|
||||
|
||||
pp = ax25_from_text(stuff, 1);
|
||||
if (pp != NULL) {
|
||||
decode_aprs_t A;
|
||||
|
||||
decode_aprs (&A, pp, 0); // Extract information into structure.
|
||||
|
||||
decode_aprs_print (&A); // Now print it in human readable format.
|
||||
|
||||
(void)ax25_check_addresses(pp); // Errors for invalid addresses.
|
||||
|
||||
// Future? Add -d option to include hex dump and maybe KISS?
|
||||
|
||||
ax25_delete (pp);
|
||||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("ERROR - Could not parse monitoring format input!\n\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("\n%s\n", "ERROR - Could not parse input!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
|
|
Binary file not shown.
|
@ -101,7 +101,9 @@ void text_color_set (dw_color_t c)
|
|||
|
||||
#else
|
||||
|
||||
#ifndef DECAMAIN
|
||||
static void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -212,7 +214,7 @@ int kiss_encapsulate (unsigned char *in, int ilen, unsigned char *out)
|
|||
*
|
||||
*-----------------------------------------------------------------*/
|
||||
|
||||
static int kiss_unwrap (unsigned char *in, int ilen, unsigned char *out)
|
||||
int kiss_unwrap (unsigned char *in, int ilen, unsigned char *out)
|
||||
{
|
||||
int olen;
|
||||
int j;
|
||||
|
@ -278,6 +280,8 @@ static int kiss_unwrap (unsigned char *in, int ilen, unsigned char *out)
|
|||
} /* end kiss_unwrap */
|
||||
|
||||
|
||||
#ifndef DECAMAIN
|
||||
|
||||
#ifndef KISSTEST
|
||||
|
||||
|
||||
|
@ -687,6 +691,7 @@ void kiss_debug_print (fromto_t fromto, char *special, unsigned char *pmsg, int
|
|||
|
||||
#endif
|
||||
|
||||
#endif /* DECAMAIN */
|
||||
|
||||
/* Quick unit test for encapsulate & unwrap */
|
||||
|
||||
|
@ -730,7 +735,7 @@ int main ()
|
|||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* KISSTEST */
|
||||
|
||||
#endif /* WALK96 */
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@ void kiss_frame_init (struct audio_s *pa);
|
|||
|
||||
int kiss_encapsulate (unsigned char *in, int ilen, unsigned char *out);
|
||||
|
||||
int kiss_unwrap (unsigned char *in, int ilen, unsigned char *out);
|
||||
|
||||
void kiss_rec_byte (kiss_frame_t *kf, unsigned char ch, int debug, int client, void (*sendfun)(int,unsigned char*,int,int));
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@ decode_aprs \- Convert APRS raw data to human readable form.
|
|||
[ \fItext-file\fR ]
|
||||
.RS
|
||||
.P
|
||||
\fItext-file\fR should contain AX.25 packets in the standard monitoring format.
|
||||
\fItext-file\fR should contain AX.25 packets in the standard monitoring format or
|
||||
as a series two digit hexadecimal numbers.
|
||||
If the first number is 00 or c0, it will be treated as a KISS frame.
|
||||
If no file specified, data will be read from stdin.
|
||||
.P
|
||||
.RE
|
||||
|
@ -43,12 +45,14 @@ Pipe it into decode_aprs to find out.
|
|||
http://www.findu.com/cgi-bin/errors.cgi has a never-ending collection of packets
|
||||
with errors. Sometimes it's not obvious what is wrong with them.
|
||||
Dire Wolf will usually tell you what is wrong. First,
|
||||
cut-n-paste the bad packets into a text file. Here a couple examples:
|
||||
cut-n-paste the bad packets into a text file. Here a few examples:
|
||||
.P
|
||||
.RS
|
||||
n2cma>APRS,TCPIP*,qAC,SEVENTH:@212127z43.2333n/77.1w_338/002g001t025P000h65b10208.wview_5_19_0
|
||||
.P
|
||||
K0YTH-10>APNU3B,NULL,qAR,K0DMF-10:!4601.5NS09255.52W#PHG6360/W2,MNn 444.575
|
||||
.P
|
||||
00 82 a0 ae ae 62 60 e0 82 96 68 84 40 40 60 9c 68 b0 ae 86 40 e0 40 ae 92 88 8a 64 63 03 f0 3e 45 4d 36 34 6e 65 2f 23 20 45 63 68 6f 6c 69 6e 6b 20 31 34 35 2e 33 31 30 2f 31 30 30 68 7a 20 54 6f 6e 65
|
||||
.RE
|
||||
.P
|
||||
If you simply fed this into decode_aprs, it would complain about the
|
||||
|
@ -67,7 +71,7 @@ Address has lower case letters. "n2cma" must be all upper case.
|
|||
.P
|
||||
After changing the source address to upper case, there are other issues. Identifying them is left as an exercise for the reader.
|
||||
.P
|
||||
And in the second example,
|
||||
In the second example,
|
||||
.P
|
||||
.RS
|
||||
.PD 0
|
||||
|
@ -77,6 +81,17 @@ Invalid character in longitude. Found '9' when expecting 0 or 1 for hundreds of
|
|||
.PD
|
||||
.RE
|
||||
|
||||
.P
|
||||
In the third example,
|
||||
.P
|
||||
.RS
|
||||
.PD 0
|
||||
Warning: Lower case letter in Maidenhead locator. Specification requires upper case.
|
||||
.P
|
||||
Digi2 Address, " WIDE2-1" contains character other than letter or digit in character position 1.
|
||||
.PD
|
||||
.RE
|
||||
|
||||
|
||||
|
||||
.SH SEE ALSO
|
||||
|
|
Loading…
Reference in New Issue