Implemented compressed position packet parsing. Reduced cut'n'paste code,

removed obsolete mic-e packet type code matching, fixed symbol size.


git-svn-id: http://repo.ham.fi/svn/aprsc/trunk@41 3ce903b1-3385-4e86-93cd-f9a4a239f7ac
This commit is contained in:
Heikki Hannikainen 2008-03-02 16:02:20 +00:00
parent fae8c79dd8
commit dce1690e5c
2 changed files with 108 additions and 59 deletions

View File

@ -37,6 +37,32 @@
#include "hlog.h"
#include "filter.h"
/*
* Check if the given character is a valid symbol table identifier
* or an overlay character
*/
int valid_sym_table(char c)
{
return (c == '/' || c == '\\' || (c >= 0x41 && c <= 0x5A)
|| (c >= 0x61 && c <= 0x6A)); /* [\/\\A-Za-j] */
}
void pbuf_fill_pos(struct pbuf_t *pb, const float lat, const float lng, const char sym_table, const char sym_code)
{
/* Pre-calculations for A/R/F/M-filter tests */
pb->lat = filter_lat2rad(lat); /* deg-to-radians */
pb->cos_lat = cosf(lat); /* used in range filters */
pb->lng = filter_lon2rad(lng); /* deg-to-radians */
/* symbol table and code */
pb->symbol[0] = sym_table;
pb->symbol[1] = sym_code;
pb->symbol[2] = 0;
pb->packettype |= T_POSITION; /* the packet has positional data */
}
int parse_aprs_nmea(struct pbuf_t *pb, const char *body, const char *body_end)
{
float lat = 0.0, lng = 0.0;
@ -59,61 +85,97 @@ int parse_aprs_nmea(struct pbuf_t *pb, const char *body, const char *body_end)
VTG Velocity and track -- no position here!
WPT Way Point Location
*/
/* Pre-calculations for A/R/F/M-filter tests */
pb->lat = filter_lat2rad(lat); /* deg-to-radians */
pb->cos_lat = cosf(pb->lat); /* used in range filters */
pb->lng = filter_lon2rad(lng); /* deg-to-radians */
pb->packettype |= T_POSITION; /* the packet has positional data */
pbuf_fill_pos(pb, lat, lng, 0, 0);
return 0;
}
int parse_aprs_telem(struct pbuf_t *pb, const char *body, const char *body_end)
{
float lat = 0.0, lng = 0.0;
fprintf(stderr, "parse_aprs_telem\n");
/* Pre-calculations for A/R/F/M-filter tests */
pb->lat = filter_lat2rad(lat); /* deg-to-radians */
pb->cos_lat = cosf(pb->lat); /* used in range filters */
pb->lng = filter_lon2rad(lng); /* deg-to-radians */
pb->packettype |= T_POSITION; /* the packet has positional data */
return 0;
}
int parse_aprs_mice(struct pbuf_t *pb, const char *body, const char *body_end)
{
//float lat = 0.0, lng = 0.0;
fprintf(stderr, "parse_aprs_mice\n");
/* Pre-calculations for A/R/F/M-filter tests */
float lat = 0.0, lng = 0.0;
pb->lat = filter_lat2rad(lat); /* deg-to-radians */
pb->cos_lat = cosf(pb->lat); /* used in range filters */
pb->lng = filter_lon2rad(lng); /* deg-to-radians */
pb->packettype |= T_POSITION; /* the packet has positional data */
//pbuf_fill_pos(pb, lat, lng, 0, 0);
return 0;
}
int parse_aprs_compressed(struct pbuf_t *pb, const char *body, const char *body_end)
{
float lat = 0.0, lng = 0.0;
fprintf(stderr, "parse_aprs_compressed\n");
/* Pre-calculations for A/R/F/M-filter tests */
char sym_table, sym_code;
int i;
int lat1, lat2, lat3, lat4, lng1, lng2, lng3, lng4;
double lat = 0.0, lng = 0.0;
pb->lat = filter_lat2rad(lat); /* deg-to-radians */
pb->cos_lat = cosf(pb->lat); /* used in range filters */
pb->lng = filter_lon2rad(lng); /* deg-to-radians */
pb->packettype |= T_POSITION; /* the packet has positional data */
fprintf(stderr, "parse_aprs_compressed\n");
/* A compressed position is always 13 characters long.
* Make sure we get at least 13 characters and that they are ok.
* Also check the allowed base-91 characters at the same time.
*/
if (body_end - body < 13)
return 0; /* too short. */
sym_table = body[0]; /* has been validated before entering this function */
sym_code = body[9];
/* We intentionally ignore invalid symbol codes. We don't care, let's
* leave it to the displaying application. */
/*
if (!vaid_sym_code(sym_code))
return 0;
*/
/* base-91 check */
for (i = 1; i <= 8; i++)
if (body[i] < 0x21 || body[i] >= 0x7b)
return 0;
for (i = 10; i <= 12; i++)
if (body[i] < 0x21 || body[i] >= 0x7b)
return 0;
fprintf(stderr, "\tpassed length and format checks, sym %c%c\n", sym_table, sym_code);
/* decode */
lat1 = body[1] - 33;
lat2 = body[2] - 33;
lat3 = body[3] - 33;
lat4 = body[4] - 33;
lng1 = body[5] - 33;
lng2 = body[6] - 33;
lng3 = body[7] - 33;
lng4 = body[8] - 33;
/* course+speed (or altitude) is ignored by this application
c1 = body[10] - 33;
s1 = body[11] - 33;
comptype = body[12] - 33;
*/
/* calculate latitude and longitude */
lat = 90.0 - ((double)(lat1 * 91 * 91 * 91 + lat2 * 91 * 91 + lat3 * 91 + lat4) / (double)380926.0);
lng = -180.0 + ((double)(lng1 * 91 * 91 * 91 + lng2 * 91 * 91 + lng3 * 91 + lng4) / (double)190463.0);
fprintf(stderr, "\tlat %.3f lng %.3f\n", lat, lng);
if (lat < 90.0 || lat > 90.0 || lng < -180.0 || lng > 180.0)
return 0; /* out of range */
pbuf_fill_pos(pb, lat, lng, sym_table, sym_code);
return 0;
}
@ -161,6 +223,9 @@ int parse_aprs_uncompressed(struct pbuf_t *pb, const char *body, const char *bod
return 0;
}
if (!valid_sym_table(sym_table))
sym_table = 0;
if (lat_hemi == 'S' || lat_hemi == 's')
issouth = 1;
else if (lat_hemi != 'N' && lat_hemi != 'n')
@ -187,46 +252,30 @@ int parse_aprs_uncompressed(struct pbuf_t *pb, const char *body, const char *bod
lat_deg, lat_min, lat_min_frag, (int)lat_hemi, lat,
lng_deg, lng_min, lng_min_frag, (int)lng_hemi, lng);
/* Pre-calculations for A/R/F/M-filter tests */
if (lat < 90.0 || lat > 90.0 || lng < -180.0 || lng > 180.0)
return 0; /* out of range */
pb->lat = filter_lat2rad(lat); /* deg-to-radians */
pb->cos_lat = cosf(pb->lat); /* used in range filters */
pb->lng = filter_lon2rad(lng); /* deg-to-radians */
pb->packettype |= T_POSITION; /* the packet has positional data */
pbuf_fill_pos(pb, lat, lng, sym_table, sym_code);
return 1;
}
int parse_aprs_object(struct pbuf_t *pb, char *body, const char *body_end)
{
float lat = 0.0, lng = 0.0;
//float lat = 0.0, lng = 0.0;
fprintf(stderr, "parse_aprs_object\n");
/* Pre-calculations for A/R/F/M-filter tests */
pb->lat = filter_lat2rad(lat); /* deg-to-radians */
pb->cos_lat = cosf(pb->lat); /* used in range filters */
pb->lng = filter_lon2rad(lng); /* deg-to-radians */
pb->packettype |= T_OBJECT; /* the packet has positional data */
//pbuf_fill_pos(pb, lat, lng);
return 0;
}
int parse_aprs_item(struct pbuf_t *pb, char *body, const char *body_end)
{
float lat = 0.0, lng = 0.0;
//float lat = 0.0, lng = 0.0;
fprintf(stderr, "parse_aprs_item\n");
/* Pre-calculations for A/R/F/M-filter tests */
pb->lat = filter_lat2rad(lat); /* deg-to-radians */
pb->cos_lat = cosf(pb->lat); /* used in range filters */
pb->lng = filter_lon2rad(lng); /* deg-to-radians */
pb->packettype |= T_ITEM; /* the packet has positional data */
//pbuf_fill_pos(pb, lat, lng);
return 0;
}
@ -293,8 +342,10 @@ int parse_aprs(struct worker_t *self, struct pbuf_t *pb)
body_end = pb->data + pb->packet_len - 2;
switch (packettype) {
case 0x1c:
case 0x1d:
/* the following are obsolete mic-e types: 0x1c 0x1d
* case 0x1c:
* case 0x1d:
*/
case 0x27: /* ' */
case 0x60: /* ` */
/* could be mic-e, minimum body length 9 chars */
@ -326,8 +377,7 @@ int parse_aprs(struct worker_t *self, struct pbuf_t *pb)
body += 7;
}
poschar = *body;
if (poschar == '/' || poschar == '\\' || (poschar >= 0x41 && poschar <= 0x5A)
|| (poschar >= 0x61 && poschar <= 0x6A)) { /* [\/\\A-Za-j] */
if (valid_sym_table(poschar)) { /* [\/\\A-Za-j] */
/* compressed position packet */
if (body_end - body >= 13) {
rc = parse_aprs_compressed(pb, body, body_end);
@ -413,8 +463,7 @@ int parse_aprs(struct worker_t *self, struct pbuf_t *pb)
pos_start = memchr(body, '!', body_end - body);
if ((pos_start) && pos_start - body <= 39) {
poschar = *pos_start;
if (poschar == '/' || poschar == '\\' || (poschar >= 0x41 && poschar <= 0x5A)
|| (poschar >= 0x61 && poschar <= 0x6A)) { /* [\/\\A-Za-j] */
if (valid_sym_table(poschar)) { /* [\/\\A-Za-j] */
/* compressed position packet */
if (body_end - pos_start >= 13) {
return parse_aprs_compressed(pb, pos_start, body_end);

View File

@ -104,7 +104,7 @@ struct pbuf_t {
float lng; /* .. in RADIAN */
float cos_lat; /* cache of COS of LATitude for radial distance filter */
char symbol[4]; /* 3(+1) chars of symbol, if any */
char symbol[3]; /* 2(+1) chars of symbol, if any */
char data[1]; /* contains the whole packet, including CRLF, ready to transmit */
};