@signalk/vedirect-serial-usb 1.5.0 → 1.6.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 +13 -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 +438 -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 +209 -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 +5 -0
- package/dist/serial.d.ts.map +1 -0
- package/dist/serial.js +78 -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 +69 -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 +159 -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
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
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
|
+
/** Minimal structural type for the `app` the signalk-server host passes to
|
|
71
|
+
* the plugin factory. */
|
|
72
|
+
export interface SignalKApp {
|
|
73
|
+
handleMessage(id: string, delta: SKDelta): void;
|
|
74
|
+
debug: DebugFn;
|
|
75
|
+
}
|
|
76
|
+
/** Shape of the plugin object returned to the signalk-server host. */
|
|
77
|
+
export interface Plugin {
|
|
78
|
+
id: string;
|
|
79
|
+
name: string;
|
|
80
|
+
description: string;
|
|
81
|
+
start(options: PluginOptions): void;
|
|
82
|
+
stop(): void;
|
|
83
|
+
schema: object;
|
|
84
|
+
}
|
|
85
|
+
/** A Signal K delta message emitted for a parsed VE.Direct block.
|
|
86
|
+
*
|
|
87
|
+
* The source is carried as a `$source` ref string (`vedirect-signalk.<index>`)
|
|
88
|
+
* rather than a structured `source` object: a `source.src` field would make
|
|
89
|
+
* signalk-server misclassify the stream as NMEA 2000. See src/Parser.ts. */
|
|
90
|
+
export interface SKDelta {
|
|
91
|
+
context: string;
|
|
92
|
+
updates: Array<{
|
|
93
|
+
$source: string;
|
|
94
|
+
timestamp: string;
|
|
95
|
+
values: Array<{
|
|
96
|
+
path: string;
|
|
97
|
+
value: number | string | null;
|
|
98
|
+
}>;
|
|
99
|
+
}>;
|
|
100
|
+
}
|
|
101
|
+
/** Converts a raw VE.Direct token into a Signal K value. Receives the raw
|
|
102
|
+
* token and the parser (for cross-field lookups and enum decoding). Returns
|
|
103
|
+
* the value to store; `undefined` to skip the field, leaving any prior value
|
|
104
|
+
* untouched; or `null` to store an explicit null, which clears the value in
|
|
105
|
+
* Signal K (e.g. TTG -1, an infinite time-to-go). */
|
|
106
|
+
export type FieldValue = (value: string, instance: FieldContext) => number | string | null | undefined;
|
|
107
|
+
export type FieldType = 'metric' | 'ratio' | 'text' | 'boolean' | 'count';
|
|
108
|
+
/**
|
|
109
|
+
* Identifies which configured device name fills a field path's `*` placeholder.
|
|
110
|
+
* `mainBatt`/`auxBatt`/`bmv`/`solar` map to the per-connection config;
|
|
111
|
+
* `aux2Batt`/`inverter` have no config slot and fall back to the parser's
|
|
112
|
+
* `defaultUnitId`. Keeping this a union (rather than `string`) ties the field
|
|
113
|
+
* table to the resolver in `getPath`: adding a new unit here forces the switch
|
|
114
|
+
* there to handle it.
|
|
115
|
+
*/
|
|
116
|
+
export type UnitId = 'mainBatt' | 'auxBatt' | 'aux2Batt' | 'bmv' | 'solar' | 'inverter';
|
|
117
|
+
/** A field definition: how to name, place and convert one VE.Direct token. */
|
|
118
|
+
export interface Field {
|
|
119
|
+
name: string;
|
|
120
|
+
path?: string;
|
|
121
|
+
unitId?: UnitId;
|
|
122
|
+
/**
|
|
123
|
+
* Alternative path and unit used when the connection is a solar charger.
|
|
124
|
+
* VE.Direct sends battery-monitor and charger data under the same labels, but
|
|
125
|
+
* a charger's reading describes its DC output, which belongs under
|
|
126
|
+
* electrical.solar, not electrical.batteries where it would clash with a
|
|
127
|
+
* monitor on the same bank.
|
|
128
|
+
*/
|
|
129
|
+
solarCharger?: {
|
|
130
|
+
path: string;
|
|
131
|
+
unitId: UnitId;
|
|
132
|
+
};
|
|
133
|
+
units?: string;
|
|
134
|
+
type?: FieldType;
|
|
135
|
+
value?: FieldValue;
|
|
136
|
+
}
|
|
137
|
+
export type FieldMap = Record<string, Field>;
|
|
138
|
+
/** A field whose `value` has been resolved to a concrete reading and stored
|
|
139
|
+
* on the parser. */
|
|
140
|
+
export interface StoredField {
|
|
141
|
+
name: string;
|
|
142
|
+
value: number | string | null;
|
|
143
|
+
path?: string;
|
|
144
|
+
unitId?: UnitId;
|
|
145
|
+
units?: string;
|
|
146
|
+
type?: FieldType;
|
|
147
|
+
}
|
|
148
|
+
/** The slice of the parser that field value functions are allowed to call.
|
|
149
|
+
* Implemented by VEDirectParser. */
|
|
150
|
+
export interface FieldContext {
|
|
151
|
+
set(key: string, value: StoredField): void;
|
|
152
|
+
getAlarmReason(value: string | number): string | undefined;
|
|
153
|
+
getErrorString(value: string | number): string | undefined;
|
|
154
|
+
getStateOfOperation(value: string | number): string | undefined;
|
|
155
|
+
getMode(value: string | number): string | undefined;
|
|
156
|
+
getTrackerOperationMode(value: string | number): string | undefined;
|
|
157
|
+
getProductLongname(value: string): string;
|
|
158
|
+
}
|
|
159
|
+
//# 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.6.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": "^4.3.20",
|
|
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
|
package/.travis.yml
DELETED
package/index.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
const serial = require('./lib/serial')
|
|
2
|
-
const udp = require('./lib/udp')
|
|
3
|
-
const tcp = require('./lib/tcp')
|
|
4
|
-
const Parser = require('./lib/Parser')
|
|
5
|
-
const VEDirect = require('./standalone')
|
|
6
|
-
|
|
7
|
-
module.exports = function (app) {
|
|
8
|
-
let parser = []
|
|
9
|
-
let shaddow = null
|
|
10
|
-
const plugin = {}
|
|
11
|
-
plugin.id = 'vedirect-signalk'
|
|
12
|
-
plugin.name = 'VE.Direct to Signal K'
|
|
13
|
-
plugin.description = plugin.name
|
|
14
|
-
|
|
15
|
-
plugin.start = function (options) {
|
|
16
|
-
shaddow = options;
|
|
17
|
-
|
|
18
|
-
if (typeof options.vedirect !== 'undefined') {
|
|
19
|
-
Object.keys(options.vedirect).forEach(items => {
|
|
20
|
-
parser[items] = new Parser(options)
|
|
21
|
-
|
|
22
|
-
parser[items].on('delta', delta => {
|
|
23
|
-
app.handleMessage('pluginId', delta)
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
let type = options.vedirect[items].device;
|
|
27
|
-
let connection = options.vedirect[items].connection;
|
|
28
|
-
let port = options.vedirect[items].port;
|
|
29
|
-
if (type == 'Serial') {
|
|
30
|
-
serial.open(connection, parser, app.debug, items)
|
|
31
|
-
} else if (type == 'UDP') {
|
|
32
|
-
udp.listen(port, parser, app.debug, items)
|
|
33
|
-
} else if (type == 'TCP') {
|
|
34
|
-
tcp.connect(connection, port, parser, app.debug, items)
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
} else {
|
|
38
|
-
if (options.device) {
|
|
39
|
-
oldConfig = {vedirect: [{device: 'Serial', connection: options.device, ignoreChecksum: options.ignoreChecksum,
|
|
40
|
-
mainBatt: options.mainBatt, auxBatt: options.auxBatt, bmv: options.bmv, solar: options.solar}]}
|
|
41
|
-
} else if (options.udpPort) {
|
|
42
|
-
oldConfig = {vedirect: [{device: 'UDP', port: options.udpPort, ignoreChecksum: options.ignoreChecksum,
|
|
43
|
-
mainBatt: options.mainBatt, auxBatt: options.auxBatt, bmv: options.bmv, solar: options.solar}]}
|
|
44
|
-
} else if (options.host) {
|
|
45
|
-
oldConfig = {vedirect: [{device: 'TCP', connection: options.host, port: options.tcpPort, ignoreChecksum: options.ignoreChecksum,
|
|
46
|
-
mainBatt: options.mainBatt, auxBatt: options.auxBatt, bmv: options.bmv, solar: options.solar}]}
|
|
47
|
-
}
|
|
48
|
-
parser[0] = new Parser(oldConfig)
|
|
49
|
-
|
|
50
|
-
parser[0].on('delta', delta => {
|
|
51
|
-
app.handleMessage('pluginId', delta)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
if (options.device) {
|
|
55
|
-
serial.open(options.device, parser, app.debug, 0)
|
|
56
|
-
} else if (options.udpPort) {
|
|
57
|
-
udp.listen(options.udpPort, parser, app.debug, 0)
|
|
58
|
-
} else if (options.host) {
|
|
59
|
-
tcp.connect(options.host, options.tcpPort, parser, app.debug, 0)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
plugin.stop = function () {
|
|
65
|
-
if (shaddow) {
|
|
66
|
-
if (typeof shaddow.vedirect !== 'undefined') {
|
|
67
|
-
Object.keys(shaddow.vedirect).forEach(items => {
|
|
68
|
-
parser[items].removeAllListeners()
|
|
69
|
-
parser[items] = null
|
|
70
|
-
let type = shaddow.vedirect[items].device;
|
|
71
|
-
if (type == 'Serial') {
|
|
72
|
-
serial.close(app.debug, items)
|
|
73
|
-
} else if (type == 'UDP') {
|
|
74
|
-
udp.close(app.debug, items)
|
|
75
|
-
} else {
|
|
76
|
-
tcp.close(app.debug, items)
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
} else {
|
|
80
|
-
parser[0].removeAllListeners()
|
|
81
|
-
parser[0] = null
|
|
82
|
-
if (shaddow.device) {
|
|
83
|
-
serial.close(app.debug, 0)
|
|
84
|
-
} else if (shaddow.udpPort) {
|
|
85
|
-
udp.close(app.debug, 0)
|
|
86
|
-
} else if (shaddow.host) {
|
|
87
|
-
tcp.close(app.debug, 0)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
shaddow = null
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
plugin.schema = {
|
|
95
|
-
type: 'object',
|
|
96
|
-
properties: {
|
|
97
|
-
vedirect: {
|
|
98
|
-
type: 'array',
|
|
99
|
-
title: 'Connections',
|
|
100
|
-
description: 'Connections to VE.Direct devices',
|
|
101
|
-
items: {
|
|
102
|
-
type: 'object',
|
|
103
|
-
required: [],
|
|
104
|
-
properties: {
|
|
105
|
-
device: {
|
|
106
|
-
type: 'string',
|
|
107
|
-
default: 'Serial',
|
|
108
|
-
title: 'Select device',
|
|
109
|
-
enum: [
|
|
110
|
-
'Serial',
|
|
111
|
-
'UDP',
|
|
112
|
-
'TCP',
|
|
113
|
-
],
|
|
114
|
-
},
|
|
115
|
-
connection: {
|
|
116
|
-
type: 'string',
|
|
117
|
-
title: 'Connection details',
|
|
118
|
-
description: 'Serial: e.g. /dev/ttyUSB0, UDP: ignored or TCP: IP address',
|
|
119
|
-
default: '/dev/ttyUSB0'
|
|
120
|
-
},
|
|
121
|
-
port: {
|
|
122
|
-
type: 'number',
|
|
123
|
-
title: 'Port',
|
|
124
|
-
description: 'Serial: ignored, UDP/TCP: port',
|
|
125
|
-
default: 7878
|
|
126
|
-
},
|
|
127
|
-
ignoreChecksum: {
|
|
128
|
-
type: 'boolean',
|
|
129
|
-
title: 'Ignore Checksum',
|
|
130
|
-
default: true
|
|
131
|
-
},
|
|
132
|
-
mainBatt: {
|
|
133
|
-
type: 'string',
|
|
134
|
-
title: 'Main Battery name in SK path',
|
|
135
|
-
default: 'House'
|
|
136
|
-
},
|
|
137
|
-
auxBatt: {
|
|
138
|
-
type: 'string',
|
|
139
|
-
title: 'Aux Battery name in SK path',
|
|
140
|
-
default: 'Starter'
|
|
141
|
-
},
|
|
142
|
-
bmv: {
|
|
143
|
-
type: 'string',
|
|
144
|
-
title: 'BMV name in SK path',
|
|
145
|
-
default: 'bmv'
|
|
146
|
-
},
|
|
147
|
-
solar: {
|
|
148
|
-
type: 'string',
|
|
149
|
-
title: 'Solar name in SK path',
|
|
150
|
-
default: 'Main'
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return plugin
|
|
159
|
-
}
|