signalk-polar-performance-plugin 2.0.0 → 2.2.0
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/CHANGELOG.md +34 -1
- package/README.md +38 -10
- package/docs/developer-reference.md +45 -21
- package/package.json +8 -11
- package/plugin/index.js +245 -294
- package/public/app.js +11 -1
- package/test/lifecycle.test.js +91 -1
- package/test/outputs.test.js +419 -0
- package/test/routePolicyShim.js +42 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,40 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Keep `performance.targetSpeed` and `performance.targetVelocityMadeGood` published in irons using the selected beat or run target; polar values and ratios based on the boat's current angle are still cleared.
|
|
11
|
+
|
|
12
|
+
## [2.2.0] - 2026-11-02
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Polar calculations now come directly from signalk-polar-management's live calculation service: the plugin always follows the active polar, the sailplan selection and the performance factor chosen in the Polar Management webapp — including v2 polar sets, which could not be calculated before. The active polar's details shown in the webapp come from the same service. signalk-polar-management (with the calculation service, >=1.5.0) is now required for all polar outputs; the `polar-math` library is no longer bundled.
|
|
16
|
+
- The overview now shows the selected sailplan for v2 polar sets, and the active polar's details refresh automatically after selection changes or edits in the management webapp, without reloading the page.
|
|
17
|
+
- Smoothed-input outputs (damped TWA and boat speed) are now published even while no polar is active; polar-derived outputs are still cleared.
|
|
18
|
+
- The webapp now distinguishes between a missing calculation service (management plugin not installed or disabled) and no active polar being selected.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- The polar selected in Polar Management is picked up automatically after a Signal K server restart, without reselecting it ([#41](https://github.com/htool/signalk-polar-performance-plugin/issues/41)).
|
|
22
|
+
|
|
23
|
+
### Known limitations
|
|
24
|
+
- Sea state (wave) correction is not applied: the Signal K specification defines no paths for the required wave height, period and direction inputs. It can be added once such paths exist.
|
|
25
|
+
|
|
26
|
+
## [2.1.0] - 2026-10-27
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
- Requires signalk-server >=2.35.0 for the upstream metadata-first subscription fix ([SignalK/signalk-server#3216](https://github.com/SignalK/signalk-server/pull/3216)).
|
|
30
|
+
- Requires signalkutilities >=3.2.0 (subscriptions without cached-value replay, smoothers cleared by `null`) and polar-math >=1.1.1 (in-irons cutoff relative to the 25° curve endpoint).
|
|
31
|
+
- Read-only Signal K users can now access live values, status, active-polar display metadata, and polar curve queries used by the plotter. Curve resolution is bounded to at most 181 samples per request; settings remain administrator-only.
|
|
32
|
+
- Clearer `meta` descriptions for `performance.optimumWindAngle` (where the optimal angle comes from, what zero means) and `performance.polarVelocityMadeGood` (the polar's prediction, not the actual VMG).
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
- Removed idle-triggered input resubscriptions to avoid replaying cached values during sensor outages. Idle/stale warnings remain, and existing subscriptions receive data when the source resumes. Source changes and heading toggles still update subscriptions normally.
|
|
36
|
+
- Heading inputs enabled at runtime now use the same lifecycle-warning callbacks as heading inputs enabled at startup.
|
|
37
|
+
- When sailing in irons, all values taken from the polar (polar speed, target speed, target and polar VMG, beat/gybe angles and VMGs, max speed) and the percentages based on them are now cleared consistently. Previously some were cleared, some kept showing and VMG % froze on its last value. This also prevents spikes in the performance percentages while tacking. Steering advice (target angle, optimum wind angle, opposite tack heading) stays available so you can see how far to bear away. Everything returns as soon as you leave irons ([#38](https://github.com/htool/signalk-polar-performance-plugin/issues/38)).
|
|
38
|
+
- When pinching (between the in-irons cutoff and the beat angle), all outputs keep being published.
|
|
39
|
+
- Actual VMG keeps updating in irons instead of freezing on its last value.
|
|
40
|
+
- Performance outputs whose inputs become unavailable (for example missing boat speed, heading or polar targets) are now cleared instead of showing a stale value.
|
|
8
41
|
|
|
9
42
|
## [2.0.0] - 2026-09-09
|
|
10
43
|
|
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@ Polar Performance calculates live sailing performance metrics — target boat sp
|
|
|
7
7
|
**Polar Performance works together with a polar provider plugin** (such as [signalk-polar-management](https://github.com/Asw1n/signalk-polar-management)).
|
|
8
8
|
|
|
9
9
|
Starting in version 2.0.0, polar file storage, file format conversion, ORC imports, and polar selection are decoupled from this compute plugin:
|
|
10
|
-
- **Polar Provider (`signalk-polar-management`):** Stores polar files, imports ORC/CSV/text polar files, manages polar metadata,
|
|
11
|
-
- **Performance Plugin (`signalk-polar-performance-plugin`):** Subscribes to
|
|
10
|
+
- **Polar Provider (`signalk-polar-management`):** Stores polar files, imports ORC/CSV/text polar files, manages polar metadata, publishes the selected active polar to Signal K (`polars.activePolar`) along with the shared performance factor (`polars.performanceFactor`), and provides an in-process polar calculation service to other plugins.
|
|
11
|
+
- **Performance Plugin (`signalk-polar-performance-plugin`):** Subscribes to boat instrument data (TWS, TWA, STW/SOG), calculates real-time performance values through the management plugin's live *active polar* calculation handle, and publishes the resulting performance metrics back to the Signal K delta stream. The handle automatically follows the active polar, the sailplan selection, and the performance factor chosen in the Polar Management webapp — including v2 polar sets.
|
|
12
12
|
|
|
13
13
|
When a polar lookup cannot be completed or required instrument data is missing/stale, output paths are cleanly set to `null` and the webapp status indicates the exact cause.
|
|
14
14
|
|
|
@@ -16,6 +16,8 @@ When a polar lookup cannot be completed or required instrument data is missing/s
|
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
19
|
+
Requires signalk-server >=2.35.0 for reliable metadata-first input subscriptions. Idle/stale warnings do not trigger resubscriptions; existing subscriptions receive data when the source resumes. Requires signalk-polar-management >=1.5.0, which provides the in-process polar calculation service.
|
|
20
|
+
|
|
19
21
|
Install both plugins from the Signal K App Store, or via npm:
|
|
20
22
|
|
|
21
23
|
```sh
|
|
@@ -23,7 +25,13 @@ cd ~/.signalk
|
|
|
23
25
|
npm install signalk-polar-performance-plugin signalk-polar-management
|
|
24
26
|
```
|
|
25
27
|
|
|
26
|
-
Then restart Signal K and enable both plugins in **Server → Plugin Config**.
|
|
28
|
+
Then restart Signal K and enable both plugins in **Server → Plugin Config**. This plugin requires signalk-polar-management for all polar calculations: without it (or with it disabled), Polar Performance runs but publishes nothing and reports the missing calculation service in its status.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## HTTP endpoint access
|
|
33
|
+
|
|
34
|
+
Signal K read-only users can view live values, status, active-polar display metadata, and polar curves used by the plotter. Plugin settings, including settings reads, require administrator access. Anonymous access remains controlled by the server's security configuration and is not enabled by this plugin. See the [developer reference](./docs/developer-reference.md#rest-api) for the endpoint list and access policies.
|
|
27
35
|
|
|
28
36
|
---
|
|
29
37
|
|
|
@@ -60,7 +68,7 @@ Most configuration is done through the webapp.
|
|
|
60
68
|
|
|
61
69
|
### Active polar and performance factor
|
|
62
70
|
|
|
63
|
-
These are **not** configured here. Select the active polar and set the performance factor in the polar management webapp (
|
|
71
|
+
These are **not** configured here. Select the active polar (and, for v2 polar sets, a sailplan) and set the performance factor in the polar management webapp (signalk-polar-management); this plugin's calculation handle follows those selections automatically on every calculation. If no polar is active, the plugin runs but publishes nothing; any previously published values are nullified immediately.
|
|
64
72
|
|
|
65
73
|
### Smoother
|
|
66
74
|
|
|
@@ -156,11 +164,29 @@ Requires `navigation.headingTrue` to be available.
|
|
|
156
164
|
|
|
157
165
|
Useful when you want downstream instruments to use the same smoothed values that drive the performance calculation.
|
|
158
166
|
|
|
167
|
+
### Output handling when pinching and in irons
|
|
168
|
+
|
|
169
|
+
The polar defines two zones above the beat angle:
|
|
170
|
+
|
|
171
|
+
- **Pinching** — TWA is between the in-irons cutoff and the beat angle. The boat is still sailing, and the polar curve is extended smoothly towards zero speed. **All outputs are published.**
|
|
172
|
+
- **In irons** — TWA is below the cutoff, which lies 80 % of the way from 25° to the beat angle (for example ~38.6° for a 42° beat angle). The polar has no sailing state here, so the outputs are handled per kind:
|
|
173
|
+
|
|
174
|
+
| Kind | Outputs | In irons |
|
|
175
|
+
|------|---------|----------|
|
|
176
|
+
| Measured | `velocityMadeGood`, `angleTrueWaterDamped`, `boatSpeedDamped` | Published |
|
|
177
|
+
| Steering advice | `targetAngle`, `optimumWindAngle`, `tackTrue` | Published, so you can see how far to bear away |
|
|
178
|
+
| Selected target performance | `targetSpeed`, `targetVelocityMadeGood` | Published from the selected beat or run target |
|
|
179
|
+
| Polar values and ratios based on them | `polarSpeed`, `polarSpeedRatio`, `polarVelocityMadeGood`, `polarVelocityMadeGoodRatio`, `beatAngle`, `gybeAngle`, `beatAngleVelocityMadeGood`, `gybeAngleVelocityMadeGood`, `maxSpeed`, `maxSpeedAngle` | Set to `null` |
|
|
180
|
+
|
|
181
|
+
The selected target speed and VMG remain available in irons because they describe the optimal beat or run target for the current TWS, rather than the boat's current angle. Clearing values based on the boat's current polar state prevents spikes in performance ratios while tacking. Through a tack the boat carries its speed head-to-wind while the polar speed falls towards zero, which would briefly drive the ratios to meaningless values. As soon as you bear away out of irons, all other polar values return on the next wind update.
|
|
182
|
+
|
|
183
|
+
A value is set to `null` once when it becomes unavailable and is not repeated until it returns.
|
|
184
|
+
|
|
159
185
|
---
|
|
160
186
|
|
|
161
187
|
## Managing polars
|
|
162
188
|
|
|
163
|
-
Polar storage, import (ORC, text formats), and active-polar/performance-factor selection are handled by
|
|
189
|
+
Polar storage, import (ORC, text formats), and active-polar/sailplan/performance-factor selection are handled by [signalk-polar-management](https://github.com/Asw1n/signalk-polar-management), which also performs all polar calculations for this plugin through its in-process calculation service. See that plugin's documentation for import formats, the ORC certificate search, and extrapolation behaviour of the underlying `polar-math` library.
|
|
164
190
|
|
|
165
191
|
---
|
|
166
192
|
|
|
@@ -221,9 +247,10 @@ The webapp shows warnings whenever something prevents accurate calculation:
|
|
|
221
247
|
| *True wind speed — no data* | `environment.wind.speedTrue` is not arriving from Signal K. |
|
|
222
248
|
| *True wind angle — no data* | `environment.wind.angleTrueWater` is not arriving. |
|
|
223
249
|
| *Boat speed — no data* | `navigation.speedThroughWater` (or SOG) is not arriving. |
|
|
224
|
-
| *No active polar* | No
|
|
225
|
-
| *
|
|
226
|
-
| *
|
|
250
|
+
| *No active polar* | No active polar is selected. Select one in the polar management webapp. |
|
|
251
|
+
| *Polar calculation service not available* | signalk-polar-management is not installed, not enabled, or too old to provide the in-process calculation service. |
|
|
252
|
+
| *Sailing in irons* | TWA is below the in-irons cutoff. Polar values and the ratios based on them are set to `null`; measured values and steering advice keep updating. See [Output handling when pinching and in irons](#output-handling-when-pinching-and-in-irons). |
|
|
253
|
+
| *Pinching* | TWA is between the in-irons cutoff and the beat angle. All outputs are published; values come from the extrapolated beat zone. |
|
|
227
254
|
| *Extrapolated beyond run angle* | TWA is deeper than the run angle. Values come from the cosine-VMG extrapolation model. |
|
|
228
255
|
| *Wind speed below/above polar range* | TWS is outside the range covered by the polar. Values are extrapolated from the nearest TWS entry. |
|
|
229
256
|
|
|
@@ -245,11 +272,12 @@ If you want to consume this plugin's live performance queries, use the developer
|
|
|
245
272
|
|
|
246
273
|
- [Developer reference](docs/developer-reference.md) for the plugin REST API.
|
|
247
274
|
- [openApi.json](openApi.json) for the authoritative machine-readable contract.
|
|
248
|
-
- For the canonical `polarTable`
|
|
275
|
+
- For the canonical `polarTable` / `polarSet` structures, polar storage, import, and the in-process calculation service, see [signalk-polar-management](https://github.com/Asw1n/signalk-polar-management) and the [polar-format](https://github.com/Asw1n/polar-format) / [polar-math](https://github.com/Asw1n/polar-math) packages it depends on.
|
|
249
276
|
|
|
250
277
|
---
|
|
251
278
|
|
|
252
279
|
## Known limitations
|
|
253
280
|
|
|
254
281
|
- Heel angle is not taken into account in the polar lookup. Most ORC polars are upright polars.
|
|
255
|
-
- Requires
|
|
282
|
+
- Requires `signalk-polar-management` to be installed and running: it stores and imports polars, owns the active selection, and performs all polar calculations for this plugin.
|
|
283
|
+
- Sea state (wave) correction is not applied, even when the active v2 polar set carries a wave-correction table. The Signal K specification currently defines no paths for the required inputs (significant wave height, wave period, wave direction), so this plugin has nothing to feed the correction with. Support can be added once such paths exist in the specification.
|
|
@@ -1,40 +1,64 @@
|
|
|
1
1
|
# Polar Performance Developer Reference
|
|
2
2
|
|
|
3
3
|
This document covers the REST API this plugin still exposes. It no longer stores, imports,
|
|
4
|
-
or manages polar files — that is handled by
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
or manages polar files — that is handled by
|
|
5
|
+
[signalk-polar-management](https://github.com/Asw1n/signalk-polar-management), which also
|
|
6
|
+
provides the in-process polar calculation service this plugin uses. For the canonical
|
|
7
|
+
`polarTable` / `polarSet` formats and the management API, see that plugin's documentation
|
|
8
|
+
and the [polar-format](https://github.com/Asw1n/polar-format) package; the underlying
|
|
9
|
+
calculation engine, [polar-math](https://github.com/Asw1n/polar-math), is a dependency of
|
|
10
|
+
the management plugin, not of this one.
|
|
9
11
|
|
|
10
12
|
For installation, day-to-day use, and webapp workflow, start with [../README.md](../README.md).
|
|
11
13
|
|
|
12
14
|
## How the active polar is resolved
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
All polar calculations and all active-polar metadata go through the in-process
|
|
17
|
+
calculation service announced by signalk-polar-management via the `polarManagement`
|
|
18
|
+
PropertyValue. At startup this plugin subscribes with
|
|
19
|
+
`app.onPropertyValues('polarManagement', …)` and acquires an **active-polar handle**
|
|
20
|
+
(`service.activePolar()`). Every calculation call on that handle automatically follows
|
|
21
|
+
the shared active polar, the shared sailplan selection (for v2 polar sets), the shared
|
|
22
|
+
performance factor, and the shared wave-correction toggle — this plugin applies none of
|
|
23
|
+
them itself. When the management plugin is missing or stopped, calculations are
|
|
24
|
+
unavailable and the plugin reports this in its status; results then carry
|
|
25
|
+
`state.available: false` with a reason such as `no_active_polar`.
|
|
15
26
|
|
|
16
|
-
|
|
17
|
-
|
|
27
|
+
Descriptive metadata comes from the same handle: `handle.describe()` returns the active
|
|
28
|
+
document's name, boat details, selected sailplan, the applied performance factor, and the
|
|
29
|
+
selected table's TWS axis. The plugin refreshes this snapshot on `handle.onChange`
|
|
30
|
+
notifications and serves it through `/meta` and `/polar/axes/tws`. It does not subscribe
|
|
31
|
+
to the `polars.*` Signal K paths and performs no resource lookups; those paths remain
|
|
32
|
+
published by signalk-polar-management for other consumers.
|
|
18
33
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
34
|
+
### Sea state / wave correction
|
|
35
|
+
|
|
36
|
+
v2 polar sets can carry a wave-correction table, and active handles accept per-call
|
|
37
|
+
`seaState` input. This plugin does not supply `seaState`, because the Signal K
|
|
38
|
+
specification currently defines no paths for the required inputs (significant wave height,
|
|
39
|
+
wave period, wave direction). Wave correction therefore has no effect on this plugin's
|
|
40
|
+
outputs. If the specification gains such paths, sea state can be wired into the existing
|
|
41
|
+
handle calls without restructuring.
|
|
23
42
|
|
|
24
43
|
## REST API
|
|
25
44
|
|
|
26
45
|
The plugin exposes a REST API under `/plugins/signalk-polar-performance-plugin/`. Authentication
|
|
27
46
|
follows Signal K server rules; the same session cookie used by the webapp works for direct API calls.
|
|
47
|
+
The endpoints marked **Read-only** are available to users with Signal K read-only permission.
|
|
48
|
+
Anonymous access is controlled only by the server's `allow_readonly` setting and is not enabled by
|
|
49
|
+
the plugin. Curve queries are capped at 181 sample angles per request (minimum step 1°).
|
|
50
|
+
`/meta` includes the active polar's boat type, sail number, source, and free-text notes, so those
|
|
51
|
+
fields are also available to read-only users.
|
|
28
52
|
|
|
29
|
-
| Method | Path | Description |
|
|
30
|
-
|
|
31
|
-
| `GET` | `/live` | Current smoothed TWS, TWA, BSP, polar speed, and polar state. |
|
|
32
|
-
| `GET` | `/status` | Full snapshot: raw inputs, smoothed inputs, and all enabled output values. |
|
|
33
|
-
| `GET` | `/meta` | Display unit metadata for all fields, plus a read-only summary of the active polar (name, boatType, sailnumber, year, source) and performance factor. |
|
|
34
|
-
| `GET` | `/settings` | Current plugin settings (smoother, output toggles, speed source — no polar selection). |
|
|
35
|
-
| `PUT` | `/settings` | Update settings. Body: JSON object with changed keys only. |
|
|
36
|
-
| `GET` | `/polar/axes/tws` | TWS axis of the currently active polar. 404 if none is active. |
|
|
37
|
-
| `GET` | `/polar/queries/curve?tws=&step=` | Interpolated curve for the active polar at the given TWS, with beat/run markers, performance factor already applied. |
|
|
53
|
+
| Method | Path | Description | Access |
|
|
54
|
+
|--------|------|-------------|--------|
|
|
55
|
+
| `GET` | `/live` | Current smoothed TWS, TWA, BSP, polar speed, and polar state. | Read-only |
|
|
56
|
+
| `GET` | `/status` | Full snapshot: raw inputs, smoothed inputs, and all enabled output values. | Read-only |
|
|
57
|
+
| `GET` | `/meta` | Display unit metadata for all fields, plus a read-only summary of the active polar (name, boatType, sailnumber, year, source, notes, selected sailplan) and the applied performance factor. | Read-only |
|
|
58
|
+
| `GET` | `/settings` | Current plugin settings (smoother, output toggles, speed source — no polar selection). | Administrator |
|
|
59
|
+
| `PUT` | `/settings` | Update settings. Body: JSON object with changed keys only. | Administrator |
|
|
60
|
+
| `GET` | `/polar/axes/tws` | TWS axis of the currently active polar. 404 if none is active. | Read-only |
|
|
61
|
+
| `GET` | `/polar/queries/curve?tws=&step=` | Interpolated curve for the active polar at the given TWS, with beat/run markers, performance factor already applied. `step` must be at least 1° and at most π/2 radians. | Read-only |
|
|
38
62
|
|
|
39
63
|
The authoritative machine-readable schema for the two `/polar/*` endpoints is in
|
|
40
64
|
[../openApi.json](../openApi.json).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "signalk-polar-performance-plugin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Calculates live sailing performance from the active polar selected in a polar management plugin (e.g. signalk-polar-management).",
|
|
5
5
|
"main": "plugin/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -19,23 +19,17 @@
|
|
|
19
19
|
],
|
|
20
20
|
"engines": {
|
|
21
21
|
"node": ">=20",
|
|
22
|
-
"signalk-server": ">=2.
|
|
22
|
+
"signalk-server": ">=2.35.0"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"test": "node --test test/**/*.test.js",
|
|
26
26
|
"prepublishOnly": "npm test"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"
|
|
30
|
-
"signalkutilities": "^3.1.3"
|
|
29
|
+
"signalkutilities": "^3.2.0"
|
|
31
30
|
},
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
},
|
|
35
|
-
"peerDependenciesMeta": {
|
|
36
|
-
"signalk-polar-management": {
|
|
37
|
-
"optional": true
|
|
38
|
-
}
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"polar-math": "^1.1.1"
|
|
39
33
|
},
|
|
40
34
|
"repository": {
|
|
41
35
|
"type": "git",
|
|
@@ -51,6 +45,9 @@
|
|
|
51
45
|
"signalk": {
|
|
52
46
|
"appIcon": "./icon.png",
|
|
53
47
|
"displayName": "Polar Performance",
|
|
48
|
+
"requires": [
|
|
49
|
+
"signalk-polar-management"
|
|
50
|
+
],
|
|
54
51
|
"screenshots": [
|
|
55
52
|
"./docs/plotter.png",
|
|
56
53
|
"./docs/overview.png",
|