@enyo-energy/sunspec-sdk 0.0.46 → 0.0.48

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.
@@ -74,8 +74,10 @@ class BaseSunspecDevice {
74
74
  const phase = this.retryManager.getCurrentPhase();
75
75
  const attempt = this.retryManager.getAttemptCount();
76
76
  const elapsed = Math.round(this.retryManager.getElapsedMs() / 1000);
77
+ const stats = this.sunspecClient.getConnectionStats();
77
78
  console.log(`${this.constructor.name} ${this.applianceId}: Reconnect attempt #${attempt} ` +
78
- `(phase: ${phase.intervalMs / 1000}s interval, elapsed: ${elapsed}s)`);
79
+ `(phase: ${phase.intervalMs / 1000}s interval, elapsed: ${elapsed}s, ` +
80
+ `opens=${stats.opens}, closes=${stats.closes}, current=${stats.currentlyOpen})`);
79
81
  try {
80
82
  const success = await this.sunspecClient.reconnect();
81
83
  if (success) {
@@ -86,7 +88,8 @@ class BaseSunspecDevice {
86
88
  if (this.applianceId) {
87
89
  await this.applianceManager.updateApplianceState(this.applianceId, enyo_appliance_js_1.EnyoApplianceConnectionType.Connector, enyo_appliance_js_1.EnyoApplianceStateEnum.Connected);
88
90
  }
89
- console.log(`${this.constructor.name} ${this.applianceId}: Reconnection successful after ${attempt} attempt(s)`);
91
+ const postStats = this.sunspecClient.getConnectionStats();
92
+ console.log(`${this.constructor.name} ${this.applianceId}: Reconnection successful after ${attempt} attempt(s) (opens=${postStats.opens}, closes=${postStats.closes}, current=${postStats.currentlyOpen})`);
90
93
  return true;
91
94
  }
92
95
  }
@@ -96,10 +99,22 @@ class BaseSunspecDevice {
96
99
  return false;
97
100
  }
98
101
  /**
99
- * Mark the device as offline: update appliance state and start tracking disconnection.
102
+ * Mark the device as offline: close the underlying socket so the next readData()
103
+ * cycle sees isConnected() === false and tryReconnect() can establish a fresh
104
+ * connection after the backoff interval. Then update appliance state.
100
105
  */
101
106
  async markOffline() {
102
107
  this.retryManager.markDisconnected();
108
+ try {
109
+ if (this.sunspecClient.isConnected()) {
110
+ await this.sunspecClient.disconnect();
111
+ }
112
+ }
113
+ catch (error) {
114
+ console.error(`${this.constructor.name} ${this.applianceId}: error closing socket on markOffline: ${error}`);
115
+ }
116
+ const stats = this.sunspecClient.getConnectionStats();
117
+ console.log(`${this.constructor.name} ${this.applianceId}: marked offline (opens=${stats.opens}, closes=${stats.closes}, current=${stats.currentlyOpen})`);
103
118
  if (this.applianceId) {
104
119
  try {
105
120
  await this.applianceManager.updateApplianceState(this.applianceId, enyo_appliance_js_1.EnyoApplianceConnectionType.Connector, enyo_appliance_js_1.EnyoApplianceStateEnum.Offline);
@@ -248,6 +263,7 @@ class SunspecInverter extends BaseSunspecDevice {
248
263
  voltageL1: inverterData.voltageAN || 0,
249
264
  voltageL2: inverterData.voltageBN ?? undefined,
250
265
  voltageL3: inverterData.voltageCN ?? undefined,
266
+ meterValueWh: inverterData.acEnergy,
251
267
  strings: dcStrings
252
268
  }
253
269
  };
@@ -305,6 +321,7 @@ class SunspecInverter extends BaseSunspecDevice {
305
321
  current: mppt.dcCurrent,
306
322
  voltage: mppt.dcVoltage,
307
323
  powerW: mppt.dcPower,
324
+ meterValueWh: mppt.dcEnergy,
308
325
  });
309
326
  }
310
327
  });
@@ -54,7 +54,9 @@ export declare abstract class BaseSunspecDevice {
54
54
  */
55
55
  protected tryReconnect(): Promise<boolean>;
56
56
  /**
57
- * Mark the device as offline: update appliance state and start tracking disconnection.
57
+ * Mark the device as offline: close the underlying socket so the next readData()
58
+ * cycle sees isConnected() === false and tryReconnect() can establish a fresh
59
+ * connection after the backoff interval. Then update appliance state.
58
60
  */
59
61
  protected markOffline(): Promise<void>;
60
62
  protected sendCommandAcknowledge(messageId: string, acknowledgeMessage: EnyoDataBusMessageEnum | string, answer: EnyoCommandAcknowledgeAnswerEnum, rejectionReason?: string): void;
@@ -33,6 +33,9 @@ class SunspecModbusClient {
33
33
  modbusDataTypeConverter;
34
34
  connectionParams = null;
35
35
  autoReconnectEnabled = true;
36
+ openCount = 0;
37
+ closeCount = 0;
38
+ currentlyOpen = 0;
36
39
  constructor(energyApp) {
37
40
  this.energyApp = energyApp;
38
41
  this.connectionHealth = new EnergyAppModbusConnectionHealth_js_1.EnergyAppModbusConnectionHealth();
@@ -63,10 +66,14 @@ class SunspecModbusClient {
63
66
  }
64
67
  this.connected = true;
65
68
  this.connectionHealth.recordSuccess();
66
- console.log(`Connected to Sunspec device at ${host}:${port} unit ${unitId}`);
69
+ this.recordOpen();
70
+ console.log(`Connected to Sunspec device at ${host}:${port} unit ${unitId} (opens=${this.openCount}, closes=${this.closeCount}, current=${this.currentlyOpen})`);
67
71
  }
68
72
  /**
69
- * Disconnect from Modbus device
73
+ * Disconnect from Modbus device.
74
+ *
75
+ * Note: connection parameters are preserved so reconnect() can be called afterwards.
76
+ * They will be overwritten by the next connect() call anyway.
70
77
  */
71
78
  async disconnect() {
72
79
  if (this.modbusClient && this.connected) {
@@ -75,9 +82,12 @@ class SunspecModbusClient {
75
82
  this.faultTolerantReader = null;
76
83
  this.connected = false;
77
84
  this.discoveredModels.clear();
85
+ this.recordClose();
86
+ const host = this.connectionParams?.primaryHost ?? 'unknown';
87
+ const port = this.connectionParams?.port ?? 0;
88
+ const unitId = this.connectionParams?.unitId ?? 0;
89
+ console.log(`Disconnected from Sunspec device at ${host}:${port} unit ${unitId} (opens=${this.openCount}, closes=${this.closeCount}, current=${this.currentlyOpen})`);
78
90
  }
79
- // Clear stored connection params
80
- this.connectionParams = null;
81
91
  }
82
92
  /**
83
93
  * Reconnect using stored connection parameters
@@ -118,6 +128,7 @@ class SunspecModbusClient {
118
128
  try {
119
129
  // Disconnect existing connection if any
120
130
  if (this.modbusClient) {
131
+ const wasConnected = this.connected;
121
132
  try {
122
133
  await this.modbusClient.disconnect();
123
134
  }
@@ -126,6 +137,10 @@ class SunspecModbusClient {
126
137
  }
127
138
  this.modbusClient = null;
128
139
  this.faultTolerantReader = null;
140
+ if (wasConnected) {
141
+ this.connected = false;
142
+ this.recordClose();
143
+ }
129
144
  }
130
145
  // Attempt connection
131
146
  this.modbusClient = await this.energyApp.useModbus().connect({
@@ -140,6 +155,8 @@ class SunspecModbusClient {
140
155
  }
141
156
  this.connected = true;
142
157
  this.connectionHealth.recordSuccess();
158
+ this.recordOpen();
159
+ console.log(`Connection attempt to ${host}:${port} unit ${unitId} succeeded (opens=${this.openCount}, closes=${this.closeCount}, current=${this.currentlyOpen})`);
143
160
  return true;
144
161
  }
145
162
  catch (error) {
@@ -147,6 +164,25 @@ class SunspecModbusClient {
147
164
  return false;
148
165
  }
149
166
  }
167
+ recordOpen() {
168
+ this.openCount++;
169
+ this.currentlyOpen++;
170
+ }
171
+ recordClose() {
172
+ this.closeCount++;
173
+ if (this.currentlyOpen > 0) {
174
+ this.currentlyOpen--;
175
+ }
176
+ else {
177
+ console.warn(`SunspecModbusClient: closeCount incremented while currentlyOpen was 0 — possible double-close`);
178
+ }
179
+ }
180
+ /**
181
+ * Get cumulative open/close counts for this client. Useful for spotting connection leaks.
182
+ */
183
+ getConnectionStats() {
184
+ return { opens: this.openCount, closes: this.closeCount, currentlyOpen: this.currentlyOpen };
185
+ }
150
186
  /**
151
187
  * Enable or disable automatic reconnection
152
188
  */
@@ -585,6 +621,7 @@ class SunspecModbusClient {
585
621
  V_SF: this.extractValue(buffer, 13, 'int16'),
586
622
  W_SF: this.extractValue(buffer, 10, 'int16'),
587
623
  Hz_SF: this.extractValue(buffer, 12, 'int16'),
624
+ WH_SF: this.extractValue(buffer, 26, 'int16'),
588
625
  DCA_SF: this.extractValue(buffer, 18, 'int16'),
589
626
  DCV_SF: this.extractValue(buffer, 19, 'int16'),
590
627
  DCW_SF: this.extractValue(buffer, 21, 'int16')
@@ -593,6 +630,7 @@ class SunspecModbusClient {
593
630
  this.logRegisterRead(101, 13, 'V_SF', scaleFactors.V_SF, 'int16');
594
631
  this.logRegisterRead(101, 10, 'W_SF', scaleFactors.W_SF, 'int16');
595
632
  this.logRegisterRead(101, 12, 'Hz_SF', scaleFactors.Hz_SF, 'int16');
633
+ this.logRegisterRead(101, 26, 'WH_SF', scaleFactors.WH_SF, 'int16');
596
634
  this.logRegisterRead(101, 18, 'DCA_SF', scaleFactors.DCA_SF, 'int16');
597
635
  this.logRegisterRead(101, 19, 'DCV_SF', scaleFactors.DCV_SF, 'int16');
598
636
  this.logRegisterRead(101, 21, 'DCW_SF', scaleFactors.DCW_SF, 'int16');
@@ -617,6 +655,12 @@ class SunspecModbusClient {
617
655
  dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'int16', 'DC Power', 20, 101),
618
656
  operatingState: stateRaw
619
657
  };
658
+ // Read AC Energy (32-bit accumulator) - Offset 24-25
659
+ const acEnergy = this.extractValue(buffer, 24, 'uint32', 2);
660
+ this.logRegisterRead(101, 24, 'AC Energy', acEnergy, 'acc32');
661
+ data.acEnergy = !this.isUnimplementedValue(acEnergy, 'acc32')
662
+ ? acEnergy * Math.pow(10, scaleFactors.WH_SF)
663
+ : undefined;
620
664
  console.debug('[Model 101] Single Phase Inverter Data:', data);
621
665
  return data;
622
666
  }
@@ -29,6 +29,9 @@ export declare class SunspecModbusClient {
29
29
  private modbusDataTypeConverter;
30
30
  private connectionParams;
31
31
  private autoReconnectEnabled;
32
+ private openCount;
33
+ private closeCount;
34
+ private currentlyOpen;
32
35
  constructor(energyApp: EnergyApp);
33
36
  /**
34
37
  * Connect to Modbus device
@@ -39,7 +42,10 @@ export declare class SunspecModbusClient {
39
42
  */
40
43
  connect(host: string, port?: number, unitId?: number, secondaryHost?: string): Promise<void>;
41
44
  /**
42
- * Disconnect from Modbus device
45
+ * Disconnect from Modbus device.
46
+ *
47
+ * Note: connection parameters are preserved so reconnect() can be called afterwards.
48
+ * They will be overwritten by the next connect() call anyway.
43
49
  */
44
50
  disconnect(): Promise<void>;
45
51
  /**
@@ -53,6 +59,16 @@ export declare class SunspecModbusClient {
53
59
  * Returns true if successful, false otherwise
54
60
  */
55
61
  private attemptConnection;
62
+ private recordOpen;
63
+ private recordClose;
64
+ /**
65
+ * Get cumulative open/close counts for this client. Useful for spotting connection leaks.
66
+ */
67
+ getConnectionStats(): {
68
+ opens: number;
69
+ closes: number;
70
+ currentlyOpen: number;
71
+ };
56
72
  /**
57
73
  * Enable or disable automatic reconnection
58
74
  */
@@ -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.46';
12
+ exports.SDK_VERSION = '0.0.48';
13
13
  /**
14
14
  * Gets the current SDK version.
15
15
  * @returns The semantic version string of the SDK
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export declare const SDK_VERSION = "0.0.46";
8
+ export declare const SDK_VERSION = "0.0.48";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
@@ -54,7 +54,9 @@ export declare abstract class BaseSunspecDevice {
54
54
  */
55
55
  protected tryReconnect(): Promise<boolean>;
56
56
  /**
57
- * Mark the device as offline: update appliance state and start tracking disconnection.
57
+ * Mark the device as offline: close the underlying socket so the next readData()
58
+ * cycle sees isConnected() === false and tryReconnect() can establish a fresh
59
+ * connection after the backoff interval. Then update appliance state.
58
60
  */
59
61
  protected markOffline(): Promise<void>;
60
62
  protected sendCommandAcknowledge(messageId: string, acknowledgeMessage: EnyoDataBusMessageEnum | string, answer: EnyoCommandAcknowledgeAnswerEnum, rejectionReason?: string): void;
@@ -71,8 +71,10 @@ export class BaseSunspecDevice {
71
71
  const phase = this.retryManager.getCurrentPhase();
72
72
  const attempt = this.retryManager.getAttemptCount();
73
73
  const elapsed = Math.round(this.retryManager.getElapsedMs() / 1000);
74
+ const stats = this.sunspecClient.getConnectionStats();
74
75
  console.log(`${this.constructor.name} ${this.applianceId}: Reconnect attempt #${attempt} ` +
75
- `(phase: ${phase.intervalMs / 1000}s interval, elapsed: ${elapsed}s)`);
76
+ `(phase: ${phase.intervalMs / 1000}s interval, elapsed: ${elapsed}s, ` +
77
+ `opens=${stats.opens}, closes=${stats.closes}, current=${stats.currentlyOpen})`);
76
78
  try {
77
79
  const success = await this.sunspecClient.reconnect();
78
80
  if (success) {
@@ -83,7 +85,8 @@ export class BaseSunspecDevice {
83
85
  if (this.applianceId) {
84
86
  await this.applianceManager.updateApplianceState(this.applianceId, EnyoApplianceConnectionType.Connector, EnyoApplianceStateEnum.Connected);
85
87
  }
86
- console.log(`${this.constructor.name} ${this.applianceId}: Reconnection successful after ${attempt} attempt(s)`);
88
+ const postStats = this.sunspecClient.getConnectionStats();
89
+ console.log(`${this.constructor.name} ${this.applianceId}: Reconnection successful after ${attempt} attempt(s) (opens=${postStats.opens}, closes=${postStats.closes}, current=${postStats.currentlyOpen})`);
87
90
  return true;
88
91
  }
89
92
  }
@@ -93,10 +96,22 @@ export class BaseSunspecDevice {
93
96
  return false;
94
97
  }
95
98
  /**
96
- * Mark the device as offline: update appliance state and start tracking disconnection.
99
+ * Mark the device as offline: close the underlying socket so the next readData()
100
+ * cycle sees isConnected() === false and tryReconnect() can establish a fresh
101
+ * connection after the backoff interval. Then update appliance state.
97
102
  */
98
103
  async markOffline() {
99
104
  this.retryManager.markDisconnected();
105
+ try {
106
+ if (this.sunspecClient.isConnected()) {
107
+ await this.sunspecClient.disconnect();
108
+ }
109
+ }
110
+ catch (error) {
111
+ console.error(`${this.constructor.name} ${this.applianceId}: error closing socket on markOffline: ${error}`);
112
+ }
113
+ const stats = this.sunspecClient.getConnectionStats();
114
+ console.log(`${this.constructor.name} ${this.applianceId}: marked offline (opens=${stats.opens}, closes=${stats.closes}, current=${stats.currentlyOpen})`);
100
115
  if (this.applianceId) {
101
116
  try {
102
117
  await this.applianceManager.updateApplianceState(this.applianceId, EnyoApplianceConnectionType.Connector, EnyoApplianceStateEnum.Offline);
@@ -244,6 +259,7 @@ export class SunspecInverter extends BaseSunspecDevice {
244
259
  voltageL1: inverterData.voltageAN || 0,
245
260
  voltageL2: inverterData.voltageBN ?? undefined,
246
261
  voltageL3: inverterData.voltageCN ?? undefined,
262
+ meterValueWh: inverterData.acEnergy,
247
263
  strings: dcStrings
248
264
  }
249
265
  };
@@ -301,6 +317,7 @@ export class SunspecInverter extends BaseSunspecDevice {
301
317
  current: mppt.dcCurrent,
302
318
  voltage: mppt.dcVoltage,
303
319
  powerW: mppt.dcPower,
320
+ meterValueWh: mppt.dcEnergy,
304
321
  });
305
322
  }
306
323
  });
@@ -29,6 +29,9 @@ export declare class SunspecModbusClient {
29
29
  private modbusDataTypeConverter;
30
30
  private connectionParams;
31
31
  private autoReconnectEnabled;
32
+ private openCount;
33
+ private closeCount;
34
+ private currentlyOpen;
32
35
  constructor(energyApp: EnergyApp);
33
36
  /**
34
37
  * Connect to Modbus device
@@ -39,7 +42,10 @@ export declare class SunspecModbusClient {
39
42
  */
40
43
  connect(host: string, port?: number, unitId?: number, secondaryHost?: string): Promise<void>;
41
44
  /**
42
- * Disconnect from Modbus device
45
+ * Disconnect from Modbus device.
46
+ *
47
+ * Note: connection parameters are preserved so reconnect() can be called afterwards.
48
+ * They will be overwritten by the next connect() call anyway.
43
49
  */
44
50
  disconnect(): Promise<void>;
45
51
  /**
@@ -53,6 +59,16 @@ export declare class SunspecModbusClient {
53
59
  * Returns true if successful, false otherwise
54
60
  */
55
61
  private attemptConnection;
62
+ private recordOpen;
63
+ private recordClose;
64
+ /**
65
+ * Get cumulative open/close counts for this client. Useful for spotting connection leaks.
66
+ */
67
+ getConnectionStats(): {
68
+ opens: number;
69
+ closes: number;
70
+ currentlyOpen: number;
71
+ };
56
72
  /**
57
73
  * Enable or disable automatic reconnection
58
74
  */
@@ -30,6 +30,9 @@ export class SunspecModbusClient {
30
30
  modbusDataTypeConverter;
31
31
  connectionParams = null;
32
32
  autoReconnectEnabled = true;
33
+ openCount = 0;
34
+ closeCount = 0;
35
+ currentlyOpen = 0;
33
36
  constructor(energyApp) {
34
37
  this.energyApp = energyApp;
35
38
  this.connectionHealth = new EnergyAppModbusConnectionHealth();
@@ -60,10 +63,14 @@ export class SunspecModbusClient {
60
63
  }
61
64
  this.connected = true;
62
65
  this.connectionHealth.recordSuccess();
63
- console.log(`Connected to Sunspec device at ${host}:${port} unit ${unitId}`);
66
+ this.recordOpen();
67
+ console.log(`Connected to Sunspec device at ${host}:${port} unit ${unitId} (opens=${this.openCount}, closes=${this.closeCount}, current=${this.currentlyOpen})`);
64
68
  }
65
69
  /**
66
- * Disconnect from Modbus device
70
+ * Disconnect from Modbus device.
71
+ *
72
+ * Note: connection parameters are preserved so reconnect() can be called afterwards.
73
+ * They will be overwritten by the next connect() call anyway.
67
74
  */
68
75
  async disconnect() {
69
76
  if (this.modbusClient && this.connected) {
@@ -72,9 +79,12 @@ export class SunspecModbusClient {
72
79
  this.faultTolerantReader = null;
73
80
  this.connected = false;
74
81
  this.discoveredModels.clear();
82
+ this.recordClose();
83
+ const host = this.connectionParams?.primaryHost ?? 'unknown';
84
+ const port = this.connectionParams?.port ?? 0;
85
+ const unitId = this.connectionParams?.unitId ?? 0;
86
+ console.log(`Disconnected from Sunspec device at ${host}:${port} unit ${unitId} (opens=${this.openCount}, closes=${this.closeCount}, current=${this.currentlyOpen})`);
75
87
  }
76
- // Clear stored connection params
77
- this.connectionParams = null;
78
88
  }
79
89
  /**
80
90
  * Reconnect using stored connection parameters
@@ -115,6 +125,7 @@ export class SunspecModbusClient {
115
125
  try {
116
126
  // Disconnect existing connection if any
117
127
  if (this.modbusClient) {
128
+ const wasConnected = this.connected;
118
129
  try {
119
130
  await this.modbusClient.disconnect();
120
131
  }
@@ -123,6 +134,10 @@ export class SunspecModbusClient {
123
134
  }
124
135
  this.modbusClient = null;
125
136
  this.faultTolerantReader = null;
137
+ if (wasConnected) {
138
+ this.connected = false;
139
+ this.recordClose();
140
+ }
126
141
  }
127
142
  // Attempt connection
128
143
  this.modbusClient = await this.energyApp.useModbus().connect({
@@ -137,6 +152,8 @@ export class SunspecModbusClient {
137
152
  }
138
153
  this.connected = true;
139
154
  this.connectionHealth.recordSuccess();
155
+ this.recordOpen();
156
+ console.log(`Connection attempt to ${host}:${port} unit ${unitId} succeeded (opens=${this.openCount}, closes=${this.closeCount}, current=${this.currentlyOpen})`);
140
157
  return true;
141
158
  }
142
159
  catch (error) {
@@ -144,6 +161,25 @@ export class SunspecModbusClient {
144
161
  return false;
145
162
  }
146
163
  }
164
+ recordOpen() {
165
+ this.openCount++;
166
+ this.currentlyOpen++;
167
+ }
168
+ recordClose() {
169
+ this.closeCount++;
170
+ if (this.currentlyOpen > 0) {
171
+ this.currentlyOpen--;
172
+ }
173
+ else {
174
+ console.warn(`SunspecModbusClient: closeCount incremented while currentlyOpen was 0 — possible double-close`);
175
+ }
176
+ }
177
+ /**
178
+ * Get cumulative open/close counts for this client. Useful for spotting connection leaks.
179
+ */
180
+ getConnectionStats() {
181
+ return { opens: this.openCount, closes: this.closeCount, currentlyOpen: this.currentlyOpen };
182
+ }
147
183
  /**
148
184
  * Enable or disable automatic reconnection
149
185
  */
@@ -582,6 +618,7 @@ export class SunspecModbusClient {
582
618
  V_SF: this.extractValue(buffer, 13, 'int16'),
583
619
  W_SF: this.extractValue(buffer, 10, 'int16'),
584
620
  Hz_SF: this.extractValue(buffer, 12, 'int16'),
621
+ WH_SF: this.extractValue(buffer, 26, 'int16'),
585
622
  DCA_SF: this.extractValue(buffer, 18, 'int16'),
586
623
  DCV_SF: this.extractValue(buffer, 19, 'int16'),
587
624
  DCW_SF: this.extractValue(buffer, 21, 'int16')
@@ -590,6 +627,7 @@ export class SunspecModbusClient {
590
627
  this.logRegisterRead(101, 13, 'V_SF', scaleFactors.V_SF, 'int16');
591
628
  this.logRegisterRead(101, 10, 'W_SF', scaleFactors.W_SF, 'int16');
592
629
  this.logRegisterRead(101, 12, 'Hz_SF', scaleFactors.Hz_SF, 'int16');
630
+ this.logRegisterRead(101, 26, 'WH_SF', scaleFactors.WH_SF, 'int16');
593
631
  this.logRegisterRead(101, 18, 'DCA_SF', scaleFactors.DCA_SF, 'int16');
594
632
  this.logRegisterRead(101, 19, 'DCV_SF', scaleFactors.DCV_SF, 'int16');
595
633
  this.logRegisterRead(101, 21, 'DCW_SF', scaleFactors.DCW_SF, 'int16');
@@ -614,6 +652,12 @@ export class SunspecModbusClient {
614
652
  dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'int16', 'DC Power', 20, 101),
615
653
  operatingState: stateRaw
616
654
  };
655
+ // Read AC Energy (32-bit accumulator) - Offset 24-25
656
+ const acEnergy = this.extractValue(buffer, 24, 'uint32', 2);
657
+ this.logRegisterRead(101, 24, 'AC Energy', acEnergy, 'acc32');
658
+ data.acEnergy = !this.isUnimplementedValue(acEnergy, 'acc32')
659
+ ? acEnergy * Math.pow(10, scaleFactors.WH_SF)
660
+ : undefined;
617
661
  console.debug('[Model 101] Single Phase Inverter Data:', data);
618
662
  return data;
619
663
  }
package/dist/version.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export declare const SDK_VERSION = "0.0.46";
8
+ export declare const SDK_VERSION = "0.0.48";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
package/dist/version.js CHANGED
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export const SDK_VERSION = '0.0.46';
8
+ export const SDK_VERSION = '0.0.48';
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enyo-energy/sunspec-sdk",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "description": "enyo Energy Sunspec SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -37,7 +37,7 @@
37
37
  "typescript": "^5.8.3"
38
38
  },
39
39
  "dependencies": {
40
- "@enyo-energy/energy-app-sdk": "^0.0.110"
40
+ "@enyo-energy/energy-app-sdk": "^0.0.113"
41
41
  },
42
42
  "volta": {
43
43
  "node": "22.17.0"