diff --git a/public_html/gmap.html b/public_html/gmap.html index 1e8422b..261a2e0 100644 --- a/public_html/gmap.html +++ b/public_html/gmap.html @@ -76,11 +76,13 @@ - Tracked aircraft (total): n/a + Aircraft (total): n/a +   - Tracked aircraft (with positions): n/a + (with positions): n/a + History: n/a positions diff --git a/public_html/planeObject.js b/public_html/planeObject.js index 1c27de4..1104130 100644 --- a/public_html/planeObject.js +++ b/public_html/planeObject.js @@ -1,3 +1,36 @@ +var planeSvg = "M 0,0 " + + "M 1.9565564,41.694305 C 1.7174505,40.497708 1.6419973,38.448747 " + + "1.8096508,37.70494 1.8936398,37.332056 2.0796653,36.88191 2.222907,36.70461 " + + "2.4497603,36.423844 4.087816,35.47248 14.917931,29.331528 l 12.434577," + + "-7.050718 -0.04295,-7.613412 c -0.03657,-6.4844888 -0.01164,-7.7625804 " + + "0.168134,-8.6194061 0.276129,-1.3160905 0.762276,-2.5869575 1.347875," + + "-3.5235502 l 0.472298,-0.7553719 1.083746,-0.6085497 c 1.194146,-0.67053522 " + + "1.399524,-0.71738842 2.146113,-0.48960552 1.077005,0.3285939 2.06344," + + "1.41299352 2.797602,3.07543322 0.462378,1.0469993 0.978731,2.7738408 " + + "1.047635,3.5036272 0.02421,0.2570284 0.06357,3.78334 0.08732,7.836246 0.02375," + + "4.052905 0.0658,7.409251 0.09345,7.458546 0.02764,0.04929 5.600384,3.561772 " + + "12.38386,7.805502 l 12.333598,7.715871 0.537584,0.959688 c 0.626485,1.118378 " + + "0.651686,1.311286 0.459287,3.516442 -0.175469,2.011604 -0.608966,2.863924 " + + "-1.590344,3.127136 -0.748529,0.200763 -1.293144,0.03637 -10.184829,-3.07436 " + + "C 48.007733,41.72562 44.793806,40.60197 43.35084,40.098045 l -2.623567," + + "-0.916227 -1.981212,-0.06614 c -1.089663,-0.03638 -1.985079,-0.05089 -1.989804," + + "-0.03225 -0.0052,0.01863 -0.02396,2.421278 -0.04267,5.339183 -0.0395,6.147742 " + + "-0.143635,7.215456 -0.862956,8.845475 l -0.300457,0.680872 2.91906,1.361455 " + + "c 2.929379,1.366269 3.714195,1.835385 4.04589,2.41841 0.368292,0.647353 " + + "0.594634,2.901439 0.395779,3.941627 -0.0705,0.368571 -0.106308,0.404853 " + + "-0.765159,0.773916 L 41.4545,62.83158 39.259237,62.80426 c -6.030106,-0.07507 " + + "-16.19508,-0.495041 -16.870991,-0.697033 -0.359409,-0.107405 -0.523792," + + "-0.227482 -0.741884,-0.541926 -0.250591,-0.361297 -0.28386,-0.522402 -0.315075," + + "-1.52589 -0.06327,-2.03378 0.23288,-3.033615 1.077963,-3.639283 0.307525," + + "-0.2204 4.818478,-2.133627 6.017853,-2.552345 0.247872,-0.08654 0.247455," + + "-0.102501 -0.01855,-0.711959 -0.330395,-0.756986 -0.708622,-2.221756 -0.832676," + + "-3.224748 -0.05031,-0.406952 -0.133825,-3.078805 -0.185533,-5.937448 -0.0517," + + "-2.858644 -0.145909,-5.208974 -0.209316,-5.222958 -0.06341,-0.01399 -0.974464," + + "-0.0493 -2.024551,-0.07845 L 23.247235,38.61921 18.831373,39.8906 C 4.9432155," + + "43.88916 4.2929558,44.057819 3.4954426,43.86823 2.7487826,43.690732 2.2007966," + + "42.916622 1.9565564,41.694305 z" + + var planeObject = { // Basic location information altitude : null, @@ -14,18 +47,29 @@ var planeObject = { // Data packet numbers messages : null, - seen : null, + + // Track history + tracklinesegs : [], + + + // When was this last updated (receiver timestamp) + last_message_time : null, + last_position_time : null, + + historySize : 0, + visible : true, // GMap Details marker : null, - markerColor : MarkerColor, - - tracklinesegs : [], - last_position_time : null, - - // When was this last updated? - updated : null, - reapable : false, + icon : { + strokeWeight: 1, + path: planeSvg, + scale: 0.4, + fillColor: MarkerColor, + fillOpacity: 0.9, + anchor: new google.maps.Point(32, 32), // Set anchor to middle of plane. + rotation: 0 + }, // Appends data to the running track so we can get a visual tail on the plane // Only useful for a long running browser session. @@ -42,6 +86,7 @@ var planeObject = { ground : (this.altitude === "ground") }; this.tracklinesegs.push(newseg); + this.historySize += 2; return; } @@ -54,7 +99,7 @@ var planeObject = { var ground_track = (this.altitude === "ground"); if (!new_data) - return; + return false; if (est_track) { if (!lastseg.estimated) { @@ -64,14 +109,16 @@ var planeObject = { line : null, head_update : this.last_position_time, estimated : true }); - return; + this.historySize += 2; + return true; } // Append to ongoing estimated line //console.log(this.icao + " extending estimated (" + lastseg.track.getLength() + ")"); lastseg.track.push(here); lastseg.head_update = this.last_position_time; - return; + this.historySize++; + return true; } if (lastseg.estimated) { @@ -83,12 +130,13 @@ var planeObject = { tail_update : this.last_position_time, estimated : false, ground : (this.altitude === "ground") }); - return; + this.historySize += 2; + return true; } if ( (lastseg.ground && this.altitude !== "ground") || (!lastseg.ground && this.altitude === "ground") ) { - console.log(this.icao + " ground state changed"); + //console.log(this.icao + " ground state changed"); // Create a new segment as the ground state changed. // assume the state changed halfway between the two points var midpoint = google.maps.geometry.spherical.interpolate(lastpos,here,0.5); @@ -99,7 +147,8 @@ var planeObject = { tail_update : this.last_position_time, estimated : false, ground : (this.altitude === "ground") }); - return; + this.historySize += 4; + return true; } // Add more data to the existing track. @@ -110,15 +159,17 @@ var planeObject = { //console.log(this.icao + " retain last point"); lastseg.track.push(here); lastseg.tail_update = lastseg.head_update; + this.historySize ++; } else { // replace the last point with the current position lastseg.track.setAt(lastseg.track.getLength()-1, here); } lastseg.head_update = this.last_position_time; + return true; }, // This is to remove the line from the screen if we deselect the plane - funcClearLine : function() { + clearLines : function() { for (var i = 0; i < this.tracklinesegs.length; ++i) { var seg = this.tracklinesegs[i]; if (seg.line !== null) { @@ -128,78 +179,39 @@ var planeObject = { } }, - // Should create an icon for us to use on the map... - funcGetIcon : function() { - this.markerColor = MarkerColor; - // If this marker is selected we should make it lighter than the rest. - if (this.is_selected == true) { - this.markerColor = SelectedColor; - } + updateIcon : function() { + var col = MarkerColor; - // If we have not seen a recent update, change color - if (this.seen > 15) { - this.markerColor = StaleColor; - } + // If this marker is selected we should make it lighter than the rest. + if (this.is_selected) + col = SelectedColor; + + // If we have not seen a recent update, change color + if (this.seen > 15) + col = StaleColor; - // Plane marker - var baseSvg = { - planeData : "M 1.9565564,41.694305 C 1.7174505,40.497708 1.6419973,38.448747 " + - "1.8096508,37.70494 1.8936398,37.332056 2.0796653,36.88191 2.222907,36.70461 " + - "2.4497603,36.423844 4.087816,35.47248 14.917931,29.331528 l 12.434577," + - "-7.050718 -0.04295,-7.613412 c -0.03657,-6.4844888 -0.01164,-7.7625804 " + - "0.168134,-8.6194061 0.276129,-1.3160905 0.762276,-2.5869575 1.347875," + - "-3.5235502 l 0.472298,-0.7553719 1.083746,-0.6085497 c 1.194146,-0.67053522 " + - "1.399524,-0.71738842 2.146113,-0.48960552 1.077005,0.3285939 2.06344," + - "1.41299352 2.797602,3.07543322 0.462378,1.0469993 0.978731,2.7738408 " + - "1.047635,3.5036272 0.02421,0.2570284 0.06357,3.78334 0.08732,7.836246 0.02375," + - "4.052905 0.0658,7.409251 0.09345,7.458546 0.02764,0.04929 5.600384,3.561772 " + - "12.38386,7.805502 l 12.333598,7.715871 0.537584,0.959688 c 0.626485,1.118378 " + - "0.651686,1.311286 0.459287,3.516442 -0.175469,2.011604 -0.608966,2.863924 " + - "-1.590344,3.127136 -0.748529,0.200763 -1.293144,0.03637 -10.184829,-3.07436 " + - "C 48.007733,41.72562 44.793806,40.60197 43.35084,40.098045 l -2.623567," + - "-0.916227 -1.981212,-0.06614 c -1.089663,-0.03638 -1.985079,-0.05089 -1.989804," + - "-0.03225 -0.0052,0.01863 -0.02396,2.421278 -0.04267,5.339183 -0.0395,6.147742 " + - "-0.143635,7.215456 -0.862956,8.845475 l -0.300457,0.680872 2.91906,1.361455 " + - "c 2.929379,1.366269 3.714195,1.835385 4.04589,2.41841 0.368292,0.647353 " + - "0.594634,2.901439 0.395779,3.941627 -0.0705,0.368571 -0.106308,0.404853 " + - "-0.765159,0.773916 L 41.4545,62.83158 39.259237,62.80426 c -6.030106,-0.07507 " + - "-16.19508,-0.495041 -16.870991,-0.697033 -0.359409,-0.107405 -0.523792," + - "-0.227482 -0.741884,-0.541926 -0.250591,-0.361297 -0.28386,-0.522402 -0.315075," + - "-1.52589 -0.06327,-2.03378 0.23288,-3.033615 1.077963,-3.639283 0.307525," + - "-0.2204 4.818478,-2.133627 6.017853,-2.552345 0.247872,-0.08654 0.247455," + - "-0.102501 -0.01855,-0.711959 -0.330395,-0.756986 -0.708622,-2.221756 -0.832676," + - "-3.224748 -0.05031,-0.406952 -0.133825,-3.078805 -0.185533,-5.937448 -0.0517," + - "-2.858644 -0.145909,-5.208974 -0.209316,-5.222958 -0.06341,-0.01399 -0.974464," + - "-0.0493 -2.024551,-0.07845 L 23.247235,38.61921 18.831373,39.8906 C 4.9432155," + - "43.88916 4.2929558,44.057819 3.4954426,43.86823 2.7487826,43.690732 2.2007966," + - "42.916622 1.9565564,41.694305 z" - }; + // If the squawk code is one of the international emergency codes, + // match the info window alert color. + var squawk_col = { '7500' : 'rgb(255, 85, 85)', + '7600' : 'rgb(0, 255, 255)', + '7700' : 'rgb(255, 255, 0)' }; + if (this.squawk in squawk_col) + col = squawk_col[this.squawk]; - // If the squawk code is one of the international emergency codes, - // match the info window alert color. - if (this.squawk == 7500) { - this.markerColor = "rgb(255, 85, 85)"; - } - if (this.squawk == 7600) { - this.markerColor = "rgb(0, 255, 255)"; - } - if (this.squawk == 7700) { - this.markerColor = "rgb(255, 255, 0)"; - } + var weight = this.is_selected ? 2 : 1; + var rotation = (this.track === null ? 0 : this.track); + + if (col === this.icon.fillColor && weight === this.icon.strokeWeight && rotation === this.icon.rotation) + return false; // no changes - // If we have not overwritten color by now, an extension still could but - // just keep on trucking. :) + this.icon.fillColor = col; + this.icon.strokeWeight = weight; + this.icon.rotation = rotation; + if (this.marker) + this.marker.setIcon(this.icon); - return { - strokeWeight: (this.is_selected ? 2 : 1), - path: "M 0,0 "+ baseSvg["planeData"], - scale: 0.4, - fillColor: this.markerColor, - fillOpacity: 0.9, - anchor: new google.maps.Point(32, 32), // Set anchor to middle of plane. - rotation: this.track - }; - }, + return true; + }, // TODO: Trigger actions of a selecting a plane selectPlane : function(){ @@ -207,12 +219,11 @@ var planeObject = { }, // Update our data - funcUpdateData : function(receiver_now,data){ + updateData : function(receiver_timestamp, data){ // Update all of our data - this.updated = new Date().getTime(); this.icao = data.hex; this.messages = data.messages; - this.seen = data.seen; + this.last_message_time = receiver_timestamp - data.seen; if (typeof data.altitude !== "undefined") this.altitude = data.altitude; @@ -223,77 +234,88 @@ var planeObject = { if (typeof data.lat !== "undefined") { this.latitude = data.lat; this.longitude = data.lon; - this.seen_pos = data.seen_pos; - this.last_position_time = receiver_now - data.seen_pos; + this.last_position_time = receiver_timestamp - data.seen_pos; } if (typeof data.flight !== "undefined") this.flight = data.flight; if (typeof data.squawk !== "undefined") this.squawk = data.squawk; + }, - // If no packet in over 58 seconds, consider the plane reapable - // This way we can hold it, but not show it just in case the plane comes back + updateTick : function(receiver_timestamp) { + // recompute seen and seen_pos + this.seen = receiver_timestamp - this.last_message_time; + this.seen_pos = (this.last_position_time === null ? null : receiver_timestamp - this.last_position_time); + + // If no packet in over 58 seconds, clear the plane. if (this.seen > 58) { - this.reapable = true; - if (this.marker) { - this.marker.setMap(null); - this.marker = null; - } - this.funcClearLine(); - if (SelectedPlane == this.icao) { - if (this.is_selected) { - this.is_selected = false; - } - SelectedPlane = null; - } + if (this.visible) { + //console.log("hiding " + this.icao); + this.clearMarker(); + this.visible = false; + if (SelectedPlane == this.icao) + selectPlaneByHex(null); + } } else { - this.reapable = false; - } - - // Is the position valid? - if (!this.reapable && typeof data.lat !== "undefined") { - this.updateTrack(); - if (this.is_selected) { - this.funcUpdateLines(); - } - - this.marker = this.funcUpdateMarker(); + this.visible = true; + if (this.latitude !== null) { + if (this.updateTrack()) { + this.updateLines(); + this.updateMarker(true); + } else { + this.updateMarker(false); // didn't move + } + } } }, + clearMarker: function() { + if (this.marker) { + this.marker.setMap(null); + this.marker = null; + } + }, + // Update our marker on the map - funcUpdateMarker: function() { - if (this.marker) { + updateMarker: function(moved) { + if (!this.visible) { + this.clearMarker(); + return; + } + + if (this.marker) { + if (moved) this.marker.setPosition(new google.maps.LatLng(this.latitude, this.longitude)); - this.marker.setIcon(this.funcGetIcon()); - } else { - this.marker = new google.maps.Marker({ - position: new google.maps.LatLng(this.latitude, this.longitude), - map: GoogleMap, - icon: this.funcGetIcon(), - visible: true - }); - - // This is so we can match icao address - this.marker.icao = this.icao; - - // Trap clicks for this marker. - google.maps.event.addListener(this.marker, 'click', this.selectPlane); - } - - // Setting the marker title - if (this.flight === null || this.flight.length == 0) { - this.marker.setTitle(this.hex); - } else { - this.marker.setTitle(this.flight+' ('+this.icao+')'); - } - return this.marker; - }, - + this.updateIcon(); + } else { + this.updateIcon(); + this.marker = new google.maps.Marker({ + position: new google.maps.LatLng(this.latitude, this.longitude), + map: GoogleMap, + icon: this.icon, + visible: true + }); + + // This is so we can match icao address + this.marker.icao = this.icao; + + // Trap clicks for this marker. + google.maps.event.addListener(this.marker, 'click', this.selectPlane); + } + + // Setting the marker title + if (this.flight === null || this.flight.length == 0) { + this.marker.setTitle(this.hex); + } else { + this.marker.setTitle(this.flight+' ('+this.icao+')'); + } + }, + // Update our planes tail line, - // TODO: Make this multi colored based on options - // altitude (default) or speed - funcUpdateLines: function() { + updateLines: function() { + if (!this.is_selected) + return; + for (var i = 0; i < this.tracklinesegs.length; ++i) { var seg = this.tracklinesegs[i]; if (seg.line === null) { @@ -329,5 +351,10 @@ var planeObject = { } } } + }, + + destroy : function() { + this.clearLines(); + this.clearMarker(); } }; diff --git a/public_html/script.js b/public_html/script.js index c71df5a..25e38dd 100644 --- a/public_html/script.js +++ b/public_html/script.js @@ -51,8 +51,14 @@ function fetchData() { } // Call the function update - plane.funcUpdateData(now, ac); + plane.updateData(now, ac); } + + // update timestamps, visibility, history track for all planes - not only those updated + for (var i = 0; i < PlanesOrdered.length; ++i) { + var plane = PlanesOrdered[i]; + plane.updateTick(now); + } refreshTableInfo(); refreshSelected(); @@ -63,7 +69,7 @@ function initialize() { PlaneRowTemplate = document.getElementById("plane_row_template"); if (!ShowClocks) { - $('#timestamps').addClass('hidden'); + $('#timestamps').css('display','none'); } // Get receiver metadata, reconfigure using it, then continue @@ -93,8 +99,8 @@ function initialize_after_config() { sortByDistance(); } else { SitePosition = null; - PlaneRowTemplate.cells[5].className = "hidden"; // hide distance column - document.getElementById("distance").className = "hidden"; // hide distance header + PlaneRowTemplate.cells[5].style.display = 'none'; // hide distance column + document.getElementById("distance").style.display = 'none'; // hide distance header sortByAltitude(); } @@ -251,18 +257,20 @@ function initialize_after_config() { // This looks for planes to reap out of the master Planes variable function reaper() { - reaptime = new Date().getTime(); + //console.log("Reaping started.."); - console.log("Reaping started.."); - - // Loop the planes + // Look for planes where we have seen no messages for >300 seconds var newPlanes = []; for (var i = 0; i < PlanesOrdered.length; ++i) { var plane = PlanesOrdered[i]; - if ((reaptime - plane.updated) > 300000) { + if (plane.seen > 300) { // Reap it. - console.log("Reaped " + plane.icao); + //console.log("Reaping " + plane.icao); + //console.log("parent " + plane.tr.parentNode); + plane.tr.parentNode.removeChild(plane.tr); + plane.tr = null; delete Planes[plane.icao]; + plane.destroy(); } else { // Keep it. newPlanes.push(plane); @@ -282,26 +290,27 @@ function refreshSelected() { } if (!selected) { - $('#dump1090_infoblock').removeClass('hidden'); + $('#selected_infoblock').css('display','none'); + $('#dump1090_infoblock').css('display','block'); $('#dump1090_version').text(Dump1090Version); $('#dump1090_total_ac').text(TrackedAircraft); $('#dump1090_total_ac_positions').text(TrackedAircraftPositions); - $('#selected_infoblock').addClass('hidden'); + $('#dump1090_total_history').text(TrackedHistorySize); return; } - $('#dump1090_infoblock').addClass('hidden'); - $('#selected_infoblock').removeClass('hidden'); + $('#dump1090_infoblock').css('display','none'); + $('#selected_infoblock').css('display','block'); if (selected.flight !== null && selected.flight !== "") { $('#selected_callsign').text(selected.flight); - $('#selected_links').removeClass('hidden'); + $('#selected_links').css('display','inline'); $('#selected_fr24_link').attr('href','http://fr24.com/'+selected.flight); $('#selected_flightstats_link').attr('href','http://www.flightstats.com/go/FlightStatus/flightStatusByFlight.do?flightNumber='+selected.flight); $('#selected_flightaware_link').attr('href','http://flightaware.com/live/flight/'+selected.flight); } else { $('#selected_callsign').text('n/a (' + selected.icao + ')'); - $('#selected_links').addClass('hidden'); + $('#selected_links').css('display','none'); } var emerg = document.getElementById('selected_emergency'); @@ -420,27 +429,27 @@ function refreshTableInfo() { TrackedAircraft = 0 TrackedAircraftPositions = 0 + TrackedHistorySize = 0 for (var i = 0; i < PlanesOrdered.length; ++i) { var tableplane = PlanesOrdered[i]; - if (tableplane.reapable) { - tableplane.tr.className = "hidden"; + TrackedHistorySize += tableplane.historySize; + if (!tableplane.visible) { + tableplane.tr.className = "plane_table_row hidden"; } else { TrackedAircraft++; - var classes = "plane_table_row"; - + if (tableplane.latitude !== null) - classes += " vPosition"; + classes += " vPosition"; if (tableplane.icao == SelectedPlane) - classes += " selected"; + classes += " selected"; if (tableplane.squawk in EmergencySquawks) { - classes += ' squawk' + tableplane.squawk; + classes += (" squawk" + tableplane.squawk); show_squawk_warning = true; - } - - tableplane.tr.className = classes; + } + // ICAO doesn't change tableplane.tr.cells[1].textContent = (tableplane.flight !== null ? tableplane.flight : ""); tableplane.tr.cells[2].textContent = (tableplane.squawk !== null ? tableplane.squawk : ""); @@ -463,13 +472,16 @@ function refreshTableInfo() { tableplane.tr.cells[6].textContent = (tableplane.track !== null ? tableplane.track : ""); tableplane.tr.cells[7].textContent = tableplane.messages; tableplane.tr.cells[8].textContent = tableplane.seen; + + tableplane.tr.className = classes; + } } if (show_squawk_warning) { - $("#SpecialSquawkWarning").removeClass('hidden'); + $("#SpecialSquawkWarning").css('display','block'); } else { - $("#SpecialSquawkWarning").addClass('hidden'); + $("#SpecialSquawkWarning").css('display','none'); } resortTable(); @@ -562,26 +574,23 @@ function selectPlaneByHex(hex) { // If SelectedPlane has something in it, clear out the selected if (SelectedPlane != null) { Planes[SelectedPlane].is_selected = false; - Planes[SelectedPlane].funcClearLine(); - Planes[SelectedPlane].markerColor = MarkerColor; - // If the selected has a marker, make it not stand out - if (Planes[SelectedPlane].marker) { - Planes[SelectedPlane].marker.setIcon(Planes[SelectedPlane].funcGetIcon()); - } - Planes[SelectedPlane].tr.classList.remove("selected"); + Planes[SelectedPlane].clearLines(); + Planes[SelectedPlane].updateMarker(); + $(Planes[SelectedPlane].tr).removeClass("selected"); } // If we are clicking the same plane, we are deselected it. - if (String(SelectedPlane) != String(hex)) { + if (SelectedPlane === hex) { + hex = null; + } + + if (hex !== null) { // Assign the new selected SelectedPlane = hex; Planes[SelectedPlane].is_selected = true; - // If the selected has a marker, make it stand out - if (Planes[SelectedPlane].marker) { - Planes[SelectedPlane].funcUpdateLines(); - Planes[SelectedPlane].marker.setIcon(Planes[SelectedPlane].funcGetIcon()); - } - Planes[SelectedPlane].tr.classList.add("selected"); + Planes[SelectedPlane].updateLines(); + Planes[SelectedPlane].updateMarker(); + $(Planes[SelectedPlane].tr).addClass("selected"); } else { SelectedPlane = null; }