1 <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
3 <title>Location</title>
4 <!-- This uses reeeally old 2.13.1 from 2013, also part of Debian distro -->
5 <script src="http://www.openlayers.org/api/OpenLayers.js">
7 <script src="https://www.openstreetmap.org/openlayers/OpenStreetMap.js">
9 <script type="text/javascript">
10 const urlParams = new URLSearchParams(window.location.search);
11 const qimei = urlParams.get("imei");
13 const wsproto = window.location.protocol === "https" ? "wss" : "ws";
14 const wshost = window.location.hostname ? window.location.hostname
16 const wsport = window.location.port ? window.location.port : 5049;
17 const limei = window.location.pathname.substring(1)
19 const imeis = new Set();
20 const locations = new Array();
23 strokeColor: '#0000ff',
42 sts = document.getElementById("sts");
43 sts.innerHTML = "uninitialized";
44 imei = document.getElementById("imei");
45 imeilst = document.getElementById("imeilst");
46 clear = document.getElementById("clear");
47 subunsub = document.getElementById("subunsub");
48 refresh = document.getElementById("refresh");
49 msgtxt = document.getElementById("msgtxt");
50 message = document.getElementById("message");
51 poweroff = document.getElementById("poweroff");
52 devstatus = document.getElementById("devstatus");
53 tstamp = document.getElementById("tstamp");
59 update_imeilst(imeis);
65 map = new OpenLayers.Map ("map", {
67 new OpenLayers.Control.Navigation(),
68 new OpenLayers.Control.PanZoomBar(),
69 new OpenLayers.Control.LayerSwitcher(),
70 new OpenLayers.Control.Attribution()],
71 maxExtent: new OpenLayers.Bounds(
72 -20037508.34,-20037508.34,
73 20037508.34,20037508.34),
74 maxResolution: 156543.0399,
77 projection: new OpenLayers.Projection(
79 displayProjection: new OpenLayers.Projection(
83 new OpenLayers.Layer.OSM.Mapnik("Mapnik");
84 map.addLayer(layerMapnik)
86 new OpenLayers.Layer.OSM.TransportMap("TransportMap");
87 map.addLayer(layerTransportMap)
89 new OpenLayers.Layer.OSM.CycleMap("CycleMap");
90 map.addLayer(layerCycleMap);
92 new OpenLayers.Layer.Vector("Line Layer");
95 OpenLayers.Control.DrawFeature(line,
96 OpenLayers.Handler.Path));
98 new OpenLayers.Layer.Markers("Markers");
99 map.addLayer(markers);
101 var size = new OpenLayers.Size(21, 25);
102 var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
103 icon = new OpenLayers.Icon(
104 'https://www.openstreetmap.org/openlayers/img/marker.png',size,offset);
107 new OpenLayers.LonLat(0, 0).transform(
108 new OpenLayers.Projection("EPSG:4326"),
109 map.getProjectionObject());
110 map.setCenter(lonLat, 1);
113 function set_marker(msg) {
114 if (locations.push(msg) > maxmarkers) {
117 console.log("new marker list " + JSON.stringify(locations));
118 tstamp.innerHTML = msg.timestamp;
119 // Draw a line between backlog locations
120 for (var i = 1; i < locations.length; i++) {
122 new OpenLayers.Geometry.Point(
123 locations[i-1].longitude,
124 locations[i-1].latitude)
125 .transform(new OpenLayers.Projection("EPSG:4326"),
126 map.getProjectionObject());
128 new OpenLayers.Geometry.Point(
129 locations[i].longitude,
130 locations[i].latitude)
131 .transform(new OpenLayers.Projection("EPSG:4326"),
132 map.getProjectionObject());
134 new OpenLayers.Geometry.LineString([p0, p1]);
136 new OpenLayers.Feature.Vector(leg, null, lineStyle);
137 line.addFeatures([lineFeature]);
140 // Set marker at the reported (last) location
141 const lonLat = new OpenLayers.LonLat(+msg.longitude,
142 +msg.latitude).transform(
143 new OpenLayers.Projection("EPSG:4326"),
144 map.getProjectionObject());
145 markers.addMarker(new OpenLayers.Marker(lonLat, icon));
146 map.setCenter(lonLat, 14);
148 function display_status(battery) {
149 console.log("status " + battery);
150 devstatus.innerHTML = "BAT: " + battery;
152 function display_cmdresult(result) {
153 console.log("cmdresult " + result);
154 devstatus.innerHTML = result;
158 wsurl = new URL("ws://localhost/");
159 wsurl.protocol = wsproto
160 wsurl.hostname = wshost
162 console.log("wsurl is " + wsurl)
163 ws = new WebSocket(wsurl);
164 ws.onopen = ws_onopen;
165 ws.onmessage = ws_onmessage;
166 ws.onerror = ws_onerror;
167 ws.onclose = ws_onclose;
169 function ws_onopen(event) {
170 console.log("ws opened " + event);
171 sts.innerHTML = "online";
172 imei.disabled = false;
173 clear.disabled = false;
178 function ws_onmessage(event) {
179 console.log("message " + event.data);
180 msg = JSON.parse(event.data);
181 if (msg.type === "location") {
183 if (msg.battery_percentage) {
184 display_status(msg.battery_percentage);
186 } else if (msg.type === "status") {
187 display_status(msg.battery);
188 } else if (msg.type === "cmdresult") {
189 display_cmdresult(msg.result);
193 function ws_onerror(event) {
194 console.log("error " + event);
195 sts.innerHTML = "error: " + event;
197 function ws_onclose(event) {
198 console.log("close " + event);
199 sts.innerHTML = "offline";
200 imei.disabled = true;
202 clear.disabled = true;
203 setTimeout(open_ws, 5000);
206 function sendIMEI() {
207 const imstr = Array.from(imeis).join(",");
208 document.title = imstr;
210 imei: Array.from(imeis),
212 timestamp: Date.now(),
215 console.log("sending" + JSON.stringify(msg));
216 ws.send(JSON.stringify(msg));
219 function sendCMD(cmd, imei, txt) {
223 timestamp: Date.now(),
226 console.log("sending" + JSON.stringify(msg));
227 ws.send(JSON.stringify(msg));
230 function handleKey(evt) {
231 if (evt.keyCode === 13 || evt.keyCode === 14) {
232 if (!imei.disabled) {
238 function change(obj) {
241 if (imeis.has(obj.value)) {
242 subunsub.value = "-";
244 "Unsubscribe from notifications from "
247 subunsub.value = "+";
249 "Subscribe to notifications from "
254 subunsub.value = "o";
259 function erase(obj) {
264 function disablebtns(yesorno) {
265 [subunsub, refresh, msgtxt, message,
266 poweroff].forEach(function(obj) {
267 obj.disabled = yesorno;
270 function update_imeilst(imeis) {
271 while (imeilst.firstChild) {
272 imeilst.removeChild(imeilst.lastChild)
274 imeis.forEach(function(item) {
275 var entry = document.createElement('option');
277 imeilst.appendChild(entry);
279 if (imeis.size == 1) {
280 imei.value = imeis.values().next().value;
286 function buttonpress(obj) {
287 console.log("button value " + obj.value);
288 console.log("button id " + obj.id);
289 console.log("input value " + imei.value);
290 if (obj.id === "subunsub") {
291 if (obj.value === "+") {
292 imeis.add(imei.value);
293 } else if (obj.value === "-") {
294 imeis.delete(imei.value);
297 update_imeilst(imeis);
301 sendCMD(obj.id, imei.value, msgtxt.value);
308 <body onload="init();" style="height: 100%; margin: 0; display: flex;
309 flex-direction: column; font-size: 1.5vh;">
310 <div style="margin: 0;" id="hdr">
311 <input id="imei" type="text" name="imei"
312 size="16" maxlength="16" placeholder="Enter or click to choose"
314 oninput ="change(this)" onkeyup="handleKey(event)" />
315 <datalist id="imeilst"></datalist>
316 <input type="button" id="clear" name="clear" value="x"
317 title="Clear input (Click on empty input shows avaliable choices)"
318 onclick="erase(this)" />
319 <input type="button" id="subunsub" name="subunsub" value="+"
320 title="Unsubscribe from events from IMEI"
321 onclick="buttonpress(this)" />
322 <input type="button" id="refresh" name="refresh" value="Refresh"
323 title="Send request to refresh location"
324 onclick="buttonpress(this)" />
325 <input id="msgtxt" type="text" name="msgtxt"
326 size="80" maxlength="80" placeholder="Input message text"
327 onkeyup="handleKey(event)" />
328 <input type="button" id="message" name="message" value="Send"
330 onclick="buttonpress(this)" />
331 <input type="button" id="poweroff" name="poweroff" value="Off"
332 title="Send request to power off"
333 style="background: red;"
334 onclick="buttonpress(this)" />
337 <div style="flex-grow: 1;" id="map"></div>
338 <div style="display: flex; flex-direction: row; width: 100%;">
339 <div id="sts" style="flex: none;"></div>
340 | <div id="devstatus" style="flex: auto;"></div>
341 | <div id="tstamp" style="flex: auto;"></div>
342 | <div id="about" style="flex: none; font-size: 1.5vmin;">
343 <a href="http://www.average.org/loctrkd/">
344 http://www.average.org/loctrkd/</a></div>