@aurora-blue/signalk-connector 0.2.0-dev.20

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.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +122 -0
  3. package/THIRD_PARTY_NOTICES.md +11 -0
  4. package/VERSION +1 -0
  5. package/dist/src/backoff.d.ts +1 -0
  6. package/dist/src/backoff.js +9 -0
  7. package/dist/src/config.d.ts +192 -0
  8. package/dist/src/config.js +317 -0
  9. package/dist/src/connector.d.ts +69 -0
  10. package/dist/src/connector.js +487 -0
  11. package/dist/src/delta.d.ts +4 -0
  12. package/dist/src/delta.js +137 -0
  13. package/dist/src/geometry.d.ts +3 -0
  14. package/dist/src/geometry.js +25 -0
  15. package/dist/src/http-client.d.ts +22 -0
  16. package/dist/src/http-client.js +158 -0
  17. package/dist/src/index.d.ts +3 -0
  18. package/dist/src/index.js +93 -0
  19. package/dist/src/safety/anchor-alarm.d.ts +33 -0
  20. package/dist/src/safety/anchor-alarm.js +79 -0
  21. package/dist/src/state-store.d.ts +45 -0
  22. package/dist/src/state-store.js +491 -0
  23. package/dist/src/storage-budget.d.ts +35 -0
  24. package/dist/src/storage-budget.js +88 -0
  25. package/dist/src/telemetry-catalog.d.ts +19 -0
  26. package/dist/src/telemetry-catalog.js +93 -0
  27. package/dist/src/telemetry-reducer.d.ts +22 -0
  28. package/dist/src/telemetry-reducer.js +150 -0
  29. package/dist/src/types.d.ts +115 -0
  30. package/dist/src/types.js +5 -0
  31. package/dist/src/version.d.ts +1 -0
  32. package/dist/src/version.js +4 -0
  33. package/package.json +60 -0
  34. package/public/aurora-blue-aboard-mark.svg +19 -0
  35. package/public/aurora-blue-archipelago-dark.svg +32 -0
  36. package/public/aurora-blue-archipelago-light.svg +81 -0
  37. package/public/ci-brand.css +77 -0
  38. package/public/ci-fonts.css +28 -0
  39. package/public/ci-tokens.css +139 -0
  40. package/public/favicon.svg +19 -0
  41. package/public/fonts/LICENSE +96 -0
  42. package/public/fonts/ubuntu-latin-300-normal.woff2 +0 -0
  43. package/public/fonts/ubuntu-latin-400-normal.woff2 +0 -0
  44. package/public/fonts/ubuntu-latin-500-normal.woff2 +0 -0
  45. package/public/fonts/ubuntu-latin-700-normal.woff2 +0 -0
  46. package/public/index.html +177 -0
  47. package/public/locales/de.json +82 -0
  48. package/public/locales/en.json +82 -0
  49. package/public/locales/es.json +82 -0
  50. package/public/locales/fr.json +82 -0
  51. package/public/status.css +262 -0
  52. package/public/status.js +237 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aurora Blue contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # Aurora Blue ABOARD Connector
2
+
3
+ Status: Adaptive protocol 1.1 connector development
4
+
5
+ The standalone status UI follows the central [Web UI CI](../aurora-blue-documentation/docs/WEB_UI_CI.md). Its packaged `public/ci-tokens.css` reproduces the server's versioned typography, semantic palette and shape contract. The live specimen ships with the server at `/system/web-ui-ci`; the connector requires no server connection to render its own status interface.
6
+
7
+ The Aurora Blue ABOARD Connector is the lightweight Signal K edge gateway between a Signal K server and an Aurora Blue ABOARD LOCAL, CONNECT or CLOUD target. The public npm package is `@aurora-blue/signalk-connector`. Its runtime plugin ID remains `aurora-blue-signalk-connector`, preserving the configuration and data-directory identity used by Signal K.
8
+
9
+ ## Implemented responsibilities
10
+
11
+ - Run as a native TypeScript-based Signal K Node server plugin
12
+ - Subscribe to the protocol 1.1 own-vessel navigation, depth, wind, environment, electrical, propulsion, and tank catalog
13
+ - Collect selected AIS target motion and identity data under the original Signal K vessel context
14
+ - Preserve Signal K source references and source timestamps
15
+ - Exchange a short-lived pairing code for a restricted device identity and token
16
+ - Assign one persistent, monotonically increasing sequence per paired device
17
+ - Evaluate an experimental local anchor alarm before historical telemetry reduction
18
+ - Reduce historical telemetry through path-specific change thresholds and maximum heartbeats
19
+ - Persist unacknowledged events in a byte-bounded append-only segmented journal
20
+ - Size the journal from filesystem capacity, free-space reserve, and measured record size
21
+ - Reduce AIS admission progressively as offline-buffer pressure rises
22
+ - Preserve the exact pending batch across retries and restarts
23
+ - Compress larger ingest batches with HTTP gzip content encoding
24
+ - Retry unavailable transfers with bounded exponential backoff and jitter
25
+ - Remove events only after a valid durable server acknowledgement
26
+ - Report pairing, buffer, acknowledgement, transfer, and dropped-event state through Signal K plugin status
27
+ - Apply server-directed active, standby, and disabled operating modes without deriving them from primary-device selection
28
+ - Provide an independent status webapp for Signal K versions that do not render the native plugin status reliably
29
+ - Report the running connector version on authenticated ingest and control requests so updates appear in device administration without pairing again
30
+ - Follow the viewing browser's system light/dark preference, with bundled Ubuntu fonts and the shared Archipelago background available offline
31
+ - Never send control commands to Signal K or the NMEA network
32
+
33
+ ## Runtime
34
+
35
+ - Node.js 20 or newer
36
+ - Signal K Node server plugin API
37
+ - No native runtime dependencies
38
+
39
+ The initial development and CI baseline uses Node.js 22. Persistent state is stored below the plugin data directory supplied by Signal K. The directory is restricted to the runtime user and metadata and journal files use mode `0600` on POSIX systems.
40
+
41
+ ## Configuration
42
+
43
+ Configure the plugin in the Signal K administration interface:
44
+
45
+ 1. Enter the base URL of the Aurora Blue target.
46
+ 2. Enter the short-lived pairing code created for the boat in Aurora Blue administration.
47
+ 3. Keep insecure HTTP disabled except for an isolated local development environment.
48
+ 4. Save and enable the plugin.
49
+
50
+ Select Aurora Blue ABOARD Connector Status under Signal K Webapps for the cross-version runtime view. The page refreshes every five seconds and reads a plugin-local endpoint governed by the Signal K server's access controls. The response omits device identity and credentials, and the page does not send data to another host.
51
+
52
+ The connector exchanges the pairing code once and clears it from the Signal K plugin configuration after successful pairing. The returned device token is stored only in the protected connector state file and is never written to logs.
53
+
54
+ The default configuration sends up to 250 events per batch, waits up to five seconds to combine normal telemetry, samples selected own-vessel Signal K paths every second, samples selected AIS paths every five seconds, and enables the preliminary underway change-or-heartbeat profile. AIS can be disabled independently. The `auto` storage profile selects a constrained, standard, or extended byte budget from filesystem capacity while preserving a free-space reserve. Its effective event limit is derived from measured journal bytes per event instead of a fixed 10,000-event default. Protocol 1.1 permits no more than 500 events per batch, and the server continues to accept exact protocol 1.0 backlog batches during upgrades.
55
+
56
+ The optional anchor alarm is an experimental development scaffold. When enabled, position is requested every 250 milliseconds and every received position reaches the safety engine before telemetry reduction. The alarm publishes a local Signal K notification and detects stale position input without requiring the Aurora Blue target. It must not yet be used as the sole safety device.
57
+
58
+ The paired Aurora Blue target controls the device operating mode. Active mode collects and transfers normal telemetry. Standby stops admitting new historical telemetry, drains existing backlog, and keeps only the local position input required by an enabled anchor alarm. Disabled mode preserves the backlog but stops collection, transfer, and local safety subscriptions. Standby and disabled connectors continue a low-rate authenticated configuration heartbeat so an administrator can reactivate them remotely.
59
+
60
+ ## Development
61
+
62
+ Install locked dependencies and run the same checks used by GitLab CI:
63
+
64
+ ```bash
65
+ npm ci
66
+ npm run check
67
+ ```
68
+
69
+ Build an installable plugin package:
70
+
71
+ ```bash
72
+ npm pack
73
+ ```
74
+
75
+ Create a bounded recording that is pseudonymized before it reaches disk:
76
+
77
+ ```bash
78
+ npm run capture:signalk -- \
79
+ --base-url http://127.0.0.1:3000 \
80
+ --output /private/tmp/sample.aurora-blue-recording.jsonl \
81
+ --duration-seconds 180 \
82
+ --sample-period-ms 1000
83
+ ```
84
+
85
+ Replay a reviewed recording through normalization, adaptive reduction, journal recovery, compression measurement, and offline-buffer projections:
86
+
87
+ ```bash
88
+ npm run replay:signalk -- \
89
+ --input /private/tmp/sample.aurora-blue-recording.jsonl \
90
+ --storage-profile auto \
91
+ --filesystem-total-megabytes 4096 \
92
+ --filesystem-free-megabytes 2048 \
93
+ --scenario-hours 6,12,24
94
+ ```
95
+
96
+ Run the deterministic dense-AIS outage simulation and the packaged-runtime checks for Linux x64, ARM64, and ARMv7:
97
+
98
+ ```bash
99
+ npm run simulate:offline
100
+ npm run verify:package
101
+ npm run verify:platforms
102
+ ```
103
+
104
+ The platform check builds once, then executes the compiled production and test artifacts in the official multi-architecture Node.js 22 image. It does not require native connector dependencies because the runtime package has none.
105
+
106
+ Capture accepts a Signal K base URL supplied at runtime but never stores that address. It replaces vessel identifiers, identity strings, source references, timestamps, and positions before serialization. It also drops distant position outliers that could reveal the original position offset. Recording files are ignored by Git and must not be committed without an explicit privacy audit.
107
+
108
+ See [Development and Operations](docs/DEVELOPMENT.md) for the state model, local installation workflow, configuration fields, and failure behavior.
109
+
110
+ ## Project boundary
111
+
112
+ This connector is licensed under MIT. See LICENSE and THIRD_PARTY_NOTICES.md. This license does not change the licensing of other Aurora Blue ABOARD repositories.
113
+
114
+ ## Installation and updates
115
+
116
+ The public package name is `@aurora-blue/signalk-connector`. Once its first release has been published and indexed, search for that name in the Signal K App Store, install it, restart Signal K if requested, then configure and enable the plugin. Future updates use the same App Store. The bundled status page supports English, German, French and Spanish.
117
+
118
+ When migrating from the unscoped development package `aurora-blue-signalk-connector`, back up Signal K configuration and plugin data first. Stop Signal K and replace only the installed package; preserve the existing plugin configuration and data directory. Do not install both package names together: they deliberately share one runtime plugin ID. Restart and verify pairing, buffered records and status before resuming normal use.
119
+
120
+ Release maintainers use the protected GitLab pipeline described in the central Connector publication document. Package preparation does not itself publish a release or guarantee App Store indexing.
121
+
122
+ The authoritative architecture and protocol documentation is maintained in the separate `aurora-blue-documentation` repository.
@@ -0,0 +1,11 @@
1
+ # Third-party notices
2
+
3
+ Bundled Ubuntu font files in `public/fonts` retain the Ubuntu Font Licence
4
+ in `public/fonts/LICENSE`. That license is not replaced by the Connector MIT
5
+ license. The application has no third-party runtime JavaScript dependencies.
6
+ Development dependencies are excluded from the installed package.
7
+
8
+ The MIT release covers this Connector and the Aurora Blue-owned UI files
9
+ bundled with it. It does not change the licenses of separate Aurora Blue
10
+ repositories or grant trademark rights to represent an unofficial fork as
11
+ an official Aurora Blue ABOARD release.
package/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0-dev.20
@@ -0,0 +1 @@
1
+ export declare const retryDelay: (attempt: number, minimumMs: number, maximumMs: number, random?: () => number) => number;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.retryDelay = void 0;
4
+ const retryDelay = (attempt, minimumMs, maximumMs, random = Math.random) => {
5
+ const exponential = Math.min(maximumMs, minimumMs * 2 ** Math.max(0, attempt - 1));
6
+ const jitter = 0.5 + random() * 0.5;
7
+ return Math.max(minimumMs, Math.floor(exponential * jitter));
8
+ };
9
+ exports.retryDelay = retryDelay;
@@ -0,0 +1,192 @@
1
+ import type { AnchorAlarmConfig } from "./safety/anchor-alarm";
2
+ import type { StorageProfile } from "./storage-budget";
3
+ import type { OperatingProfile } from "./telemetry-reducer";
4
+ export interface ConnectorConfig {
5
+ targetUrl: string;
6
+ deviceName: string;
7
+ pairingCode?: string;
8
+ allowInsecureHttp: boolean;
9
+ batchSize: number;
10
+ flushIntervalMs: number;
11
+ samplePeriodMs: number;
12
+ aisEnabled: boolean;
13
+ aisSamplePeriodMs: number;
14
+ safetySamplePeriodMs: number;
15
+ requestTimeoutMs: number;
16
+ retryMinimumMs: number;
17
+ retryMaximumMs: number;
18
+ storageProfile: StorageProfile;
19
+ maxBufferEvents: number;
20
+ maxBufferBytes: number;
21
+ storageReserveBytes: number;
22
+ storageMaximumFraction: number;
23
+ bufferSegmentBytes: number;
24
+ compressionEnabled: boolean;
25
+ compressionThresholdBytes: number;
26
+ adaptiveTelemetryEnabled: boolean;
27
+ operatingProfile: OperatingProfile;
28
+ anchorAlarm: AnchorAlarmConfig;
29
+ }
30
+ export declare const resolveConfig: (input: object) => ConnectorConfig;
31
+ export declare const pluginSchema: {
32
+ readonly type: "object";
33
+ readonly required: readonly ["targetUrl"];
34
+ readonly properties: {
35
+ readonly targetUrl: {
36
+ readonly type: "string";
37
+ readonly title: "Aurora Blue target URL";
38
+ readonly description: "Base URL of Aurora Blue Server or Aurora Blue Cloud. [Open connector status](/aurora-blue-signalk-connector/).";
39
+ };
40
+ readonly deviceName: {
41
+ readonly type: "string";
42
+ readonly title: "Device name";
43
+ readonly default: "Aurora Blue Signal K";
44
+ };
45
+ readonly pairingCode: {
46
+ readonly type: "string";
47
+ readonly title: "Pairing code";
48
+ readonly description: "Short-lived code from Aurora Blue. Cleared after successful pairing.";
49
+ };
50
+ readonly allowInsecureHttp: {
51
+ readonly type: "boolean";
52
+ readonly title: "Allow insecure HTTP for local development";
53
+ readonly default: false;
54
+ };
55
+ readonly batchSize: {
56
+ readonly type: "integer";
57
+ readonly title: "Maximum events per batch";
58
+ readonly minimum: 1;
59
+ readonly maximum: 500;
60
+ readonly default: 250;
61
+ };
62
+ readonly samplePeriodMs: {
63
+ readonly type: "integer";
64
+ readonly title: "Signal K sample period in milliseconds";
65
+ readonly minimum: 250;
66
+ readonly maximum: 60000;
67
+ readonly default: 1000;
68
+ };
69
+ readonly aisEnabled: {
70
+ readonly type: "boolean";
71
+ readonly title: "Collect AIS targets";
72
+ readonly description: "Collect selected dynamic and identity data for other vessels with conservative transfer reduction.";
73
+ readonly default: true;
74
+ };
75
+ readonly aisSamplePeriodMs: {
76
+ readonly type: "integer";
77
+ readonly title: "AIS sample period in milliseconds";
78
+ readonly minimum: 1000;
79
+ readonly maximum: 120000;
80
+ readonly default: 5000;
81
+ };
82
+ readonly adaptiveTelemetryEnabled: {
83
+ readonly type: "boolean";
84
+ readonly title: "Reduce telemetry by change or heartbeat";
85
+ readonly default: true;
86
+ };
87
+ readonly operatingProfile: {
88
+ readonly type: "string";
89
+ readonly title: "Telemetry operating profile";
90
+ readonly enum: readonly ["anchored", "moored", "underway"];
91
+ readonly default: "underway";
92
+ };
93
+ readonly storageProfile: {
94
+ readonly type: "string";
95
+ readonly title: "Offline storage profile";
96
+ readonly description: "Auto selects a capacity class from the filesystem size. Explicit profiles use capacity-oriented limits and custom uses the advanced limits below.";
97
+ readonly enum: readonly ["auto", "constrained", "standard", "extended", "custom"];
98
+ readonly enumNames: readonly ["Auto (recommended)", "Constrained flash", "Standard embedded storage", "Extended or external storage", "Custom"];
99
+ readonly default: "auto";
100
+ };
101
+ readonly anchorAlarmEnabled: {
102
+ readonly type: "boolean";
103
+ readonly title: "Enable experimental local anchor alarm";
104
+ readonly description: "Evaluation remains local, but this development version is not approved as a sole safety device.";
105
+ readonly default: false;
106
+ };
107
+ readonly anchorLatitude: {
108
+ readonly type: "number";
109
+ readonly title: "Anchor latitude";
110
+ readonly minimum: -90;
111
+ readonly maximum: 90;
112
+ };
113
+ readonly anchorLongitude: {
114
+ readonly type: "number";
115
+ readonly title: "Anchor longitude";
116
+ readonly minimum: -180;
117
+ readonly maximum: 180;
118
+ };
119
+ readonly anchorRadiusMeters: {
120
+ readonly type: "integer";
121
+ readonly title: "Anchor radius in meters";
122
+ readonly minimum: 5;
123
+ readonly maximum: 2000;
124
+ readonly default: 30;
125
+ };
126
+ readonly anchorHysteresisMeters: {
127
+ readonly type: "integer";
128
+ readonly title: "Anchor clear hysteresis in meters";
129
+ readonly minimum: 0;
130
+ readonly maximum: 500;
131
+ readonly default: 5;
132
+ };
133
+ readonly anchorConfirmationSeconds: {
134
+ readonly type: "integer";
135
+ readonly title: "Seconds outside radius before alarm";
136
+ readonly minimum: 0;
137
+ readonly maximum: 300;
138
+ readonly default: 10;
139
+ };
140
+ readonly anchorStalePositionSeconds: {
141
+ readonly type: "integer";
142
+ readonly title: "Seconds without position before alarm";
143
+ readonly minimum: 5;
144
+ readonly maximum: 600;
145
+ readonly default: 30;
146
+ };
147
+ readonly maxBufferEvents: {
148
+ readonly type: "integer";
149
+ readonly title: "Custom event safety limit";
150
+ readonly description: "Absolute secondary safety limit for the custom profile. The effective event limit is derived from the byte budget and measured event size.";
151
+ readonly minimum: 500;
152
+ readonly maximum: 1000000;
153
+ readonly default: 1000000;
154
+ };
155
+ readonly maxBufferMegabytes: {
156
+ readonly type: "integer";
157
+ readonly title: "Custom maximum journal size in megabytes";
158
+ readonly minimum: 4;
159
+ readonly maximum: 1024;
160
+ readonly default: 64;
161
+ };
162
+ readonly storageReserveMegabytes: {
163
+ readonly type: "integer";
164
+ readonly title: "Custom free-space reserve in megabytes";
165
+ readonly minimum: 32;
166
+ readonly maximum: 16384;
167
+ readonly default: 256;
168
+ };
169
+ readonly storageMaximumPercent: {
170
+ readonly type: "integer";
171
+ readonly title: "Custom maximum filesystem percentage";
172
+ readonly minimum: 1;
173
+ readonly maximum: 50;
174
+ readonly default: 5;
175
+ };
176
+ readonly compressionEnabled: {
177
+ readonly type: "boolean";
178
+ readonly title: "Compress larger batches";
179
+ readonly default: true;
180
+ };
181
+ };
182
+ };
183
+ export declare const pluginUiSchema: {
184
+ readonly targetUrl: {
185
+ readonly "ui:options": {
186
+ readonly enableMarkdownInDescription: true;
187
+ };
188
+ };
189
+ readonly pairingCode: {
190
+ readonly "ui:widget": "password";
191
+ };
192
+ };