@enyo-energy/sunspec-sdk 0.0.32 → 0.0.34
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 +178 -51
- package/dist/cjs/sunspec-devices.d.cts +47 -6
- package/dist/cjs/sunspec-interfaces.cjs +28 -5
- package/dist/cjs/sunspec-interfaces.d.cts +18 -5
- package/dist/cjs/sunspec-modbus-client.cjs +61 -91
- package/dist/cjs/sunspec-modbus-client.d.cts +27 -28
- 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 +47 -6
- package/dist/sunspec-devices.js +178 -51
- package/dist/sunspec-interfaces.d.ts +18 -5
- package/dist/sunspec-interfaces.js +27 -4
- package/dist/sunspec-modbus-client.d.ts +27 -28
- package/dist/sunspec-modbus-client.js +62 -92
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
|
@@ -1,9 +1,22 @@
|
|
|
1
|
-
import { type SunspecBatteryBaseData, type SunspecBatteryControls, SunspecStorageMode } from "./sunspec-interfaces.cjs";
|
|
1
|
+
import { type SunspecBatteryBaseData, type SunspecBatteryControls, SunspecStorageMode, SunspecInverterCapability, SunspecBatteryCapability, SunspecMeterCapability } from "./sunspec-interfaces.cjs";
|
|
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.cjs";
|
|
6
|
-
import {
|
|
6
|
+
import { ConnectionRetryManager } from "./connection-retry-manager.cjs";
|
|
7
|
+
import { type IRetryConfig } from "./sunspec-interfaces.cjs";
|
|
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
|
*/
|
|
@@ -176,12 +216,13 @@ export declare class SunspecBattery extends BaseSunspecDevice {
|
|
|
176
216
|
private handleStartGridCharge;
|
|
177
217
|
private handleStopGridCharge;
|
|
178
218
|
private handleSetDischargeLimit;
|
|
179
|
-
private sendCommandAcknowledge;
|
|
180
219
|
}
|
|
181
220
|
/**
|
|
182
221
|
* Sunspec Meter implementation
|
|
183
222
|
*/
|
|
184
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);
|
|
185
226
|
/**
|
|
186
227
|
* Connect to the meter and create/update the appliance
|
|
187
228
|
*/
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* SunSpec block interfaces with block numbers
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.SunspecStorageMode = exports.SunspecChargeSource = exports.SunspecVArPctMode = exports.SunspecEnableControl = exports.SunspecConnectionControl = exports.SunspecStorageControlMode = exports.SunspecBatteryEvent1 = exports.SunspecBatteryBankState = exports.SunspecBatteryType = exports.SunspecBatteryControlMode = exports.SunspecBatteryChargeState = exports.SunspecMPPTOperatingState = exports.SunspecModelId = exports.DEFAULT_RETRY_CONFIG = void 0;
|
|
6
|
+
exports.SunspecMeterCapability = exports.SunspecBatteryCapability = exports.SunspecInverterCapability = exports.SunspecStorageMode = exports.SunspecChargeSource = exports.SunspecVArPctMode = exports.SunspecEnableControl = exports.SunspecConnectionControl = exports.SunspecStorageControlMode = exports.SunspecBatteryEvent1 = exports.SunspecBatteryBankState = exports.SunspecBatteryType = exports.SunspecBatteryControlMode = exports.SunspecBatteryChargeState = exports.SunspecMPPTOperatingState = exports.SunspecModelId = exports.DEFAULT_RETRY_CONFIG = void 0;
|
|
7
7
|
exports.DEFAULT_RETRY_CONFIG = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
phases: [
|
|
9
|
+
{ intervalMs: 10_000, durationMs: 60_000 }, // Phase 1: every 10s for 1 minute
|
|
10
|
+
{ intervalMs: 30_000, durationMs: 120_000 }, // Phase 2: every 30s for 2 minutes
|
|
11
|
+
{ intervalMs: 60_000, durationMs: 300_000 }, // Phase 3: every 1m for 5 minutes
|
|
12
|
+
{ intervalMs: 300_000, durationMs: 0 }, // Phase 4: every 5m forever
|
|
13
|
+
]
|
|
12
14
|
};
|
|
13
15
|
/**
|
|
14
16
|
* Common Sunspec Model IDs
|
|
@@ -200,3 +202,24 @@ var SunspecStorageMode;
|
|
|
200
202
|
SunspecStorageMode["HOLDING"] = "holding";
|
|
201
203
|
SunspecStorageMode["AUTO"] = "auto"; // Both charge and discharge allowed
|
|
202
204
|
})(SunspecStorageMode || (exports.SunspecStorageMode = SunspecStorageMode = {}));
|
|
205
|
+
/**
|
|
206
|
+
* Battery control structure for writing to Model 124
|
|
207
|
+
* Used for controlling battery charge/discharge behavior
|
|
208
|
+
*
|
|
209
|
+
* IMPORTANT: To enable grid charging with specific power:
|
|
210
|
+
* 1. Set storCtlMod with appropriate bits to enable external control
|
|
211
|
+
* 2. Set chaGriSet = 1 to allow grid charging
|
|
212
|
+
* 3. Set wChaMax to the desired charging power in Watts
|
|
213
|
+
*/
|
|
214
|
+
var SunspecInverterCapability;
|
|
215
|
+
(function (SunspecInverterCapability) {
|
|
216
|
+
SunspecInverterCapability["FeedInLimit"] = "feed-in-limit";
|
|
217
|
+
})(SunspecInverterCapability || (exports.SunspecInverterCapability = SunspecInverterCapability = {}));
|
|
218
|
+
var SunspecBatteryCapability;
|
|
219
|
+
(function (SunspecBatteryCapability) {
|
|
220
|
+
SunspecBatteryCapability["GridCharging"] = "grid-charging";
|
|
221
|
+
SunspecBatteryCapability["DischargeLimit"] = "discharge-limit";
|
|
222
|
+
})(SunspecBatteryCapability || (exports.SunspecBatteryCapability = SunspecBatteryCapability = {}));
|
|
223
|
+
var SunspecMeterCapability;
|
|
224
|
+
(function (SunspecMeterCapability) {
|
|
225
|
+
})(SunspecMeterCapability || (exports.SunspecMeterCapability = SunspecMeterCapability = {}));
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
* SunSpec block interfaces with block numbers
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* A single phase in the tiered retry schedule
|
|
6
|
+
*/
|
|
7
|
+
export interface IRetryPhase {
|
|
8
|
+
intervalMs: number;
|
|
9
|
+
durationMs: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for connection retry with tiered schedule
|
|
6
13
|
*/
|
|
7
14
|
export interface IRetryConfig {
|
|
8
|
-
|
|
9
|
-
maxDelayMs: number;
|
|
10
|
-
backoffFactor: number;
|
|
11
|
-
maxAttempts: number;
|
|
15
|
+
phases: IRetryPhase[];
|
|
12
16
|
}
|
|
13
17
|
export declare const DEFAULT_RETRY_CONFIG: IRetryConfig;
|
|
14
18
|
/**
|
|
@@ -551,6 +555,15 @@ export declare enum SunspecStorageMode {
|
|
|
551
555
|
* 2. Set chaGriSet = 1 to allow grid charging
|
|
552
556
|
* 3. Set wChaMax to the desired charging power in Watts
|
|
553
557
|
*/
|
|
558
|
+
export declare enum SunspecInverterCapability {
|
|
559
|
+
FeedInLimit = "feed-in-limit"
|
|
560
|
+
}
|
|
561
|
+
export declare enum SunspecBatteryCapability {
|
|
562
|
+
GridCharging = "grid-charging",
|
|
563
|
+
DischargeLimit = "discharge-limit"
|
|
564
|
+
}
|
|
565
|
+
export declare enum SunspecMeterCapability {
|
|
566
|
+
}
|
|
554
567
|
export interface SunspecBatteryControls {
|
|
555
568
|
storCtlMod?: number;
|
|
556
569
|
chaGriSet?: number;
|
|
@@ -20,7 +20,6 @@ exports.SunspecModbusClient = void 0;
|
|
|
20
20
|
* - string: all registers 0x0000 (NULL)
|
|
21
21
|
*/
|
|
22
22
|
const sunspec_interfaces_js_1 = require("./sunspec-interfaces.cjs");
|
|
23
|
-
const connection_retry_manager_js_1 = require("./connection-retry-manager.cjs");
|
|
24
23
|
const EnergyAppModbusConnectionHealth_js_1 = require("@enyo-energy/energy-app-sdk/dist/implementations/modbus/EnergyAppModbusConnectionHealth.js");
|
|
25
24
|
const EnergyAppModbusFaultTolerantReader_js_1 = require("@enyo-energy/energy-app-sdk/dist/implementations/modbus/EnergyAppModbusFaultTolerantReader.js");
|
|
26
25
|
const EnergyAppModbusDataTypeConverter_js_1 = require("@enyo-energy/energy-app-sdk/dist/implementations/modbus/EnergyAppModbusDataTypeConverter.js");
|
|
@@ -33,13 +32,11 @@ class SunspecModbusClient {
|
|
|
33
32
|
faultTolerantReader = null;
|
|
34
33
|
modbusDataTypeConverter;
|
|
35
34
|
connectionParams = null;
|
|
36
|
-
retryManager;
|
|
37
35
|
autoReconnectEnabled = true;
|
|
38
|
-
constructor(energyApp
|
|
36
|
+
constructor(energyApp) {
|
|
39
37
|
this.energyApp = energyApp;
|
|
40
38
|
this.connectionHealth = new EnergyAppModbusConnectionHealth_js_1.EnergyAppModbusConnectionHealth();
|
|
41
39
|
this.modbusDataTypeConverter = new EnergyAppModbusDataTypeConverter_js_1.EnergyAppModbusDataTypeConverter();
|
|
42
|
-
this.retryManager = new connection_retry_manager_js_1.ConnectionRetryManager(retryConfig);
|
|
43
40
|
}
|
|
44
41
|
/**
|
|
45
42
|
* Connect to Modbus device
|
|
@@ -66,15 +63,12 @@ class SunspecModbusClient {
|
|
|
66
63
|
}
|
|
67
64
|
this.connected = true;
|
|
68
65
|
this.connectionHealth.recordSuccess();
|
|
69
|
-
this.retryManager.reset();
|
|
70
66
|
console.log(`Connected to Sunspec device at ${host}:${port} unit ${unitId}`);
|
|
71
67
|
}
|
|
72
68
|
/**
|
|
73
69
|
* Disconnect from Modbus device
|
|
74
70
|
*/
|
|
75
71
|
async disconnect() {
|
|
76
|
-
// Cancel any pending retry attempts
|
|
77
|
-
this.retryManager.cancelPendingRetry();
|
|
78
72
|
if (this.modbusClient && this.connected) {
|
|
79
73
|
await this.modbusClient.disconnect();
|
|
80
74
|
this.modbusClient = null;
|
|
@@ -153,61 +147,12 @@ class SunspecModbusClient {
|
|
|
153
147
|
return false;
|
|
154
148
|
}
|
|
155
149
|
}
|
|
156
|
-
/**
|
|
157
|
-
* Check connection health and trigger automatic reconnection if unhealthy
|
|
158
|
-
* Returns true if connection is healthy or was successfully restored
|
|
159
|
-
*/
|
|
160
|
-
async ensureHealthyConnection() {
|
|
161
|
-
// If already healthy, return immediately
|
|
162
|
-
if (this.isHealthy()) {
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
// If no connection params, we can't reconnect
|
|
166
|
-
if (!this.connectionParams) {
|
|
167
|
-
console.error('Connection unhealthy and no connection parameters stored for reconnection.');
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
// If auto-reconnect is disabled, just report the status
|
|
171
|
-
if (!this.autoReconnectEnabled) {
|
|
172
|
-
console.log('Connection unhealthy but auto-reconnect is disabled.');
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
// If a retry is already in progress, don't start another
|
|
176
|
-
if (this.retryManager.isRetryInProgress()) {
|
|
177
|
-
console.log('Retry already in progress...');
|
|
178
|
-
return false;
|
|
179
|
-
}
|
|
180
|
-
console.log('Connection unhealthy, initiating reconnection with exponential backoff...');
|
|
181
|
-
// Attempt reconnection with exponential backoff
|
|
182
|
-
let success = false;
|
|
183
|
-
while (this.retryManager.shouldRetry() && !success) {
|
|
184
|
-
success = await this.retryManager.scheduleRetry(() => this.reconnect());
|
|
185
|
-
if (success) {
|
|
186
|
-
// Re-discover models after successful reconnection
|
|
187
|
-
try {
|
|
188
|
-
await this.discoverModels();
|
|
189
|
-
console.log('Models re-discovered after reconnection.');
|
|
190
|
-
}
|
|
191
|
-
catch (e) {
|
|
192
|
-
console.warn('Failed to re-discover models after reconnection:', e);
|
|
193
|
-
}
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
if (!success) {
|
|
198
|
-
console.error('Failed to restore healthy connection after all retry attempts.');
|
|
199
|
-
}
|
|
200
|
-
return success;
|
|
201
|
-
}
|
|
202
150
|
/**
|
|
203
151
|
* Enable or disable automatic reconnection
|
|
204
152
|
*/
|
|
205
153
|
setAutoReconnect(enabled) {
|
|
206
154
|
this.autoReconnectEnabled = enabled;
|
|
207
155
|
console.log(`Auto-reconnect ${enabled ? 'enabled' : 'disabled'}`);
|
|
208
|
-
if (!enabled) {
|
|
209
|
-
this.retryManager.cancelPendingRetry();
|
|
210
|
-
}
|
|
211
156
|
}
|
|
212
157
|
/**
|
|
213
158
|
* Check if auto-reconnect is enabled
|
|
@@ -215,12 +160,6 @@ class SunspecModbusClient {
|
|
|
215
160
|
isAutoReconnectEnabled() {
|
|
216
161
|
return this.autoReconnectEnabled;
|
|
217
162
|
}
|
|
218
|
-
/**
|
|
219
|
-
* Get the retry manager for advanced configuration
|
|
220
|
-
*/
|
|
221
|
-
getRetryManager() {
|
|
222
|
-
return this.retryManager;
|
|
223
|
-
}
|
|
224
163
|
/**
|
|
225
164
|
* Detect the base address and addressing mode (0-based or 1-based) for SunSpec
|
|
226
165
|
*/
|
|
@@ -500,7 +439,7 @@ class SunspecModbusClient {
|
|
|
500
439
|
}
|
|
501
440
|
}
|
|
502
441
|
/**
|
|
503
|
-
* Read inverter data from Model 103 (Three Phase)
|
|
442
|
+
* Read inverter data from Model 101 (Single Phase) / Model 103 (Three Phase)
|
|
504
443
|
*/
|
|
505
444
|
async readInverterData() {
|
|
506
445
|
const model = this.findModel(sunspec_interfaces_js_1.SunspecModelId.Inverter3Phase);
|
|
@@ -717,8 +656,7 @@ class SunspecModbusClient {
|
|
|
717
656
|
}
|
|
718
657
|
}
|
|
719
658
|
/**
|
|
720
|
-
* Read
|
|
721
|
-
* Returns the scale factors for DC Current, DC Voltage, DC Power, and DC Energy
|
|
659
|
+
* Read scale factors from Model 160 (MPPT)
|
|
722
660
|
*
|
|
723
661
|
* MPPT Model 160 Scale Factor Register Offsets (relative to module start):
|
|
724
662
|
* - DCA_SF (Current Scale Factor): Offset 2
|
|
@@ -838,7 +776,7 @@ class SunspecModbusClient {
|
|
|
838
776
|
}
|
|
839
777
|
}
|
|
840
778
|
/**
|
|
841
|
-
* Read all
|
|
779
|
+
* Read all MPPT strings from Model 160 (Multiple MPPT)
|
|
842
780
|
*/
|
|
843
781
|
async readAllMPPTData() {
|
|
844
782
|
const mpptData = [];
|
|
@@ -1152,7 +1090,7 @@ class SunspecModbusClient {
|
|
|
1152
1090
|
}
|
|
1153
1091
|
}
|
|
1154
1092
|
/**
|
|
1155
|
-
* Read battery data from Model 124 (Basic Storage
|
|
1093
|
+
* Read battery data from Model 124 (Basic Storage) with fallback to Model 802 / Model 803
|
|
1156
1094
|
*/
|
|
1157
1095
|
async readBatteryData() {
|
|
1158
1096
|
// Try Model 124 first (Basic Storage Controls)
|
|
@@ -1420,7 +1358,7 @@ class SunspecModbusClient {
|
|
|
1420
1358
|
return this.writeBatteryControls({ chaGriSet });
|
|
1421
1359
|
}
|
|
1422
1360
|
/**
|
|
1423
|
-
* Read
|
|
1361
|
+
* Read battery control settings from Model 124 (Basic Storage Controls)
|
|
1424
1362
|
*/
|
|
1425
1363
|
async readBatteryControls() {
|
|
1426
1364
|
const model = this.findModel(sunspec_interfaces_js_1.SunspecModelId.Battery);
|
|
@@ -1465,7 +1403,7 @@ class SunspecModbusClient {
|
|
|
1465
1403
|
}
|
|
1466
1404
|
}
|
|
1467
1405
|
/**
|
|
1468
|
-
* Read meter data (Model 203
|
|
1406
|
+
* Read meter data from Model 201 (Single Phase) / Model 203 (Three Phase) / Model 204 (Split Phase)
|
|
1469
1407
|
*/
|
|
1470
1408
|
async readMeterData() {
|
|
1471
1409
|
let model = this.findModel(sunspec_interfaces_js_1.SunspecModelId.Meter3Phase);
|
|
@@ -1627,7 +1565,7 @@ class SunspecModbusClient {
|
|
|
1627
1565
|
return this.connectionHealth;
|
|
1628
1566
|
}
|
|
1629
1567
|
/**
|
|
1630
|
-
* Read
|
|
1568
|
+
* Read inverter settings from Model 121 (Inverter Settings)
|
|
1631
1569
|
*/
|
|
1632
1570
|
async readInverterSettings() {
|
|
1633
1571
|
const model = this.findModel(sunspec_interfaces_js_1.SunspecModelId.Settings);
|
|
@@ -1716,7 +1654,7 @@ class SunspecModbusClient {
|
|
|
1716
1654
|
}
|
|
1717
1655
|
}
|
|
1718
1656
|
/**
|
|
1719
|
-
* Read
|
|
1657
|
+
* Read inverter controls from Model 123 (Immediate Inverter Controls)
|
|
1720
1658
|
*/
|
|
1721
1659
|
async readInverterControls() {
|
|
1722
1660
|
const model = this.findModel(sunspec_interfaces_js_1.SunspecModelId.Controls);
|
|
@@ -1846,7 +1784,7 @@ class SunspecModbusClient {
|
|
|
1846
1784
|
}
|
|
1847
1785
|
}
|
|
1848
1786
|
/**
|
|
1849
|
-
* Write
|
|
1787
|
+
* Write inverter controls to Model 123 (Immediate Inverter Controls)
|
|
1850
1788
|
*/
|
|
1851
1789
|
async writeInverterControls(controls) {
|
|
1852
1790
|
const model = this.findModel(sunspec_interfaces_js_1.SunspecModelId.Controls);
|
|
@@ -1856,32 +1794,35 @@ class SunspecModbusClient {
|
|
|
1856
1794
|
}
|
|
1857
1795
|
const baseAddr = model.address;
|
|
1858
1796
|
try {
|
|
1859
|
-
// Connection control
|
|
1860
|
-
if (controls.Conn !== undefined
|
|
1861
|
-
|
|
1862
|
-
console.log(`
|
|
1797
|
+
// Connection control (Register 2)
|
|
1798
|
+
if (controls.Conn !== undefined) {
|
|
1799
|
+
await this.writeRegisterValue(baseAddr + 2, controls.Conn, 'uint16');
|
|
1800
|
+
console.log(`Set connection control to ${controls.Conn}`);
|
|
1863
1801
|
}
|
|
1864
|
-
// Power limit control
|
|
1865
|
-
if (controls.WMaxLimPct !== undefined
|
|
1866
|
-
const
|
|
1867
|
-
const scaleFactor = sfBuffer.readInt16BE(0);
|
|
1802
|
+
// Power limit control (Register 3) - needs scale factor
|
|
1803
|
+
if (controls.WMaxLimPct !== undefined) {
|
|
1804
|
+
const scaleFactor = await this.readRegisterValue(baseAddr + 21, 1, 'int16');
|
|
1868
1805
|
const scaledValue = Math.round(controls.WMaxLimPct / Math.pow(10, scaleFactor));
|
|
1869
|
-
|
|
1806
|
+
await this.writeRegisterValue(baseAddr + 3, scaledValue, 'uint16');
|
|
1807
|
+
console.log(`Set power limit to ${controls.WMaxLimPct}% (scaled: ${scaledValue})`);
|
|
1870
1808
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
1809
|
+
// Throttle enable/disable (Register 7)
|
|
1810
|
+
if (controls.WMaxLim_Ena !== undefined) {
|
|
1811
|
+
await this.writeRegisterValue(baseAddr + 7, controls.WMaxLim_Ena, 'uint16');
|
|
1812
|
+
console.log(`Set throttle enable to ${controls.WMaxLim_Ena}`);
|
|
1873
1813
|
}
|
|
1874
|
-
// Power factor control
|
|
1875
|
-
if (controls.OutPFSet !== undefined
|
|
1876
|
-
const
|
|
1877
|
-
const scaleFactor = sfBuffer.readInt16BE(0);
|
|
1814
|
+
// Power factor control (Register 8) - needs scale factor
|
|
1815
|
+
if (controls.OutPFSet !== undefined) {
|
|
1816
|
+
const scaleFactor = await this.readRegisterValue(baseAddr + 22, 1, 'int16');
|
|
1878
1817
|
const scaledValue = Math.round(controls.OutPFSet / Math.pow(10, scaleFactor));
|
|
1879
|
-
|
|
1818
|
+
await this.writeRegisterValue(baseAddr + 8, scaledValue, 'int16');
|
|
1819
|
+
console.log(`Set power factor to ${controls.OutPFSet} (scaled: ${scaledValue})`);
|
|
1880
1820
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1821
|
+
// Power factor enable/disable (Register 12)
|
|
1822
|
+
if (controls.OutPFSet_Ena !== undefined) {
|
|
1823
|
+
await this.writeRegisterValue(baseAddr + 12, controls.OutPFSet_Ena, 'uint16');
|
|
1824
|
+
console.log(`Set PF enable to ${controls.OutPFSet_Ena}`);
|
|
1883
1825
|
}
|
|
1884
|
-
// Add more control writes as needed
|
|
1885
1826
|
console.log('Inverter controls written successfully');
|
|
1886
1827
|
return true;
|
|
1887
1828
|
}
|
|
@@ -1890,5 +1831,34 @@ class SunspecModbusClient {
|
|
|
1890
1831
|
return false;
|
|
1891
1832
|
}
|
|
1892
1833
|
}
|
|
1834
|
+
/**
|
|
1835
|
+
* Set the inverter feed-in power limit using Model 123 (Immediate Inverter Controls)
|
|
1836
|
+
*
|
|
1837
|
+
* When limitW is a number, reads WMax from Model 121, computes percentage,
|
|
1838
|
+
* writes WMaxLimPct and enables WMaxLim_Ena.
|
|
1839
|
+
* When limitW is null, disables the limit by setting WMaxLim_Ena = DISABLED.
|
|
1840
|
+
*
|
|
1841
|
+
* @param limitW - Power limit in Watts, or null to remove the limit
|
|
1842
|
+
* @returns true if successful, false otherwise
|
|
1843
|
+
*/
|
|
1844
|
+
async setFeedInLimit(limitW) {
|
|
1845
|
+
if (limitW === null) {
|
|
1846
|
+
// Remove limit: disable WMaxLim_Ena
|
|
1847
|
+
console.log('Removing feed-in limit (disabling WMaxLim_Ena)');
|
|
1848
|
+
return this.writeInverterControls({ WMaxLim_Ena: sunspec_interfaces_js_1.SunspecEnableControl.DISABLED });
|
|
1849
|
+
}
|
|
1850
|
+
// Read WMax from Model 121 to compute percentage
|
|
1851
|
+
const settings = await this.readInverterSettings();
|
|
1852
|
+
if (!settings || !settings.WMax) {
|
|
1853
|
+
console.error('Cannot set feed-in limit: unable to read WMax from Model 121');
|
|
1854
|
+
return false;
|
|
1855
|
+
}
|
|
1856
|
+
const pct = (limitW / settings.WMax) * 100;
|
|
1857
|
+
console.log(`Setting feed-in limit to ${limitW}W (${pct.toFixed(2)}% of WMax ${settings.WMax}W)`);
|
|
1858
|
+
return this.writeInverterControls({
|
|
1859
|
+
WMaxLimPct: pct,
|
|
1860
|
+
WMaxLim_Ena: sunspec_interfaces_js_1.SunspecEnableControl.ENABLED
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1893
1863
|
}
|
|
1894
1864
|
exports.SunspecModbusClient = SunspecModbusClient;
|
|
@@ -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 SunspecBatteryBaseData, 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,11 +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
|
-
|
|
144
|
-
|
|
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;
|
|
145
134
|
/**
|
|
146
|
-
* Read
|
|
147
|
-
* Returns the scale factors for DC Current, DC Voltage, DC Power, and DC Energy
|
|
135
|
+
* Read scale factors from Model 160 (MPPT)
|
|
148
136
|
*
|
|
149
137
|
* MPPT Model 160 Scale Factor Register Offsets (relative to module start):
|
|
150
138
|
* - DCA_SF (Current Scale Factor): Offset 2
|
|
@@ -165,7 +153,7 @@ export declare class SunspecModbusClient {
|
|
|
165
153
|
*/
|
|
166
154
|
readMPPTData(moduleId?: number): Promise<SunspecMPPTData | null>;
|
|
167
155
|
/**
|
|
168
|
-
* Read all
|
|
156
|
+
* Read all MPPT strings from Model 160 (Multiple MPPT)
|
|
169
157
|
*/
|
|
170
158
|
readAllMPPTData(): Promise<SunspecMPPTData[]>;
|
|
171
159
|
/**
|
|
@@ -191,7 +179,7 @@ export declare class SunspecModbusClient {
|
|
|
191
179
|
*/
|
|
192
180
|
readBatteryBaseData(): Promise<SunspecBatteryBaseData | null>;
|
|
193
181
|
/**
|
|
194
|
-
* Read battery data from Model 124 (Basic Storage
|
|
182
|
+
* Read battery data from Model 124 (Basic Storage) with fallback to Model 802 / Model 803
|
|
195
183
|
*/
|
|
196
184
|
readBatteryData(): Promise<SunspecBatteryData | null>;
|
|
197
185
|
/**
|
|
@@ -207,11 +195,11 @@ export declare class SunspecModbusClient {
|
|
|
207
195
|
*/
|
|
208
196
|
enableGridCharging(enable: boolean): Promise<boolean>;
|
|
209
197
|
/**
|
|
210
|
-
* Read
|
|
198
|
+
* Read battery control settings from Model 124 (Basic Storage Controls)
|
|
211
199
|
*/
|
|
212
200
|
readBatteryControls(): Promise<SunspecBatteryControls | null>;
|
|
213
201
|
/**
|
|
214
|
-
* Read meter data (Model 203
|
|
202
|
+
* Read meter data from Model 201 (Single Phase) / Model 203 (Three Phase) / Model 204 (Split Phase)
|
|
215
203
|
*/
|
|
216
204
|
readMeterData(): Promise<SunspecMeterData | null>;
|
|
217
205
|
/**
|
|
@@ -235,11 +223,11 @@ export declare class SunspecModbusClient {
|
|
|
235
223
|
*/
|
|
236
224
|
getConnectionHealth(): IConnectionHealth;
|
|
237
225
|
/**
|
|
238
|
-
* Read
|
|
226
|
+
* Read inverter settings from Model 121 (Inverter Settings)
|
|
239
227
|
*/
|
|
240
228
|
readInverterSettings(): Promise<SunspecInverterSettings | null>;
|
|
241
229
|
/**
|
|
242
|
-
* Read
|
|
230
|
+
* Read inverter controls from Model 123 (Immediate Inverter Controls)
|
|
243
231
|
*/
|
|
244
232
|
readInverterControls(): Promise<SunspecInverterControls | null>;
|
|
245
233
|
/**
|
|
@@ -247,7 +235,18 @@ export declare class SunspecModbusClient {
|
|
|
247
235
|
*/
|
|
248
236
|
writeInverterSettings(settings: Partial<SunspecInverterSettings>): Promise<boolean>;
|
|
249
237
|
/**
|
|
250
|
-
* Write
|
|
238
|
+
* Write inverter controls to Model 123 (Immediate Inverter Controls)
|
|
251
239
|
*/
|
|
252
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>;
|
|
253
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.34';
|
|
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