UNPKG

e-inkdashboardextended

Version:

E-InkDashboardExtended is a signalK dashboard aimed at devices with e-ink screen. This application is based on the work of Vladimir Kalachikhin.

448 lines (432 loc) 13.9 kB
<!DOCTYPE html> <html> <head> <link href="common.css" rel="stylesheet" type="text/css" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <script src="internationalisation.js"></script> <!-- required at the beginning, to initialize variables --> <script src="fCommon.js"></script> <script src="options.js"></script> <!-- necessarily at the end so that the variables mentioned there are already there --> <title>e-inkDashboardExtended</title> </head> <body> <div id="leftTopBlock" onclick="bigBlock(this,'leftTopBlockBig');" style="display: none" ></div> <div id="rightTopBlock" onclick="bigBlock(this,'rightTopBlockBig');" style="display: none" ></div> <div id="leftBottomBlock" onclick="bigBlock(this,'leftBottomBlockBig');" style="display: none" ></div> <div id="rightBottomBlock" onclick="bigBlock(this,'rightBottomBlockBig');" style="display: none" ></div> <div id="compass"> <div id="center_icon"> <svg xml:space="default" version="1.1" viewBox="0 0 250 250" xmlns="http://www.w3.org/2000/svg" > <path fill="none" stroke="black" stroke-width="10px" d="M70 125 L 70 245 180 245 180 125 Q 180 65 125 10 70 70 70 125" /> </svg> </div> <div id="windSVGimage_container"> <svg xml:space="default" version="1.1" viewBox="0 0 100 300" xmlns="http://www.w3.org/2000/svg" id="windSVGimage" > <line fill="none" stroke="black" stroke-width="10px" x1="50" y1="50.5" x2="50" y2="130" ></line> <line fill="none" stroke="black" stroke-width="10px" x1="46.8" y1="50" x2="70" y2="70" ></line> <line fill="none" stroke="black" stroke-width="10px" x1="53.2" y1="50" x2="30" y2="70" ></line> </svg> </div> <div id="max_upwind_angle"> <svg id="max_upwind_angle_streak_l" xml:space="default" version="1.1" viewBox="0 0 4 300" xmlns="http://www.w3.org/2000/svg" > <line fill="none" stroke="black" stroke-width="7px" x1="0" y1="50" x2="0" y2="110" ></line> </svg> <svg id="max_upwind_angle_streak_r" xml:space="default" version="1.1" viewBox="0 0 4 300" xmlns="http://www.w3.org/2000/svg" > <line fill="none" stroke="black" stroke-width="7px" x1="0" y1="50" x2="0" y2="110" ></line> </svg> <svg id="max_downwind_angle_streak_l" xml:space="default" version="1.1" viewBox="0 0 4 300" xmlns="http://www.w3.org/2000/svg" > <line fill="none" stroke="black" stroke-width="7px" x1="0" y1="50" x2="0" y2="110" ></line> </svg> <svg id="max_downwind_angle_streak_r" xml:space="default" version="1.1" viewBox="0 0 4 300" xmlns="http://www.w3.org/2000/svg" > <line fill="none" stroke="black" stroke-width="7px" x1="0" y1="50" x2="0" y2="110" ></line> </svg> </div> <div id="center_marc"> <svg id="center_marc_streak" xml:space="default" version="1.1" viewBox="0 0 4 300" xmlns="http://www.w3.org/2000/svg" > <line fill="none" stroke="black" stroke-width="3px" x1="0" y1="10" x2="0" y2="110" ></line> <line fill="none" stroke="black" stroke-width="3px" x1="0" y1="190" x2="0" y2="290" ></line> </svg> <svg id="center_marc_static" xml:space="default" version="1.1" viewBox="0 0 4 300" xmlns="http://www.w3.org/2000/svg" > <line fill="none" stroke="black" stroke-width="7px" x1="0" y1="0" x2="0" y2="10" ></line> </svg> <div class="compass-card" id="compassCard"> <div class="compass-face"> <div class="charN"> <div class="compas-face-scale">0</div> N </div> <div class="charNNE"> <div class="compas-face-scale">22.5</div> NNE<br />| </div> <div class="charNE"> <div class="compas-face-scale">45</div> NE </div> <div class="charENE"> <div class="compas-face-scale">67.5</div> ENE<br />| </div> <div class="charE"> <div class="compas-face-scale">90</div> E </div> <div class="charESE"> <div class="compas-face-scale">112.5</div> ESE<br />| </div> <div class="charSE"> <div class="compas-face-scale">135</div> SE </div> <div class="charSSE"> <div class="compas-face-scale">157.5</div> SSE<br />| </div> <div class="charS"> <div class="compas-face-scale">180</div> S </div> <div class="charSSW"> <div class="compas-face-scale">202.5</div> SSW<br />| </div> <div class="charSW"> <div class="compas-face-scale">225</div> SW </div> <div class="charWSW"> <div class="compas-face-scale">247.5</div> WSW<br />| </div> <div class="charW"> <div class="compas-face-scale">270</div> W </div> <div class="charWNW"> <div class="compas-face-scale">292.5</div> WNW<br />| </div> <div class="charNW"> <div class="compas-face-scale">315</div> NW </div> <div class="charNNW"> <div class="compas-face-scale">337.5</div> NNW<br />| </div> </div> <div id="nextPointDirection" style="display: none"> <svg version="1.1" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg" > <polygon fill="black" stroke="black" points="1,1 5,9 9,1" /> </svg> </div> </div> </div> </div> <script> //compassCard.style.transform = 'rotate(30deg)'; var tpv = {}; var socket; var wangle_smoothed = -1; // Variables with signature strings are defined in internationalisation.js // Variables - options are defined in options.js // Final initialization var instanceSelf = getCookie("e-inkDashboardExtendedInstance"); // The identifier of the instance of the program if (!instanceSelf) { instanceSelf = generateUUID(); let expires = new Date(); expires.setTime(expires.getTime() + 24 * 60 * 60 * 1000); // It will decay in a day document.cookie = "e-inkDashboardExtendedInstance=" + instanceSelf + "; expires=" + expires + "; path=/; SameSite=Lax;"; } if (displayData.wangle && displayData.wangle.trueWind) { // If the wind is true compassCard.appendChild(windSVGimage); // Repair the wind symbol into the cartoon } // Go const uri = `ws://${document.location.host}/signalk/v1/stream?subscribe=none`; // We will subscribe separately doWebsocket(uri); //We launch the listening of the socket and process the resulting // Then the definition of functions function doWebsocket(uri) { socket = new WebSocket(uri); socket.onopen = websocketOnOpen; socket.onmessage = websocketOnMessage; socket.onclose = websocketOnClose; socket.onerror = websocketOnError; } // end function doWebsocket function websocketOnOpen(event) { /**/ // We form a subscription let signalKsubscribe = { context: "vessels.self", subscribe: [], }; for (let tpvName in displayData) { // displayData is in options.js signalKsubscribe.subscribe.push({ path: displayData[tpvName].signalkPath, format: "delta", policy: "instant", minPeriod: displayData[tpvName].maxRefreshInterval, }); } event.target.send(JSON.stringify(signalKsubscribe)); // подписываемся console.log("Winsocket open: Connection establish with " + uri); displayON(); display(); } // end function websocketOnOpen function websocketOnMessage(event) { // We get the initial data let SKdata; try { SKdata = JSON.parse(event.data); // But just a line is a correct json, and there will be no mistakes if the server has returned not json if (!SKdata) throw Error("inbound empty"); if (typeof SKdata !== "object") throw Error("inbound not a object: " + SKdata); } catch (error) { console.log("Parsing inbound data error: ", error.message); tpv = {}; display(); return; } if (SKdata.roles) { // greeting return; } // We take the necessary data let changedTPV = []; // The list of tpv keys, the values of which received changes, to update them in the interface let checksTPV = []; // TPV key list, for which Setinterval control of freshness is launched for (let props of SKdata.updates) { if (!props.values) continue; // I do not know when and why suddenly it may not be.But - it does not happen for (let prop of props.values) { bytpvName: for (let tpvName in displayData) { // displayData is in options.js if (prop.path != displayData[tpvName].signalkPath) continue; // Check for freshness if (!tpv[tpvName]) { tpv[tpvName] = {}; // We start cleaning data from outdated checksTPV[tpvName] = window.setInterval( chkTPV, displayData[tpvName].fresh - 1, tpvName, checksTPV ); } // Leading to normal dimensions if (prop.value !== null && displayData[tpvName].multiplicator) tmp = prop.value * displayData[tpvName].multiplicator; else tmp = prop.value; // Prevent tiny correction of the rotating components -> reduce frame refresh if ( (tpvName == "heading" || tpvName == "track" || tpvName == "wangle") && tpv[tpvName].value > 0 ) { if (Math.abs(tpv[tpvName].value - tmp) > 1.0) { tpv[tpvName].value = tmp; } } else { tpv[tpvName].value = tmp; } if (tpvName == "wangle") { if (wangle_smoothed < 0) { wangle_smoothed = tpv[tpvName].value; } else { wangle_smoothed = 0.3 * tpv[tpvName].value + 0.7 * wangle_smoothed; tpv[tpvName].value = wangle_smoothed; } } tpv[tpvName].timestamp = Date.parse(props.timestamp); changedTPV.push(tpvName); } } } changedTPV = Array.from(new Set(changedTPV)); // unique array display(changedTPV); // Actually drawing data } // end function websocketOnMessage function websocketOnClose(event) { /**/ if (event.wasClean) { console.log( `Websocket closed cleary with cide ${event.code} by reason: ${event.reason}` ); } else { // The server killed the process or the network is not available.Usually in this case Event.code 1006 console.log( `Websocket closed: connection broken with code ${event.code} by reason ${event.reason}` ); window.setTimeout(doWebsocket, 5000, uri); // restart the socket after 5 seconds } tpv = {}; displayOFF(); } // end function websocketOnClose function websocketOnError(error) { /**/ console.log(`Websocket error: ${error.message}`); display(); // Perhaps removing outdated data will support the correct display } // end function websocketOnError </script> </body> </html>