Merge remote-tracking branch 'upstream/master' latest dump1090 from Malcolm Robb

Conflicts:
	net_io.c
This commit is contained in:
Karl Lehenbauer 2014-07-21 22:49:54 -05:00
commit 9b619927ae
5 changed files with 232 additions and 89 deletions

View File

@ -395,7 +395,7 @@ void showHelp(void) {
"| dump1090 ModeS Receiver Ver : " MODES_DUMP1090_VERSION " |\n"
"-----------------------------------------------------------------------------\n"
"--device-index <index> Select RTL device (default: 0)\n"
"--gain <db> Set gain (default: max gain. Use -100 for auto-gain)\n"
"--gain <db> Set gain (default: max gain. Use -10 for auto-gain)\n"
"--enable-agc Enable the Automatic Gain Control (default: off)\n"
"--freq <hz> Set frequency (default: 1090 Mhz)\n"
"--ifile <filename> Read data from file (use '-' for stdin)\n"
@ -417,7 +417,7 @@ void showHelp(void) {
"--net-bo-port <port> TCP Beast output listen port (default: 30005)\n"
"--net-ro-size <size> TCP raw output minimum size (default: 0)\n"
"--net-ro-rate <rate> TCP raw output memory flush rate (default: 0)\n"
"--net-heartbeat <rate> TCP heartbeat rate in seconds (default: 60 sec)\n"
"--net-heartbeat <rate> TCP heartbeat rate in seconds (default: 60 sec; 0 to disable)\n"
"--net-buffer <n> TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n"
"--lat <latitude> Reference/receiver latitude for surface posn (opt)\n"
"--lon <longitude> Reference/receiver longitude for surface posn (opt)\n"
@ -506,6 +506,68 @@ void backgroundTasks(void) {
//
//=========================================================================
//
int verbose_device_search(char *s)
{
int i, device_count, device, offset;
char *s2;
char vendor[256], product[256], serial[256];
device_count = rtlsdr_get_device_count();
if (!device_count) {
fprintf(stderr, "No supported devices found.\n");
return -1;
}
fprintf(stderr, "Found %d device(s):\n", device_count);
for (i = 0; i < device_count; i++) {
rtlsdr_get_device_usb_strings(i, vendor, product, serial);
fprintf(stderr, " %d: %s, %s, SN: %s\n", i, vendor, product, serial);
}
fprintf(stderr, "\n");
/* does string look like raw id number */
device = (int)strtol(s, &s2, 0);
if (s2[0] == '\0' && device >= 0 && device < device_count) {
fprintf(stderr, "Using device %d: %s\n",
device, rtlsdr_get_device_name((uint32_t)device));
return device;
}
/* does string exact match a serial */
for (i = 0; i < device_count; i++) {
rtlsdr_get_device_usb_strings(i, vendor, product, serial);
if (strcmp(s, serial) != 0) {
continue;}
device = i;
fprintf(stderr, "Using device %d: %s\n",
device, rtlsdr_get_device_name((uint32_t)device));
return device;
}
/* does string prefix match a serial */
for (i = 0; i < device_count; i++) {
rtlsdr_get_device_usb_strings(i, vendor, product, serial);
if (strncmp(s, serial, strlen(s)) != 0) {
continue;}
device = i;
fprintf(stderr, "Using device %d: %s\n",
device, rtlsdr_get_device_name((uint32_t)device));
return device;
}
/* does string suffix match a serial */
for (i = 0; i < device_count; i++) {
rtlsdr_get_device_usb_strings(i, vendor, product, serial);
offset = strlen(serial) - strlen(s);
if (offset < 0) {
continue;}
if (strncmp(s, serial+offset, strlen(s)) != 0) {
continue;}
device = i;
fprintf(stderr, "Using device %d: %s\n",
device, rtlsdr_get_device_name((uint32_t)device));
return device;
}
fprintf(stderr, "No matching devices found.\n");
return -1;
}
//
//=========================================================================
//
int main(int argc, char **argv) {
int j;
@ -518,7 +580,7 @@ int main(int argc, char **argv) {
int more = j+1 < argc; // There are more arguments
if (!strcmp(argv[j],"--device-index") && more) {
Modes.dev_index = atoi(argv[++j]);
Modes.dev_index = verbose_device_search(argv[++j]);
} else if (!strcmp(argv[j],"--gain") && more) {
Modes.gain = (int) atof(argv[++j])*10; // Gain is in tens of DBs
} else if (!strcmp(argv[j],"--enable-agc")) {

View File

@ -746,7 +746,7 @@ int decodeMovementField(int movement) {
//
// Capability table
char *ca_str[8] = {
/* 0 */ "Level 1 (Survillance Only)",
/* 0 */ "Level 1 (Surveillance Only)",
/* 1 */ "Level 2 (DF0,4,5,11)",
/* 2 */ "Level 3 (DF0,4,5,11,20,21)",
/* 3 */ "Level 4 (DF0,4,5,11,20,21,24)",
@ -779,6 +779,20 @@ char *fs_str[8] = {
/* 6 */ "Value 6 is not assigned",
/* 7 */ "Value 7 is not assigned"
};
// Emergency state table
// from https://www.ll.mit.edu/mission/aviation/publications/publication-files/atc-reports/Grappel_2007_ATC-334_WW-15318.pdf
// and 1090-DO-260B_FRAC
char *es_str[8] = {
/* 0 */ "No emergency",
/* 1 */ "General emergency (squawk 7700)",
/* 2 */ "Lifeguard/Medical",
/* 3 */ "Minimum fuel",
/* 4 */ "No communications (squawk 7600)",
/* 5 */ "Unlawful interference (squawk 7500)",
/* 6 */ "Downed Aircraft",
/* 7 */ "Reserved"
};
//
//=========================================================================
//
@ -797,6 +811,8 @@ char *getMEDescription(int metype, int mesub) {
mename = "Airborne Position (GNSS Height)";
else if (metype == 23 && mesub == 0)
mename = "Test Message";
else if (metype == 23 && mesub == 7)
mename = "Test Message -- Squawk";
else if (metype == 24 && mesub == 1)
mename = "Surface System Status";
else if (metype == 28 && mesub == 1)
@ -944,7 +960,7 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) {
if ( (mm->msgtype == 17)
|| ((mm->msgtype == 18) && ((mm->ca == 0) || (mm->ca == 1) || (mm->ca == 6)) )) {
int metype = mm->metype = msg[4] >> 3; // Extended squitter message type
int mesub = mm->mesub = msg[4] & 7; // Extended squitter message subtype
int mesub = mm->mesub = (metype == 29 ? ((msg[4]&6)>>1) : (msg[4] & 7)); // Extended squitter message subtype
// Decode the extended squitter message
@ -1060,7 +1076,23 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) {
mm->heading = ((((msg[5] & 0x03) << 8) | msg[6]) * 45) >> 7;
}
}
}
} else if (mm->metype == 23) { // Test metype squawk field
if (mm->mesub == 7) { // (see 1090-WP-15-20)
int ID13Field = (((msg[5] << 8) | msg[6]) & 0xFFF1)>>3;
if (ID13Field) {
mm->bFlags |= MODES_ACFLAGS_SQUAWK_VALID;
mm->modeA = decodeID13Field(ID13Field);
}
}
} else if (mm->metype == 28) { // Emergency status squawk field
if (mm->mesub == 1) {
int ID13Field = (((msg[5] << 8) | msg[6]) & 0x1FFF);
if (ID13Field) {
mm->bFlags |= MODES_ACFLAGS_SQUAWK_VALID;
mm->modeA = decodeID13Field(ID13Field);
}
}
}
}
// Fields for DF20, DF21 Comm-B
@ -1159,8 +1191,8 @@ void displayModesMessage(struct modesMessage *mm) {
} else if ( mm->msg[4] == 0x30) { // BDS 3,0 ACAS Active Resolution Advisory
printf(" BDS 3,0 ACAS Active Resolution Advisory\n");
} else if ((mm->msg[4] >> 3) == 28) { // BDS 6,1 Extended Squitter Emergecy/Priority Status
printf(" BDS 6,1 Emergecy/Priority Status\n");
} else if ((mm->msg[4] >> 3) == 28) { // BDS 6,1 Extended Squitter Emergency/Priority Status
printf(" BDS 6,1 Emergency/Priority Status\n");
} else if ((mm->msg[4] >> 3) == 29) { // BDS 6,2 Target State and Status
printf(" BDS 6,2 Target State and Status\n");
@ -1177,7 +1209,7 @@ void displayModesMessage(struct modesMessage *mm) {
printf(" Flight Status : %s\n", fs_str[mm->fs]);
printf(" DR : %d\n", ((mm->msg[1] >> 3) & 0x1F));
printf(" UM : %d\n", (((mm->msg[1] & 7) << 3) | (mm->msg[2] >> 5)));
printf(" Squawk : %x\n", mm->modeA);
printf(" Squawk : %04x\n", mm->modeA);
printf(" ICAO Address : %06x\n", mm->addr);
if (mm->msgtype == 21) {
@ -1193,8 +1225,8 @@ void displayModesMessage(struct modesMessage *mm) {
} else if ( mm->msg[4] == 0x30) { // BDS 3,0 ACAS Active Resolution Advisory
printf(" BDS 3,0 ACAS Active Resolution Advisory\n");
} else if ((mm->msg[4] >> 3) == 28) { // BDS 6,1 Extended Squitter Emergecy/Priority Status
printf(" BDS 6,1 Emergecy/Priority Status\n");
} else if ((mm->msg[4] >> 3) == 28) { // BDS 6,1 Extended Squitter Emergency/Priority Status
printf(" BDS 6,1 Emergency/Priority Status\n");
} else if ((mm->msg[4] >> 3) == 29) { // BDS 6,2 Target State and Status
printf(" BDS 6,2 Target State and Status\n");
@ -1275,6 +1307,20 @@ void displayModesMessage(struct modesMessage *mm) {
//} else if (mm->metype >= 20 && mm->metype <= 22) { // Airborne position GNSS
} else if (mm->metype == 28) { // Extended Squitter Aircraft Status
if (mm->mesub == 1) {
printf(" Emergency State: %s\n", es_str[(mm->msg[5] & 0xE0) >> 5]);
printf(" Squawk: %04x\n", mm->modeA);
} else {
printf(" Unrecognized ME subtype: %d subtype: %d\n", mm->metype, mm->mesub);
}
} else if (mm->metype == 23) { // Test Message
if (mm->mesub == 7) {
printf(" Squawk: %04x\n", mm->modeA);
} else {
printf(" Unrecognized ME subtype: %d subtype: %d\n", mm->metype, mm->mesub);
}
} else {
printf(" Unrecognized ME type: %d subtype: %d\n", mm->metype, mm->mesub);
}
@ -1976,12 +2022,24 @@ void decodeCPR(struct aircraft *a, int fflag, int surface) {
double rlat0 = AirDlat0 * (cprModFunction(j,60) + lat0 / 131072);
double rlat1 = AirDlat1 * (cprModFunction(j,59) + lat1 / 131072);
time_t now = time(NULL);
double surface_rlat = MODES_USER_LATITUDE_DFLT;
double surface_rlon = MODES_USER_LONGITUDE_DFLT;
if (surface) {
// If we're on the ground, make sure we have our receiver base station Lat/Lon
if (0 == (Modes.bUserFlags & MODES_USER_LATLON_VALID))
{return;}
rlat0 += floor(Modes.fUserLat / 90.0) * 90.0; // Move from 1st quadrant to our quadrant
rlat1 += floor(Modes.fUserLat / 90.0) * 90.0;
// If we're on the ground, make sure we have a (likely) valid Lat/Lon
if ((a->bFlags & MODES_ACFLAGS_LATLON_VALID) && (((int)(now - a->seenLatLon)) < Modes.interactive_display_ttl)) {
surface_rlat = a->lat;
surface_rlon = a->lon;
} else if (Modes.bUserFlags & MODES_USER_LATLON_VALID) {
surface_rlat = Modes.fUserLat;
surface_rlon = Modes.fUserLon;
} else {
surface_rlat = Modes.fUserLat;
return;
}
rlat0 += floor(surface_rlat / 90.0) * 90.0; // Move from 1st quadrant to our quadrant
rlat1 += floor(surface_rlat / 90.0) * 90.0;
} else {
if (rlat0 >= 270) rlat0 -= 360;
if (rlat1 >= 270) rlat1 -= 360;
@ -2006,7 +2064,7 @@ void decodeCPR(struct aircraft *a, int fflag, int surface) {
}
if (surface) {
a->lon += floor(Modes.fUserLon / 90.0) * 90.0; // Move from 1st quadrant to our quadrant
a->lon += floor(surface_rlon / 90.0) * 90.0; // Move from 1st quadrant to our quadrant
} else if (a->lon > 180) {
a->lon -= 360;
}

101
net_io.c
View File

@ -46,22 +46,30 @@
//
// Networking "stack" initialization
//
struct service {
char *descr;
int *socket;
int port;
int enabled;
};
struct service services[MODES_NET_SERVICES_NUM];
void modesInitNet(void) {
struct {
char *descr;
int *socket;
int port;
} services[MODES_NET_SERVICES_NUM] = {
{"Raw TCP output", &Modes.ros, Modes.net_output_raw_port},
{"Raw TCP input", &Modes.ris, Modes.net_input_raw_port},
{"Beast TCP output", &Modes.bos, Modes.net_output_beast_port},
{"Beast TCP input", &Modes.bis, Modes.net_input_beast_port},
{"HTTP server", &Modes.https, Modes.net_http_port},
{"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port},
{"FlightAware TSV output", &Modes.fatsvos, MODES_NET_OUTPUT_FA_TSV_PORT}
};
int j;
struct service svc[MODES_NET_SERVICES_NUM] = {
{"Raw TCP output", &Modes.ros, Modes.net_output_raw_port, 1},
{"Raw TCP input", &Modes.ris, Modes.net_input_raw_port, 1},
{"Beast TCP output", &Modes.bos, Modes.net_output_beast_port, 1},
{"Beast TCP input", &Modes.bis, Modes.net_input_beast_port, 1},
{"HTTP server", &Modes.https, Modes.net_http_port, 1},
{"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port, 1},
{"FlightAware TSV output", &Modes.fatsvos, MODES_NET_OUTPUT_FA_TSV_PORT, 1}
};
memcpy(&services, &svc, sizeof(svc));//services = svc;
Modes.clients = NULL;
#ifdef _WIN32
@ -76,14 +84,19 @@ void modesInitNet(void) {
#endif
for (j = 0; j < MODES_NET_SERVICES_NUM; j++) {
int s = anetTcpServer(Modes.aneterr, services[j].port, NULL);
if (s == -1) {
fprintf(stderr, "Error opening the listening port %d (%s): %s\n",
services[j].port, services[j].descr, strerror(errno));
exit(1);
}
anetNonBlock(Modes.aneterr, s);
*services[j].socket = s;
services[j].enabled = (services[j].port != 0);
if (services[j].enabled) {
int s = anetTcpServer(Modes.aneterr, services[j].port, NULL);
if (s == -1) {
fprintf(stderr, "Error opening the listening port %d (%s): %s\n",
services[j].port, services[j].descr, strerror(errno));
exit(1);
}
anetNonBlock(Modes.aneterr, s);
*services[j].socket = s;
} else {
if (Modes.debug & MODES_DEBUG_NET) printf("%s port is disabled\n", services[j].descr);
}
}
#ifndef _WIN32
@ -100,39 +113,31 @@ struct client * modesAcceptClients(void) {
int fd, port;
unsigned int j;
struct client *c;
int services[MODES_NET_SERVICES_NUM];
services[0] = Modes.ros;
services[1] = Modes.ris;
services[2] = Modes.bos;
services[3] = Modes.bis;
services[4] = Modes.https;
services[5] = Modes.sbsos;
services[6] = Modes.fatsvos;
for (j = 0; j < MODES_NET_SERVICES_NUM; j++) {
fd = anetTcpAccept(Modes.aneterr, services[j], NULL, &port);
if (fd == -1) continue;
if (services[j].enabled) {
fd = anetTcpAccept(Modes.aneterr, *services[j].socket, NULL, &port);
if (fd == -1) continue;
anetNonBlock(Modes.aneterr, fd);
c = (struct client *) malloc(sizeof(*c));
c->service = services[j];
c->next = Modes.clients;
c->fd = fd;
c->buflen = 0;
c->tsvVerbatim[0] = '\0';
Modes.clients = c;
anetSetSendBuffer(Modes.aneterr,fd, (MODES_NET_SNDBUF_SIZE << Modes.net_sndbuf_size));
anetNonBlock(Modes.aneterr, fd);
c = (struct client *) malloc(sizeof(*c));
c->service = *services[j].socket;
c->next = Modes.clients;
c->fd = fd;
c->buflen = 0;
Modes.clients = c;
anetSetSendBuffer(Modes.aneterr,fd, (MODES_NET_SNDBUF_SIZE << Modes.net_sndbuf_size));
if (services[j] == Modes.sbsos) Modes.stat_sbs_connections++;
if (services[j] == Modes.fatsvos) Modes.stat_fatsv_connections++;
if (services[j] == Modes.ros) Modes.stat_raw_connections++;
if (services[j] == Modes.bos) Modes.stat_beast_connections++;
if (*services[j].socket == Modes.sbsos) Modes.stat_sbs_connections++;
if (*services[j].socket == Modes.ros) Modes.stat_raw_connections++;
if (*services[j].socket == Modes.bos) Modes.stat_beast_connections++;
if (*services[j].socket == Modes.fatsvos) Modes.stat_fatsv_connections++;
j--; // Try again with the same listening port
j--; // Try again with the same listening port
if (Modes.debug & MODES_DEBUG_NET)
printf("Created new client %d\n", fd);
if (Modes.debug & MODES_DEBUG_NET)
printf("Created new client %d\n", fd);
}
}
return Modes.clients;
}

View File

@ -115,6 +115,34 @@ void view1090Init(void) {
// Prepare error correction tables
modesInitErrorInfo();
}
// Set up data connection
int setupConnection(struct client *c) {
int fd;
// Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here.
if ((fd = anetTcpConnect(Modes.aneterr, View1090.net_input_beast_ipaddr, Modes.net_input_beast_port)) != ANET_ERR) {
anetNonBlock(Modes.aneterr, fd);
//
// Setup a service callback client structure for a beast binary input (from dump1090)
// This is a bit dodgy under Windows. The fd parameter is a handle to the internet
// socket on which we are receiving data. Under Linux, these seem to start at 0 and
// count upwards. However, Windows uses "HANDLES" and these don't nececeriy start at 0.
// dump1090 limits fd to values less than 1024, and then uses the fd parameter to
// index into an array of clients. This is ok-ish if handles are allocated up from 0.
// However, there is no gaurantee that Windows will behave like this, and if Windows
// allocates a handle greater than 1024, then dump1090 won't like it. On my test machine,
// the first Windows handle is usually in the 0x54 (84 decimal) region.
c->next = NULL;
c->buflen = 0;
c->fd =
c->service =
Modes.bis = fd;
Modes.clients = c;
}
return fd;
}
//
// ================================ Main ====================================
//
@ -181,6 +209,7 @@ void showCopyright(void) {
int main(int argc, char **argv) {
int j, fd;
struct client *c;
char pk_buf[8];
// Set sane defaults
@ -244,45 +273,32 @@ int main(int argc, char **argv) {
view1090Init();
// Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here.
if ((fd = anetTcpConnect(Modes.aneterr, View1090.net_input_beast_ipaddr, Modes.net_input_beast_port)) == ANET_ERR) {
c = (struct client *) malloc(sizeof(*c));
if ((fd = setupConnection(c)) == ANET_ERR) {
fprintf(stderr, "Failed to connect to %s:%d\n", View1090.net_input_beast_ipaddr, Modes.net_input_beast_port);
exit(1);
}
//
// Setup a service callback client structure for a beast binary input (from dump1090)
// This is a bit dodgy under Windows. The fd parameter is a handle to the internet
// socket on which we are receiving data. Under Linux, these seem to start at 0 and
// count upwards. However, Windows uses "HANDLES" and these don't nececeriy start at 0.
// dump1090 limits fd to values less than 1024, and then uses the fd parameter to
// index into an array of clients. This is ok-ish if handles are allocated up from 0.
// However, there is no gaurantee that Windows will behave like this, and if Windows
// allocates a handle greater than 1024, then dump1090 won't like it. On my test machine,
// the first Windows handle is usually in the 0x54 (84 decimal) region.
c = (struct client *) malloc(sizeof(*c));
c->next = NULL;
c->buflen = 0;
c->fd =
c->service =
Modes.bis = fd;
Modes.clients = c;
// Keep going till the user does something that stops us
while (!Modes.exit) {
modesReadFromClient(c,"",decodeBinMessage);
interactiveRemoveStaleAircrafts();
interactiveShowData();
if ((fd == ANET_ERR) || (recv(c->fd, pk_buf, sizeof(pk_buf), MSG_PEEK | MSG_DONTWAIT) == 0)) {
free(c);
usleep(1000000);
c = (struct client *) malloc(sizeof(*c));
fd = setupConnection(c);
continue;
}
modesReadFromClient(c,"",decodeBinMessage);
usleep(100000);
}
// The user has stopped us, so close any socket we opened
if (fd != ANET_ERR)
{close(fd);}
#ifndef _WIN32
pthread_exit(0);
#else
return (0);
#endif
}
//
//=========================================================================

View File

@ -49,6 +49,8 @@
#include <fcntl.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "rtl-sdr.h"
#include "anet.h"
#else