@enyo-energy/sunspec-sdk 0.0.31 → 0.0.33
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/dist/cjs/connection-retry-manager.cjs +63 -80
- package/dist/cjs/connection-retry-manager.d.cts +32 -27
- package/dist/cjs/sunspec-devices.cjs +201 -33
- package/dist/cjs/sunspec-devices.d.cts +56 -6
- package/dist/cjs/sunspec-interfaces.cjs +109 -5
- package/dist/cjs/sunspec-interfaces.d.cts +191 -5
- package/dist/cjs/sunspec-modbus-client.cjs +599 -290
- package/dist/cjs/sunspec-modbus-client.d.cts +43 -27
- package/dist/cjs/version.cjs +1 -1
- package/dist/cjs/version.d.cts +1 -1
- package/dist/connection-retry-manager.d.ts +32 -27
- package/dist/connection-retry-manager.js +63 -80
- package/dist/sunspec-devices.d.ts +56 -6
- package/dist/sunspec-devices.js +201 -33
- package/dist/sunspec-interfaces.d.ts +191 -5
- package/dist/sunspec-interfaces.js +108 -4
- package/dist/sunspec-modbus-client.d.ts +43 -27
- package/dist/sunspec-modbus-client.js +600 -291
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
|
@@ -16,9 +16,8 @@
|
|
|
16
16
|
* - pad: 0x8000 (always returns this value)
|
|
17
17
|
* - string: all registers 0x0000 (NULL)
|
|
18
18
|
*/
|
|
19
|
-
import { type SunspecInverterControls, type SunspecInverterData, type SunspecInverterSettings, type SunspecMeterData, type SunspecModel, type SunspecMPPTData, type SunspecBatteryData, type SunspecBatteryControls, SunspecStorageMode
|
|
20
|
-
import {
|
|
21
|
-
import { IConnectionHealth } from "@enyo-energy/energy-app-sdk/dist/implementations/modbus/interfaces.js";
|
|
19
|
+
import { type SunspecInverterControls, type SunspecInverterData, type SunspecInverterSettings, type SunspecMeterData, type SunspecModel, type SunspecMPPTData, type SunspecBatteryData, type SunspecBatteryBaseData, type SunspecBatteryControls, SunspecStorageMode } from "./sunspec-interfaces.cjs";
|
|
20
|
+
import { EnergyAppModbusDataType, IConnectionHealth } from "@enyo-energy/energy-app-sdk/dist/implementations/modbus/interfaces.js";
|
|
22
21
|
import { EnergyApp } from "@enyo-energy/energy-app-sdk";
|
|
23
22
|
export declare class SunspecModbusClient {
|
|
24
23
|
private energyApp;
|
|
@@ -29,9 +28,8 @@ export declare class SunspecModbusClient {
|
|
|
29
28
|
private faultTolerantReader;
|
|
30
29
|
private modbusDataTypeConverter;
|
|
31
30
|
private connectionParams;
|
|
32
|
-
private retryManager;
|
|
33
31
|
private autoReconnectEnabled;
|
|
34
|
-
constructor(energyApp: EnergyApp
|
|
32
|
+
constructor(energyApp: EnergyApp);
|
|
35
33
|
/**
|
|
36
34
|
* Connect to Modbus device
|
|
37
35
|
* @param host Primary host (hostname) to connect to
|
|
@@ -55,11 +53,6 @@ export declare class SunspecModbusClient {
|
|
|
55
53
|
* Returns true if successful, false otherwise
|
|
56
54
|
*/
|
|
57
55
|
private attemptConnection;
|
|
58
|
-
/**
|
|
59
|
-
* Check connection health and trigger automatic reconnection if unhealthy
|
|
60
|
-
* Returns true if connection is healthy or was successfully restored
|
|
61
|
-
*/
|
|
62
|
-
ensureHealthyConnection(): Promise<boolean>;
|
|
63
56
|
/**
|
|
64
57
|
* Enable or disable automatic reconnection
|
|
65
58
|
*/
|
|
@@ -68,10 +61,6 @@ export declare class SunspecModbusClient {
|
|
|
68
61
|
* Check if auto-reconnect is enabled
|
|
69
62
|
*/
|
|
70
63
|
isAutoReconnectEnabled(): boolean;
|
|
71
|
-
/**
|
|
72
|
-
* Get the retry manager for advanced configuration
|
|
73
|
-
*/
|
|
74
|
-
getRetryManager(): ConnectionRetryManager;
|
|
75
64
|
/**
|
|
76
65
|
* Detect the base address and addressing mode (0-based or 1-based) for SunSpec
|
|
77
66
|
*/
|
|
@@ -119,13 +108,13 @@ export declare class SunspecModbusClient {
|
|
|
119
108
|
/**
|
|
120
109
|
* Helper to read register value(s) using the fault-tolerant reader with data type conversion
|
|
121
110
|
*/
|
|
122
|
-
|
|
111
|
+
readRegisterValue(address: number, quantity: number | undefined, dataType: EnergyAppModbusDataType): Promise<number | string | number[]>;
|
|
123
112
|
/**
|
|
124
113
|
* Helper to write register value(s)
|
|
125
114
|
*/
|
|
126
|
-
|
|
115
|
+
writeRegisterValue(address: number, value: number | number[], dataType?: EnergyAppModbusDataType): Promise<boolean>;
|
|
127
116
|
/**
|
|
128
|
-
* Read inverter data from Model 103 (Three Phase)
|
|
117
|
+
* Read inverter data from Model 101 (Single Phase) / Model 103 (Three Phase)
|
|
129
118
|
*/
|
|
130
119
|
readInverterData(): Promise<SunspecInverterData | null>;
|
|
131
120
|
/**
|
|
@@ -140,10 +129,10 @@ export declare class SunspecModbusClient {
|
|
|
140
129
|
* Apply scale factor to a value
|
|
141
130
|
* Returns undefined if the value is unimplemented or scale factor is out of range
|
|
142
131
|
*/
|
|
143
|
-
|
|
132
|
+
applyScaleFactor(value: number, scaleFactor: number, dataType?: 'uint16' | 'int16' | 'acc32', fieldName?: string, offset?: number, modelId?: number): number | undefined;
|
|
133
|
+
logRegisterRead(modelId: number, offset: number, fieldName: string, rawValue: number | string | undefined, dataType?: string): void;
|
|
144
134
|
/**
|
|
145
|
-
* Read
|
|
146
|
-
* Returns the scale factors for DC Current, DC Voltage, DC Power, and DC Energy
|
|
135
|
+
* Read scale factors from Model 160 (MPPT)
|
|
147
136
|
*
|
|
148
137
|
* MPPT Model 160 Scale Factor Register Offsets (relative to module start):
|
|
149
138
|
* - DCA_SF (Current Scale Factor): Offset 2
|
|
@@ -164,7 +153,7 @@ export declare class SunspecModbusClient {
|
|
|
164
153
|
*/
|
|
165
154
|
readMPPTData(moduleId?: number): Promise<SunspecMPPTData | null>;
|
|
166
155
|
/**
|
|
167
|
-
* Read all
|
|
156
|
+
* Read all MPPT strings from Model 160 (Multiple MPPT)
|
|
168
157
|
*/
|
|
169
158
|
readAllMPPTData(): Promise<SunspecMPPTData[]>;
|
|
170
159
|
/**
|
|
@@ -174,7 +163,23 @@ export declare class SunspecModbusClient {
|
|
|
174
163
|
*/
|
|
175
164
|
private mapBatteryChargeState;
|
|
176
165
|
/**
|
|
177
|
-
*
|
|
166
|
+
* Map battery type to human-readable name (Model 802)
|
|
167
|
+
*/
|
|
168
|
+
private mapBatteryType;
|
|
169
|
+
/**
|
|
170
|
+
* Map battery bank state to human-readable name (Model 802)
|
|
171
|
+
*/
|
|
172
|
+
private mapBatteryBankState;
|
|
173
|
+
/**
|
|
174
|
+
* Read Model 802 scale factors (offsets 52-63)
|
|
175
|
+
*/
|
|
176
|
+
private readBatteryBaseScaleFactors;
|
|
177
|
+
/**
|
|
178
|
+
* Read battery base data from Model 802 (Battery Base)
|
|
179
|
+
*/
|
|
180
|
+
readBatteryBaseData(): Promise<SunspecBatteryBaseData | null>;
|
|
181
|
+
/**
|
|
182
|
+
* Read battery data from Model 124 (Basic Storage) with fallback to Model 802 / Model 803
|
|
178
183
|
*/
|
|
179
184
|
readBatteryData(): Promise<SunspecBatteryData | null>;
|
|
180
185
|
/**
|
|
@@ -190,11 +195,11 @@ export declare class SunspecModbusClient {
|
|
|
190
195
|
*/
|
|
191
196
|
enableGridCharging(enable: boolean): Promise<boolean>;
|
|
192
197
|
/**
|
|
193
|
-
* Read
|
|
198
|
+
* Read battery control settings from Model 124 (Basic Storage Controls)
|
|
194
199
|
*/
|
|
195
200
|
readBatteryControls(): Promise<SunspecBatteryControls | null>;
|
|
196
201
|
/**
|
|
197
|
-
* Read meter data (Model 203
|
|
202
|
+
* Read meter data from Model 201 (Single Phase) / Model 203 (Three Phase) / Model 204 (Split Phase)
|
|
198
203
|
*/
|
|
199
204
|
readMeterData(): Promise<SunspecMeterData | null>;
|
|
200
205
|
/**
|
|
@@ -218,11 +223,11 @@ export declare class SunspecModbusClient {
|
|
|
218
223
|
*/
|
|
219
224
|
getConnectionHealth(): IConnectionHealth;
|
|
220
225
|
/**
|
|
221
|
-
* Read
|
|
226
|
+
* Read inverter settings from Model 121 (Inverter Settings)
|
|
222
227
|
*/
|
|
223
228
|
readInverterSettings(): Promise<SunspecInverterSettings | null>;
|
|
224
229
|
/**
|
|
225
|
-
* Read
|
|
230
|
+
* Read inverter controls from Model 123 (Immediate Inverter Controls)
|
|
226
231
|
*/
|
|
227
232
|
readInverterControls(): Promise<SunspecInverterControls | null>;
|
|
228
233
|
/**
|
|
@@ -230,7 +235,18 @@ export declare class SunspecModbusClient {
|
|
|
230
235
|
*/
|
|
231
236
|
writeInverterSettings(settings: Partial<SunspecInverterSettings>): Promise<boolean>;
|
|
232
237
|
/**
|
|
233
|
-
* Write
|
|
238
|
+
* Write inverter controls to Model 123 (Immediate Inverter Controls)
|
|
234
239
|
*/
|
|
235
240
|
writeInverterControls(controls: Partial<SunspecInverterControls>): Promise<boolean>;
|
|
241
|
+
/**
|
|
242
|
+
* Set the inverter feed-in power limit using Model 123 (Immediate Inverter Controls)
|
|
243
|
+
*
|
|
244
|
+
* When limitW is a number, reads WMax from Model 121, computes percentage,
|
|
245
|
+
* writes WMaxLimPct and enables WMaxLim_Ena.
|
|
246
|
+
* When limitW is null, disables the limit by setting WMaxLim_Ena = DISABLED.
|
|
247
|
+
*
|
|
248
|
+
* @param limitW - Power limit in Watts, or null to remove the limit
|
|
249
|
+
* @returns true if successful, false otherwise
|
|
250
|
+
*/
|
|
251
|
+
setFeedInLimit(limitW: number | null): Promise<boolean>;
|
|
236
252
|
}
|
package/dist/cjs/version.cjs
CHANGED
|
@@ -9,7 +9,7 @@ exports.getSdkVersion = getSdkVersion;
|
|
|
9
9
|
/**
|
|
10
10
|
* Current version of the enyo Energy App SDK.
|
|
11
11
|
*/
|
|
12
|
-
exports.SDK_VERSION = '0.0.
|
|
12
|
+
exports.SDK_VERSION = '0.0.33';
|
|
13
13
|
/**
|
|
14
14
|
* Gets the current SDK version.
|
|
15
15
|
* @returns The semantic version string of the SDK
|
package/dist/cjs/version.d.cts
CHANGED
|
@@ -1,53 +1,58 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Connection Retry Manager with
|
|
2
|
+
* Connection Retry Manager with Tiered Schedule
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Poll-based retry manager — no timers or setTimeout loops.
|
|
5
|
+
* Called on each readData() cycle; determines whether enough time has elapsed
|
|
6
|
+
* to attempt a reconnection based on the current retry phase.
|
|
7
|
+
*
|
|
8
|
+
* Default schedule:
|
|
9
|
+
* - Phase 1: every 10s for 1 minute
|
|
10
|
+
* - Phase 2: every 30s for 2 minutes
|
|
11
|
+
* - Phase 3: every 1m for 5 minutes
|
|
12
|
+
* - Phase 4: every 5m forever
|
|
6
13
|
*/
|
|
7
|
-
import { IRetryConfig } from './sunspec-interfaces.js';
|
|
14
|
+
import { IRetryConfig, IRetryPhase } from './sunspec-interfaces.js';
|
|
8
15
|
export declare class ConnectionRetryManager {
|
|
9
16
|
private config;
|
|
10
|
-
private
|
|
11
|
-
private
|
|
12
|
-
private
|
|
13
|
-
constructor(config?:
|
|
17
|
+
private disconnectedSince;
|
|
18
|
+
private lastAttemptTime;
|
|
19
|
+
private attemptCount;
|
|
20
|
+
constructor(config?: IRetryConfig);
|
|
14
21
|
/**
|
|
15
|
-
*
|
|
16
|
-
* Formula: min(initialDelayMs * backoffFactor^attempt, maxDelayMs)
|
|
22
|
+
* Mark the connection as disconnected. Sets the timestamp if not already set.
|
|
17
23
|
*/
|
|
18
|
-
|
|
24
|
+
markDisconnected(): void;
|
|
19
25
|
/**
|
|
20
|
-
* Reset
|
|
26
|
+
* Reset all retry state (call on successful reconnect).
|
|
21
27
|
*/
|
|
22
28
|
reset(): void;
|
|
23
29
|
/**
|
|
24
|
-
*
|
|
25
|
-
* Returns true if we haven't exceeded maxAttempts or if maxAttempts is -1 (infinite)
|
|
30
|
+
* Determine which retry phase we're currently in based on elapsed time since disconnect.
|
|
26
31
|
*/
|
|
27
|
-
|
|
32
|
+
getCurrentPhase(): IRetryPhase;
|
|
28
33
|
/**
|
|
29
|
-
*
|
|
34
|
+
* Check if we should attempt a reconnection now.
|
|
35
|
+
* Called on every readData() poll cycle.
|
|
30
36
|
*/
|
|
31
|
-
|
|
37
|
+
shouldAttemptNow(): boolean;
|
|
32
38
|
/**
|
|
33
|
-
*
|
|
39
|
+
* Record that an attempt was just made.
|
|
34
40
|
*/
|
|
35
|
-
|
|
41
|
+
recordAttempt(): void;
|
|
36
42
|
/**
|
|
37
|
-
*
|
|
43
|
+
* Get the number of reconnection attempts made.
|
|
38
44
|
*/
|
|
39
|
-
|
|
45
|
+
getAttemptCount(): number;
|
|
40
46
|
/**
|
|
41
|
-
*
|
|
42
|
-
* Returns a promise that resolves when the callback completes
|
|
47
|
+
* Get milliseconds elapsed since disconnect was first detected.
|
|
43
48
|
*/
|
|
44
|
-
|
|
49
|
+
getElapsedMs(): number;
|
|
45
50
|
/**
|
|
46
|
-
*
|
|
51
|
+
* Check if the manager is currently tracking a disconnection.
|
|
47
52
|
*/
|
|
48
|
-
|
|
53
|
+
isDisconnected(): boolean;
|
|
49
54
|
/**
|
|
50
|
-
* Get the current configuration
|
|
55
|
+
* Get the current configuration.
|
|
51
56
|
*/
|
|
52
57
|
getConfig(): IRetryConfig;
|
|
53
58
|
}
|
|
@@ -1,119 +1,102 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Connection Retry Manager with
|
|
2
|
+
* Connection Retry Manager with Tiered Schedule
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Poll-based retry manager — no timers or setTimeout loops.
|
|
5
|
+
* Called on each readData() cycle; determines whether enough time has elapsed
|
|
6
|
+
* to attempt a reconnection based on the current retry phase.
|
|
7
|
+
*
|
|
8
|
+
* Default schedule:
|
|
9
|
+
* - Phase 1: every 10s for 1 minute
|
|
10
|
+
* - Phase 2: every 30s for 2 minutes
|
|
11
|
+
* - Phase 3: every 1m for 5 minutes
|
|
12
|
+
* - Phase 4: every 5m forever
|
|
6
13
|
*/
|
|
7
14
|
import { DEFAULT_RETRY_CONFIG } from './sunspec-interfaces.js';
|
|
8
15
|
export class ConnectionRetryManager {
|
|
9
16
|
config;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
disconnectedSince = null;
|
|
18
|
+
lastAttemptTime = 0;
|
|
19
|
+
attemptCount = 0;
|
|
13
20
|
constructor(config) {
|
|
14
|
-
this.config =
|
|
21
|
+
this.config = config ?? DEFAULT_RETRY_CONFIG;
|
|
15
22
|
}
|
|
16
23
|
/**
|
|
17
|
-
*
|
|
18
|
-
* Formula: min(initialDelayMs * backoffFactor^attempt, maxDelayMs)
|
|
24
|
+
* Mark the connection as disconnected. Sets the timestamp if not already set.
|
|
19
25
|
*/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
markDisconnected() {
|
|
27
|
+
if (this.disconnectedSince === null) {
|
|
28
|
+
this.disconnectedSince = Date.now();
|
|
29
|
+
}
|
|
23
30
|
}
|
|
24
31
|
/**
|
|
25
|
-
* Reset
|
|
32
|
+
* Reset all retry state (call on successful reconnect).
|
|
26
33
|
*/
|
|
27
34
|
reset() {
|
|
28
|
-
this.
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
35
|
+
this.disconnectedSince = null;
|
|
36
|
+
this.lastAttemptTime = 0;
|
|
37
|
+
this.attemptCount = 0;
|
|
31
38
|
}
|
|
32
39
|
/**
|
|
33
|
-
*
|
|
34
|
-
* Returns true if we haven't exceeded maxAttempts or if maxAttempts is -1 (infinite)
|
|
40
|
+
* Determine which retry phase we're currently in based on elapsed time since disconnect.
|
|
35
41
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
getCurrentPhase() {
|
|
43
|
+
const elapsed = this.getElapsedMs();
|
|
44
|
+
let cumulativeDuration = 0;
|
|
45
|
+
for (const phase of this.config.phases) {
|
|
46
|
+
if (phase.durationMs === 0) {
|
|
47
|
+
// This is the final "forever" phase
|
|
48
|
+
return phase;
|
|
49
|
+
}
|
|
50
|
+
cumulativeDuration += phase.durationMs;
|
|
51
|
+
if (elapsed < cumulativeDuration) {
|
|
52
|
+
return phase;
|
|
53
|
+
}
|
|
39
54
|
}
|
|
40
|
-
return
|
|
55
|
+
// Fallback: return last phase
|
|
56
|
+
return this.config.phases[this.config.phases.length - 1];
|
|
41
57
|
}
|
|
42
58
|
/**
|
|
43
|
-
*
|
|
59
|
+
* Check if we should attempt a reconnection now.
|
|
60
|
+
* Called on every readData() poll cycle.
|
|
44
61
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
62
|
+
shouldAttemptNow() {
|
|
63
|
+
if (this.disconnectedSince === null) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const now = Date.now();
|
|
67
|
+
const phase = this.getCurrentPhase();
|
|
68
|
+
return (now - this.lastAttemptTime) >= phase.intervalMs;
|
|
47
69
|
}
|
|
48
70
|
/**
|
|
49
|
-
*
|
|
71
|
+
* Record that an attempt was just made.
|
|
50
72
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
73
|
+
recordAttempt() {
|
|
74
|
+
this.lastAttemptTime = Date.now();
|
|
75
|
+
this.attemptCount++;
|
|
53
76
|
}
|
|
54
77
|
/**
|
|
55
|
-
*
|
|
78
|
+
* Get the number of reconnection attempts made.
|
|
56
79
|
*/
|
|
57
|
-
|
|
58
|
-
return this.
|
|
80
|
+
getAttemptCount() {
|
|
81
|
+
return this.attemptCount;
|
|
59
82
|
}
|
|
60
83
|
/**
|
|
61
|
-
*
|
|
62
|
-
* Returns a promise that resolves when the callback completes
|
|
84
|
+
* Get milliseconds elapsed since disconnect was first detected.
|
|
63
85
|
*/
|
|
64
|
-
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
if (this.isRetrying) {
|
|
70
|
-
console.log('Retry already in progress, skipping duplicate request.');
|
|
71
|
-
return false;
|
|
86
|
+
getElapsedMs() {
|
|
87
|
+
if (this.disconnectedSince === null) {
|
|
88
|
+
return 0;
|
|
72
89
|
}
|
|
73
|
-
|
|
74
|
-
const delay = this.getNextDelay();
|
|
75
|
-
const attemptNumber = this.currentAttempt + 1;
|
|
76
|
-
const maxAttemptsStr = this.config.maxAttempts === -1 ? '∞' : this.config.maxAttempts.toString();
|
|
77
|
-
console.log(`Scheduling reconnection attempt ${attemptNumber}/${maxAttemptsStr} in ${delay}ms`);
|
|
78
|
-
return new Promise((resolve) => {
|
|
79
|
-
this.pendingRetryTimeout = setTimeout(async () => {
|
|
80
|
-
this.pendingRetryTimeout = null;
|
|
81
|
-
this.currentAttempt++;
|
|
82
|
-
try {
|
|
83
|
-
console.log(`Attempting reconnection (attempt ${attemptNumber}/${maxAttemptsStr})...`);
|
|
84
|
-
const success = await callback();
|
|
85
|
-
if (success) {
|
|
86
|
-
console.log('Reconnection successful!');
|
|
87
|
-
this.reset();
|
|
88
|
-
resolve(true);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
console.log('Reconnection attempt failed.');
|
|
92
|
-
this.isRetrying = false;
|
|
93
|
-
resolve(false);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
console.error(`Reconnection attempt failed with error: ${error}`);
|
|
98
|
-
this.isRetrying = false;
|
|
99
|
-
resolve(false);
|
|
100
|
-
}
|
|
101
|
-
}, delay);
|
|
102
|
-
});
|
|
90
|
+
return Date.now() - this.disconnectedSince;
|
|
103
91
|
}
|
|
104
92
|
/**
|
|
105
|
-
*
|
|
93
|
+
* Check if the manager is currently tracking a disconnection.
|
|
106
94
|
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
clearTimeout(this.pendingRetryTimeout);
|
|
110
|
-
this.pendingRetryTimeout = null;
|
|
111
|
-
this.isRetrying = false;
|
|
112
|
-
console.log('Pending retry cancelled.');
|
|
113
|
-
}
|
|
95
|
+
isDisconnected() {
|
|
96
|
+
return this.disconnectedSince !== null;
|
|
114
97
|
}
|
|
115
98
|
/**
|
|
116
|
-
* Get the current configuration
|
|
99
|
+
* Get the current configuration.
|
|
117
100
|
*/
|
|
118
101
|
getConfig() {
|
|
119
102
|
return { ...this.config };
|
|
@@ -1,9 +1,22 @@
|
|
|
1
|
-
import { type SunspecBatteryControls, SunspecStorageMode } from "./sunspec-interfaces.js";
|
|
1
|
+
import { type SunspecBatteryBaseData, type SunspecBatteryControls, SunspecStorageMode, SunspecInverterCapability, SunspecBatteryCapability, SunspecMeterCapability } from "./sunspec-interfaces.js";
|
|
2
2
|
import { ApplianceManager, EnergyApp } from "@enyo-energy/energy-app-sdk";
|
|
3
3
|
import { EnyoApplianceName } from "@enyo-energy/energy-app-sdk/dist/types/enyo-appliance.js";
|
|
4
4
|
import { EnyoNetworkDevice } from "@enyo-energy/energy-app-sdk/dist/types/enyo-network-device.js";
|
|
5
5
|
import { SunspecModbusClient } from "./sunspec-modbus-client.js";
|
|
6
|
-
import {
|
|
6
|
+
import { ConnectionRetryManager } from "./connection-retry-manager.js";
|
|
7
|
+
import { type IRetryConfig } from "./sunspec-interfaces.js";
|
|
8
|
+
import { EnyoCommandAcknowledgeAnswerEnum, EnyoDataBusMessage, EnyoDataBusMessageEnum, EnyoDataBusMessageResolution } from "@enyo-energy/energy-app-sdk/dist/types/enyo-data-bus-value.js";
|
|
9
|
+
import { EnergyAppDataBus } from "@enyo-energy/energy-app-sdk/dist/packages/energy-app-data-bus.js";
|
|
10
|
+
export declare const ENYO_DATA_BUS_SET_INVERTER_FEED_IN_LIMIT_V1 = "SetInverterFeedInLimitV1";
|
|
11
|
+
export interface EnyoDataBusSetInverterFeedInLimitV1 {
|
|
12
|
+
id: string;
|
|
13
|
+
type: 'message';
|
|
14
|
+
message: string;
|
|
15
|
+
applianceId: string;
|
|
16
|
+
data: {
|
|
17
|
+
feedInLimitW: number | null;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
7
20
|
/**
|
|
8
21
|
* Base abstract class for all Sunspec devices
|
|
9
22
|
*/
|
|
@@ -18,7 +31,10 @@ export declare abstract class BaseSunspecDevice {
|
|
|
18
31
|
protected readonly baseAddress: number;
|
|
19
32
|
protected applianceId?: string;
|
|
20
33
|
protected lastUpdateTime: number;
|
|
21
|
-
|
|
34
|
+
protected dataBusListenerId?: string;
|
|
35
|
+
protected dataBus?: EnergyAppDataBus;
|
|
36
|
+
protected retryManager: ConnectionRetryManager;
|
|
37
|
+
constructor(energyApp: EnergyApp, name: EnyoApplianceName[], networkDevice: EnyoNetworkDevice, sunspecClient: SunspecModbusClient, applianceManager: ApplianceManager, unitId?: number, port?: number, baseAddress?: number, retryConfig?: IRetryConfig);
|
|
22
38
|
/**
|
|
23
39
|
* Connect to the device and create/update the appliance
|
|
24
40
|
*/
|
|
@@ -42,11 +58,24 @@ export declare abstract class BaseSunspecDevice {
|
|
|
42
58
|
* Ensure the Sunspec client is connected and models are discovered
|
|
43
59
|
*/
|
|
44
60
|
protected ensureConnected(): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Attempt a reconnection if the tiered retry schedule allows it.
|
|
63
|
+
* Called from readData() when the device is disconnected.
|
|
64
|
+
* Returns true if reconnection succeeded.
|
|
65
|
+
*/
|
|
66
|
+
protected tryReconnect(): Promise<boolean>;
|
|
67
|
+
/**
|
|
68
|
+
* Mark the device as offline: update appliance state and start tracking disconnection.
|
|
69
|
+
*/
|
|
70
|
+
protected markOffline(): Promise<void>;
|
|
71
|
+
protected sendCommandAcknowledge(messageId: string, acknowledgeMessage: EnyoDataBusMessageEnum | string, answer: EnyoCommandAcknowledgeAnswerEnum, rejectionReason?: string): void;
|
|
45
72
|
}
|
|
46
73
|
/**
|
|
47
74
|
* Sunspec Inverter implementation using dynamic model discovery
|
|
48
75
|
*/
|
|
49
76
|
export declare class SunspecInverter extends BaseSunspecDevice {
|
|
77
|
+
private readonly capabilities;
|
|
78
|
+
constructor(energyApp: EnergyApp, name: EnyoApplianceName[], networkDevice: EnyoNetworkDevice, sunspecClient: SunspecModbusClient, applianceManager: ApplianceManager, unitId?: number, port?: number, baseAddress?: number, capabilities?: SunspecInverterCapability[], retryConfig?: IRetryConfig);
|
|
50
79
|
connect(): Promise<void>;
|
|
51
80
|
disconnect(): Promise<void>;
|
|
52
81
|
isConnected(): boolean;
|
|
@@ -59,13 +88,24 @@ export declare class SunspecInverter extends BaseSunspecDevice {
|
|
|
59
88
|
private mapMPPTToStrings;
|
|
60
89
|
private mapMPPTOperatingState;
|
|
61
90
|
private mapDcStringToApplianceMetadata;
|
|
91
|
+
/**
|
|
92
|
+
* Start listening for inverter commands on the data bus.
|
|
93
|
+
* Idempotent — does nothing if already listening.
|
|
94
|
+
*/
|
|
95
|
+
startDataBusListening(): void;
|
|
96
|
+
/**
|
|
97
|
+
* Stop listening for inverter commands on the data bus.
|
|
98
|
+
*/
|
|
99
|
+
stopDataBusListening(): void;
|
|
100
|
+
private handleInverterCommand;
|
|
101
|
+
private handleSetFeedInLimit;
|
|
62
102
|
}
|
|
63
103
|
/**
|
|
64
104
|
* Sunspec Battery implementation
|
|
65
105
|
*/
|
|
66
106
|
export declare class SunspecBattery extends BaseSunspecDevice {
|
|
67
|
-
private
|
|
68
|
-
|
|
107
|
+
private readonly capabilities;
|
|
108
|
+
constructor(energyApp: EnergyApp, name: EnyoApplianceName[], networkDevice: EnyoNetworkDevice, sunspecClient: SunspecModbusClient, applianceManager: ApplianceManager, unitId?: number, port?: number, baseAddress?: number, capabilities?: SunspecBatteryCapability[], retryConfig?: IRetryConfig);
|
|
69
109
|
/**
|
|
70
110
|
* Connect to the battery and create/update the appliance
|
|
71
111
|
*/
|
|
@@ -130,6 +170,15 @@ export declare class SunspecBattery extends BaseSunspecDevice {
|
|
|
130
170
|
* @returns Promise<SunspecBatteryControls | null> - Current control settings or null if error
|
|
131
171
|
*/
|
|
132
172
|
getBatteryControls(): Promise<SunspecBatteryControls | null>;
|
|
173
|
+
/**
|
|
174
|
+
* Read full battery base data from Model 802
|
|
175
|
+
*
|
|
176
|
+
* Returns the complete Model 802 data structure with all fields,
|
|
177
|
+
* including nameplate, SoC/health, status, events, voltage, current, and power.
|
|
178
|
+
*
|
|
179
|
+
* @returns Promise<SunspecBatteryBaseData | null> - Full model 802 data or null if not available
|
|
180
|
+
*/
|
|
181
|
+
readBatteryBaseData(): Promise<SunspecBatteryBaseData | null>;
|
|
133
182
|
/**
|
|
134
183
|
* Write custom battery control settings
|
|
135
184
|
*
|
|
@@ -167,12 +216,13 @@ export declare class SunspecBattery extends BaseSunspecDevice {
|
|
|
167
216
|
private handleStartGridCharge;
|
|
168
217
|
private handleStopGridCharge;
|
|
169
218
|
private handleSetDischargeLimit;
|
|
170
|
-
private sendCommandAcknowledge;
|
|
171
219
|
}
|
|
172
220
|
/**
|
|
173
221
|
* Sunspec Meter implementation
|
|
174
222
|
*/
|
|
175
223
|
export declare class SunspecMeter extends BaseSunspecDevice {
|
|
224
|
+
private readonly capabilities;
|
|
225
|
+
constructor(energyApp: EnergyApp, name: EnyoApplianceName[], networkDevice: EnyoNetworkDevice, sunspecClient: SunspecModbusClient, applianceManager: ApplianceManager, unitId?: number, port?: number, baseAddress?: number, capabilities?: SunspecMeterCapability[], retryConfig?: IRetryConfig);
|
|
176
226
|
/**
|
|
177
227
|
* Connect to the meter and create/update the appliance
|
|
178
228
|
*/
|