New feature: Output in SBS format
This commit is contained in:
parent
2fe188286e
commit
071a021f20
11
README.md
11
README.md
|
@ -152,6 +152,17 @@ Or alternatively to see what's happening on the screen:
|
||||||
|
|
||||||
Then you can feed it from different data sources from the internet.
|
Then you can feed it from different data sources from the internet.
|
||||||
|
|
||||||
|
Port 30003
|
||||||
|
---
|
||||||
|
|
||||||
|
Connected clients are served with messages in SBS1 (BaseStation) format, similar to:
|
||||||
|
|
||||||
|
MSG,4,,,738065,,,,,,,,420,179,,,0,,0,0,0,0
|
||||||
|
MSG,3,,,738065,,,,,,,35000,,,34.81609,34.07810,,,0,0,0,0
|
||||||
|
|
||||||
|
This can be used to feed data to various sharing sites without the need to use another decoder.
|
||||||
|
|
||||||
|
|
||||||
Antenna
|
Antenna
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
7
TODO
7
TODO
|
@ -8,10 +8,3 @@ TODO
|
||||||
aircraft ICAO address, like: 30xxxx -> Italy.
|
aircraft ICAO address, like: 30xxxx -> Italy.
|
||||||
* Actually use the fancy --debug feature in order to improve the recognition
|
* Actually use the fancy --debug feature in order to improve the recognition
|
||||||
algorithm if possibile.
|
algorithm if possibile.
|
||||||
* Listen to port 30003 and provide output in the following format, to
|
|
||||||
connected clients:
|
|
||||||
|
|
||||||
Server: Welcome to the adsb-server
|
|
||||||
MSG,3,0,19,4841D9,19,2013/01/05,15:51:45.747,2013/01/05,15:51:45.747,,33700,,,51.8853,-6.2134,,,0,0,0,0
|
|
||||||
MSG,4,0,15,405638,15,2013/01/05,15:51:45.747,2013/01/05,15:51:45.747,,,415,188,,,0,,0,0,0,0
|
|
||||||
...
|
|
||||||
|
|
76
dump1090.c
76
dump1090.c
|
@ -81,6 +81,7 @@
|
||||||
#define MODES_INTERACTIVE_TTL 60 /* TTL before being removed */
|
#define MODES_INTERACTIVE_TTL 60 /* TTL before being removed */
|
||||||
|
|
||||||
#define MODES_NET_MAX_FD 1024
|
#define MODES_NET_MAX_FD 1024
|
||||||
|
#define MODES_NET_OUTPUT_SBS_PORT 30003
|
||||||
#define MODES_NET_OUTPUT_RAW_PORT 30002
|
#define MODES_NET_OUTPUT_RAW_PORT 30002
|
||||||
#define MODES_NET_INPUT_RAW_PORT 30001
|
#define MODES_NET_INPUT_RAW_PORT 30001
|
||||||
#define MODES_NET_HTTP_PORT 8080
|
#define MODES_NET_HTTP_PORT 8080
|
||||||
|
@ -144,6 +145,7 @@ struct {
|
||||||
char aneterr[ANET_ERR_LEN];
|
char aneterr[ANET_ERR_LEN];
|
||||||
struct client *clients[MODES_NET_MAX_FD]; /* Our clients. */
|
struct client *clients[MODES_NET_MAX_FD]; /* Our clients. */
|
||||||
int maxfd; /* Greatest fd currently active. */
|
int maxfd; /* Greatest fd currently active. */
|
||||||
|
int sbsos; /* SBS output listening socket. */
|
||||||
int ros; /* Raw output listening socket. */
|
int ros; /* Raw output listening socket. */
|
||||||
int ris; /* Raw input listening socket. */
|
int ris; /* Raw input listening socket. */
|
||||||
int https; /* HTTP listening socket. */
|
int https; /* HTTP listening socket. */
|
||||||
|
@ -156,6 +158,7 @@ struct {
|
||||||
int debug; /* Debugging mode. */
|
int debug; /* Debugging mode. */
|
||||||
int net; /* Enable networking. */
|
int net; /* Enable networking. */
|
||||||
int net_only; /* Enable just networking. */
|
int net_only; /* Enable just networking. */
|
||||||
|
int net_output_sbs_port; /* SBS output TCP port. */
|
||||||
int net_output_raw_port; /* Raw output TCP port. */
|
int net_output_raw_port; /* Raw output TCP port. */
|
||||||
int net_input_raw_port; /* Raw input TCP port. */
|
int net_input_raw_port; /* Raw input TCP port. */
|
||||||
int net_http_port; /* HTTP port. */
|
int net_http_port; /* HTTP port. */
|
||||||
|
@ -180,6 +183,7 @@ struct {
|
||||||
long long stat_single_bit_fix;
|
long long stat_single_bit_fix;
|
||||||
long long stat_two_bits_fix;
|
long long stat_two_bits_fix;
|
||||||
long long stat_http_requests;
|
long long stat_http_requests;
|
||||||
|
long long stat_sbs_connections;
|
||||||
} Modes;
|
} Modes;
|
||||||
|
|
||||||
/* The struct we use to store information about a decoded message. */
|
/* The struct we use to store information about a decoded message. */
|
||||||
|
@ -227,8 +231,9 @@ struct modesMessage {
|
||||||
};
|
};
|
||||||
|
|
||||||
void interactiveShowData(void);
|
void interactiveShowData(void);
|
||||||
void interactiveReceiveData(struct modesMessage *mm);
|
struct aircraft* interactiveReceiveData(struct modesMessage *mm);
|
||||||
void modesSendRawOutput(struct modesMessage *mm);
|
void modesSendRawOutput(struct modesMessage *mm);
|
||||||
|
void modesSendSBSOutput(struct modesMessage *mm, struct aircraft *a);
|
||||||
void useModesMessage(struct modesMessage *mm);
|
void useModesMessage(struct modesMessage *mm);
|
||||||
int fixSingleBitErrors(unsigned char *msg, int bits);
|
int fixSingleBitErrors(unsigned char *msg, int bits);
|
||||||
int fixTwoBitsErrors(unsigned char *msg, int bits);
|
int fixTwoBitsErrors(unsigned char *msg, int bits);
|
||||||
|
@ -258,6 +263,7 @@ void modesInitConfig(void) {
|
||||||
Modes.raw = 0;
|
Modes.raw = 0;
|
||||||
Modes.net = 0;
|
Modes.net = 0;
|
||||||
Modes.net_only = 0;
|
Modes.net_only = 0;
|
||||||
|
Modes.net_output_sbs_port = MODES_NET_OUTPUT_SBS_PORT;
|
||||||
Modes.net_output_raw_port = MODES_NET_OUTPUT_RAW_PORT;
|
Modes.net_output_raw_port = MODES_NET_OUTPUT_RAW_PORT;
|
||||||
Modes.net_input_raw_port = MODES_NET_INPUT_RAW_PORT;
|
Modes.net_input_raw_port = MODES_NET_INPUT_RAW_PORT;
|
||||||
Modes.net_http_port = MODES_NET_HTTP_PORT;
|
Modes.net_http_port = MODES_NET_HTTP_PORT;
|
||||||
|
@ -311,6 +317,7 @@ void modesInit(void) {
|
||||||
Modes.stat_single_bit_fix = 0;
|
Modes.stat_single_bit_fix = 0;
|
||||||
Modes.stat_two_bits_fix = 0;
|
Modes.stat_two_bits_fix = 0;
|
||||||
Modes.stat_http_requests = 0;
|
Modes.stat_http_requests = 0;
|
||||||
|
Modes.stat_sbs_connections = 0;
|
||||||
Modes.exit = 0;
|
Modes.exit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1369,8 +1376,9 @@ void useModesMessage(struct modesMessage *mm) {
|
||||||
if (!Modes.stats && (Modes.check_crc == 0 || mm->crcok)) {
|
if (!Modes.stats && (Modes.check_crc == 0 || mm->crcok)) {
|
||||||
/* Track aircrafts in interactive mode or if the HTTP
|
/* Track aircrafts in interactive mode or if the HTTP
|
||||||
* interface is enabled. */
|
* interface is enabled. */
|
||||||
if (Modes.interactive || Modes.stat_http_requests > 0) {
|
if (Modes.interactive || Modes.stat_http_requests > 0 || Modes.stat_sbs_connections > 0) {
|
||||||
interactiveReceiveData(mm);
|
struct aircraft *a = interactiveReceiveData(mm);
|
||||||
|
if (a && Modes.stat_sbs_connections > 0) modesSendSBSOutput(mm, a); /* Feed SBS output clients. */
|
||||||
}
|
}
|
||||||
/* In non-interactive way, display messages on standard output. */
|
/* In non-interactive way, display messages on standard output. */
|
||||||
if (!Modes.interactive) {
|
if (!Modes.interactive) {
|
||||||
|
@ -1552,11 +1560,11 @@ void decodeCPR(struct aircraft *a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive new messages and populate the interactive mode with more info. */
|
/* Receive new messages and populate the interactive mode with more info. */
|
||||||
void interactiveReceiveData(struct modesMessage *mm) {
|
struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
struct aircraft *a, *aux;
|
struct aircraft *a, *aux;
|
||||||
|
|
||||||
if (Modes.check_crc && mm->crcok == 0) return;
|
if (Modes.check_crc && mm->crcok == 0) return NULL;
|
||||||
addr = (mm->aa1 << 16) | (mm->aa2 << 8) | mm->aa3;
|
addr = (mm->aa1 << 16) | (mm->aa2 << 8) | mm->aa3;
|
||||||
|
|
||||||
/* Loookup our aircraft or create a new one. */
|
/* Loookup our aircraft or create a new one. */
|
||||||
|
@ -1615,6 +1623,7 @@ void interactiveReceiveData(struct modesMessage *mm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show the currently captured interactive data on screen. */
|
/* Show the currently captured interactive data on screen. */
|
||||||
|
@ -1715,17 +1724,18 @@ void modesInitNet(void) {
|
||||||
char *descr;
|
char *descr;
|
||||||
int *socket;
|
int *socket;
|
||||||
int port;
|
int port;
|
||||||
} services[3] = {
|
} services[4] = {
|
||||||
{"Raw TCP output", &Modes.ros, Modes.net_output_raw_port},
|
{"Raw TCP output", &Modes.ros, Modes.net_output_raw_port},
|
||||||
{"Raw TCP input", &Modes.ris, Modes.net_input_raw_port},
|
{"Raw TCP input", &Modes.ris, Modes.net_input_raw_port},
|
||||||
{"HTTP server", &Modes.https, Modes.net_http_port}
|
{"HTTP server", &Modes.https, Modes.net_http_port},
|
||||||
|
{"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port}
|
||||||
};
|
};
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
memset(Modes.clients,0,sizeof(Modes.clients));
|
memset(Modes.clients,0,sizeof(Modes.clients));
|
||||||
Modes.maxfd = -1;
|
Modes.maxfd = -1;
|
||||||
|
|
||||||
for (j = 0; j < 3; j++) {
|
for (j = 0; j < 4; j++) {
|
||||||
int s = anetTcpServer(Modes.aneterr, services[j].port, NULL);
|
int s = anetTcpServer(Modes.aneterr, services[j].port, NULL);
|
||||||
if (s == -1) {
|
if (s == -1) {
|
||||||
fprintf(stderr, "Error opening the listening port %d (%s): %s\n",
|
fprintf(stderr, "Error opening the listening port %d (%s): %s\n",
|
||||||
|
@ -1746,11 +1756,12 @@ void modesAcceptClients(void) {
|
||||||
int fd, port;
|
int fd, port;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
struct client *c;
|
struct client *c;
|
||||||
int services[3];
|
int services[4];
|
||||||
|
|
||||||
services[0] = Modes.ros;
|
services[0] = Modes.ros;
|
||||||
services[1] = Modes.ris;
|
services[1] = Modes.ris;
|
||||||
services[2] = Modes.https;
|
services[2] = Modes.https;
|
||||||
|
services[3] = Modes.sbsos;
|
||||||
|
|
||||||
for (j = 0; j < sizeof(services)/sizeof(int); j++) {
|
for (j = 0; j < sizeof(services)/sizeof(int); j++) {
|
||||||
fd = anetTcpAccept(Modes.aneterr, services[j], NULL, &port);
|
fd = anetTcpAccept(Modes.aneterr, services[j], NULL, &port);
|
||||||
|
@ -1770,6 +1781,8 @@ void modesAcceptClients(void) {
|
||||||
anetSetSendBuffer(Modes.aneterr,fd,MODES_NET_SNDBUF_SIZE);
|
anetSetSendBuffer(Modes.aneterr,fd,MODES_NET_SNDBUF_SIZE);
|
||||||
|
|
||||||
if (Modes.maxfd < fd) Modes.maxfd = fd;
|
if (Modes.maxfd < fd) Modes.maxfd = fd;
|
||||||
|
if (services[j] == Modes.sbsos) Modes.stat_sbs_connections++;
|
||||||
|
|
||||||
j--; /* Try again with the same listening port. */
|
j--; /* Try again with the same listening port. */
|
||||||
|
|
||||||
if (Modes.debug == MODES_DEBUG_NET)
|
if (Modes.debug == MODES_DEBUG_NET)
|
||||||
|
@ -1829,6 +1842,48 @@ void modesSendRawOutput(struct modesMessage *mm) {
|
||||||
modesSendAllClients(Modes.ros, msg, p-msg);
|
modesSendAllClients(Modes.ros, msg, p-msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write SBS output to TCP clients. */
|
||||||
|
void modesSendSBSOutput(struct modesMessage *mm, struct aircraft *a) {
|
||||||
|
char msg[256], *p = msg;
|
||||||
|
int emergency = 0, ground = 0, alert = 0, spi = 0;
|
||||||
|
|
||||||
|
if (mm->msgtype == 4 || mm->msgtype == 5 || mm->msgtype == 21) {
|
||||||
|
if (mm->identity == 7500 || mm->identity == 7600 || mm->identity == 7700) emergency = -1; /* identity is calculated/kept in base10 but is actually octal (07500 is represented as 7500) */
|
||||||
|
if (mm->fs == 1 || mm->fs == 3) ground = -1;
|
||||||
|
if (mm->fs == 2 || mm->fs == 3 || mm->fs == 4) alert = -1;
|
||||||
|
if (mm->fs == 4 || mm->fs == 5) spi = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mm->msgtype == 0) {
|
||||||
|
p += sprintf(p, "MSG,5,,,%02X%02X%02X,,,,,,,%d,,,,,,,,,,", mm->aa1, mm->aa2, mm->aa3, mm->altitude);
|
||||||
|
} else if (mm->msgtype == 4) {
|
||||||
|
p += sprintf(p, "MSG,5,,,%02X%02X%02X,,,,,,,%d,,,,,,,%d,%d,%d,%d", mm->aa1, mm->aa2, mm->aa3, mm->altitude, alert, emergency, spi, ground);
|
||||||
|
} else if (mm->msgtype == 5) {
|
||||||
|
p += sprintf(p, "MSG,6,,,%02X%02X%02X,,,,,,,,,,,,,%d,%d,%d,%d,%d", mm->aa1, mm->aa2, mm->aa3, mm->identity, alert, emergency, spi, ground);
|
||||||
|
} else if (mm->msgtype == 11) {
|
||||||
|
p += sprintf(p, "MSG,8,,,%02X%02X%02X,,,,,,,,,,,,,,,,,", mm->aa1, mm->aa2, mm->aa3);
|
||||||
|
} else if (mm->msgtype == 17 && mm->metype == 4) {
|
||||||
|
p += sprintf(p, "MSG,1,,,%02X%02X%02X,,,,,,%s,,,,,,,,0,0,0,0", mm->aa1, mm->aa2, mm->aa3, mm->flight);
|
||||||
|
} else if (mm->msgtype == 17 && mm->metype >= 9 && mm->metype <= 18) {
|
||||||
|
if (a->lat == 0 && a->lon == 0)
|
||||||
|
p += sprintf(p, "MSG,3,,,%02X%02X%02X,,,,,,,%d,,,,,,,0,0,0,0", mm->aa1, mm->aa2, mm->aa3, mm->altitude);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "MSG,3,,,%02X%02X%02X,,,,,,,%d,,,%1.5f,%1.5f,,,0,0,0,0", mm->aa1, mm->aa2, mm->aa3, mm->altitude, a->lat, a->lon);
|
||||||
|
} else if (mm->msgtype == 17 && mm->metype == 19 && mm->mesub == 1) {
|
||||||
|
int vr = (mm->vert_rate_sign==0?1:-1) * (mm->vert_rate-1) * 64;
|
||||||
|
p += sprintf(p, "MSG,4,,,%02X%02X%02X,,,,,,,,%d,%d,,,%i,,0,0,0,0", mm->aa1, mm->aa2, mm->aa3, a->speed, a->track, vr);
|
||||||
|
} else if (mm->msgtype == 21) {
|
||||||
|
p += sprintf(p, "MSG,6,,,%02X%02X%02X,,,,,,,,,,,,,%d,%d,%d,%d,%d", mm->aa1, mm->aa2, mm->aa3, mm->identity, alert, emergency, spi, ground);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg == p) return; // empty string
|
||||||
|
|
||||||
|
*p++ = '\n';
|
||||||
|
|
||||||
|
modesSendAllClients(Modes.sbsos, msg, p-msg);
|
||||||
|
}
|
||||||
|
|
||||||
/* Turn an hex digit into its 4 bit decimal value.
|
/* Turn an hex digit into its 4 bit decimal value.
|
||||||
* Returns -1 if the digit is not in the 0-F range. */
|
* Returns -1 if the digit is not in the 0-F range. */
|
||||||
int hexDigitVal(int c) {
|
int hexDigitVal(int c) {
|
||||||
|
@ -2130,6 +2185,7 @@ void showHelp(void) {
|
||||||
"--net-ro-port <port> TCP listening port for raw output (default: 30002).\n"
|
"--net-ro-port <port> TCP listening port for raw output (default: 30002).\n"
|
||||||
"--net-ri-port <port> TCP listening port for raw input (default: 30001).\n"
|
"--net-ri-port <port> TCP listening port for raw input (default: 30001).\n"
|
||||||
"--net-http-port <port> HTTP server port (default: 8080).\n"
|
"--net-http-port <port> HTTP server port (default: 8080).\n"
|
||||||
|
"--net-sbs-port <port> TCP listening port for BaseStation format output (default: 30003).\n"
|
||||||
"--no-fix Disable single-bits error correction using CRC.\n"
|
"--no-fix Disable single-bits error correction using CRC.\n"
|
||||||
"--no-crc-check Disable messages with broken CRC (discouraged).\n"
|
"--no-crc-check Disable messages with broken CRC (discouraged).\n"
|
||||||
"--aggressive More CPU for more messages (two bits fixes, ...).\n"
|
"--aggressive More CPU for more messages (two bits fixes, ...).\n"
|
||||||
|
@ -2199,6 +2255,8 @@ int main(int argc, char **argv) {
|
||||||
Modes.net_input_raw_port = atoi(argv[++j]);
|
Modes.net_input_raw_port = atoi(argv[++j]);
|
||||||
} else if (!strcmp(argv[j],"--net-http-port") && more) {
|
} else if (!strcmp(argv[j],"--net-http-port") && more) {
|
||||||
Modes.net_http_port = atoi(argv[++j]);
|
Modes.net_http_port = atoi(argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--net-sbs-port") && more) {
|
||||||
|
Modes.net_output_sbs_port = atoi(argv[++j]);
|
||||||
} else if (!strcmp(argv[j],"--onlyaddr")) {
|
} else if (!strcmp(argv[j],"--onlyaddr")) {
|
||||||
Modes.onlyaddr = 1;
|
Modes.onlyaddr = 1;
|
||||||
} else if (!strcmp(argv[j],"--metric")) {
|
} else if (!strcmp(argv[j],"--metric")) {
|
||||||
|
|
Loading…
Reference in a new issue