New feature: Output in SBS format

This commit is contained in:
Kemal Hadimli 2013-01-17 20:12:23 +02:00 committed by antirez
parent 2fe188286e
commit 071a021f20
3 changed files with 78 additions and 16 deletions

View file

@ -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
View file

@ -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
...

View file

@ -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")) {