@enyo-energy/energy-app-sdk 1.7.0 → 1.9.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/README.md +80 -0
- package/dist/cjs/energy-app-package-definition.d.cts +12 -0
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.d.cts +1 -0
- package/dist/cjs/packages/energy-app-modbus.cjs +64 -0
- package/dist/cjs/packages/energy-app-modbus.d.cts +159 -0
- package/dist/cjs/types/enyo-appliance-command-forecast.cjs +9 -3
- package/dist/cjs/types/enyo-appliance-command-forecast.d.cts +15 -8
- package/dist/cjs/types/enyo-appliance.cjs +9 -1
- package/dist/cjs/types/enyo-appliance.d.cts +11 -3
- package/dist/cjs/types/enyo-data-bus-value.cjs +14 -6
- package/dist/cjs/types/enyo-data-bus-value.d.cts +21 -11
- package/dist/cjs/types/enyo-onboarding-v2.d.cts +1 -16
- package/dist/cjs/types/enyo-onboarding.cjs +3 -5
- package/dist/cjs/types/enyo-onboarding.d.cts +3 -5
- package/dist/cjs/version.cjs +1 -1
- package/dist/cjs/version.d.cts +1 -1
- package/dist/energy-app-package-definition.d.ts +12 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/packages/energy-app-modbus.d.ts +159 -0
- package/dist/packages/energy-app-modbus.js +62 -1
- package/dist/types/enyo-appliance-command-forecast.d.ts +15 -8
- package/dist/types/enyo-appliance-command-forecast.js +9 -3
- package/dist/types/enyo-appliance.d.ts +11 -3
- package/dist/types/enyo-appliance.js +9 -1
- package/dist/types/enyo-data-bus-value.d.ts +21 -11
- package/dist/types/enyo-data-bus-value.js +14 -6
- package/dist/types/enyo-onboarding-v2.d.ts +1 -16
- package/dist/types/enyo-onboarding.d.ts +3 -5
- package/dist/types/enyo-onboarding.js +3 -5
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -571,6 +571,86 @@ const registers = await client.readHoldingRegisters(1001, 10);
|
|
|
571
571
|
await client.writeSingleRegister(2001, 500);
|
|
572
572
|
```
|
|
573
573
|
|
|
574
|
+
##### Exceptions are data, not just failures
|
|
575
|
+
|
|
576
|
+
When a device *answers* but refuses an operation, the call rejects with a `ModbusExceptionError`
|
|
577
|
+
carrying the device's raw exception code. That is different from a timeout or a dropped socket, and
|
|
578
|
+
the distinction is the whole point: a permission probe is a write you expect to be refused.
|
|
579
|
+
|
|
580
|
+
```typescript
|
|
581
|
+
import {ModbusExceptionError} from '@enyo-energy/energy-app-sdk';
|
|
582
|
+
|
|
583
|
+
// May this connection write at all? Write a register back its own value and see.
|
|
584
|
+
const current = (await client.readHoldingRegisters(43006, 1)).readUInt16BE(0);
|
|
585
|
+
try {
|
|
586
|
+
await client.writeSingleRegister(43006, current);
|
|
587
|
+
controlAllowed = true; // the write landed
|
|
588
|
+
} catch (error) {
|
|
589
|
+
if (error instanceof ModbusExceptionError) {
|
|
590
|
+
controlAllowed = false; // refused by the device, e.g. code 0x80
|
|
591
|
+
} else {
|
|
592
|
+
throw error; // the link is broken — a different problem
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
Vendor-specific codes are passed through unvalidated (Huawei answers `0x80` for "permission
|
|
598
|
+
authentication failure or permission expiration", which is outside the standard `0x01`…`0x0B`
|
|
599
|
+
range). An exception response never recycles the socket.
|
|
600
|
+
|
|
601
|
+
##### Vendor function codes: `sendRawPdu()`
|
|
602
|
+
|
|
603
|
+
Some devices reserve a function code of their own for things the standard eight codes cannot
|
|
604
|
+
express — most commonly an installer login that must succeed before any control write is accepted.
|
|
605
|
+
`sendRawPdu()` puts one PDU on the wire verbatim and hands back the raw answer, on the connection
|
|
606
|
+
the SDK already owns:
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
const response = await client.sendRawPdu(0x41, Buffer.from([0x24, ...challengeBytes]));
|
|
610
|
+
|
|
611
|
+
if (response.exceptionCode !== undefined) {
|
|
612
|
+
// The device refused. Expected often enough that it is a result, not a throw.
|
|
613
|
+
console.warn(`Vendor command refused with 0x${response.exceptionCode.toString(16)}`);
|
|
614
|
+
} else {
|
|
615
|
+
parseVendorReply(response.payload);
|
|
616
|
+
}
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
- The SDK knows nothing about the vendor. Sub-commands, digests and keepalives stay in your app.
|
|
620
|
+
- The call queues on the same per-connection chain as every other request, so `noParallelRequests`
|
|
621
|
+
and `waitBetweenMessagesMs` hold — a login can never interleave with a block read that is already
|
|
622
|
+
in flight.
|
|
623
|
+
- Request payloads are **never logged**; only the function code and the payload length are. Vendor
|
|
624
|
+
handshakes carry credential digests.
|
|
625
|
+
- Payloads are capped at `MODBUS_MAX_PDU_PAYLOAD_BYTES` (252), keeping the frame inside the 253-byte
|
|
626
|
+
Modbus PDU limit. Function codes must be 1…127.
|
|
627
|
+
- It needs the same `Modbus` permission as the rest of the Modbus surface — an app that can already
|
|
628
|
+
call `writeMultipleRegisters` can write any holding register, so this grants reach, not privilege.
|
|
629
|
+
|
|
630
|
+
##### Knowing when the socket was replaced
|
|
631
|
+
|
|
632
|
+
Anything the device tracks per *connection* rather than per device — a vendor login above all — dies
|
|
633
|
+
silently when the socket is recycled. The next write simply comes back refused. `onReconnect()` is
|
|
634
|
+
the signal that lets you re-establish it beforehand:
|
|
635
|
+
|
|
636
|
+
```typescript
|
|
637
|
+
const stopListening = client.onReconnect(() => {
|
|
638
|
+
// Permission was granted to the old socket and is gone with it.
|
|
639
|
+
authenticated = false;
|
|
640
|
+
void loginAgain();
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
// Or check after the fact, without keeping a listener alive:
|
|
644
|
+
const before = client.connectionGeneration();
|
|
645
|
+
await doSomething();
|
|
646
|
+
if (client.connectionGeneration() !== before) {
|
|
647
|
+
// The socket was replaced in the meantime; connection-scoped state is void.
|
|
648
|
+
}
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
Listeners are dropped automatically on `disconnect()`, and `onReconnect()` returns a function that
|
|
652
|
+
removes just yours.
|
|
653
|
+
|
|
574
654
|
#### `useOcpp(): EnergyAppOcpp`
|
|
575
655
|
|
|
576
656
|
Handle OCPP charging station communication:
|
|
@@ -261,6 +261,18 @@ export interface EnergyAppPackageCompatibilityVendor {
|
|
|
261
261
|
vendorName: string;
|
|
262
262
|
/** Models from this vendor that the package supports */
|
|
263
263
|
models: EnergyAppPackageCompatibilityModel[];
|
|
264
|
+
/**
|
|
265
|
+
* Marks this package as the default Energy App for the vendor when no
|
|
266
|
+
* concrete model has been selected.
|
|
267
|
+
*
|
|
268
|
+
* During onboarding a user may only know the manufacturer of their device,
|
|
269
|
+
* not its exact model. When several packages declare compatibility with the
|
|
270
|
+
* same vendor, the one flagged with `default: true` is the app the enyo
|
|
271
|
+
* Store and onboarding flows pick in that case. Set it on at most one
|
|
272
|
+
* package per vendor; omit it (or set `false`) when the package should only
|
|
273
|
+
* be offered for an explicitly selected model.
|
|
274
|
+
*/
|
|
275
|
+
defaultEnergyApp?: boolean;
|
|
264
276
|
}
|
|
265
277
|
/**
|
|
266
278
|
* A file published together with an Energy App package and served publicly
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -56,6 +56,7 @@ __exportStar(require("./implementations/data-bus/data-bus-command-handler.cjs"),
|
|
|
56
56
|
__exportStar(require("./types/enyo-currency.cjs"), exports);
|
|
57
57
|
__exportStar(require("./packages/energy-app-sequence-generator.cjs"), exports);
|
|
58
58
|
__exportStar(require("./packages/energy-app-energy-prices.cjs"), exports);
|
|
59
|
+
__exportStar(require("./packages/energy-app-modbus.cjs"), exports);
|
|
59
60
|
__exportStar(require("./packages/energy-app-modbus-rtu.cjs"), exports);
|
|
60
61
|
__exportStar(require("./types/enyo-modbus-server.cjs"), exports);
|
|
61
62
|
__exportStar(require("./packages/energy-app-modbus-server.cjs"), exports);
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -40,6 +40,7 @@ export * from './implementations/data-bus/data-bus-command-handler.cjs';
|
|
|
40
40
|
export * from './types/enyo-currency.cjs';
|
|
41
41
|
export * from './packages/energy-app-sequence-generator.cjs';
|
|
42
42
|
export * from './packages/energy-app-energy-prices.cjs';
|
|
43
|
+
export * from './packages/energy-app-modbus.cjs';
|
|
43
44
|
export * from './packages/energy-app-modbus-rtu.cjs';
|
|
44
45
|
export * from './types/enyo-modbus-server.cjs';
|
|
45
46
|
export * from './packages/energy-app-modbus-server.cjs';
|
|
@@ -1,2 +1,66 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ModbusExceptionError = exports.MODBUS_MAX_PDU_PAYLOAD_BYTES = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The largest payload {@link EnergyAppModbusInstance.sendRawPdu} accepts, in bytes.
|
|
6
|
+
*
|
|
7
|
+
* A Modbus PDU is capped at 253 bytes; one of those is the function code, leaving 252 for
|
|
8
|
+
* the payload.
|
|
9
|
+
*/
|
|
10
|
+
exports.MODBUS_MAX_PDU_PAYLOAD_BYTES = 252;
|
|
11
|
+
/**
|
|
12
|
+
* Thrown when a Modbus device answered a request with an exception response — the device is
|
|
13
|
+
* reachable and the frame was well-formed, it simply refused the operation.
|
|
14
|
+
*
|
|
15
|
+
* This is deliberately distinct from a transport failure. An app probing whether it is
|
|
16
|
+
* allowed to write (write a register back its own value and see what happens) needs
|
|
17
|
+
* "refused with code 0x80" to be reliably distinguishable from "timed out" or "socket
|
|
18
|
+
* dropped", and a generic `Error` with the code buried in its message string is not a
|
|
19
|
+
* contract anything can be built on.
|
|
20
|
+
*
|
|
21
|
+
* The socket is left intact when this is thrown: an exception response is a protocol answer,
|
|
22
|
+
* not a broken link.
|
|
23
|
+
*
|
|
24
|
+
* Note that {@link EnergyAppModbusInstance.sendRawPdu} does *not* throw this — a raw PDU
|
|
25
|
+
* reports its exception as data on {@link ModbusRawPduResponse.exceptionCode}, because there
|
|
26
|
+
* the exception is frequently the expected outcome rather than a failure.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* try {
|
|
31
|
+
* await instance.writeSingleRegister(43006, currentValue);
|
|
32
|
+
* // The write landed — this connection may write.
|
|
33
|
+
* } catch (error) {
|
|
34
|
+
* if (error instanceof ModbusExceptionError && error.exceptionCode === 0x80) {
|
|
35
|
+
* // Refused for lack of permission — a login is required.
|
|
36
|
+
* }
|
|
37
|
+
* throw error;
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
class ModbusExceptionError extends Error {
|
|
42
|
+
exceptionCode;
|
|
43
|
+
functionCode;
|
|
44
|
+
address;
|
|
45
|
+
/**
|
|
46
|
+
* @param exceptionCode The raw exception code the device answered with. Standard codes
|
|
47
|
+
* are `0x01`…`0x0B`; vendor-specific codes are passed through
|
|
48
|
+
* unvalidated.
|
|
49
|
+
* @param functionCode The function code of the request that was refused (the request's
|
|
50
|
+
* own code, without the exception high bit).
|
|
51
|
+
* @param message Human-readable description, including the operation that failed.
|
|
52
|
+
* @param address The register or coil address involved, when the operation had
|
|
53
|
+
* one.
|
|
54
|
+
*/
|
|
55
|
+
constructor(exceptionCode, functionCode, message, address) {
|
|
56
|
+
super(message);
|
|
57
|
+
this.exceptionCode = exceptionCode;
|
|
58
|
+
this.functionCode = functionCode;
|
|
59
|
+
this.address = address;
|
|
60
|
+
this.name = 'ModbusExceptionError';
|
|
61
|
+
// Restores the prototype chain so `instanceof` holds when this package is consumed
|
|
62
|
+
// from code compiled down to ES5.
|
|
63
|
+
Object.setPrototypeOf(this, ModbusExceptionError.prototype);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.ModbusExceptionError = ModbusExceptionError;
|
|
@@ -98,4 +98,163 @@ export interface EnergyAppModbusInstance {
|
|
|
98
98
|
writeMultipleRegisters: (address: number, values: number[]) => Promise<void>;
|
|
99
99
|
/** Read holding register string value */
|
|
100
100
|
readRegisterStringValue: (address: number, quantity: number) => Promise<string>;
|
|
101
|
+
/**
|
|
102
|
+
* Sends one Modbus PDU verbatim on this connection and returns the raw response.
|
|
103
|
+
*
|
|
104
|
+
* This is the escape hatch for vendor function codes — the sub-commands a manufacturer
|
|
105
|
+
* reserves for itself outside the eight standard codes, such as the installer login a
|
|
106
|
+
* Huawei SUN2000 requires before it accepts a single control write. The transport owns
|
|
107
|
+
* framing (MBAP header, transaction id, unit id) exactly as it does for every other
|
|
108
|
+
* request; `payload` is put on the wire untouched and the response bytes come back
|
|
109
|
+
* untouched.
|
|
110
|
+
*
|
|
111
|
+
* The call is queued on the same per-connection chain as the standard reads and writes,
|
|
112
|
+
* so it honours {@link ModbusOptions.noParallelRequests} and
|
|
113
|
+
* {@link ModbusOptions.waitBetweenMessagesMs} and can never be interleaved with a block
|
|
114
|
+
* read that is already in flight.
|
|
115
|
+
*
|
|
116
|
+
* A device that answers with an exception resolves rather than rejects: the exception
|
|
117
|
+
* code is data (see {@link ModbusRawPduResponse.exceptionCode}), because for a
|
|
118
|
+
* permission probe "not allowed" is the expected answer and has to be distinguishable
|
|
119
|
+
* from a timeout or a dropped socket. Only transport failures reject.
|
|
120
|
+
*
|
|
121
|
+
* Request payloads are never logged — a vendor handshake typically carries a credential
|
|
122
|
+
* digest. Only the function code and the payload length appear in the logs.
|
|
123
|
+
*
|
|
124
|
+
* @param functionCode Modbus function code, 1…127. The exception space (`>= 0x80`) and
|
|
125
|
+
* `0` are rejected; the eight standard codes are allowed but the
|
|
126
|
+
* dedicated methods above are the better way to reach them.
|
|
127
|
+
* @param payload PDU bytes after the function code. At most
|
|
128
|
+
* {@link MODBUS_MAX_PDU_PAYLOAD_BYTES} bytes, so the frame stays
|
|
129
|
+
* within the 253-byte Modbus PDU limit. May be empty.
|
|
130
|
+
* @param options Optional per-call overrides.
|
|
131
|
+
* @throws Error if the parameters are out of range, if the connection is gone, or if the
|
|
132
|
+
* device does not answer within the deadline.
|
|
133
|
+
*/
|
|
134
|
+
sendRawPdu: (functionCode: number, payload: Buffer, options?: ModbusRawPduOptions) => Promise<ModbusRawPduResponse>;
|
|
135
|
+
/**
|
|
136
|
+
* Registers a listener that fires whenever the underlying socket for this unit has been
|
|
137
|
+
* replaced — a reconnect after a dropped link, a recycled half-open socket, or a stale
|
|
138
|
+
* socket torn down by the transport.
|
|
139
|
+
*
|
|
140
|
+
* This matters for anything the device tracks per connection rather than per device.
|
|
141
|
+
* A vendor login, for instance, grants permission to the *socket* that authenticated:
|
|
142
|
+
* once that socket is gone the permission is gone with it, silently — the next write
|
|
143
|
+
* simply comes back with an exception. The listener is the point at which an app can
|
|
144
|
+
* re-authenticate before the next command instead of after a failed one.
|
|
145
|
+
*
|
|
146
|
+
* The listener fires once per socket replacement, after the old socket is gone and
|
|
147
|
+
* before the next operation is served. It is not called for the initial connect.
|
|
148
|
+
* Listeners must not throw; a throwing listener is logged and ignored.
|
|
149
|
+
*
|
|
150
|
+
* @param listener Called with no arguments once per socket replacement.
|
|
151
|
+
* @returns A function that removes the listener. Every listener is dropped automatically
|
|
152
|
+
* on {@link EnergyAppModbusInstance.disconnect}.
|
|
153
|
+
*/
|
|
154
|
+
onReconnect: (listener: () => void) => () => void;
|
|
155
|
+
/**
|
|
156
|
+
* Monotonic counter of how many sockets this unit has been bound to, starting at `1` for
|
|
157
|
+
* the first live socket.
|
|
158
|
+
*
|
|
159
|
+
* The pull-based counterpart to {@link EnergyAppModbusInstance.onReconnect}: read it
|
|
160
|
+
* before and after an operation to tell whether connection-scoped state (a vendor login,
|
|
161
|
+
* a session token) survived, without having to keep a listener alive. A value that
|
|
162
|
+
* changed means the socket was replaced and anything scoped to it is void.
|
|
163
|
+
*
|
|
164
|
+
* Returns `0` while the instance has never had a live socket.
|
|
165
|
+
*/
|
|
166
|
+
connectionGeneration: () => number;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Per-call options for {@link EnergyAppModbusInstance.sendRawPdu}.
|
|
170
|
+
*/
|
|
171
|
+
export interface ModbusRawPduOptions {
|
|
172
|
+
/**
|
|
173
|
+
* Deadline for this single request in milliseconds. Defaults to the connection's
|
|
174
|
+
* {@link ModbusOptions.readTimeoutMs}. As with every other operation, exceeding it is
|
|
175
|
+
* treated as a dead link and recycles the socket.
|
|
176
|
+
*/
|
|
177
|
+
timeoutMs?: number;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The raw answer to a {@link EnergyAppModbusInstance.sendRawPdu} call.
|
|
181
|
+
*
|
|
182
|
+
* Both a normal response and a device-level exception arrive here; only transport failures
|
|
183
|
+
* are thrown. Check {@link ModbusRawPduResponse.exceptionCode} first — it is `undefined`
|
|
184
|
+
* exactly when the device accepted the request.
|
|
185
|
+
*/
|
|
186
|
+
export interface ModbusRawPduResponse {
|
|
187
|
+
/**
|
|
188
|
+
* The function code the device echoed. On an exception this is the requested code with
|
|
189
|
+
* the high bit set (`functionCode | 0x80`), which is what the device actually put on the
|
|
190
|
+
* wire.
|
|
191
|
+
*/
|
|
192
|
+
functionCode: number;
|
|
193
|
+
/**
|
|
194
|
+
* The response bytes that followed the function code, with vendor framing intact.
|
|
195
|
+
* Empty on an exception — the exception code is reported separately rather than left in
|
|
196
|
+
* the payload.
|
|
197
|
+
*/
|
|
198
|
+
payload: Buffer;
|
|
199
|
+
/**
|
|
200
|
+
* The device's exception code when it rejected the request, otherwise `undefined`.
|
|
201
|
+
*
|
|
202
|
+
* Standard Modbus defines `0x01`…`0x0B`, but vendors add their own — Huawei answers
|
|
203
|
+
* `0x80` for "permission authentication failure or permission expiration" — so this is
|
|
204
|
+
* the raw byte, passed through without validation against the standard set.
|
|
205
|
+
*/
|
|
206
|
+
exceptionCode?: number;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* The largest payload {@link EnergyAppModbusInstance.sendRawPdu} accepts, in bytes.
|
|
210
|
+
*
|
|
211
|
+
* A Modbus PDU is capped at 253 bytes; one of those is the function code, leaving 252 for
|
|
212
|
+
* the payload.
|
|
213
|
+
*/
|
|
214
|
+
export declare const MODBUS_MAX_PDU_PAYLOAD_BYTES = 252;
|
|
215
|
+
/**
|
|
216
|
+
* Thrown when a Modbus device answered a request with an exception response — the device is
|
|
217
|
+
* reachable and the frame was well-formed, it simply refused the operation.
|
|
218
|
+
*
|
|
219
|
+
* This is deliberately distinct from a transport failure. An app probing whether it is
|
|
220
|
+
* allowed to write (write a register back its own value and see what happens) needs
|
|
221
|
+
* "refused with code 0x80" to be reliably distinguishable from "timed out" or "socket
|
|
222
|
+
* dropped", and a generic `Error` with the code buried in its message string is not a
|
|
223
|
+
* contract anything can be built on.
|
|
224
|
+
*
|
|
225
|
+
* The socket is left intact when this is thrown: an exception response is a protocol answer,
|
|
226
|
+
* not a broken link.
|
|
227
|
+
*
|
|
228
|
+
* Note that {@link EnergyAppModbusInstance.sendRawPdu} does *not* throw this — a raw PDU
|
|
229
|
+
* reports its exception as data on {@link ModbusRawPduResponse.exceptionCode}, because there
|
|
230
|
+
* the exception is frequently the expected outcome rather than a failure.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* try {
|
|
235
|
+
* await instance.writeSingleRegister(43006, currentValue);
|
|
236
|
+
* // The write landed — this connection may write.
|
|
237
|
+
* } catch (error) {
|
|
238
|
+
* if (error instanceof ModbusExceptionError && error.exceptionCode === 0x80) {
|
|
239
|
+
* // Refused for lack of permission — a login is required.
|
|
240
|
+
* }
|
|
241
|
+
* throw error;
|
|
242
|
+
* }
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
export declare class ModbusExceptionError extends Error {
|
|
246
|
+
readonly exceptionCode: number;
|
|
247
|
+
readonly functionCode: number;
|
|
248
|
+
readonly address?: number | undefined;
|
|
249
|
+
/**
|
|
250
|
+
* @param exceptionCode The raw exception code the device answered with. Standard codes
|
|
251
|
+
* are `0x01`…`0x0B`; vendor-specific codes are passed through
|
|
252
|
+
* unvalidated.
|
|
253
|
+
* @param functionCode The function code of the request that was refused (the request's
|
|
254
|
+
* own code, without the exception high bit).
|
|
255
|
+
* @param message Human-readable description, including the operation that failed.
|
|
256
|
+
* @param address The register or coil address involved, when the operation had
|
|
257
|
+
* one.
|
|
258
|
+
*/
|
|
259
|
+
constructor(exceptionCode: number, functionCode: number, message: string, address?: number | undefined);
|
|
101
260
|
}
|
|
@@ -90,9 +90,15 @@ var BatteryCommandForecastDirectionEnum;
|
|
|
90
90
|
/** Power should flow from the battery into the home / grid (discharging). */
|
|
91
91
|
BatteryCommandForecastDirectionEnum["Discharge"] = "discharge";
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
93
|
+
* Leave the slot to the battery's own logic — for the duration of
|
|
94
|
+
* the entry the appliance decides itself whether to charge,
|
|
95
|
+
* discharge or stand still (auto mode).
|
|
96
|
+
*
|
|
97
|
+
* This is *not* a "no energy flow" marker: to block charging or
|
|
98
|
+
* discharging, use {@link BatteryCommandForecastDirectionEnum.Charge}
|
|
99
|
+
* respectively {@link BatteryCommandForecastDirectionEnum.Discharge}
|
|
100
|
+
* with `powerW = 0`. An `Idle` entry prescribes no setpoint, so its
|
|
101
|
+
* `powerW` must be `0`.
|
|
96
102
|
*/
|
|
97
103
|
BatteryCommandForecastDirectionEnum["Idle"] = "idle";
|
|
98
104
|
})(BatteryCommandForecastDirectionEnum || (exports.BatteryCommandForecastDirectionEnum = BatteryCommandForecastDirectionEnum = {}));
|
|
@@ -180,9 +180,15 @@ export declare enum BatteryCommandForecastDirectionEnum {
|
|
|
180
180
|
/** Power should flow from the battery into the home / grid (discharging). */
|
|
181
181
|
Discharge = "discharge",
|
|
182
182
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
183
|
+
* Leave the slot to the battery's own logic — for the duration of
|
|
184
|
+
* the entry the appliance decides itself whether to charge,
|
|
185
|
+
* discharge or stand still (auto mode).
|
|
186
|
+
*
|
|
187
|
+
* This is *not* a "no energy flow" marker: to block charging or
|
|
188
|
+
* discharging, use {@link BatteryCommandForecastDirectionEnum.Charge}
|
|
189
|
+
* respectively {@link BatteryCommandForecastDirectionEnum.Discharge}
|
|
190
|
+
* with `powerW = 0`. An `Idle` entry prescribes no setpoint, so its
|
|
191
|
+
* `powerW` must be `0`.
|
|
186
192
|
*/
|
|
187
193
|
Idle = "idle"
|
|
188
194
|
}
|
|
@@ -205,11 +211,12 @@ export interface BatteryCommandForecastScheduleEntry {
|
|
|
205
211
|
/**
|
|
206
212
|
* Target power in Watts. Always non-negative — direction is carried
|
|
207
213
|
* by {@link direction}, never by sign. A `powerW` of `0` together
|
|
208
|
-
* with a `Charge` or `Discharge` direction
|
|
209
|
-
* the
|
|
210
|
-
*
|
|
211
|
-
* {@link BatteryCommandForecastDirectionEnum.Idle}
|
|
212
|
-
*
|
|
214
|
+
* with a `Charge` or `Discharge` direction blocks that direction —
|
|
215
|
+
* the battery must not charge respectively discharge until the next
|
|
216
|
+
* entry. Use that to keep the battery still, *not*
|
|
217
|
+
* {@link BatteryCommandForecastDirectionEnum.Idle}, which hands
|
|
218
|
+
* control back to the appliance's own logic and prescribes no
|
|
219
|
+
* setpoint at all (its `powerW` must be `0`).
|
|
213
220
|
*/
|
|
214
221
|
powerW: number;
|
|
215
222
|
}
|
|
@@ -24,7 +24,9 @@ var EnyoApplianceStateEnum;
|
|
|
24
24
|
* which describes connectivity. `Healthy` means the appliance is operating
|
|
25
25
|
* normally; `Warning` means a non-blocking issue has been reported (the
|
|
26
26
|
* appliance is still functional but should be inspected); `Faulted` means it
|
|
27
|
-
* has reported an internal error and may need attention
|
|
27
|
+
* has reported an internal error and may need attention; `Deactivated` means
|
|
28
|
+
* the appliance has been intentionally switched off from energy management and
|
|
29
|
+
* is neither monitored nor controlled until it is reactivated. Vendor- or
|
|
28
30
|
* protocol-specific details should be conveyed via accompanying error codes.
|
|
29
31
|
*/
|
|
30
32
|
var EnyoApplianceStatusEnum;
|
|
@@ -35,6 +37,12 @@ var EnyoApplianceStatusEnum;
|
|
|
35
37
|
EnyoApplianceStatusEnum["Warning"] = "warning";
|
|
36
38
|
/** Appliance has reported an internal fault */
|
|
37
39
|
EnyoApplianceStatusEnum["Faulted"] = "faulted";
|
|
40
|
+
/**
|
|
41
|
+
* Appliance has been intentionally deactivated and is excluded from energy
|
|
42
|
+
* management. It is not controlled and its health is not evaluated until it
|
|
43
|
+
* is reactivated.
|
|
44
|
+
*/
|
|
45
|
+
EnyoApplianceStatusEnum["Deactivated"] = "deactivated";
|
|
38
46
|
})(EnyoApplianceStatusEnum || (exports.EnyoApplianceStatusEnum = EnyoApplianceStatusEnum = {}));
|
|
39
47
|
var EnyoApplianceConnectionType;
|
|
40
48
|
(function (EnyoApplianceConnectionType) {
|
|
@@ -33,7 +33,9 @@ export declare enum EnyoApplianceStateEnum {
|
|
|
33
33
|
* which describes connectivity. `Healthy` means the appliance is operating
|
|
34
34
|
* normally; `Warning` means a non-blocking issue has been reported (the
|
|
35
35
|
* appliance is still functional but should be inspected); `Faulted` means it
|
|
36
|
-
* has reported an internal error and may need attention
|
|
36
|
+
* has reported an internal error and may need attention; `Deactivated` means
|
|
37
|
+
* the appliance has been intentionally switched off from energy management and
|
|
38
|
+
* is neither monitored nor controlled until it is reactivated. Vendor- or
|
|
37
39
|
* protocol-specific details should be conveyed via accompanying error codes.
|
|
38
40
|
*/
|
|
39
41
|
export declare enum EnyoApplianceStatusEnum {
|
|
@@ -42,7 +44,13 @@ export declare enum EnyoApplianceStatusEnum {
|
|
|
42
44
|
/** Appliance is operating but has reported a non-blocking issue that should be inspected */
|
|
43
45
|
Warning = "warning",
|
|
44
46
|
/** Appliance has reported an internal fault */
|
|
45
|
-
Faulted = "faulted"
|
|
47
|
+
Faulted = "faulted",
|
|
48
|
+
/**
|
|
49
|
+
* Appliance has been intentionally deactivated and is excluded from energy
|
|
50
|
+
* management. It is not controlled and its health is not evaluated until it
|
|
51
|
+
* is reactivated.
|
|
52
|
+
*/
|
|
53
|
+
Deactivated = "deactivated"
|
|
46
54
|
}
|
|
47
55
|
/**
|
|
48
56
|
* Severity classification for an {@link EnyoApplianceErrorCode}.
|
|
@@ -175,7 +183,7 @@ export interface EnyoApplianceMetadata {
|
|
|
175
183
|
ipAddress?: string;
|
|
176
184
|
/** Connection state */
|
|
177
185
|
state?: EnyoApplianceStateEnum;
|
|
178
|
-
/** Health status of the appliance (e.g. healthy or
|
|
186
|
+
/** Health status of the appliance (e.g. healthy, faulted or deactivated) */
|
|
179
187
|
status?: EnyoApplianceStatusEnum;
|
|
180
188
|
network?: EnyoApplianceNetworkMetadata;
|
|
181
189
|
modbus?: EnyoApplianceModbusMetadata;
|
|
@@ -324,9 +324,11 @@ var EnyoStorageScheduleModeEnum;
|
|
|
324
324
|
* non-negative, and consumers never have to disambiguate `0` from
|
|
325
325
|
* "direction-of-zero" or interpret sign conventions per integration.
|
|
326
326
|
*
|
|
327
|
-
* `Idle`
|
|
328
|
-
*
|
|
329
|
-
* `
|
|
327
|
+
* `Idle` hands the slot back to the battery's own logic — it does *not*
|
|
328
|
+
* mean "no energy flow". To keep the battery still, use `Charge` or
|
|
329
|
+
* `Discharge` with `powerW = 0`, which blocks that direction for the
|
|
330
|
+
* duration of the entry. An `Idle` entry prescribes no setpoint, so it
|
|
331
|
+
* must carry `powerW = 0`.
|
|
330
332
|
*/
|
|
331
333
|
var EnyoStorageScheduleDirectionEnum;
|
|
332
334
|
(function (EnyoStorageScheduleDirectionEnum) {
|
|
@@ -335,9 +337,15 @@ var EnyoStorageScheduleDirectionEnum;
|
|
|
335
337
|
/** Power should flow from the battery into the grid / home (discharging). */
|
|
336
338
|
EnyoStorageScheduleDirectionEnum["Discharge"] = "discharge";
|
|
337
339
|
/**
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
340
|
+
* Leave the slot to the battery's own logic — for the duration of
|
|
341
|
+
* the entry the appliance decides itself whether to charge,
|
|
342
|
+
* discharge or stand still (auto mode).
|
|
343
|
+
*
|
|
344
|
+
* This is *not* a "no energy flow" marker: to block charging or
|
|
345
|
+
* discharging, use {@link EnyoStorageScheduleDirectionEnum.Charge}
|
|
346
|
+
* respectively {@link EnyoStorageScheduleDirectionEnum.Discharge}
|
|
347
|
+
* with `powerW = 0`. An `Idle` entry prescribes no setpoint, so its
|
|
348
|
+
* `powerW` must be `0`.
|
|
341
349
|
*/
|
|
342
350
|
EnyoStorageScheduleDirectionEnum["Idle"] = "idle";
|
|
343
351
|
})(EnyoStorageScheduleDirectionEnum || (exports.EnyoStorageScheduleDirectionEnum = EnyoStorageScheduleDirectionEnum = {}));
|
|
@@ -593,7 +593,8 @@ export interface EnyoDataBusApplianceFlexibilityAnnouncementV1 extends EnyoDataB
|
|
|
593
593
|
* provided together if they change in the same event. `errorCodes` carries
|
|
594
594
|
* vendor- or protocol-specific codes that explain a transition into a
|
|
595
595
|
* `warning` or `faulted` status; each entry's `severity` field indicates
|
|
596
|
-
* which.
|
|
596
|
+
* which. A transition into `deactivated` is intentional and normally carries
|
|
597
|
+
* no error codes.
|
|
597
598
|
*/
|
|
598
599
|
export interface EnyoDataBusApplianceStateUpdateV1 extends EnyoDataBusMessage {
|
|
599
600
|
type: 'message';
|
|
@@ -1636,9 +1637,11 @@ export declare enum EnyoStorageScheduleModeEnum {
|
|
|
1636
1637
|
* non-negative, and consumers never have to disambiguate `0` from
|
|
1637
1638
|
* "direction-of-zero" or interpret sign conventions per integration.
|
|
1638
1639
|
*
|
|
1639
|
-
* `Idle`
|
|
1640
|
-
*
|
|
1641
|
-
* `
|
|
1640
|
+
* `Idle` hands the slot back to the battery's own logic — it does *not*
|
|
1641
|
+
* mean "no energy flow". To keep the battery still, use `Charge` or
|
|
1642
|
+
* `Discharge` with `powerW = 0`, which blocks that direction for the
|
|
1643
|
+
* duration of the entry. An `Idle` entry prescribes no setpoint, so it
|
|
1644
|
+
* must carry `powerW = 0`.
|
|
1642
1645
|
*/
|
|
1643
1646
|
export declare enum EnyoStorageScheduleDirectionEnum {
|
|
1644
1647
|
/** Power should flow from the grid into the battery (charging). */
|
|
@@ -1646,9 +1649,15 @@ export declare enum EnyoStorageScheduleDirectionEnum {
|
|
|
1646
1649
|
/** Power should flow from the battery into the grid / home (discharging). */
|
|
1647
1650
|
Discharge = "discharge",
|
|
1648
1651
|
/**
|
|
1649
|
-
*
|
|
1650
|
-
*
|
|
1651
|
-
*
|
|
1652
|
+
* Leave the slot to the battery's own logic — for the duration of
|
|
1653
|
+
* the entry the appliance decides itself whether to charge,
|
|
1654
|
+
* discharge or stand still (auto mode).
|
|
1655
|
+
*
|
|
1656
|
+
* This is *not* a "no energy flow" marker: to block charging or
|
|
1657
|
+
* discharging, use {@link EnyoStorageScheduleDirectionEnum.Charge}
|
|
1658
|
+
* respectively {@link EnyoStorageScheduleDirectionEnum.Discharge}
|
|
1659
|
+
* with `powerW = 0`. An `Idle` entry prescribes no setpoint, so its
|
|
1660
|
+
* `powerW` must be `0`.
|
|
1652
1661
|
*/
|
|
1653
1662
|
Idle = "idle"
|
|
1654
1663
|
}
|
|
@@ -1678,10 +1687,11 @@ export interface EnyoStorageScheduleEntry {
|
|
|
1678
1687
|
* Target power for this setpoint in Watts. Always non-negative —
|
|
1679
1688
|
* direction is carried by {@link direction}, never by sign. A
|
|
1680
1689
|
* `powerW` of `0` together with a `Charge` or `Discharge` direction
|
|
1681
|
-
*
|
|
1682
|
-
* until the next entry
|
|
1683
|
-
* {@link EnyoStorageScheduleDirectionEnum.Idle}
|
|
1684
|
-
*
|
|
1690
|
+
* blocks that direction — the battery must not charge respectively
|
|
1691
|
+
* discharge until the next entry. Use that to keep the battery
|
|
1692
|
+
* still, *not* {@link EnyoStorageScheduleDirectionEnum.Idle}, which
|
|
1693
|
+
* hands control back to the appliance's own logic and prescribes no
|
|
1694
|
+
* setpoint at all (its `powerW` must be `0`).
|
|
1685
1695
|
*/
|
|
1686
1696
|
powerW: number;
|
|
1687
1697
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* (`../implementations/onboarding-v2/onboarding-v2-validators.ts`) to fail fast
|
|
21
21
|
* before publishing.
|
|
22
22
|
*/
|
|
23
|
-
import type {
|
|
23
|
+
import type { EnyoOnboardingTranslatedContent } from './enyo-onboarding.cjs';
|
|
24
24
|
/**
|
|
25
25
|
* The situation a flow starts from. A vendor/model can have up to one guide per
|
|
26
26
|
* variant; a branch can jump into another variant's flow
|
|
@@ -1067,21 +1067,6 @@ export interface EnyoOnboardingV2Guide {
|
|
|
1067
1067
|
title: EnyoOnboardingTranslatedContent[];
|
|
1068
1068
|
/** Which start situation this guide covers. */
|
|
1069
1069
|
startVariant: EnyoOnboardingV2StartVariant;
|
|
1070
|
-
/**
|
|
1071
|
-
* The lifecycle role this guide plays, which decides where the host offers
|
|
1072
|
-
* it (an "add new device" entry point, the configuration-required prompt).
|
|
1073
|
-
*
|
|
1074
|
-
* Distinct from {@link startVariant}, which describes the *situation the
|
|
1075
|
-
* flow starts from* (device not found, found but unconfigured, …). This says
|
|
1076
|
-
* *why the installer is here at all*: configuring the package for the first
|
|
1077
|
-
* time is a different entry point from adding a second device to a package
|
|
1078
|
-
* that already works, even when both start from `device-not-found`.
|
|
1079
|
-
*
|
|
1080
|
-
* Shared with the v1 model rather than restated as a v2 enum — the category
|
|
1081
|
-
* is a property of a guide's role, not of the authoring model. Defaults to
|
|
1082
|
-
* {@link EnyoOnboardingGuideCategory.InitialSetup} semantics when omitted.
|
|
1083
|
-
*/
|
|
1084
|
-
category?: EnyoOnboardingGuideCategory;
|
|
1085
1070
|
/**
|
|
1086
1071
|
* Whether the host runs its local network scan before entering this guide.
|
|
1087
1072
|
*
|
|
@@ -6,11 +6,9 @@ exports.EnyoOnboardingSectionType = exports.EnyoOnboardingGuideCategory = void 0
|
|
|
6
6
|
* Used to distinguish guides that perform different roles, e.g. initial
|
|
7
7
|
* configuration of a package vs. adding or reconnecting a single device.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
* {@link EnyoOnboardingV2Guide
|
|
11
|
-
*
|
|
12
|
-
* the category is a property of a guide's role, not of the authoring model it
|
|
13
|
-
* was written in.
|
|
9
|
+
* @deprecated Superseded by the v2 graph model. Author guides with
|
|
10
|
+
* {@link EnyoOnboardingV2Guide} via `defineOnboardingGuideV2()`. v1 is retained
|
|
11
|
+
* for backward compatibility and will be removed in a future major.
|
|
14
12
|
*/
|
|
15
13
|
var EnyoOnboardingGuideCategory;
|
|
16
14
|
(function (EnyoOnboardingGuideCategory) {
|
|
@@ -14,11 +14,9 @@ export interface EnyoOnboardingTranslatedContent {
|
|
|
14
14
|
* Used to distinguish guides that perform different roles, e.g. initial
|
|
15
15
|
* configuration of a package vs. adding or reconnecting a single device.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
* {@link EnyoOnboardingV2Guide
|
|
19
|
-
*
|
|
20
|
-
* the category is a property of a guide's role, not of the authoring model it
|
|
21
|
-
* was written in.
|
|
17
|
+
* @deprecated Superseded by the v2 graph model. Author guides with
|
|
18
|
+
* {@link EnyoOnboardingV2Guide} via `defineOnboardingGuideV2()`. v1 is retained
|
|
19
|
+
* for backward compatibility and will be removed in a future major.
|
|
22
20
|
*/
|
|
23
21
|
export declare enum EnyoOnboardingGuideCategory {
|
|
24
22
|
/** Initial package configuration — shown when EnergyAppStateEnum is 'configuration-required' */
|
package/dist/cjs/version.cjs
CHANGED
package/dist/cjs/version.d.cts
CHANGED
|
@@ -261,6 +261,18 @@ export interface EnergyAppPackageCompatibilityVendor {
|
|
|
261
261
|
vendorName: string;
|
|
262
262
|
/** Models from this vendor that the package supports */
|
|
263
263
|
models: EnergyAppPackageCompatibilityModel[];
|
|
264
|
+
/**
|
|
265
|
+
* Marks this package as the default Energy App for the vendor when no
|
|
266
|
+
* concrete model has been selected.
|
|
267
|
+
*
|
|
268
|
+
* During onboarding a user may only know the manufacturer of their device,
|
|
269
|
+
* not its exact model. When several packages declare compatibility with the
|
|
270
|
+
* same vendor, the one flagged with `default: true` is the app the enyo
|
|
271
|
+
* Store and onboarding flows pick in that case. Set it on at most one
|
|
272
|
+
* package per vendor; omit it (or set `false`) when the package should only
|
|
273
|
+
* be offered for an explicitly selected model.
|
|
274
|
+
*/
|
|
275
|
+
defaultEnergyApp?: boolean;
|
|
264
276
|
}
|
|
265
277
|
/**
|
|
266
278
|
* A file published together with an Energy App package and served publicly
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export * from './implementations/data-bus/data-bus-command-handler.js';
|
|
|
40
40
|
export * from './types/enyo-currency.js';
|
|
41
41
|
export * from './packages/energy-app-sequence-generator.js';
|
|
42
42
|
export * from './packages/energy-app-energy-prices.js';
|
|
43
|
+
export * from './packages/energy-app-modbus.js';
|
|
43
44
|
export * from './packages/energy-app-modbus-rtu.js';
|
|
44
45
|
export * from './types/enyo-modbus-server.js';
|
|
45
46
|
export * from './packages/energy-app-modbus-server.js';
|
package/dist/index.js
CHANGED
|
@@ -40,6 +40,7 @@ export * from './implementations/data-bus/data-bus-command-handler.js';
|
|
|
40
40
|
export * from './types/enyo-currency.js';
|
|
41
41
|
export * from './packages/energy-app-sequence-generator.js';
|
|
42
42
|
export * from './packages/energy-app-energy-prices.js';
|
|
43
|
+
export * from './packages/energy-app-modbus.js';
|
|
43
44
|
export * from './packages/energy-app-modbus-rtu.js';
|
|
44
45
|
export * from './types/enyo-modbus-server.js';
|
|
45
46
|
export * from './packages/energy-app-modbus-server.js';
|
|
@@ -98,4 +98,163 @@ export interface EnergyAppModbusInstance {
|
|
|
98
98
|
writeMultipleRegisters: (address: number, values: number[]) => Promise<void>;
|
|
99
99
|
/** Read holding register string value */
|
|
100
100
|
readRegisterStringValue: (address: number, quantity: number) => Promise<string>;
|
|
101
|
+
/**
|
|
102
|
+
* Sends one Modbus PDU verbatim on this connection and returns the raw response.
|
|
103
|
+
*
|
|
104
|
+
* This is the escape hatch for vendor function codes — the sub-commands a manufacturer
|
|
105
|
+
* reserves for itself outside the eight standard codes, such as the installer login a
|
|
106
|
+
* Huawei SUN2000 requires before it accepts a single control write. The transport owns
|
|
107
|
+
* framing (MBAP header, transaction id, unit id) exactly as it does for every other
|
|
108
|
+
* request; `payload` is put on the wire untouched and the response bytes come back
|
|
109
|
+
* untouched.
|
|
110
|
+
*
|
|
111
|
+
* The call is queued on the same per-connection chain as the standard reads and writes,
|
|
112
|
+
* so it honours {@link ModbusOptions.noParallelRequests} and
|
|
113
|
+
* {@link ModbusOptions.waitBetweenMessagesMs} and can never be interleaved with a block
|
|
114
|
+
* read that is already in flight.
|
|
115
|
+
*
|
|
116
|
+
* A device that answers with an exception resolves rather than rejects: the exception
|
|
117
|
+
* code is data (see {@link ModbusRawPduResponse.exceptionCode}), because for a
|
|
118
|
+
* permission probe "not allowed" is the expected answer and has to be distinguishable
|
|
119
|
+
* from a timeout or a dropped socket. Only transport failures reject.
|
|
120
|
+
*
|
|
121
|
+
* Request payloads are never logged — a vendor handshake typically carries a credential
|
|
122
|
+
* digest. Only the function code and the payload length appear in the logs.
|
|
123
|
+
*
|
|
124
|
+
* @param functionCode Modbus function code, 1…127. The exception space (`>= 0x80`) and
|
|
125
|
+
* `0` are rejected; the eight standard codes are allowed but the
|
|
126
|
+
* dedicated methods above are the better way to reach them.
|
|
127
|
+
* @param payload PDU bytes after the function code. At most
|
|
128
|
+
* {@link MODBUS_MAX_PDU_PAYLOAD_BYTES} bytes, so the frame stays
|
|
129
|
+
* within the 253-byte Modbus PDU limit. May be empty.
|
|
130
|
+
* @param options Optional per-call overrides.
|
|
131
|
+
* @throws Error if the parameters are out of range, if the connection is gone, or if the
|
|
132
|
+
* device does not answer within the deadline.
|
|
133
|
+
*/
|
|
134
|
+
sendRawPdu: (functionCode: number, payload: Buffer, options?: ModbusRawPduOptions) => Promise<ModbusRawPduResponse>;
|
|
135
|
+
/**
|
|
136
|
+
* Registers a listener that fires whenever the underlying socket for this unit has been
|
|
137
|
+
* replaced — a reconnect after a dropped link, a recycled half-open socket, or a stale
|
|
138
|
+
* socket torn down by the transport.
|
|
139
|
+
*
|
|
140
|
+
* This matters for anything the device tracks per connection rather than per device.
|
|
141
|
+
* A vendor login, for instance, grants permission to the *socket* that authenticated:
|
|
142
|
+
* once that socket is gone the permission is gone with it, silently — the next write
|
|
143
|
+
* simply comes back with an exception. The listener is the point at which an app can
|
|
144
|
+
* re-authenticate before the next command instead of after a failed one.
|
|
145
|
+
*
|
|
146
|
+
* The listener fires once per socket replacement, after the old socket is gone and
|
|
147
|
+
* before the next operation is served. It is not called for the initial connect.
|
|
148
|
+
* Listeners must not throw; a throwing listener is logged and ignored.
|
|
149
|
+
*
|
|
150
|
+
* @param listener Called with no arguments once per socket replacement.
|
|
151
|
+
* @returns A function that removes the listener. Every listener is dropped automatically
|
|
152
|
+
* on {@link EnergyAppModbusInstance.disconnect}.
|
|
153
|
+
*/
|
|
154
|
+
onReconnect: (listener: () => void) => () => void;
|
|
155
|
+
/**
|
|
156
|
+
* Monotonic counter of how many sockets this unit has been bound to, starting at `1` for
|
|
157
|
+
* the first live socket.
|
|
158
|
+
*
|
|
159
|
+
* The pull-based counterpart to {@link EnergyAppModbusInstance.onReconnect}: read it
|
|
160
|
+
* before and after an operation to tell whether connection-scoped state (a vendor login,
|
|
161
|
+
* a session token) survived, without having to keep a listener alive. A value that
|
|
162
|
+
* changed means the socket was replaced and anything scoped to it is void.
|
|
163
|
+
*
|
|
164
|
+
* Returns `0` while the instance has never had a live socket.
|
|
165
|
+
*/
|
|
166
|
+
connectionGeneration: () => number;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Per-call options for {@link EnergyAppModbusInstance.sendRawPdu}.
|
|
170
|
+
*/
|
|
171
|
+
export interface ModbusRawPduOptions {
|
|
172
|
+
/**
|
|
173
|
+
* Deadline for this single request in milliseconds. Defaults to the connection's
|
|
174
|
+
* {@link ModbusOptions.readTimeoutMs}. As with every other operation, exceeding it is
|
|
175
|
+
* treated as a dead link and recycles the socket.
|
|
176
|
+
*/
|
|
177
|
+
timeoutMs?: number;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The raw answer to a {@link EnergyAppModbusInstance.sendRawPdu} call.
|
|
181
|
+
*
|
|
182
|
+
* Both a normal response and a device-level exception arrive here; only transport failures
|
|
183
|
+
* are thrown. Check {@link ModbusRawPduResponse.exceptionCode} first — it is `undefined`
|
|
184
|
+
* exactly when the device accepted the request.
|
|
185
|
+
*/
|
|
186
|
+
export interface ModbusRawPduResponse {
|
|
187
|
+
/**
|
|
188
|
+
* The function code the device echoed. On an exception this is the requested code with
|
|
189
|
+
* the high bit set (`functionCode | 0x80`), which is what the device actually put on the
|
|
190
|
+
* wire.
|
|
191
|
+
*/
|
|
192
|
+
functionCode: number;
|
|
193
|
+
/**
|
|
194
|
+
* The response bytes that followed the function code, with vendor framing intact.
|
|
195
|
+
* Empty on an exception — the exception code is reported separately rather than left in
|
|
196
|
+
* the payload.
|
|
197
|
+
*/
|
|
198
|
+
payload: Buffer;
|
|
199
|
+
/**
|
|
200
|
+
* The device's exception code when it rejected the request, otherwise `undefined`.
|
|
201
|
+
*
|
|
202
|
+
* Standard Modbus defines `0x01`…`0x0B`, but vendors add their own — Huawei answers
|
|
203
|
+
* `0x80` for "permission authentication failure or permission expiration" — so this is
|
|
204
|
+
* the raw byte, passed through without validation against the standard set.
|
|
205
|
+
*/
|
|
206
|
+
exceptionCode?: number;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* The largest payload {@link EnergyAppModbusInstance.sendRawPdu} accepts, in bytes.
|
|
210
|
+
*
|
|
211
|
+
* A Modbus PDU is capped at 253 bytes; one of those is the function code, leaving 252 for
|
|
212
|
+
* the payload.
|
|
213
|
+
*/
|
|
214
|
+
export declare const MODBUS_MAX_PDU_PAYLOAD_BYTES = 252;
|
|
215
|
+
/**
|
|
216
|
+
* Thrown when a Modbus device answered a request with an exception response — the device is
|
|
217
|
+
* reachable and the frame was well-formed, it simply refused the operation.
|
|
218
|
+
*
|
|
219
|
+
* This is deliberately distinct from a transport failure. An app probing whether it is
|
|
220
|
+
* allowed to write (write a register back its own value and see what happens) needs
|
|
221
|
+
* "refused with code 0x80" to be reliably distinguishable from "timed out" or "socket
|
|
222
|
+
* dropped", and a generic `Error` with the code buried in its message string is not a
|
|
223
|
+
* contract anything can be built on.
|
|
224
|
+
*
|
|
225
|
+
* The socket is left intact when this is thrown: an exception response is a protocol answer,
|
|
226
|
+
* not a broken link.
|
|
227
|
+
*
|
|
228
|
+
* Note that {@link EnergyAppModbusInstance.sendRawPdu} does *not* throw this — a raw PDU
|
|
229
|
+
* reports its exception as data on {@link ModbusRawPduResponse.exceptionCode}, because there
|
|
230
|
+
* the exception is frequently the expected outcome rather than a failure.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* try {
|
|
235
|
+
* await instance.writeSingleRegister(43006, currentValue);
|
|
236
|
+
* // The write landed — this connection may write.
|
|
237
|
+
* } catch (error) {
|
|
238
|
+
* if (error instanceof ModbusExceptionError && error.exceptionCode === 0x80) {
|
|
239
|
+
* // Refused for lack of permission — a login is required.
|
|
240
|
+
* }
|
|
241
|
+
* throw error;
|
|
242
|
+
* }
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
export declare class ModbusExceptionError extends Error {
|
|
246
|
+
readonly exceptionCode: number;
|
|
247
|
+
readonly functionCode: number;
|
|
248
|
+
readonly address?: number | undefined;
|
|
249
|
+
/**
|
|
250
|
+
* @param exceptionCode The raw exception code the device answered with. Standard codes
|
|
251
|
+
* are `0x01`…`0x0B`; vendor-specific codes are passed through
|
|
252
|
+
* unvalidated.
|
|
253
|
+
* @param functionCode The function code of the request that was refused (the request's
|
|
254
|
+
* own code, without the exception high bit).
|
|
255
|
+
* @param message Human-readable description, including the operation that failed.
|
|
256
|
+
* @param address The register or coil address involved, when the operation had
|
|
257
|
+
* one.
|
|
258
|
+
*/
|
|
259
|
+
constructor(exceptionCode: number, functionCode: number, message: string, address?: number | undefined);
|
|
101
260
|
}
|
|
@@ -1 +1,62 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The largest payload {@link EnergyAppModbusInstance.sendRawPdu} accepts, in bytes.
|
|
3
|
+
*
|
|
4
|
+
* A Modbus PDU is capped at 253 bytes; one of those is the function code, leaving 252 for
|
|
5
|
+
* the payload.
|
|
6
|
+
*/
|
|
7
|
+
export const MODBUS_MAX_PDU_PAYLOAD_BYTES = 252;
|
|
8
|
+
/**
|
|
9
|
+
* Thrown when a Modbus device answered a request with an exception response — the device is
|
|
10
|
+
* reachable and the frame was well-formed, it simply refused the operation.
|
|
11
|
+
*
|
|
12
|
+
* This is deliberately distinct from a transport failure. An app probing whether it is
|
|
13
|
+
* allowed to write (write a register back its own value and see what happens) needs
|
|
14
|
+
* "refused with code 0x80" to be reliably distinguishable from "timed out" or "socket
|
|
15
|
+
* dropped", and a generic `Error` with the code buried in its message string is not a
|
|
16
|
+
* contract anything can be built on.
|
|
17
|
+
*
|
|
18
|
+
* The socket is left intact when this is thrown: an exception response is a protocol answer,
|
|
19
|
+
* not a broken link.
|
|
20
|
+
*
|
|
21
|
+
* Note that {@link EnergyAppModbusInstance.sendRawPdu} does *not* throw this — a raw PDU
|
|
22
|
+
* reports its exception as data on {@link ModbusRawPduResponse.exceptionCode}, because there
|
|
23
|
+
* the exception is frequently the expected outcome rather than a failure.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* try {
|
|
28
|
+
* await instance.writeSingleRegister(43006, currentValue);
|
|
29
|
+
* // The write landed — this connection may write.
|
|
30
|
+
* } catch (error) {
|
|
31
|
+
* if (error instanceof ModbusExceptionError && error.exceptionCode === 0x80) {
|
|
32
|
+
* // Refused for lack of permission — a login is required.
|
|
33
|
+
* }
|
|
34
|
+
* throw error;
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export class ModbusExceptionError extends Error {
|
|
39
|
+
exceptionCode;
|
|
40
|
+
functionCode;
|
|
41
|
+
address;
|
|
42
|
+
/**
|
|
43
|
+
* @param exceptionCode The raw exception code the device answered with. Standard codes
|
|
44
|
+
* are `0x01`…`0x0B`; vendor-specific codes are passed through
|
|
45
|
+
* unvalidated.
|
|
46
|
+
* @param functionCode The function code of the request that was refused (the request's
|
|
47
|
+
* own code, without the exception high bit).
|
|
48
|
+
* @param message Human-readable description, including the operation that failed.
|
|
49
|
+
* @param address The register or coil address involved, when the operation had
|
|
50
|
+
* one.
|
|
51
|
+
*/
|
|
52
|
+
constructor(exceptionCode, functionCode, message, address) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.exceptionCode = exceptionCode;
|
|
55
|
+
this.functionCode = functionCode;
|
|
56
|
+
this.address = address;
|
|
57
|
+
this.name = 'ModbusExceptionError';
|
|
58
|
+
// Restores the prototype chain so `instanceof` holds when this package is consumed
|
|
59
|
+
// from code compiled down to ES5.
|
|
60
|
+
Object.setPrototypeOf(this, ModbusExceptionError.prototype);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -180,9 +180,15 @@ export declare enum BatteryCommandForecastDirectionEnum {
|
|
|
180
180
|
/** Power should flow from the battery into the home / grid (discharging). */
|
|
181
181
|
Discharge = "discharge",
|
|
182
182
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
183
|
+
* Leave the slot to the battery's own logic — for the duration of
|
|
184
|
+
* the entry the appliance decides itself whether to charge,
|
|
185
|
+
* discharge or stand still (auto mode).
|
|
186
|
+
*
|
|
187
|
+
* This is *not* a "no energy flow" marker: to block charging or
|
|
188
|
+
* discharging, use {@link BatteryCommandForecastDirectionEnum.Charge}
|
|
189
|
+
* respectively {@link BatteryCommandForecastDirectionEnum.Discharge}
|
|
190
|
+
* with `powerW = 0`. An `Idle` entry prescribes no setpoint, so its
|
|
191
|
+
* `powerW` must be `0`.
|
|
186
192
|
*/
|
|
187
193
|
Idle = "idle"
|
|
188
194
|
}
|
|
@@ -205,11 +211,12 @@ export interface BatteryCommandForecastScheduleEntry {
|
|
|
205
211
|
/**
|
|
206
212
|
* Target power in Watts. Always non-negative — direction is carried
|
|
207
213
|
* by {@link direction}, never by sign. A `powerW` of `0` together
|
|
208
|
-
* with a `Charge` or `Discharge` direction
|
|
209
|
-
* the
|
|
210
|
-
*
|
|
211
|
-
* {@link BatteryCommandForecastDirectionEnum.Idle}
|
|
212
|
-
*
|
|
214
|
+
* with a `Charge` or `Discharge` direction blocks that direction —
|
|
215
|
+
* the battery must not charge respectively discharge until the next
|
|
216
|
+
* entry. Use that to keep the battery still, *not*
|
|
217
|
+
* {@link BatteryCommandForecastDirectionEnum.Idle}, which hands
|
|
218
|
+
* control back to the appliance's own logic and prescribes no
|
|
219
|
+
* setpoint at all (its `powerW` must be `0`).
|
|
213
220
|
*/
|
|
214
221
|
powerW: number;
|
|
215
222
|
}
|
|
@@ -87,9 +87,15 @@ export var BatteryCommandForecastDirectionEnum;
|
|
|
87
87
|
/** Power should flow from the battery into the home / grid (discharging). */
|
|
88
88
|
BatteryCommandForecastDirectionEnum["Discharge"] = "discharge";
|
|
89
89
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
90
|
+
* Leave the slot to the battery's own logic — for the duration of
|
|
91
|
+
* the entry the appliance decides itself whether to charge,
|
|
92
|
+
* discharge or stand still (auto mode).
|
|
93
|
+
*
|
|
94
|
+
* This is *not* a "no energy flow" marker: to block charging or
|
|
95
|
+
* discharging, use {@link BatteryCommandForecastDirectionEnum.Charge}
|
|
96
|
+
* respectively {@link BatteryCommandForecastDirectionEnum.Discharge}
|
|
97
|
+
* with `powerW = 0`. An `Idle` entry prescribes no setpoint, so its
|
|
98
|
+
* `powerW` must be `0`.
|
|
93
99
|
*/
|
|
94
100
|
BatteryCommandForecastDirectionEnum["Idle"] = "idle";
|
|
95
101
|
})(BatteryCommandForecastDirectionEnum || (BatteryCommandForecastDirectionEnum = {}));
|
|
@@ -33,7 +33,9 @@ export declare enum EnyoApplianceStateEnum {
|
|
|
33
33
|
* which describes connectivity. `Healthy` means the appliance is operating
|
|
34
34
|
* normally; `Warning` means a non-blocking issue has been reported (the
|
|
35
35
|
* appliance is still functional but should be inspected); `Faulted` means it
|
|
36
|
-
* has reported an internal error and may need attention
|
|
36
|
+
* has reported an internal error and may need attention; `Deactivated` means
|
|
37
|
+
* the appliance has been intentionally switched off from energy management and
|
|
38
|
+
* is neither monitored nor controlled until it is reactivated. Vendor- or
|
|
37
39
|
* protocol-specific details should be conveyed via accompanying error codes.
|
|
38
40
|
*/
|
|
39
41
|
export declare enum EnyoApplianceStatusEnum {
|
|
@@ -42,7 +44,13 @@ export declare enum EnyoApplianceStatusEnum {
|
|
|
42
44
|
/** Appliance is operating but has reported a non-blocking issue that should be inspected */
|
|
43
45
|
Warning = "warning",
|
|
44
46
|
/** Appliance has reported an internal fault */
|
|
45
|
-
Faulted = "faulted"
|
|
47
|
+
Faulted = "faulted",
|
|
48
|
+
/**
|
|
49
|
+
* Appliance has been intentionally deactivated and is excluded from energy
|
|
50
|
+
* management. It is not controlled and its health is not evaluated until it
|
|
51
|
+
* is reactivated.
|
|
52
|
+
*/
|
|
53
|
+
Deactivated = "deactivated"
|
|
46
54
|
}
|
|
47
55
|
/**
|
|
48
56
|
* Severity classification for an {@link EnyoApplianceErrorCode}.
|
|
@@ -175,7 +183,7 @@ export interface EnyoApplianceMetadata {
|
|
|
175
183
|
ipAddress?: string;
|
|
176
184
|
/** Connection state */
|
|
177
185
|
state?: EnyoApplianceStateEnum;
|
|
178
|
-
/** Health status of the appliance (e.g. healthy or
|
|
186
|
+
/** Health status of the appliance (e.g. healthy, faulted or deactivated) */
|
|
179
187
|
status?: EnyoApplianceStatusEnum;
|
|
180
188
|
network?: EnyoApplianceNetworkMetadata;
|
|
181
189
|
modbus?: EnyoApplianceModbusMetadata;
|
|
@@ -21,7 +21,9 @@ export var EnyoApplianceStateEnum;
|
|
|
21
21
|
* which describes connectivity. `Healthy` means the appliance is operating
|
|
22
22
|
* normally; `Warning` means a non-blocking issue has been reported (the
|
|
23
23
|
* appliance is still functional but should be inspected); `Faulted` means it
|
|
24
|
-
* has reported an internal error and may need attention
|
|
24
|
+
* has reported an internal error and may need attention; `Deactivated` means
|
|
25
|
+
* the appliance has been intentionally switched off from energy management and
|
|
26
|
+
* is neither monitored nor controlled until it is reactivated. Vendor- or
|
|
25
27
|
* protocol-specific details should be conveyed via accompanying error codes.
|
|
26
28
|
*/
|
|
27
29
|
export var EnyoApplianceStatusEnum;
|
|
@@ -32,6 +34,12 @@ export var EnyoApplianceStatusEnum;
|
|
|
32
34
|
EnyoApplianceStatusEnum["Warning"] = "warning";
|
|
33
35
|
/** Appliance has reported an internal fault */
|
|
34
36
|
EnyoApplianceStatusEnum["Faulted"] = "faulted";
|
|
37
|
+
/**
|
|
38
|
+
* Appliance has been intentionally deactivated and is excluded from energy
|
|
39
|
+
* management. It is not controlled and its health is not evaluated until it
|
|
40
|
+
* is reactivated.
|
|
41
|
+
*/
|
|
42
|
+
EnyoApplianceStatusEnum["Deactivated"] = "deactivated";
|
|
35
43
|
})(EnyoApplianceStatusEnum || (EnyoApplianceStatusEnum = {}));
|
|
36
44
|
export var EnyoApplianceConnectionType;
|
|
37
45
|
(function (EnyoApplianceConnectionType) {
|
|
@@ -593,7 +593,8 @@ export interface EnyoDataBusApplianceFlexibilityAnnouncementV1 extends EnyoDataB
|
|
|
593
593
|
* provided together if they change in the same event. `errorCodes` carries
|
|
594
594
|
* vendor- or protocol-specific codes that explain a transition into a
|
|
595
595
|
* `warning` or `faulted` status; each entry's `severity` field indicates
|
|
596
|
-
* which.
|
|
596
|
+
* which. A transition into `deactivated` is intentional and normally carries
|
|
597
|
+
* no error codes.
|
|
597
598
|
*/
|
|
598
599
|
export interface EnyoDataBusApplianceStateUpdateV1 extends EnyoDataBusMessage {
|
|
599
600
|
type: 'message';
|
|
@@ -1636,9 +1637,11 @@ export declare enum EnyoStorageScheduleModeEnum {
|
|
|
1636
1637
|
* non-negative, and consumers never have to disambiguate `0` from
|
|
1637
1638
|
* "direction-of-zero" or interpret sign conventions per integration.
|
|
1638
1639
|
*
|
|
1639
|
-
* `Idle`
|
|
1640
|
-
*
|
|
1641
|
-
* `
|
|
1640
|
+
* `Idle` hands the slot back to the battery's own logic — it does *not*
|
|
1641
|
+
* mean "no energy flow". To keep the battery still, use `Charge` or
|
|
1642
|
+
* `Discharge` with `powerW = 0`, which blocks that direction for the
|
|
1643
|
+
* duration of the entry. An `Idle` entry prescribes no setpoint, so it
|
|
1644
|
+
* must carry `powerW = 0`.
|
|
1642
1645
|
*/
|
|
1643
1646
|
export declare enum EnyoStorageScheduleDirectionEnum {
|
|
1644
1647
|
/** Power should flow from the grid into the battery (charging). */
|
|
@@ -1646,9 +1649,15 @@ export declare enum EnyoStorageScheduleDirectionEnum {
|
|
|
1646
1649
|
/** Power should flow from the battery into the grid / home (discharging). */
|
|
1647
1650
|
Discharge = "discharge",
|
|
1648
1651
|
/**
|
|
1649
|
-
*
|
|
1650
|
-
*
|
|
1651
|
-
*
|
|
1652
|
+
* Leave the slot to the battery's own logic — for the duration of
|
|
1653
|
+
* the entry the appliance decides itself whether to charge,
|
|
1654
|
+
* discharge or stand still (auto mode).
|
|
1655
|
+
*
|
|
1656
|
+
* This is *not* a "no energy flow" marker: to block charging or
|
|
1657
|
+
* discharging, use {@link EnyoStorageScheduleDirectionEnum.Charge}
|
|
1658
|
+
* respectively {@link EnyoStorageScheduleDirectionEnum.Discharge}
|
|
1659
|
+
* with `powerW = 0`. An `Idle` entry prescribes no setpoint, so its
|
|
1660
|
+
* `powerW` must be `0`.
|
|
1652
1661
|
*/
|
|
1653
1662
|
Idle = "idle"
|
|
1654
1663
|
}
|
|
@@ -1678,10 +1687,11 @@ export interface EnyoStorageScheduleEntry {
|
|
|
1678
1687
|
* Target power for this setpoint in Watts. Always non-negative —
|
|
1679
1688
|
* direction is carried by {@link direction}, never by sign. A
|
|
1680
1689
|
* `powerW` of `0` together with a `Charge` or `Discharge` direction
|
|
1681
|
-
*
|
|
1682
|
-
* until the next entry
|
|
1683
|
-
* {@link EnyoStorageScheduleDirectionEnum.Idle}
|
|
1684
|
-
*
|
|
1690
|
+
* blocks that direction — the battery must not charge respectively
|
|
1691
|
+
* discharge until the next entry. Use that to keep the battery
|
|
1692
|
+
* still, *not* {@link EnyoStorageScheduleDirectionEnum.Idle}, which
|
|
1693
|
+
* hands control back to the appliance's own logic and prescribes no
|
|
1694
|
+
* setpoint at all (its `powerW` must be `0`).
|
|
1685
1695
|
*/
|
|
1686
1696
|
powerW: number;
|
|
1687
1697
|
}
|
|
@@ -321,9 +321,11 @@ export var EnyoStorageScheduleModeEnum;
|
|
|
321
321
|
* non-negative, and consumers never have to disambiguate `0` from
|
|
322
322
|
* "direction-of-zero" or interpret sign conventions per integration.
|
|
323
323
|
*
|
|
324
|
-
* `Idle`
|
|
325
|
-
*
|
|
326
|
-
* `
|
|
324
|
+
* `Idle` hands the slot back to the battery's own logic — it does *not*
|
|
325
|
+
* mean "no energy flow". To keep the battery still, use `Charge` or
|
|
326
|
+
* `Discharge` with `powerW = 0`, which blocks that direction for the
|
|
327
|
+
* duration of the entry. An `Idle` entry prescribes no setpoint, so it
|
|
328
|
+
* must carry `powerW = 0`.
|
|
327
329
|
*/
|
|
328
330
|
export var EnyoStorageScheduleDirectionEnum;
|
|
329
331
|
(function (EnyoStorageScheduleDirectionEnum) {
|
|
@@ -332,9 +334,15 @@ export var EnyoStorageScheduleDirectionEnum;
|
|
|
332
334
|
/** Power should flow from the battery into the grid / home (discharging). */
|
|
333
335
|
EnyoStorageScheduleDirectionEnum["Discharge"] = "discharge";
|
|
334
336
|
/**
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
337
|
+
* Leave the slot to the battery's own logic — for the duration of
|
|
338
|
+
* the entry the appliance decides itself whether to charge,
|
|
339
|
+
* discharge or stand still (auto mode).
|
|
340
|
+
*
|
|
341
|
+
* This is *not* a "no energy flow" marker: to block charging or
|
|
342
|
+
* discharging, use {@link EnyoStorageScheduleDirectionEnum.Charge}
|
|
343
|
+
* respectively {@link EnyoStorageScheduleDirectionEnum.Discharge}
|
|
344
|
+
* with `powerW = 0`. An `Idle` entry prescribes no setpoint, so its
|
|
345
|
+
* `powerW` must be `0`.
|
|
338
346
|
*/
|
|
339
347
|
EnyoStorageScheduleDirectionEnum["Idle"] = "idle";
|
|
340
348
|
})(EnyoStorageScheduleDirectionEnum || (EnyoStorageScheduleDirectionEnum = {}));
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* (`../implementations/onboarding-v2/onboarding-v2-validators.ts`) to fail fast
|
|
21
21
|
* before publishing.
|
|
22
22
|
*/
|
|
23
|
-
import type {
|
|
23
|
+
import type { EnyoOnboardingTranslatedContent } from './enyo-onboarding.js';
|
|
24
24
|
/**
|
|
25
25
|
* The situation a flow starts from. A vendor/model can have up to one guide per
|
|
26
26
|
* variant; a branch can jump into another variant's flow
|
|
@@ -1067,21 +1067,6 @@ export interface EnyoOnboardingV2Guide {
|
|
|
1067
1067
|
title: EnyoOnboardingTranslatedContent[];
|
|
1068
1068
|
/** Which start situation this guide covers. */
|
|
1069
1069
|
startVariant: EnyoOnboardingV2StartVariant;
|
|
1070
|
-
/**
|
|
1071
|
-
* The lifecycle role this guide plays, which decides where the host offers
|
|
1072
|
-
* it (an "add new device" entry point, the configuration-required prompt).
|
|
1073
|
-
*
|
|
1074
|
-
* Distinct from {@link startVariant}, which describes the *situation the
|
|
1075
|
-
* flow starts from* (device not found, found but unconfigured, …). This says
|
|
1076
|
-
* *why the installer is here at all*: configuring the package for the first
|
|
1077
|
-
* time is a different entry point from adding a second device to a package
|
|
1078
|
-
* that already works, even when both start from `device-not-found`.
|
|
1079
|
-
*
|
|
1080
|
-
* Shared with the v1 model rather than restated as a v2 enum — the category
|
|
1081
|
-
* is a property of a guide's role, not of the authoring model. Defaults to
|
|
1082
|
-
* {@link EnyoOnboardingGuideCategory.InitialSetup} semantics when omitted.
|
|
1083
|
-
*/
|
|
1084
|
-
category?: EnyoOnboardingGuideCategory;
|
|
1085
1070
|
/**
|
|
1086
1071
|
* Whether the host runs its local network scan before entering this guide.
|
|
1087
1072
|
*
|
|
@@ -14,11 +14,9 @@ export interface EnyoOnboardingTranslatedContent {
|
|
|
14
14
|
* Used to distinguish guides that perform different roles, e.g. initial
|
|
15
15
|
* configuration of a package vs. adding or reconnecting a single device.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
* {@link EnyoOnboardingV2Guide
|
|
19
|
-
*
|
|
20
|
-
* the category is a property of a guide's role, not of the authoring model it
|
|
21
|
-
* was written in.
|
|
17
|
+
* @deprecated Superseded by the v2 graph model. Author guides with
|
|
18
|
+
* {@link EnyoOnboardingV2Guide} via `defineOnboardingGuideV2()`. v1 is retained
|
|
19
|
+
* for backward compatibility and will be removed in a future major.
|
|
22
20
|
*/
|
|
23
21
|
export declare enum EnyoOnboardingGuideCategory {
|
|
24
22
|
/** Initial package configuration — shown when EnergyAppStateEnum is 'configuration-required' */
|
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
* Used to distinguish guides that perform different roles, e.g. initial
|
|
4
4
|
* configuration of a package vs. adding or reconnecting a single device.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* {@link EnyoOnboardingV2Guide
|
|
8
|
-
*
|
|
9
|
-
* the category is a property of a guide's role, not of the authoring model it
|
|
10
|
-
* was written in.
|
|
6
|
+
* @deprecated Superseded by the v2 graph model. Author guides with
|
|
7
|
+
* {@link EnyoOnboardingV2Guide} via `defineOnboardingGuideV2()`. v1 is retained
|
|
8
|
+
* for backward compatibility and will be removed in a future major.
|
|
11
9
|
*/
|
|
12
10
|
export var EnyoOnboardingGuideCategory;
|
|
13
11
|
(function (EnyoOnboardingGuideCategory) {
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED