Skip to content

Commit b65f9df

Browse files
author
Sam Lord
committed
Project push
V1.0
1 parent 1ee5802 commit b65f9df

File tree

5 files changed

+183
-0
lines changed

5 files changed

+183
-0
lines changed

index.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<html>
2+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
3+
integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA=="
4+
crossorigin=""/>
5+
<!-- Make sure you put this AFTER Leaflet's CSS -->
6+
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"
7+
integrity="sha512-QVftwZFqvtRNi0ZyCtsznlKSWOStnDORoefr1enyq5mVL4tmKB3S/EnC3rRJcxCPavG10IcrVGSmPh6Qw5lwrg=="
8+
crossorigin=""></script>
9+
<link rel="stylesheet" href="./style.css"/>
10+
<title>Dump1090 Web Client</title>
11+
12+
<div id="planeMap"></div>
13+
14+
<script src="./map.js"></script>
15+
</html>

map.js

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Leaflet map setup
2+
var planeMap = L.map('planeMap').setView([50.27, -3.70], 8);
3+
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
4+
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
5+
}).addTo(planeMap);
6+
var markers = L.layerGroup().addTo(planeMap);
7+
8+
// Time between data fetches in seconds
9+
let dataFetchBreakTime = 3;
10+
// How long to wait until we remove planes from the map (seconds)
11+
let planeTimeout = 120;
12+
// In-mem plane storage
13+
let activePlanes = {};
14+
15+
/**
16+
* Fetch new data from the server
17+
* @param {Function} cb Called with state change and XMLHttpRequest
18+
*/
19+
let getNewData = (cb) => {
20+
const Http = new XMLHttpRequest();
21+
const url='http://192.168.0.38:8080/dump1090/data.json'; // dump1090 server
22+
Http.open("GET", url);
23+
Http.send();
24+
Http.onreadystatechange=(res) => {
25+
cb(res, Http)
26+
};
27+
}
28+
29+
/**
30+
* Takes server-returned plane object and converts to HTML info text
31+
* @param {*} plane
32+
*/
33+
let planeToInfoPanel = (plane) => {
34+
if (plane.seen > planeTimeout - 10) return 'Lost'; // 10 seconds before removal, flag as being lost
35+
let infoPanel = '{' + plane.lat.toFixed(4) + ',' + plane.lon.toFixed(4) + '}';
36+
if(plane.altitude){
37+
infoPanel += ' Alt: ' + plane.altitude
38+
}
39+
if(plane.validtrack) {
40+
infoPanel += ' Hdg: ' + plane.track;
41+
}
42+
if(plane.speed) {
43+
infoPanel += ' Spd: ' + plane.speed;
44+
}
45+
infoPanel += '<br>Last seen ' + plane.seen + 's ago';
46+
if(plane.flight) {
47+
infoPanel += '<br>'
48+
infoPanel += plane.flight.trim();
49+
infoPanel += ': <a href="https://uk.flightaware.com/live/flight/' + plane.flight.trim() + '" target="_blank">FlightAware</a>';
50+
}
51+
return infoPanel;
52+
}
53+
54+
/**
55+
* Call this once to trigger the map continuous update
56+
*/
57+
let updateMap = () => {
58+
/**
59+
* Remove and re-add plane markers and info
60+
* @param {*} activePlanes Our plane repository
61+
*/
62+
let drawMarkers = (activePlanes) => {
63+
// clear map markers
64+
markers.clearLayers();
65+
Object.values(activePlanes).forEach(plane => {
66+
if(plane.new) {
67+
console.log('New plane!', plane.hex, plane.flight, plane.validposition ? 'with position' : 'no position', plane.firstSeen);
68+
}
69+
if(plane.validposition) {
70+
let newMarker = new L.Marker([plane.lat, plane.lon], {
71+
icon: new L.DivIcon({
72+
className: 'infoPanel',
73+
html: '<img style="transform: rotate(' + plane.track + 'deg)" src="./media/plane_black.png"/>' +
74+
'<div class="infoText">' + planeToInfoPanel(plane) + '</div>'
75+
})
76+
});
77+
markers.addLayer(newMarker).addTo(planeMap);
78+
}
79+
});
80+
};
81+
/**
82+
* Used as callback for getNewData
83+
* Updates our in-mem plane repository including removing old planes
84+
* @param {*} res
85+
* @param {*} http
86+
*/
87+
let updatePlanes = (res, http) => {
88+
if(!http.responseText) return;
89+
let newPlanes = JSON.parse(http.responseText);
90+
// Add/update with returned planes
91+
newPlanes.forEach(plane => {
92+
if(!activePlanes[plane.hex]) {
93+
plane.new = true;
94+
plane.firstSeen = Date.now();
95+
} else {
96+
plane.new = false;
97+
plane.firstSeen = activePlanes[plane.hex].firstSeen;
98+
}
99+
// Add or override
100+
activePlanes[plane.hex] = plane;
101+
});
102+
// Remove out of date planes
103+
Object.values(newPlanes).forEach((plane, index) => {
104+
if(plane.seen > planeTimeout){
105+
delete activePlanes[plane.hex];
106+
}
107+
});
108+
drawMarkers(activePlanes);
109+
};
110+
111+
getNewData(updatePlanes);
112+
setInterval(getNewData.bind(this, updatePlanes), dataFetchBreakTime * 1000);
113+
};
114+
115+
updateMap();

media/plane_black.png

303 Bytes
Loading

readme.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# 1090WebClient
2+
3+
A web client for plane spotting
4+
5+
## Install
6+
1) `git clone https://github.com/Slord6/1090webclient.git`
7+
2) Update the url variable in `getNewData` in `map.js` to point at your data source
8+
3) Just host with you favourite web server - If you don't have one, I'm using [Fenix](https://fenixwebserver.com/).
9+
10+
## What is this?
11+
12+
A replacement client for [dump1090](https://github.com/MalcolmRobb/dump1090) .
13+
Super, super simple (plain js/css/html) dump1090 web client using [Leaflet](https://leafletjs.com/) for maps.
14+
Currently setup to use open street maps for map tiles but any leaflet-supported map tile service should work.
15+
16+
## How to use
17+
Once you're serving the website, just navigate to it in a web browser (only tested in Chrome, so that's your best bet) and then wait for planes to appear.
18+
Hover over a plane on the map for more info.
19+
20+
## Screenshot
21+
![Sample screenshot](https://i.imgur.com/qcztJHm.jpg)
22+
23+
## FAQ
24+
### No planes
25+
If you don't see any planes, check the console to see if your question is answered there.
26+
27+
### Change default location
28+
Edit the lat/lon + zoom values passed to `setView` on the first line of `map.js`
29+
30+
### Change data fetch frequency
31+
32+
## Licence
33+
See separate file (but its MIT)

style.css

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#planeMap {
2+
height: 100%;
3+
}
4+
5+
.infoText {
6+
padding: 4px;
7+
min-width: 150px;
8+
background-color: black;
9+
color: white;
10+
font-family: "Lucida Console", Monaco, monospace;
11+
opacity: 0;
12+
}
13+
14+
.infoText a {
15+
color: blanchedalmond;
16+
}
17+
18+
.infoPanel:hover .infoText, .infoText:hover {
19+
opacity: 1;
20+
}

0 commit comments

Comments
 (0)