diff --git a/.gitignore b/.gitignore index 90a0967..bba68c8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ testfiles/*.bin misc frames.js .*.swp -~* - +*~ +*.rej +*.orig diff --git a/dump1090.c b/dump1090.c index 2b17a08..d2c79bb 100644 --- a/dump1090.c +++ b/dump1090.c @@ -3623,18 +3623,28 @@ char *aircraftsToJson(int *len) { p += l; buflen -= l; while(a) { int altitude = a->altitude, speed = a->speed; - + int position = 0; + int track = 0; + /* Convert units to metric if --metric was specified. */ if (Modes.metric) { altitude = (int) (altitude / 3.2828); speed = (int) (speed * 1.852); } + if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) { + position = 1; + } + + if (a->bFlags & MODES_ACFLAGS_HEADING_VALID) { + track = 1; + } + l = snprintf(p,buflen, "{\"hex\":\"%06x\", \"squawk\":\"%04x\", \"flight\":\"%s\", \"lat\":%f, " - "\"lon\":%f, \"altitude\":%d, \"track\":%d, " + "\"lon\":%f, \"validposition\":%d, \"altitude\":%d, \"track\":%d, \"validtrack\":%d," "\"speed\":%d, \"messages\":%ld, \"seen\":%d},\n", - a->addr, a->modeA, a->flight, a->lat, a->lon, a->altitude, a->track, + a->addr, a->modeA, a->flight, a->lat, a->lon, position, a->altitude, a->track, track, a->speed, a->messages, (int)(now - a->seen)); p += l; buflen -= l; diff --git a/public_html/gmap.html b/public_html/gmap.html index 4f086d9..b26217b 100644 --- a/public_html/gmap.html +++ b/public_html/gmap.html @@ -10,7 +10,7 @@ -
+

Dump1090 - 00:00:00 UTC

@@ -22,3 +22,4 @@
+ diff --git a/public_html/script.js b/public_html/script.js index 4fdb03e..e78d9b2 100644 --- a/public_html/script.js +++ b/public_html/script.js @@ -11,156 +11,264 @@ if (localStorage['CenterLat']) { CenterLat = Number(localStorage['CenterLat']); if (localStorage['CenterLon']) { CenterLon = Number(localStorage['CenterLon']); } if (localStorage['ZoomLvl']) { ZoomLvl = Number(localStorage['ZoomLvl']); } -function getIconForPlane(plane) { +function getIconForPlane(plane, deselect) { + var selected = false; + var track = 0; var r = 255, g = 255, b = 0; var maxalt = 40000; // Max altitude in the average case - var invalt = maxalt-plane.altitude; - var selected = (Selected == plane.hex); - + var invalt = 0; + + // If there is plane object + if (plane) { + invalt = maxalt-plane.altitude; + if (Selected == plane.hex && !deselect) { + selected = true; + } + track = plane.track; + } + if (invalt < 0) invalt = 0; b = parseInt(255/maxalt*invalt); + return { strokeWeight: (selected ? 2 : 1), path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW, scale: 5, fillColor: 'rgb('+r+','+g+','+b+')', fillOpacity: 0.9, - rotation: plane.track + rotation: track }; } -function selectPlane() { - if (!Planes[this.planehex]) return; +/* Gets hex code of selected plane as string or nothing. * + * Select not valid ICAO24 (hex) address to clear selection. */ +function selectPlane(selectedPlane) { + if (selectedPlane.length) this.planehex = selectedPlane; + + // Deselect planes + if (!Planes[this.planehex]) { + if (Planes[Selected].marker) { + Planes[Selected].marker.setIcon(getIconForPlane(Planes[Selected], true)); + } + Selected = null; + refreshSelectedInfo(); + refreshTableInfo(); + return; + } + var old = Selected; Selected = this.planehex; - if (Planes[old]) { - /* Remove the highlight in the previously selected plane. */ + + if (Planes[old] && Planes[old].validposition) { + // Remove the highlight in the previously selected plane. Planes[old].marker.setIcon(getIconForPlane(Planes[old])); } - Planes[Selected].marker.setIcon(getIconForPlane(Planes[Selected])); + + if (Planes[Selected].validposition) { + Planes[Selected].marker.setIcon(getIconForPlane(Planes[Selected])); + } + refreshSelectedInfo(); + refreshTableInfo(); } function refreshGeneralInfo() { var i = document.getElementById('geninfo'); - i.innerHTML = PlanesOnGrid + ' planes on grid.
'; - i.innerHTML += PlanesOnMap + ' planes on map.'; + i.innerHTML = PlanesOnMap + ' planes on map.
'; + i.innerHTML += PlanesOnGrid + ' planes on grid.'; } function refreshSelectedInfo() { var i = document.getElementById('selinfo'); var p = Planes[Selected]; - - if (!p) return; - var html = 'ICAO: '+p.hex+'
'; - if (p.flight.length) { - html += ''+p.flight+'
'; + + // If no plane is selected + if (!p) { + p = {}; + p.flight = ""; + p.hex = ""; + p.squawk = ""; + p.altitude = "0"; + p.speed = "0"; + p.lat = "lat"; + p.lon = "lon"; + p.messages = "0"; + p.seen = "0"; } - html += 'Altitude: '+p.altitude+' feet
'; - html += 'Speed: '+p.speed+' knots
'; - html += 'Coordinates: '+p.lat+', '+p.lon+'
'; - html += 'Messages: '+p.messages+'
'; - html += 'Seen: '+p.seen+' sec
'; - i.innerHTML = html; -} - -function refreshTableInfo() { - var i = document.getElementById('tabinfo'); - - var html = ''; - html += ''; - for (var p in Planes) { - if (p == Selected) { - html += ''; - } else { - html += ''; - } - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; + + var html = '
FlightAltitudeSpeedTrackLatLongSeenMsgs
' + Planes[p].flight + '' + Planes[p].altitude + '' + Planes[p].speed + '' + Planes[p].track + '' + Planes[p].lat + '' + Planes[p].lon + '' + Planes[p].seen + '' + Planes[p].messages + '
'; + html += ''; + html += ''; + if (p.squawk != "0000") { + html += ''; + } else { + html += ''; } + html += ''; + html += ''; + if (p.validposition) { + html += ''; + } else { + html += ''; + } + html += ''; + html += ''; html += '
'+p.flight+' 
ICAO:'+p.hex+'
Squawk:'+p.squawk+'
Squawk:n/a
Altitude:'+p.altitude+' feet
Speed:'+p.speed+' knots
Coordinates:'+p.lat+', '+p.lon+'
Coordinates:n/a
Messages:'+p.messages+'
Seen:'+p.seen+' sec
'; i.innerHTML = html; } -function fetchData() { - $.getJSON('data.json', function(data) { - var stillhere = {} - PlanesOnMap = 0; - - for (var j=0; j < data.length; j++) { - var plane = data[j]; - stillhere[plane.hex] = true; - plane.flight = $.trim(plane.flight); - - if (plane.lat != 0 && plane.lon != 0) { - // Show only planes with position - var marker = null; - PlanesOnMap++; - - if (Planes[plane.hex]) { - // Move and refresh old plane on map - var myplane = Planes[plane.hex]; - marker = myplane.marker; - var icon = marker.getIcon(); - var newpos = new google.maps.LatLng(plane.lat, plane.lon); - marker.setPosition(newpos); - marker.setIcon(getIconForPlane(plane)); - myplane.altitude = plane.altitude; - myplane.speed = plane.speed; - myplane.lat = plane.lat; - myplane.lon = plane.lon; - myplane.track = plane.track; - myplane.flight = plane.flight; - myplane.seen = plane.seen; - myplane.messages = plane.messages; - if (myplane.hex == Selected) - refreshSelectedInfo(); - } else { - // Add new plane to map - marker = new google.maps.Marker({ - position: new google.maps.LatLng(plane.lat, plane.lon), - map: Map, - icon: getIconForPlane(plane) - }); - plane.marker = marker; - marker.planehex = plane.hex; - Planes[plane.hex] = plane; - - // Trap clicks for this marker. - google.maps.event.addListener(marker, 'click', selectPlane); - } - - if (plane.flight.length == 0) { - marker.setTitle(plane.hex) - } else { - marker.setTitle(plane.flight+' ('+plane.hex+')') - } - } +function refreshTableInfo() { + var html = ''; + html += ''; + html += ''; + html += ''; + html += ''; + for (var p in Planes) { + var specialStyle = ""; + if (p == Selected) { + html += ''; + } else { + html += ''; } - - PlanesOnGrid = data.length; - - /* Remove idle planes. */ - for (var p in Planes) { - if (!stillhere[p]) { - Planes[p].marker.setMap(null); - delete Planes[p]; - } + if (Planes[p].validposition) { + specialStyle = 'bold'; } + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + } + html += '
hexFlightSquawkAltitudeSpeedTrackMsgsSeen
' + Planes[p].hex + '' + Planes[p].flight + '' + Planes[p].squawk + '' + Planes[p].altitude + '' + Planes[p].speed + '' + Planes[p].track + '' + Planes[p].messages + '' + Planes[p].seen + '
'; + + document.getElementById('tabinfo').innerHTML = html; - refreshTableInfo() ; - + // Click event for table - lags sometimes for some reason? + $('#tableinfo').find('tr').click( function(){ + var hex = $(this).find('td:first').text(); + selectPlane(hex); }); } +function fetchData() { + $.getJSON('data.json', function(data) { + // Planes that are still with us, and set map count to 0 + var stillhere = {} + PlanesOnMap = 0; + + // Loop through all the planes in the data packet + for (var j=0; j < data.length; j++) { + + // Set plane to be this particular plane in the data set + var plane = data[j]; + // Add to the still here list + stillhere[plane.hex] = true; + plane.flight = $.trim(plane.flight); + + // Set the marker to null, for now + var marker = null; + + // Either update the data or add it + if (Planes[plane.hex]) { + // Declare our plane that we are working with from our old data set + var myplane = Planes[plane.hex]; + + // If the has valid position, we should make a marker for it + if (plane.validposition) { + if (myplane.marker != null) { + marker = myplane.marker; + var icon = marker.getIcon(); + var newpos = new google.maps.LatLng(plane.lat, plane.lon); + marker.setPosition(newpos); + marker.setIcon(getIconForPlane(plane)); + PlanesOnMap++; + } else { + // Add new plane to map, dont ask me why this is needed here now... + marker = new google.maps.Marker({ + position: new google.maps.LatLng(plane.lat, plane.lon), + map: Map, + icon: getIconForPlane(plane) + }); + myplane.marker = marker; + marker.planehex = plane.hex; + PlanesOnMap++; + + // Trap clicks for this marker. + google.maps.event.addListener(marker, 'click', selectPlane); + } + } + + // Update all the other information + myplane.altitude = plane.altitude; + myplane.speed = plane.speed; + myplane.lat = plane.lat; + myplane.lon = plane.lon; + myplane.track = plane.track; + myplane.flight = plane.flight; + myplane.seen = plane.seen; + myplane.messages = plane.messages; + myplane.squawk = plane.squawk; + myplane.validposition = plane.validposition; + myplane.validtrack = plane.validtrack; + + // If this is a selected plane, refresh its data outside of the table + if (myplane.hex == Selected) + refreshSelectedInfo(); + } else { + // This is a new plane + // Do we have a lat/long that is not 0? + if (plane.validposition) { + // Add new plane to map + marker = new google.maps.Marker({ + position: new google.maps.LatLng(plane.lat, plane.lon), + map: Map, + icon: getIconForPlane(plane) + }); + plane.marker = marker; + marker.planehex = plane.hex; + PlanesOnMap++; + + // Trap clicks for this marker. + google.maps.event.addListener(marker, 'click', selectPlane); + } + + // Copy the plane into Planes + Planes[plane.hex] = plane; + } + + // If we have lat/long, we must have a marker, so lets set the marker title + if (plane.validposition) { + if (plane.flight.length == 0) { + marker.setTitle(plane.hex) + } else { + marker.setTitle(plane.flight+' ('+plane.hex+')') + } + } + + } + + // How many planes have we heard from? + PlanesOnGrid = data.length; + + /* Remove idle planes. */ + for (var p in Planes) { + if (!stillhere[p]) { + if (Planes[p].marker != null) + Planes[p].marker.setMap(null); + delete Planes[p]; + } + } + + refreshTableInfo(); + refreshSelectedInfo(); + }); +} + function checkTime(i) { if (i < 10) { return "0" + i; @@ -180,7 +288,7 @@ function printTime() { } } -function placeFooter() { +function placeFooter() { var windHeight = $(window).height(); var footerHeight = $('#info_footer').height(); var offset = parseInt(windHeight) - parseInt(footerHeight); @@ -200,7 +308,7 @@ function resetMap() { Map.setZoom(parseInt(localStorage['ZoomLvl'])); Map.setCenter(new google.maps.LatLng(parseInt(localStorage['CenterLat']), parseInt(localStorage['CenterLon']))); Selected = null; - document.getElementById('selinfo').innerHTML = ''; + refreshSelectedInfo(); } function initialize() { @@ -249,6 +357,15 @@ function initialize() { google.maps.event.addListener(Map, 'zoom_changed', function() { localStorage['ZoomLvl'] = Map.getZoom(); }); + + google.maps.event.addListener(Map, 'click', function() { + if (Selected) { + selectPlane("xyzxyz"); // Select not valid ICAO24 (hex) address to clear selection. + } + Selected = null; + refreshSelectedInfo(); + refreshTableInfo(); + }); // Setup our timer to poll from the server. window.setInterval(function() { @@ -260,4 +377,8 @@ function initialize() { window.setInterval(function() { printTime(); }, 250); + + refreshGeneralInfo(); + refreshSelectedInfo(); + refreshTableInfo(); } diff --git a/public_html/style.css b/public_html/style.css index 86c8576..7296a9e 100644 --- a/public_html/style.css +++ b/public_html/style.css @@ -1,9 +1,12 @@ html { height: 100% } body { height: 100%; margin: 0; padding: 0 } -#map_canvas { height: 100% } +#map_canvas { +height: 100%; +margin-right:390px; +} #info { position: absolute; -width:20%; +width:390px; height:100%; bottom:0px; right:0px; @@ -36,4 +39,10 @@ margin:0px; font-size: x-small; font-family: monospace; } +#tableinforow { +cursor: pointer; +} +#tableinforow .bold { +font-weight:bold; +}