diff --git a/public_html/dbloader.js b/public_html/dbloader.js new file mode 100644 index 0000000..e824232 --- /dev/null +++ b/public_html/dbloader.js @@ -0,0 +1,118 @@ +// -*- mode: javascript; indent-tabs-mode: nil; c-basic-offset: 8 -*- + +// Part of dump1090, a Mode S message decoder for RTLSDR devices. +// +// dbloader.js: load aircraft metadata from static json files +// +// Copyright (c) 2014,2015 Oliver Jowett +// +// This file is free software: you may copy, redistribute and/or modify it +// under the terms of the GNU General Public License as published by the +// Free Software Foundation, either version 2 of the License, or (at your +// option) any later version. +// +// This file is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +"use strict"; + +var _aircraft_cache = {}; + +function getAircraftData(icao) { + var defer; + + icao = icao.toUpperCase(); + + if (icao in _aircraft_cache) { + defer = _aircraft_cache[icao]; + } else { + // load from blocks: + defer = _aircraft_cache[icao] = $.Deferred(); + request_from_db(icao, 1, defer); + } + + return defer; +} + +function request_from_db(icao, level, defer) { + var bkey = icao.substring(0, level); + var dkey = icao.substring(level); + var req = db_ajax(bkey); + + req.done(function(data) { + var subkey; + + if ("children" in data) { + subkey = bkey + dkey.substring(0,1); + if (data.children.indexOf(subkey) == -1) { + defer.reject(); + } else { + request_from_db(icao, level+1, defer); + } + } else { + if (dkey in data) { + defer.resolve(data[dkey]); + } else { + defer.reject(); + } + } + }); + + req.fail(function(jqXHR,textStatus,errorThrown) { + defer.reject(); + }); +} + +var _request_count = 0; +var _request_queue = []; +var _request_cache = {}; + +var MAX_REQUESTS = 2; + +function db_ajax(bkey) { + var defer; + + if (bkey in _request_cache) { + return _request_cache[bkey]; + } + + if (_request_count < MAX_REQUESTS) { + // just do ajax directly + ++_request_count; + defer = _request_cache[bkey] = $.ajax({ url: 'db/' + bkey + '.json', + cache: true, + timeout: 5000, + dataType : 'json' }); + defer.always(db_ajax_request_complete); + } else { + // put it in the queue + defer = _request_cache[bkey] = $.Deferred(); + defer.bkey = bkey; + _request_queue.push(defer); + } + + return defer; +} + +function db_ajax_request_complete() { + var req; + var ajaxreq; + + if (_request_queue.length == 0) { + --_request_count; + } else { + req = _request_queue.shift(); + ajaxreq = $.ajax({ url: 'db/' + req.bkey + '.json', + cache: true, + timeout: 5000, + dataType : 'json' }); + ajaxreq.done(function(data) { req.resolve(data); }); + ajaxreq.fail(function(jqxhr, status, error) { req.reject(jqxhr, status, error); }); + ajaxreq.always(db_ajax_request_complete); + } +} diff --git a/public_html/gmap.html b/public_html/gmap.html index 0b4bc97..3288fc0 100644 --- a/public_html/gmap.html +++ b/public_html/gmap.html @@ -8,6 +8,7 @@ + @@ -114,6 +115,8 @@ + + [FR24] diff --git a/public_html/planeObject.js b/public_html/planeObject.js index 187c03f..1a7fd4b 100644 --- a/public_html/planeObject.js +++ b/public_html/planeObject.js @@ -36,6 +36,23 @@ function PlaneObject(icao) { this.marker = null; this.icon = { type: 'generic', fillOpacity: 0.9 }; + + // request metadata + this.registration = null; + this.icaotype = null; + getAircraftData(this.icao).done(function(data) { + if ("r" in data) { + this.registration = data.r; + } + + if ("t" in data) { + this.icaotype = data.t; + } + + if (this.selected) { + refreshSelected(); + } + }.bind(this)); } // Appends data to the running track so we can get a visual tail on the plane diff --git a/public_html/script.js b/public_html/script.js index aff834e..06d2691 100644 --- a/public_html/script.js +++ b/public_html/script.js @@ -554,7 +554,19 @@ function refreshSelected() { $('#selected_callsign').text('n/a'); $('#selected_links').css('display','none'); } - + + if (selected.registration !== null) { + $('#selected_registration').text(selected.registration); + } else { + $('#selected_registration').text(""); + } + + if (selected.icaotype !== null) { + $('#selected_icaotype').text(selected.icaotype); + } else { + $('#selected_icaotype').text(""); + } + var emerg = document.getElementById('selected_emergency'); if (selected.squawk in SpecialSquawks) { emerg.className = SpecialSquawks[selected.squawk].cssClass; diff --git a/public_html/style.css b/public_html/style.css index 7234d12..0f098f2 100644 --- a/public_html/style.css +++ b/public_html/style.css @@ -34,6 +34,8 @@ div#loader { z-index: 99; position: absolute; left: 0; top: 0; bottom: 0; right: .infoblock_body { font-size: small; } #selected_icao { font-size: x-small; } +#selected_registration { font-size: x-small; } +#selected_icaotype { font-size: x-small; } .dim { opacity: 0.3; filter:alpha(opacity=30); /* For IE8 and earlier */ } diff --git a/tools/vrs-basicaircraft-to-json.py b/tools/vrs-basicaircraft-to-json.py new file mode 100755 index 0000000..9db9f8f --- /dev/null +++ b/tools/vrs-basicaircraft-to-json.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python2 + +# +# Converts a Virtual Radar Server BasicAircraftLookup.sqb database +# into a bunch of json files suitable for use by the webmap +# + +import sqlite3, json +from contextlib import closing + +def extract(dbfile, todir, blocklimit): + ac_count = 0 + block_count = 0 + + blocks = {} + for i in xrange(16): + blocks['%01X' % i] = {} + + print 'Reading', dbfile + with closing(sqlite3.connect(dbfile)) as db: + with closing(db.execute('SELECT a.Icao, a.Registration, m.Icao FROM Aircraft a, Model m WHERE a.ModelID = m.ModelID')) as c: + for icao24, reg, icaotype in c: + bkey = icao24[0:1].upper() + dkey = icao24[1:].upper() + blocks[bkey][dkey] = {} + if reg: blocks[bkey][dkey]['r'] = reg + if icaotype: blocks[bkey][dkey]['t'] = icaotype + ac_count += 1 + print 'Read', ac_count, 'aircraft' + + queue = list(blocks.keys()) + while queue: + bkey = queue[0] + del queue[0] + + blockdata = blocks[bkey] + if len(blockdata) > blocklimit: + print 'Splitting block', bkey, 'with', len(blockdata), 'entries..', + children = {} + for dkey in blockdata.keys(): + new_bkey = bkey + dkey[0] + new_dkey = dkey[1:] + + if new_bkey not in children: blocks[new_bkey] = children[new_bkey] = {} + children[new_bkey][new_dkey] = blockdata[dkey] + + print len(children), 'children' + queue.extend(children.keys()) + blockdata = blocks[bkey] = { 'children' : sorted(children.keys()) } + + path = todir + '/' + bkey + '.json' + print 'Writing', len(blockdata), 'entries to', path + block_count += 1 + with closing(open(path, 'w')) as f: + json.dump(obj=blockdata, fp=f, check_circular=False, separators=(',',':'), sort_keys=True) + + print 'Wrote', block_count, 'blocks' + +if __name__ == '__main__': + import sys + if len(sys.argv) < 3: + print 'Syntax: %s ' % sys.argv[0] + sys.exit(1) + else: + extract(sys.argv[1], sys.argv[2], 1000) + sys.exit(0)