receiver.json support, internal webserver cleanup.
Add data/receiver.json (generated once) and support for it in script.js. Internal webserver rearrangement to support multiple json files.
This commit is contained in:
parent
f707f2cdce
commit
9fa09e0e92
2
debian/changelog
vendored
2
debian/changelog
vendored
|
@ -5,6 +5,8 @@ dump1090-mutability (1.08.2302.14+1mu-3) UNRELEASED; urgency=medium
|
||||||
* Be much more cautious about missing config settings so we don't explode
|
* Be much more cautious about missing config settings so we don't explode
|
||||||
so badly if something is omitted.
|
so badly if something is omitted.
|
||||||
* Use the package version as the version number compiled into the binary.
|
* Use the package version as the version number compiled into the binary.
|
||||||
|
* Add data/receiver.json (generated once) and support for it in script.js.
|
||||||
|
* Internal webserver rearrangement to support multiple json files.
|
||||||
|
|
||||||
-- Oliver Jowett <oliver@mutability.co.uk> Wed, 10 Dec 2014 02:01:27 +0000
|
-- Oliver Jowett <oliver@mutability.co.uk> Wed, 10 Dec 2014 02:01:27 +0000
|
||||||
|
|
||||||
|
|
19
dump1090.c
19
dump1090.c
|
@ -634,14 +634,15 @@ void backgroundTasks(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Modes.json_path && Modes.json_interval > 0) {
|
if (Modes.json_aircraft_path && Modes.json_interval > 0) {
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
if (now >= next_json) {
|
if (now >= next_json) {
|
||||||
modesWriteJson(Modes.json_path);
|
writeJsonToFile(Modes.json_aircraft_path, generateAircraftJson);
|
||||||
next_json = now + Modes.json_interval;
|
next_json = now + Modes.json_interval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//
|
//
|
||||||
|
@ -837,9 +838,13 @@ int main(int argc, char **argv) {
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
} else if (!strcmp(argv[j], "--write-json") && more) {
|
} else if (!strcmp(argv[j], "--write-json") && more) {
|
||||||
++j;
|
++j;
|
||||||
Modes.json_path = malloc(strlen(argv[j]) + 15);
|
Modes.json_aircraft_path = malloc(strlen(argv[j]) + 15);
|
||||||
strcpy(Modes.json_path, argv[j]);
|
strcpy(Modes.json_aircraft_path, argv[j]);
|
||||||
strcat(Modes.json_path, "/aircraft.json");
|
strcat(Modes.json_aircraft_path, "/aircraft.json");
|
||||||
|
|
||||||
|
Modes.json_metadata_path = malloc(strlen(argv[j]) + 15);
|
||||||
|
strcpy(Modes.json_metadata_path, argv[j]);
|
||||||
|
strcat(Modes.json_metadata_path, "/receiver.json");
|
||||||
} else if (!strcmp(argv[j], "--write-json-every") && more) {
|
} else if (!strcmp(argv[j], "--write-json-every") && more) {
|
||||||
Modes.json_interval = atoi(argv[++j]);
|
Modes.json_interval = atoi(argv[++j]);
|
||||||
#endif
|
#endif
|
||||||
|
@ -908,6 +913,10 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
if (Modes.net) modesInitNet();
|
if (Modes.net) modesInitNet();
|
||||||
|
|
||||||
|
if (Modes.json_metadata_path && Modes.json_interval > 0) {
|
||||||
|
writeJsonToFile(Modes.json_metadata_path, generateReceiverJson); // once only on startup
|
||||||
|
}
|
||||||
|
|
||||||
// If the user specifies --net-only, just run in order to serve network
|
// If the user specifies --net-only, just run in order to serve network
|
||||||
// clients without reading data from the RTL device
|
// clients without reading data from the RTL device
|
||||||
while (Modes.net_only) {
|
while (Modes.net_only) {
|
||||||
|
|
10
dump1090.h
10
dump1090.h
|
@ -369,8 +369,9 @@ struct { // Internal state
|
||||||
int mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...;
|
int mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...;
|
||||||
int interactive_rtl1090; // flight table in interactive mode is formatted like RTL1090
|
int interactive_rtl1090; // flight table in interactive mode is formatted like RTL1090
|
||||||
int no_decode; // Disable decoding and aircraft tracking
|
int no_decode; // Disable decoding and aircraft tracking
|
||||||
char *json_path; // Path to json data file to write, or NULL not to.
|
char *json_aircraft_path; // Path to json aircraft file to write, or NULL not to.
|
||||||
int json_interval; // Interval between rewriting the json data file
|
char *json_metadata_path; // Path to json metadata file to write, or NULL not to.
|
||||||
|
int json_interval; // Interval between rewriting the json aircraft file
|
||||||
|
|
||||||
// User details
|
// User details
|
||||||
double fUserLat; // Users receiver/antenna lat/lon needed for initial surface location
|
double fUserLat; // Users receiver/antenna lat/lon needed for initial surface location
|
||||||
|
@ -495,7 +496,10 @@ void modesInitNet (void);
|
||||||
void modesQueueOutput (struct modesMessage *mm);
|
void modesQueueOutput (struct modesMessage *mm);
|
||||||
void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *));
|
void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *));
|
||||||
void modesNetPeriodicWork (void);
|
void modesNetPeriodicWork (void);
|
||||||
void modesWriteJson (const char *path);
|
|
||||||
|
void writeJsonToFile(const char *path, char * (*generator) (int*));
|
||||||
|
char *generateAircraftJson(int *len);
|
||||||
|
char *generateReceiverJson(int *len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
120
net_io.c
120
net_io.c
|
@ -667,7 +667,7 @@ int decodeHexMessage(struct client *c, char *hex) {
|
||||||
//
|
//
|
||||||
// Return a description of planes in json. No metric conversion
|
// Return a description of planes in json. No metric conversion
|
||||||
//
|
//
|
||||||
char *aircraftsToJson(int *len) {
|
char *generateAircraftJson(int *len) {
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
struct aircraft *a = Modes.aircrafts;
|
struct aircraft *a = Modes.aircrafts;
|
||||||
int buflen = 1024; // The initial buffer is incremented as needed
|
int buflen = 1024; // The initial buffer is incremented as needed
|
||||||
|
@ -727,15 +727,40 @@ char *aircraftsToJson(int *len) {
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write JSON state to json_path
|
//
|
||||||
void modesWriteJson(const char *path)
|
// Return a description of the receiver in json.
|
||||||
|
//
|
||||||
|
char *generateReceiverJson(int *len)
|
||||||
|
{
|
||||||
|
char *buf = (char *) malloc(1024), *p = buf;
|
||||||
|
|
||||||
|
p += sprintf(p, "{ " \
|
||||||
|
"\"version\" : \"%s\", "
|
||||||
|
"\"refresh\" : %d",
|
||||||
|
MODES_DUMP1090_VERSION, Modes.json_interval * 1000);
|
||||||
|
|
||||||
|
if (Modes.fUserLat != 0.0 || Modes.fUserLon != 0.0) {
|
||||||
|
p += sprintf(p, ", " \
|
||||||
|
"\"lat\" : %.2f, "
|
||||||
|
"\"lon\" : %.2f",
|
||||||
|
Modes.fUserLat, Modes.fUserLon); // round to 2dp - about 0.5-1km accuracy - for privacy reasons
|
||||||
|
}
|
||||||
|
|
||||||
|
p += sprintf(p, " }\n");
|
||||||
|
|
||||||
|
*len = (p - buf);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write JSON to file
|
||||||
|
void writeJsonToFile(const char *path, char * (*generator) (int*))
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
char tmppath[PATH_MAX];
|
char tmppath[PATH_MAX];
|
||||||
int fd;
|
int fd;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
char *content;
|
|
||||||
mode_t mask;
|
mode_t mask;
|
||||||
|
char *content;
|
||||||
|
|
||||||
snprintf(tmppath, PATH_MAX, "%s.XXXXXX", path);
|
snprintf(tmppath, PATH_MAX, "%s.XXXXXX", path);
|
||||||
tmppath[PATH_MAX-1] = 0;
|
tmppath[PATH_MAX-1] = 0;
|
||||||
|
@ -747,27 +772,29 @@ void modesWriteJson(const char *path)
|
||||||
umask(mask);
|
umask(mask);
|
||||||
fchmod(fd, 0644 & ~mask);
|
fchmod(fd, 0644 & ~mask);
|
||||||
|
|
||||||
content = aircraftsToJson(&len);
|
content = generator(&len);
|
||||||
|
|
||||||
if (write(fd, content, len) != len)
|
if (write(fd, content, len) != len)
|
||||||
goto error_1;
|
goto error_1;
|
||||||
|
|
||||||
if (close(fd) < 0)
|
if (close(fd) < 0)
|
||||||
goto error_2;
|
goto error_2;
|
||||||
|
|
||||||
free(content);
|
|
||||||
rename(tmppath, path);
|
rename(tmppath, path);
|
||||||
|
free(content);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error_1:
|
error_1:
|
||||||
close(fd);
|
close(fd);
|
||||||
error_2:
|
error_2:
|
||||||
free(content);
|
|
||||||
unlink(tmppath);
|
unlink(tmppath);
|
||||||
|
free(content);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//
|
//
|
||||||
|
@ -775,6 +802,17 @@ void modesWriteJson(const char *path)
|
||||||
#define MODES_CONTENT_TYPE_CSS "text/css;charset=utf-8"
|
#define MODES_CONTENT_TYPE_CSS "text/css;charset=utf-8"
|
||||||
#define MODES_CONTENT_TYPE_JSON "application/json;charset=utf-8"
|
#define MODES_CONTENT_TYPE_JSON "application/json;charset=utf-8"
|
||||||
#define MODES_CONTENT_TYPE_JS "application/javascript;charset=utf-8"
|
#define MODES_CONTENT_TYPE_JS "application/javascript;charset=utf-8"
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char *path;
|
||||||
|
char * (*handler)(int*);
|
||||||
|
char *content_type;
|
||||||
|
} url_handlers[] = {
|
||||||
|
{ "/data/aircraft.json", generateAircraftJson, MODES_CONTENT_TYPE_JSON },
|
||||||
|
{ "/data/receiver.json", generateReceiverJson, MODES_CONTENT_TYPE_JSON },
|
||||||
|
{ NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get an HTTP request header and write the response to the client.
|
// Get an HTTP request header and write the response to the client.
|
||||||
// gain here we assume that the socket buffer is enough without doing
|
// gain here we assume that the socket buffer is enough without doing
|
||||||
|
@ -788,10 +826,10 @@ int handleHTTPRequest(struct client *c, char *p) {
|
||||||
int clen, hdrlen;
|
int clen, hdrlen;
|
||||||
int httpver, keepalive;
|
int httpver, keepalive;
|
||||||
int statuscode = 500;
|
int statuscode = 500;
|
||||||
char *url, *content;
|
char *url, *content = NULL;
|
||||||
char ctype[48];
|
|
||||||
char getFile[1024];
|
|
||||||
char *ext;
|
char *ext;
|
||||||
|
char *content_type;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (Modes.debug & MODES_DEBUG_NET)
|
if (Modes.debug & MODES_DEBUG_NET)
|
||||||
printf("\nHTTP request: %s\n", c->buf);
|
printf("\nHTTP request: %s\n", c->buf);
|
||||||
|
@ -820,23 +858,30 @@ int handleHTTPRequest(struct client *c, char *p) {
|
||||||
printf("HTTP requested URL: %s\n\n", url);
|
printf("HTTP requested URL: %s\n\n", url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(url) < 2) {
|
statuscode = 404;
|
||||||
snprintf(getFile, sizeof getFile, "%s/gmap.html", HTMLPATH); // Default file
|
for (i = 0; url_handlers[i].path; ++i) {
|
||||||
} else {
|
if (!strcmp(url, url_handlers[i].path)) {
|
||||||
snprintf(getFile, sizeof getFile, "%s/%s", HTMLPATH, url);
|
content_type = url_handlers[i].content_type;
|
||||||
|
content = url_handlers[i].handler(&clen);
|
||||||
|
statuscode = 200;
|
||||||
|
if (Modes.debug & MODES_DEBUG_NET) {
|
||||||
|
printf("HTTP: 200: %s -> internal (%d bytes, %s)\n", url, clen, content_type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select the content to send, we have just two so far:
|
if (!content) {
|
||||||
// "/" -> Our google map application.
|
|
||||||
// "/aircraft.json" -> Our ajax request to update planes.
|
|
||||||
if (strstr(url, "/data/aircraft.json")) {
|
|
||||||
statuscode = 200;
|
|
||||||
content = aircraftsToJson(&clen);
|
|
||||||
//snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JSON);
|
|
||||||
} else {
|
|
||||||
struct stat sbuf;
|
struct stat sbuf;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
char rp[PATH_MAX], hrp[PATH_MAX];
|
char rp[PATH_MAX], hrp[PATH_MAX];
|
||||||
|
char getFile[1024];
|
||||||
|
|
||||||
|
if (strlen(url) < 2) {
|
||||||
|
snprintf(getFile, sizeof getFile, "%s/gmap.html", HTMLPATH); // Default file
|
||||||
|
} else {
|
||||||
|
snprintf(getFile, sizeof getFile, "%s/%s", HTMLPATH, url);
|
||||||
|
}
|
||||||
|
|
||||||
if (!realpath(getFile, rp))
|
if (!realpath(getFile, rp))
|
||||||
rp[0] = 0;
|
rp[0] = 0;
|
||||||
|
@ -866,22 +911,27 @@ int handleHTTPRequest(struct client *c, char *p) {
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Get file extension and content type
|
// Get file extension and content type
|
||||||
snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_HTML); // Default content type
|
content_type = MODES_CONTENT_TYPE_HTML; // Default content type
|
||||||
ext = strrchr(getFile, '.');
|
ext = strrchr(getFile, '.');
|
||||||
|
|
||||||
if (strlen(ext) > 0) {
|
if (strlen(ext) > 0) {
|
||||||
if (strstr(ext, ".json")) {
|
if (strstr(ext, ".json")) {
|
||||||
snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JSON);
|
content_type = MODES_CONTENT_TYPE_JSON;
|
||||||
} else if (strstr(ext, ".css")) {
|
} else if (strstr(ext, ".css")) {
|
||||||
snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_CSS);
|
content_type = MODES_CONTENT_TYPE_CSS;
|
||||||
} else if (strstr(ext, ".js")) {
|
} else if (strstr(ext, ".js")) {
|
||||||
snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JS);
|
content_type = MODES_CONTENT_TYPE_JS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Modes.debug & MODES_DEBUG_NET) {
|
||||||
|
printf("HTTP: %d: %s -> %s (%d bytes, %s)\n", statuscode, url, rp, clen, content_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create the header and send the reply
|
// Create the header and send the reply
|
||||||
hdrlen = snprintf(hdr, sizeof(hdr),
|
hdrlen = snprintf(hdr, sizeof(hdr),
|
||||||
"HTTP/1.1 %d \r\n"
|
"HTTP/1.1 %d \r\n"
|
||||||
|
@ -893,7 +943,7 @@ int handleHTTPRequest(struct client *c, char *p) {
|
||||||
"Expires: Sat, 26 Jul 1997 05:00:00 GMT\r\n"
|
"Expires: Sat, 26 Jul 1997 05:00:00 GMT\r\n"
|
||||||
"\r\n",
|
"\r\n",
|
||||||
statuscode,
|
statuscode,
|
||||||
ctype,
|
content_type,
|
||||||
keepalive ? "keep-alive" : "close",
|
keepalive ? "keep-alive" : "close",
|
||||||
clen);
|
clen);
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@ CenterLat = Number(localStorage['CenterLat']) || CONST_CENTERLAT;
|
||||||
CenterLon = Number(localStorage['CenterLon']) || CONST_CENTERLON;
|
CenterLon = Number(localStorage['CenterLon']) || CONST_CENTERLON;
|
||||||
ZoomLvl = Number(localStorage['ZoomLvl']) || CONST_ZOOMLVL;
|
ZoomLvl = Number(localStorage['ZoomLvl']) || CONST_ZOOMLVL;
|
||||||
|
|
||||||
|
Dump1090Version = "unknown version";
|
||||||
|
RefreshInterval = 1000;
|
||||||
|
|
||||||
function fetchData() {
|
function fetchData() {
|
||||||
$.getJSON('data/aircraft.json', function(data) {
|
$.getJSON('data/aircraft.json', function(data) {
|
||||||
PlanesOnMap = 0
|
PlanesOnMap = 0
|
||||||
|
@ -32,15 +35,10 @@ function fetchData() {
|
||||||
var plane = jQuery.extend(true, {}, planeObject);
|
var plane = jQuery.extend(true, {}, planeObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For special squawk tests
|
// Set SpecialSquawk-value
|
||||||
if (data[j].hex == '48413x') {
|
if (data[j].squawk == '7500' || data[j].squawk == '7600' || data[j].squawk == '7700') {
|
||||||
data[j].squawk = '7700';
|
SpecialSquawk = true;
|
||||||
} //*/
|
}
|
||||||
|
|
||||||
// Set SpecialSquawk-value
|
|
||||||
if (data[j].squawk == '7500' || data[j].squawk == '7600' || data[j].squawk == '7700') {
|
|
||||||
SpecialSquawk = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the function update
|
// Call the function update
|
||||||
plane.funcUpdateData(data[j]);
|
plane.funcUpdateData(data[j]);
|
||||||
|
@ -53,8 +51,25 @@ function fetchData() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initalizes the map and starts up our timers to call various functions
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
|
// Get receiver metadata, reconfigure using it, then continue
|
||||||
|
// with initialization
|
||||||
|
$.getJSON('data/receiver.json')
|
||||||
|
.done(function(data) {
|
||||||
|
if (typeof data.receiverlat !== "undefined") {
|
||||||
|
SiteShow = true;
|
||||||
|
SiteLat = data.receiverlat;
|
||||||
|
SiteLon = data.receiverlon;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dump1090Version = data.version;
|
||||||
|
RefreshInterval = data.refresh;
|
||||||
|
})
|
||||||
|
.always(initialize_after_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initalizes the map and starts up our timers to call various functions
|
||||||
|
function initialize_after_config() {
|
||||||
// Make a list of all the available map IDs
|
// Make a list of all the available map IDs
|
||||||
var mapTypeIds = [];
|
var mapTypeIds = [];
|
||||||
for(var type in google.maps.MapTypeId) {
|
for(var type in google.maps.MapTypeId) {
|
||||||
|
@ -209,7 +224,7 @@ function initialize() {
|
||||||
refreshSelected();
|
refreshSelected();
|
||||||
reaper();
|
reaper();
|
||||||
extendedPulse();
|
extendedPulse();
|
||||||
}, 1000);
|
}, RefreshInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This looks for planes to reap out of the master Planes variable
|
// This looks for planes to reap out of the master Planes variable
|
||||||
|
@ -257,7 +272,7 @@ function refreshSelected() {
|
||||||
html += '<tr><td colspan="' + columns + '" id="selectedinfotitle"><b>' +
|
html += '<tr><td colspan="' + columns + '" id="selectedinfotitle"><b>' +
|
||||||
selected.flight + '</b>';
|
selected.flight + '</b>';
|
||||||
} else {
|
} else {
|
||||||
html += '<tr><td colspan="' + columns + '" id="selectedinfotitle"><b>DUMP1090</b>';
|
html += '<tr><td colspan="' + columns + '" id="selectedinfotitle"><b>DUMP1090 ' + Dump1090Version + '</b>';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected && selected.squawk == 7500) { // Lets hope we never see this... Aircraft Hijacking
|
if (selected && selected.squawk == 7500) { // Lets hope we never see this... Aircraft Hijacking
|
||||||
|
|
Loading…
Reference in a new issue