@enyo-energy/sunspec-sdk 0.0.15 → 0.0.16

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.
@@ -102,16 +102,8 @@ class SunspecInverter extends BaseSunspecDevice {
102
102
  // Read inverter data
103
103
  const inverterData = await this.sunspecClient.readInverterData();
104
104
  const mpptDataList = await this.sunspecClient.readAllMPPTData();
105
+ const inverterSettings = await this.sunspecClient.readInverterSettings();
105
106
  if (inverterData) {
106
- // Log what we're sending
107
- console.log('Preparing Inverter Message:', {
108
- pvPowerW: inverterData.dcPower,
109
- acPower: inverterData.acPower,
110
- voltageL1: inverterData.voltageAN,
111
- voltageL2: inverterData.voltageBN,
112
- voltageL3: inverterData.voltageCN,
113
- stringsCount: mpptDataList.length
114
- });
115
107
  const inverterMessage = {
116
108
  id: (0, node_crypto_1.randomUUID)(),
117
109
  message: enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.InverterValuesUpdateV1,
@@ -122,12 +114,12 @@ class SunspecInverter extends BaseSunspecDevice {
122
114
  timestampIso: timestamp.toISOString(),
123
115
  resolution,
124
116
  data: {
125
- pvPowerW: inverterData.dcPower || 0, // Use DC power for PV power
126
- activePowerLimitationW: inverterData.acPower || 0,
117
+ pvPowerW: inverterData.acPower || 0,
118
+ activePowerLimitationW: inverterSettings?.WMax,
127
119
  state: this.mapOperatingState(inverterData.operatingState),
128
120
  voltageL1: inverterData.voltageAN || 0,
129
- voltageL2: inverterData.voltageBN ?? undefined, // Use undefined if unimplemented phase
130
- voltageL3: inverterData.voltageCN ?? undefined, // Use undefined if unimplemented phase
121
+ voltageL2: inverterData.voltageBN ?? undefined,
122
+ voltageL3: inverterData.voltageCN ?? undefined,
131
123
  strings: this.mapMPPTToStrings(mpptDataList)
132
124
  }
133
125
  };
@@ -166,12 +158,38 @@ class SunspecInverter extends BaseSunspecDevice {
166
158
  result.push({
167
159
  index: index + 1,
168
160
  voltage: mppt.dcVoltage ?? undefined, // Use null if undefined
169
- powerW: mppt.dcPower ?? 0 // Default to 0 if undefined
161
+ powerW: mppt.dcPower ?? undefined // Default to 0 if undefined
170
162
  });
171
163
  }
172
164
  });
173
165
  return result;
174
166
  }
167
+ mapMPPTOperatingState(state) {
168
+ switch (state) {
169
+ case sunspec_interfaces_js_1.SunspecMPPTOperatingState.OFF:
170
+ return "OFF";
171
+ case sunspec_interfaces_js_1.SunspecMPPTOperatingState.SLEEPING:
172
+ return "SLEEPING";
173
+ case sunspec_interfaces_js_1.SunspecMPPTOperatingState.STARTING:
174
+ return "STARTING";
175
+ case sunspec_interfaces_js_1.SunspecMPPTOperatingState.MPPT:
176
+ return "MPPT";
177
+ case sunspec_interfaces_js_1.SunspecMPPTOperatingState.THROTTLED:
178
+ return "THROTTLED";
179
+ case sunspec_interfaces_js_1.SunspecMPPTOperatingState.SHUTTING_DOWN:
180
+ return "SHUTTING_DOWN";
181
+ case sunspec_interfaces_js_1.SunspecMPPTOperatingState.FAULT:
182
+ return "FAULT";
183
+ case sunspec_interfaces_js_1.SunspecMPPTOperatingState.STANDBY:
184
+ return "STANDBY";
185
+ case sunspec_interfaces_js_1.SunspecMPPTOperatingState.TEST:
186
+ return "TEST";
187
+ case sunspec_interfaces_js_1.SunspecMPPTOperatingState.RESERVED_10:
188
+ return "RESERVED_10";
189
+ default:
190
+ return `UNKNOWN(${state})`;
191
+ }
192
+ }
175
193
  }
176
194
  exports.SunspecInverter = SunspecInverter;
177
195
  /**
@@ -217,6 +235,32 @@ class SunspecBattery extends BaseSunspecDevice {
217
235
  await this.applianceManager.updateApplianceState(this.applianceId, enyo_appliance_js_1.EnyoApplianceConnectionType.Connector, enyo_appliance_js_1.EnyoApplianceStateEnum.Offline);
218
236
  }
219
237
  }
238
+ /**
239
+ * Map SunSpec battery charge state to Enyo battery state
240
+ */
241
+ mapToEnyoBatteryState(sunspecState) {
242
+ if (sunspecState === undefined) {
243
+ return undefined;
244
+ }
245
+ switch (sunspecState) {
246
+ case sunspec_interfaces_js_1.SunspecBatteryChargeState.OFF:
247
+ return enyo_data_bus_value_js_1.EnyoBatteryStateEnum.Off;
248
+ case sunspec_interfaces_js_1.SunspecBatteryChargeState.EMPTY:
249
+ return enyo_data_bus_value_js_1.EnyoBatteryStateEnum.Empty;
250
+ case sunspec_interfaces_js_1.SunspecBatteryChargeState.DISCHARGING:
251
+ return enyo_data_bus_value_js_1.EnyoBatteryStateEnum.Discharging;
252
+ case sunspec_interfaces_js_1.SunspecBatteryChargeState.CHARGING:
253
+ return enyo_data_bus_value_js_1.EnyoBatteryStateEnum.Charging;
254
+ case sunspec_interfaces_js_1.SunspecBatteryChargeState.FULL:
255
+ return enyo_data_bus_value_js_1.EnyoBatteryStateEnum.Full;
256
+ case sunspec_interfaces_js_1.SunspecBatteryChargeState.HOLDING:
257
+ return enyo_data_bus_value_js_1.EnyoBatteryStateEnum.Holding;
258
+ case sunspec_interfaces_js_1.SunspecBatteryChargeState.TESTING:
259
+ return enyo_data_bus_value_js_1.EnyoBatteryStateEnum.Testing;
260
+ default:
261
+ return undefined;
262
+ }
263
+ }
220
264
  /**
221
265
  * Update battery data and return data bus messages
222
266
  */
@@ -227,24 +271,57 @@ class SunspecBattery extends BaseSunspecDevice {
227
271
  const messages = [];
228
272
  const timestamp = new Date();
229
273
  try {
230
- // For now, return basic battery data
231
- // In a real implementation, we would read from battery models
232
- const batteryMessage = {
233
- id: (0, node_crypto_1.randomUUID)(),
234
- message: enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.BatteryValuesUpdateV1,
235
- type: 'message',
236
- source: enyo_source_enum_js_1.EnyoSourceEnum.Device,
237
- applianceId: this.applianceId,
238
- clockId,
239
- timestampIso: timestamp.toISOString(),
240
- resolution,
241
- data: {
242
- batterySoC: 50, // Placeholder - would read from battery model
243
- batteryPowerW: 0,
244
- state: enyo_data_bus_value_js_1.EnyoBatteryStateEnum.Holding
274
+ // Read actual battery data from SunSpec device
275
+ const batteryData = await this.sunspecClient.readBatteryData();
276
+ if (batteryData) {
277
+ // Calculate battery power
278
+ let batteryPowerW = 0;
279
+ if (batteryData.chargePower !== undefined && batteryData.chargePower > 0) {
280
+ batteryPowerW = batteryData.chargePower; // Positive for charging
245
281
  }
246
- };
247
- messages.push(batteryMessage);
282
+ else if (batteryData.dischargePower !== undefined && batteryData.dischargePower > 0) {
283
+ batteryPowerW = -batteryData.dischargePower; // Negative for discharging
284
+ }
285
+ const batteryMessage = {
286
+ id: (0, node_crypto_1.randomUUID)(),
287
+ message: enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.BatteryValuesUpdateV1,
288
+ type: 'message',
289
+ source: enyo_source_enum_js_1.EnyoSourceEnum.Device,
290
+ applianceId: this.applianceId,
291
+ clockId,
292
+ timestampIso: timestamp.toISOString(),
293
+ resolution,
294
+ data: {
295
+ batterySoC: batteryData.soc || batteryData.chaState || 0,
296
+ batteryPowerW: batteryPowerW,
297
+ state: this.mapToEnyoBatteryState(batteryData.chaSt)
298
+ }
299
+ };
300
+ messages.push(batteryMessage);
301
+ console.log(`Battery update - SoC: ${batteryData.soc?.toFixed(1)}%, ` +
302
+ `Power: ${batteryPowerW.toFixed(0)}W, ` +
303
+ `State: ${batteryData.chaStName || 'Unknown'}`);
304
+ }
305
+ else {
306
+ console.warn('No battery data available from device');
307
+ // Send a message with unknown/zero values
308
+ const batteryMessage = {
309
+ id: (0, node_crypto_1.randomUUID)(),
310
+ message: enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.BatteryValuesUpdateV1,
311
+ type: 'message',
312
+ source: enyo_source_enum_js_1.EnyoSourceEnum.Device,
313
+ applianceId: this.applianceId,
314
+ clockId,
315
+ timestampIso: timestamp.toISOString(),
316
+ resolution,
317
+ data: {
318
+ batterySoC: 0,
319
+ batteryPowerW: 0,
320
+ state: undefined
321
+ }
322
+ };
323
+ messages.push(batteryMessage);
324
+ }
248
325
  this.lastUpdateTime = timestamp.getTime();
249
326
  }
250
327
  catch (error) {
@@ -327,8 +404,8 @@ class SunspecMeter extends BaseSunspecDevice {
327
404
  resolution,
328
405
  data: {
329
406
  gridPowerW: meterData.totalPower || 0,
330
- gridFeedInWh: Number(meterData.exportedEnergy || 0),
331
- gridConsumptionWh: Number(meterData.importedEnergy || 0),
407
+ gridFeedInWh: meterData.exportedEnergy || 0,
408
+ gridConsumptionWh: meterData.importedEnergy || 0,
332
409
  selfConsumptionW: undefined,
333
410
  selfConsumptionWh: undefined
334
411
  }
@@ -53,6 +53,7 @@ export declare class SunspecInverter extends BaseSunspecDevice {
53
53
  * Map MPPT data to DC string structure for data bus
54
54
  */
55
55
  private mapMPPTToStrings;
56
+ private mapMPPTOperatingState;
56
57
  }
57
58
  /**
58
59
  * Sunspec Battery implementation
@@ -63,6 +64,10 @@ export declare class SunspecBattery extends BaseSunspecDevice {
63
64
  */
64
65
  connect(): Promise<void>;
65
66
  disconnect(): Promise<void>;
67
+ /**
68
+ * Map SunSpec battery charge state to Enyo battery state
69
+ */
70
+ private mapToEnyoBatteryState;
66
71
  /**
67
72
  * Update battery data and return data bus messages
68
73
  */
@@ -3,7 +3,7 @@
3
3
  * SunSpec block interfaces with block numbers
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SunspecVArPctMode = exports.SunspecEnableControl = exports.SunspecConnectionControl = exports.SunspecModelId = void 0;
6
+ exports.SunspecVArPctMode = exports.SunspecEnableControl = exports.SunspecConnectionControl = exports.SunspecStorageControlMode = exports.SunspecBatteryChargeState = exports.SunspecMPPTOperatingState = exports.SunspecModelId = void 0;
7
7
  /**
8
8
  * Common Sunspec Model IDs
9
9
  */
@@ -25,6 +25,44 @@ var SunspecModelId;
25
25
  SunspecModelId[SunspecModelId["Controls"] = 123] = "Controls";
26
26
  SunspecModelId[SunspecModelId["EndMarker"] = 65535] = "EndMarker";
27
27
  })(SunspecModelId || (exports.SunspecModelId = SunspecModelId = {}));
28
+ /**
29
+ * MPPT Operating State values for Model 160
30
+ * These represent the DC module/string operating states
31
+ */
32
+ var SunspecMPPTOperatingState;
33
+ (function (SunspecMPPTOperatingState) {
34
+ SunspecMPPTOperatingState[SunspecMPPTOperatingState["OFF"] = 1] = "OFF";
35
+ SunspecMPPTOperatingState[SunspecMPPTOperatingState["SLEEPING"] = 2] = "SLEEPING";
36
+ SunspecMPPTOperatingState[SunspecMPPTOperatingState["STARTING"] = 3] = "STARTING";
37
+ SunspecMPPTOperatingState[SunspecMPPTOperatingState["MPPT"] = 4] = "MPPT";
38
+ SunspecMPPTOperatingState[SunspecMPPTOperatingState["THROTTLED"] = 5] = "THROTTLED";
39
+ SunspecMPPTOperatingState[SunspecMPPTOperatingState["SHUTTING_DOWN"] = 6] = "SHUTTING_DOWN";
40
+ SunspecMPPTOperatingState[SunspecMPPTOperatingState["FAULT"] = 7] = "FAULT";
41
+ SunspecMPPTOperatingState[SunspecMPPTOperatingState["STANDBY"] = 8] = "STANDBY";
42
+ SunspecMPPTOperatingState[SunspecMPPTOperatingState["TEST"] = 9] = "TEST";
43
+ SunspecMPPTOperatingState[SunspecMPPTOperatingState["RESERVED_10"] = 10] = "RESERVED_10";
44
+ })(SunspecMPPTOperatingState || (exports.SunspecMPPTOperatingState = SunspecMPPTOperatingState = {}));
45
+ /**
46
+ * Battery Charge State values for Model 124
47
+ */
48
+ var SunspecBatteryChargeState;
49
+ (function (SunspecBatteryChargeState) {
50
+ SunspecBatteryChargeState[SunspecBatteryChargeState["OFF"] = 1] = "OFF";
51
+ SunspecBatteryChargeState[SunspecBatteryChargeState["EMPTY"] = 2] = "EMPTY";
52
+ SunspecBatteryChargeState[SunspecBatteryChargeState["DISCHARGING"] = 3] = "DISCHARGING";
53
+ SunspecBatteryChargeState[SunspecBatteryChargeState["CHARGING"] = 4] = "CHARGING";
54
+ SunspecBatteryChargeState[SunspecBatteryChargeState["FULL"] = 5] = "FULL";
55
+ SunspecBatteryChargeState[SunspecBatteryChargeState["HOLDING"] = 6] = "HOLDING";
56
+ SunspecBatteryChargeState[SunspecBatteryChargeState["TESTING"] = 7] = "TESTING";
57
+ })(SunspecBatteryChargeState || (exports.SunspecBatteryChargeState = SunspecBatteryChargeState = {}));
58
+ /**
59
+ * Storage Control Mode bitfield values for Model 124
60
+ */
61
+ var SunspecStorageControlMode;
62
+ (function (SunspecStorageControlMode) {
63
+ SunspecStorageControlMode[SunspecStorageControlMode["CHARGE"] = 1] = "CHARGE";
64
+ SunspecStorageControlMode[SunspecStorageControlMode["DISCHARGE"] = 2] = "DISCHARGE"; // Bit 1 - Enable discharge mode
65
+ })(SunspecStorageControlMode || (exports.SunspecStorageControlMode = SunspecStorageControlMode = {}));
28
66
  /**
29
67
  * Enum values for connection control
30
68
  */
@@ -98,6 +98,29 @@ export interface SunspecInverterData extends SunspecBlock {
98
98
  }
99
99
  /**
100
100
  * MPPT data structure based on Model 160
101
+ *
102
+ * SunSpec Model 160 - Multiple MPPT Inverter Extension Model
103
+ *
104
+ * Register Map (offsets relative to module start):
105
+ * - 0: ID - Module/String ID (uint16)
106
+ * - 1-8: N - Module/String Identifier (string, 16 chars)
107
+ * - 9: DCA - DC Current in Amps (uint16)
108
+ * - 10: DCA_SF - DC Current Scale Factor (sunssf/int16)
109
+ * - 11: DCV - DC Voltage in Volts (uint16)
110
+ * - 12: DCV_SF - DC Voltage Scale Factor (sunssf/int16)
111
+ * - 13: DCW - DC Power in Watts (uint16)
112
+ * - 14: DCW_SF - DC Power Scale Factor (sunssf/int16)
113
+ * - 15-16: DCWH - DC Energy in Watt-hours (acc32/uint32)
114
+ * - 17: DCWH_SF - DC Energy Scale Factor (sunssf/int16)
115
+ * - 18-19: Tms - Timestamp in seconds since epoch (uint32)
116
+ * - 20: Tmp - Module Temperature in Celsius (int16)
117
+ * - 21: Tmp_SF - Temperature Scale Factor (sunssf/int16)
118
+ * - 22: St - Operating State (enum16)
119
+ * - 23: StVnd - Vendor Operating State (enum16)
120
+ * - 24-25: Evt - Event Flags (bitfield32)
121
+ *
122
+ * Note: This is a repeating block model where each MPPT string/module
123
+ * occupies 26 registers (0-25). Multiple modules are stored sequentially.
101
124
  */
102
125
  export interface SunspecMPPTData extends SunspecBlock {
103
126
  blockNumber: 160;
@@ -115,14 +138,91 @@ export interface SunspecMPPTData extends SunspecBlock {
115
138
  temperature?: number;
116
139
  temperatureSF?: number;
117
140
  operatingState?: number;
118
- vendorState?: number;
119
141
  events?: number;
120
142
  }
121
143
  /**
122
- * Battery data structure
144
+ * MPPT Operating State values for Model 160
145
+ * These represent the DC module/string operating states
146
+ */
147
+ export declare enum SunspecMPPTOperatingState {
148
+ OFF = 1,
149
+ SLEEPING = 2,
150
+ STARTING = 3,
151
+ MPPT = 4,// Maximum Power Point Tracking active
152
+ THROTTLED = 5,// Power output is being limited
153
+ SHUTTING_DOWN = 6,
154
+ FAULT = 7,
155
+ STANDBY = 8,
156
+ TEST = 9,
157
+ RESERVED_10 = 10
158
+ }
159
+ /**
160
+ * Battery Charge State values for Model 124
161
+ */
162
+ export declare enum SunspecBatteryChargeState {
163
+ OFF = 1,
164
+ EMPTY = 2,
165
+ DISCHARGING = 3,
166
+ CHARGING = 4,
167
+ FULL = 5,
168
+ HOLDING = 6,
169
+ TESTING = 7
170
+ }
171
+ /**
172
+ * Storage Control Mode bitfield values for Model 124
173
+ */
174
+ export declare enum SunspecStorageControlMode {
175
+ CHARGE = 1,// Bit 0 - Enable charge mode
176
+ DISCHARGE = 2
177
+ }
178
+ /**
179
+ * Battery data structure based on Model 124 (Basic Storage Controls)
180
+ *
181
+ * SunSpec Model 124 Register Map:
182
+ * - 0-1: ID and Length
183
+ * - 2: WChaMax - Maximum charge setpoint (W)
184
+ * - 3: WChaGra - Maximum charging rate (% WChaMax/sec)
185
+ * - 4: WDisChaGra - Maximum discharge rate (% WChaMax/sec)
186
+ * - 5: StorCtl_Mod - Storage control mode bitfield
187
+ * - 6: VAChaMax - Maximum charging VA
188
+ * - 7: MinRsvPct - Minimum reserve percentage
189
+ * - 8: ChaState - State of charge (%)
190
+ * - 9: StorAval - Available storage (AH)
191
+ * - 10: InBatV - Internal battery voltage (V)
192
+ * - 11: ChaSt - Charge status enum
193
+ * - 12: OutWRte - Discharge rate (% WDisChaMax)
194
+ * - 13: InWRte - Charge rate (% WChaMax)
195
+ * - 14-16: Timing parameters
196
+ * - 17: ChaGriSet - Charge source setting
197
+ * - 18-25: Scale factors
123
198
  */
124
199
  export interface SunspecBatteryData extends SunspecBlock {
125
200
  blockNumber: 124 | 802 | 803;
201
+ wChaMax?: number;
202
+ wChaMaxSF?: number;
203
+ wChaGra?: number;
204
+ wDisChaGra?: number;
205
+ wChaDisChaGraSF?: number;
206
+ storCtlMod?: number;
207
+ vaChaMax?: number;
208
+ vaChaMaxSF?: number;
209
+ minRsvPct?: number;
210
+ minRsvPctSF?: number;
211
+ chaState?: number;
212
+ chaStateSF?: number;
213
+ storAval?: number;
214
+ storAvalSF?: number;
215
+ inBatV?: number;
216
+ inBatVSF?: number;
217
+ chaSt?: number;
218
+ chaStName?: string;
219
+ outWRte?: number;
220
+ inWRte?: number;
221
+ inOutWRteSF?: number;
222
+ inOutWRteWinTms?: number;
223
+ inOutWRteRvrtTms?: number;
224
+ inOutWRteRmpTms?: number;
225
+ chaGriSet?: number;
126
226
  soc?: number;
127
227
  soh?: number;
128
228
  chargePower?: number;