From 8d171b6494251d5efb635219e37fddf967a70fca Mon Sep 17 00:00:00 2001 From: Paul Tomlinson Date: Sun, 5 Jul 2015 09:55:43 -0600 Subject: [PATCH 1/6] Clarifies whitespace, adds "--home" attribute for quick configuration of web interface, and adds loc.json pull to retrieve home or lat/lon details. --- dump1090.c | 115 +++++++++++++++++++++--------------------- dump1090.h | 1 + net_io.c | 144 ++++++++++++++++++++++++++++++++++------------------- 3 files changed, 152 insertions(+), 108 deletions(-) diff --git a/dump1090.c b/dump1090.c index 60882fc73..e36f23048 100644 --- a/dump1090.c +++ b/dump1090.c @@ -422,6 +422,7 @@ void showHelp(void) { "--net-buffer TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n" "--lat Reference/receiver latitude for surface posn (opt)\n" "--lon Reference/receiver longitude for surface posn (opt)\n" +"--home Google Maps Search String for setting map \"home\" (opt, overrides lat/long in map)\n" "--fix Enable 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" @@ -600,62 +601,62 @@ 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 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; } // //========================================================================= @@ -741,6 +742,8 @@ int main(int argc, char **argv) { Modes.fUserLat = atof(argv[++j]); } else if (!strcmp(argv[j],"--lon") && more) { Modes.fUserLon = atof(argv[++j]); + } else if (!strcmp(argv[j],"--home") && more) { + Modes.home = strdup(argv[++j]); } else if (!strcmp(argv[j],"--debug") && more) { char *f = argv[++j]; while(*f) { diff --git a/dump1090.h b/dump1090.h index 9ad4de037..08769a96a 100644 --- a/dump1090.h +++ b/dump1090.h @@ -322,6 +322,7 @@ struct { // Internal state // User details double fUserLat; // Users receiver/antenna lat/lon needed for initial surface location double fUserLon; // Users receiver/antenna lat/lon needed for initial surface location + char *home; // Address lookup for net:map interface. int bUserFlags; // Flags relating to the user details // Interactive mode diff --git a/net_io.c b/net_io.c index a979883f5..2962616ac 100644 --- a/net_io.c +++ b/net_io.c @@ -47,10 +47,10 @@ // Networking "stack" initialization // struct service { - char *descr; - int *socket; - int port; - int enabled; + char *descr; + int *socket; + int port; + int enabled; }; struct service services[MODES_NET_SERVICES_NUM]; @@ -58,16 +58,16 @@ struct service services[MODES_NET_SERVICES_NUM]; void modesInitNet(void) { 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} - }; + 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} + }; - memcpy(&services, &svc, sizeof(svc));//services = svc; + memcpy(&services, &svc, sizeof(svc));//services = svc; Modes.clients = NULL; @@ -83,19 +83,19 @@ void modesInitNet(void) { #endif for (j = 0; j < MODES_NET_SERVICES_NUM; j++) { - services[j].enabled = (services[j].port != 0); - if (services[j].enabled) { - int s = anetTcpServer(Modes.aneterr, services[j].port, Modes.net_bind_address); - if (s == -1) { - fprintf(stderr, "Error opening the listening port %d (%s): %s\n", - services[j].port, services[j].descr, Modes.aneterr); - 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); - } + services[j].enabled = (services[j].port != 0); + if (services[j].enabled) { + int s = anetTcpServer(Modes.aneterr, services[j].port, Modes.net_bind_address); + if (s == -1) { + fprintf(stderr, "Error opening the listening port %d (%s): %s\n", + services[j].port, services[j].descr, Modes.aneterr); + 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 @@ -114,28 +114,28 @@ struct client * modesAcceptClients(void) { struct client *c; for (j = 0; j < MODES_NET_SERVICES_NUM; j++) { - 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].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].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++; - - j--; // Try again with the same listening port - - if (Modes.debug & MODES_DEBUG_NET) - printf("Created new client %d\n", fd); - } + 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].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].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++; + + j--; // Try again with the same listening port + + if (Modes.debug & MODES_DEBUG_NET) + printf("Created new client %d\n", fd); + } } return Modes.clients; } @@ -169,7 +169,7 @@ void modesFreeClient(struct client *c) { // Close the client connection and mark it as closed // void modesCloseClient(struct client *c) { - close(c->fd); + close(c->fd); if (c->service == Modes.sbsos) { if (Modes.stat_sbs_connections) Modes.stat_sbs_connections--; } else if (c->service == Modes.ros) { @@ -697,6 +697,43 @@ char *aircraftsToJson(int *len) { // //========================================================================= // + +// +//========================================================================= +// +// Return a home location using the home string if set, or lat/long +// +char *locationToJson(int *len) { + unsigned int buflen = 1024; // The initial buffer is incremented as needed + char *buf = (char *) malloc(buflen), *p = buf; + int l; + + if (Modes.home != NULL) { + // Prevent buffer overrun by making it Modes.home length + // plus 1024 (because we sure aren't going to use that + // much around it, so we're nice and safe). + if ( buflen < strlen( Modes.home ) ) { + buflen += strlen( Modes.home ); + buf = (char *) realloc(buf, buflen); + } + l = snprintf( p, buflen, "{\"home\":\"%s\"}\n", Modes.home ); + } else if (Modes.fUserLat || Modes.fUserLon) { + l = snprintf( + p, buflen, + "{\"lat\":%f, \"lon\":%f}\n", + Modes.fUserLat, Modes.fUserLon + ); + } else { + l = snprintf( p, buflen, "{}\n" ); + } + p += l; buflen -= l; + + *len = p-buf; + return buf; +} +// +//========================================================================= +// #define MODES_CONTENT_TYPE_HTML "text/html;charset=utf-8" #define MODES_CONTENT_TYPE_CSS "text/css;charset=utf-8" #define MODES_CONTENT_TYPE_JSON "application/json;charset=utf-8" @@ -759,6 +796,9 @@ int handleHTTPRequest(struct client *c, char *p) { statuscode = 200; content = aircraftsToJson(&clen); //snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JSON); + } else if (strstr(url, "/loc.json")) { + statuscode = 200; + content = locationToJson(&clen); } else { struct stat sbuf; int fd = -1; @@ -880,9 +920,9 @@ void modesReadFromClient(struct client *c, char *sep, if (nread < 0) {errno = WSAGetLastError();} #endif if (nread == 0) { - modesCloseClient(c); - return; - } + modesCloseClient(c); + return; + } // If we didn't get all the data we asked for, then return once we've processed what we did get. if (nread != left) { From d549e02c5d1b78bcd0a4e987e0f36d5c4d864e96 Mon Sep 17 00:00:00 2001 From: Paul Tomlinson Date: Sun, 5 Jul 2015 10:01:45 -0600 Subject: [PATCH 2/6] - Add automatic Site configuration based on dump1090 args - Add plane path projection (with supporting calls) - Add plane projection animation - Show data retrieval heartbeat in UI - Add ICAO lookup via airframes.org - Refines cardinality fetch (bearing to compass ref) - Adds bearing-to-selected-plane - Adds sweep line to selected plane (helpful when off-screen) - Standardizes whitespace - W3C validation for HTML5 corrections - Add configuration options (to config.js) for new features (defaults to on) - Several small bug fixes (boundary checking, variable spelling, and performance enhancements) --- public_html/config.js | 39 ++- public_html/gmap.html | 32 +- public_html/planeObject.js | 202 ++++++++---- public_html/script.js | 609 ++++++++++++++++++++++--------------- public_html/style.css | 1 + 5 files changed, 567 insertions(+), 316 deletions(-) diff --git a/public_html/config.js b/public_html/config.js index f7d8e2eb1..a008e6cc7 100644 --- a/public_html/config.js +++ b/public_html/config.js @@ -7,10 +7,10 @@ // -- Output Settings ------------------------------------- // Show metric values -Metric = false; // true or false +Metric = false; // true or false (Boolean) // -- Map settings ---------------------------------------- -// The Latitude and Longitude in decimal format +// The default Latitude and Longitude in decimal format CONST_CENTERLAT = 45.0; CONST_CENTERLON = 9.0; // The google maps zoom level, 0 - 16, lower is further out @@ -23,12 +23,39 @@ SelectedColor = "rgb(225, 225, 225)"; StaleColor = "rgb(190, 190, 190)"; // -- Site Settings --------------------------------------- -SiteShow = false; // true or false -// The Latitude and Longitude in decimal format -SiteLat = 45.0; -SiteLon = 9.0; +// If SiteFromLoc is true, a call will be made to the server +// to fetch any location settings passed to it on startup in +// the form of --lat and --lon, or --home (which can be a +// free text string which will use Google Maps to resolve to +// a known location). If a location is successfully identified +// from the server's data, SiteShow will automatically be set +// to "true" as well, and SiteLat & SiteLon will be updated +// to the identified coordinates. +SiteFromLoc = true; + +SiteShow = false; // Boolean +// The Latitude and Longitude in decimal format (use defaults) +SiteLat = CONST_CENTERLAT; +SiteLon = CONST_CENTERLON; SiteCircles = true; // true or false (Only shown if SiteShow is true) // In nautical miles or km (depending settings value 'Metric') SiteCirclesDistances = new Array(100,150,200); +SiteSweep = true; // Draw a line from the Site to the selected Plane +SweepColor = 'rgb(0, 255, 255)'; // ...in this color + +// If true, turns projections on. Projections are a line in front +// of a plane based on its last known heading and speed, set +// ProjectionDist seconds in the future. This allows for interpolation +// between positional updates, and in practice has proven remarkably +// accurate, though tight turns with infrequent updates will be off. +// Note: Does not account for acceleration, deceleration, or curved +// paths. +PlaneProjection = true; +ProjectionColor = 'rgb(0, 0, 255)'; // Color of the projection line +ProjectionDist = 60; // Time in seconds +// Shows a smaller, lighter plane icon (derived from the plane's icon +// setting, whatever that may be) moving along the projection line at +// a rate consistent with the last known speed. +ProjectionAnimation = true; diff --git a/public_html/gmap.html b/public_html/gmap.html index 9ab2dc28d..9dfc71c16 100644 --- a/public_html/gmap.html +++ b/public_html/gmap.html @@ -1,3 +1,4 @@ + @@ -14,9 +15,9 @@ - DUMP1090 + DUMP1090 - + @@ -26,29 +27,24 @@