signalk-wakelogger 0.2.0-beta.10 → 0.2.0-beta.11
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 +28 -6
- package/README.md +6 -6
- package/dist/config/schema.d.ts +2 -2
- package/dist/config/schema.js +2 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/courses/course-store.d.ts +13 -0
- package/dist/courses/course-store.js +45 -4
- package/dist/courses/course-store.js.map +1 -1
- package/dist/index.js +51 -11
- package/dist/index.js.map +1 -1
- package/docs/evidence/course-progress-source.md +88 -0
- package/docs/evidence/eta-correction-independent-review.md +67 -0
- package/docs/evidence/eta-independent-recheck.md +161 -0
- package/docs/evidence/eta-independent-review.md +82 -0
- package/docs/evidence/eta-native-source-availability.md +120 -0
- package/docs/evidence/eta-order-recheck.mjs +20 -0
- package/docs/evidence/eta-order-repro.mjs +11 -0
- package/docs/evidence/eta-print-recheck.mjs +33 -0
- package/docs/evidence/eta-production-independent.md +25 -0
- package/docs/evidence/eta-production-investigation.md +140 -0
- package/docs/evidence/eta-production-reconstruction.json +64 -0
- package/docs/evidence/eta-production-repro.py +53 -0
- package/docs/evidence/eta-source.md +206 -0
- package/docs/evidence/finish-trip-controls.md +76 -0
- package/docs/evidence/finish-trip-independent-review.md +64 -0
- package/docs/evidence/leg-average-boundary-independent-recheck.md +67 -0
- package/docs/evidence/leg-average-eta.md +255 -0
- package/docs/evidence/leg-average-independent-check.mjs +37 -0
- package/docs/evidence/leg-average-independent-review.md +80 -0
- package/docs/evidence/live-tracking-confirmation.md +112 -0
- package/docs/evidence/live-tracking-independent-verification.md +66 -0
- package/docs/evidence/overlays/direct-ground-gybe-1280.png +0 -0
- package/docs/evidence/overlays/direct-ground-gybe-390.png +0 -0
- package/docs/evidence/overlays-source.md +102 -0
- package/docs/evidence/the903/frontend-lint-final-independent.md +75 -0
- package/docs/evidence/true-wind-source.md +174 -0
- package/docs/evidence/vmg-independent.md +77 -0
- package/docs/evidence/vmg-source.md +111 -0
- package/docs/releases/0.2.0-beta.11.md +27 -0
- package/package.json +5 -5
- package/public/app.mjs +47 -28
- package/public/course-progress.mjs +56 -18
- package/public/index.html +4 -4
- package/public/instruments.mjs +64 -23
- package/public/leg-eta.mjs +49 -0
- package/public/style.css +2 -0
- package/public/tracking-controls.mjs +31 -0
- package/public/vessel-guides.mjs +26 -9
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
Updates for boat owners and crew: what's new, what's improved, and anything you need to do.
|
|
4
4
|
|
|
5
|
+
## [0.2.0-beta.11] - 2026-10-17
|
|
6
|
+
|
|
7
|
+
### Live tracking asks before it changes
|
|
8
|
+
|
|
9
|
+
- Turning **Live tracking** on or off now asks you to confirm the change and names its effect. The new setting is only reported once it has been saved onboard, and if the setting changed somewhere else the app re-reads it instead of overwriting it.
|
|
10
|
+
- Live transmission can only be switched on by the confirmed control in the onboard app. The Signal K plugin settings page no longer turns uploads on by itself.
|
|
11
|
+
|
|
12
|
+
### An ETA that follows the leg you are sailing
|
|
13
|
+
|
|
14
|
+
- The Race tab's ETA and VMG are based on your net progress along the current leg — the leg-average speed actually being made good — instead of native time-to-go or a single speed sample. The value is labelled **Leg-average VMG (ground)**. During the first minute of a leg, a matching Wake Logger leg plan may provide a clearly labelled provisional estimate **(plan)**.
|
|
15
|
+
- If the position, speed or course data needed for the estimate is missing, stale or out of sync, the ETA is withheld and the reason is shown instead. Estimates outside normal sailing speeds or more than a day away are not displayed.
|
|
16
|
+
|
|
17
|
+
### Wind values labelled by their source
|
|
18
|
+
|
|
19
|
+
- True wind angle is derived relative to the bow, never the boat's course, and is worked out separately for each velocity reference, so a ground-based result can no longer stand in for water wind.
|
|
20
|
+
- Wind VMG is computed and labelled per reference (ground or water). A value that would mix references, or that is stale, is shown as unavailable instead of being displayed.
|
|
21
|
+
|
|
22
|
+
### A clearer map, progress and finish
|
|
23
|
+
|
|
24
|
+
- Course progress now shows the distance sailed along the active leg, so it advances smoothly between waypoints instead of jumping at each mark.
|
|
25
|
+
- **Finish trip** is always a local save: cloud connection, upload queue and race readiness never block it, and a failed attempt explains the exact cause with a safe retry path.
|
|
26
|
+
- The heading and tack/gybe guide label now names the current tack and stays visible, and the map frames the boat even before a course or track exists. Guides still take no tide or leeway into account.
|
|
27
|
+
|
|
28
|
+
### Updating
|
|
29
|
+
|
|
30
|
+
- Update Wake Logger in the Signal K App Store and restart Signal K if prompted. Your settings, pairing and recorded trips are retained.
|
|
31
|
+
- After this update, **confirm Live tracking ON in the onboard app** to resume uploading new trips. Until you confirm, the plugin keeps recording locally and live transmission stays off — a saved setting or the plugin configuration page can no longer start transmitting by itself.
|
|
32
|
+
|
|
5
33
|
## [0.2.0-beta.10] - 2026-10-11
|
|
6
34
|
|
|
7
35
|
### Race-day navigation survives course activation failures
|
|
@@ -69,8 +97,6 @@ Updates for boat owners and crew: what's new, what's improved, and anything you
|
|
|
69
97
|
- A source time more than 30 days before the delta was delivered is treated as a broken clock and replaced by receipt time, instead of being queued and later rejected by Wake Logger as outside the vessel's entitled capture window (for example a GPS reporting a stale 2014 default date).
|
|
70
98
|
- The database outbox now declares sequences skipped by a seed or reset as dropped when it opens, matching the file outbox, so the cloud's contiguous acknowledgement can advance and later trips are not left waiting for history.
|
|
71
99
|
|
|
72
|
-
## [Unreleased] - 2026-09-27
|
|
73
|
-
|
|
74
100
|
### Offline race readiness you can trust
|
|
75
101
|
|
|
76
102
|
- One clear **Offline race ready** status now checks that the selected course is applied, the expected Signal K route is active, and a Race Pack that matches the course (id, race plan and course definition) is prepared with supported rules and a current forecast. Changing the course immediately invalidates readiness for the old pack, even though that pack is kept for history.
|
|
@@ -80,10 +106,6 @@ Updates for boat owners and crew: what's new, what's improved, and anything you
|
|
|
80
106
|
|
|
81
107
|
- Failed Signal K requests now keep the operation, method, path, HTTP status and a bounded, credential-safe reason. Advancing, setting or activating a course shows a human-readable message such as "Could not advance to the next course point to Mark 3 — Signal K rejected the active route update: <reason>", and the bounded detail is written to the plugin log. Tokens and passwords are never logged or displayed.
|
|
82
108
|
|
|
83
|
-
### A track that survives reload
|
|
84
|
-
|
|
85
|
-
- The onboard map now rebuilds the current recording's track from an independent durable onboard archive on open or reload, rather than starting at page-open time and rather than depending on whether telemetry has already been uploaded. New fixes append incrementally; long trips are decimated for display without changing the recording; and the complete geometry survives browser reload, page-resume and plugin restart with no Wake Logger/cloud connection. A tail-only cloud trip is marked "Reconstructing trip · N% history received" until its history converges.
|
|
86
|
-
|
|
87
109
|
### Standalone vessel instruments
|
|
88
110
|
|
|
89
111
|
- A new **Instruments** tab is the default when no course is selected. It reads position, speed and course over ground, heading (true or magnetic), speed through water, depth (with its reference), and apparent and true wind directly from the local Signal K server.
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ The plugin requires Node.js 20 or newer on the Signal K server. Your boat does n
|
|
|
29
29
|
1. In Signal K's **App Store**, install **Wake Logger** (`signalk-wakelogger`).
|
|
30
30
|
2. In Wake Logger, open your vessel's settings and generate a Signal K pairing code.
|
|
31
31
|
3. Open **Wake Logger** in Signal K's plugin configuration, enter the code and save. Enable the plugin if it is disabled.
|
|
32
|
-
4. Check the connection status. When your boat supplies a position and the connection is online, it will appear in the vessel's **Signal K Live** view in Wake Logger.
|
|
32
|
+
4. Open the onboard **Wake Logger webapp** and confirm **Live tracking** on when you are ready to upload. Check the connection status. When your boat supplies a position and the connection is online, it will appear in the vessel's **Signal K Live** view in Wake Logger.
|
|
33
33
|
|
|
34
34
|
Pairing codes are single-use. If a code expires or is rejected, generate a new one. You do not need to pair again after an ordinary internet outage or plugin update.
|
|
35
35
|
|
|
@@ -37,13 +37,13 @@ Pairing codes are single-use. If a code expires or is rejected, generate a new o
|
|
|
37
37
|
|
|
38
38
|
Recording and uploading are separate. Keep Signal K and the Wake Logger plugin running, with your boat's navigation data available, for the trip to be recorded.
|
|
39
39
|
|
|
40
|
-
**For normal use:**
|
|
40
|
+
**For normal use:** Confirm **Live tracking** on in the onboard Wake Logger app. If internet access drops, the plugin stores readings onboard and resumes uploads when the connection returns, provided your confirmed choice is still on.
|
|
41
41
|
|
|
42
|
-
**To deliberately defer uploading:** Pair first, then
|
|
42
|
+
**To deliberately defer uploading:** Pair first, then confirm **Live tracking** off on the onboard Wake Logger map. The plugin keeps recording locally, up to your storage and age limits. Confirm it on when you are ready to send your live position and upload stored history. Changing the switch does not end a trip or restart recording, and the confirmed setting survives restarts and configuration updates. Both directions require confirmation. New installations and upgrades without a readable confirmed choice start with live tracking off; confirm it on in the onboard app when ready. Saving the legacy upload mode in plugin settings cannot enable live tracking.
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
The plugin configuration still shows the legacy **Upload mode** setting. Saving **Record locally** or **Automatic upload** there does not change your confirmed live-tracking choice. Use the onboard **Live tracking** switch to change it.
|
|
45
45
|
|
|
46
|
-
On reconnecting, the latest position is sent promptly while stored history uploads in the background. With the supporting Wake Logger service update, your vessel view shows the percentage of stored history uploaded and an estimated time remaining once there is enough upload progress to measure. Estimates pause when the connection is lost. Detailed recording updates are available under **Upload details**. Wake Logger uses the recorded movement and times to identify trips; switching live tracking does not itself create a new trip. Missing or rejected readings are flagged rather than presented as a complete trip.
|
|
46
|
+
On reconnecting with **Live tracking** on, the latest position is sent promptly while stored history uploads in the background. Reconnecting with it off keeps recording local and does not enable uploads. With the supporting Wake Logger service update, your vessel view shows the percentage of stored history uploaded and an estimated time remaining once there is enough upload progress to measure. Estimates pause when the connection is lost. Detailed recording updates are available under **Upload details**. Wake Logger uses the recorded movement and times to identify trips; switching live tracking does not itself create a new trip. Missing or rejected readings are flagged rather than presented as a complete trip.
|
|
47
47
|
|
|
48
48
|
**When you dock:** Tap **Finish trip** before switching off boat power. The plugin saves the trip’s actual final recorded sequence and capture time immediately, including offline and with Live tracking off. **Saved onboard · upload pending** is local success, not cloud confirmation. Keep power and Live tracking on until **Trip confirmed ready by cloud** appears if you need confirmation now; the same connection checks receipt coverage and processing. Otherwise the pending finish survives restart and uploads later. The automatic 15-minute stationary stop remains the fallback. Finish trip does not change the active Signal K route, and fresh movement can start a new recording.
|
|
49
49
|
|
|
@@ -93,7 +93,7 @@ Vessel roles and sharing settings in Wake Logger control who can see your data.
|
|
|
93
93
|
## If something is not working
|
|
94
94
|
|
|
95
95
|
- **Not paired:** Generate a pairing code in Wake Logger and enter it in the plugin settings.
|
|
96
|
-
- **Offline or waiting to upload:** Check **
|
|
96
|
+
- **Offline or waiting to upload:** Check **Live tracking** in the onboard app, your internet connection and the plugin's queue status. Confirm Live tracking on when you want uploads to resume. Leave the plugin running so it can record and retry while tracking is on; saving the legacy **Upload mode** setting cannot enable uploads.
|
|
97
97
|
- **No vessel position:** Check that Signal K itself is receiving a valid position from your boat.
|
|
98
98
|
- **Course not active:** Check whether another app selected a route. Reactivate the Wake Logger course when appropriate.
|
|
99
99
|
- **Blank basemap:** Check your selected chart source and local coverage. Course and vessel information can still be displayed.
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -7,8 +7,8 @@ export declare const configSchema: {
|
|
|
7
7
|
readonly title: "Upload mode";
|
|
8
8
|
readonly enum: readonly ["automatic", "local_only"];
|
|
9
9
|
readonly enumNames: readonly ["Automatic upload", "Record locally"];
|
|
10
|
-
readonly default: "
|
|
11
|
-
readonly description: "
|
|
10
|
+
readonly default: "local_only";
|
|
11
|
+
readonly description: "Legacy upload setting. Live tracking is controlled only by the confirmed switch in the onboard Wake Logger app; saving this setting cannot enable uploads.";
|
|
12
12
|
};
|
|
13
13
|
readonly pairingCode: {
|
|
14
14
|
readonly type: "string";
|
package/dist/config/schema.js
CHANGED
|
@@ -10,8 +10,8 @@ exports.configSchema = {
|
|
|
10
10
|
title: 'Upload mode',
|
|
11
11
|
enum: ['automatic', 'local_only'],
|
|
12
12
|
enumNames: ['Automatic upload', 'Record locally'],
|
|
13
|
-
default: '
|
|
14
|
-
description: '
|
|
13
|
+
default: 'local_only',
|
|
14
|
+
description: 'Legacy upload setting. Live tracking is controlled only by the confirmed switch in the onboard Wake Logger app; saving this setting cannot enable uploads.'
|
|
15
15
|
},
|
|
16
16
|
pairingCode: {
|
|
17
17
|
type: 'string',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG;IAC1B,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,UAAU,EAAE;QACV,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC;YACjC,SAAS,EAAE,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;YACjD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG;IAC1B,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,UAAU,EAAE;QACV,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC;YACjC,SAAS,EAAE,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;YACjD,OAAO,EAAE,YAAY;YACrB,WAAW,EAAE,4JAA4J;SAC1K;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,0BAA0B;YACjC,WAAW,EAAE,qFAAqF;SACnG;QACD,aAAa,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,gDAAgD;YACzD,OAAO,EAAE,WAAW;SACrB;QACD,cAAc,EAAE;YACd,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,gCAAgC;YACvC,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,IAAI;SACd;QACD,WAAW,EAAE;YACX,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,iCAAiC;YACxC,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,GAAG;SACb;QACD,aAAa,EAAE;YACb,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,kCAAkC;YACzC,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,CAAC;SACX;QACD,cAAc,EAAE;YACd,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,gCAAgC;YACvC,OAAO,EAAE,KAAK;SACf;QACD,mBAAmB,EAAE;YACnB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,qBAAqB;YAC5B,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC;YAChC,SAAS,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC;YAC1C,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,wMAAwM;SACtN;KACF;CACO,CAAA"}
|
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import { NativeCourseService } from './native-course';
|
|
2
2
|
import { type CourseAcknowledgement } from './protocol';
|
|
3
|
+
export interface LegStart {
|
|
4
|
+
identity: string;
|
|
5
|
+
observedAt: number;
|
|
6
|
+
startedAt: number | null;
|
|
7
|
+
position: {
|
|
8
|
+
latitude: number;
|
|
9
|
+
longitude: number;
|
|
10
|
+
} | null;
|
|
11
|
+
positionTimestamp: number | null;
|
|
12
|
+
}
|
|
3
13
|
export declare class CourseStore {
|
|
4
14
|
private readonly target;
|
|
5
15
|
private readonly native;
|
|
6
16
|
private snapshot;
|
|
7
17
|
private operation;
|
|
18
|
+
private latestLegPosition;
|
|
8
19
|
constructor(target: string, native: NativeCourseService);
|
|
9
20
|
open(): Promise<void>;
|
|
10
21
|
acknowledgement(): Promise<CourseAcknowledgement | undefined>;
|
|
22
|
+
observeLeg(now?: number, activation?: boolean): Promise<void>;
|
|
23
|
+
observeLegPosition(position: unknown, timestamp: unknown, now?: number): Promise<void>;
|
|
11
24
|
status(): Promise<object>;
|
|
12
25
|
receive(payload: Buffer): Promise<CourseAcknowledgement>;
|
|
13
26
|
activate(): Promise<void>;
|
|
@@ -13,6 +13,7 @@ class CourseStore {
|
|
|
13
13
|
native;
|
|
14
14
|
snapshot = { version: 1 };
|
|
15
15
|
operation = Promise.resolve();
|
|
16
|
+
latestLegPosition = null;
|
|
16
17
|
constructor(target, native) {
|
|
17
18
|
this.target = target;
|
|
18
19
|
this.native = native;
|
|
@@ -64,13 +65,50 @@ class CourseStore {
|
|
|
64
65
|
return undefined;
|
|
65
66
|
return { ...acknowledgement, activation: await this.activation(), mapReadiness: this.snapshot.mapReadiness?.revision === this.snapshot.desired?.revision ? this.snapshot.mapReadiness?.status ?? 'unknown' : 'unknown' };
|
|
66
67
|
}
|
|
68
|
+
// One durable marker for every observed activation/advance. Never use page
|
|
69
|
+
// load time, a packet receipt time, or an old race-plan timestamp as leg start.
|
|
70
|
+
async observeLeg(now = Date.now(), activation = false) {
|
|
71
|
+
await this.exclusive(async () => {
|
|
72
|
+
const desired = this.snapshot.desired;
|
|
73
|
+
const native = await this.native.current();
|
|
74
|
+
const matches = desired?.action === 'activate' && await this.native.matches(desired);
|
|
75
|
+
const points = desired?.action === 'activate' ? (0, protocol_1.coursePoints)(desired) : [];
|
|
76
|
+
const index = matches ? native?.activeRoute?.pointIndex : desired?.action === 'activate' ? desired.activeWaypointIndex ?? 1 : null;
|
|
77
|
+
const identity = desired?.action === 'activate' && Number.isInteger(index) && index >= 0 && index < points.length
|
|
78
|
+
? JSON.stringify([desired.courseId, desired.revision, desired.updatedAt, index, matches ? native?.activeRoute?.href : 'cached', matches && native?.activeRoute?.reverse === true, points]) : null;
|
|
79
|
+
if (!activation && (identity === this.snapshot.legStart?.identity || (!identity && !this.snapshot.legStart)))
|
|
80
|
+
return;
|
|
81
|
+
// A first attachment to an already active route cannot reconstruct its
|
|
82
|
+
// activation. Controlled activation or an observed transition is required.
|
|
83
|
+
const knownEvent = activation || !!this.snapshot.legStart;
|
|
84
|
+
const fix = this.latestLegPosition;
|
|
85
|
+
const baseline = knownEvent && fix && fix.at <= now && now - fix.at <= 30000 ? fix : null;
|
|
86
|
+
const next = { ...this.snapshot, legStart: identity ? { identity, observedAt: now, startedAt: knownEvent ? now : null,
|
|
87
|
+
position: baseline?.position ?? null, positionTimestamp: baseline?.at ?? null } : undefined };
|
|
88
|
+
await this.persist(next);
|
|
89
|
+
this.snapshot = next;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
observeLegPosition(position, timestamp, now = Date.now()) {
|
|
93
|
+
return this.exclusive(async () => {
|
|
94
|
+
const p = position;
|
|
95
|
+
const at = typeof timestamp === 'string' ? Date.parse(timestamp) : NaN;
|
|
96
|
+
if (!p || typeof p.latitude !== 'number' || typeof p.longitude !== 'number'
|
|
97
|
+
|| !Number.isFinite(p.latitude) || !Number.isFinite(p.longitude) || Math.abs(p.latitude) > 90 || Math.abs(p.longitude) > 180
|
|
98
|
+
|| !Number.isFinite(at) || at > now || now - at > 30000 || (this.latestLegPosition && at <= this.latestLegPosition.at))
|
|
99
|
+
return;
|
|
100
|
+
this.latestLegPosition = { position: { latitude: p.latitude, longitude: p.longitude }, at };
|
|
101
|
+
});
|
|
102
|
+
}
|
|
67
103
|
async status() {
|
|
104
|
+
await this.observeLeg();
|
|
68
105
|
const course = this.snapshot.cachedCourse;
|
|
69
106
|
const native = await this.native.current();
|
|
70
107
|
const activation = await this.activation();
|
|
71
108
|
const activeMatchesDesired = !!course && this.snapshot.desired?.action === 'activate' && await this.native.matches(course);
|
|
72
109
|
return {
|
|
73
110
|
desired: this.snapshot.desired ?? null, cachedCourse: course ?? null,
|
|
111
|
+
legStart: this.snapshot.legStart ?? null,
|
|
74
112
|
acknowledgement: await this.acknowledgement() ?? null,
|
|
75
113
|
routePoints: course ? (0, protocol_1.coursePoints)(course) : [],
|
|
76
114
|
native: {
|
|
@@ -83,6 +121,7 @@ class CourseStore {
|
|
|
83
121
|
};
|
|
84
122
|
}
|
|
85
123
|
receive(payload) {
|
|
124
|
+
let activated = false;
|
|
86
125
|
return this.exclusive(async () => {
|
|
87
126
|
let document;
|
|
88
127
|
try {
|
|
@@ -102,8 +141,10 @@ class CourseStore {
|
|
|
102
141
|
await this.native.clearOwned(previousCourse);
|
|
103
142
|
else {
|
|
104
143
|
await this.native.ensureResource(document);
|
|
105
|
-
if (!duplicate)
|
|
106
|
-
await this.native.activate(document, false, previousCourse);
|
|
144
|
+
if (!duplicate) {
|
|
145
|
+
const result = await this.native.activate(document, false, previousCourse);
|
|
146
|
+
activated = result === 'active' || previous?.revision !== document.revision;
|
|
147
|
+
}
|
|
107
148
|
}
|
|
108
149
|
const activation = await this.activation();
|
|
109
150
|
const blocker = activation === 'conflict' && document.action === 'activate'
|
|
@@ -127,7 +168,7 @@ class CourseStore {
|
|
|
127
168
|
this.snapshot.acknowledgement = acknowledgement;
|
|
128
169
|
return acknowledgement;
|
|
129
170
|
}
|
|
130
|
-
});
|
|
171
|
+
}).then(async (acknowledgement) => { await this.observeLeg(Date.now(), activated); return acknowledgement; });
|
|
131
172
|
}
|
|
132
173
|
activate() {
|
|
133
174
|
return this.exclusive(async () => {
|
|
@@ -142,7 +183,7 @@ class CourseStore {
|
|
|
142
183
|
const acknowledgement = { v: 1, revision: course.revision, status: 'applied', activation: 'active' };
|
|
143
184
|
await this.persist({ ...this.snapshot, acknowledgement });
|
|
144
185
|
this.snapshot.acknowledgement = acknowledgement;
|
|
145
|
-
});
|
|
186
|
+
}).then(async () => { await this.observeLeg(Date.now(), true); });
|
|
146
187
|
}
|
|
147
188
|
setMapReadiness(revision, status) {
|
|
148
189
|
return this.exclusive(async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"course-store.js","sourceRoot":"","sources":["../../src/courses/course-store.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"course-store.js","sourceRoot":"","sources":["../../src/courses/course-store.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -59,8 +59,8 @@ const constructor = (app) => {
|
|
|
59
59
|
// Explicit, leased, generation-stamped navigation-control ownership. Only the
|
|
60
60
|
// owning onboard client may apply a detected rounding; other pages are viewers.
|
|
61
61
|
const navigationLease = new navigation_control_1.NavigationControlLease();
|
|
62
|
-
let activeUploadMode = '
|
|
63
|
-
let persistedUploadMode = '
|
|
62
|
+
let activeUploadMode = 'local_only';
|
|
63
|
+
let persistedUploadMode = 'local_only';
|
|
64
64
|
let persistenceError;
|
|
65
65
|
let rawConfiguration = {};
|
|
66
66
|
let trackingOperation = Promise.resolve();
|
|
@@ -85,6 +85,8 @@ const constructor = (app) => {
|
|
|
85
85
|
schema: schema_1.configSchema,
|
|
86
86
|
start(configuration) {
|
|
87
87
|
ready = false;
|
|
88
|
+
activeUploadMode = 'local_only';
|
|
89
|
+
persistedUploadMode = 'local_only';
|
|
88
90
|
trackingRevision += 1;
|
|
89
91
|
rawConfiguration = structuredClone(configuration);
|
|
90
92
|
pairingAbortController?.abort();
|
|
@@ -101,9 +103,10 @@ const constructor = (app) => {
|
|
|
101
103
|
await initialise((0, defaults_1.parseConfig)(configuration), thisGeneration);
|
|
102
104
|
ready = thisGeneration === generation;
|
|
103
105
|
}
|
|
104
|
-
})().catch((error) => {
|
|
106
|
+
})().catch(async (error) => {
|
|
105
107
|
if (thisGeneration !== generation)
|
|
106
108
|
return;
|
|
109
|
+
await pauseTransmission();
|
|
107
110
|
const message = safeError(error);
|
|
108
111
|
app.setPluginError(`Wake Logger initialization failed: ${message}`);
|
|
109
112
|
app.error(`Wake Logger initialization failed: ${message}`);
|
|
@@ -140,7 +143,8 @@ const constructor = (app) => {
|
|
|
140
143
|
}
|
|
141
144
|
});
|
|
142
145
|
writeRouter.post('/tracking', async (request, response, next) => {
|
|
143
|
-
const
|
|
146
|
+
const body = request.body;
|
|
147
|
+
const mode = body?.uploadMode;
|
|
144
148
|
if (mode !== 'automatic' && mode !== 'local_only') {
|
|
145
149
|
response.status(400).json({ error: 'invalid_upload_mode' });
|
|
146
150
|
return;
|
|
@@ -149,6 +153,14 @@ const constructor = (app) => {
|
|
|
149
153
|
response.status(409).json({ error: 'tracking_unavailable', ...await trackingStatus() });
|
|
150
154
|
return;
|
|
151
155
|
}
|
|
156
|
+
if (body?.confirmed !== true) {
|
|
157
|
+
response.status(400).json({ error: 'tracking_confirmation_required', ...await trackingStatus() });
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (body.expectedUploadMode !== activeUploadMode) {
|
|
161
|
+
response.status(409).json({ error: 'tracking_changed', ...await trackingStatus() });
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
152
164
|
const revision = ++trackingRevision;
|
|
153
165
|
const thisGeneration = generation;
|
|
154
166
|
// Off wins immediately, even while an earlier options save is pending.
|
|
@@ -854,9 +866,20 @@ const constructor = (app) => {
|
|
|
854
866
|
associationCheck = undefined;
|
|
855
867
|
}
|
|
856
868
|
async function initialise(config, thisGeneration) {
|
|
857
|
-
|
|
869
|
+
// Configuration/defaults are never authority for live transmission. Only a
|
|
870
|
+
// versioned choice written by the confirmed control route may restore ON.
|
|
871
|
+
persistedUploadMode = 'local_only';
|
|
872
|
+
activeUploadMode = 'local_only';
|
|
858
873
|
persistenceError = undefined;
|
|
859
|
-
|
|
874
|
+
try {
|
|
875
|
+
const choice = JSON.parse(await node_fs_1.promises.readFile(node_path_1.default.join(app.getDataDirPath(), 'tracking-choice.json'), 'utf8'));
|
|
876
|
+
if (choice.version !== 1 || choice.confirmed !== true || !['automatic', 'local_only'].includes(choice.uploadMode))
|
|
877
|
+
throw new Error('Invalid tracking choice');
|
|
878
|
+
persistedUploadMode = activeUploadMode = choice.uploadMode;
|
|
879
|
+
}
|
|
880
|
+
catch {
|
|
881
|
+
persistenceError = 'No readable confirmed tracking choice; live tracking remains off. Confirm a choice in the onboard app.';
|
|
882
|
+
}
|
|
860
883
|
try {
|
|
861
884
|
await node_fs_1.promises.access(node_path_1.default.join(app.getDataDirPath(), 'tracking-pause.json'));
|
|
862
885
|
activeUploadMode = 'local_only';
|
|
@@ -873,7 +896,7 @@ const constructor = (app) => {
|
|
|
873
896
|
const credentialStore = new credentials_1.CredentialStore(node_path_1.default.join(dataDirectory, 'identity'));
|
|
874
897
|
let credentials = await credentialStore.load();
|
|
875
898
|
const lastPairingCodeFingerprint = await credentialStore.lastPairingCodeFingerprint();
|
|
876
|
-
if (config.uploadMode === 'automatic' && (0, credentials_1.shouldExchangePairingCode)(credentials, config.pairingCode, lastPairingCodeFingerprint)) {
|
|
899
|
+
if ((config.uploadMode === 'automatic' || !credentials) && (0, credentials_1.shouldExchangePairingCode)(credentials, config.pairingCode, lastPairingCodeFingerprint)) {
|
|
877
900
|
const controller = new AbortController();
|
|
878
901
|
pairingAbortController = controller;
|
|
879
902
|
try {
|
|
@@ -917,7 +940,7 @@ const constructor = (app) => {
|
|
|
917
940
|
}
|
|
918
941
|
if (!credentials) {
|
|
919
942
|
connectionState = 'unpaired';
|
|
920
|
-
app.setPluginStatus(
|
|
943
|
+
app.setPluginStatus('Wake Logger: Not paired');
|
|
921
944
|
return;
|
|
922
945
|
}
|
|
923
946
|
if (generation !== thisGeneration)
|
|
@@ -1083,6 +1106,11 @@ const constructor = (app) => {
|
|
|
1083
1106
|
stopSubscription = (0, subscriber_1.subscribeToTelemetry)(app, (delta) => {
|
|
1084
1107
|
normaliser.ingest(delta);
|
|
1085
1108
|
observations?.ingest(delta);
|
|
1109
|
+
for (const update of delta.updates ?? [])
|
|
1110
|
+
for (const entry of ('values' in update ? update.values : []) ?? []) {
|
|
1111
|
+
if (entry.path === 'navigation.position')
|
|
1112
|
+
void courses?.observeLegPosition(entry.value, update.timestamp).catch(() => app.error('Wake Logger leg marker checkpoint failed'));
|
|
1113
|
+
}
|
|
1086
1114
|
if (!progression)
|
|
1087
1115
|
return;
|
|
1088
1116
|
const fix = normaliser.latestFix();
|
|
@@ -1252,10 +1280,22 @@ const constructor = (app) => {
|
|
|
1252
1280
|
app.savePluginOptions(configuration, (error) => error ? reject(error) : resolve());
|
|
1253
1281
|
});
|
|
1254
1282
|
rawConfiguration = configuration;
|
|
1283
|
+
if (revision !== trackingRevision || generation !== thisGeneration)
|
|
1284
|
+
return;
|
|
1285
|
+
await (0, history_1.durableJson)(node_path_1.default.join(app.getDataDirPath(), 'tracking-choice.json'), { version: 1, confirmed: true, uploadMode: mode });
|
|
1286
|
+
if (generation !== thisGeneration) {
|
|
1287
|
+
await (0, history_1.durableJson)(guard, { paused: true, at: Date.now() });
|
|
1288
|
+
throw new Error('tracking_restarted');
|
|
1289
|
+
}
|
|
1290
|
+
if (revision !== trackingRevision)
|
|
1291
|
+
return;
|
|
1292
|
+
await node_fs_1.promises.unlink(guard).catch((error) => { if (error.code !== 'ENOENT')
|
|
1293
|
+
throw error; });
|
|
1294
|
+
if (generation !== thisGeneration || revision !== trackingRevision) {
|
|
1295
|
+
await (0, history_1.durableJson)(guard, { paused: true, at: Date.now() });
|
|
1296
|
+
throw new Error('tracking_restarted');
|
|
1297
|
+
}
|
|
1255
1298
|
persistedUploadMode = mode;
|
|
1256
|
-
if (revision === trackingRevision && generation === thisGeneration)
|
|
1257
|
-
await node_fs_1.promises.unlink(guard).catch((error) => { if (error.code !== 'ENOENT')
|
|
1258
|
-
throw error; });
|
|
1259
1299
|
persistenceError = undefined;
|
|
1260
1300
|
}
|
|
1261
1301
|
catch (error) {
|