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>
|
<title>Trackme</title>
|
||||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
<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="static/style.css" crossorigin="">
|
||||||
<link rel="stylesheet" href="style.css" crossorigin=""/>
|
<link rel="stylesheet" href="static/leaflet/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="">
|
||||||
<script src="leaflet/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin="">
|
<link rel="stylesheet" href="static/bootstrap/bootstrap.min.css" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="">
|
||||||
</script>
|
<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="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: dark)" content="black">
|
||||||
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#0313fc"/>
|
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#0313fc">
|
||||||
<body>
|
<body>
|
||||||
<div id="dash">
|
<div id="dash">
|
||||||
<div id="map"></div>
|
<div id="map">
|
||||||
<button id="togglefollow">Unfollow</button>
|
</div>
|
||||||
</div>
|
<button id="togglefollow" class="btn btn-primary btn-lg btn-block">Unfollow tracker</button>
|
||||||
<script defer src="engine.js"></script>
|
</div>
|
||||||
</body>
|
<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>
|
</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 */
|
/* service worker */
|
||||||
|
const CACHE_NAME = "trackme-v1";
|
||||||
|
const urlsToCache = [
|
||||||
|
"/",
|
||||||
|
"/leaflet/leaflet.js",
|
||||||
|
"/engine.js",
|
||||||
|
"/style.css",
|
||||||
|
];
|
||||||
{
|
{
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
navigator.serviceWorker.register("/engine.js")
|
navigator.serviceWorker.register("/engine.js")
|
@ -8,4 +8,5 @@
|
|||||||
|
|
||||||
#dash {
|
#dash {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|