signalk-polar-performance-plugin
Version:
A plugin that calculates performance information based on a (CSV) polar diagram.
250 lines (219 loc) • 5.88 kB
HTML
<html>
<script type='text/javascript' src="./Chart.min.js"></script>
<script type='text/javascript' src='/jquery/dist/jquery.min.js'></script>
<title>Polar performance</title>
<body style="background-color:#020202;">
<canvas id="myChart" style="width:100%;max-width:1200px"></canvas>
<script>
var polarSpeed, boatSpeed, TWA
var myChart, chartData
$.getJSON("/plugins/signalk-polar-performance-plugin/chartData", function(json) {
// Add actual values dots
json.datasets.unshift({
label: 'Polar Speed',
backgroundColor: 'rgba(0,255,0,0.7)',
borderColor: 'rgba(0,255,0,0.2)',
borderWidth: 1,
radius: 30,
type: 'bubble',
data: [
{
y: 0,
x: 0,
r: 10
}
]
},
{
label: 'Boat Speed',
backgroundColor: 'rgba(0,150,255,0.7)',
borderColor: 'rgba(0,150,255,0.2)',
borderWidth: 1,
radius: 30,
type: 'bubble',
data: [
{
y: 0,
x: 0,
r: 10
}
]
})
chartData = json
showChart(chartData)
})
function showChart (data) {
console.log(data)
myChart = new Chart("myChart", {
type: "scatter",
data: data,
options: {
legend: {
display: true,
labels: {
fontSize: 16,
fontColor: 'white'
}
},
spanGaps: true,
scales: {
x: {
type: 'linear',
ticks: {
color: 'white',
font: {
size: 14
}
}
},
y: {
type: 'linear',
ticks: {
color: 'white',
font: {
size: 14
}
}
},
xAxes: [{
scaleLabel: {
display: true,
labelString: 'True wind angle (TWA)',
fontColor: 'white',
fontSize: 16
},
ticks: {
display: true,
fontColor: 'white',
fontSize: 16,
},
gridLines: {
color: 'rgba(180,180,180,0.7)',
lineWidth: 1
}
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Target boat speed (POL SPD)',
fontColor: 'white',
fontSize: 14
},
ticks: {
display: true,
fontColor: 'white',
fontSize: 14,
},
gridLines: {
color: 'rgba(180,180,180,0.7)',
lineWidth: 1
}
}],
},
tooltips: {
enabled: true,
callbacks: {
label: function (tooltipItems, data) {
console.log("tooltipItems: " + JSON.stringify(tooltipItems))
console.log("data: " + data)
let label = tooltipItems.xLabel + "° " + tooltipItems.yLabel + " kts"
return label
}
},
backgroundColor: '#666',
titleFontSize: 18,
titleFontColor: '#0066ff',
bodyFontColor: '#ddd',
bodyFontSize: 18,
displayColors: false
}
}
})
var ctx = document.getElementById("myChart")
ctx.style.backgroundColor = 'rgba(0,0,0,0.8)'
ctx.style.fontColor = 'white'
}
function connect () {
console.log("connect()")
ws = new WebSocket((window.location.protocol === 'https:' ? 'wss' : 'ws') + "://" + window.location.host + "/signalk/v1/stream?subscribe=none");
ws.onopen = function() {
// Start listening for value updates
startListeners();
ws.onmessage = function(event) {
if (event.data.includes('signalk-server')) {
welcomeMessage = event.data;
console.log("Skipping welcome message: " + welcomeMessage)
} else {
handleData(JSON.parse(event.data));
}
}
ws.onclose = function() {
console.log("WebSocket closed")
setTimeout(connect, 500)
}
ws.onerror = function(err) {
console.log("WebSocket connection error: " + err.message + " - closing connection");
setTimeout(connect, 500)
}
}
}
window.addEventListener('focus', function () {
if (ws.readyState == 0) {
console.log("Restarting websocket")
connect()
}
})
function startListeners () {
var paths = [{'path': 'environment.wind.angleTrueWaterDamped'}, {'path': 'performance.polarSpeed'}, {'path': 'performance.boatSpeedDamped'}]
var subscriptionObject = {
"context": "vessels.self",
"policy" : "ideal",
"minPeriod": 2000,
"subscribe": paths
}
var subscriptionMessage = JSON.stringify(subscriptionObject);
console.log("subscriptionMessage: " + subscriptionMessage);
ws.send(subscriptionMessage);
}
function handleData (data) {
if (typeof data.updates[0].meta != 'undefined') {
return
}
var path = data.updates[0].values[0].path
var value = data.updates[0].values[0].value
if (path == 'performance.polarSpeed') {
polarSpeed = roundDec(msToKts(value), 1)
// console.log('polarSpeed set to %s', polarSpeed)
chartData.datasets[0].data[0].y = polarSpeed
} else if (path == 'environment.wind.angleTrueWaterDamped') {
TWA = roundDec(Math.abs(radToDeg(value)),1)
// console.log('TWA set to %s', TWA)
chartData.datasets[0].data[0].x = TWA
chartData.datasets[1].data[0].x = TWA
} else if (path == 'performance.boatSpeedDamped') {
boatSpeed = roundDec(msToKts(value),1)
// console.log('boatSpeed set to %s', boatSpeed)
chartData.datasets[1].data[0].y = boatSpeed
}
}
connect()
setInterval(updateChart, 300)
function updateChart () {
myChart.update()
}
function radToDeg(radians) {
return radians * 180 / Math.PI
}
function msToKts(ms) {
return ms * 1.94384
}
function roundDec (value, decimals) {
if (typeof value == 'undefined') {
return undefined
} else {
value = Number(value.toFixed(decimals))
return value
}
}
</script>