trap.js (6789B)
1 /* 2 trap { 3 id: int 4 name: str? 5 status: str 6 offline: bool 7 locationSearch: bool 8 latitude: float? 9 longitude: float? 10 accuracy: float? 11 satellites: int? 12 activated: bool 13 owner: str 14 battery: int 15 charging: bool 16 temperature: bool 17 lastStatus: str 18 ownedDate: str 19 } 20 */ 21 22 var map = L.map('trap-map'), 23 socket = io(); 24 25 let token = null, 26 remote = false, 27 traps = {}, 28 markers = []; 29 30 map.setView([52.283333, 5.666667], 7); 31 L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { 32 attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', 33 }).addTo(map); 34 35 socket.on('trap-change', function (trap) { 36 var clone, 37 append = false; 38 39 if (traps[trap.id]) { 40 Object.assign(traps[trap.id], trap); 41 42 clone = traps[trap.id].element; 43 } else { 44 traps[trap.id] = trap; 45 46 clone = document.getElementById('trap-template').content.cloneNode(true).querySelector('article'); 47 traps[trap.id].element = clone; 48 traps[trap.id].updating = false; 49 clone.id = `trap-${trap.id}`; 50 append = true; 51 } 52 53 if (!traps[trap.id].updating) { 54 var statusIcons = '', 55 statusString = '', 56 statusIcon, 57 batteryIcon, 58 tempIcon; 59 60 if (trap.offline) (statusIcon = 'moon'), (statusString += 'offline'); 61 else if (trap.activated) (statusIcon = 'circle-exclamation'), (statusString += 'geactiveerd'); 62 else (statusIcon = 'clock'), (statusString += 'wachtend'); 63 statusIcons += `<i class='fas fa-${statusIcon}'></i>`; 64 // clone.style.background = '#bdecb6'; 65 clone.style.background = '#ffffff'; 66 67 if (!trap.offline) { 68 if (trap.activated) { 69 clone.style.background = '#aec6cf'; 70 } 71 if (trap.charging) (batteryIcon = 'plug-circle-bolt'), (statusString += ', aan het opladen'); 72 else if (trap.battery == 0) batteryIcon = 'battery-empty'; 73 else if (trap.battery < 30) batteryIcon = 'battery-quarter'; 74 else if (trap.battery < 55) batteryIcon = 'battery-half'; 75 else if (trap.battery < 80) batteryIcon = 'battery-three-quarters'; 76 else if (trap.battery < 100) batteryIcon = 'battery-full'; 77 else (batteryIcon = 'plug-circle-xmark'), (statusString += ', problemen met batterij'); 78 statusIcons += `<i class='fas fa-${batteryIcon}'></i>`; 79 80 if (trap.temperature > 50) (tempIcon = 'temperature-high'), (statusString += ', oververhit'); 81 else if (trap.temperature < -10) (tempIcon = 'temperature-low'), (statusString += ', onderkoeld'); 82 if (tempIcon) statusIcons += `<i class='fas fa-${tempIcon}'></i>`; 83 84 if (trap.locationSearching) (statusIcons += '<i class="fas fa-satellite"></i>'), (statusString += ', zoekt naar locatie'); 85 } else { 86 clone.style.background = '#eeeeee'; 87 } 88 89 clone.querySelector('a.update').onclick = function () { 90 var nameSpan = clone.querySelector('span.name'), 91 input = nameSpan.querySelector('input'); 92 if (input) { 93 clone.querySelector('a.update').innerHTML = 'bewerken'; 94 traps[trap.id].updating = false; 95 socket.emit('name', { id: trap.id, name: input.value }); 96 } else { 97 nameSpan.innerHTML = `<input type="entry" value="${trap.name}" />`; 98 traps[trap.id].updating = true; 99 clone.querySelector('a.update').innerHTML = 'klaar'; 100 } 101 }; 102 clone.querySelector('a.delete').onclick = function () { 103 socket.emit('delete', { id: trap.id }); 104 clone.remove(); 105 delete traps[trap.id]; 106 }; 107 clone.querySelector('a.location').onclick = function () { 108 socket.emit('location-search', { id: trap.id, search: !trap.locationSearch }); 109 }; 110 111 clone.querySelector('span.location-button').innerHTML = trap.locationSearch ? 'locatie vastzetten' : 'locatie zoeken'; 112 clone.querySelector('span.status-icons').innerHTML = statusIcons; 113 clone.querySelector('span.status').innerHTML = statusString; 114 clone.querySelector('span.name').innerHTML = trap.name; 115 clone.querySelector('span.owner').innerHTML = trap.owner; 116 clone.querySelector('span.accuracy').innerHTML = trap.accuracy; 117 clone.querySelector('span.satellites').innerHTML = trap.satellites; 118 clone.querySelector('span.temperature').innerHTML = trap.temperature; 119 clone.querySelector('span.last-status').innerHTML = trap.lastStatus; 120 clone.querySelector('span.owned-date').innerHTML = trap.ownedDate; 121 if (trap.battery < 100) { 122 clone.querySelector('p.battery').style.display = 'inherit'; 123 clone.querySelector('span.battery').innerHTML = trap.battery; 124 } else { 125 clone.querySelector('p.battery').style.display = 'none'; 126 } 127 if (trap.locationSearch) { 128 clone.querySelector('p.accuracy').style.display = 'inherit'; 129 } else { 130 clone.querySelector('p.accuracy').style.display = 'none'; 131 } 132 } 133 134 if (append) document.getElementById('trap-container').appendChild(clone); 135 136 if (trap.accuracy) { 137 if (traps[trap.id].marker) { 138 traps[trap.id].marker.setLatLng([trap.latitude, trap.longitude]); 139 } else { 140 traps[trap.id].marker = L.marker([trap.latitude, trap.longitude]).addTo(map).bindPopup(trap.name); 141 map.fitBounds( 142 Object.values(traps) 143 .filter((x) => x.accuracy) 144 .map((x) => [x.latitude, x.longitude]) 145 ); 146 } 147 } else if (traps[trap.id].marker) { 148 traps[trap.id].marker.remove(); 149 traps[trap.id].marker = undefined; 150 } 151 }); 152 153 socket.on('trap-remove', function (trap) { 154 if (traps[trap.id].marker) traps[trap.id].marker.remove(); 155 traps[trap.id].element.remove(); 156 157 delete traps[trap.id]; 158 }); 159 160 socket.on('statistics', function ({ table, months }) { 161 var chart = new CanvasJS.Chart('trap-chart', { 162 data: [ 163 { 164 type: 'column', 165 dataPoints: [ 166 { label: 'Januari', y: months[0] }, 167 { label: 'Februari', y: months[1] }, 168 { label: 'Maart', y: months[2] }, 169 { label: 'April', y: months[3] }, 170 { label: 'Mei', y: months[4] }, 171 { label: 'Juni', y: months[5] }, 172 { label: 'Juli', y: months[6] }, 173 { label: 'Augustus', y: months[7] }, 174 { label: 'September', y: months[8] }, 175 { label: 'October', y: months[9] }, 176 { label: 'November', y: months[10] }, 177 { label: 'December', y: months[11] }, 178 ], 179 }, 180 ], 181 }); 182 chart.render(); 183 var tbl = document.getElementById('trap-table'); 184 tbl.innerHTML = 185 '<tr><th>Muizenval</th><th>Datum</th><th></th></tr>' + 186 table.map(([id, name, date]) => `<tr><td>${name}</td><td>${date}</td><td><a href="javascript:deleteStc(${id})">verwijderen</a></td></tr>`).join('\n'); 187 }); 188 189 function deleteStc(id) { 190 socket.emit('delete-statistic', id); 191 } 192 193 function websocket() { 194 let ws = new WebSocket('ws://localhost:1612/'); 195 ws.addEventListener('open', () => ws.send('token')); 196 ws.addEventListener('message', (evt) => (token = evt.data)); 197 ws.addEventListener('close', () => { 198 if (token) { 199 socket.emit('token', token); 200 remote = true; 201 } else { 202 remote = false; 203 } 204 }); 205 ws.addEventListener('error', () => { 206 token = null; 207 remote = false; 208 }); 209 } 210 211 setInterval(websocket, 10000); 212 213 websocket();