From 2c0a9893ff8502451a90844039fa06970de471d8 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 16 Aug 2025 14:55:56 +0200 Subject: [PATCH] updated frontend --- html/engine.js | 157 ++++++++++++++---------- html/index.html | 7 +- html/leaflet/images/marker-icon-alt.png | Bin 0 -> 5888 bytes html/{ => old}/ws.js | 0 html/service.js | 21 ++++ html/style.css | 8 ++ {html => ws}/const.lua | 0 {html => ws}/lastloc.lua | 0 {html => ws}/ws.lua | 2 - ws/ws2.lua | 90 ++++++++++++++ 10 files changed, 216 insertions(+), 69 deletions(-) create mode 100644 html/leaflet/images/marker-icon-alt.png rename html/{ => old}/ws.js (100%) create mode 100644 html/service.js rename {html => ws}/const.lua (100%) rename {html => ws}/lastloc.lua (100%) rename {html => ws}/ws.lua (98%) create mode 100644 ws/ws2.lua diff --git a/html/engine.js b/html/engine.js index 89a2c64..287e1c3 100644 --- a/html/engine.js +++ b/html/engine.js @@ -1,24 +1,57 @@ -//engine.js +// engine.js -let map; -let point; - -const arrows = ["↑", "↗", "→", "↘", "↓", "↙", "←", "↖"]; 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; -function create_location(coords, text) { point = L.marker(coords, { - color: 'red', - fillColor: '#f03', + color: "red", + fillColor: "#f03", fillOpacity: 0.5, - radius: 50 + radius: 50, + icon: icon }).addTo(map).bindPopup(text); - point.getPopup().autoPan=false; + + point.getPopup().autoPan = false; point.openPopup(); } -function create_map(coords) { - map = L.map('map', { +function createMap(coords) { + let map = L.map("map", { center: coords, zoom: 15 }); @@ -27,69 +60,63 @@ function create_map(coords) { attribution: `© OpenStreetMap / PaulBSD` }).addTo(map); map.zoomControl.setPosition('bottomright'); + + return map; } -function update(data) { - const coords = [data.latitude,data.longitude]; - const speed = data.speed/10; - let section = parseInt(data.direction/45 + 0.5); - section = section % 8; - const text = `time: ${data.time}
latitude: ${data.latitude}
longitude: ${data.longitude}
height: ${data.height}
speed: ${speed}
direction: ${arrows[section]} ${data.direction}°
serial: ${data.serial}`; +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}
latitude: ${trackerdata.latitude}
longitude: ${trackerdata.longitude}
height: ${trackerdata.height}
speed: ${speed}
direction: ${arrows[section]} ${trackerdata.direction}°
serial: ${trackerdata.serial}`; if (map) { - map.setView(coords); - map.flyTo(coords); + if (follow) { + map.setView(coords); + map.flyTo(coords); + } } else { - create_map(coords); + map = createMap(coords); } - if (point) { - point.setLatLng(coords); - point.setPopupContent(text); + if (trackerpoint) { + trackerpoint.setLatLng(coords); + trackerpoint.setPopupContent(text); } else { - create_location(coords, text); + createLocation(map, trackerpoint, coords, text, blueIconUrl); } } -function ping() { - socket.send("ping"); -} +function main() { + let map; + let trackerpoint; + let userpoint; + let pos; -socket.addEventListener("message", (event) => { - const data = JSON.parse(event.data); - update(data); -}); - -socket.addEventListener("open", (event) => { - console.log(event); - socket.send("ping"); -}); - -setInterval(ping, 1000) - -// service worker -if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/engine.js') - .then((reg) => { - console.log('Enregistrement réussi'); - }).catch((error) => { - console.log('Erreur : ' + error); + 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); } -const CACHE_NAME = 'my-site-cache-v1'; -const urlsToCache = [ - '/', - '/leaflet/leaflet.js', - '/engine.js', - '/style.css', -]; - -self.addEventListener('install', function(event) { - // Perform install steps - event.waitUntil( - caches.open(CACHE_NAME) - .then(function(cache) { - console.log('Opened cache'); - return cache.addAll(urlsToCache); - }) - ); -}); +main(); diff --git a/html/index.html b/html/index.html index 5971c8f..3b91750 100644 --- a/html/index.html +++ b/html/index.html @@ -9,7 +9,10 @@ -
- +
+
+ +
+ diff --git a/html/leaflet/images/marker-icon-alt.png b/html/leaflet/images/marker-icon-alt.png new file mode 100644 index 0000000000000000000000000000000000000000..46c7395facd85bf02c26cd4a01dcfdba1e754bae GIT binary patch literal 5888 zcmeHLXH-*J*S_=&WkhL;Ek^tRU(-l|L_kWALU2|Ok01Oy(niqVX2Ori5ZTNhBU)+88QWNFv3weQZq(my_3qpBFC{n^h@)QC- z04V+tvRVvkaEOT!S3fh5Y+-r~Jj)uPwP_^J zikk&JJGp~v{aj~Ee%h$VVECOMW?Rn6hX9}!FK~5bF5H@o_es0K&`; z8wcdoPAy9?#V=Yg($!Xdt8L}=KrErLKS}Kje_kPN<87`_LWz&&qqIe-92a)Jqh$(1 zvFBX$=xCH#k6(N5>ZF-Sk!GGkswk{t)kny+LV8{PdYsAf34Hq zByFhnHCDo9rx3v9<;(P-a>POm$Q84B7==&**Bt=ZuTn@rP6!V|vUx!Qkpt@Wm1`)Z zfa`$rAu(}Gi7PKyK#!90)<=1IbD}~x6fSC&qprPz3KIx<5QtO=Lq#&G!T~kSONH-M zW-JOh4S_-&P`*qS(p4?#V3?7nV;!JvX3gjdSDfx1dGSuutFhrriTo2i-1W!2J|02WZv*D#d`5%;&3U4 z=N7>eK}%;+a52$apEH9KNgrPEcR{R%Jx-*!p&mJlXf&@azv==P)7f49J z|3|DZVpEMwr!zAU*!?r_7wAv9PlI6;lS!qCIpM1C7&HfzYJMtL%n@*@)3+d*#K++X zcr+Iz*`bLzq79nDCfcI86bhTbA@a$5TW|&yLnMPh5r?Oug2^!gn1@FIZFodB1; zOhmK!L@t^{u;t=NWSpHH$e*U-a;U4tQXvR0r$7h>@vst6(DZ;xaH=zl;efKi;Qq0& zLP3ZRJ2;>`1fp=oKLg$ZA#Xhds?@~Wl1Kz1k%FV(i8dtC4DX+KQW;!{Do#8OLm*GP ztCocdCj$!$s_GObn6|^YP+g@w5E4th#o|y0lqw{o%JcIu6W&f-5CUl+#Dht3HY6&} zj*2IH;|Wxv9o2^NFPse(Hv=!`3iy%#7h1J>koF&zoGy^T^G8mbKJ2LVys!^XA09&m z(_0CNoZb{vknnFS5Ka>I=Pv-M%c_cK4PsX8% zToMP(Ch|CFJ6q5eZ;J!*AV~R=T_)y3a!|^14uW-rwSvoYS}Ua0^g>yGiIxZRRI30B zhQ`^U|6MTb$Aqz}p7AMTd+fhyVm}R-(PUu14>q`Y!Mzasxfy=cOx1S&i=U5c@n4() zrv5g`SLypru5WUEl>%P{{#ISz}-0*;?K6LYG-Y?pSTzk9+&)PoA24j2XRPF!l&Z>-&?p(@q%L zSeinq<@6SFM$y@#a%y&4TF|Acsi#kJ2aZ^*S{T*ioH1J68`+|*O@4mL3-?E?K@DHO zLO(+@XK6ahY8_HGFaPdi^vSZK#4)`N%Fv6-1Is9m6Q|QOoS$Zp(P+W!JIS3s~^~HiH*MOOT)KOh;fHex8%|e*M^tQ-L##HHaPj9 z-;FnorT-oV^)+w+r(3IrrQI}Y^wic_@s2Kii7!&+Y3k}b*KF0^z1nE?e5-X!0+UKh zf;8gy(~EWqy=pHx`lTccHCyjetYjot9d(cPms|DzHOJrLlH(6ID$;~Eg02mN!=eG_ zv#mGA%+5W%vH0BP(io$vE!&Ghvwr9v^4gMF^tkZBi2ZvPE+37|ZctJN=y|D#=6~%| zbe|t#-)gQv-+o6PdAhVC8Zp1Jq%LqzRjf{PwNCo>yP}pu4ay-6B6BMpk?*ee%a-7B zjk%S_5xXN6Zu?>LXwinO;)0Q_KkL1#?EWF7Eq<7`v%2y7gpH2I9%;JU<+N>@Tz#qU z_S2dfL}mW*w}$MofwG>xY8L;KXxIRzrOqCk4YVJ(2|@vq14{WT>JI(o=YDEkygaiM zhdfr({$#AT{s{|EoXo9QViBHsvhn*xT5}iY`tQvnQnilm7~9h7_jkra&lX^`3U~i% zyXT=CR>SP|Mk|eXpzmc5UjPs})@ zcExim%1KMz=tm8CN;gWKJYy7ie z7c<8#0ve(9L6HCYFihs=o$~lfo!@sqr|C=GI~LXH4bd)4Jh=z`lviSa%`i;;aj6;o zVz?10z$Cc>3)LF|qn(FVih+sHLW*e-9m?eR0IqK8r<#2A-<;=U9W7XaQrk{zse$q6 z$MHvfat($SvG&sL5+D6)?rFX4GKbhP*7bXj<#ME>%_B@5>hdya0N{kloEs9bYu=W= z>wP6RFIWJ_EEWq7CWaiOR?#DR5&~Jl2dVz~`x!k)0-)QM#_M7q1sG^AHc#u75ndZ$ zX8|_I)VgLi%282iwl)KBYA*<4w|Iv5nK*+ztqO-Z<;5wr7GcV6&lQmy{r~J~U%T{t z!npDhrp|ayQt+LPhO@ay)|y*vRD0#fZ}e8uoh|Zuhpg;8d{$fhas+M&RSWemhr z2T9W>q z--^XvhP6M95!vmh$b?PzkbU>So1TP~SEKrFbYa88&-M+l$08%TBi3CSByx7!1UBz! z9T2_7#Q#`q*)g^2hqS7l#FsklV3J6U9$@SUoSDxt)f38xvzq~WczEWOJp3>2H WZ>s5v(^CDj4KUn1X(cY3 { + console.log("Registration successful"); + }).catch((error) => { + console.log(`Registration error: ${error}`); + }); + } + + self.addEventListener("install", function(event) { + event.waitUntil( + caches.open(CACHE_NAME) + .then(function(cache) { + console.log("Opened cache"); + return cache.addAll(urlsToCache); + }) + ); + }); +} diff --git a/html/style.css b/html/style.css index f6e0274..d7f51a5 100644 --- a/html/style.css +++ b/html/style.css @@ -1,3 +1,11 @@ .leaflet-popup-content { /*font-size: 13pt;*/ } + +#map { + height: 95%; +} + +#dash { + height: 100%; +} diff --git a/html/const.lua b/ws/const.lua similarity index 100% rename from html/const.lua rename to ws/const.lua diff --git a/html/lastloc.lua b/ws/lastloc.lua similarity index 100% rename from html/lastloc.lua rename to ws/lastloc.lua diff --git a/html/ws.lua b/ws/ws.lua similarity index 98% rename from html/ws.lua rename to ws/ws.lua index e610912..39c729b 100644 --- a/html/ws.lua +++ b/ws/ws.lua @@ -24,7 +24,6 @@ function getdata() ["serial"] = row.serial, } end - -- db:close() return data end @@ -43,7 +42,6 @@ function geows() while true do local data = getdata() if data.time ~= last_time then - --do local locstr = json.encode(data) local bytes, err = wb:send_text(locstr) if not bytes then diff --git a/ws/ws2.lua b/ws/ws2.lua new file mode 100644 index 0000000..098d501 --- /dev/null +++ b/ws/ws2.lua @@ -0,0 +1,90 @@ +#!/usr/bin/lua + +package.path = package.path..";/home/paul/git/micodus_server/html/?.lua" + +local const = require("const") +local json = require("json") +local server = require("nginx.websocket.server") +local sqlite = require("lsqlite3") + +--ngx.shared.geo:set("last_time","") +local db = sqlite.open(const.dbfile, sqlite.OPEN_READONLY) + +function getdata() + local res, vm = db:nrows(const.query) + local data = {} + for row in res, vm do + data = { + ["time"] = row.time, + ["latitude"] = row.latitude, + ["longitude"] = row.longitude, + ["height"] = row.height, + ["speed"] = row.speed, + ["direction"] = row.direction, + ["serial"] = row.serial, + } + end + -- db:close() + return data +end + +function handle_ping(wb) + local data, typ, err = wb:recv_frame() + if data then + ngx.log(ndx.ERR,data) + end + coroutine.yield() +end + +function send_data(wb, last_time) + while true do + ngx.log(ndx.ERR,"test") + local data = getdata() + ngx.log(ndx.ERR,data) + if data.time ~= last_time then + local locstr = json.encode(data) + local bytes, err = wb:send_text(locstr) + ngx.log(ndx.ERR,bytes) + if not bytes then + ngx.log(ngx.ERR, "failed to send text: ", err) + return ngx.exit(444) + end + last_time = data.time + end + ngx.sleep(0.5) + coroutine.yield() + end +end + +function geows() + local locstr = nil + local wb, err = server:new { + timeout = 5000, + max_payload_len = 65535 + } + if not wb then + ngx.log(ngx.ERR, "failed to new websocket: ", err) + return ngx.exit(444) + end + local last_time = nil + + local h = coroutine.create(handle_ping, wb) + local s = coroutine.create(send_data, wb, last_time) + + local i=0 + while true do + ngx.log(ngx.ERR,i) + coroutine.resume(h,wb) + coroutine.resume(s,wb,last_time) + if not wb then + ngx.log(ngx.ERR, "failed to new websocket: ", err) + return ngx.exit(444) + end + i=i+1 + ngx.sleep(0.5) + end + + wb:send_close() +end + +geows()