// Temporary TCP and Serial data used to calculate vincenty distance between two coordinates in realtime. let tempTCPCoords = null; let tempSERIALCoords = null; window.addEventListener("load", function(evt) { let output = document.getElementById("output"); let checkBoxSmartphone = document.getElementById("checkbox1"); let checkBoxUblox = document.getElementById("checkbox2"); let ws; const wsOnCloseF = function (evt) { ws = null; print2("CLOSED"); let intervalId; intervalId = setInterval(() => { console.log("reconnect websocket...") if (ws !== null && ws.CONNECTING) { return } if (ws !== null && ws.OPEN) { clearInterval(intervalId) return } ws = new WebSocket("ws://localhost:3011/ws"); ws.onopen = wsOnOpenF ws.onclose = wsOnCloseF ws.onmessage = wsOnMessageF ws.onerror = wsOnErrorF }, 1000) } // function called every time a message is received by the server. const wsOnMessageF = function (evt) { let dat = JSON.parse(evt.data) // If message comes from TCP source call functions to add TCP data != 0 to the charts if ('SOURCE_TCP' in dat) { setIndicatorsTcp(dat.SOURCE_TCP) if(dat.SOURCE_TCP.Orientation[0] !== 0 && dat.SOURCE_TCP.Orientation[1] !== 0 && dat.SOURCE_TCP.Orientation[2] !== 0){ let heading = (dat.SOURCE_TCP.Orientation[2]+90)%360 renderTCP((dat.SOURCE_TCP.Orientation[0]*Math.PI/180),heading*Math.PI/180,-(dat.SOURCE_TCP.Orientation[1]*Math.PI/180)) } if(dat.SOURCE_TCP.Position[1] !== 0 && dat.SOURCE_TCP.Position[0] !== 0){ document.getElementById("TCPlong").innerHTML = "Smartphone long: " + dat.SOURCE_TCP.Position[1] document.getElementById("TCPlat").innerHTML = "Smartphone lat: " + dat.SOURCE_TCP.Position[0] updateMapTCP(dat.SOURCE_TCP.Position[1], dat.SOURCE_TCP.Position[0]) map.panTo([dat.SOURCE_TCP.Position[1], dat.SOURCE_TCP.Position[0]]) tempTCPCoords = dat.SOURCE_TCP } if(dat.SOURCE_TCP.Speed !== 0){ addSpeedTcp(dat.SOURCE_TCP.Speed); } if(dat.SOURCE_TCP.HeadDevice !== 0){ document.getElementById("compassTCP").innerHTML = " Heading Device: " + dat.SOURCE_TCP.HeadDevice.toFixed(2) + "°" } if(dat.SOURCE_TCP.HeadMotion !== 0) { document.getElementById("compassTCPMot").innerHTML = "Heading Motion: " + dat.SOURCE_TCP.HeadMotion.toFixed(2) + "°" } if(dat.SOURCE_TCP.HAcc !== 0 && dat.SOURCE_TCP.VAcc !== 0){ addTCPAccuracy(dat.SOURCE_TCP.HAcc, dat.SOURCE_TCP.VAcc) document.getElementById("tcpHAcc").innerHTML = "Phone HAcc: " + dat.SOURCE_TCP.HAcc.toFixed(2) + " m" document.getElementById("tcpVAcc").innerHTML = "Phone VAcc: " + dat.SOURCE_TCP.VAcc.toFixed(2) + " m" } } // If message comes from Serial source call functions to add serial data != 0 to the charts if ('SOURCE_SERIAL' in dat) { setIndicatorsSer(dat.SOURCE_SERIAL) if(dat.SOURCE_SERIAL.Orientation[0] !== 0 && dat.SOURCE_SERIAL.Orientation[2] !== 0){ renderSerial(dat.SOURCE_SERIAL.Orientation[0]*Math.PI/180,-dat.SOURCE_SERIAL.Orientation[2]*Math.PI/180,dat.SOURCE_SERIAL.Orientation[1]*Math.PI/180) } if(dat.SOURCE_SERIAL.Position[1] !== 0 && dat.SOURCE_SERIAL.Position[0] !== 0){ document.getElementById("SERIALlong").innerHTML = "Ublox long: " + dat.SOURCE_SERIAL.Position[1] document.getElementById("SERIALlat").innerHTML = "Ublox lat: " + dat.SOURCE_SERIAL.Position[0] updateMapSERIAL(dat.SOURCE_SERIAL.Position[1], dat.SOURCE_SERIAL.Position[0]) map.panTo([dat.SOURCE_SERIAL.Position[1], dat.SOURCE_SERIAL.Position[0]]) tempSERIALCoords = dat.SOURCE_SERIAL if (tempTCPCoords !== null) { // calculate distance between coordinates from phone and m8u let tempDist = distVincenty(tempTCPCoords.Position, tempSERIALCoords.Position) // calculate time difference between currently cached measurements from phone and m8u let timeDiff = Date.parse(tempTCPCoords.Timestamp) - Date.parse(tempSERIALCoords.Timestamp) // calculate error estimation: traveled distance in time difference let distError = Math.abs(dat.SOURCE_SERIAL.Speed / 1000 * timeDiff) // remove invalid negative values let distClean = Math.max(tempDist - distError, 0) // set to zero if error greater than diff as this is only an estimation addDistanceToBarChart(distClean) document.getElementById("distance").innerHTML = "Distance 2D: " + distClean.toFixed(3) + " m" if(distClean <= dat.SOURCE_SERIAL.HAcc){ document.getElementById("greenlamp").style.backgroundColor = 'rgba(0, 230, 64, 1)' document.getElementById("yellow").style.backgroundColor = 'rgb(157,117,25)' document.getElementById("redlamp").style.backgroundColor = 'rgba(139, 0, 0, 1)' } else if(distClean <= tempTCPCoords.HAcc){ document.getElementById("greenlamp").style.backgroundColor = 'rgba(0, 100, 0, 1)' document.getElementById("yellow").style.backgroundColor = 'rgb(255,199,66)' document.getElementById("redlamp").style.backgroundColor = 'rgba(139, 0, 0, 1)' } else{ document.getElementById("greenlamp").style.backgroundColor = 'rgba(0, 100, 0, 1)' document.getElementById("yellow").style.backgroundColor = 'rgb(157,117,25)' document.getElementById("redlamp").style.backgroundColor = 'rgb(255,14,14)' } } tempTCPCoords = null } if(dat.SOURCE_SERIAL.Speed !== 0){ addSpeedSerial(dat.SOURCE_SERIAL.Speed); } if(dat.SOURCE_SERIAL.HeadDevice !== 0){ document.getElementById("compassSERIAL").innerHTML = "Heading Device: " + dat.SOURCE_SERIAL.HeadDevice.toFixed(2) + "°" } if(dat.SOURCE_SERIAL.HeadMotion !== 0) { document.getElementById("compassSERIALMot").innerHTML = "Heading Motion: " + dat.SOURCE_SERIAL.HeadMotion.toFixed(2) + "°" } if(dat.SOURCE_SERIAL.HAcc !== 0 && dat.SOURCE_SERIAL.VAcc !== 0){ addSerialAccuracy(dat.SOURCE_SERIAL.HAcc, dat.SOURCE_SERIAL.VAcc) document.getElementById("serialHAcc").innerHTML = "Ublox HAcc: " + dat.SOURCE_SERIAL.HAcc.toFixed(3) + " m" document.getElementById("serialVAcc").innerHTML = "Ublox VAcc: " + dat.SOURCE_SERIAL.VAcc.toFixed(2) + " m" } } } const wsOnOpenF = function (evt) { print2("OPEN"); } const wsOnErrorF = function(evt) { console.log(evt) print2("ERROR: " + evt); } ws = new WebSocket("ws://localhost:3011/ws"); ws.onopen = wsOnOpenF ws.onclose = wsOnCloseF ws.onmessage = wsOnMessageF ws.onerror = wsOnErrorF const print2 = function(message) { let d = document.createElement("p"); d.innerText = message; oldNode = output.firstChild output.replaceChild(d, oldNode) }; // On open send HTTP request corresponding to the chosen Source/s document.getElementById("open").onclick = function(evt) { if(checkBoxSmartphone.checked && checkBoxUblox.checked){ fetch('http://localhost:3011/trackings?serial=true&tcp=true', { method: 'POST', body: 'some test data'}) .then(results => results.json()) .then(console.log); } else if(!checkBoxSmartphone.checked && checkBoxUblox.checked){ fetch('http://localhost:3011/trackings?serial=true&tcp=false', { method: 'POST', body: 'some test data'}) .then(results => results.json()) .then(console.log); } else if(checkBoxSmartphone.checked && !checkBoxUblox.checked){ fetch('http://localhost:3011/trackings?serial=false&tcp=true', { method: 'POST', body: 'some test data'}) .then(results => results.json()) .then(console.log); } else if(!checkBoxSmartphone.checked && !checkBoxUblox.checked){ fetch('http://localhost:3011/trackings?serial=false&tcp=false', { method: 'POST', body: 'some test data'}) .then(results => results.json()) .then(console.log); } document.getElementById("tracking state").innerHTML = "Tracking state: LIVE" checkBoxSmartphone.disabled = true; checkBoxUblox.disabled = true; return false; }; document.getElementById("close").onclick = function(evt) { if (!ws) { return false; } ws.close(); return false; }; //------------------------Buttons------------------------------ /* Provides every Button with the corresponding HTTP request if the websocket is open. */ document.getElementById("messungstarten").onclick = function(evt) { if (ws) { fetch('http://localhost:3011/trackings/', { method: 'PATCH', body: 'some data'}) .then(results => results.json()) .then(console.log); document.getElementById("tracking state").innerHTML = "Tracking state: RECORD" } return false; }; document.getElementById("messungbeenden").onclick = function(evt) { if (ws) { fetch('http://localhost:3011/trackings/', { method: 'PUT', body: 'some data'}) .then(results => results.json()) .then(console.log); document.getElementById("tracking state").innerHTML = "Tracking state: LIVE" } return false; }; document.getElementById("allesbeenden").onclick = function(evt) { if (ws) { fetch('http://localhost:3011/trackings/', { method: 'DELETE', body: 'some data'}) .then(results => results.json()) .then(console.log); checkBoxSmartphone.disabled = false; checkBoxUblox.disabled = false; document.getElementById("tracking state").innerHTML = "Tracking state: CLOSED" } return false; }; var trackings = null; document.getElementById("messungladen").onclick = function(evt) { fetch('http://localhost:3011/trackings/', { method: 'GET'}).then(results => { return results.json() }).then(r => { console.log(r) if (!'data' in r) { return } trackings = r.data let sel = document.getElementById("meas") r.data.sort((a,b) => new Date(b.TimeCreated).getTime() - new Date(a.TimeCreated).getTime()); r.data.forEach(tracking => { console.log(tracking) let option = document.createElement("option"); option.text = tracking.TimeCreated + " Size: " + tracking.Size sel.add(option) }) sel.disabled = false document.getElementById("replaystarten").disabled = false }) }; document.getElementById("replaystarten").onclick = function(evt) { emptyTCP.features[0].geometry.coordinates = [] emptySERIAL.features[0].geometry.coordinates = [] let sel = document.getElementById("meas") console.log(trackings[sel.selectedIndex].UUID) fetch(`http://localhost:3011/trackings/${trackings[sel.selectedIndex].UUID}?replay=true`, { method: 'GET'}).then(results => { return results.json() }).then(r => { console.log(r.data.Data) }) document.getElementById("tracking state").innerHTML = "Tracking state: REPLAY" } document.getElementById("fullReplay").onclick = function(evt) { window.open('http://localhost:3011/tracking') } });