signalk-racer 0.9.13 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/ReleaseNotes.md +6 -0
- package/index.js +37 -36
- package/package.json +1 -1
- package/racer-kip.png +0 -0
- package/kip-freeboard-screenshot.png +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Signal K Racing Plugin
|
|
2
2
|
|
|
3
|
-
This plugin adds sail racing
|
|
3
|
+
This plugin adds sail racing relevant data to a Signal K server. It focuses on real-time information useful during the start of a race, such as:
|
|
4
4
|
+ A server side race timer that can be displayed on multiple screens and be finely adjusted
|
|
5
5
|
+ A mechanism to set and adjust the start line using waypoints and REST commands
|
|
6
6
|
+ Calculation of the distance to the line.
|
|
@@ -26,9 +26,10 @@ This plugin calculates and publishes the following Signal K paths:
|
|
|
26
26
|
| `navigation.racing.`<br/>`timeToStart` | Period of time until the race start | `s` | Y |
|
|
27
27
|
| `navigation.racing.`<br/>`startTime` | The start time as an ISO timestamp | `rfc3339` | |
|
|
28
28
|
|
|
29
|
-
These values can be displayed in KIP widgets, Freeboard-SK, or other Signal K clients.
|
|
29
|
+
These values can be displayed in KIP widgets, Freeboard-SK, or other Signal K clients.
|
|
30
|
+
There are dedicated widgets for the start timer and line adjustment since 3.5.0 of KIP
|
|
30
31
|
|
|
31
|
-

|
|
32
33
|
|
|
33
34
|
There is also a webapp to adjust the line and timer.
|
|
34
35
|
|
|
@@ -95,7 +96,7 @@ If `navigation.headingTrue` is not available, then `navigation.courseOverGroundT
|
|
|
95
96
|
|
|
96
97
|
## 🌐 API Access
|
|
97
98
|
|
|
98
|
-
This plugin uses WebSocket-based PUT requests to Signal K model paths.
|
|
99
|
+
This plugin uses the following WebSocket-based PUT requests to Signal K model paths.
|
|
99
100
|
|
|
100
101
|
### `navigation.racing.setStartLine`
|
|
101
102
|
|
|
@@ -133,13 +134,15 @@ Used to **start**, **sync**, **reset**, or **set a fixed start time**.
|
|
|
133
134
|
---
|
|
134
135
|
|
|
135
136
|
## 🧩 KIP Widgets
|
|
136
|
-
KIP components for `racer-timer` and `racer-line` have been developed and
|
|
137
|
+
KIP components for `racer-timer` and `racer-line` have been developed and are available from release 3.5.0 of KIP.
|
|
137
138
|
|
|
138
139
|
## 🔄 Dependencies
|
|
139
140
|
|
|
140
141
|
### Plugins
|
|
142
|
+
- [KIP >= 3.5.0](https://github.com/mxtommy/Kip) for graphic widget support
|
|
143
|
+
- [FreeboardSK](https://github.com/SignalK/freeboard-sk#readme) for graphic display of the start line
|
|
141
144
|
- [resources-provider](https://www.npmjs.com/package/@signalk/resources-provider) plugin with waypoints enabled
|
|
142
|
-
- [course-provider](https://www.npmjs.com/package/@signalk/course-provider) plugin
|
|
145
|
+
- [course-provider](https://www.npmjs.com/package/@signalk/course-provider) plugin to enable the next leg calculations
|
|
143
146
|
|
|
144
147
|
### Libraries
|
|
145
148
|
- `geolib`: for distance and bearing calculations.
|
|
@@ -151,7 +154,6 @@ KIP components for `racer-timer` and `racer-line` have been developed and will b
|
|
|
151
154
|
- Add calculations for:
|
|
152
155
|
- **Time to line** (using STW and heading or polar speeds)
|
|
153
156
|
- **Laylines** and distance/time to them
|
|
154
|
-
- Better integration with **Freeboard-SK** and **KIP** dashboards
|
|
155
157
|
|
|
156
158
|
---
|
|
157
159
|
## 📬 Feedback
|
package/ReleaseNotes.md
CHANGED
package/index.js
CHANGED
|
@@ -18,12 +18,12 @@ module.exports = (app) => {
|
|
|
18
18
|
updateStartLineWaypoint: {
|
|
19
19
|
type: 'boolean',
|
|
20
20
|
title: 'Update the start line waypoints if the startLine is updated',
|
|
21
|
-
default:
|
|
21
|
+
default: true
|
|
22
22
|
},
|
|
23
23
|
createStartLineWaypoint: {
|
|
24
24
|
type: 'boolean',
|
|
25
25
|
title: 'Create the start line waypoints if the startLine is updated and the waypoint does not exist',
|
|
26
|
-
default:
|
|
26
|
+
default: true
|
|
27
27
|
},
|
|
28
28
|
period: {
|
|
29
29
|
type: 'number',
|
|
@@ -105,7 +105,7 @@ module.exports = (app) => {
|
|
|
105
105
|
]
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
-
// send multiple deltas, each in the form of { path, value
|
|
108
|
+
// send multiple deltas, each in the form of { path, value }
|
|
109
109
|
function sendDeltas(updatesArray) {
|
|
110
110
|
const timestamp = new Date().toISOString();
|
|
111
111
|
|
|
@@ -199,14 +199,12 @@ module.exports = (app) => {
|
|
|
199
199
|
app.debug(`putStartLineEnd: ${end} ${JSON.stringify(position)}`);
|
|
200
200
|
|
|
201
201
|
try {
|
|
202
|
-
if (!end || !position || typeof position.latitude !== 'number' || typeof position.longitude !== 'number')
|
|
202
|
+
if (!end || !position || typeof position.latitude !== 'number' || typeof position.longitude !== 'number')
|
|
203
203
|
return complete(callback, 400, 'Failed to put start line end: !end || !position');
|
|
204
|
-
}
|
|
205
204
|
|
|
206
205
|
end = end.toLowerCase();
|
|
207
|
-
if (end !== 'port' && end !== 'stb')
|
|
206
|
+
if (end !== 'port' && end !== 'stb')
|
|
208
207
|
return complete(callback, 400, 'Failed to put start line end: unknown end');
|
|
209
|
-
}
|
|
210
208
|
|
|
211
209
|
let startLine = state.startLine;
|
|
212
210
|
if (startLine) {
|
|
@@ -427,9 +425,8 @@ module.exports = (app) => {
|
|
|
427
425
|
}
|
|
428
426
|
|
|
429
427
|
case 'sync': {
|
|
430
|
-
if (!state.timerRunning || state.timeToStart == null)
|
|
428
|
+
if (!state.timerRunning || state.timeToStart == null)
|
|
431
429
|
return complete(callback, 500, 'sync timer: !running');
|
|
432
|
-
}
|
|
433
430
|
|
|
434
431
|
const rounded = Math.round(state.timeToStart / 60) * 60;
|
|
435
432
|
state.timeToStart = rounded;
|
|
@@ -465,7 +462,7 @@ module.exports = (app) => {
|
|
|
465
462
|
{path: 'navigation.racing.timeToStart', value: 0},
|
|
466
463
|
{path: 'navigation.racing.startTime', value: null}
|
|
467
464
|
]);
|
|
468
|
-
return complete(callback, 200, 'set timer:
|
|
465
|
+
return complete(callback, 200, 'set timer: Ignored negative start time');
|
|
469
466
|
}
|
|
470
467
|
|
|
471
468
|
state.timerRunning = true;
|
|
@@ -483,15 +480,16 @@ module.exports = (app) => {
|
|
|
483
480
|
|
|
484
481
|
case 'adjust': {
|
|
485
482
|
const delta = Number(args.delta);
|
|
486
|
-
if (isNaN(delta)
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
483
|
+
if (isNaN(delta))
|
|
484
|
+
return complete(callback, 400, 'adjust timer: Cannot adjust invalid delta');
|
|
485
|
+
|
|
486
|
+
if (state.timeToStart == null)
|
|
487
|
+
return complete(callback, 400, 'adjust timer: Cannot adjust start time');
|
|
490
488
|
|
|
491
489
|
const nextTimeToStart = state.timeToStart + delta;
|
|
492
|
-
if (nextTimeToStart <=
|
|
493
|
-
return;
|
|
494
|
-
|
|
490
|
+
if (nextTimeToStart <= 0)
|
|
491
|
+
return complete(callback, 200, 'adjust timer: Ignored negative start time');
|
|
492
|
+
|
|
495
493
|
state.timeToStart = nextTimeToStart;
|
|
496
494
|
|
|
497
495
|
if (state.timerRunning) {
|
|
@@ -518,8 +516,8 @@ module.exports = (app) => {
|
|
|
518
516
|
}
|
|
519
517
|
}
|
|
520
518
|
} catch (err) {
|
|
521
|
-
app.debug('startTimerCommand:',
|
|
522
|
-
return complete(callback, 500, 'Failed to command timer: ' +
|
|
519
|
+
app.debug('startTimerCommand:', err);
|
|
520
|
+
return complete(callback, 500, 'Failed to command timer: ' + err.message);
|
|
523
521
|
}
|
|
524
522
|
}
|
|
525
523
|
|
|
@@ -659,6 +657,7 @@ module.exports = (app) => {
|
|
|
659
657
|
state.distanceToLine = null;
|
|
660
658
|
sendDeltas([
|
|
661
659
|
{path: 'navigation.racing.distanceStartline', value: null},
|
|
660
|
+
{path: 'navigation.racing.startLineBias', value: null},
|
|
662
661
|
]);
|
|
663
662
|
}
|
|
664
663
|
}
|
|
@@ -684,7 +683,7 @@ module.exports = (app) => {
|
|
|
684
683
|
const startLine = state.startLine;
|
|
685
684
|
if (startLine && isNearLineInRoute()) {
|
|
686
685
|
app.debug(`processWind ${twd} to ${JSON.stringify(startLine)}`);
|
|
687
|
-
bias = - startLine.length * Math.cos(toRadians(startLine.bearing) -
|
|
686
|
+
bias = - startLine.length * Math.cos(toRadians(startLine.bearing) - twd);
|
|
688
687
|
}
|
|
689
688
|
|
|
690
689
|
sendDeltas([
|
|
@@ -958,23 +957,25 @@ module.exports = (app) => {
|
|
|
958
957
|
(delta) => {
|
|
959
958
|
app.debug('DELTAS START LINE ENDS ' + JSON.stringify(delta));
|
|
960
959
|
delta.updates.forEach((u) => {
|
|
961
|
-
u.values
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
960
|
+
if (u.values) {
|
|
961
|
+
u.values.forEach((v) => {
|
|
962
|
+
app.debug(`DELTA START LINE END from ${u.source.label}: ${v.path} = ${JSON.stringify(v.value)}`);
|
|
963
|
+
if (u.source && u.source.label && u.source.label !== 'signalk-racer') {
|
|
964
|
+
switch (v.path) {
|
|
965
|
+
case 'navigation.racing.startLinePort' :
|
|
966
|
+
putStartLineEnd('port', v.value, ignored => {
|
|
967
|
+
}, false).then(ignored => {
|
|
968
|
+
});
|
|
969
|
+
break;
|
|
970
|
+
case 'navigation.racing.startLineStb' :
|
|
971
|
+
putStartLineEnd('port', v.value, ignored => {
|
|
972
|
+
}, false).then(ignored => {
|
|
973
|
+
});
|
|
974
|
+
break;
|
|
975
|
+
}
|
|
975
976
|
}
|
|
976
|
-
}
|
|
977
|
-
}
|
|
977
|
+
});
|
|
978
|
+
}
|
|
978
979
|
});
|
|
979
980
|
}
|
|
980
981
|
);
|
package/package.json
CHANGED
package/racer-kip.png
ADDED
|
Binary file
|
|
Binary file
|