@signalk/vedirect-serial-usb 1.5.0 → 1.7.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.
- package/LICENSE +201 -0
- package/README.md +36 -24
- package/dist/Parser.d.ts +50 -0
- package/dist/Parser.d.ts.map +1 -0
- package/dist/Parser.js +350 -0
- package/dist/Parser.js.map +1 -0
- package/dist/constants.d.ts +5 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +14 -0
- package/dist/constants.js.map +1 -0
- package/dist/fields.d.ts +14 -0
- package/dist/fields.d.ts.map +1 -0
- package/dist/fields.js +439 -0
- package/dist/fields.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +305 -0
- package/dist/index.js.map +1 -0
- package/dist/productIds.d.ts +9 -0
- package/dist/productIds.d.ts.map +1 -0
- package/dist/productIds.js +95 -0
- package/dist/productIds.js.map +1 -0
- package/dist/serial.d.ts +14 -0
- package/dist/serial.d.ts.map +1 -0
- package/dist/serial.js +106 -0
- package/dist/serial.js.map +1 -0
- package/dist/standalone.d.ts +22 -0
- package/dist/standalone.d.ts.map +1 -0
- package/dist/standalone.js +73 -0
- package/dist/standalone.js.map +1 -0
- package/dist/tcp.d.ts +5 -0
- package/dist/tcp.d.ts.map +1 -0
- package/dist/tcp.js +106 -0
- package/dist/tcp.js.map +1 -0
- package/dist/types.d.ts +181 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/dist/udp.d.ts +5 -0
- package/dist/udp.d.ts.map +1 -0
- package/dist/udp.js +67 -0
- package/dist/udp.js.map +1 -0
- package/docs/screenshots/1_config.png +0 -0
- package/logo.svg +46 -0
- package/package.json +79 -19
- package/.github/FUNDING.yml +0 -1
- package/.travis.yml +0 -13
- package/index.js +0 -159
- package/lib/Parser.js +0 -396
- package/lib/fields.js +0 -503
- package/lib/filestream.js +0 -38
- package/lib/productIds.json +0 -84
- package/lib/serial.js +0 -48
- package/lib/tcp.js +0 -53
- package/lib/udp.js +0 -26
- package/log/one.txt +0 -18
- package/log/run-log.js +0 -7
- package/log/sampleOutput.txt +0 -297
- package/migration.js +0 -57
- package/run.js +0 -10
- package/standalone.js +0 -68
- package/test/index.js +0 -52
- package/todo.md +0 -14
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Standalone library wrapper.
|
|
4
|
+
*
|
|
5
|
+
* Shims the signalk-server host so the plugin can be consumed as a plain
|
|
6
|
+
* Node.js library (see the README "Usage as a library" section). The plugin's
|
|
7
|
+
* `app.handleMessage` deltas are re-emitted as `delta` events on this
|
|
8
|
+
* EventEmitter; functionality is otherwise identical to running inside
|
|
9
|
+
* signalk-server.
|
|
10
|
+
*/
|
|
11
|
+
const events_1 = require("events");
|
|
12
|
+
const createPlugin = require("./index");
|
|
13
|
+
class VEDirect extends events_1.EventEmitter {
|
|
14
|
+
_debug;
|
|
15
|
+
app;
|
|
16
|
+
plugin;
|
|
17
|
+
constructor(config = {}, _debug = false) {
|
|
18
|
+
super();
|
|
19
|
+
this._debug = _debug;
|
|
20
|
+
const options = {
|
|
21
|
+
device: 'Serial',
|
|
22
|
+
connection: '/dev/ttyUSB0',
|
|
23
|
+
port: 7878,
|
|
24
|
+
ignoreChecksum: true,
|
|
25
|
+
mainBatt: 'House',
|
|
26
|
+
auxBatt: 'Starter',
|
|
27
|
+
bmv: 'bmv',
|
|
28
|
+
solar: 'Main',
|
|
29
|
+
...config
|
|
30
|
+
};
|
|
31
|
+
this.app = {
|
|
32
|
+
handleMessage: (kind, data) => {
|
|
33
|
+
// The plugin posts its parsed deltas under its own id; re-emit those as
|
|
34
|
+
// `delta` events. Anything else the host might receive passes through
|
|
35
|
+
// on a channel named for its kind.
|
|
36
|
+
if (kind === this.plugin.id) {
|
|
37
|
+
this.emit('delta', data);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
this.emit(kind, data);
|
|
41
|
+
},
|
|
42
|
+
debug: (msg) => this.debug(msg),
|
|
43
|
+
// The standalone library has no PUT transport, so relay handler
|
|
44
|
+
// registrations are accepted and dropped; the returned no-op unregister
|
|
45
|
+
// keeps start()/stop() symmetric with the server host.
|
|
46
|
+
registerPutHandler: () => () => { },
|
|
47
|
+
options
|
|
48
|
+
};
|
|
49
|
+
this.plugin = createPlugin(this.app);
|
|
50
|
+
this.start();
|
|
51
|
+
}
|
|
52
|
+
start() {
|
|
53
|
+
if (typeof this.plugin.start !== 'function') {
|
|
54
|
+
this.debug("Plugin not initialised, can't start");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
this.plugin.start(this.app.options);
|
|
58
|
+
}
|
|
59
|
+
stop() {
|
|
60
|
+
if (typeof this.plugin.stop !== 'function') {
|
|
61
|
+
this.debug("Plugin not initialised, can't stop");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.plugin.stop();
|
|
65
|
+
}
|
|
66
|
+
debug(...args) {
|
|
67
|
+
if (this._debug) {
|
|
68
|
+
console.log(...args);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
module.exports = VEDirect;
|
|
73
|
+
//# sourceMappingURL=standalone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standalone.js","sourceRoot":"","sources":["../src/standalone.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AACH,mCAAqC;AACrC,wCAAwC;AASxC,MAAM,QAAS,SAAQ,qBAAY;IAChB,MAAM,CAAS;IACf,GAAG,CAA0C;IAC7C,MAAM,CAAQ;IAE/B,YAAY,SAAyB,EAAE,EAAE,MAAM,GAAG,KAAK;QACrD,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QAEpB,MAAM,OAAO,GAAmB;YAC9B,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,cAAc;YAC1B,IAAI,EAAE,IAAI;YACV,cAAc,EAAE,IAAI;YACpB,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,SAAS;YAClB,GAAG,EAAE,KAAK;YACV,KAAK,EAAE,MAAM;YACb,GAAG,MAAM;SACV,CAAA;QAED,IAAI,CAAC,GAAG,GAAG;YACT,aAAa,EAAE,CAAC,IAAY,EAAE,IAAa,EAAE,EAAE;gBAC7C,wEAAwE;gBACxE,sEAAsE;gBACtE,mCAAmC;gBACnC,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;oBAC5B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;oBACxB,OAAM;gBACR,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YACvB,CAAC;YACD,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;YACvC,gEAAgE;YAChE,wEAAwE;YACxE,uDAAuD;YACvD,kBAAkB,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC;YAClC,OAAO;SACR,CAAA;QAED,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACpC,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAED,KAAK;QACH,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YAC5C,IAAI,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAA;YACjD,OAAM;QACR,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAwB,CAAC,CAAA;IACtD,CAAC;IAED,IAAI;QACF,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAA;YAChD,OAAM;QACR,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAA;IACpB,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;CACF;AAED,iBAAS,QAAQ,CAAA"}
|
package/dist/tcp.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { VEDirectParser } from './Parser';
|
|
2
|
+
import type { DebugFn } from './types';
|
|
3
|
+
export declare function connect(host: string, port: number, parser: VEDirectParser[], debug: DebugFn, connectionIndex: number): void;
|
|
4
|
+
export declare function close(debug: DebugFn, connectionIndex: number): void;
|
|
5
|
+
//# sourceMappingURL=tcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp.d.ts","sourceRoot":"","sources":["../src/tcp.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAkDtC,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,cAAc,EAAE,EACxB,KAAK,EAAE,OAAO,EACd,eAAe,EAAE,MAAM,GACtB,IAAI,CAsBN;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,CAanE"}
|
package/dist/tcp.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.connect = connect;
|
|
37
|
+
exports.close = close;
|
|
38
|
+
/**
|
|
39
|
+
* TCP transport.
|
|
40
|
+
*
|
|
41
|
+
* Connects to a host:port that bridges a remote VE.Direct device onto the
|
|
42
|
+
* network and feeds the received bytes into the matching parser. On close the
|
|
43
|
+
* socket is re-dialled after a back-off, unless it was deliberately closed via
|
|
44
|
+
* `close()` (which clears the slot and cancels any pending reconnect).
|
|
45
|
+
*/
|
|
46
|
+
const Net = __importStar(require("net"));
|
|
47
|
+
const RECONNECT_DELAY_MS = 10000;
|
|
48
|
+
const SOCKET_TIMEOUT_MS = 5000;
|
|
49
|
+
const client = [];
|
|
50
|
+
const reconnectTimer = [];
|
|
51
|
+
function makeConnection(host, port, debug, connectionIndex) {
|
|
52
|
+
const socket = new Net.Socket();
|
|
53
|
+
socket.connect({ port, host });
|
|
54
|
+
socket.setTimeout(SOCKET_TIMEOUT_MS);
|
|
55
|
+
debug(`Connection to ${host}:${port}`);
|
|
56
|
+
client[connectionIndex] = socket;
|
|
57
|
+
return socket;
|
|
58
|
+
}
|
|
59
|
+
function onData(msg, parser, debug, connectionIndex) {
|
|
60
|
+
parser[connectionIndex]?.addChunk(msg, connectionIndex);
|
|
61
|
+
debug(`${msg}`);
|
|
62
|
+
}
|
|
63
|
+
function onClose(host, port, parser, debug, connectionIndex) {
|
|
64
|
+
// Only reconnect if the slot is still active (not cleared by close()). The
|
|
65
|
+
// timer handle is tracked so close() can cancel a pending reconnect.
|
|
66
|
+
if (client[connectionIndex] !== undefined) {
|
|
67
|
+
reconnectTimer[connectionIndex] = setTimeout(() => {
|
|
68
|
+
reconnectTimer[connectionIndex] = undefined;
|
|
69
|
+
debug(`Trying to reconnect to ${host}:${port}`);
|
|
70
|
+
connect(host, port, parser, debug, connectionIndex);
|
|
71
|
+
}, RECONNECT_DELAY_MS);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function connect(host, port, parser, debug, connectionIndex) {
|
|
75
|
+
const socket = makeConnection(host, port, debug, connectionIndex);
|
|
76
|
+
socket.on('data', (msg) => {
|
|
77
|
+
onData(msg, parser, debug, connectionIndex);
|
|
78
|
+
});
|
|
79
|
+
socket.on('close', () => {
|
|
80
|
+
debug(`TCP connection to ${host}:${port} closed`);
|
|
81
|
+
socket.destroy();
|
|
82
|
+
onClose(host, port, parser, debug, connectionIndex);
|
|
83
|
+
});
|
|
84
|
+
socket.on('error', (err) => {
|
|
85
|
+
debug(`TCP connection error ${host}:${port}: ${err.message}`);
|
|
86
|
+
socket.destroy();
|
|
87
|
+
});
|
|
88
|
+
socket.on('timeout', () => {
|
|
89
|
+
debug(`TCP connection timeout ${host}:${port}`);
|
|
90
|
+
socket.destroy();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function close(debug, connectionIndex) {
|
|
94
|
+
const timer = reconnectTimer[connectionIndex];
|
|
95
|
+
if (timer !== undefined) {
|
|
96
|
+
clearTimeout(timer);
|
|
97
|
+
reconnectTimer[connectionIndex] = undefined;
|
|
98
|
+
}
|
|
99
|
+
const socket = client[connectionIndex];
|
|
100
|
+
if (socket !== undefined) {
|
|
101
|
+
client[connectionIndex] = undefined;
|
|
102
|
+
socket.destroy();
|
|
103
|
+
debug('TCP port closed');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=tcp.js.map
|
package/dist/tcp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp.js","sourceRoot":"","sources":["../src/tcp.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the vedirect-serial-usb plugin.
|
|
3
|
+
*
|
|
4
|
+
* `SignalKApp` and `Plugin` are minimal structural descriptions of the
|
|
5
|
+
* objects exchanged with the signalk-server host: only the members the
|
|
6
|
+
* plugin actually uses are modelled.
|
|
7
|
+
*
|
|
8
|
+
* The `Field` / `FieldContext` / `StoredField` triple decouples the field
|
|
9
|
+
* definition table (src/fields.ts) from the parser (src/Parser.ts). Field
|
|
10
|
+
* value functions receive a `FieldContext` rather than the concrete parser
|
|
11
|
+
* class, which keeps the two modules free of a runtime import cycle.
|
|
12
|
+
*/
|
|
13
|
+
/** Best-effort log sink. signalk-server passes `app.debug`; the standalone
|
|
14
|
+
* shim and the network modules use the same shape. */
|
|
15
|
+
export type DebugFn = (message: string) => void;
|
|
16
|
+
/**
|
|
17
|
+
* What kind of Victron device a connection talks to. VE.Direct reuses the
|
|
18
|
+
* `V`/`I` labels for both battery monitors and solar chargers, so the device
|
|
19
|
+
* type decides where those readings land (see `Field.solarCharger`). Treated as
|
|
20
|
+
* a battery monitor when unset, which preserves the historical paths.
|
|
21
|
+
*/
|
|
22
|
+
export type DeviceType = 'Battery monitor' | 'Solar charger';
|
|
23
|
+
/** One VE.Direct connection as configured in the plugin schema. */
|
|
24
|
+
export interface VEDirectConnection {
|
|
25
|
+
device: 'Serial' | 'UDP' | 'TCP';
|
|
26
|
+
connection: string;
|
|
27
|
+
port: number;
|
|
28
|
+
deviceType?: DeviceType;
|
|
29
|
+
ignoreChecksum: boolean;
|
|
30
|
+
mainBatt: string;
|
|
31
|
+
auxBatt: string;
|
|
32
|
+
bmv: string;
|
|
33
|
+
solar: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Plugin options. The current schema uses the `vedirect[]` array; the flat
|
|
37
|
+
* fields are the legacy single-connection format kept so that configs
|
|
38
|
+
* written before the multi-connection rework still start (the in-memory
|
|
39
|
+
* fallback in src/index.ts).
|
|
40
|
+
*/
|
|
41
|
+
export interface PluginOptions {
|
|
42
|
+
vedirect?: VEDirectConnection[];
|
|
43
|
+
device?: string;
|
|
44
|
+
host?: string;
|
|
45
|
+
udpPort?: number;
|
|
46
|
+
tcpPort?: number;
|
|
47
|
+
ignoreChecksum?: boolean;
|
|
48
|
+
mainBatt?: string;
|
|
49
|
+
auxBatt?: string;
|
|
50
|
+
bmv?: string;
|
|
51
|
+
solar?: string;
|
|
52
|
+
deviceType?: DeviceType;
|
|
53
|
+
}
|
|
54
|
+
/** Flat single-connection configuration accepted by the standalone library
|
|
55
|
+
* wrapper (src/standalone.ts). */
|
|
56
|
+
export interface VEDirectConfig {
|
|
57
|
+
device?: string;
|
|
58
|
+
connection?: string;
|
|
59
|
+
port?: number;
|
|
60
|
+
host?: string;
|
|
61
|
+
udpPort?: number;
|
|
62
|
+
tcpPort?: number;
|
|
63
|
+
ignoreChecksum?: boolean;
|
|
64
|
+
mainBatt?: string;
|
|
65
|
+
auxBatt?: string;
|
|
66
|
+
bmv?: string;
|
|
67
|
+
solar?: string;
|
|
68
|
+
deviceType?: DeviceType;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Result of a Signal K PUT action. A handler returns `COMPLETED` (with an
|
|
72
|
+
* HTTP-like `statusCode`) to answer synchronously, or `PENDING` when it will
|
|
73
|
+
* call the async callback later. This plugin only answers synchronously.
|
|
74
|
+
*/
|
|
75
|
+
export interface PutResult {
|
|
76
|
+
state: 'COMPLETED' | 'PENDING';
|
|
77
|
+
statusCode?: number;
|
|
78
|
+
message?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Handler for a PUT request on a registered context/path. `value` is whatever
|
|
82
|
+
* the requester sent (hence `unknown`; the handler narrows it). The trailing
|
|
83
|
+
* callback is for `PENDING` async replies and is unused here.
|
|
84
|
+
*/
|
|
85
|
+
export type PutHandler = (context: string, path: string, value: unknown, callback: (result: PutResult) => void) => PutResult | void;
|
|
86
|
+
/** Minimal structural type for the `app` the signalk-server host passes to
|
|
87
|
+
* the plugin factory. */
|
|
88
|
+
export interface SignalKApp {
|
|
89
|
+
handleMessage(id: string, delta: SKDelta): void;
|
|
90
|
+
debug: DebugFn;
|
|
91
|
+
/**
|
|
92
|
+
* Registers a handler for PUT requests on `context`/`path`. Returns a
|
|
93
|
+
* function that unregisters it again, which the plugin calls on `stop()` so a
|
|
94
|
+
* config reload does not leave a stale handler writing to a closed port.
|
|
95
|
+
*/
|
|
96
|
+
registerPutHandler(context: string, path: string, handler: PutHandler, source?: string): () => void;
|
|
97
|
+
}
|
|
98
|
+
/** Shape of the plugin object returned to the signalk-server host. */
|
|
99
|
+
export interface Plugin {
|
|
100
|
+
id: string;
|
|
101
|
+
name: string;
|
|
102
|
+
description: string;
|
|
103
|
+
start(options: PluginOptions): void;
|
|
104
|
+
stop(): void;
|
|
105
|
+
schema: object;
|
|
106
|
+
}
|
|
107
|
+
/** A Signal K delta message emitted for a parsed VE.Direct block.
|
|
108
|
+
*
|
|
109
|
+
* The source is carried as a `$source` ref string (`vedirect-signalk.<index>`)
|
|
110
|
+
* rather than a structured `source` object: a `source.src` field would make
|
|
111
|
+
* signalk-server misclassify the stream as NMEA 2000. See src/Parser.ts. */
|
|
112
|
+
export interface SKDelta {
|
|
113
|
+
context: string;
|
|
114
|
+
updates: Array<{
|
|
115
|
+
$source: string;
|
|
116
|
+
timestamp: string;
|
|
117
|
+
values: Array<{
|
|
118
|
+
path: string;
|
|
119
|
+
value: number | string | null;
|
|
120
|
+
}>;
|
|
121
|
+
}>;
|
|
122
|
+
}
|
|
123
|
+
/** Converts a raw VE.Direct token into a Signal K value. Receives the raw
|
|
124
|
+
* token and the parser (for cross-field lookups and enum decoding). Returns
|
|
125
|
+
* the value to store; `undefined` to skip the field, leaving any prior value
|
|
126
|
+
* untouched; or `null` to store an explicit null, which clears the value in
|
|
127
|
+
* Signal K (e.g. TTG -1, an infinite time-to-go). */
|
|
128
|
+
export type FieldValue = (value: string, instance: FieldContext) => number | string | null | undefined;
|
|
129
|
+
export type FieldType = 'metric' | 'ratio' | 'text' | 'boolean' | 'count';
|
|
130
|
+
/**
|
|
131
|
+
* Identifies which configured device name fills a field path's `*` placeholder.
|
|
132
|
+
* `mainBatt`/`auxBatt`/`bmv`/`solar` map to the per-connection config;
|
|
133
|
+
* `aux2Batt`/`inverter` have no config slot and fall back to the parser's
|
|
134
|
+
* `defaultUnitId`. Keeping this a union (rather than `string`) ties the field
|
|
135
|
+
* table to the resolver in `getPath`: adding a new unit here forces the switch
|
|
136
|
+
* there to handle it.
|
|
137
|
+
*/
|
|
138
|
+
export type UnitId = 'mainBatt' | 'auxBatt' | 'aux2Batt' | 'bmv' | 'solar' | 'inverter';
|
|
139
|
+
/** A field definition: how to name, place and convert one VE.Direct token. */
|
|
140
|
+
export interface Field {
|
|
141
|
+
name: string;
|
|
142
|
+
path?: string;
|
|
143
|
+
unitId?: UnitId;
|
|
144
|
+
/**
|
|
145
|
+
* Alternative path and unit used when the connection is a solar charger.
|
|
146
|
+
* VE.Direct sends battery-monitor and charger data under the same labels, but
|
|
147
|
+
* a charger's reading describes its DC output, which belongs under
|
|
148
|
+
* electrical.solar, not electrical.batteries where it would clash with a
|
|
149
|
+
* monitor on the same bank.
|
|
150
|
+
*/
|
|
151
|
+
solarCharger?: {
|
|
152
|
+
path: string;
|
|
153
|
+
unitId: UnitId;
|
|
154
|
+
};
|
|
155
|
+
units?: string;
|
|
156
|
+
type?: FieldType;
|
|
157
|
+
value?: FieldValue;
|
|
158
|
+
}
|
|
159
|
+
export type FieldMap = Record<string, Field>;
|
|
160
|
+
/** A field whose `value` has been resolved to a concrete reading and stored
|
|
161
|
+
* on the parser. */
|
|
162
|
+
export interface StoredField {
|
|
163
|
+
name: string;
|
|
164
|
+
value: number | string | null;
|
|
165
|
+
path?: string;
|
|
166
|
+
unitId?: UnitId;
|
|
167
|
+
units?: string;
|
|
168
|
+
type?: FieldType;
|
|
169
|
+
}
|
|
170
|
+
/** The slice of the parser that field value functions are allowed to call.
|
|
171
|
+
* Implemented by VEDirectParser. */
|
|
172
|
+
export interface FieldContext {
|
|
173
|
+
set(key: string, value: StoredField): void;
|
|
174
|
+
getAlarmReason(value: string | number): string | undefined;
|
|
175
|
+
getErrorString(value: string | number): string | undefined;
|
|
176
|
+
getStateOfOperation(value: string | number): string | undefined;
|
|
177
|
+
getMode(value: string | number): string | undefined;
|
|
178
|
+
getTrackerOperationMode(value: string | number): string | undefined;
|
|
179
|
+
getProductLongname(value: string): string;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared types for the vedirect-serial-usb plugin.
|
|
4
|
+
*
|
|
5
|
+
* `SignalKApp` and `Plugin` are minimal structural descriptions of the
|
|
6
|
+
* objects exchanged with the signalk-server host: only the members the
|
|
7
|
+
* plugin actually uses are modelled.
|
|
8
|
+
*
|
|
9
|
+
* The `Field` / `FieldContext` / `StoredField` triple decouples the field
|
|
10
|
+
* definition table (src/fields.ts) from the parser (src/Parser.ts). Field
|
|
11
|
+
* value functions receive a `FieldContext` rather than the concrete parser
|
|
12
|
+
* class, which keeps the two modules free of a runtime import cycle.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG"}
|
package/dist/udp.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { VEDirectParser } from './Parser';
|
|
2
|
+
import type { DebugFn } from './types';
|
|
3
|
+
export declare function listen(port: number, parser: VEDirectParser[], debug: DebugFn, connectionIndex: number): void;
|
|
4
|
+
export declare function close(debug: DebugFn, connectionIndex: number): void;
|
|
5
|
+
//# sourceMappingURL=udp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"udp.d.ts","sourceRoot":"","sources":["../src/udp.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAItC,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,cAAc,EAAE,EACxB,KAAK,EAAE,OAAO,EACd,eAAe,EAAE,MAAM,GACtB,IAAI,CAcN;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,CAOnE"}
|
package/dist/udp.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.listen = listen;
|
|
37
|
+
exports.close = close;
|
|
38
|
+
/**
|
|
39
|
+
* UDP transport.
|
|
40
|
+
*
|
|
41
|
+
* Binds a UDP socket per connection index and feeds each received datagram
|
|
42
|
+
* into the matching parser. Used when a bridge forwards a remote VE.Direct
|
|
43
|
+
* device's serial data as UDP packets.
|
|
44
|
+
*/
|
|
45
|
+
const dgram = __importStar(require("dgram"));
|
|
46
|
+
const socket = [];
|
|
47
|
+
function listen(port, parser, debug, connectionIndex) {
|
|
48
|
+
const sock = dgram.createSocket({ type: 'udp4', reuseAddr: true });
|
|
49
|
+
socket[connectionIndex] = sock;
|
|
50
|
+
sock.on('listening', () => {
|
|
51
|
+
debug(`listening on UDP ${port}`);
|
|
52
|
+
});
|
|
53
|
+
sock.on('message', (msg, rinfo) => {
|
|
54
|
+
debug(`${rinfo.address}:${rinfo.port}:${msg}`);
|
|
55
|
+
parser[connectionIndex]?.addChunk(msg, connectionIndex);
|
|
56
|
+
});
|
|
57
|
+
sock.bind(port);
|
|
58
|
+
}
|
|
59
|
+
function close(debug, connectionIndex) {
|
|
60
|
+
const sock = socket[connectionIndex];
|
|
61
|
+
if (sock !== undefined) {
|
|
62
|
+
sock.close();
|
|
63
|
+
socket[connectionIndex] = undefined;
|
|
64
|
+
debug('UDP port closed');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=udp.js.map
|
package/dist/udp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"udp.js","sourceRoot":"","sources":["../src/udp.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,wBAmBC;AAED,sBAOC;AAzCD;;;;;;GAMG;AACH,6CAA8B;AAI9B,MAAM,MAAM,GAAiC,EAAE,CAAA;AAE/C,SAAgB,MAAM,CACpB,IAAY,EACZ,MAAwB,EACxB,KAAc,EACd,eAAuB;IAEvB,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAClE,MAAM,CAAC,eAAe,CAAC,GAAG,IAAI,CAAA;IAE9B,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;QACxB,KAAK,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAW,EAAE,KAAuB,EAAE,EAAE;QAC1D,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC,CAAA;QAC9C,MAAM,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACjB,CAAC;AAED,SAAgB,KAAK,CAAC,KAAc,EAAE,eAAuB;IAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,eAAe,CAAC,CAAA;IACpC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,MAAM,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;QACnC,KAAK,CAAC,iBAAiB,CAAC,CAAA;IAC1B,CAAC;AACH,CAAC"}
|
|
Binary file
|
package/logo.svg
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-label="Victron VE.Direct">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="sea" x1="0" y1="0" x2="0" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#1b6ea8"/>
|
|
5
|
+
<stop offset="1" stop-color="#0b3a5e"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<clipPath id="card">
|
|
8
|
+
<rect x="0" y="0" width="128" height="128" rx="22"/>
|
|
9
|
+
</clipPath>
|
|
10
|
+
</defs>
|
|
11
|
+
|
|
12
|
+
<g clip-path="url(#card)">
|
|
13
|
+
<rect width="128" height="128" fill="url(#sea)"/>
|
|
14
|
+
|
|
15
|
+
<g stroke="#bee3f4" stroke-opacity="0.25" stroke-width="1" fill="none">
|
|
16
|
+
<path d="M0 24 H128 M0 48 H128 M0 72 H128 M0 96 H128"/>
|
|
17
|
+
<path d="M24 0 V128 M48 0 V128 M72 0 V128 M96 0 V128"/>
|
|
18
|
+
</g>
|
|
19
|
+
|
|
20
|
+
<!-- Victron-style energy waves radiating from the device -->
|
|
21
|
+
<g stroke="#35aee0" stroke-width="2.8" fill="none" stroke-linecap="round">
|
|
22
|
+
<path d="M53 37 Q61 29 69 37"/>
|
|
23
|
+
<path d="M48 37 Q61 23 74 37"/>
|
|
24
|
+
<path d="M43 37 Q61 17 79 37"/>
|
|
25
|
+
</g>
|
|
26
|
+
|
|
27
|
+
<!-- battery (monitor / charger that VE.Direct reads) -->
|
|
28
|
+
<rect x="53" y="40" width="16" height="7" rx="2.5" fill="#cbd5e1" stroke="#0b3a5e" stroke-width="2"/>
|
|
29
|
+
<rect x="40" y="47" width="42" height="56" rx="7" fill="#e7eef5" stroke="#0b3a5e" stroke-width="2.6"/>
|
|
30
|
+
<!-- charge level -->
|
|
31
|
+
<path d="M44 73 H78 V95 Q78 99 74 99 H48 Q44 99 44 95 Z" fill="#1f9bd7"/>
|
|
32
|
+
|
|
33
|
+
<!-- charge bolt -->
|
|
34
|
+
<polygon points="65,53 52,79 60,79 56,98 75,71 64,71 70,53" fill="#e63946" stroke="#0b3a5e" stroke-width="1.6" stroke-linejoin="round"/>
|
|
35
|
+
|
|
36
|
+
<!-- compass rose -->
|
|
37
|
+
<g transform="translate(104 104)">
|
|
38
|
+
<circle r="11" fill="#0b3a5e" fill-opacity="0.7" stroke="#bee3f4" stroke-width="0.8"/>
|
|
39
|
+
<polygon points="0,-9 2.2,0 0,0" fill="#e63946"/>
|
|
40
|
+
<polygon points="0,-9 -2.2,0 0,0" fill="#b5232f"/>
|
|
41
|
+
<polygon points="0,9 2.2,0 0,0" fill="#e2e8f0"/>
|
|
42
|
+
<polygon points="0,9 -2.2,0 0,0" fill="#cbd5e1"/>
|
|
43
|
+
<circle r="1.1" fill="#e2e8f0"/>
|
|
44
|
+
</g>
|
|
45
|
+
</g>
|
|
46
|
+
</svg>
|
package/package.json
CHANGED
|
@@ -1,12 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signalk/vedirect-serial-usb",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Signal K Node.js server plugin to read VE.Direct data via serial USB",
|
|
5
|
-
"main": "index.js",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./standalone": {
|
|
14
|
+
"types": "./dist/standalone.d.ts",
|
|
15
|
+
"require": "./dist/standalone.js",
|
|
16
|
+
"default": "./dist/standalone.js"
|
|
17
|
+
},
|
|
18
|
+
"./package.json": "./package.json"
|
|
19
|
+
},
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"logo.svg",
|
|
27
|
+
"docs/screenshots",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE"
|
|
30
|
+
],
|
|
31
|
+
"signalk": {
|
|
32
|
+
"displayName": "Victron VE.Direct",
|
|
33
|
+
"appIcon": "./logo.svg",
|
|
34
|
+
"screenshots": [
|
|
35
|
+
"./docs/screenshots/1_config.png"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
6
38
|
"scripts": {
|
|
39
|
+
"build": "tsc -p tsconfig.build.json",
|
|
40
|
+
"clean": "rimraf dist",
|
|
41
|
+
"prebuild": "npm run clean",
|
|
42
|
+
"typecheck": "tsc --noEmit",
|
|
7
43
|
"test": "mocha",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
44
|
+
"coverage": "c8 --reporter=text --reporter=lcov npm test",
|
|
45
|
+
"mutation": "stryker run",
|
|
46
|
+
"prettier:check": "prettier --check .",
|
|
47
|
+
"prettier": "prettier --write .",
|
|
48
|
+
"format": "npm run prettier",
|
|
49
|
+
"prepublishOnly": "npm run build"
|
|
10
50
|
},
|
|
11
51
|
"keywords": [
|
|
12
52
|
"signalk-node-server-plugin"
|
|
@@ -21,23 +61,43 @@
|
|
|
21
61
|
"type": "git",
|
|
22
62
|
"url": "https://github.com/SignalK/vedirect-serial-usb"
|
|
23
63
|
},
|
|
24
|
-
"contributors": [],
|
|
25
64
|
"dependencies": {
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"serialport": "^
|
|
29
|
-
},
|
|
30
|
-
"standard": {
|
|
31
|
-
"globals": [
|
|
32
|
-
"describe",
|
|
33
|
-
"it",
|
|
34
|
-
"expect",
|
|
35
|
-
"before"
|
|
36
|
-
]
|
|
65
|
+
"@serialport/parser-delimiter": "^13.0.0",
|
|
66
|
+
"debug": "^4.4.3",
|
|
67
|
+
"serialport": "^13.0.0"
|
|
37
68
|
},
|
|
38
69
|
"devDependencies": {
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
70
|
+
"@stryker-mutator/core": "^9.6.1",
|
|
71
|
+
"@stryker-mutator/mocha-runner": "^9.6.1",
|
|
72
|
+
"@types/chai": "^5.2.3",
|
|
73
|
+
"@types/debug": "^4.1.12",
|
|
74
|
+
"@types/mocha": "^10.0.10",
|
|
75
|
+
"@types/node": "^25.9.2",
|
|
76
|
+
"c8": "^11.0.0",
|
|
77
|
+
"chai": "^6.2.2",
|
|
78
|
+
"mocha": "^11.7.1",
|
|
79
|
+
"prettier": "^3.8.2",
|
|
80
|
+
"rimraf": "^6.1.3",
|
|
81
|
+
"tsx": "^4.21.0",
|
|
82
|
+
"typescript": "^6.0.3"
|
|
83
|
+
},
|
|
84
|
+
"c8": {
|
|
85
|
+
"extension": [
|
|
86
|
+
".ts"
|
|
87
|
+
],
|
|
88
|
+
"include": [
|
|
89
|
+
"src/**/*.ts"
|
|
90
|
+
],
|
|
91
|
+
"exclude": [
|
|
92
|
+
"test/**",
|
|
93
|
+
"coverage/**",
|
|
94
|
+
"dist/**",
|
|
95
|
+
"src/types.ts"
|
|
96
|
+
],
|
|
97
|
+
"all": true,
|
|
98
|
+
"reporter": [
|
|
99
|
+
"text",
|
|
100
|
+
"lcov"
|
|
101
|
+
]
|
|
42
102
|
}
|
|
43
103
|
}
|
package/.github/FUNDING.yml
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
github: joabakk
|