signalk-masterbus 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 (45) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +128 -0
  3. package/bin/darwin-arm64/masterbus-signalk +0 -0
  4. package/bin/darwin-x64/masterbus-signalk +0 -0
  5. package/bin/linux-arm/masterbus-signalk +0 -0
  6. package/bin/linux-arm64/masterbus-signalk +0 -0
  7. package/bin/linux-x64/masterbus-signalk +0 -0
  8. package/bin/win32-x64/masterbus-signalk.exe +0 -0
  9. package/package.json +82 -0
  10. package/plugin/client.d.ts +39 -0
  11. package/plugin/client.d.ts.map +1 -0
  12. package/plugin/client.js +93 -0
  13. package/plugin/client.js.map +1 -0
  14. package/plugin/config.d.ts +146 -0
  15. package/plugin/config.d.ts.map +1 -0
  16. package/plugin/config.js +143 -0
  17. package/plugin/config.js.map +1 -0
  18. package/plugin/daemon.d.ts +63 -0
  19. package/plugin/daemon.d.ts.map +1 -0
  20. package/plugin/daemon.js +223 -0
  21. package/plugin/daemon.js.map +1 -0
  22. package/plugin/index.d.ts +16 -0
  23. package/plugin/index.d.ts.map +1 -0
  24. package/plugin/index.js +199 -0
  25. package/plugin/index.js.map +1 -0
  26. package/plugin/put-bridge.d.ts +47 -0
  27. package/plugin/put-bridge.d.ts.map +1 -0
  28. package/plugin/put-bridge.js +116 -0
  29. package/plugin/put-bridge.js.map +1 -0
  30. package/plugin/router.d.ts +20 -0
  31. package/plugin/router.d.ts.map +1 -0
  32. package/plugin/router.js +38 -0
  33. package/plugin/router.js.map +1 -0
  34. package/plugin/stream-forwarder.d.ts +54 -0
  35. package/plugin/stream-forwarder.d.ts.map +1 -0
  36. package/plugin/stream-forwarder.js +139 -0
  37. package/plugin/stream-forwarder.js.map +1 -0
  38. package/plugin/types.d.ts +136 -0
  39. package/plugin/types.d.ts.map +1 -0
  40. package/plugin/types.js +19 -0
  41. package/plugin/types.js.map +1 -0
  42. package/public/assets/icon.svg +6 -0
  43. package/public/assets/index-D5ZZgo9o.js +49 -0
  44. package/public/assets/index-rkv4IC1b.css +1 -0
  45. package/public/index.html +14 -0
@@ -0,0 +1,146 @@
1
+ /**
2
+ * The plugin's configuration: the JSON Schema the admin UI renders, the
3
+ * matching TypeScript type, and the defaults.
4
+ *
5
+ * Signal K does not seed schema defaults into the runtime config: when the
6
+ * plugin is enabled without the form being saved, `start()` receives `{}`.
7
+ * `withDefaults` fills the gaps so the rest of the plugin can rely on every
8
+ * field being present.
9
+ */
10
+ export type Mode = 'bundled' | 'external';
11
+ export type Transport = 'auto' | 'can' | 'usb';
12
+ export interface BundledConfig {
13
+ /** `auto` lets the daemon detect a USB link or the lone CAN interface. */
14
+ transport: Transport;
15
+ /** CAN interface name, or USB-link serial (blank = first). */
16
+ deviceName: string;
17
+ /** 24-bit hex id to announce as bus master, or blank to stay passive. */
18
+ heartbeatMaster: string;
19
+ apiPort: number;
20
+ streamPort: number;
21
+ /** A `masterbus-signalk` binary to run instead of the bundled one. */
22
+ binaryPath: string;
23
+ }
24
+ export interface ExternalConfig {
25
+ host: string;
26
+ apiPort: number;
27
+ streamPort: number;
28
+ token: string;
29
+ }
30
+ export interface Config {
31
+ mode: Mode;
32
+ bundled: BundledConfig;
33
+ external: ExternalConfig;
34
+ /** Mastervolt installer code, for writes to fields that need a login. */
35
+ installerCode: number | null;
36
+ }
37
+ export declare const DEFAULTS: Config;
38
+ /** The configuration with every missing field filled from `DEFAULTS`. */
39
+ export declare function withDefaults(config: unknown): Config;
40
+ export declare const SCHEMA: {
41
+ type: string;
42
+ properties: {
43
+ mode: {
44
+ type: string;
45
+ title: string;
46
+ description: string;
47
+ enum: string[];
48
+ enumNames: string[];
49
+ default: string;
50
+ };
51
+ bundled: {
52
+ type: string;
53
+ title: string;
54
+ properties: {
55
+ transport: {
56
+ type: string;
57
+ title: string;
58
+ description: string;
59
+ enum: string[];
60
+ enumNames: string[];
61
+ default: string;
62
+ };
63
+ deviceName: {
64
+ type: string;
65
+ title: string;
66
+ description: string;
67
+ default: string;
68
+ };
69
+ heartbeatMaster: {
70
+ type: string;
71
+ title: string;
72
+ description: string;
73
+ default: string;
74
+ };
75
+ apiPort: {
76
+ type: string;
77
+ title: string;
78
+ default: number;
79
+ minimum: number;
80
+ maximum: number;
81
+ };
82
+ streamPort: {
83
+ type: string;
84
+ title: string;
85
+ default: number;
86
+ minimum: number;
87
+ maximum: number;
88
+ };
89
+ binaryPath: {
90
+ type: string;
91
+ title: string;
92
+ description: string;
93
+ default: string;
94
+ };
95
+ };
96
+ };
97
+ external: {
98
+ type: string;
99
+ title: string;
100
+ properties: {
101
+ host: {
102
+ type: string;
103
+ title: string;
104
+ default: string;
105
+ };
106
+ apiPort: {
107
+ type: string;
108
+ title: string;
109
+ default: number;
110
+ minimum: number;
111
+ maximum: number;
112
+ };
113
+ streamPort: {
114
+ type: string;
115
+ title: string;
116
+ default: number;
117
+ minimum: number;
118
+ maximum: number;
119
+ };
120
+ token: {
121
+ type: string;
122
+ title: string;
123
+ description: string;
124
+ default: string;
125
+ };
126
+ };
127
+ };
128
+ installerCode: {
129
+ type: string[];
130
+ title: string;
131
+ description: string;
132
+ default: null;
133
+ };
134
+ };
135
+ };
136
+ export declare const UI_SCHEMA: {
137
+ external: {
138
+ token: {
139
+ 'ui:widget': string;
140
+ };
141
+ };
142
+ installerCode: {
143
+ 'ui:widget': string;
144
+ };
145
+ };
146
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,IAAI,GAAG,SAAS,GAAG,UAAU,CAAA;AACzC,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAA;AAE9C,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,SAAS,EAAE,SAAS,CAAA;IACpB,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAA;IAClB,yEAAyE;IACzE,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,EAAE,aAAa,CAAA;IACtB,QAAQ,EAAE,cAAc,CAAA;IACxB,yEAAyE;IACzE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B;AAED,eAAO,MAAM,QAAQ,EAAE,MAiBtB,CAAA;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAWpD;AAED,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuGlB,CAAA;AAED,eAAO,MAAM,SAAS;;;;;;;;;CAGrB,CAAA"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * The plugin's configuration: the JSON Schema the admin UI renders, the
3
+ * matching TypeScript type, and the defaults.
4
+ *
5
+ * Signal K does not seed schema defaults into the runtime config: when the
6
+ * plugin is enabled without the form being saved, `start()` receives `{}`.
7
+ * `withDefaults` fills the gaps so the rest of the plugin can rely on every
8
+ * field being present.
9
+ */
10
+ export const DEFAULTS = {
11
+ mode: 'bundled',
12
+ bundled: {
13
+ transport: 'auto',
14
+ deviceName: '',
15
+ heartbeatMaster: '',
16
+ apiPort: 3010,
17
+ streamPort: 3009,
18
+ binaryPath: ''
19
+ },
20
+ external: {
21
+ host: 'localhost',
22
+ apiPort: 3010,
23
+ streamPort: 3009,
24
+ token: ''
25
+ },
26
+ installerCode: null
27
+ };
28
+ /** The configuration with every missing field filled from `DEFAULTS`. */
29
+ export function withDefaults(config) {
30
+ const c = (config ?? {});
31
+ return {
32
+ mode: c.mode === 'external' ? 'external' : 'bundled',
33
+ bundled: { ...DEFAULTS.bundled, ...(c.bundled ?? {}) },
34
+ external: { ...DEFAULTS.external, ...(c.external ?? {}) },
35
+ installerCode: typeof c.installerCode === 'number' && Number.isFinite(c.installerCode)
36
+ ? c.installerCode
37
+ : null
38
+ };
39
+ }
40
+ export const SCHEMA = {
41
+ type: 'object',
42
+ properties: {
43
+ mode: {
44
+ type: 'string',
45
+ title: 'Where the MasterBus daemon runs',
46
+ description: 'Bundled: this plugin starts masterbus-signalk on this machine, which must be the one ' +
47
+ 'wired to the bus (CAN adapter or Mastervolt USB link). External: connect to a ' +
48
+ 'masterbus-signalk already running elsewhere, with its API enabled.',
49
+ enum: ['bundled', 'external'],
50
+ enumNames: ['Bundled (run it here)', 'External (connect to one)'],
51
+ default: 'bundled'
52
+ },
53
+ bundled: {
54
+ type: 'object',
55
+ title: 'Bundled daemon',
56
+ properties: {
57
+ transport: {
58
+ type: 'string',
59
+ title: 'Transport',
60
+ description: 'Auto picks a plugged-in Mastervolt USB link, else the only CAN interface. Set it ' +
61
+ 'explicitly when the machine has several.',
62
+ enum: ['auto', 'can', 'usb'],
63
+ enumNames: ['Auto-detect', 'SocketCAN (Linux)', 'Mastervolt USB link'],
64
+ default: 'auto'
65
+ },
66
+ deviceName: {
67
+ type: 'string',
68
+ title: 'Device',
69
+ description: 'CAN interface (e.g. can0), or the USB link serial number (blank = first).',
70
+ default: ''
71
+ },
72
+ heartbeatMaster: {
73
+ type: 'string',
74
+ title: 'Act as bus master (hex id)',
75
+ description: 'A 24-bit hex id, e.g. 000001, makes the daemon send master heartbeats so devices ' +
76
+ 'stay responsive on a bus without an EasyView or other master. Leave blank to stay ' +
77
+ 'passive.',
78
+ default: ''
79
+ },
80
+ apiPort: {
81
+ type: 'integer',
82
+ title: 'API port (loopback)',
83
+ default: 3010,
84
+ minimum: 1,
85
+ maximum: 65535
86
+ },
87
+ streamPort: {
88
+ type: 'integer',
89
+ title: 'Stream port (loopback)',
90
+ default: 3009,
91
+ minimum: 1,
92
+ maximum: 65535
93
+ },
94
+ binaryPath: {
95
+ type: 'string',
96
+ title: 'masterbus-signalk binary (advanced)',
97
+ description: 'Leave blank to use the binary bundled with this plugin. A path here runs that ' +
98
+ 'instead, e.g. a development build.',
99
+ default: ''
100
+ }
101
+ }
102
+ },
103
+ external: {
104
+ type: 'object',
105
+ title: 'External daemon',
106
+ properties: {
107
+ host: { type: 'string', title: 'Host', default: 'localhost' },
108
+ apiPort: {
109
+ type: 'integer',
110
+ title: 'API port',
111
+ default: 3010,
112
+ minimum: 1,
113
+ maximum: 65535
114
+ },
115
+ streamPort: {
116
+ type: 'integer',
117
+ title: 'Stream port',
118
+ default: 3009,
119
+ minimum: 1,
120
+ maximum: 65535
121
+ },
122
+ token: {
123
+ type: 'string',
124
+ title: 'API token',
125
+ description: "The daemon's api_token from its config.ini.",
126
+ default: ''
127
+ }
128
+ }
129
+ },
130
+ installerCode: {
131
+ type: ['number', 'null'],
132
+ title: 'Installer code',
133
+ description: 'The Mastervolt installer access code. Only needed for writes to fields that are ' +
134
+ 'read-only at user level; leave blank otherwise.',
135
+ default: null
136
+ }
137
+ }
138
+ };
139
+ export const UI_SCHEMA = {
140
+ external: { token: { 'ui:widget': 'password' } },
141
+ installerCode: { 'ui:widget': 'password' }
142
+ };
143
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import type { BundledConfig } from './config.js';
2
+ /** The directory under `bin/` that carries this platform's daemon. */
3
+ export declare function platformDir(platform?: string, arch?: string): string;
4
+ /**
5
+ * Where the daemon binary is: the configured path if any, else the bundled
6
+ * one under `bin/<os>-<arch>/` next to `plugin/` (put there by
7
+ * `scripts/fetch-daemons.mjs` before publishing). Throws with a message fit
8
+ * for the plugin status when neither exists.
9
+ */
10
+ export declare function resolveBinary(binaryPath: string, from?: string): string;
11
+ /**
12
+ * The `config.ini` the daemon reads, rendered from the plugin's settings.
13
+ * With transport `auto` and a file already present, the file is left alone:
14
+ * the daemon auto-detected it on first run and the user may have edited it.
15
+ * Ports and the API address are always ours, so those keys are rewritten.
16
+ */
17
+ export declare function renderConfigIni(cfg: BundledConfig, existing: string | null): string | null;
18
+ export interface DaemonEvents {
19
+ /** A line of the daemon's stderr. */
20
+ log(line: string): void;
21
+ /** The daemon exited; `restartIn` is null when it will not be restarted. */
22
+ exited(code: number | null, signal: string | null, restartIn: number | null): void;
23
+ /** The daemon is up again after a restart. */
24
+ ready(): void;
25
+ }
26
+ export interface DaemonOptions {
27
+ binary: string;
28
+ /** Where config.ini, mapping.json and the schema cache live. */
29
+ dataDir: string;
30
+ config: BundledConfig;
31
+ events: DaemonEvents;
32
+ /** Extra arguments, e.g. `['--fake-bus']` in tests. */
33
+ extraArgs?: string[];
34
+ /** How long to wait for READY before giving up, ms. */
35
+ readyTimeoutMs?: number;
36
+ }
37
+ /**
38
+ * Runs `masterbus-signalk` as a child process: renders its config and token,
39
+ * spawns it with `--config-dir`, waits for the `READY` line, and restarts
40
+ * it with backoff if it exits. `stop()` ends it for good.
41
+ */
42
+ export declare class DaemonManager {
43
+ readonly token: string;
44
+ private readonly opts;
45
+ private child;
46
+ private stopping;
47
+ private restartTimer;
48
+ private backoffMs;
49
+ private readonly recent;
50
+ private generation;
51
+ constructor(opts: DaemonOptions);
52
+ /** The last lines the daemon wrote to stderr, for an error status. */
53
+ get recentLog(): string[];
54
+ get running(): boolean;
55
+ /** Start the daemon and resolve once it reports READY. */
56
+ start(): Promise<void>;
57
+ private spawnOnce;
58
+ private readyTimeout;
59
+ /** Stop the daemon: SIGTERM, then SIGKILL after a grace period. */
60
+ stop(graceMs?: number): Promise<void>;
61
+ }
62
+ export declare function errMsg(err: unknown): string;
63
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,sEAAsE;AACtE,wBAAgB,WAAW,CACzB,QAAQ,GAAE,MAAyB,EACnC,IAAI,GAAE,MAAqB,GAC1B,MAAM,CAER;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,MAAwB,GAAG,MAAM,CAgBxF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CA6B1F;AAED,MAAM,WAAW,YAAY;IAC3B,qCAAqC;IACrC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,4EAA4E;IAC5E,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IAClF,8CAA8C;IAC9C,KAAK,IAAI,IAAI,CAAA;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,aAAa,CAAA;IACrB,MAAM,EAAE,YAAY,CAAA;IACpB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAID;;;;GAIG;AACH,qBAAa,aAAa;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,YAAY,CAA6C;IACjE,OAAO,CAAC,SAAS,CAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,UAAU,CAAI;gBAEV,IAAI,EAAE,aAAa;IAK/B,sEAAsE;IACtE,IAAI,SAAS,IAAI,MAAM,EAAE,CAExB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,0DAA0D;IACpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B,OAAO,CAAC,SAAS;IAsFjB,OAAO,CAAC,YAAY;IAIpB,mEAAmE;IAC7D,IAAI,CAAC,OAAO,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAqB1C;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAE3C"}
@@ -0,0 +1,223 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { randomBytes } from 'node:crypto';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import readline from 'node:readline';
6
+ import { fileURLToPath } from 'node:url';
7
+ /** The directory under `bin/` that carries this platform's daemon. */
8
+ export function platformDir(platform = process.platform, arch = process.arch) {
9
+ return `${platform}-${arch}`;
10
+ }
11
+ /**
12
+ * Where the daemon binary is: the configured path if any, else the bundled
13
+ * one under `bin/<os>-<arch>/` next to `plugin/` (put there by
14
+ * `scripts/fetch-daemons.mjs` before publishing). Throws with a message fit
15
+ * for the plugin status when neither exists.
16
+ */
17
+ export function resolveBinary(binaryPath, from = import.meta.url) {
18
+ if (binaryPath.trim()) {
19
+ const p = binaryPath.trim();
20
+ if (!fs.existsSync(p))
21
+ throw new Error(`the configured binary ${p} does not exist`);
22
+ return p;
23
+ }
24
+ const exe = process.platform === 'win32' ? 'masterbus-signalk.exe' : 'masterbus-signalk';
25
+ const root = path.resolve(path.dirname(fileURLToPath(from)), '..');
26
+ const bin = path.join(root, 'bin', platformDir(), exe);
27
+ if (!fs.existsSync(bin)) {
28
+ throw new Error(`no bundled daemon for ${platformDir()} (${bin} is missing; in a development checkout ` +
29
+ 'run `npm run fetch-daemons`); set a binary path, or use external mode');
30
+ }
31
+ return bin;
32
+ }
33
+ /**
34
+ * The `config.ini` the daemon reads, rendered from the plugin's settings.
35
+ * With transport `auto` and a file already present, the file is left alone:
36
+ * the daemon auto-detected it on first run and the user may have edited it.
37
+ * Ports and the API address are always ours, so those keys are rewritten.
38
+ */
39
+ export function renderConfigIni(cfg, existing) {
40
+ const ownKeys = ['listen', 'api_listen', 'api_token'];
41
+ const managed = (body) => body
42
+ .split('\n')
43
+ .filter((line) => {
44
+ const key = line.split('=')[0]?.trim().replace(/^#\s*/, '');
45
+ return !(key && ownKeys.includes(key));
46
+ })
47
+ .join('\n')
48
+ .replace(/\n{3,}/g, '\n\n')
49
+ .trimEnd();
50
+ const ours = `\n# Managed by the Signal K plugin (signalk-masterbus); edit ports there.\n` +
51
+ `listen = 127.0.0.1:${cfg.streamPort}\n` +
52
+ `api_listen = 127.0.0.1:${cfg.apiPort}\n`;
53
+ if (cfg.transport === 'auto') {
54
+ if (existing === null)
55
+ return null; // let the daemon auto-detect and write it
56
+ return `${managed(existing)}\n${ours}`;
57
+ }
58
+ const hb = cfg.heartbeatMaster.trim();
59
+ return ('# masterbus configuration, written by the Signal K plugin (signalk-masterbus).\n' +
60
+ '# Transport, device and master role are edited in the plugin settings.\n' +
61
+ (hb ? `heartbeat_master = ${hb}\n` : '# heartbeat_master = 000001\n') +
62
+ `device_type = ${cfg.transport}\n` +
63
+ `device_name = ${cfg.deviceName.trim()}\n` +
64
+ ours);
65
+ }
66
+ const KEEP_LINES = 40;
67
+ /**
68
+ * Runs `masterbus-signalk` as a child process: renders its config and token,
69
+ * spawns it with `--config-dir`, waits for the `READY` line, and restarts
70
+ * it with backoff if it exits. `stop()` ends it for good.
71
+ */
72
+ export class DaemonManager {
73
+ token;
74
+ opts;
75
+ child = null;
76
+ stopping = false;
77
+ restartTimer = null;
78
+ backoffMs = 1000;
79
+ recent = [];
80
+ generation = 0;
81
+ constructor(opts) {
82
+ this.opts = opts;
83
+ this.token = randomBytes(24).toString('hex');
84
+ }
85
+ /** The last lines the daemon wrote to stderr, for an error status. */
86
+ get recentLog() {
87
+ return [...this.recent];
88
+ }
89
+ get running() {
90
+ return this.child !== null && this.child.exitCode === null && !this.child.killed;
91
+ }
92
+ /** Start the daemon and resolve once it reports READY. */
93
+ async start() {
94
+ this.stopping = false;
95
+ fs.mkdirSync(this.opts.dataDir, { recursive: true });
96
+ const ini = path.join(this.opts.dataDir, 'config.ini');
97
+ const existing = fs.existsSync(ini) ? fs.readFileSync(ini, 'utf8') : null;
98
+ const rendered = renderConfigIni(this.opts.config, existing);
99
+ if (rendered !== null && rendered !== existing)
100
+ fs.writeFileSync(ini, rendered);
101
+ const tokenFile = path.join(this.opts.dataDir, 'api-token');
102
+ fs.writeFileSync(tokenFile, this.token, { mode: 0o600 });
103
+ await this.spawnOnce(tokenFile);
104
+ }
105
+ spawnOnce(tokenFile) {
106
+ const generation = ++this.generation;
107
+ const { config } = this.opts;
108
+ const args = [
109
+ '--config-dir',
110
+ this.opts.dataDir,
111
+ '--stream',
112
+ `127.0.0.1:${config.streamPort}`,
113
+ '--api',
114
+ `127.0.0.1:${config.apiPort}`,
115
+ '--api-token-file',
116
+ tokenFile,
117
+ ...(this.opts.extraArgs ?? [])
118
+ ];
119
+ return new Promise((resolve, reject) => {
120
+ let settled = false;
121
+ const child = spawn(this.opts.binary, args, {
122
+ stdio: ['ignore', 'pipe', 'pipe'],
123
+ env: { ...process.env, RUST_LOG: process.env.RUST_LOG ?? 'warn' }
124
+ });
125
+ this.child = child;
126
+ const timeout = setTimeout(() => {
127
+ if (settled)
128
+ return;
129
+ settled = true;
130
+ reject(new Error(`the daemon did not report READY within ${this.readyTimeout() / 1000} s`));
131
+ }, this.readyTimeout());
132
+ // Both pipes exist: stdio is ['ignore', 'pipe', 'pipe'] above.
133
+ readline
134
+ .createInterface({ input: child.stdout })
135
+ .on('line', (line) => {
136
+ if (line.startsWith('READY')) {
137
+ this.backoffMs = 1000;
138
+ if (!settled) {
139
+ settled = true;
140
+ clearTimeout(timeout);
141
+ resolve();
142
+ }
143
+ else {
144
+ this.opts.events.ready();
145
+ }
146
+ }
147
+ });
148
+ readline
149
+ .createInterface({ input: child.stderr })
150
+ .on('line', (line) => {
151
+ this.recent.push(line);
152
+ if (this.recent.length > KEEP_LINES)
153
+ this.recent.shift();
154
+ this.opts.events.log(line);
155
+ });
156
+ child.on('error', (err) => {
157
+ this.recent.push(`spawn: ${err.message}`);
158
+ if (!settled) {
159
+ settled = true;
160
+ clearTimeout(timeout);
161
+ reject(err);
162
+ }
163
+ });
164
+ child.on('exit', (code, signal) => {
165
+ if (generation !== this.generation) {
166
+ // Superseded by stop() or a later start(): report, never restart.
167
+ this.opts.events.exited(code, signal, null);
168
+ return;
169
+ }
170
+ this.child = null;
171
+ const restartIn = this.stopping ? null : this.backoffMs;
172
+ this.opts.events.exited(code, signal, restartIn);
173
+ if (!settled) {
174
+ settled = true;
175
+ clearTimeout(timeout);
176
+ reject(new Error(`the daemon exited with ${code ?? signal ?? 'no status'} before READY`));
177
+ return;
178
+ }
179
+ if (restartIn !== null) {
180
+ this.restartTimer = setTimeout(() => {
181
+ this.restartTimer = null;
182
+ if (this.stopping)
183
+ return;
184
+ this.spawnOnce(tokenFile).catch((err) => {
185
+ this.opts.events.log(`restart failed: ${errMsg(err)}`);
186
+ });
187
+ }, restartIn);
188
+ this.backoffMs = Math.min(this.backoffMs * 2, 60_000);
189
+ }
190
+ });
191
+ });
192
+ }
193
+ readyTimeout() {
194
+ return this.opts.readyTimeoutMs ?? 30_000;
195
+ }
196
+ /** Stop the daemon: SIGTERM, then SIGKILL after a grace period. */
197
+ async stop(graceMs = 5000) {
198
+ this.stopping = true;
199
+ this.generation++;
200
+ if (this.restartTimer) {
201
+ clearTimeout(this.restartTimer);
202
+ this.restartTimer = null;
203
+ }
204
+ const child = this.child;
205
+ this.child = null;
206
+ if (!child || child.exitCode !== null)
207
+ return;
208
+ await new Promise((resolve) => {
209
+ const killer = setTimeout(() => {
210
+ child.kill('SIGKILL');
211
+ }, graceMs);
212
+ child.once('exit', () => {
213
+ clearTimeout(killer);
214
+ resolve();
215
+ });
216
+ child.kill('SIGTERM');
217
+ });
218
+ }
219
+ }
220
+ export function errMsg(err) {
221
+ return err instanceof Error ? err.message : String(err);
222
+ }
223
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Plugin, ServerAPI } from '@signalk/server-api';
2
+ export declare const PLUGIN_ID = "signalk-masterbus";
3
+ /**
4
+ * Mastervolt MasterBus for Signal K.
5
+ *
6
+ * The plugin is a thin layer over `masterbus-signalk`, the daemon from the
7
+ * masterbus project. In *bundled* mode the plugin starts the daemon on this
8
+ * machine and keeps its config, mapping and schema cache under the plugin's
9
+ * data directory; in *external* mode it connects to one running elsewhere.
10
+ * Either way it speaks the same two things to it: the delta stream, which is
11
+ * republished through `handleMessage`, and the control API, which the
12
+ * mapping editor (the webapp under `public/`) reaches through this plugin's
13
+ * router and which turns Signal K PUTs into field writes.
14
+ */
15
+ export default function plugin(app: ServerAPI): Plugin;
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAgB,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAU1E,eAAO,MAAM,SAAS,sBAAsB,CAAA;AAK5C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CA2LrD"}