signalk-livedepth-plugin 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,7 +11,9 @@ layer. It is the server side of Freeboard-SK's LiveDepth layer.
11
11
  base level `z20` (≈0.15 m per cell), min-pooled down to `z4` (≈2.4 km per
12
12
  cell). A tile is stored sparsely — only the cells a sounding fell in — as a
13
13
  5-byte record (`cx, cy, depthCm, count`) keeping the shallowest depth, so
14
- zooming out never deepens a shoal.
14
+ zooming out never deepens a shoal. The tile algorithm itself lives in
15
+ [`signalk-livedepth-tiles`](https://www.npmjs.com/package/signalk-livedepth-tiles),
16
+ shared with the chart client so both build identical tiles.
15
17
  - Serves the tiles over HTTP so a chart client can draw a depth surface for the
16
18
  area without replaying the raw track or interpolating at query time.
17
19
  - Can seed the store from the server's History API at the finest granularity it
@@ -1,15 +1,18 @@
1
1
  import { Writable } from "stream";
2
2
  import { ServerAPI } from "@signalk/server-api";
3
+ import { TransducerOffset } from "signalk-livedepth-tiles";
3
4
  import { Config } from "./config.js";
4
5
  export interface CollectorOptions {
5
6
  app: ServerAPI;
6
7
  config: Config;
7
8
  /** The tile writer fed the live soundings. */
8
9
  writer: Writable;
10
+ /** Shift each sounding from the reported position to the transducer. */
11
+ offset?: TransducerOffset;
9
12
  signal: AbortSignal;
10
13
  }
11
14
  /**
12
15
  * Pair depth with position once and feed the soundings to the tile writer.
13
16
  */
14
- export declare function createCollector({ app, config, writer, signal, }: CollectorOptions): import("stream-transform").Transformer;
17
+ export declare function createCollector({ app, config, writer, offset, signal, }: CollectorOptions): import("stream-transform").Transformer;
15
18
  //# sourceMappingURL=collector.d.ts.map
@@ -1 +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"}
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,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,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,wEAAwE;IACxE,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC9B,GAAG,EACH,MAAM,EACN,MAAM,EACN,MAAM,EACN,MAAM,GACP,EAAE,gBAAgB,0CAkBlB"}
package/dist/collector.js CHANGED
@@ -3,8 +3,8 @@ import { createLiveStream, toPrecision } from "./streams/index.js";
3
3
  /**
4
4
  * Pair depth with position once and feed the soundings to the tile writer.
5
5
  */
6
- export function createCollector({ app, config, writer, signal, }) {
7
- const live = createLiveStream(app, config);
6
+ export function createCollector({ app, config, writer, offset, signal, }) {
7
+ const live = createLiveStream(app, config, offset);
8
8
  const precise = live.pipe(transform(toPrecision()));
9
9
  precise.pipe(writer);
10
10
  const destroy = () => {
@@ -1 +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"}
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAK7C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAYnE;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,GAAG,EACH,MAAM,EACN,MAAM,EACN,MAAM,EACN,MAAM,GACW;IACjB,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,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"}
package/dist/config.d.ts CHANGED
@@ -1,42 +1,23 @@
1
1
  import { ServerAPI } from "@signalk/server-api";
2
2
  export type Config = {
3
+ /** Which depth datum to record. Signal K already publishes each relative to
4
+ * its own reference, so the value is stored as-is. */
3
5
  path: (typeof DepthPaths)[number];
6
+ /** The depth transducer's position on the hull: `y` from the bow, `x` from
7
+ * the centreline (+starboard). Used only to place a sounding at the
8
+ * transducer rather than at the position the server reports. */
4
9
  sounder: {
5
10
  x: number;
6
11
  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
12
  };
13
+ /** Shift soundings from the vessel reference point the server reports to the
14
+ * transducer. `off` leaves them where the server put them. */
15
+ transducerCorrection: "off" | "replace";
23
16
  seed?: {
24
17
  run?: boolean;
25
18
  resolution?: number;
26
19
  };
27
20
  };
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
21
  export declare const DepthPaths: readonly ["belowSurface", "belowTransducer", "belowKeel"];
41
22
  export declare function schema(app: ServerAPI): {
42
23
  type: string;
@@ -47,21 +28,15 @@ export declare function schema(app: ServerAPI): {
47
28
  title: string;
48
29
  description: string;
49
30
  enum: readonly ["belowSurface", "belowTransducer", "belowKeel"];
31
+ enumNames: string[];
50
32
  default: "belowKeel" | "belowSurface" | "belowTransducer" | undefined;
51
33
  };
52
34
  sounder: {
53
35
  type: string;
54
36
  title: string;
37
+ description: string;
55
38
  required: string[];
56
39
  properties: {
57
- source: {
58
- type: string;
59
- title: string;
60
- enum: string[];
61
- enumNames: string[];
62
- default: string | undefined;
63
- description: string;
64
- };
65
40
  y: {
66
41
  type: string;
67
42
  title: string;
@@ -74,49 +49,15 @@ export declare function schema(app: ServerAPI): {
74
49
  description: string;
75
50
  default: unknown;
76
51
  };
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
52
  };
89
53
  };
90
- gnss: {
54
+ transducerCorrection: {
91
55
  type: string;
92
56
  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
- };
57
+ description: string;
58
+ enum: string[];
59
+ enumNames: string[];
60
+ default: string;
120
61
  };
121
62
  seed: {
122
63
  type: string;
@@ -1 +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"}
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;0DACsD;IACtD,IAAI,EAAE,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;IAClC;;oEAEgE;IAChE,OAAO,EAAE;QACP,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;KACX,CAAC;IACF;kEAC8D;IAC9D,oBAAoB,EAAE,KAAK,GAAG,SAAS,CAAC;IACxC,IAAI,CAAC,EAAE;QACL,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,UAAU,YACrB,cAAc,EACd,iBAAiB,EACjB,WAAW,CACH,CAAC;AAEX,wBAAgB,MAAM,CAAC,GAAG,EAAE,SAAS;IAKjC,IAAI;IACJ,WAAW;IAEX,UAAU;QACR,IAAI;YACF,IAAI;YACJ,KAAK;YACL,WAAW;YAEX,IAAI;YACJ,SAAS;YAKT,OAAO;;QAET,OAAO;YACL,IAAI;YACJ,KAAK;YACL,WAAW;YAEX,QAAQ;YACR,UAAU;gBACR,CAAC;oBACC,IAAI;oBACJ,KAAK;oBACL,OAAO;oBACP,OAAO;;gBAET,CAAC;oBACC,IAAI;oBACJ,KAAK;oBACL,WAAW;oBACX,OAAO;;;;QAIb,oBAAoB;YAClB,IAAI;YACJ,KAAK;YACL,WAAW;YAEX,IAAI;YACJ,SAAS;YACT,OAAO;;QAET,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 CHANGED
@@ -1,64 +1,3 @@
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
1
  export const DepthPaths = [
63
2
  "belowSurface",
64
3
  "belowTransducer",
@@ -66,27 +5,28 @@ export const DepthPaths = [
66
5
  ];
67
6
  export function schema(app) {
68
7
  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
8
  return {
74
9
  type: "object",
75
10
  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
11
  properties: {
77
12
  path: {
78
13
  type: "string",
79
- title: "Path",
80
- description: "The path to the depth data. (e.g. environment.depth.belowTransducer)",
14
+ title: "Depth",
15
+ description: "Which depth datum to record. Signal K publishes each relative to its own reference, so no draft or transducer offset is needed here.",
81
16
  enum: DepthPaths,
17
+ enumNames: [
18
+ "Depth below surface",
19
+ "Depth below transducer",
20
+ "Depth below keel",
21
+ ],
82
22
  default: defaultPath,
83
23
  },
84
24
  sounder: {
85
25
  type: "object",
86
- title: "Depth Sounder",
87
- required: ["x", "y", "z"],
26
+ title: "Depth Transducer",
27
+ description: "Where the transducer sits on the hull, so a sounding is placed at it rather than at the position the server reports.",
28
+ required: ["x", "y"],
88
29
  properties: {
89
- source: sourceSchema(app, "Depth source", "depth", depthSources),
90
30
  y: {
91
31
  type: "number",
92
32
  title: "Distance of the transducer from the bow (meters)",
@@ -99,42 +39,15 @@ export function schema(app) {
99
39
  description: "+ve to starboard, -ve to port",
100
40
  default: app.getSelfPath("sensors.depth.fromCenter.value"),
101
41
  },
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
42
  },
114
43
  },
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
- },
44
+ transducerCorrection: {
45
+ type: "string",
46
+ title: "Transducer position correction",
47
+ description: "Shift each sounding from the vessel reference point the server reports to the transducer. This is only meaningful when the server's own GNSS correction is on (Server → Settings → Vessel → GNSS correction): otherwise the position is the GNSS antenna, not the vessel reference point, and the offset is applied from the wrong place.",
48
+ enum: ["off", "replace"],
49
+ enumNames: ["Off", "Replace with the transducer's position"],
50
+ default: "off",
138
51
  },
139
52
  seed: {
140
53
  type: "object",
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAsBA,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,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,WAAW,EACT,mIAAmI;QACrI,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,OAAO;gBACd,WAAW,EACT,sIAAsI;gBACxI,IAAI,EAAE,UAAU;gBAChB,SAAS,EAAE;oBACT,qBAAqB;oBACrB,wBAAwB;oBACxB,kBAAkB;iBACnB;gBACD,OAAO,EAAE,WAAW;aACrB;YACD,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,kBAAkB;gBACzB,WAAW,EACT,sHAAsH;gBACxH,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;gBACpB,UAAU,EAAE;oBACV,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;iBACF;aACF;YACD,oBAAoB,EAAE;gBACpB,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,gCAAgC;gBACvC,WAAW,EACT,2UAA2U;gBAC7U,IAAI,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC;gBACxB,SAAS,EAAE,CAAC,KAAK,EAAE,wCAAwC,CAAC;gBAC5D,OAAO,EAAE,KAAK;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"}
package/dist/plugin.d.ts CHANGED
@@ -1,3 +1,12 @@
1
1
  import { ServerAPI, Plugin } from "@signalk/server-api";
2
+ /** The vessel's length overall, for locating the reference point the server
3
+ * reports (the CCRP is midships).
4
+ *
5
+ * `design.length` is a compound-value node — `{ value: { overall, hull,
6
+ * waterline } }` — not a leaf, and `getSelfPath` is a `lodash.get` over the raw
7
+ * self model, so `design.length.overall` resolves to nothing. Read the node and
8
+ * take `.value.overall` (matching how the server's own GNSS corrector reads it).
9
+ * Handles `getSelfPath` returning either the value or its node. */
10
+ export declare function readLengthOverall(app: ServerAPI): number | undefined;
2
11
  export default function createPlugin(app: ServerAPI): Plugin;
3
12
  //# sourceMappingURL=plugin.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AActE;;;;;;;mEAOmE;AACnE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAWpE;AA+CD,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAwG3D"}
package/dist/plugin.js CHANGED
@@ -5,12 +5,67 @@ import { createTileWriter } from "./tiles/writer.js";
5
5
  import { seedFromHistory } from "./tiles/seed.js";
6
6
  import { registerBathymetryRoutes, } from "./tiles/api.js";
7
7
  import { createCollector } from "./collector.js";
8
+ /** The vessel's length overall, for locating the reference point the server
9
+ * reports (the CCRP is midships).
10
+ *
11
+ * `design.length` is a compound-value node — `{ value: { overall, hull,
12
+ * waterline } }` — not a leaf, and `getSelfPath` is a `lodash.get` over the raw
13
+ * self model, so `design.length.overall` resolves to nothing. Read the node and
14
+ * take `.value.overall` (matching how the server's own GNSS corrector reads it).
15
+ * Handles `getSelfPath` returning either the value or its node. */
16
+ export function readLengthOverall(app) {
17
+ const node = app.getSelfPath("design.length");
18
+ const value = typeof node === "number" ? node : node?.value;
19
+ const overall = typeof value === "number"
20
+ ? value
21
+ : value?.overall;
22
+ return typeof overall === "number" && Number.isFinite(overall) && overall > 0
23
+ ? overall
24
+ : undefined;
25
+ }
26
+ /** The server's GNSS antenna correction mode; `off` unless configured. */
27
+ function readGnssCorrection(app) {
28
+ // @ts-expect-error: app.config is not a public API
29
+ return app.config?.settings?.gnssCorrection ?? "off";
30
+ }
31
+ /**
32
+ * The body-frame offset from the reference point the server reports to the
33
+ * transducer, or undefined when correction is off (or can't be located).
34
+ *
35
+ * The server corrects `navigation.position` to the CCRP (midships on the
36
+ * centreline) only when its own `gnssCorrection` is on. When it is off the
37
+ * position is the GNSS antenna, whose body position we do not know — so the
38
+ * offset is meaningless. We still apply what the user configured, but flag it.
39
+ */
40
+ function resolveTransducerOffset(app, config) {
41
+ if (config.transducerCorrection !== "replace") {
42
+ return undefined;
43
+ }
44
+ if (readGnssCorrection(app) === "off") {
45
+ app.setPluginError("Transducer correction is on but the server's GNSS correction is off, so " +
46
+ "the position is the GNSS antenna, not the vessel reference point the " +
47
+ "offset is measured from. Enable GNSS correction (Server → Settings → " +
48
+ "Vessel) or turn this off.");
49
+ }
50
+ const length = readLengthOverall(app);
51
+ if (length === undefined) {
52
+ app.setPluginError("Transducer correction needs the vessel's length overall " +
53
+ "(design.length.overall) to locate the reference point; soundings are " +
54
+ "left where the server reports them.");
55
+ return undefined;
56
+ }
57
+ return {
58
+ forward: (config.sounder?.y ?? 0) - length / 2,
59
+ starboard: config.sounder?.x ?? 0,
60
+ };
61
+ }
8
62
  export default function createPlugin(app) {
9
63
  let abortController = undefined;
10
64
  // The gridded store served to chart clients. Built in start(), read by the
11
65
  // routes registered in registerWithRouter().
12
66
  let tileStore;
13
67
  let config;
68
+ let transducer;
14
69
  let seedStatus = { running: false };
15
70
  const runSeed = async (resolution) => {
16
71
  if (seedStatus.running)
@@ -27,6 +82,7 @@ export default function createPlugin(app) {
27
82
  store,
28
83
  config: cfg,
29
84
  resolution,
85
+ offset: transducer,
30
86
  signal: abortController?.signal,
31
87
  onProgress: (p) => {
32
88
  seedStatus = { running: !p.done, progress: p };
@@ -51,10 +107,12 @@ export default function createPlugin(app) {
51
107
  app.debug("Starting signalk-livedepth-plugin");
52
108
  abortController = new AbortController();
53
109
  tileStore = createTileStore(createTileDB(join(app.getDataDirPath(), `bathymetry-tiles.sqlite`)));
110
+ transducer = resolveTransducerOffset(app, config);
54
111
  createCollector({
55
112
  app,
56
113
  config,
57
114
  writer: createTileWriter(tileStore),
115
+ offset: transducer,
58
116
  signal: abortController.signal,
59
117
  });
60
118
  app.setPluginStatus("Collecting depth into the bathymetry tile store");
@@ -79,8 +137,7 @@ export default function createPlugin(app) {
79
137
  registerWithRouter(router) {
80
138
  registerBathymetryRoutes(router, () => tileStore, () => ({
81
139
  depthPath: config ? `environment.depth.${config.path}` : undefined,
82
- sounder: config?.sounder,
83
- gnss: config?.gnss,
140
+ transducer,
84
141
  }), seed);
85
142
  },
86
143
  };
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,11 @@
1
1
  import { ServerAPI } from "@signalk/server-api";
2
2
  import { PassThrough } from "stream";
3
+ import { TransducerOffset } from "signalk-livedepth-tiles";
3
4
  import { Config } from "../config.js";
4
5
  /**
5
6
  * Subscribe to the vessel's own depth and pair each sounding with the last
6
- * position fix, emitting `BathymetryData` objects.
7
+ * position fix, emitting `BathymetryData` objects. When `offset` is given, the
8
+ * position is shifted from the vessel reference point to the transducer.
7
9
  */
8
- export declare function createLiveStream(app: ServerAPI, config: Config): PassThrough;
10
+ export declare function createLiveStream(app: ServerAPI, config: Config, offset?: TransducerOffset): PassThrough;
9
11
  //# sourceMappingURL=live.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/streams/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAOtC;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,eAmE9D"}
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/streams/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAuB,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAOtC;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,gBAAgB,eAyE1B"}
@@ -1,18 +1,15 @@
1
1
  import { PassThrough } from "stream";
2
+ import { correctToTransducer } from "signalk-livedepth-tiles";
2
3
  import { Temporal } from "@js-temporal/polyfill";
3
4
  /** Maximum age of last position fix for a depth to be saved */
4
5
  const ttl = 2000;
5
6
  /**
6
7
  * Subscribe to the vessel's own depth and pair each sounding with the last
7
- * position fix, emitting `BathymetryData` objects.
8
+ * position fix, emitting `BathymetryData` objects. When `offset` is given, the
9
+ * position is shifted from the vessel reference point to the transducer.
8
10
  */
9
- export function createLiveStream(app, config) {
11
+ export function createLiveStream(app, config, offset) {
10
12
  const path = `environment.depth.${config.path}`;
11
- let offset = 0;
12
- if (config.path === "belowTransducer")
13
- offset += config.sounder?.z ?? 0;
14
- if (config.path === "belowKeel")
15
- offset += config.sounder?.draft ?? 0;
16
13
  app.debug(`Collecting depth data from environment.depth.${path}`);
17
14
  const unsubscribes = [];
18
15
  const stream = new PassThrough({ objectMode: true });
@@ -31,7 +28,6 @@ export function createLiveStream(app, config) {
31
28
  update.values.forEach(({ value }) => {
32
29
  if (!value)
33
30
  return;
34
- const depth = value + offset;
35
31
  if (!position)
36
32
  return app.debug("No position data, ignoring depth data");
37
33
  if (isStale(position, timestamp, ttl))
@@ -40,14 +36,19 @@ export function createLiveStream(app, config) {
40
36
  app.debug("Stale heading data, discarding");
41
37
  heading = undefined;
42
38
  }
43
- const data = {
44
- longitude: position.value.longitude,
45
- latitude: position.value.latitude,
46
- depth,
39
+ const { lon, lat } = offset
40
+ ? correctToTransducer({
41
+ lon: position.value.longitude,
42
+ lat: position.value.latitude,
43
+ }, heading?.value, offset)
44
+ : { lon: position.value.longitude, lat: position.value.latitude };
45
+ stream.push({
46
+ longitude: lon,
47
+ latitude: lat,
48
+ depth: value,
47
49
  timestamp,
48
50
  heading: heading?.value,
49
- };
50
- stream.push(data);
51
+ });
51
52
  });
52
53
  }
53
54
  });
@@ -1 +1 @@
1
- {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/streams/live.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/streams/live.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { PluginRouter } from "@signalk/server-api";
2
+ import { TileStore } from "signalk-livedepth-tiles";
2
3
  import { SeedProgress } from "./seed.js";
3
- import { TileStore } from "./store.js";
4
4
  /** Wire format of a `/bathymetry/tiles` response. */
5
5
  export declare const BATHYMETRY_FORMAT = "sparse-v1";
6
6
  /** Extra fields a client needs to mirror the store (depth path, offsets, …). */
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/tiles/api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAQxD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C,gFAAgF;AAChF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAErD,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,MAAM,IAAI,UAAU,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,SAAS,GAAG,SAAS,EACrC,OAAO,GAAE,MAAM,cAA2B,EAC1C,IAAI,CAAC,EAAE,UAAU,GAChB,IAAI,CA+DN"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/tiles/api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAKL,SAAS,EAEV,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C,gFAAgF;AAChF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAErD,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,MAAM,IAAI,UAAU,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,SAAS,GAAG,SAAS,EACrC,OAAO,GAAE,MAAM,cAA2B,EAC1C,IAAI,CAAC,EAAE,UAAU,GAChB,IAAI,CAoEN"}
package/dist/tiles/api.js CHANGED
@@ -1,4 +1,4 @@
1
- import { BASE_ZOOM, MIN_ZOOM, RECORD_BYTES, TILE_SIZE, encodeTile, } from "./grid.js";
1
+ import { BASE_ZOOM, MIN_ZOOM, RECORD_BYTES, TILE_SIZE, encodeTile, } from "signalk-livedepth-tiles";
2
2
  /** Wire format of a `/bathymetry/tiles` response. */
3
3
  export const BATHYMETRY_FORMAT = "sparse-v1";
4
4
  /**
@@ -55,10 +55,15 @@ export function registerBathymetryRoutes(router, getStore, getMeta = () => ({}),
55
55
  res.status(404).end();
56
56
  return;
57
57
  }
58
+ // Send a Buffer, not the Uint8Array `encodeTile` returns: express's
59
+ // `res.send` JSON-encodes anything that isn't a Buffer or string (it
60
+ // becomes `{"0":…,"1":…}`), so the client would decode the JSON text as
61
+ // sparse records. `Buffer` is a Uint8Array subclass, so it sends the
62
+ // bytes verbatim.
58
63
  res
59
64
  .set("Content-Type", "application/octet-stream")
60
65
  .set("Cache-Control", "no-cache")
61
- .send(encodeTile(cells));
66
+ .send(Buffer.from(encodeTile(cells)));
62
67
  });
63
68
  if (seed) {
64
69
  // Registered without access() so the trigger requires admin.