Skip to content
This repository was archived by the owner on Sep 14, 2019. It is now read-only.

Commit da2fff8

Browse files
committed
Proof of concept for an aircraft metadata DB.
1 parent d7c5047 commit da2fff8

File tree

6 files changed

+219
-1
lines changed

6 files changed

+219
-1
lines changed

public_html/dbloader.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// -*- mode: javascript; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2+
3+
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
4+
//
5+
// dbloader.js: load aircraft metadata from static json files
6+
//
7+
// Copyright (c) 2014,2015 Oliver Jowett <[email protected]>
8+
//
9+
// This file is free software: you may copy, redistribute and/or modify it
10+
// under the terms of the GNU General Public License as published by the
11+
// Free Software Foundation, either version 2 of the License, or (at your
12+
// option) any later version.
13+
//
14+
// This file is distributed in the hope that it will be useful, but
15+
// WITHOUT ANY WARRANTY; without even the implied warranty of
16+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17+
// General Public License for more details.
18+
//
19+
// You should have received a copy of the GNU General Public License
20+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+
"use strict";
23+
24+
var _aircraft_cache = {};
25+
26+
function getAircraftData(icao) {
27+
var defer;
28+
29+
icao = icao.toUpperCase();
30+
31+
if (icao in _aircraft_cache) {
32+
defer = _aircraft_cache[icao];
33+
} else {
34+
// load from blocks:
35+
defer = _aircraft_cache[icao] = $.Deferred();
36+
request_from_db(icao, 1, defer);
37+
}
38+
39+
return defer;
40+
}
41+
42+
function request_from_db(icao, level, defer) {
43+
var bkey = icao.substring(0, level);
44+
var dkey = icao.substring(level);
45+
var req = db_ajax(bkey);
46+
47+
req.done(function(data) {
48+
var subkey;
49+
50+
if ("children" in data) {
51+
subkey = bkey + dkey.substring(0,1);
52+
if (data.children.indexOf(subkey) == -1) {
53+
defer.reject();
54+
} else {
55+
request_from_db(icao, level+1, defer);
56+
}
57+
} else {
58+
if (dkey in data) {
59+
defer.resolve(data[dkey]);
60+
} else {
61+
defer.reject();
62+
}
63+
}
64+
});
65+
66+
req.fail(function(jqXHR,textStatus,errorThrown) {
67+
defer.reject();
68+
});
69+
}
70+
71+
var _request_count = 0;
72+
var _request_queue = [];
73+
var _request_cache = {};
74+
75+
var MAX_REQUESTS = 2;
76+
77+
function db_ajax(bkey) {
78+
var defer;
79+
80+
if (bkey in _request_cache) {
81+
return _request_cache[bkey];
82+
}
83+
84+
if (_request_count < MAX_REQUESTS) {
85+
// just do ajax directly
86+
++_request_count;
87+
defer = _request_cache[bkey] = $.ajax({ url: 'db/' + bkey + '.json',
88+
cache: true,
89+
timeout: 5000,
90+
dataType : 'json' });
91+
defer.always(db_ajax_request_complete);
92+
} else {
93+
// put it in the queue
94+
defer = _request_cache[bkey] = $.Deferred();
95+
defer.bkey = bkey;
96+
_request_queue.push(defer);
97+
}
98+
99+
return defer;
100+
}
101+
102+
function db_ajax_request_complete() {
103+
var req;
104+
var ajaxreq;
105+
106+
if (_request_queue.length == 0) {
107+
--_request_count;
108+
} else {
109+
req = _request_queue.shift();
110+
ajaxreq = $.ajax({ url: 'db/' + req.bkey + '.json',
111+
cache: true,
112+
timeout: 5000,
113+
dataType : 'json' });
114+
ajaxreq.done(function(data) { req.resolve(data); });
115+
ajaxreq.fail(function(jqxhr, status, error) { req.reject(jqxhr, status, error); });
116+
ajaxreq.always(db_ajax_request_complete);
117+
}
118+
}

public_html/gmap.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false&amp;libraries=geometry"></script>
99
<script type="text/javascript" src="config.js"></script>
1010
<script type="text/javascript" src="markers.js"></script>
11+
<script type="text/javascript" src="dbloader.js"></script>
1112
<script type="text/javascript" src="planeObject.js"></script>
1213
<script type="text/javascript" src="formatter.js"></script>
1314
<script type="text/javascript" src="script.js"></script>
@@ -114,6 +115,8 @@
114115
<span id="selected_icao"></span>
115116
</a>
116117

118+
<span id="selected_registration"></span>
119+
<span id="selected_icaotype"></span>
117120
<span id="selected_emergency"></span>
118121
<span id="selected_links">
119122
<a id="selected_fr24_link" href="" target="_blank">[FR24]</a>

public_html/planeObject.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,23 @@ function PlaneObject(icao) {
3636
this.marker = null;
3737
this.icon = { type: 'generic',
3838
fillOpacity: 0.9 };
39+
40+
// request metadata
41+
this.registration = null;
42+
this.icaotype = null;
43+
getAircraftData(this.icao).done(function(data) {
44+
if ("r" in data) {
45+
this.registration = data.r;
46+
}
47+
48+
if ("t" in data) {
49+
this.icaotype = data.t;
50+
}
51+
52+
if (this.selected) {
53+
refreshSelected();
54+
}
55+
}.bind(this));
3956
}
4057

4158
// Appends data to the running track so we can get a visual tail on the plane

public_html/script.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,19 @@ function refreshSelected() {
554554
$('#selected_callsign').text('n/a');
555555
$('#selected_links').css('display','none');
556556
}
557-
557+
558+
if (selected.registration !== null) {
559+
$('#selected_registration').text(selected.registration);
560+
} else {
561+
$('#selected_registration').text("");
562+
}
563+
564+
if (selected.icaotype !== null) {
565+
$('#selected_icaotype').text(selected.icaotype);
566+
} else {
567+
$('#selected_icaotype').text("");
568+
}
569+
558570
var emerg = document.getElementById('selected_emergency');
559571
if (selected.squawk in SpecialSquawks) {
560572
emerg.className = SpecialSquawks[selected.squawk].cssClass;

public_html/style.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ div#loader { z-index: 99; position: absolute; left: 0; top: 0; bottom: 0; right:
3434
.infoblock_body { font-size: small; }
3535

3636
#selected_icao { font-size: x-small; }
37+
#selected_registration { font-size: x-small; }
38+
#selected_icaotype { font-size: x-small; }
3739

3840
.dim { opacity: 0.3; filter:alpha(opacity=30); /* For IE8 and earlier */ }
3941

tools/vrs-basicaircraft-to-json.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/usr/bin/env python2
2+
3+
#
4+
# Converts a Virtual Radar Server BasicAircraftLookup.sqb database
5+
# into a bunch of json files suitable for use by the webmap
6+
#
7+
8+
import sqlite3, json
9+
from contextlib import closing
10+
11+
def extract(dbfile, todir, blocklimit):
12+
ac_count = 0
13+
block_count = 0
14+
15+
blocks = {}
16+
for i in xrange(16):
17+
blocks['%01X' % i] = {}
18+
19+
print 'Reading', dbfile
20+
with closing(sqlite3.connect(dbfile)) as db:
21+
with closing(db.execute('SELECT a.Icao, a.Registration, m.Icao FROM Aircraft a, Model m WHERE a.ModelID = m.ModelID')) as c:
22+
for icao24, reg, icaotype in c:
23+
bkey = icao24[0:1].upper()
24+
dkey = icao24[1:].upper()
25+
blocks[bkey][dkey] = {}
26+
if reg: blocks[bkey][dkey]['r'] = reg
27+
if icaotype: blocks[bkey][dkey]['t'] = icaotype
28+
ac_count += 1
29+
print 'Read', ac_count, 'aircraft'
30+
31+
queue = list(blocks.keys())
32+
while queue:
33+
bkey = queue[0]
34+
del queue[0]
35+
36+
blockdata = blocks[bkey]
37+
if len(blockdata) > blocklimit:
38+
print 'Splitting block', bkey, 'with', len(blockdata), 'entries..',
39+
children = {}
40+
for dkey in blockdata.keys():
41+
new_bkey = bkey + dkey[0]
42+
new_dkey = dkey[1:]
43+
44+
if new_bkey not in children: blocks[new_bkey] = children[new_bkey] = {}
45+
children[new_bkey][new_dkey] = blockdata[dkey]
46+
47+
print len(children), 'children'
48+
queue.extend(children.keys())
49+
blockdata = blocks[bkey] = { 'children' : sorted(children.keys()) }
50+
51+
path = todir + '/' + bkey + '.json'
52+
print 'Writing', len(blockdata), 'entries to', path
53+
block_count += 1
54+
with closing(open(path, 'w')) as f:
55+
json.dump(obj=blockdata, fp=f, check_circular=False, separators=(',',':'), sort_keys=True)
56+
57+
print 'Wrote', block_count, 'blocks'
58+
59+
if __name__ == '__main__':
60+
import sys
61+
if len(sys.argv) < 3:
62+
print 'Syntax: %s <path to BasicAircraftLookup.sqb> <path to DB dir>' % sys.argv[0]
63+
sys.exit(1)
64+
else:
65+
extract(sys.argv[1], sys.argv[2], 1000)
66+
sys.exit(0)

0 commit comments

Comments
 (0)