@enyo-energy/sunspec-sdk 0.0.16 → 0.0.18

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.
@@ -6,6 +6,7 @@ const node_crypto_1 = require("node:crypto");
6
6
  const enyo_appliance_js_1 = require("@enyo-energy/energy-app-sdk/dist/types/enyo-appliance.js");
7
7
  const enyo_data_bus_value_js_1 = require("@enyo-energy/energy-app-sdk/dist/types/enyo-data-bus-value.js");
8
8
  const enyo_source_enum_js_1 = require("@enyo-energy/energy-app-sdk/dist/types/enyo-source.enum.js");
9
+ const enyo_meter_appliance_js_1 = require("@enyo-energy/energy-app-sdk/dist/types/enyo-meter-appliance.js");
9
10
  /**
10
11
  * Base abstract class for all Sunspec devices
11
12
  */
@@ -58,6 +59,7 @@ class SunspecInverter extends BaseSunspecDevice {
58
59
  }
59
60
  // Get device info from common block
60
61
  const commonData = await this.sunspecClient.readCommonBlock();
62
+ const inverterSettings = await this.sunspecClient.readInverterSettings();
61
63
  // Create or update appliance
62
64
  try {
63
65
  this.applianceId = await this.applianceManager.createOrUpdateAppliance({
@@ -70,6 +72,9 @@ class SunspecInverter extends BaseSunspecDevice {
70
72
  serialNumber: commonData?.serialNumber,
71
73
  modelName: commonData?.model,
72
74
  vendorName: commonData?.manufacturer,
75
+ },
76
+ inverter: {
77
+ maxPvProductionW: inverterSettings?.WMax
73
78
  }
74
79
  });
75
80
  console.log(`Sunspec Inverter connected: ${this.networkDevice.hostname} (${this.applianceId})`);
@@ -210,6 +215,7 @@ class SunspecBattery extends BaseSunspecDevice {
210
215
  }
211
216
  // Get device info
212
217
  const commonData = await this.sunspecClient.readCommonBlock();
218
+ const batteryData = await this.sunspecClient.readBatteryData();
213
219
  // Create or update appliance
214
220
  try {
215
221
  this.applianceId = await this.applianceManager.createOrUpdateAppliance({
@@ -219,8 +225,8 @@ class SunspecBattery extends BaseSunspecDevice {
219
225
  metadata: {
220
226
  connectionType: enyo_appliance_js_1.EnyoApplianceConnectionType.Connector,
221
227
  state: enyo_appliance_js_1.EnyoApplianceStateEnum.Connected,
222
- serialNumber: commonData?.serialNumber ? `${commonData.serialNumber}-BAT` : undefined,
223
- modelName: commonData?.model ? `${commonData.model} Battery` : 'Battery',
228
+ serialNumber: commonData?.serialNumber,
229
+ modelName: commonData?.model,
224
230
  vendorName: commonData?.manufacturer,
225
231
  }
226
232
  });
@@ -282,6 +288,7 @@ class SunspecBattery extends BaseSunspecDevice {
282
288
  else if (batteryData.dischargePower !== undefined && batteryData.dischargePower > 0) {
283
289
  batteryPowerW = -batteryData.dischargePower; // Negative for discharging
284
290
  }
291
+ const advancedBatteryModel = this.sunspecClient.findModel(801);
285
292
  const batteryMessage = {
286
293
  id: (0, node_crypto_1.randomUUID)(),
287
294
  message: enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.BatteryValuesUpdateV1,
@@ -293,8 +300,8 @@ class SunspecBattery extends BaseSunspecDevice {
293
300
  resolution,
294
301
  data: {
295
302
  batterySoC: batteryData.soc || batteryData.chaState || 0,
296
- batteryPowerW: batteryPowerW,
297
- state: this.mapToEnyoBatteryState(batteryData.chaSt)
303
+ batteryPowerW: advancedBatteryModel ? batteryPowerW : undefined,
304
+ state: this.mapToEnyoBatteryState(batteryData.chaSt),
298
305
  }
299
306
  };
300
307
  messages.push(batteryMessage);
@@ -359,9 +366,15 @@ class SunspecMeter extends BaseSunspecDevice {
359
366
  metadata: {
360
367
  connectionType: enyo_appliance_js_1.EnyoApplianceConnectionType.Connector,
361
368
  state: enyo_appliance_js_1.EnyoApplianceStateEnum.Connected,
362
- serialNumber: commonData?.serialNumber ? `${commonData.serialNumber}-MTR` : undefined,
363
- modelName: commonData?.model ? `${commonData.model} Meter` : 'Meter',
369
+ serialNumber: commonData?.serialNumber,
370
+ modelName: commonData?.model,
364
371
  vendorName: commonData?.manufacturer,
372
+ },
373
+ topology: {
374
+ features: [enyo_appliance_js_1.EnyoApplianceTopologyFeatureEnum.PrimaryMeter]
375
+ },
376
+ meter: {
377
+ availableFeatures: [enyo_meter_appliance_js_1.EnyoMeterApplianceAvailableFeaturesEnum.LivePowerConsumption]
365
378
  }
366
379
  });
367
380
  console.log(`Sunspec Meter connected: ${this.networkDevice.hostname} unit ${this.unitId} (${this.applianceId})`);
@@ -363,18 +363,9 @@ class SunspecModbusClient {
363
363
  // Read AC Energy (32-bit accumulator) - Offset 24-25
364
364
  const acEnergyAddr = baseAddr + 24;
365
365
  const acEnergy = await this.readRegisterValue(acEnergyAddr, 2, 'uint32');
366
- console.log(`AC Energy: address=${acEnergyAddr}, raw=0x${acEnergy.toString(16).toUpperCase()} (${acEnergy}), SF=${scaleFactors.WH_SF}`);
367
366
  data.acEnergy = !this.isUnimplementedValue(acEnergy, 'acc32')
368
367
  ? acEnergy * Math.pow(10, scaleFactors.WH_SF) // Regular number with scale factor
369
368
  : undefined;
370
- // Log final calculated values
371
- console.log('Inverter Final Values:', {
372
- acPower: data.acPower,
373
- voltageAN: data.voltageAN,
374
- voltageBN: data.voltageBN,
375
- voltageCN: data.voltageCN,
376
- acCurrent: data.acCurrent
377
- });
378
369
  return data;
379
370
  }
380
371
  catch (error) {
@@ -610,6 +601,7 @@ class SunspecModbusClient {
610
601
  for (let i = 1; i <= 4; i++) {
611
602
  try {
612
603
  const data = await this.readMPPTData(i);
604
+ console.log(`MPPT ${i} has id ${data?.id} (${data?.stringId}) with ${data?.dcPower}W`);
613
605
  // Only include if we got valid data (not null) and it has actual values
614
606
  if (data &&
615
607
  (data.dcCurrent !== undefined ||
@@ -757,19 +749,13 @@ class SunspecModbusClient {
757
749
  // Calculate charge/discharge power if rates are available
758
750
  if (data.inWRte !== undefined && data.wChaMax !== undefined) {
759
751
  data.chargePower = (data.inWRte / 100) * data.wChaMax;
760
- console.log(`Calculated Charge Power: ${data.chargePower?.toFixed(2)} W`);
752
+ console.log(`Calculated Charge Power: (inWRte: ${data.inWRte}, wChaMax: ${data.wChaMax}) ${data.chargePower?.toFixed(2)} W`);
761
753
  }
762
754
  if (data.outWRte !== undefined && data.wChaMax !== undefined) {
763
755
  // Assuming WDisChaMax is similar to WChaMax for simplicity
764
756
  data.dischargePower = Math.abs((data.outWRte / 100) * data.wChaMax);
765
- console.log(`Calculated Discharge Power: ${data.dischargePower?.toFixed(2)} W`);
757
+ console.log(`Calculated Discharge Power (inWRte: ${data.outWRte}, wChaMax: ${data.wChaMax}): ${data.dischargePower?.toFixed(2)} W`);
766
758
  }
767
- console.log('Battery Status:', {
768
- soc: data.soc !== undefined ? `${data.soc.toFixed(1)}%` : 'N/A',
769
- voltage: data.voltage !== undefined ? `${data.voltage.toFixed(2)} V` : 'N/A',
770
- chargeState: chaStName,
771
- availableStorage: data.storAval !== undefined ? `${data.storAval.toFixed(2)} AH` : 'N/A'
772
- });
773
759
  return data;
774
760
  }
775
761
  else {
@@ -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.16';
12
+ exports.SDK_VERSION = '0.0.18';
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.16";
8
+ export declare const SDK_VERSION = "0.0.18";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
@@ -1,8 +1,9 @@
1
- import { SunspecModelId, SunspecMPPTOperatingState, SunspecBatteryChargeState } from "./sunspec-interfaces.js";
1
+ import { SunspecBatteryChargeState, SunspecModelId, SunspecMPPTOperatingState } from "./sunspec-interfaces.js";
2
2
  import { randomUUID } from "node:crypto";
3
- import { EnyoApplianceConnectionType, EnyoApplianceStateEnum, EnyoApplianceTypeEnum } from "@enyo-energy/energy-app-sdk/dist/types/enyo-appliance.js";
3
+ import { EnyoApplianceConnectionType, EnyoApplianceStateEnum, EnyoApplianceTopologyFeatureEnum, EnyoApplianceTypeEnum } from "@enyo-energy/energy-app-sdk/dist/types/enyo-appliance.js";
4
4
  import { EnyoBatteryStateEnum, EnyoDataBusMessageEnum, EnyoInverterStateEnum } from "@enyo-energy/energy-app-sdk/dist/types/enyo-data-bus-value.js";
5
5
  import { EnyoSourceEnum } from "@enyo-energy/energy-app-sdk/dist/types/enyo-source.enum.js";
6
+ import { EnyoMeterApplianceAvailableFeaturesEnum } from "@enyo-energy/energy-app-sdk/dist/types/enyo-meter-appliance.js";
6
7
  /**
7
8
  * Base abstract class for all Sunspec devices
8
9
  */
@@ -54,6 +55,7 @@ export class SunspecInverter extends BaseSunspecDevice {
54
55
  }
55
56
  // Get device info from common block
56
57
  const commonData = await this.sunspecClient.readCommonBlock();
58
+ const inverterSettings = await this.sunspecClient.readInverterSettings();
57
59
  // Create or update appliance
58
60
  try {
59
61
  this.applianceId = await this.applianceManager.createOrUpdateAppliance({
@@ -66,6 +68,9 @@ export class SunspecInverter extends BaseSunspecDevice {
66
68
  serialNumber: commonData?.serialNumber,
67
69
  modelName: commonData?.model,
68
70
  vendorName: commonData?.manufacturer,
71
+ },
72
+ inverter: {
73
+ maxPvProductionW: inverterSettings?.WMax
69
74
  }
70
75
  });
71
76
  console.log(`Sunspec Inverter connected: ${this.networkDevice.hostname} (${this.applianceId})`);
@@ -205,6 +210,7 @@ export class SunspecBattery extends BaseSunspecDevice {
205
210
  }
206
211
  // Get device info
207
212
  const commonData = await this.sunspecClient.readCommonBlock();
213
+ const batteryData = await this.sunspecClient.readBatteryData();
208
214
  // Create or update appliance
209
215
  try {
210
216
  this.applianceId = await this.applianceManager.createOrUpdateAppliance({
@@ -214,8 +220,8 @@ export class SunspecBattery extends BaseSunspecDevice {
214
220
  metadata: {
215
221
  connectionType: EnyoApplianceConnectionType.Connector,
216
222
  state: EnyoApplianceStateEnum.Connected,
217
- serialNumber: commonData?.serialNumber ? `${commonData.serialNumber}-BAT` : undefined,
218
- modelName: commonData?.model ? `${commonData.model} Battery` : 'Battery',
223
+ serialNumber: commonData?.serialNumber,
224
+ modelName: commonData?.model,
219
225
  vendorName: commonData?.manufacturer,
220
226
  }
221
227
  });
@@ -277,6 +283,7 @@ export class SunspecBattery extends BaseSunspecDevice {
277
283
  else if (batteryData.dischargePower !== undefined && batteryData.dischargePower > 0) {
278
284
  batteryPowerW = -batteryData.dischargePower; // Negative for discharging
279
285
  }
286
+ const advancedBatteryModel = this.sunspecClient.findModel(801);
280
287
  const batteryMessage = {
281
288
  id: randomUUID(),
282
289
  message: EnyoDataBusMessageEnum.BatteryValuesUpdateV1,
@@ -288,8 +295,8 @@ export class SunspecBattery extends BaseSunspecDevice {
288
295
  resolution,
289
296
  data: {
290
297
  batterySoC: batteryData.soc || batteryData.chaState || 0,
291
- batteryPowerW: batteryPowerW,
292
- state: this.mapToEnyoBatteryState(batteryData.chaSt)
298
+ batteryPowerW: advancedBatteryModel ? batteryPowerW : undefined,
299
+ state: this.mapToEnyoBatteryState(batteryData.chaSt),
293
300
  }
294
301
  };
295
302
  messages.push(batteryMessage);
@@ -353,9 +360,15 @@ export class SunspecMeter extends BaseSunspecDevice {
353
360
  metadata: {
354
361
  connectionType: EnyoApplianceConnectionType.Connector,
355
362
  state: EnyoApplianceStateEnum.Connected,
356
- serialNumber: commonData?.serialNumber ? `${commonData.serialNumber}-MTR` : undefined,
357
- modelName: commonData?.model ? `${commonData.model} Meter` : 'Meter',
363
+ serialNumber: commonData?.serialNumber,
364
+ modelName: commonData?.model,
358
365
  vendorName: commonData?.manufacturer,
366
+ },
367
+ topology: {
368
+ features: [EnyoApplianceTopologyFeatureEnum.PrimaryMeter]
369
+ },
370
+ meter: {
371
+ availableFeatures: [EnyoMeterApplianceAvailableFeaturesEnum.LivePowerConsumption]
359
372
  }
360
373
  });
361
374
  console.log(`Sunspec Meter connected: ${this.networkDevice.hostname} unit ${this.unitId} (${this.applianceId})`);
@@ -360,18 +360,9 @@ export class SunspecModbusClient {
360
360
  // Read AC Energy (32-bit accumulator) - Offset 24-25
361
361
  const acEnergyAddr = baseAddr + 24;
362
362
  const acEnergy = await this.readRegisterValue(acEnergyAddr, 2, 'uint32');
363
- console.log(`AC Energy: address=${acEnergyAddr}, raw=0x${acEnergy.toString(16).toUpperCase()} (${acEnergy}), SF=${scaleFactors.WH_SF}`);
364
363
  data.acEnergy = !this.isUnimplementedValue(acEnergy, 'acc32')
365
364
  ? acEnergy * Math.pow(10, scaleFactors.WH_SF) // Regular number with scale factor
366
365
  : undefined;
367
- // Log final calculated values
368
- console.log('Inverter Final Values:', {
369
- acPower: data.acPower,
370
- voltageAN: data.voltageAN,
371
- voltageBN: data.voltageBN,
372
- voltageCN: data.voltageCN,
373
- acCurrent: data.acCurrent
374
- });
375
366
  return data;
376
367
  }
377
368
  catch (error) {
@@ -607,6 +598,7 @@ export class SunspecModbusClient {
607
598
  for (let i = 1; i <= 4; i++) {
608
599
  try {
609
600
  const data = await this.readMPPTData(i);
601
+ console.log(`MPPT ${i} has id ${data?.id} (${data?.stringId}) with ${data?.dcPower}W`);
610
602
  // Only include if we got valid data (not null) and it has actual values
611
603
  if (data &&
612
604
  (data.dcCurrent !== undefined ||
@@ -754,19 +746,13 @@ export class SunspecModbusClient {
754
746
  // Calculate charge/discharge power if rates are available
755
747
  if (data.inWRte !== undefined && data.wChaMax !== undefined) {
756
748
  data.chargePower = (data.inWRte / 100) * data.wChaMax;
757
- console.log(`Calculated Charge Power: ${data.chargePower?.toFixed(2)} W`);
749
+ console.log(`Calculated Charge Power: (inWRte: ${data.inWRte}, wChaMax: ${data.wChaMax}) ${data.chargePower?.toFixed(2)} W`);
758
750
  }
759
751
  if (data.outWRte !== undefined && data.wChaMax !== undefined) {
760
752
  // Assuming WDisChaMax is similar to WChaMax for simplicity
761
753
  data.dischargePower = Math.abs((data.outWRte / 100) * data.wChaMax);
762
- console.log(`Calculated Discharge Power: ${data.dischargePower?.toFixed(2)} W`);
754
+ console.log(`Calculated Discharge Power (inWRte: ${data.outWRte}, wChaMax: ${data.wChaMax}): ${data.dischargePower?.toFixed(2)} W`);
763
755
  }
764
- console.log('Battery Status:', {
765
- soc: data.soc !== undefined ? `${data.soc.toFixed(1)}%` : 'N/A',
766
- voltage: data.voltage !== undefined ? `${data.voltage.toFixed(2)} V` : 'N/A',
767
- chargeState: chaStName,
768
- availableStorage: data.storAval !== undefined ? `${data.storAval.toFixed(2)} AH` : 'N/A'
769
- });
770
756
  return data;
771
757
  }
772
758
  else {
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.16";
8
+ export declare const SDK_VERSION = "0.0.18";
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.16';
8
+ export const SDK_VERSION = '0.0.18';
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.16",
3
+ "version": "0.0.18",
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.39"
40
+ "@enyo-energy/energy-app-sdk": "^0.0.40"
41
41
  },
42
42
  "volta": {
43
43
  "node": "22.17.0"