]> www.average.org Git - loctrkd.git/blob - webdemo/index.html
webdemo: implement sending cmds to the terminal
[loctrkd.git] / webdemo / index.html
1 <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
2 <head>
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">
6 </script>
7 <script src="https://www.openstreetmap.org/openlayers/OpenStreetMap.js">
8 </script>
9 <script type="text/javascript">
10         const urlParams = new URLSearchParams(window.location.search);
11         const qimei = urlParams.get("imei");
12
13         const wsproto = window.location.protocol === "https" ? "wss" : "ws";
14         const wshost = window.location.hostname ? window.location.hostname
15                                                 : "localhost";
16         const wsport = window.location.port ? window.location.port : 5049;
17         const limei = window.location.pathname.substring(1)
18
19         const imeis = new Set();
20         const locations = new Array();
21         const maxmarkers = 5;
22         const lineStyle = {
23                 strokeColor: '#0000ff',
24                 strokeOpacity: 0.5,
25                 strokeWidth: 5
26         };
27
28         var sts;
29         var ws;
30         var imei;
31         var imeilst;
32         var clear;
33         var subunsub;
34         var tstamp;
35         var map;
36         var line;
37         var markers;
38         var icon;
39
40         function init() {
41                 init_map();
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");
54                 if (qimei) {
55                         imeis.add(qimei);
56                 } else if (limei) {
57                         imeis.add(limei);
58                 }
59                 update_imeilst(imeis);
60                 change(imei)
61                 open_ws();
62         }
63
64         function init_map() {
65                 map = new OpenLayers.Map ("map", {
66                         controls:[
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,
75                         numZoomLevels: 19,
76                         units: 'm',
77                         projection: new OpenLayers.Projection(
78                                                 "EPSG:900913"),
79                         displayProjection: new OpenLayers.Projection(
80                                                 "EPSG:4326")
81                 });
82                 layerMapnik =
83                   new OpenLayers.Layer.OSM.Mapnik("Mapnik");
84                 map.addLayer(layerMapnik)
85                 layerTransportMap =
86                   new OpenLayers.Layer.OSM.TransportMap("TransportMap");
87                 map.addLayer(layerTransportMap)
88                 layerCycleMap =
89                   new OpenLayers.Layer.OSM.CycleMap("CycleMap");
90                 map.addLayer(layerCycleMap);
91                 line =
92                   new OpenLayers.Layer.Vector("Line Layer");
93                 map.addLayer(line);
94                 map.addControl(new
95                   OpenLayers.Control.DrawFeature(line,
96                                   OpenLayers.Handler.Path));
97                 markers =
98                   new OpenLayers.Layer.Markers("Markers");
99                 map.addLayer(markers);
100
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);
105
106                 var lonLat =
107                   new OpenLayers.LonLat(0, 0).transform(
108                     new OpenLayers.Projection("EPSG:4326"),
109                       map.getProjectionObject());
110                 map.setCenter(lonLat, 1);
111         }
112
113         function set_marker(msg) {
114                 if (locations.push(msg) > maxmarkers) {
115                         locations.shift();
116                 }
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++) {
121                         const p0 =
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());
127                         const p1 =
128                           new OpenLayers.Geometry.Point(
129                                 locations[i].longitude,
130                                 locations[i].latitude)
131                              .transform(new OpenLayers.Projection("EPSG:4326"),
132                                              map.getProjectionObject());
133                         const leg =
134                           new OpenLayers.Geometry.LineString([p0, p1]);
135                         const lineFeature =
136                           new OpenLayers.Feature.Vector(leg, null, lineStyle);
137                         line.addFeatures([lineFeature]);
138
139                 }
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);
147         }
148         function display_status(battery) {
149                 console.log("status " + battery);
150                 devstatus.innerHTML = "BAT: " + battery;
151         }
152         function display_cmdresult(result) {
153                 console.log("cmdresult " + result);
154                 devstatus.innerHTML = result;
155         }
156
157         function open_ws() {
158                 wsurl = new URL("ws://localhost/");
159                 wsurl.protocol = wsproto
160                 wsurl.hostname = wshost
161                 wsurl.port = wsport
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;
168         }
169         function ws_onopen(event) {
170                 console.log("ws opened " + event);
171                 sts.innerHTML = "online";
172                 imei.disabled = false;
173                 clear.disabled = false;
174                 change(imei);
175                 locations.splice(0);
176                 sendIMEI();
177         }
178         function ws_onmessage(event) {
179                 console.log("message " + event.data);
180                 msg = JSON.parse(event.data);
181                 if (msg.type === "location") {
182                         set_marker(msg);
183                         if (msg.battery_percentage) {
184                                 display_status(msg.battery_percentage);
185                         }
186                 } else if (msg.type === "status") {
187                         display_status(msg.battery);
188                 } else if (msg.type === "cmdresult") {
189                         display_cmdresult(msg.result);
190                 }
191
192         }
193         function ws_onerror(event) {
194                 console.log("error " + event);
195                 sts.innerHTML = "error: " + event;
196         }
197         function ws_onclose(event) {
198                 console.log("close " + event);
199                 sts.innerHTML = "offline";
200                 imei.disabled = true;
201                 disablebtns(true);
202                 clear.disabled = true;
203                 setTimeout(open_ws, 5000);
204         }
205
206         function sendIMEI() {
207                 const imstr = Array.from(imeis).join(",");
208                 document.title = imstr;
209                 var msg = {
210                         imei: Array.from(imeis),
211                         type: "subscribe",
212                         timestamp: Date.now(),
213                         backlog: maxmarkers
214                 };
215                 console.log("sending" + JSON.stringify(msg));
216                 ws.send(JSON.stringify(msg));
217         }
218
219         function sendCMD(cmd, imei, txt) {
220                 var msg = {
221                         imei: imei,
222                         type: cmd,
223                         timestamp: Date.now(),
224                         txt: txt
225                 };
226                 console.log("sending" + JSON.stringify(msg));
227                 ws.send(JSON.stringify(msg));
228         }
229
230         function handleKey(evt) {
231                 if (evt.keyCode === 13 || evt.keyCode === 14) {
232                         if (!imei.disabled) {
233                                 sendIMEI(false);
234                         }
235                 }
236         }
237
238         function change(obj) {
239                 if (obj.value) {
240                         disablebtns(false);
241                         if (imeis.has(obj.value)) {
242                                 subunsub.value = "-";
243                                 subunsub.title =
244                                 "Unsubscribe from notifications from "
245                                         + obj.value;
246                         } else {
247                                 subunsub.value = "+";
248                                 subunsub.title =
249                                 "Subscribe to notifications from "
250                                         + obj.value;
251                         }
252                 } else {
253                         disablebtns(true);
254                         subunsub.value = "o";
255                         subunsub.title = "";
256                 }
257         }
258
259         function erase(obj) {
260                 imei.value = "";
261                 change(imei);
262         }
263
264         function disablebtns(yesorno) {
265                 [subunsub, refresh, msgtxt, message,
266                  poweroff].forEach(function(obj) {
267                         obj.disabled = yesorno;
268                 })
269         }
270         function update_imeilst(imeis) {
271                 while (imeilst.firstChild) {
272                         imeilst.removeChild(imeilst.lastChild)
273                 }
274                 imeis.forEach(function(item) {
275                         var entry = document.createElement('option');
276                         entry.value = item;
277                         imeilst.appendChild(entry);
278                 })
279                 if (imeis.size == 1) {
280                         imei.value = imeis.values().next().value;
281                 } else {
282                         imei.value = "";
283                 }
284         }
285
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);
295                                 imei.value = "";
296                         }
297                         update_imeilst(imeis);
298                         change(imei);
299                         sendIMEI();
300                 } else {
301                         sendCMD(obj.id, imei.value, msgtxt.value);
302                         msgtxt.value = "";
303                 }
304         }
305 </script>
306
307 </head>
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"
313                  list="imeilst"
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"
329                  title="Send message"
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)" />
335                 <br />
336         </div>
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>
345         </div>
346 </body>
347 </html>