1327 lines
56 KiB
JavaScript
1327 lines
56 KiB
JavaScript
/********************************************************************
|
|
* 2D Map based on Google Maps
|
|
********************************************************************
|
|
* Guenter Koellner Embedded Development GmbH
|
|
*
|
|
* Am Rain 24
|
|
* 85256 Vierkirchen
|
|
* Geschaeftsfuehrer Guenter Koellner
|
|
*
|
|
********************************************************************/
|
|
|
|
var Gmap=null;
|
|
var Planes={};
|
|
var Sensors={};
|
|
var flightPath={};
|
|
var flightPath2={};
|
|
|
|
var HighlightSensors = null;
|
|
|
|
var SingleAircraft = null;
|
|
var SingleSensor = null;
|
|
|
|
var Filters = {
|
|
enable_alt:false, altitude_min:null,altitude_max:null,
|
|
enable_gnd : true,
|
|
enable_spd:false, speed_min :null,speed_max:null,
|
|
enable_dis:false, distance_min:null,distance_max:null,
|
|
reg_enable:false, reg_filter :null,
|
|
sensors_enable:false,sensors_filter:null,
|
|
typ_enable: false,typ_filter: null,
|
|
fli_enable : false,
|
|
fli_filter : null,
|
|
dest_enable : false,
|
|
dest_filter : null,
|
|
orig_enable : false,
|
|
orig_filter : null,
|
|
squawk_enable : false,
|
|
squawk_filter : null,
|
|
prio_enable : false,
|
|
prio_filter : null,
|
|
enable_adsb : true,
|
|
enable_mlat : true,
|
|
enable_modeac : true,
|
|
enable_flawa : true,
|
|
enable_ogn : true,
|
|
enable_flarm : true,
|
|
pref_source : 'auto'
|
|
};
|
|
|
|
var prio_filter_splitted = [];
|
|
|
|
var GmapInit = {
|
|
Zoomlevel : 8,
|
|
CenterLat : 48.353013,
|
|
CenterLon : 11.785958,
|
|
LatLonSrc : 'GPS',
|
|
DistanceUnit : 'km',
|
|
enable_night : true,
|
|
mapstyle : 'terrain',
|
|
refreshtime : 5,
|
|
tracklength : 300,
|
|
enable_atrack: true,
|
|
enable_mtrack: true,
|
|
show_sensors : true
|
|
};
|
|
|
|
var Selected=[];
|
|
var PreSelected=undefined;
|
|
var NauticalMiles_to_Meters=1852;
|
|
var KiloMeters_to_Meters=1000;
|
|
|
|
//var map_container;
|
|
var map_box;
|
|
var map_info_box;
|
|
var flight_info_box_adsb;
|
|
var flight_info_box_modeac;
|
|
var flight_info_box_klick;
|
|
var hide_info;
|
|
var hide_info_btn;
|
|
|
|
// https://stackoverflow.com/questions/26246601/wildcard-string-comparison-in-javascript
|
|
// Short code
|
|
function matchRuleShort(str, rule) {
|
|
var escapeRegex = (str) => str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
|
|
return new RegExp("^" + rule.split("*").map(escapeRegex).join(".*") + "$").test(str);
|
|
}
|
|
|
|
function getTimeString(isLocal) {
|
|
var hours;
|
|
var minutes;
|
|
var date = new Date();
|
|
var zone_offset = date.getTimezoneOffset();
|
|
|
|
if (isLocal) {
|
|
hours = date.getHours();
|
|
minutes = date.getMinutes();
|
|
seconds = date.getSeconds();
|
|
} else {
|
|
hours = date.getUTCHours();
|
|
minutes = date.getUTCMinutes();
|
|
seconds = date.getUTCSeconds();
|
|
}
|
|
|
|
if (hours < 10) { hours = '0' + hours; }
|
|
if (minutes < 10) { minutes = '0' + minutes; }
|
|
if (seconds < 10) { seconds = '0' + seconds; }
|
|
|
|
var zeit_string = hours + ':' + minutes + ':' + seconds;
|
|
|
|
return zeit_string;
|
|
}
|
|
|
|
function getStrokeColor(alt, isGround) {
|
|
const colorMap = [
|
|
[ 0,"ffffff"],
|
|
[ 100,"ffe062"],
|
|
[ 200,"ffea00"],
|
|
[ 300,"f0ff00"],
|
|
[ 400,"ccff00"],
|
|
[ 600,"42ff00"],
|
|
[ 800,"1eff00"],
|
|
[ 1000,"00ff0c"],
|
|
[ 1200,"00ff36"],
|
|
[ 1500,"00ff72"],
|
|
[ 2000,"00ff9c"],
|
|
[ 2500,"00ffd2"],
|
|
[ 3000,"00ffe4"],
|
|
[ 3500,"00eaff"],
|
|
[ 4000,"00c0ff"],
|
|
[ 4500,"00a8ff"],
|
|
[ 5000,"0096ff"],
|
|
[ 5500,"0078ff"],
|
|
[ 6000,"0054ff"],
|
|
[ 6500,"0030ff"],
|
|
[ 7000,"001eff"],
|
|
[ 7500,"0000ff"],
|
|
[ 8500,"1200ff"],
|
|
[ 8500,"2400ff"],
|
|
[ 9000,"3600ff"],
|
|
[ 9500,"4e00ff"],
|
|
[10000,"6000ff"],
|
|
[10500,"7800ff"],
|
|
[11000,"9600ff"],
|
|
[11500,"ae00ff"],
|
|
[12000,"d800ff"],
|
|
[12500,"ff00e4"],
|
|
[13000,"ff0000"]
|
|
];
|
|
|
|
if( isGround ) { return '8B4513'; }
|
|
|
|
var color;
|
|
for (var i = 0; i < colorMap.length; i++) {
|
|
if (alt > colorMap[i][0]) {
|
|
color = colorMap[i][1];
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
return color;
|
|
}
|
|
|
|
function getIconForPlane(plane)
|
|
{
|
|
var Border = plane.src == 'M' ? 'Red'
|
|
: plane.src == 'F' ? 'LimeGreen'
|
|
: plane.src == 'L' ? 'DeepPink'
|
|
: plane.src == 'O' ? 'HotPink'
|
|
: plane.src == 'AC' ? 'Blue'
|
|
: 'Black';
|
|
|
|
var Fill = plane.vrt > 300 ? 'rgb(53, 235, 244)' //'DeepSkyBlue'
|
|
: plane.vrt < -300 ? 'rgb(185, 92, 0)' //'Sienna'
|
|
: 'rgb(255,255,0)'; //'Yellow';
|
|
|
|
var maxalt = 40000; /* Max altitude in the average case */
|
|
var invalt = maxalt-plane.alt;
|
|
if( plane.data_src=='AC' ) {
|
|
var imageObj = get_modeac_image_object();
|
|
} else {
|
|
var imageObj = get_image_object(plane.cat, plane.typ);
|
|
}
|
|
|
|
var object_box = Raphael.pathBBox(imageObj.path);
|
|
var offset_x = (object_box.x + object_box.x2) / 2;
|
|
var offset_y = (object_box.y + object_box.y2) / 2;
|
|
|
|
var strokew = Selected.includes(plane.hex) ? 2 : 1;
|
|
var Zindex = Selected.includes(plane.hex) ? 5 : 1;
|
|
|
|
var myZoom = Gmap.getZoom();
|
|
var Scale = myZoom>=12 ? imageObj.scale * 1.45
|
|
: myZoom==11 ? imageObj.scale * 1.3
|
|
: myZoom==10 ? imageObj.scale * 1.15
|
|
: myZoom== 9 ? imageObj.scale * 1.0
|
|
: myZoom== 8 ? imageObj.scale * 0.85
|
|
: myZoom== 7 ? imageObj.scale * 0.7
|
|
: myZoom== 6 ? imageObj.scale * 0.55
|
|
: imageObj.scale * 0.4
|
|
|
|
var ac_symbol = {
|
|
strokeColor : Border,
|
|
strokeWeight: strokew,
|
|
path : imageObj.path,
|
|
scale : Scale,
|
|
fillColor : Fill,
|
|
fillOpacity : 0.9,
|
|
anchor : new google.maps.Point(offset_x, offset_y),
|
|
rotation : (plane.trk + imageObj.rotcorr) % 360,
|
|
zIndex : Zindex
|
|
};
|
|
|
|
return ac_symbol;
|
|
}
|
|
|
|
|
|
function showInfoBox() {
|
|
hide_info.style.visibility = 'visible';
|
|
map_info_box.style.width = '210px';
|
|
hide_info_btn.setAttribute("class", "glyphicon glyphicon-minus");
|
|
}
|
|
|
|
|
|
function hideInfoBox() {
|
|
hide_info.style.visibility = 'hidden';
|
|
map_info_box.style.width = '1px';
|
|
hide_info_btn.setAttribute("class", "glyphicon glyphicon-plus");
|
|
}
|
|
|
|
|
|
function toggleInfoBox() {
|
|
if (hide_info.style.visibility == 'hidden')
|
|
showInfoBox();
|
|
else
|
|
hideInfoBox();
|
|
}
|
|
|
|
|
|
/********************************************************************************
|
|
* clicking on a sensor selects only this one
|
|
*******************************************************************************/
|
|
function selectSensor() {
|
|
//console.log("selectSensor="+this.sensorid);
|
|
SingleSensor = this.sensorid;
|
|
fetchAllData();
|
|
}
|
|
|
|
|
|
/********************************************************************************
|
|
* clicking on a plane selects display of details in sidebar
|
|
*******************************************************************************/
|
|
function selectPlane() {
|
|
|
|
var hex = this.hex;
|
|
//console.log('selectPlane hex='+hex+' event.altKey='+event.altKey+' event.ctrlKey='+event.ctrlKey);
|
|
//console.log('Selected='+Selected);
|
|
if( !Planes[hex] ) { console.log ('not in Planes'); return; }
|
|
|
|
if( Selected && Selected.includes(hex) ) { Selected.splice(Selected.indexOf(hex), 1); }
|
|
if( Selected===null) Selected = [hex];
|
|
else Selected.push(hex);
|
|
Planes[hex].marker1.setIcon(getIconForPlane(Planes[hex]));
|
|
labelSetStyle(Planes[hex], Planes[hex].marker1);
|
|
|
|
if (event.shiftKey) {
|
|
SingleAircraft = (SingleAircraft==hex) ? null : hex;
|
|
}
|
|
|
|
refreshSelectedInfo();
|
|
fetchAllData();
|
|
showInfoBox();
|
|
}
|
|
|
|
function rightSelectPlane() {
|
|
var hex = this.hex;
|
|
//console.log('rightSelectPlane hex='+hex+' event.altKey='+event.altKey+' event.ctrlKey='+event.ctrlKey);
|
|
if( Selected && !Selected.includes(hex) ) { console.log ('not in Selected'); return; }
|
|
deselectPlane(hex);
|
|
}
|
|
|
|
function preselectPlane(hex) {
|
|
//console.log('preselectPlane src=ADSB id='+hex);
|
|
this.src='ADSB';
|
|
this.id=hex;
|
|
selectPlane();
|
|
}
|
|
|
|
function updateURLPlaneSelection() {
|
|
var hashObj = {};
|
|
location.hash.replace('#', '').split('&').forEach(function(item) {
|
|
hashObj[item.split('=')[0]] = item.split('=')[1];
|
|
});
|
|
PreSelected = { 'src':'ADSB', 'hex':hashObj.icao };
|
|
}
|
|
|
|
function deselectPlaneAll() {
|
|
var old = Selected;
|
|
Selected = [];
|
|
old.forEach( function(hex) { deselectPlane(hex); });
|
|
SingleAircraft = null;
|
|
SingleSensor = null;
|
|
fetchAllData();
|
|
}
|
|
|
|
function deselectPlane(hex)
|
|
{
|
|
Selected.splice(Selected.indexOf(hex), 1);
|
|
|
|
/* Remove the highlight in the previously selected plane. */
|
|
if( Planes[hex] ) {
|
|
Planes[hex].marker1.setIcon(getIconForPlane(Planes[hex]));
|
|
labelSetStyle(Planes[hex], Planes[hex].marker1);
|
|
}
|
|
|
|
if( flightPath[hex] ) {
|
|
flightPath[hex].forEach ( function( X ) { X.setMap(null); });
|
|
delete flightPath[hex];
|
|
}
|
|
|
|
if( flightPath2[hex] ) {
|
|
flightPath2[hex].forEach ( function( X ) { X.setMap(null); });
|
|
delete flightPath2[hex];
|
|
}
|
|
|
|
if( !Selected.length ) { // Selected is empty now, remove sidebar
|
|
flight_info_box_adsb.style.display='none';
|
|
flight_info_box_modeac.style.display='none';
|
|
flight_info_box_klick.style.display='';
|
|
}
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* Info box in div map_info_box - left side, always visible
|
|
******************************************************************************/
|
|
|
|
function fetchMapInfo() {
|
|
getJSON(rcd_globals.fcgipath+'mapinfo.json', function(mapinfo) {
|
|
// equal, but not better: $('#TimeStringUTC')[0].innerHTML = '<b>'+getTimeString(false)+'</b>';
|
|
document.getElementById('TimeStringUTC' ).innerHTML = '<b>'+getTimeString(false)+'</b>';
|
|
document.getElementById('TimeStringLocal' ).innerHTML = '<b>'+getTimeString(true )+'</b>';
|
|
document.getElementById('mapinfo_dbsize' ).innerHTML = '<b>'+mapinfo.dbsize +'</b>';
|
|
document.getElementById('mapinfo_watched' ).innerHTML = '<b>'+mapinfo.watched +'</b>';
|
|
document.getElementById('mapinfo_num_adsb' ).innerHTML = '<b>'+mapinfo.num_adsb +'</b>';
|
|
document.getElementById('mapinfo_num_mlat' ).innerHTML = '<b>'+mapinfo.num_mlat +'</b>';
|
|
document.getElementById('mapinfo_num_flarm').innerHTML = '<b>'+mapinfo.num_flarm+'</b>';
|
|
});
|
|
}
|
|
|
|
|
|
function isAltitude ( code )
|
|
{
|
|
if( typeof(code)!='string' || code.length!=4 ) return false;
|
|
var d = parseInt(code.substring(3,4));
|
|
var c = code.substring(2,3);
|
|
var ret = !( d&1 || c=='0' || c=='5' || c=='7' )
|
|
return ret;
|
|
}
|
|
|
|
|
|
function decodeModeACAltitude ( code )
|
|
{
|
|
if( typeof(code)!='string' || code.length!=4 ) return false;
|
|
var V0 = parseInt(code.substr(0,2),16);
|
|
var V1 = parseInt(code.substr(2,4),16);
|
|
|
|
var altitude = ((V1 << 9) & 0x400) | // D2 1 + 9 =10
|
|
((V1 << 7) & 0x200) | // D4 2 + 7 = 9
|
|
((V0 << 4) & 0x100) | // A1 4 + 4 = 8
|
|
((V0 << 2) & 0x080) | // A2 5 + 2 = 7
|
|
((V0 ) & 0x040) | // A4 6 + 0 = 6
|
|
((V0 << 5) & 0x020) | // B1 0 + 5 = 5
|
|
((V0 << 3) & 0x010) | // B2 1 + 3 = 4
|
|
((V0 << 1) & 0x008) | // B4 2 + 1 = 3
|
|
((V1 >> 2) & 0x004) | // C1 4 - 2 = 2
|
|
((V1 >> 4) & 0x002) | // C2 5 - 4 = 1
|
|
((V1 >> 6) & 0x001); // C4 6 - 6 = 0
|
|
|
|
altitude ^= (altitude >> 8);
|
|
altitude ^= (altitude >> 4);
|
|
altitude ^= (altitude >> 2);
|
|
altitude ^= (altitude >> 1);
|
|
altitude -= ((altitude >> 4) * 6) + (((altitude % 16) / 5) * 2);
|
|
altitude = (altitude - 13) * 100;
|
|
ret = Math.round(altitude);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/********************************************************************************
|
|
* Additional info about plane, visible in left sidebar if a plane is selected
|
|
*******************************************************************************/
|
|
function refreshSelectedInfo() {
|
|
|
|
var p = Planes[Selected.slice(-1)[0]];
|
|
|
|
if ( p ) {
|
|
|
|
if( p.data_src=='AC' )
|
|
{
|
|
flight_info_box_adsb.style.display = 'none';
|
|
flight_info_box_modeac.style.display = '';
|
|
flight_info_box_klick.style.display = 'none';
|
|
|
|
document.getElementById('fib_ac_code' ).innerHTML = p.ac + ' ';
|
|
document.getElementById('fib_ac_decoded').innerHTML = (isAltitude(p.ac) ? decodeModeACAltitude(p.ac)+'ft' : 'Squawk');
|
|
|
|
p.achistory.sort(function(a, b) {
|
|
if( a[2]==b[2] ) return 0;
|
|
return (a[2] < b[2]) ? -1 : 1;
|
|
});
|
|
|
|
var nof_ac_codes = p.achistory.length;
|
|
var counts = 'Count<br/>';
|
|
var codes = 'Mode-A/C<br>';
|
|
var alts = 'Alt [ft]<br/>';
|
|
var llas = 'Age[s]<br/>';
|
|
for ( var i=0; i<Math.min(nof_ac_codes, 10); i+=1) {
|
|
codes += p.achistory[i ][1] + '<br/>';
|
|
alts += (isAltitude(p.achistory[i][1]) ? decodeModeACAltitude(p.achistory[i][1]) : '') + '<br/>';
|
|
counts += p.achistory[i ][0] + '<br/>';
|
|
llas += p.achistory[i ][2] + '<br/>';
|
|
}
|
|
|
|
document.getElementById('fib_ac_history_c1').innerHTML = counts;
|
|
document.getElementById('fib_ac_history_c2').innerHTML = codes;
|
|
document.getElementById('fib_ac_history_c3').innerHTML = alts;
|
|
document.getElementById('fib_ac_history_c4').innerHTML = llas;
|
|
|
|
document.getElementById('fib_ac_trk').innerHTML = p.trk + ' °';
|
|
document.getElementById('fib_ac_spd').innerHTML = (p.spd) ? (p.spd + ' kt' ) : ' ';
|
|
document.getElementById('fib_ac_alt').innerHTML = (p.alt) ? (p.alt + ' ft') : ' ';
|
|
document.getElementById('fib_ac_vrt').innerHTML = (p.vrt) ? (p.vrt + ' ft/min') : ' ';
|
|
document.getElementById('fib_ac_lat').innerHTML = p.lat + ' °';
|
|
document.getElementById('fib_ac_lon').innerHTML = p.lon + ' °';
|
|
document.getElementById('fib_ac_dis').innerHTML = ' ';
|
|
document.getElementById('fib_ac_src').innerHTML = 'Mode-A/C';
|
|
document.getElementById('fib_ac_lla' ).innerHTML = p.lla + ' sec';
|
|
document.getElementById('fib_ac_pest').innerHTML = p.pest + ' ';
|
|
}
|
|
else
|
|
{
|
|
flight_info_box_adsb.style.display = '';
|
|
flight_info_box_modeac.style.display = 'none';
|
|
flight_info_box_klick.style.display = 'none';
|
|
|
|
document.getElementById('fib_reg').innerHTML =
|
|
( p.reg && p.reg!= '' && !p.reg.includes('state') )
|
|
? '<a href="https://planespotters.net/search?q=' + encodeURIComponent(p.reg) + '" target="_blank">' + p.reg + '</a>'
|
|
: p.reg + ' ';
|
|
document.getElementById('fib_log').innerHTML = '<a href="mlat/log?' + p.hex + '"<span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span></a> Network Info'
|
|
document.getElementById('fib_hex').innerHTML = p.hex + ' ';
|
|
document.getElementById('fib_typ').innerHTML = (p.typ) ? (p.typ + ' ') : ' ';
|
|
document.getElementById('fib_cat').innerHTML = (p.cat) ? (p.cat + ' ') : ' ';
|
|
document.getElementById('fib_fli').innerHTML = (p.fli) ? (p.fli + ' ') : ' ';
|
|
document.getElementById('fib_squ').innerHTML = (p.squ) ? (p.squ + ' ') : ' ';
|
|
|
|
/* Flight Details Row 2 */
|
|
document.getElementById('fib_org').innerHTML =
|
|
(!p.org)
|
|
? '<b>n/a</b>'
|
|
: '<b>' + p.org + ' </b><br/><small>' + resolveAirportById(p.org).label + ' </small>';
|
|
document.getElementById('fib_dst').innerHTML =
|
|
(!p.dst)
|
|
? '<b>n/a</b>'
|
|
: '<b>' + p.dst + ' </b><br/><small>' + resolveAirportById(p.dst).label + ' </small>';
|
|
|
|
document.getElementById('fib_trk').innerHTML = p.trk + ' °';
|
|
document.getElementById('fib_spd').innerHTML = (p.spd) ? (p.spd + ' kt' ) : ' ';
|
|
document.getElementById('fib_alt').innerHTML = (p.alt) ? (p.alt + ' ft') : ' ';
|
|
document.getElementById('fib_vrt').innerHTML = (p.vrt) ? (p.vrt + ' ft/min') : ' ';
|
|
document.getElementById('fib_lat').innerHTML = p.lat + ' °';
|
|
document.getElementById('fib_lon').innerHTML = p.lon + ' °';
|
|
document.getElementById('fib_dis').innerHTML = p.dis.toFixed(1) + ' ' + DistanceUnit;
|
|
document.getElementById('fib_src').innerHTML =
|
|
(p.src=='A') ? 'ADS-B'
|
|
: (p.src=='M') ? 'MLAT'
|
|
: (p.src=='F') ? 'FlAwa'
|
|
: (p.src=='O') ? 'OGN'
|
|
: (p.src=='L') ? 'Flarm'
|
|
: ' ';
|
|
|
|
document.getElementById('fib_lla' ).innerHTML = p.lla + ' sec';
|
|
document.getElementById('fib_pest').innerHTML = p.pest + ' ';
|
|
|
|
document.getElementById('fib_nof_clnt').innerHTML = 'Current Sensors: ' + p.nocl;
|
|
|
|
if( rcd_globals.productname=='MLAT_SERVER' ) {
|
|
var i = 0;
|
|
var clnt = ['','','','',''];
|
|
p.clnt.sort().forEach(function(C){ clnt[i%5] += C + '<br/>'; i++; });
|
|
document.getElementById('fib_clnt0').innerHTML = clnt[0] + ' ';
|
|
document.getElementById('fib_clnt1').innerHTML = clnt[1] + ' ';
|
|
document.getElementById('fib_clnt2').innerHTML = clnt[2] + ' ';
|
|
document.getElementById('fib_clnt3').innerHTML = clnt[3] + ' ';
|
|
document.getElementById('fib_clnt4').innerHTML = clnt[4] + ' ';
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
flight_info_box_adsb.style.display = 'none';
|
|
flight_info_box_modeac.style.display = 'none';
|
|
flight_info_box_klick.style.display = '';
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************************************
|
|
* Information that is displayed on map together with plane
|
|
*******************************************************************************/
|
|
function labelDataID(plane) {
|
|
if( plane.fli!==null && plane.fli!=="") return plane.fli;
|
|
if( plane.reg!==null && plane.reg!=="" && plane.reg!=="(state)" ) return plane.reg;
|
|
return plane.hex;
|
|
}
|
|
|
|
function labelDataVerticalRate(plane) {
|
|
// Vertical Rate
|
|
if (!plane.vrt ) return ' '
|
|
else if (plane.vrt < -300) return Math.round(plane.vrt/100);
|
|
else if (plane.vrt > 300) return "+" + Math.round(plane.vrt/100);
|
|
return '\u00B10'; // unicode plusminus + '0'
|
|
}
|
|
|
|
function labelDataAltitude(plane) {
|
|
if (plane.gda == "G") { return "GND"; }
|
|
|
|
// Altitude
|
|
var s = Math.round(plane.alt/100);
|
|
if (s < 0) {
|
|
s = '-0' + -1*s;
|
|
} else {
|
|
if (s < 10) s = "00" + s;
|
|
else
|
|
if (s < 100) s = "0" + s;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
function labelDataSpeed(plane) {
|
|
return Math.round(plane.spd/10);
|
|
}
|
|
|
|
function permanentLabelTable(plane) {
|
|
var ret;
|
|
if( plane.data_src=='AC' ) {
|
|
ret = '<table class="aircraft_label">' +
|
|
'<tr><td class="flight"><b>' + plane.ac + '</b> </td><td colspan="2">' + plane.uid + '</td></tr>' +
|
|
'<tr><td class="altitude">' + labelDataAltitude(plane) + '</td><td class="verticalRate">' + labelDataVerticalRate(plane) + '</td><td class="speed">' + labelDataSpeed(plane) + '</td></tr>' +
|
|
'<tr><td class="flight">' + plane.tsz + '</td><td class="speed">' + plane.lla + '</td><td class="speed">' + plane.pest + '</td></tr>' +
|
|
'</table>';
|
|
} else {
|
|
ret = '<table class="aircraft_label">' +
|
|
'<tr><td class="flight" colspan="2">' + labelDataID(plane) + ' </td><td>' + (plane.reg==null?'':plane.reg) + '</td></tr>' +
|
|
'<tr><td class="altitude" >' + labelDataAltitude(plane) + '</td><td class="verticalRate">' + labelDataVerticalRate(plane) + '</td><td class="speed">' + labelDataSpeed(plane) + '</td></tr>' +
|
|
//'<tr><td class="flight">' + plane.clnt.length + '</td><td class="speed"><b>' + plane.squ + '</b></td><td class="speed">' + plane.pest + '</td></tr>' +
|
|
'</table>';
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
function getPopupForPlane(plane) {
|
|
if( plane.data_src=='AC' )
|
|
{
|
|
var ret = '';
|
|
plane.achistory.forEach ( function (E) { ret += E[0] + ':' + E[1] + ' '; });
|
|
return ret;
|
|
}
|
|
|
|
if( plane.fli.length == 0 ) {
|
|
return plane.hex;
|
|
} else {
|
|
var title = plane.hex + " " + plane.typ;
|
|
if ( plane.org!=null && plane.org.length ) { title += '\n' + plane.org; }
|
|
if ( plane.dst!=null && plane.dst.length ) { title += '->' + plane.dst; }
|
|
if ( plane.squ!=null && plane.squ.length ) { title += '\nSQ:' + plane.squ; }
|
|
return title;
|
|
}
|
|
}
|
|
|
|
// function labelSetAnchor(plane, marker, offset) {
|
|
// if (plane.trk > 315) { marker.set("labelAnchor", new google.maps.Point( 66, -1 + offset)); return; }
|
|
// if (plane.trk < 45) { marker.set("labelAnchor", new google.maps.Point( 66, -1 + offset)); return; }
|
|
// if (plane.trk < 135) { marker.set("labelAnchor", new google.maps.Point( 37, -1 + 28 + offset)); return; }
|
|
// if (plane.trk < 225) { marker.set("labelAnchor", new google.maps.Point(-17, -1 + offset)); return; }
|
|
// marker.set("labelAnchor", new google.maps.Point(37, -1 - 28 + offset));
|
|
// }
|
|
|
|
function isInPrio(item) {
|
|
var ret=false;
|
|
prio_filter_splitted.forEach(function(mask) {
|
|
if ( matchRuleShort(item, mask) ) { ret=true; return; };
|
|
});
|
|
return ret;
|
|
}
|
|
|
|
// https://www.quackit.com/html/codes/color/html_color_chart.cfm
|
|
function labelSetStyle(plane, marker) {
|
|
if ( Selected.includes(plane.hex) ) {marker.set('labelStyle', { opacity: 0.5, 'background-color': 'greenyellow'}); return; }
|
|
if ( plane.squ && plane.squ=="7700") {marker.set('labelStyle', { opacity: 0.5, 'background-color': 'red'}); return; }
|
|
if ( plane.spi ) {marker.set('labelStyle', { opacity: 0.5, 'background-color': 'aqua', border: '2px solid darkblue'}); return; }
|
|
if ( plane.alr && plane.alr!=0 ) {marker.set('labelStyle', { opacity: 0.5, 'background-color': 'gold', border: '2px solid black' }); return; }
|
|
if ( Filters.prio_enable===true ) {
|
|
if ( isInPrio(plane.hex) || isInPrio(plane.reg) ) {marker.set('labelStyle', { opacity: 0.8, 'background-color': 'yellow'}); return; }
|
|
}
|
|
marker.set('labelStyle', { opacity: 0.5, 'background-color': 'gold'});
|
|
}
|
|
|
|
// Shapes: https://developers.google.com/maps/documentation/javascript/shapes
|
|
// https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/examples/overlay-symbol-dashed?hl=vi
|
|
function drawColoredTrack (data)
|
|
{
|
|
data.forEach( function(path) {
|
|
var hex = path.src=='AC' ? 'AC_'+path.uid : path.icao;
|
|
if( !Selected.includes(hex) ) return; // no longer selected
|
|
|
|
if( flightPath[hex] ) flightPath[hex].forEach( function ( X ) { X.setMap(null); });
|
|
flightPath[hex] = [];
|
|
|
|
if( path.fpth.length<2 ) return;
|
|
|
|
var trackpoints = [];
|
|
var veryFirst = true;
|
|
var strokeColor_tm1;
|
|
|
|
path.fpth.forEach( function (trackpoint, index) {
|
|
|
|
var strokeColor = getStrokeColor(trackpoint.alt, trackpoint.gnd ? trackpoint.gnd : false ); // AC has no gnd field
|
|
var g_tp = { 'lat':trackpoint.lat, 'lng':trackpoint.lon };
|
|
trackpoints.push( g_tp );
|
|
|
|
if( veryFirst )
|
|
{
|
|
strokeColor_tm1=strokeColor;
|
|
veryFirst=false;
|
|
}
|
|
else
|
|
{
|
|
if( strokeColor!=strokeColor_tm1 || index==path.fpth.length-1 )
|
|
{
|
|
var pathSegment = new google.maps.Polyline({
|
|
path: trackpoints,
|
|
geodesic: true,
|
|
strokeColor: '#'+strokeColor_tm1,
|
|
strokeOpacity: 1.0,
|
|
strokeWeight: 2,
|
|
zIndex : 1,
|
|
map: Gmap
|
|
});
|
|
|
|
flightPath[hex].push(pathSegment);
|
|
trackpoints = [ g_tp ];
|
|
strokeColor_tm1 = strokeColor;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
function drawDashedTrack (data)
|
|
{
|
|
// Define a symbol using SVG path notation, with an opacity of 1.
|
|
const lineSymbol = {
|
|
path: 'M 0,-1 0,1',
|
|
strokeOpacity: 1,
|
|
scale: 2
|
|
};
|
|
|
|
data.forEach( function(path) {
|
|
var hex = path.src=='AC' ? 'AC_'+path.uid : path.icao;
|
|
if( !Selected.includes(hex) ) return; // no longer selected
|
|
|
|
if( flightPath2[hex] ) flightPath2[hex].forEach( function ( X ) { X.setMap(null); });
|
|
flightPath2[hex] = [];
|
|
|
|
if( path.fpth.length<2 ) return;
|
|
|
|
var trackpoints = [];
|
|
var veryFirst = true;
|
|
|
|
path.fpth.forEach( function (trackpoint) {
|
|
g_tp = { 'lat':trackpoint.lat, 'lng':trackpoint.lon };
|
|
trackpoints.push( g_tp );
|
|
});
|
|
|
|
var pathSegment = new google.maps.Polyline({
|
|
path: trackpoints,
|
|
geodesic: true,
|
|
strokeColor: 'black',
|
|
strokeOpacity: 0,
|
|
icons: [{
|
|
icon: lineSymbol,
|
|
offset: '0',
|
|
repeat: '10px'
|
|
}],
|
|
zIndex : 10,
|
|
map: Gmap
|
|
});
|
|
|
|
flightPath2[hex].push(pathSegment);
|
|
});
|
|
}
|
|
|
|
|
|
function fetchTrackData()
|
|
{
|
|
if( Selected.length==0 ) { return; }
|
|
|
|
var vps = Gmap.getBounds().getSouthWest().lat().toFixed(5);
|
|
var vpw = Gmap.getBounds().getSouthWest().lng().toFixed(5);
|
|
var vpn = Gmap.getBounds().getNorthEast().lat().toFixed(5);
|
|
var vpe = Gmap.getBounds().getNorthEast().lng().toFixed(5);
|
|
|
|
var tracks_adsb = [];
|
|
var tracks_mlat = [];
|
|
var tracks_flarm = [];
|
|
var tracks_ogn = [];
|
|
var tracks_flawa = [];
|
|
var tracks_modeac = [];
|
|
|
|
// sort selected targets by source because flightpath must be called separately
|
|
Selected.forEach( function (hex) {
|
|
if( Planes[hex].data_src=='AC') { tracks_modeac.push(Planes[hex].uid); }
|
|
else if( Planes[hex].src=='A' ) { tracks_adsb.push(hex); }
|
|
else if( Planes[hex].src=='M' ) { tracks_mlat.push(hex); }
|
|
else if( Planes[hex].src=='L' ) { tracks_flarm.push(hex); }
|
|
else if( Planes[hex].src=='F' ) { tracks_flawa.push(hex); }
|
|
else if( Planes[hex].src=='O' ) { tracks_ogn.push(hex); }
|
|
else console.log('unknown data_src=' + Planes[hex].data_src + ' src=' + Planes[hex].src + ' for flightpath.json' )
|
|
});
|
|
|
|
// colored tracks
|
|
[tracks_adsb, tracks_mlat, tracks_flarm, tracks_ogn, tracks_flawa].forEach( function (tracks) {
|
|
if( tracks.length ) {
|
|
var link = rcd_globals.fcgipath
|
|
+ 'flightpath.json?icao=' + tracks.join(',')
|
|
+ '&srcpref=' + Planes[tracks[0]].src
|
|
+ ( GmapInit.tracklength ? ( '&lookback=' + GmapInit.tracklength ) : '' )
|
|
+ '&pixelxy=' + window.innerWidth + ',' + window.innerHeight
|
|
+ '&vpn=' + vpn + '&vpe=' + vpe + '&vps=' + vps + '&vpw=' + vpw;
|
|
|
|
getJSON(link, drawColoredTrack);
|
|
}
|
|
});
|
|
|
|
// dashed tracks
|
|
tracks_dashed = [];
|
|
if( GmapInit.enable_atrack ) { tracks_dashed.push({'src':'A', 'points':tracks_mlat}); }
|
|
if( GmapInit.enable_mtrack ) { tracks_dashed.push({'src':'M', 'points':tracks_adsb}); }
|
|
tracks_dashed.forEach( function (tracks) {
|
|
if( tracks['points'].length ) {
|
|
var link = rcd_globals.fcgipath
|
|
+ 'flightpath.json?icao=' + tracks['points'].join(',')
|
|
+ '&srcpref=' + tracks['src']
|
|
+ ( GmapInit.tracklength ? ( '&lookback=' + GmapInit.tracklength ) : '' )
|
|
+ '&pixelxy=' + window.innerWidth + ',' + window.innerHeight
|
|
+ '&vpn=' + vpn + '&vpe=' + vpe + '&vps=' + vps + '&vpw=' + vpw;
|
|
|
|
getJSON(link, drawDashedTrack);
|
|
}
|
|
});
|
|
|
|
// Mode-A/C tracks
|
|
if( tracks_modeac.length ) {
|
|
var link = rcd_globals.fcgipath
|
|
+ 'modeacpath.json?uid=' + tracks_modeac.join(',')
|
|
+ ( GmapInit.tracklength ? ( '&lookback=' + GmapInit.tracklength ) : '' )
|
|
+ '&pixelxy=' + window.innerWidth + ',' + window.innerHeight
|
|
+ '&vpn=' + vpn + '&vpe=' + vpe + '&vps=' + vps + '&vpw=' + vpw;
|
|
|
|
getJSON(link, drawColoredTrack);
|
|
}
|
|
}
|
|
|
|
// Wrappers because callback cannot have parameter
|
|
function updatePlanes (data) {
|
|
document.getElementById('num_planesOnMap').innerHTML = '<b>'+data.length+'</b>';
|
|
updateObjects ( data, 'ADSB' );
|
|
}
|
|
function updateModeAC (data) { updateObjects ( data, 'AC' ); }
|
|
function updateSensors (data) { updateObjects ( data, 'Sensor' ); }
|
|
|
|
/* Functionality of this display assumes that all 'hex' codes are unique by the provider */
|
|
/* Mode-S, ADS-B and MLAT sources use 0x00000000 - 0x00ffffff hex id */
|
|
/* Mode-A/C sources use 0xACxxxxxx identifiers */
|
|
/* Sensors should use 0x5Exxxxxx identifiers */
|
|
/* and 'hex' is only traditional... */
|
|
function updateObjects (data, data_src) {
|
|
var stillhere = [];
|
|
data.forEach ( function (plane) {
|
|
|
|
var marker1;
|
|
if( data_src=='AC' ) plane.hex = 'AC_'+plane.uid;
|
|
stillhere.push(plane.hex);
|
|
plane.data_src = data_src;
|
|
plane.fli = $.trim(plane.fli);
|
|
|
|
/* update */
|
|
if( Planes[plane.hex] ) {
|
|
marker1 = Planes[plane.hex].marker1;
|
|
|
|
var newpos = new google.maps.LatLng(plane.lat, plane.lon);
|
|
|
|
/* update flight number */
|
|
marker1.setIcon ( getIconForPlane(plane)) ;
|
|
marker1.setPosition( newpos );
|
|
marker1.set ('labelContent', permanentLabelTable(plane) );
|
|
labelSetStyle ( plane, marker1 );
|
|
marker1.label.draw();
|
|
|
|
if( Selected.includes(plane.hex) ) refreshSelectedInfo();
|
|
}
|
|
else
|
|
{
|
|
/* new flight */
|
|
marker1 = new MarkerWithLabel({
|
|
position : new google.maps.LatLng(plane.lat, plane.lon),
|
|
draggable : false,
|
|
raiseOnDrag : false,
|
|
zIndex : 70000,
|
|
map : Gmap,
|
|
labelContent : permanentLabelTable(plane),
|
|
labelAnchor : plane.data_src=='AC' ? new google.maps.Point(0, 32) : new google.maps.Point(0, 0),
|
|
labelClass : 'labels',
|
|
labelStyle : {},
|
|
labelZIndex : 60000,
|
|
icon : getIconForPlane(plane)
|
|
});
|
|
|
|
labelSetStyle(plane, marker1);
|
|
|
|
/* Trap clicks for this marker. */
|
|
marker1.addListener('click', selectPlane);
|
|
marker1.addListener('rightclick', rightSelectPlane);
|
|
}
|
|
|
|
marker1.hex = plane.hex; /* remember for click */
|
|
plane.marker1 = marker1;
|
|
Planes[plane.hex] = plane;
|
|
|
|
/* Popup window when mouse over aircraft icon */
|
|
marker1.setTitle( getPopupForPlane(plane) )
|
|
});
|
|
|
|
/* Remove no longer given planes. */
|
|
//console.log("Planes["+T+"]\n"+Planes[T]);
|
|
//console.log("stillhere\n"+stillhere);
|
|
for( var hex in Planes ) {
|
|
if( !stillhere.includes(hex) ) {
|
|
if( Planes[hex].data_src != data_src ) continue;
|
|
if( Selected.includes(hex) ) { deselectPlane(hex); }
|
|
Planes[hex].marker1.setMap(null);
|
|
delete Planes[hex];
|
|
}
|
|
}
|
|
|
|
if( PreSelected ) {
|
|
preselectPlane(PreSelected);
|
|
PreSelected=undefined;
|
|
}
|
|
}
|
|
|
|
|
|
function fetchAdsbData() {
|
|
|
|
var bounds = Gmap.getBounds();
|
|
if (bounds == null) { return; } // getBounds might not be defined even if map already is
|
|
|
|
var link = rcd_globals.fcgipath + 'aircraftlist.json?knownposonly=1';
|
|
|
|
var vps = Gmap.getBounds().getSouthWest().lat().toFixed(5);
|
|
var vpw = Gmap.getBounds().getSouthWest().lng().toFixed(5);
|
|
var vpn = Gmap.getBounds().getNorthEast().lat().toFixed(5);
|
|
var vpe = Gmap.getBounds().getNorthEast().lng().toFixed(5);
|
|
link += '&vpn=' + vpn + '&vpe=' + vpe + '&vps=' + vps + '&vpw=' + vpw;
|
|
|
|
if( Filters.enable_alt ) {
|
|
if( Filters.altitude_min ) { link += '&altitude.from=' + Filters.altitude_min; }
|
|
if( Filters.altitude_max ) { link += '&altitude.to=' + Filters.altitude_max; }
|
|
}
|
|
|
|
if (Filters.enable_gnd===false) { link+="&gndexcl=1"; }
|
|
|
|
if (Filters.enable_spd) {
|
|
if( Filters.speed_min ) { link += "&speed.from=" + Filters.speed_min; }
|
|
if( Filters.speed_max ) { link += "&speed.to=" + Filters.speed_max; }
|
|
}
|
|
|
|
if (Filters.enable_dis) {
|
|
if( Filters.distance_min ) { link += "&distance.from=" + Filters.distance_min; }
|
|
if( Filters.distance_max ) { link += "&distance.to=" + Filters.distance_max; }
|
|
}
|
|
|
|
if( SingleAircraft ) { link+= "&icao=" + SingleAircraft; }
|
|
else
|
|
if( Filters.reg_enable && Filters.reg_filter ) { link += "&icao=" + Filters.reg_filter; }
|
|
if( Filters.typ_enable && Filters.typ_filter ) { link += "&type=" + Filters.typ_filter; }
|
|
if( Filters.fli_enable && Filters.fli_filter ) { link += "&flight=" + Filters.fli_filter; }
|
|
|
|
if( Filters.dest_enable && Filters.dest_filter ) { link += "&dest=" + Filters.dest_filter; }
|
|
if( Filters.orig_enable && Filters.orig_filter ) { link += "&orig=" + Filters.orig_filter; }
|
|
if( Filters.squawk_enable && Filters.squawk_filter) { link += "&squawk=" + Filters.squawk_filter; }
|
|
if( Filters.prio_enable && Filters.prio_filter ) { link += "&prio=" + Filters.prio_filter; }
|
|
|
|
// C++ backend assumes that default is all on, so we only need to send the 'off' condition
|
|
if (!Filters.enable_adsb) { link += "&srcexcl=a"; }
|
|
if (!Filters.enable_mlat) { link += "&srcexcl=m"; }
|
|
if (!Filters.enable_flawa) { link += "&srcexcl=f"; }
|
|
if (!Filters.enable_ogn) { link += "&srcexcl=o"; }
|
|
if (!Filters.enable_flarm) { link += "&srcexcl=l"; }
|
|
|
|
if (typeof Filters.pref_source !== "undefined" && Filters.pref_source !== null && Filters.perfsource !== "") {
|
|
srcpref = "&srcpref=" + Filters.pref_source;
|
|
}
|
|
|
|
if( SingleSensor ) { link += "&sensor.only=" + SingleSensor; }
|
|
else
|
|
if( Filters.sensors_enable && Filters.sensors_filter ) { link += "&sensor.only=" + Filters.sensors_filter; }
|
|
|
|
getJSON( link, updatePlanes );
|
|
}
|
|
|
|
|
|
function fetchModeACData() {
|
|
|
|
if( !Filters.enable_modeac ) {
|
|
updateModeAC([]); // empty list clears the list
|
|
return;
|
|
}
|
|
|
|
if (Gmap.getBounds() == null) { return; } // getBounds might not be defined even if map already is
|
|
|
|
var link = rcd_globals.fcgipath + 'modeactargets.json';
|
|
|
|
getJSON( link, updateModeAC );
|
|
}
|
|
|
|
|
|
function FilterControl(controlDiv)
|
|
{
|
|
var controlUI = document.createElement('div');
|
|
controlUI.className = 'filter-button';
|
|
controlUI.title = 'Click to modify the filters';
|
|
controlDiv.appendChild(controlUI);
|
|
|
|
var controlText = document.createElement('div');
|
|
controlText.className = 'filter-icon';
|
|
controlUI.appendChild(controlText);
|
|
|
|
controlUI.addEventListener('click', function()
|
|
{
|
|
if (document.getElementById('filter-dialog') === null) {
|
|
var filterDialog = document.createElement('div');
|
|
filterDialog.id = 'filter-dialog';
|
|
filterDialog.innerHTML = '<div class="clear" title="Clear"></div><div class="close" title="Close"></div>' +
|
|
'<table>' +
|
|
'<tr><td><input type="checkbox" id="prio_enable" /></td><td class="filter-label">Prio & Highlight</td><td colspan="2"><input id="prio_filter" placeholder="Aircraft always shown" class="spanme" /></td></tr>' +
|
|
'<tr><td><input type="checkbox" id="enable_gnd" /></td><td class="filter-label">Ground Traffic </td><td colspan="2"></td></tr>' +
|
|
'<tr><td><input type="checkbox" id="enable_alt" /></td><td class="filter-label">Altitude (ft) </td><td><input id="filter-alt-min" placeholder="from" /></td><td><input id="filter-alt-max" placeholder="to"/></td></tr>' +
|
|
'<tr><td><input type="checkbox" id="enable_spd" /></td><td class="filter-label">Speed (kt) </td><td><input id="filter-spd-min" placeholder="from" /></td><td><input id="filter-spd-max" placeholder="to"/></td></tr>' +
|
|
'<tr><td><input type="checkbox" id="enable_dis" /></td><td class="filter-label">Distance (km) </td><td><input id="filter-dis-min" placeholder="from" /></td><td><input id="filter-dis-max" placeholder="to"/></td></tr>' +
|
|
'<tr><td></td></tr>' +
|
|
'<tr><td><input type="checkbox" id="dest_enable" /></td><td class="filter-label">Destination </td><td colspan="2"><input id="dest_filter" placeholder="Flight Destination (with wildcard)" class="spanme" /></td></tr>' +
|
|
'<tr><td><input type="checkbox" id="orig_enable" /></td><td class="filter-label">Origin </td><td colspan="2"><input id="orig_filter" placeholder="Flight Origin (with wildcard)" class="spanme" /></td></tr>' +
|
|
'<tr><td><input type="checkbox" id="squawk_enable" /></td><td class="filter-label">Squawk </td><td colspan="2"><input id="squawk_filter" placeholder="Squawk list" class="spanme" /></td></tr>' +
|
|
'<tr><td><input type="checkbox" id="fli_enable" /></td><td class="filter-label">Flight </td><td colspan="2"><input id="fli_filter" placeholder="Flight ID (with wildcard)" class="spanme" /></td></tr>' +
|
|
'<tr><td><input type="checkbox" id="typ_enable" /></td><td class="filter-label">Aircraft Type </td><td colspan="2"><input id="typ_filter" placeholder="A/C type (with wildcard)" class="spanme" /></td></tr>' +
|
|
'<tr><td><input type="checkbox" id="reg_enable" /></td><td class="filter-label">Fleet Watch </td><td colspan="2"><input id="reg_filter" placeholder="6 digit ICAO or Registration (with wildcard)" class="spanme" /></td></tr>' +
|
|
|
|
( ( rcd_globals.productname=='MLAT_SERVER' )
|
|
? '<tr><td><input type="checkbox" id="sensors_enable"/></td><td class="filter-label">Sensors </td><td colspan="2"><input id="sensors_filter" placeholder="Sensors list (with wildcard)" class="spanme" /></td></tr>' +
|
|
'<tr><td> </td><td class="filter-label">Sources </td><td colspan="2"><input type="checkbox" id="enable_adsb"/> ADSB <input type="checkbox" id="enable_mlat"/> MLAT <input type="checkbox" id="enable_modeac"/> A/C <input type="checkbox" id="enable_flarm"/> FLARM</td></tr>'
|
|
: '<tr><td> </td><td class="filter-label">Sources </td><td colspan="2"><input type="checkbox" id="enable_adsb"/> ADSB <input type="checkbox" id="enable_mlat"/> MLAT <input type="checkbox" id="enable_flarm"/> Flarm <input type="checkbox" id="enable_flawa"/> FlaWa <input type="checkbox" id="enable_ogn"/> OGN</td></tr>' ) +
|
|
|
|
'<tr><td> </td><td> </td><td><input type="checkbox" id="enable_mtrack"/> MLAT track with ADS-B</td><td colspan="2"><input type="checkbox" id="enable_atrack"/> ADS-B track with MLAT</td></tr>' +
|
|
'<tr><td> </td><td> </td><td></td></tr>' +
|
|
( ( rcd_globals.productname=='MLAT_SERVER' )
|
|
? '<tr><td> </td><td> </td><td><input type="checkbox" id="show_sensors"/> Show Sensors</td><td><input type="checkbox" id="enable_night"/> Show day and night</td></tr>'
|
|
: '<tr><td> </td><td> </td><td> </td><td><input type="checkbox" id="enable_night"/> Show day and night</td></tr>' ) +
|
|
'<tr><td> </td><td class="filter-label">Preferred Source</td>' +
|
|
|
|
( ( rcd_globals.productname=='MLAT_SERVER' )
|
|
? '<td><select id="pref_source"><option value="Q">Auto</option><option value="A">ADS-B</option><option value="M">Multilateration</option><option value="L">FLARM</option></select></td></tr>'
|
|
: '<td><select id="pref_source"><option value="Q">Auto</option><option value="A">ADS-B</option><option value="M">Jetvision MLAT</option><option value="F">FlightAware</option><option value="O">Open Glider Net Server</option><option value="L">OGN Local Receiver</option></select></td></tr>' ) +
|
|
|
|
'<tr><td> </td><td class="filter-label">Track Length </td><td><input id="tracklength" placeholder="sec" /></td><td class="filter-label">Map Style <select id="mapstyle"><option value="terrain">Terrain</option><option value="roadmap">Roadmap</option><option value="satellite">Satellite</option><option value="hybrid">Hybrid</option></select></td></tr>' +
|
|
'<tr><td> </td><td class="filter-label">Refresh Time </td><td><input id="refreshtime" placeholder="sec" /></td><td></td></tr>' +
|
|
'<tr><td> </td><td> </td><td> </td><td><button id="filter-apply">Apply & Close</button>' +
|
|
'</table>';
|
|
controlDiv.appendChild(filterDialog);
|
|
|
|
$("#filter-apply").click(function() {
|
|
handleChange();
|
|
$("#filter-dialog").hide();
|
|
});
|
|
|
|
$('#mapstyle, #enable_night, #refreshtime, #tracklength, #enable_atrack, #enable_mtrack, #show_sensors').change(mapstyleChange);
|
|
$('#filter-alt-min, #filter-alt-max, #enable_alt, #enable_gnd, ' +
|
|
'#filter-spd-min, #filter-spd-max, #enable_spd, ' +
|
|
'#filter-dis-min, #filter-dis-max, #enable_dis, ' +
|
|
'#reg_filter, #reg_enable, ' +
|
|
'#sensors_filter, #sensors_enable, ' +
|
|
'#typ_filter, #typ_enable, ' +
|
|
'#fli_filter, #fli_enable, ' +
|
|
'#dest_filter, #dest_enable, ' +
|
|
'#orig_filter, #orig_enable, ' +
|
|
'#squawk_filter, #squawk_enable, ' +
|
|
'#prio_filter, #prio_enable, ' +
|
|
'#pref_source, ' +
|
|
'#enable_adsb, #enable_mlat, #enable_modeac, #enable_flawa, #enable_ogn, #enable_flarm'
|
|
).change(handleChange);
|
|
|
|
$("#filter-dialog .close").click(function() {
|
|
$("#filter-dialog").hide();
|
|
});
|
|
$("#filter-dialog .clear").click(clear_filters);
|
|
|
|
$("#filter-alt-min").val(Filters.altitude_min);
|
|
$("#filter-alt-max").val(Filters.altitude_max);
|
|
$("#enable_alt" ).prop("checked",Filters.enable_alt );
|
|
$("#enable_gnd" ).prop("checked",Filters.enable_gnd );
|
|
$("#filter-spd-min").val(Filters.speed_min);
|
|
$("#filter-spd-max").val(Filters.speed_max);
|
|
$("#enable_spd" ).prop("checked",Filters.enable_spd );
|
|
$("#filter-dis-min").val(Filters.distance_min);
|
|
$("#filter-dis-max").val(Filters.distance_max);
|
|
$("#enable_dis" ).prop("checked",Filters.enable_dis );
|
|
$("#reg_filter" ).val(Filters.reg_filter);
|
|
$("#reg_enable" ).prop("checked",Filters.reg_enable );
|
|
$("#sensors_filter").val(Filters.sensors_filter);
|
|
$("#sensors_enable").prop("checked",Filters.sensors_enable);
|
|
$("#typ_enable" ).prop("checked",Filters.typ_enable );
|
|
$("#typ_filter" ).val(Filters.typ_filter);
|
|
$("#fli_enable" ).prop("checked",Filters.fli_enable );
|
|
$("#fli_filter" ).val(Filters.fli_filter);
|
|
$("#dest_enable" ).prop("checked",Filters.dest_enable );
|
|
$("#dest_filter" ).val(Filters.dest_filter);
|
|
$("#orig_enable" ).prop("checked",Filters.orig_enable );
|
|
$("#orig_filter" ).val(Filters.orig_filter);
|
|
$("#squawk_enable" ).prop("checked",Filters.squawk_enable );
|
|
$("#squawk_filter" ).val(Filters.squawk_filter);
|
|
$("#prio_enable" ).prop("checked",Filters.prio_enable );
|
|
$("#prio_filter" ).val(Filters.prio_filter);
|
|
$("#enable_adsb" ).prop("checked",Filters.enable_adsb );
|
|
$("#enable_mlat" ).prop("checked",Filters.enable_mlat );
|
|
$("#enable_modeac" ).prop("checked",Filters.enable_modeac );
|
|
$("#enable_flawa" ).prop("checked",Filters.enable_flawa );
|
|
$("#enable_ogn" ).prop("checked",Filters.enable_ogn );
|
|
$("#enable_flarm" ).prop("checked",Filters.enable_flarm );
|
|
$("#pref_source" ).val(Filters.pref_source);
|
|
$("#enable_night" ).prop("checked",GmapInit.enable_night );
|
|
$("#enable_atrack" ).prop("checked",GmapInit.enable_atrack );
|
|
$("#enable_mtrack" ).prop("checked",GmapInit.enable_mtrack );
|
|
$("#tracklength" ).val(GmapInit.tracklength);
|
|
$('#mapstyle' ).val(GmapInit.mapstyle);
|
|
$('#refreshtime' ).val(GmapInit.refreshtime);
|
|
$('#show_sensors' ).val(GmapInit.show_sensors);
|
|
|
|
|
|
function handleChange() {
|
|
Filters.altitude_min = $("#filter-alt-min").val() || undefined;
|
|
Filters.altitude_max = $("#filter-alt-max").val() || undefined;
|
|
Filters.enable_alt = $("#enable_alt" ).prop( "checked" );
|
|
Filters.enable_gnd = $("#enable_gnd" ).prop( "checked" );
|
|
Filters.speed_min = $("#filter-spd-min").val() || undefined;
|
|
Filters.speed_max = $("#filter-spd-max").val() || undefined;
|
|
Filters.enable_spd = $("#enable_spd" ).prop( "checked" );
|
|
Filters.distance_min = $("#filter-dis-min").val() || undefined;
|
|
Filters.distance_max = $("#filter-dis-max").val() || undefined;
|
|
Filters.enable_dis = $("#enable_dis" ).prop( "checked" );
|
|
Filters.reg_enable = $("#reg_enable" ).prop( "checked" );
|
|
Filters.reg_filter = $("#reg_filter" ).val() || undefined;
|
|
Filters.sensors_enable= $("#sensors_enable").prop( "checked" );
|
|
Filters.sensors_filter= $("#sensors_filter").val() || undefined;
|
|
Filters.typ_enable = $("#typ_enable" ).prop( "checked" );
|
|
Filters.typ_filter = $("#typ_filter" ).val() || undefined;
|
|
Filters.fli_enable = $("#fli_enable" ).prop( "checked" );
|
|
Filters.fli_filter = $("#fli_filter" ).val() || undefined;
|
|
Filters.dest_enable = $("#dest_enable" ).prop( "checked" );
|
|
Filters.dest_filter = $("#dest_filter" ).val() || undefined;
|
|
Filters.orig_enable = $("#orig_enable" ).prop( "checked" );
|
|
Filters.orig_filter = $("#orig_filter" ).val() || undefined;
|
|
Filters.squawk_enable = $("#squawk_enable" ).prop( "checked" );
|
|
Filters.squawk_filter = $("#squawk_filter" ).val() || undefined;
|
|
Filters.prio_enable = $("#prio_enable" ).prop( "checked" );
|
|
Filters.prio_filter = $("#prio_filter" ).val() || undefined;
|
|
Filters.enable_adsb = $("#enable_adsb" ).prop( "checked" );
|
|
Filters.enable_mlat = $("#enable_mlat" ).prop( "checked" );
|
|
Filters.enable_modeac = $("#enable_modeac" ).prop( "checked" );
|
|
Filters.enable_flawa = $("#enable_flawa" ).prop( "checked" );
|
|
Filters.enable_ogn = $("#enable_ogn" ).prop( "checked" );
|
|
Filters.enable_flarm = $("#enable_flarm" ).prop( "checked" );
|
|
Filters.pref_source = $("#pref_source" ).val() || undefined;
|
|
|
|
localStorage.setItem(rcd_globals.ls_filters_id, JSON.stringify(Filters));
|
|
|
|
if( Filters.prio_filter ) {
|
|
prio_filter_splitted = Filters.prio_filter.toUpperCase().split(",");
|
|
} else {
|
|
prio_filter_splitted = [];
|
|
}
|
|
|
|
fetchAdsbData();
|
|
}
|
|
|
|
function mapstyleChange() {
|
|
GmapInit.mapstyle = $('#mapstyle' ).val() || undefined;
|
|
GmapInit.enable_night = $('#enable_night' ).prop('checked');
|
|
GmapInit.refreshtime = $("#refreshtime" ).val() || undefined;
|
|
GmapInit.tracklength = $("#tracklength" ).val() || undefined;
|
|
GmapInit.enable_atrack = $("#enable_atrack").prop( "checked" );
|
|
GmapInit.enable_mtrack = $("#enable_mtrack").prop( "checked" );
|
|
GmapInit.show_sensors = $("#show_sensors" ).prop( "checked" );
|
|
Gmap.setMapTypeId(GmapInit.mapstyle);
|
|
|
|
localStorage.setItem(rcd_globals.ls_gmapinit_id, JSON.stringify(GmapInit));
|
|
|
|
if( GmapInit.enable_night ) nite.show();
|
|
else nite.hide();
|
|
|
|
fetchAllData();
|
|
|
|
for( var hex in flightPath2 ) {
|
|
flightPath2[hex].forEach( function ( X ) { X.setMap(null); });
|
|
delete flightPath2[hex];
|
|
}
|
|
|
|
}
|
|
|
|
function clear_filters() {
|
|
$('#filter-alt-min, #filter-alt-max, ' +
|
|
'#filter-spd-min, #filter-spd-max, ' +
|
|
'#filter-dis-min, #filter-dis-max, ' +
|
|
'#reg_filter, #sensors_filter, #typ_filter, #fli_filter, #dest_filter, ' +
|
|
"#orig_filter, #squawk_filter, #prio_filter, #pref_source").val(null);
|
|
$('#enable_alt, #enable_dis, #enable_spd, #reg_enable, #sensors_enable, #typ_enable, #fli_enable, #dest_enable, ' +
|
|
'#orig_enable, #squawk_enable, #prio_enable, #enable_atrack, #enable_mtrack, #enable_night').prop( 'checked', false );
|
|
$('#enable_adsb, #enable_gnd, #enable_mlat, #enable_modeac, #enable_flawa, #enable_ogn, #enable_flarm').prop( 'checked', true );
|
|
|
|
prio_filter_splitted = [];
|
|
handleChange();
|
|
};
|
|
}
|
|
else
|
|
{
|
|
$("#filter-dialog").show();
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
/********************************************************************************
|
|
* Information that is displayed as permanent label
|
|
* Color Table:
|
|
* https://www.quackit.com/html/codes/color/html_color_chart.cfm
|
|
*******************************************************************************/
|
|
function getIconForSensor(sensor)
|
|
{
|
|
var Scale = 1;
|
|
var Border = 'Black';
|
|
var Strokew = 1;
|
|
|
|
if( SingleSensor==sensor.id ) {
|
|
Border = 'Red';
|
|
Strokew = 3;
|
|
Scale = 1.5;
|
|
}
|
|
else if( Selected.length>0 ) {
|
|
var p = Planes[Selected.slice(-1)[0]].hex;
|
|
if( Planes[p].clnt.includes(sensor.id) ) {
|
|
Border = 'Blue';
|
|
Strokew = 3;
|
|
Scale = 1.5;
|
|
}
|
|
}
|
|
|
|
var Fill = ( sensor.active && sensor.iBy>30 ) ? 'Lime'
|
|
: ( sensor.active ) ? 'Orange'
|
|
: 'Red';
|
|
|
|
//http://tutorials.jenkov.com/svg/path-element.html
|
|
//var imageObj = {path:"M0,0 6,12 12,0z"}; // Triangle
|
|
//var imageObj = {path:"m25,1 6,17h18l-14,11 5,17-15-10-15,10 5-17-14-11h18z"}; // Star
|
|
var imageObj = {path:'M 13.6,18.8 L 6.3,18.8 1.1,13.6 1.1,6.3 6.3,1.1 13.6,1.1 18.8,6.3 18.8,13.6 z'}; // Octagon
|
|
|
|
var object_box = Raphael.pathBBox(imageObj.path);
|
|
var offset_x = (object_box.x + object_box.x2) / 2;
|
|
var offset_y = (object_box.y + object_box.y2) / 2;
|
|
|
|
var sensor_symbol = {
|
|
strokeColor : Border,
|
|
strokeWeight : Strokew,
|
|
path : imageObj.path,
|
|
scale : Scale,
|
|
fillColor : Fill,
|
|
fillOpacity : 0.9,
|
|
anchor : new google.maps.Point(offset_x, offset_y),
|
|
rotation : 180,
|
|
zIndex : 10
|
|
};
|
|
|
|
return sensor_symbol;
|
|
}
|
|
|
|
function labelSensorSetStyle(sensor, marker) {
|
|
marker.set('labelStyle', { opacity: 0.5, 'background-color': 'LightGreen'});
|
|
}
|
|
|
|
function fetchAllData() {
|
|
fetchAdsbData();
|
|
fetchTrackData();
|
|
fetchMapInfo();
|
|
if( rcd_globals.productname=='MLAT_SERVER' ) {
|
|
fetchSensors(GmapInit.show_sensors);
|
|
fetchModeACData();
|
|
}
|
|
}
|
|
|
|
/********************************************************************************
|
|
* Main
|
|
*******************************************************************************/
|
|
|
|
$(document).ready(function() {
|
|
getJSON( rcd_globals.fcgipath+"param.json?param=ownlat,ownlon,distanceunit", function(params) {
|
|
CenterLat = params.ownlat;
|
|
CenterLon = params.ownlon;
|
|
DistanceUnit = params.distanceunit ? "km" : "nm";
|
|
initialize();
|
|
});
|
|
});
|
|
|
|
function initialize() {
|
|
|
|
updateURLPlaneSelection();
|
|
|
|
/* There is no info_box_table without refreshGeneralInfo() */
|
|
loadAirports();
|
|
|
|
map_box = document.getElementById('map_box');
|
|
map_info_box = document.getElementById('map_info_box');
|
|
flight_info_box_adsb = document.getElementById('flight_info_box_adsb');
|
|
flight_info_box_modeac = document.getElementById('flight_info_box_modeac');
|
|
flight_info_box_klick = document.getElementById('flight_info_box_klick');
|
|
|
|
info_box_table = document.getElementById('info_box_table');
|
|
hide_info = document.getElementById('hide_info');
|
|
hide_info_btn = document.getElementById('hide_info_btn');
|
|
|
|
document.getElementById("btn_hide_info_box").onclick = toggleInfoBox;
|
|
|
|
showInfoBox(); // hideInfoBox();
|
|
|
|
var LS;
|
|
LS = localStorage.getItem(rcd_globals.ls_filters_id);
|
|
if( LS ) $.extend(Filters, JSON.parse(LS));
|
|
if( Filters.prio_filter ) prio_filter_splitted = Filters.prio_filter.toUpperCase().split(',');
|
|
|
|
LS = localStorage.getItem(rcd_globals.ls_gmapinit_id);
|
|
if( LS ) $.extend(GmapInit, JSON.parse(LS));
|
|
|
|
Gmap = new google.maps.Map(
|
|
map_box,
|
|
{
|
|
disableDefaultUI : true,
|
|
center : new google.maps.LatLng(GmapInit.CenterLat, GmapInit.CenterLon),
|
|
zoom : GmapInit.Zoomlevel,
|
|
mapTypeId : GmapInit.mapstyle,
|
|
zoomControl : true,
|
|
zoomControlOptions : { position : google.maps.ControlPosition.RIGHT_BOTTOM },
|
|
scaleControl : false,
|
|
streetViewControl : false
|
|
}
|
|
);
|
|
|
|
var currCenter = new google.maps.LatLng(GmapInit.CenterLat, GmapInit.CenterLon);
|
|
|
|
Gmap.addListener('click', deselectPlaneAll);
|
|
|
|
Gmap.addListener('zoom_changed', function() {
|
|
GmapInit.Zoomlevel=Gmap.getZoom();
|
|
localStorage.setItem(rcd_globals.ls_gmapinit_id, JSON.stringify(GmapInit));
|
|
});
|
|
|
|
Gmap.addListener('dragend', function() {
|
|
var currCenter = new google.maps.LatLng;
|
|
GmapInit.CenterLat = Gmap.getCenter().lat();
|
|
GmapInit.CenterLon = Gmap.getCenter().lng();
|
|
localStorage.setItem(rcd_globals.ls_gmapinit_id, JSON.stringify(GmapInit));
|
|
});
|
|
|
|
var filterControlDiv = document.createElement('div');
|
|
var filterControl = new FilterControl(filterControlDiv);
|
|
filterControlDiv.index = 1;
|
|
Gmap.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(filterControlDiv);
|
|
|
|
/* Setup night/day overlay */
|
|
nite.init(Gmap);
|
|
window.setInterval(function() { nite.setDate(null); nite.refresh(); }, 20000); // every 20s
|
|
if( Filters.enable_night ) nite.show();
|
|
else nite.hide();
|
|
|
|
/* Modify menus */
|
|
var MlatServerShow = document.getElementsByClassName('MlatServerShow');
|
|
console.log (MlatServerShow);
|
|
|
|
if( rcd_globals.productname=='MLAT_SERVER' ) {
|
|
document.getElementById("StatusHeader").innerHTML = ' MLAT Server Status';
|
|
}
|
|
|
|
var refreshLoop = function() {
|
|
return function() {
|
|
var timeout = parseFloat(GmapInit.refreshtime);
|
|
if( !timeout ) { timeout=1; }
|
|
if( rcd_globals.initialized ) {
|
|
fetchAllData();
|
|
}
|
|
timeout = Math.max(1000, 1000 * timeout);
|
|
window.setTimeout(refreshLoop, timeout);
|
|
}
|
|
}();
|
|
|
|
window.setTimeout(refreshLoop, 1000);
|
|
}
|