signalk-livedepth-plugin 0.0.0-stage → 0.1.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.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +51 -2
  3. package/dist/collector.d.ts +15 -0
  4. package/dist/collector.d.ts.map +1 -0
  5. package/dist/collector.js +23 -0
  6. package/dist/collector.js.map +1 -0
  7. package/dist/config.d.ts +142 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +161 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/constants.d.ts +5 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/constants.js +5 -0
  14. package/dist/constants.js.map +1 -0
  15. package/dist/fetch.d.ts +5 -0
  16. package/dist/fetch.d.ts.map +1 -0
  17. package/dist/fetch.js +13 -0
  18. package/dist/fetch.js.map +1 -0
  19. package/dist/history.d.ts +24 -0
  20. package/dist/history.d.ts.map +1 -0
  21. package/dist/history.js +76 -0
  22. package/dist/history.js.map +1 -0
  23. package/dist/index.d.ts +8 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +8 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/plugin.d.ts +3 -0
  28. package/dist/plugin.d.ts.map +1 -0
  29. package/dist/plugin.js +88 -0
  30. package/dist/plugin.js.map +1 -0
  31. package/dist/streams/index.d.ts +3 -0
  32. package/dist/streams/index.d.ts.map +1 -0
  33. package/dist/streams/index.js +3 -0
  34. package/dist/streams/index.js.map +1 -0
  35. package/dist/streams/live.d.ts +9 -0
  36. package/dist/streams/live.d.ts.map +1 -0
  37. package/dist/streams/live.js +62 -0
  38. package/dist/streams/live.js.map +1 -0
  39. package/dist/streams/transforms.d.ts +14 -0
  40. package/dist/streams/transforms.d.ts.map +1 -0
  41. package/dist/streams/transforms.js +21 -0
  42. package/dist/streams/transforms.js.map +1 -0
  43. package/dist/tiles/accumulator.d.ts +34 -0
  44. package/dist/tiles/accumulator.d.ts.map +1 -0
  45. package/dist/tiles/accumulator.js +60 -0
  46. package/dist/tiles/accumulator.js.map +1 -0
  47. package/dist/tiles/api.d.ts +36 -0
  48. package/dist/tiles/api.d.ts.map +1 -0
  49. package/dist/tiles/api.js +75 -0
  50. package/dist/tiles/api.js.map +1 -0
  51. package/dist/tiles/grid.d.ts +59 -0
  52. package/dist/tiles/grid.d.ts.map +1 -0
  53. package/dist/tiles/grid.js +121 -0
  54. package/dist/tiles/grid.js.map +1 -0
  55. package/dist/tiles/index.d.ts +7 -0
  56. package/dist/tiles/index.d.ts.map +1 -0
  57. package/dist/tiles/index.js +7 -0
  58. package/dist/tiles/index.js.map +1 -0
  59. package/dist/tiles/seed.d.ts +45 -0
  60. package/dist/tiles/seed.d.ts.map +1 -0
  61. package/dist/tiles/seed.js +132 -0
  62. package/dist/tiles/seed.js.map +1 -0
  63. package/dist/tiles/store.d.ts +36 -0
  64. package/dist/tiles/store.d.ts.map +1 -0
  65. package/dist/tiles/store.js +114 -0
  66. package/dist/tiles/store.js.map +1 -0
  67. package/dist/tiles/writer.d.ts +15 -0
  68. package/dist/tiles/writer.d.ts.map +1 -0
  69. package/dist/tiles/writer.js +46 -0
  70. package/dist/tiles/writer.js.map +1 -0
  71. package/dist/tsconfig.tsbuildinfo +1 -0
  72. package/dist/types.d.ts +10 -0
  73. package/dist/types.d.ts.map +1 -0
  74. package/dist/types.js +2 -0
  75. package/dist/types.js.map +1 -0
  76. package/icon.svg +12 -0
  77. package/package.json +53 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nick Roberts
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 CHANGED
@@ -1,3 +1,52 @@
1
- # Temporary Holding Version
1
+ # signalk-livedepth-plugin
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A Signal K server plugin that builds a **gridded bathymetry tile store** from the
4
+ vessel's own position and depth, and serves it to a chart client's LiveDepth
5
+ layer. It is the server side of Freeboard-SK's LiveDepth layer.
6
+
7
+ ## What it does
8
+
9
+ - Subscribes to the vessel's own `environment.depth.*` and `navigation.position`,
10
+ and folds each sounding into a Web-Mercator XYZ tile store: 256-cell tiles,
11
+ base level `z20` (≈0.15 m per cell), min-pooled down to `z4` (≈2.4 km per
12
+ cell). A tile is stored sparsely — only the cells a sounding fell in — as a
13
+ 5-byte record (`cx, cy, depthCm, count`) keeping the shallowest depth, so
14
+ zooming out never deepens a shoal.
15
+ - Serves the tiles over HTTP so a chart client can draw a depth surface for the
16
+ area without replaying the raw track or interpolating at query time.
17
+ - Can seed the store from the server's History API at the finest granularity it
18
+ offers — a one-time, resumable rebuild for a store that already has a track.
19
+
20
+ ## Routes
21
+
22
+ Mounted by the server at `/plugins/signalk-livedepth-plugin`:
23
+
24
+ | Route | Returns |
25
+ | -------------------------------- | -------------------------------------------------------------------------------------- |
26
+ | `GET /bathymetry/meta` | grid spec (base/min zoom, tile size, record size) and the depth path/offsets to mirror |
27
+ | `GET /bathymetry/tiles/:z/:x/:y` | the sparse tile blob (`application/octet-stream`), or `404` |
28
+ | `GET /bathymetry/seed` | admin only: status of the one-time history rebuild |
29
+ | `POST /bathymetry/seed` | admin only: start the one-time history rebuild (`202`) |
30
+
31
+ A client seeds its view from the tiles, then keeps its own copy current from the
32
+ same Signal K stream.
33
+
34
+ ## Configuration
35
+
36
+ - **Path** — the `environment.depth.*` path to record.
37
+ - **Depth Sounder / GPS Receiver** — the sensor offsets, and the source to pin
38
+ each path to (so soundings from a second GPS don't smear the track).
39
+ - **Rebuild from History** — a one-shot rebuild from the server's History API;
40
+ it fires once when saved and clears itself when it finishes.
41
+
42
+ ## Development
43
+
44
+ ```bash
45
+ npm install
46
+ npm run build # tsc -b -> dist/
47
+ npm test # vitest
48
+ npm run format
49
+ npm run lint
50
+ ```
51
+
52
+ Node `>=22.5` (the store uses the built-in `node:sqlite`).
@@ -0,0 +1,15 @@
1
+ import { Writable } from "stream";
2
+ import { ServerAPI } from "@signalk/server-api";
3
+ import { Config } from "./config.js";
4
+ export interface CollectorOptions {
5
+ app: ServerAPI;
6
+ config: Config;
7
+ /** The tile writer fed the live soundings. */
8
+ writer: Writable;
9
+ signal: AbortSignal;
10
+ }
11
+ /**
12
+ * Pair depth with position once and feed the soundings to the tile writer.
13
+ */
14
+ export declare function createCollector({ app, config, writer, signal, }: CollectorOptions): import("stream-transform").Transformer;
15
+ //# sourceMappingURL=collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC9B,GAAG,EACH,MAAM,EACN,MAAM,EACN,MAAM,GACP,EAAE,gBAAgB,0CAkBlB"}
@@ -0,0 +1,23 @@
1
+ import { transform } from "stream-transform";
2
+ import { createLiveStream, toPrecision } from "./streams/index.js";
3
+ /**
4
+ * Pair depth with position once and feed the soundings to the tile writer.
5
+ */
6
+ export function createCollector({ app, config, writer, signal, }) {
7
+ const live = createLiveStream(app, config);
8
+ const precise = live.pipe(transform(toPrecision()));
9
+ precise.pipe(writer);
10
+ const destroy = () => {
11
+ live.destroy();
12
+ precise.destroy();
13
+ writer.destroy();
14
+ };
15
+ if (signal.aborted) {
16
+ destroy();
17
+ }
18
+ else {
19
+ signal.addEventListener("abort", destroy, { once: true });
20
+ }
21
+ return precise;
22
+ }
23
+ //# sourceMappingURL=collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAUnE;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,GAAG,EACH,MAAM,EACN,MAAM,EACN,MAAM,GACW;IACjB,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAErB,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC,CAAC;IAEF,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,142 @@
1
+ import { ServerAPI } from "@signalk/server-api";
2
+ export type Config = {
3
+ path: (typeof DepthPaths)[number];
4
+ sounder: {
5
+ x: number;
6
+ y: number;
7
+ z: number;
8
+ draft?: number;
9
+ make?: string;
10
+ model?: string;
11
+ frequency?: number;
12
+ transducer?: string;
13
+ source?: string;
14
+ };
15
+ gnss: {
16
+ x: number;
17
+ y: number;
18
+ z: number;
19
+ make?: string;
20
+ model?: string;
21
+ source?: string;
22
+ };
23
+ seed?: {
24
+ run?: boolean;
25
+ resolution?: number;
26
+ };
27
+ };
28
+ /**
29
+ * The source Signal K currently prioritizes for a path (its `$source`) plus the
30
+ * full list of sources that have reported it. Used to default and populate the
31
+ * source selectors so soundings stay pinned to one sensor rather than mixing
32
+ * antenna offsets from multiple GPS sources.
33
+ */
34
+ export declare function sourcesFor(app: ServerAPI, path: string): {
35
+ selected: string | undefined;
36
+ available: string[];
37
+ };
38
+ /** Configured source if set, else the server's prioritized source, else undefined. */
39
+ export declare function resolveSource(app: ServerAPI, configured: string | undefined, path: string): string | undefined;
40
+ export declare const DepthPaths: readonly ["belowSurface", "belowTransducer", "belowKeel"];
41
+ export declare function schema(app: ServerAPI): {
42
+ type: string;
43
+ description: string;
44
+ properties: {
45
+ path: {
46
+ type: string;
47
+ title: string;
48
+ description: string;
49
+ enum: readonly ["belowSurface", "belowTransducer", "belowKeel"];
50
+ default: "belowKeel" | "belowSurface" | "belowTransducer" | undefined;
51
+ };
52
+ sounder: {
53
+ type: string;
54
+ title: string;
55
+ required: string[];
56
+ properties: {
57
+ source: {
58
+ type: string;
59
+ title: string;
60
+ enum: string[];
61
+ enumNames: string[];
62
+ default: string | undefined;
63
+ description: string;
64
+ };
65
+ y: {
66
+ type: string;
67
+ title: string;
68
+ minimum: number;
69
+ default: unknown;
70
+ };
71
+ x: {
72
+ type: string;
73
+ title: string;
74
+ description: string;
75
+ default: unknown;
76
+ };
77
+ z: {
78
+ type: string;
79
+ title: string;
80
+ default: unknown;
81
+ };
82
+ draft: {
83
+ type: string;
84
+ title: string;
85
+ description: string;
86
+ default: unknown;
87
+ };
88
+ };
89
+ };
90
+ gnss: {
91
+ type: string;
92
+ title: string;
93
+ required: string[];
94
+ properties: {
95
+ source: {
96
+ type: string;
97
+ title: string;
98
+ enum: string[];
99
+ enumNames: string[];
100
+ default: string | undefined;
101
+ description: string;
102
+ };
103
+ y: {
104
+ type: string;
105
+ title: string;
106
+ minimum: number;
107
+ default: unknown;
108
+ };
109
+ x: {
110
+ type: string;
111
+ title: string;
112
+ description: string;
113
+ default: unknown;
114
+ };
115
+ z: {
116
+ type: string;
117
+ title: string;
118
+ };
119
+ };
120
+ };
121
+ seed: {
122
+ type: string;
123
+ title: string;
124
+ description: string;
125
+ properties: {
126
+ run: {
127
+ type: string;
128
+ default: boolean;
129
+ title: string;
130
+ description: string;
131
+ };
132
+ resolution: {
133
+ type: string;
134
+ default: number;
135
+ title: string;
136
+ description: string;
137
+ };
138
+ };
139
+ };
140
+ };
141
+ };
142
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,EAAE;QACP,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,IAAI,EAAE;QACJ,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,IAAI,CAAC,EAAE;QACL,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM;;;EAUtD;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAC3B,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAEpB;AAsDD,eAAO,MAAM,UAAU,YACrB,cAAc,EACd,iBAAiB,EACjB,WAAW,CACH,CAAC;AAEX,wBAAgB,MAAM,CAAC,GAAG,EAAE,SAAS;IASjC,IAAI;IACJ,WAAW;IAEX,UAAU;QACR,IAAI;YACF,IAAI;YACJ,KAAK;YACL,WAAW;YAEX,IAAI;YACJ,OAAO;;QAET,OAAO;YACL,IAAI;YACJ,KAAK;YACL,QAAQ;YACR,UAAU;gBACR,MAAM;;;;;;;;gBACN,CAAC;oBACC,IAAI;oBACJ,KAAK;oBACL,OAAO;oBACP,OAAO;;gBAET,CAAC;oBACC,IAAI;oBACJ,KAAK;oBACL,WAAW;oBACX,OAAO;;gBAET,CAAC;oBACC,IAAI;oBACJ,KAAK;oBACL,OAAO;;gBAIT,KAAK;oBACH,IAAI;oBACJ,KAAK;oBACL,WAAW;oBACX,OAAO;;;;QAIb,IAAI;YACF,IAAI;YACJ,KAAK;YACL,QAAQ;YACR,UAAU;gBACR,MAAM;;;;;;;;gBAMN,CAAC;oBACC,IAAI;oBACJ,KAAK;oBACL,OAAO;oBACP,OAAO;;gBAET,CAAC;oBACC,IAAI;oBACJ,KAAK;oBACL,WAAW;oBACX,OAAO;;gBAET,CAAC;oBACC,IAAI;oBACJ,KAAK;;;;QAIX,IAAI;YACF,IAAI;YACJ,KAAK;YACL,WAAW;YAEX,UAAU;gBACR,GAAG;oBACD,IAAI;oBACJ,OAAO;oBACP,KAAK;oBACL,WAAW;;gBAGb,UAAU;oBACR,IAAI;oBACJ,OAAO;oBACP,KAAK;oBACL,WAAW;;;;;EAOtB"}
package/dist/config.js ADDED
@@ -0,0 +1,161 @@
1
+ /**
2
+ * The source Signal K currently prioritizes for a path (its `$source`) plus the
3
+ * full list of sources that have reported it. Used to default and populate the
4
+ * source selectors so soundings stay pinned to one sensor rather than mixing
5
+ * antenna offsets from multiple GPS sources.
6
+ */
7
+ export function sourcesFor(app, path) {
8
+ const node = app.getSelfPath(path);
9
+ const selected = node?.$source;
10
+ // Multi-source paths carry a `values` map keyed by sourceRef; single-source
11
+ // paths have none, so fall back to the active `$source`. Either way, make sure
12
+ // the active source is in the list.
13
+ const available = node?.values ? Object.keys(node.values) : [];
14
+ if (selected && !available.includes(selected))
15
+ available.unshift(selected);
16
+ return { selected, available };
17
+ }
18
+ /** Configured source if set, else the server's prioritized source, else undefined. */
19
+ export function resolveSource(app, configured, path) {
20
+ return configured || sourcesFor(app, path).selected;
21
+ }
22
+ /**
23
+ * A friendly label for a sourceRef, e.g. "Airmar DST200 (PICAN-M.35)", built
24
+ * from the NMEA 2000 device info Signal K keeps under `sources`. Falls back to
25
+ * the raw sourceRef when no device details are known.
26
+ */
27
+ function sourceLabel(app, sourceRef) {
28
+ const dot = sourceRef.indexOf(".");
29
+ const label = dot === -1 ? sourceRef : sourceRef.slice(0, dot);
30
+ const instance = dot === -1 ? "" : sourceRef.slice(dot + 1);
31
+ const sources = app.getPath("sources");
32
+ const connection = sources?.[label];
33
+ // The sources tree keys devices by numeric bus address, but with
34
+ // useCanName the sourceRef carries the hex CAN name instead, so fall
35
+ // back to matching each device's n2k.canName (mirrors the admin UI's
36
+ // getDeviceInfo in signalk-server's sourceLabels.ts).
37
+ const n2k = connection?.[instance]?.n2k ??
38
+ Object.values(connection ?? {}).find((device) => device?.n2k?.canName === instance)?.n2k;
39
+ const name = [n2k?.manufacturerCode, n2k?.modelId]
40
+ .filter((p) => typeof p === "string" && p.length > 0)
41
+ .join(" ");
42
+ return name ? `${name} (${sourceRef})` : sourceRef;
43
+ }
44
+ /**
45
+ * Schema for a source selector. Always an enum, with friendly device names via
46
+ * enumNames. When nothing has reported the path yet the enum is empty and the
47
+ * description warns that no data is available so the empty dropdown isn't a
48
+ * mystery.
49
+ */
50
+ function sourceSchema(app, title, noun, sources) {
51
+ return {
52
+ type: "string",
53
+ title,
54
+ enum: sources.available,
55
+ enumNames: sources.available.map((source) => sourceLabel(app, source)),
56
+ default: sources.selected,
57
+ description: sources.available.length
58
+ ? `The ${noun} source to record. Defaults to the source Signal K prioritizes; choose one when the vessel has more than one.`
59
+ : `No ${noun} data available — reload this page once it is being received.`,
60
+ };
61
+ }
62
+ export const DepthPaths = [
63
+ "belowSurface",
64
+ "belowTransducer",
65
+ "belowKeel",
66
+ ];
67
+ export function schema(app) {
68
+ const defaultPath = DepthPaths.find((path) => app.getSelfPath(`environment.depth.${path}.value`));
69
+ const positionSources = sourcesFor(app, "navigation.position");
70
+ const depthSources = defaultPath
71
+ ? sourcesFor(app, `environment.depth.${defaultPath}`)
72
+ : { selected: undefined, available: [] };
73
+ return {
74
+ type: "object",
75
+ description: "Build a gridded bathymetry tile store from the vessel's own position and depth, and serve it to a chart client's LiveDepth layer.",
76
+ properties: {
77
+ path: {
78
+ type: "string",
79
+ title: "Path",
80
+ description: "The path to the depth data. (e.g. environment.depth.belowTransducer)",
81
+ enum: DepthPaths,
82
+ default: defaultPath,
83
+ },
84
+ sounder: {
85
+ type: "object",
86
+ title: "Depth Sounder",
87
+ required: ["x", "y", "z"],
88
+ properties: {
89
+ source: sourceSchema(app, "Depth source", "depth", depthSources),
90
+ y: {
91
+ type: "number",
92
+ title: "Distance of the transducer from the bow (meters)",
93
+ minimum: 0,
94
+ default: app.getSelfPath("sensors.depth.fromBow.value"),
95
+ },
96
+ x: {
97
+ type: "number",
98
+ title: "Distance of the transducer from the center (meters)",
99
+ description: "+ve to starboard, -ve to port",
100
+ default: app.getSelfPath("sensors.depth.fromCenter.value"),
101
+ },
102
+ z: {
103
+ type: "number",
104
+ title: "Distance of the transducer below the waterline (meters)",
105
+ default: app.getSelfPath("environment.depth.surfaceToTransducer.value"),
106
+ },
107
+ draft: {
108
+ type: "number",
109
+ title: "Draft",
110
+ description: "The draft of the vessel in meters.",
111
+ default: app.getSelfPath("design.draft.value"),
112
+ },
113
+ },
114
+ },
115
+ gnss: {
116
+ type: "object",
117
+ title: "GPS Receiver",
118
+ required: ["x", "y", "z"],
119
+ properties: {
120
+ source: sourceSchema(app, "Position source", "position", positionSources),
121
+ y: {
122
+ type: "number",
123
+ title: "Distance of the antenna from the bow (meters)",
124
+ minimum: 0,
125
+ default: app.getSelfPath("sensors.gps.fromBow.value"),
126
+ },
127
+ x: {
128
+ type: "number",
129
+ title: "Distance of the antenna from the center (meters)",
130
+ description: "+ve to starboard, -ve to port",
131
+ default: app.getSelfPath("sensors.gps.fromCenter.value"),
132
+ },
133
+ z: {
134
+ type: "number",
135
+ title: "Distance of the antenna above the waterline (meters)",
136
+ },
137
+ },
138
+ },
139
+ seed: {
140
+ type: "object",
141
+ title: "Rebuild from History",
142
+ description: "Rebuild the gridded bathymetry tiles from the server's History API at the finest granularity it offers. Slow — it reads the whole record — so run it once; the live stream keeps the tiles current afterwards, and an interrupted run resumes where it stopped.",
143
+ properties: {
144
+ run: {
145
+ type: "boolean",
146
+ default: false,
147
+ title: "Rebuild the bathymetry tiles from history now",
148
+ description: "Starts the rebuild when the configuration is saved. Resets itself when it finishes; leave off to skip.",
149
+ },
150
+ resolution: {
151
+ type: "number",
152
+ default: 0.1,
153
+ title: "History resolution (seconds)",
154
+ description: "Granularity to read. The provider floors this at its native cadence; 0.1 keeps nearly every fix.",
155
+ },
156
+ },
157
+ },
158
+ },
159
+ };
160
+ }
161
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA6BA;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,GAAc,EAAE,IAAY;IACrD,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,IAAI,CACmC,CAAC;IACrE,MAAM,QAAQ,GAAG,IAAI,EAAE,OAAO,CAAC;IAC/B,4EAA4E;IAC5E,+EAA+E;IAC/E,oCAAoC;IACpC,MAAM,SAAS,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/D,IAAI,QAAQ,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AACjC,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAC3B,GAAc,EACd,UAA8B,EAC9B,IAAY;IAEZ,OAAO,UAAU,IAAI,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,GAAc,EAAE,SAAiB;IACpD,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAExB,CAAC;IACd,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;IACpC,iEAAiE;IACjE,qEAAqE;IACrE,qEAAqE;IACrE,sDAAsD;IACtD,MAAM,GAAG,GACP,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG;QAC3B,MAAM,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,CAClC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,QAAQ,CAC9C,EAAE,GAAG,CAAC;IACT,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,OAAO,CAAC;SAC/C,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SACjE,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,SAAS,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACrD,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CACnB,GAAc,EACd,KAAa,EACb,IAAY,EACZ,OAAsC;IAEtC,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,KAAK;QACL,IAAI,EAAE,OAAO,CAAC,SAAS;QACvB,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACtE,OAAO,EAAE,OAAO,CAAC,QAAQ;QACzB,WAAW,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM;YACnC,CAAC,CAAC,OAAO,IAAI,+GAA+G;YAC5H,CAAC,CAAC,MAAM,IAAI,+DAA+D;KAC9E,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,cAAc;IACd,iBAAiB;IACjB,WAAW;CACH,CAAC;AAEX,MAAM,UAAU,MAAM,CAAC,GAAc;IACnC,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAC3C,GAAG,CAAC,WAAW,CAAC,qBAAqB,IAAI,QAAQ,CAAC,CACnD,CAAC;IACF,MAAM,eAAe,GAAG,UAAU,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;IAC/D,MAAM,YAAY,GAAG,WAAW;QAC9B,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,qBAAqB,WAAW,EAAE,CAAC;QACrD,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;IAC3C,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,WAAW,EACT,mIAAmI;QACrI,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,MAAM;gBACb,WAAW,EACT,sEAAsE;gBACxE,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,WAAW;aACrB;YACD,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,eAAe;gBACtB,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;gBACzB,UAAU,EAAE;oBACV,MAAM,EAAE,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,CAAC;oBAChE,CAAC,EAAE;wBACD,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,kDAAkD;wBACzD,OAAO,EAAE,CAAC;wBACV,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC,6BAA6B,CAAC;qBACxD;oBACD,CAAC,EAAE;wBACD,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,qDAAqD;wBAC5D,WAAW,EAAE,+BAA+B;wBAC5C,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC,gCAAgC,CAAC;qBAC3D;oBACD,CAAC,EAAE;wBACD,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,yDAAyD;wBAChE,OAAO,EAAE,GAAG,CAAC,WAAW,CACtB,6CAA6C,CAC9C;qBACF;oBACD,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,OAAO;wBACd,WAAW,EAAE,oCAAoC;wBACjD,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC,oBAAoB,CAAC;qBAC/C;iBACF;aACF;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,cAAc;gBACrB,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;gBACzB,UAAU,EAAE;oBACV,MAAM,EAAE,YAAY,CAClB,GAAG,EACH,iBAAiB,EACjB,UAAU,EACV,eAAe,CAChB;oBACD,CAAC,EAAE;wBACD,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,+CAA+C;wBACtD,OAAO,EAAE,CAAC;wBACV,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC,2BAA2B,CAAC;qBACtD;oBACD,CAAC,EAAE;wBACD,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,kDAAkD;wBACzD,WAAW,EAAE,+BAA+B;wBAC5C,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC,8BAA8B,CAAC;qBACzD;oBACD,CAAC,EAAE;wBACD,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,sDAAsD;qBAC9D;iBACF;aACF;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,sBAAsB;gBAC7B,WAAW,EACT,iQAAiQ;gBACnQ,UAAU,EAAE;oBACV,GAAG,EAAE;wBACH,IAAI,EAAE,SAAS;wBACf,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,+CAA+C;wBACtD,WAAW,EACT,wGAAwG;qBAC3G;oBACD,UAAU,EAAE;wBACV,IAAI,EAAE,QAAQ;wBACd,OAAO,EAAE,GAAG;wBACZ,KAAK,EAAE,8BAA8B;wBACrC,WAAW,EACT,kGAAkG;qBACrG;iBACF;aACF;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { Temporal } from "@js-temporal/polyfill";
2
+ /** Earliest instant the history seed reaches back to. signalk-to-influxdb was
3
+ * first released on 2017-06-28 — the earliest recorded bathymetry. */
4
+ export declare const BATHY_EPOCH: Temporal.Instant;
5
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD;sEACsE;AACtE,eAAO,MAAM,WAAW,kBAEvB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { Temporal } from "@js-temporal/polyfill";
2
+ /** Earliest instant the history seed reaches back to. signalk-to-influxdb was
3
+ * first released on 2017-06-28 — the earliest recorded bathymetry. */
4
+ export const BATHY_EPOCH = Temporal.Instant.from(process.env.BATHY_EPOCH ?? "2017-06-28T00:00:00Z");
5
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD;sEACsE;AACtE,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAC9C,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,sBAAsB,CAClD,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Fetch wrapper that adds a User-Agent, used by the History API HTTP fallback.
3
+ */
4
+ export default function (url: string | URL, init?: RequestInit): Promise<Response>;
5
+ //# sourceMappingURL=fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,OAAO,WAAW,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,GAAE,WAAgB,qBAQjE"}
package/dist/fetch.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Fetch wrapper that adds a User-Agent, used by the History API HTTP fallback.
3
+ */
4
+ export default function (url, init = {}) {
5
+ return fetch(url, {
6
+ ...init,
7
+ headers: {
8
+ ...init.headers,
9
+ "User-Agent": "signalk-livedepth-plugin",
10
+ },
11
+ });
12
+ }
13
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,OAAO,WAAW,GAAiB,EAAE,IAAI,GAAgB,EAAE;IAChE,OAAO,KAAK,CAAC,GAAG,EAAE;QAChB,GAAG,IAAI;QACP,OAAO,EAAE;YACP,GAAG,IAAI,CAAC,OAAO;YACf,YAAY,EAAE,0BAA0B;SACzC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { Path, ServerAPI } from "@signalk/server-api";
2
+ import { HistoryApi, ValuesResponse } from "@signalk/server-api/history";
3
+ export type HistoryAPIOptions = {
4
+ app: ServerAPI;
5
+ host?: string;
6
+ };
7
+ /**
8
+ * The History Provider API is new and may not be available. This uses a provider if available,
9
+ * and otherwise falls back to direct HTTP access if available.
10
+ */
11
+ export declare function getHistoryAPI({ app, port, host, }: HistoryAPIOptions): Promise<HistoryApi | undefined>;
12
+ /**
13
+ * Build a lookup from SignalK path to its column index in a history `DataRow`.
14
+ *
15
+ * `values[i]` describes data column `i + 1` (column 0 is always the timestamp),
16
+ * so the returned index can be used directly against a `DataRow`. The response's
17
+ * `values` metadata is authoritative — v2+ providers may reorder or drop columns
18
+ * — but providers that omit it fall back to the requested path order. When a
19
+ * path appears more than once the first matching column wins.
20
+ */
21
+ export declare function columnsByPath(values: ValuesResponse["values"] | undefined, requested: readonly {
22
+ path: Path;
23
+ }[]): Map<string, number>;
24
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAGL,UAAU,EAIV,cAAc,EACf,MAAM,6BAA6B,CAAC;AAKrC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,SAAS,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAMF;;;GAGG;AACH,wBAAsB,aAAa,CAAC,EAClC,GAAG,EAEH,IAAqE,EACrE,IAA8D,GAC/D,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CA2DrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,SAAS,EAC5C,SAAS,EAAE,SAAS;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,EAAE,GACnC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAOrB"}
@@ -0,0 +1,76 @@
1
+ import { Temporal } from "@js-temporal/polyfill";
2
+ import { BATHY_EPOCH } from "./constants.js";
3
+ import fetch from "./fetch.js";
4
+ /**
5
+ * The History Provider API is new and may not be available. This uses a provider if available,
6
+ * and otherwise falls back to direct HTTP access if available.
7
+ */
8
+ export async function getHistoryAPI({ app,
9
+ // @ts-expect-error: app.config is not a public API
10
+ port = Number(process.env.PORT) || app.config?.settings?.port || 3000, host = process.env.SIGNALK_HOST ?? `http://localhost:${port}/`, }) {
11
+ try {
12
+ // Try to get the built-in history provider API first. It either returns the API or throws
13
+ // an error if no provider is configured. It will also throw if the API is not available.
14
+ const api = await app.getHistoryApi();
15
+ app.debug("Using built-in history provider");
16
+ return api;
17
+ }
18
+ catch {
19
+ // History provider API not available or no provider configured.
20
+ }
21
+ try {
22
+ await getContexts({
23
+ from: BATHY_EPOCH,
24
+ to: Temporal.Now.instant(),
25
+ });
26
+ app.debug("Using History API available at %s", host);
27
+ }
28
+ catch {
29
+ app.debug("History API is not available");
30
+ return;
31
+ }
32
+ return { getValues, getContexts, getPaths };
33
+ async function get(path, params = {}) {
34
+ const url = new URL(path, new URL("/signalk/v2/api/history/", host));
35
+ url.search = new URLSearchParams(params).toString();
36
+ app.debug("Fetching %s", url.toString());
37
+ const res = await fetch(url);
38
+ if (!res.ok) {
39
+ throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
40
+ }
41
+ return res.json();
42
+ }
43
+ function getValues({ pathSpecs, ...query }) {
44
+ return get("values", {
45
+ ...query,
46
+ paths: pathSpecs
47
+ .map(({ path, aggregate }) => [path, aggregate].join(":"))
48
+ .join(","),
49
+ });
50
+ }
51
+ function getContexts(query) {
52
+ return get("contexts", query);
53
+ }
54
+ function getPaths(query) {
55
+ return get("paths", query);
56
+ }
57
+ }
58
+ /**
59
+ * Build a lookup from SignalK path to its column index in a history `DataRow`.
60
+ *
61
+ * `values[i]` describes data column `i + 1` (column 0 is always the timestamp),
62
+ * so the returned index can be used directly against a `DataRow`. The response's
63
+ * `values` metadata is authoritative — v2+ providers may reorder or drop columns
64
+ * — but providers that omit it fall back to the requested path order. When a
65
+ * path appears more than once the first matching column wins.
66
+ */
67
+ export function columnsByPath(values, requested) {
68
+ const source = values && values.length ? values : requested;
69
+ const columns = new Map();
70
+ source.forEach((column, i) => {
71
+ if (!columns.has(column.path))
72
+ columns.set(column.path, i + 1);
73
+ });
74
+ return columns;
75
+ }
76
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import createPlugin from "./plugin.js";
2
+ export default createPlugin;
3
+ export * from "./constants.js";
4
+ export * from "./types.js";
5
+ export * from "./config.js";
6
+ export * from "./streams/index.js";
7
+ export * from "./tiles/index.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,aAAa,CAAC;eAExB,YAAY;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import createPlugin from "./plugin.js";
2
+ export default createPlugin;
3
+ export * from "./constants.js";
4
+ export * from "./types.js";
5
+ export * from "./config.js";
6
+ export * from "./streams/index.js";
7
+ export * from "./tiles/index.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,aAAa,CAAC;AAEvC,eAAe,YAAY,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { ServerAPI, Plugin } from "@signalk/server-api";
2
+ export default function createPlugin(app: ServerAPI): Plugin;
3
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AAatE,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAqG3D"}