chore: micodus_server rework #1
122
html/engine.js
@ -1,122 +0,0 @@
|
||||
// engine.js
|
||||
|
||||
const socket = new WebSocket("wss://trackme.ovh/ws");
|
||||
const arrows = ["↑", "↗", "→", "↘", "↓", "↙", "←", "↖"];
|
||||
const CACHE_NAME = "trackme-v1";
|
||||
const urlsToCache = [
|
||||
"/",
|
||||
"/leaflet/leaflet.js",
|
||||
"/engine.js",
|
||||
"/style.css",
|
||||
];
|
||||
const blueIconUrl = "marker-icon.png";
|
||||
const purpleIconUrl = "marker-icon-alt.png";
|
||||
|
||||
let follow = true;
|
||||
let userdata;
|
||||
|
||||
function userGPSsuccess(position) {
|
||||
const lat = position.coords.latitude;
|
||||
const lon = position.coords.longitude;
|
||||
trackerdata = [lat,lon];
|
||||
}
|
||||
|
||||
function userGPSerror(err) {
|
||||
trackerdata = [49,0];
|
||||
}
|
||||
|
||||
function getPosition(pos) {
|
||||
if (navigator.geolocation) {
|
||||
return new Promise((resolve, _reject) => {
|
||||
navigator.geolocation.getCurrentPosition(userGPSsuccess, userGPSerror);
|
||||
resolve("Position fetched");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function createLocation(map, point, coords, text, iconUrl) {
|
||||
let icon = new L.Icon.Default;
|
||||
icon.options.iconUrl = iconUrl;
|
||||
|
||||
point = L.marker(coords, {
|
||||
color: "red",
|
||||
fillColor: "#f03",
|
||||
fillOpacity: 0.5,
|
||||
radius: 50,
|
||||
icon: icon
|
||||
}).addTo(map).bindPopup(text);
|
||||
|
||||
point.getPopup().autoPan = false;
|
||||
point.openPopup();
|
||||
}
|
||||
|
||||
function createMap(coords) {
|
||||
let map = L.map("map", {
|
||||
center: coords,
|
||||
zoom: 15
|
||||
});
|
||||
L.tileLayer(`https://tile.openstreetmap.org/{z}/{x}/{y}.png`, {
|
||||
maxZoom: 19,
|
||||
attribution: `© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> / <a href="https://www.paulbsd.com">PaulBSD</a>`
|
||||
}).addTo(map);
|
||||
map.zoomControl.setPosition('bottomright');
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
function middle(trackercoords, usercoords) {
|
||||
let mid = [0, 0];
|
||||
for (let i in mid) {
|
||||
mid[i] = Math.min(trackercoords[i], usercoords[i]) + Math.abs(trackercoords[i] - usercoords[i]);
|
||||
}
|
||||
return mid;
|
||||
}
|
||||
|
||||
function update(map, trackerpoint, trackerdata) {
|
||||
const coords = [trackerdata.latitude, trackerdata.longitude];
|
||||
const speed = trackerdata.speed/10;
|
||||
const section = parseInt(trackerdata.direction/45 + 0.5) % 8;
|
||||
const text = `time: ${trackerdata.time}<br/>latitude: ${trackerdata.latitude}<br/>longitude: ${trackerdata.longitude}<br/>height: ${trackerdata.height}<br/>speed: ${speed}<br/>direction: ${arrows[section]} ${trackerdata.direction}°<br/>serial: ${trackerdata.serial}`;
|
||||
if (map) {
|
||||
if (follow) {
|
||||
map.setView(coords);
|
||||
map.flyTo(coords);
|
||||
}
|
||||
} else {
|
||||
map = createMap(coords);
|
||||
}
|
||||
if (trackerpoint) {
|
||||
trackerpoint.setLatLng(coords);
|
||||
trackerpoint.setPopupContent(text);
|
||||
} else {
|
||||
createLocation(map, trackerpoint, coords, text, blueIconUrl);
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
let map;
|
||||
let trackerpoint;
|
||||
let userpoint;
|
||||
let pos;
|
||||
|
||||
let togglefollow = document.querySelector("#togglefollow");
|
||||
togglefollow.addEventListener("click", function() {
|
||||
follow = !follow;
|
||||
if (follow) togglefollow.innerHTML = "Unfollow";
|
||||
else togglefollow.innerHTML = "Follow";
|
||||
});
|
||||
|
||||
socket.addEventListener("message", (event) => {
|
||||
const trackerdata = JSON.parse(event.data);
|
||||
update(map, trackerpoint, trackerdata);
|
||||
});
|
||||
|
||||
socket.addEventListener("open", (event) => {
|
||||
socket.send("ping");
|
||||
});
|
||||
|
||||
setInterval(getPosition, 1000, pos);
|
||||
setInterval(function () { socket.send("ping") }, 1000);
|
||||
}
|
||||
|
||||
main();
|
@ -1,18 +1,20 @@
|
||||
<html>
|
||||
<html lang="en">
|
||||
<title>Trackme</title>
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="leaflet/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
|
||||
<link rel="stylesheet" href="style.css" crossorigin=""/>
|
||||
<script src="leaflet/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin="">
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||||
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black"/>
|
||||
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#0313fc"/>
|
||||
<body>
|
||||
<div id="dash">
|
||||
<div id="map"></div>
|
||||
<button id="togglefollow">Unfollow</button>
|
||||
</div>
|
||||
<script defer src="engine.js"></script>
|
||||
</body>
|
||||
<link rel="stylesheet" href="static/style.css" crossorigin="">
|
||||
<link rel="stylesheet" href="static/leaflet/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="">
|
||||
<link rel="stylesheet" href="static/bootstrap/bootstrap.min.css" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="">
|
||||
<script src="static/leaflet/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black">
|
||||
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#0313fc">
|
||||
<body>
|
||||
<div id="dash">
|
||||
<div id="map">
|
||||
</div>
|
||||
<button id="togglefollow" class="btn btn-primary btn-lg btn-block">Unfollow tracker</button>
|
||||
</div>
|
||||
<script src="static/bootstrap/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
|
||||
<script defer src="static/engine.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
7
html/static/bootstrap/bootstrap.bundle.min.js
vendored
Normal file
6
html/static/bootstrap/bootstrap.min.css
vendored
Normal file
189
html/static/engine.js
Normal file
@ -0,0 +1,189 @@
|
||||
// engine.js
|
||||
|
||||
let socket = new WebSocket("wss://trackme.ovh/ws");
|
||||
const arrows = ["↑", "↗", "→", "↘", "↓", "↙", "←", "↖"];
|
||||
|
||||
class Position {
|
||||
constructor(type, iconUrl, iconRetinaUrl) {
|
||||
this.type = type;
|
||||
this.iconUrl = iconUrl;
|
||||
this.iconRetinaUrl = iconRetinaUrl;
|
||||
this.text = "";
|
||||
}
|
||||
|
||||
setData(obj) {
|
||||
this.data = obj;
|
||||
}
|
||||
|
||||
setDefaultData() {
|
||||
this.data = {latitude:49, longitude:0};
|
||||
}
|
||||
|
||||
static getMiddle(t, u) {
|
||||
const mid = {coords: [49, 0]};
|
||||
if (t.coords && u.coords) {
|
||||
for (const i in mid.coords) {
|
||||
mid.coords[i] = Math.min(t.coords[i], u.coords[i]) + (Math.abs(t.coords[i] - u.coords[i])/2);
|
||||
}
|
||||
} else mid.coords = t.coords;
|
||||
return mid.coords;
|
||||
}
|
||||
|
||||
createLocation() {
|
||||
const icon = new L.Icon.Default;
|
||||
icon.options.iconUrl = this.iconUrl;
|
||||
icon.options.iconRetinaUrl = this.iconRetinaUrl;
|
||||
|
||||
try {
|
||||
this.point = L.marker(this.coords, {
|
||||
color: "red",
|
||||
fillColor: "#f03",
|
||||
fillOpacity: 0.5,
|
||||
radius: 50,
|
||||
icon: icon
|
||||
}).addTo(map).bindPopup(this.text);
|
||||
|
||||
this.point.getPopup().autoPan = false;
|
||||
//this.point.openPopup();
|
||||
} catch (err) {
|
||||
console.log(`unable to create point (${err})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let map;
|
||||
let follow = true;
|
||||
const tracker = new Position("tracker", "marker-icon.png", "marker-icon-2x.png");
|
||||
const user = new Position("user", "marker-icon-alt.png", "marker-icon-2x-alt.png");
|
||||
|
||||
|
||||
function userGPSsuccess(pos) {
|
||||
user.data = {
|
||||
latitude: pos.coords.latitude,
|
||||
longitude: pos.coords.longitude,
|
||||
height: pos.coords.altitude,
|
||||
speed: pos.coords.speed,
|
||||
direction: pos.coords.heading,
|
||||
};
|
||||
user.coords = [pos.coords.latitude, pos.coords.longitude];
|
||||
}
|
||||
|
||||
function userGPSerror(err) {
|
||||
console.log(err);
|
||||
user.setDefaultData();
|
||||
}
|
||||
|
||||
function getPosition() {
|
||||
if (navigator.geolocation) {
|
||||
return new Promise((resolve, _reject) => {
|
||||
navigator.geolocation.getCurrentPosition(userGPSsuccess, userGPSerror);
|
||||
resolve("Position fetched");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function createMap(coords) {
|
||||
map = L.map("map", {
|
||||
center: coords,
|
||||
zoom: 10
|
||||
});
|
||||
L.tileLayer(`https://tile.openstreetmap.org/{z}/{x}/{y}.png`, {
|
||||
maxZoom: 19,
|
||||
attribution: `© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> / <a href="https://www.paulbsd.com">PaulBSD</a>`
|
||||
}).addTo(map);
|
||||
map.zoomControl.setPosition('bottomright');
|
||||
map.addEventListener("zoomlevelschange", (_event) => {
|
||||
update();
|
||||
});
|
||||
}
|
||||
|
||||
function update() {
|
||||
if (tracker.data) {
|
||||
tracker.coords = [tracker.data.latitude, tracker.data.longitude];
|
||||
tracker.data.speed = tracker.data.speed/10;
|
||||
tracker.section = parseInt(tracker.data.direction/45 + 0.5) % 8;
|
||||
tracker.text = `<b>Tracker</b><br/>time: ${tracker.data.time}<br/>latitude: ${tracker.data.latitude}<br/>longitude: ${tracker.data.longitude}<br/>height: ${tracker.data.height}<br/>speed: ${tracker.data.speed}<br/>direction: ${arrows[tracker.section]} ${tracker.data.direction}°<br/>serial: ${tracker.data.serial}`;
|
||||
}
|
||||
|
||||
//user.text = `<b>You</b><br/>latitude: ${user.data.latitude}<br/>longitude: ${user.data.longitude}<br/>height: ${user.data.height}<br/>speed: ${user.data.speed}<br/>direction: ${arrows[user.section]} ${user.data.direction}°`;
|
||||
if (user.data) {
|
||||
user.text = `<b>You</b><br/>latitude: ${user.data.latitude}<br/>longitude: ${user.data.longitude}`;
|
||||
}
|
||||
|
||||
if (tracker.data) {
|
||||
const center = [tracker.data.latitude, tracker.data.longitude];
|
||||
if (!map) {
|
||||
createMap(center);
|
||||
}
|
||||
}
|
||||
|
||||
if (map && follow) {
|
||||
const coords = Position.getMiddle(tracker, user);
|
||||
try {
|
||||
map.setView(coords);
|
||||
map.flyTo(coords);
|
||||
map.fitBounds([tracker.coords, user.coords]);
|
||||
} catch (e) {
|
||||
console.log(e, coords);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tracker.point && tracker.data) {
|
||||
tracker.createLocation();
|
||||
} else {
|
||||
if (tracker.coords) {
|
||||
tracker.point.setLatLng(tracker.coords);
|
||||
tracker.point.setPopupContent(tracker.text);
|
||||
}
|
||||
}
|
||||
|
||||
if (!user.point && user.data) {
|
||||
user.createLocation();
|
||||
} else {
|
||||
if (user.coords) {
|
||||
user.point.setLatLng(user.coords);
|
||||
user.point.setPopupContent(user.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ping() {
|
||||
try {
|
||||
socket.send("ping")
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
socket = new WebSocket("wss://trackme.ovh/ws");
|
||||
}
|
||||
}
|
||||
|
||||
function followButton() {
|
||||
if (follow) togglefollow.innerHTML = "Unfollow tracker";
|
||||
else togglefollow.innerHTML = "Follow tracker";
|
||||
}
|
||||
|
||||
function main() {
|
||||
const togglefollow = document.querySelector("#togglefollow");
|
||||
follow = JSON.parse(localStorage.getItem("follow"));
|
||||
followButton();
|
||||
|
||||
togglefollow.addEventListener("click", function() {
|
||||
follow = !follow;
|
||||
localStorage.setItem("follow", follow);
|
||||
followButton();
|
||||
});
|
||||
|
||||
socket.addEventListener("message", (event) => {
|
||||
tracker.data = JSON.parse(event.data);
|
||||
update();
|
||||
});
|
||||
|
||||
socket.addEventListener("open", (_event) => {
|
||||
ping();
|
||||
});
|
||||
|
||||
setInterval(getPosition, 1000);
|
||||
setInterval(ping, 1000);
|
||||
setInterval(update, 1000);
|
||||
}
|
||||
|
||||
main();
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 696 B After Width: | Height: | Size: 696 B |
BIN
html/static/leaflet/images/marker-icon-2x-alt.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
html/static/leaflet/images/marker-icon-alt.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 618 B After Width: | Height: | Size: 618 B |
@ -1,4 +1,11 @@
|
||||
/* service worker */
|
||||
const CACHE_NAME = "trackme-v1";
|
||||
const urlsToCache = [
|
||||
"/",
|
||||
"/leaflet/leaflet.js",
|
||||
"/engine.js",
|
||||
"/style.css",
|
||||
];
|
||||
{
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.register("/engine.js")
|
@ -8,4 +8,5 @@
|
||||
|
||||
#dash {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|