@enyo-energy/sunspec-sdk 0.0.6 → 0.0.8

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.
@@ -103,6 +103,15 @@ class SunspecInverter extends BaseSunspecDevice {
103
103
  const inverterData = await this.sunspecClient.readInverterData();
104
104
  const mpptDataList = await this.sunspecClient.readAllMPPTData();
105
105
  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
+ });
106
115
  const inverterMessage = {
107
116
  id: (0, node_crypto_1.randomUUID)(),
108
117
  message: enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.InverterValuesUpdateV1,
@@ -117,8 +126,8 @@ class SunspecInverter extends BaseSunspecDevice {
117
126
  activePowerLimitationW: inverterData.acPower || 0,
118
127
  state: this.mapOperatingState(inverterData.operatingState),
119
128
  voltageL1: inverterData.voltageAN || 0,
120
- voltageL2: inverterData.voltageBN ?? undefined, // Use null if undefined (unimplemented phase)
121
- voltageL3: inverterData.voltageCN ?? undefined, // Use null if undefined (unimplemented phase)
129
+ voltageL2: inverterData.voltageBN ?? undefined, // Use undefined if unimplemented phase
130
+ voltageL3: inverterData.voltageCN ?? undefined, // Use undefined if unimplemented phase
122
131
  strings: this.mapMPPTToStrings(mpptDataList)
123
132
  }
124
133
  };
@@ -79,7 +79,7 @@ export interface SunspecInverterData extends SunspecBlock {
79
79
  apparentPower?: number;
80
80
  reactivePower?: number;
81
81
  powerFactor?: number;
82
- acEnergy?: bigint;
82
+ acEnergy?: number;
83
83
  dcCurrent?: number;
84
84
  dcVoltage?: number;
85
85
  dcPower?: number;
@@ -109,7 +109,7 @@ export interface SunspecMPPTData extends SunspecBlock {
109
109
  dcVoltageSF?: number;
110
110
  dcPower?: number;
111
111
  dcPowerSF?: number;
112
- dcEnergy?: bigint;
112
+ dcEnergy?: number;
113
113
  dcEnergySF?: number;
114
114
  timestamp?: number;
115
115
  temperature?: number;
@@ -141,9 +141,9 @@ export interface SunspecMeterData extends SunspecBlock {
141
141
  phaseAPower?: number;
142
142
  phaseBPower?: number;
143
143
  phaseCPower?: number;
144
- totalEnergy?: bigint;
145
- exportedEnergy?: bigint;
146
- importedEnergy?: bigint;
144
+ totalEnergy?: number;
145
+ exportedEnergy?: number;
146
+ importedEnergy?: number;
147
147
  voltage?: number;
148
148
  current?: number;
149
149
  frequency?: number;
@@ -279,11 +279,14 @@ class SunspecModbusClient {
279
279
  console.error('No inverter model found');
280
280
  return null;
281
281
  }
282
+ console.warn('IMPORTANT: Working with single-phase inverter, but 3-phase is expected!');
282
283
  return this.readSinglePhaseInverterData(singlePhaseModel);
283
284
  }
285
+ console.log(`Found 3-phase inverter model 103 at address ${model.address} with length ${model.length}`);
284
286
  const baseAddr = model.address + 2; // Skip ID and Length
285
287
  try {
286
288
  // Read all scale factors first using fault-tolerant reader
289
+ console.log(`Reading Inverter Data from Model 103 at base address: ${baseAddr}`);
287
290
  const scaleFactors = await this.readInverterScaleFactors(baseAddr);
288
291
  // Read values using fault-tolerant reader with proper data types
289
292
  // Read raw voltage values to check for unimplemented phases
@@ -300,7 +303,12 @@ class SunspecModbusClient {
300
303
  blockAddress: model.address,
301
304
  blockLength: model.length,
302
305
  // AC Current values - Offsets 2-5
303
- acCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 2, 1, 'uint16'), scaleFactors.A_SF),
306
+ acCurrent: this.applyScaleFactor(await (async () => {
307
+ const addr = baseAddr + 2;
308
+ const raw = await this.readRegisterValue(addr, 1, 'uint16');
309
+ console.log(`AC Current: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw})`);
310
+ return raw;
311
+ })(), scaleFactors.A_SF),
304
312
  phaseACurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 3, 1, 'uint16'), scaleFactors.A_SF),
305
313
  phaseBCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 4, 1, 'uint16'), scaleFactors.A_SF),
306
314
  phaseCCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 5, 1, 'uint16'), scaleFactors.A_SF),
@@ -313,16 +321,36 @@ class SunspecModbusClient {
313
321
  voltageBN: this.applyScaleFactor(voltageBNRaw, scaleFactors.V_SF),
314
322
  voltageCN: this.applyScaleFactor(voltageCNRaw, scaleFactors.V_SF),
315
323
  // Power values - Offsets 14, 18, 20, 22
316
- acPower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 14, 1, 'int16'), scaleFactors.W_SF),
324
+ acPower: this.applyScaleFactor(await (async () => {
325
+ const addr = baseAddr + 14;
326
+ const raw = await this.readRegisterValue(addr, 1, 'int16');
327
+ console.log(`AC Power (W): address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw}), SF=${scaleFactors.W_SF}`);
328
+ return raw;
329
+ })(), scaleFactors.W_SF, 'int16'),
317
330
  apparentPower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 18, 1, 'uint16'), scaleFactors.VA_SF),
318
331
  reactivePower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 20, 1, 'int16'), scaleFactors.VAr_SF),
319
332
  powerFactor: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 22, 1, 'int16'), scaleFactors.PF_SF),
320
333
  // Frequency - Offset 16
321
334
  frequency: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 16, 1, 'uint16'), scaleFactors.Hz_SF),
322
335
  // DC values - Offsets 27, 28, 30
323
- dcCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 27, 1, 'uint16'), scaleFactors.DCA_SF),
324
- dcVoltage: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 28, 1, 'uint16'), scaleFactors.DCV_SF),
325
- dcPower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 30, 1, 'int16'), scaleFactors.DCW_SF),
336
+ dcCurrent: this.applyScaleFactor(await (async () => {
337
+ const addr = baseAddr + 27;
338
+ const raw = await this.readRegisterValue(addr, 1, 'uint16');
339
+ console.log(`DC Current: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw})`);
340
+ return raw;
341
+ })(), scaleFactors.DCA_SF),
342
+ dcVoltage: this.applyScaleFactor(await (async () => {
343
+ const addr = baseAddr + 28;
344
+ const raw = await this.readRegisterValue(addr, 1, 'uint16');
345
+ console.log(`DC Voltage: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw})`);
346
+ return raw;
347
+ })(), scaleFactors.DCV_SF),
348
+ dcPower: this.applyScaleFactor(await (async () => {
349
+ const addr = baseAddr + 30;
350
+ const raw = await this.readRegisterValue(addr, 1, 'int16');
351
+ console.log(`DC Power: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw}), SF=${scaleFactors.DCW_SF}`);
352
+ return raw;
353
+ })(), scaleFactors.DCW_SF, 'int16'),
326
354
  // Temperature values - Offsets 32, 34, 35, 36
327
355
  cabinetTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 32, 1, 'int16'), scaleFactors.Tmp_SF),
328
356
  heatSinkTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 34, 1, 'int16'), scaleFactors.Tmp_SF),
@@ -340,8 +368,20 @@ class SunspecModbusClient {
340
368
  vendorEvents4: await this.readRegisterValue(baseAddr + 50, 2, 'uint32')
341
369
  };
342
370
  // Read AC Energy (32-bit accumulator) - Offset 24-25
343
- const acEnergy = await this.readRegisterValue(baseAddr + 24, 2, 'acc32');
344
- data.acEnergy = BigInt(acEnergy) * BigInt(Math.pow(10, scaleFactors.WH_SF));
371
+ const acEnergyAddr = baseAddr + 24;
372
+ const acEnergy = await this.readRegisterValue(acEnergyAddr, 2, 'acc32');
373
+ console.log(`AC Energy: address=${acEnergyAddr}, raw=0x${acEnergy.toString(16).toUpperCase()} (${acEnergy}), SF=${scaleFactors.WH_SF}`);
374
+ data.acEnergy = !this.isUnimplementedValue(acEnergy, 'uint32')
375
+ ? acEnergy * Math.pow(10, scaleFactors.WH_SF) // Regular number with scale factor
376
+ : undefined;
377
+ // Log final calculated values
378
+ console.log('Inverter Final Values:', {
379
+ acPower: data.acPower,
380
+ voltageAN: data.voltageAN,
381
+ voltageBN: data.voltageBN,
382
+ voltageCN: data.voltageCN,
383
+ acCurrent: data.acCurrent
384
+ });
345
385
  return data;
346
386
  }
347
387
  catch (error) {
@@ -357,15 +397,53 @@ class SunspecModbusClient {
357
397
  // Implementation would be similar but simplified
358
398
  const baseAddr = model.address + 2;
359
399
  try {
360
- // Simplified implementation for single phase
400
+ console.log(`Reading Single-Phase Inverter Data from Model 101 at base address: ${baseAddr}`);
401
+ // Read scale factors for single phase model
402
+ const scaleFactors = {
403
+ A_SF: await this.readRegisterValue(baseAddr + 6, 1, 'int16'),
404
+ V_SF: await this.readRegisterValue(baseAddr + 13, 1, 'int16'),
405
+ W_SF: await this.readRegisterValue(baseAddr + 10, 1, 'int16'),
406
+ Hz_SF: await this.readRegisterValue(baseAddr + 12, 1, 'int16'),
407
+ DCA_SF: await this.readRegisterValue(baseAddr + 18, 1, 'int16'),
408
+ DCV_SF: await this.readRegisterValue(baseAddr + 19, 1, 'int16'),
409
+ DCW_SF: await this.readRegisterValue(baseAddr + 21, 1, 'int16')
410
+ };
411
+ console.log('Single-Phase Inverter Scale Factors:', JSON.stringify(scaleFactors, null, 2));
412
+ // Read raw values with logging
413
+ const acCurrentAddr = baseAddr + 2;
414
+ const acCurrentRaw = await this.readRegisterValue(acCurrentAddr, 1, 'uint16');
415
+ console.log(`AC Current: address=${acCurrentAddr}, raw=0x${acCurrentRaw.toString(16).toUpperCase()} (${acCurrentRaw})`);
416
+ const voltageAddr = baseAddr + 7;
417
+ const voltageRaw = await this.readRegisterValue(voltageAddr, 1, 'uint16');
418
+ console.log(`AC Voltage: address=${voltageAddr}, raw=0x${voltageRaw.toString(16).toUpperCase()} (${voltageRaw})`);
419
+ const acPowerAddr = baseAddr + 9;
420
+ const acPowerRaw = await this.readRegisterValue(acPowerAddr, 1, 'int16');
421
+ console.log(`AC Power: address=${acPowerAddr}, raw=0x${acPowerRaw.toString(16).toUpperCase()} (${acPowerRaw}), SF=${scaleFactors.W_SF}`);
422
+ const freqAddr = baseAddr + 11;
423
+ const freqRaw = await this.readRegisterValue(freqAddr, 1, 'uint16');
424
+ console.log(`Frequency: address=${freqAddr}, raw=0x${freqRaw.toString(16).toUpperCase()} (${freqRaw})`);
425
+ const dcCurrentAddr = baseAddr + 14;
426
+ const dcCurrentRaw = await this.readRegisterValue(dcCurrentAddr, 1, 'uint16');
427
+ console.log(`DC Current: address=${dcCurrentAddr}, raw=0x${dcCurrentRaw.toString(16).toUpperCase()} (${dcCurrentRaw})`);
428
+ const dcVoltageAddr = baseAddr + 15;
429
+ const dcVoltageRaw = await this.readRegisterValue(dcVoltageAddr, 1, 'uint16');
430
+ console.log(`DC Voltage: address=${dcVoltageAddr}, raw=0x${dcVoltageRaw.toString(16).toUpperCase()} (${dcVoltageRaw})`);
431
+ const dcPowerAddr = baseAddr + 20;
432
+ const dcPowerRaw = await this.readRegisterValue(dcPowerAddr, 1, 'int16');
433
+ console.log(`DC Power: address=${dcPowerAddr}, raw=0x${dcPowerRaw.toString(16).toUpperCase()} (${dcPowerRaw}), SF=${scaleFactors.DCW_SF}`);
434
+ const stateAddr = baseAddr + 24;
435
+ const stateRaw = await this.readRegisterValue(stateAddr, 1, 'uint16');
436
+ console.log(`Operating State: address=${stateAddr}, raw=0x${stateRaw.toString(16).toUpperCase()} (${stateRaw})`);
361
437
  return {
362
438
  blockNumber: 101,
363
- voltageAN: await this.readRegisterWithScaleFactor(baseAddr + 7, baseAddr + 13), // PhVphA with V_SF
364
- acCurrent: await this.readRegisterWithScaleFactor(baseAddr + 2, baseAddr + 6),
365
- acPower: await this.readRegisterWithScaleFactor(baseAddr + 9, baseAddr + 10),
366
- frequency: await this.readRegisterWithScaleFactor(baseAddr + 11, baseAddr + 12),
367
- dcPower: await this.readRegisterWithScaleFactor(baseAddr + 20, baseAddr + 21),
368
- operatingState: await this.readRegisterValue(baseAddr + 24, 1)
439
+ voltageAN: this.applyScaleFactor(voltageRaw, scaleFactors.V_SF),
440
+ acCurrent: this.applyScaleFactor(acCurrentRaw, scaleFactors.A_SF),
441
+ acPower: this.applyScaleFactor(acPowerRaw, scaleFactors.W_SF, 'int16'),
442
+ frequency: this.applyScaleFactor(freqRaw, scaleFactors.Hz_SF),
443
+ dcCurrent: this.applyScaleFactor(dcCurrentRaw, scaleFactors.DCA_SF),
444
+ dcVoltage: this.applyScaleFactor(dcVoltageRaw, scaleFactors.DCV_SF),
445
+ dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'int16'),
446
+ operatingState: stateRaw
369
447
  };
370
448
  }
371
449
  catch (error) {
@@ -403,11 +481,6 @@ class SunspecModbusClient {
403
481
  if (this.isUnimplementedValue(value, dataType)) {
404
482
  return undefined;
405
483
  }
406
- // Validate scale factor is within reasonable range (-10 to +10)
407
- if (Math.abs(scaleFactor) > 10) {
408
- console.warn(`Scale factor ${scaleFactor} is outside reasonable range, clamping to ±10`);
409
- scaleFactor = Math.max(-10, Math.min(10, scaleFactor));
410
- }
411
484
  return value * Math.pow(10, scaleFactor);
412
485
  }
413
486
  /**
@@ -474,7 +547,7 @@ class SunspecModbusClient {
474
547
  // DC Energy - Offset 15-16 (32-bit accumulator)
475
548
  // Only calculate if value is not unimplemented
476
549
  dcEnergy: !this.isUnimplementedValue(dcEnergyRaw, 'uint32')
477
- ? BigInt(dcEnergyRaw) * BigInt(Math.pow(10, scaleFactors.DCWH_SF))
550
+ ? dcEnergyRaw * Math.pow(10, scaleFactors.DCWH_SF) // Regular number with scale factor
478
551
  : undefined,
479
552
  dcEnergySF: scaleFactors.DCWH_SF,
480
553
  // Timestamp - Offset 18-19 (32-bit)
@@ -536,13 +609,58 @@ class SunspecModbusClient {
536
609
  return null;
537
610
  }
538
611
  const baseAddr = model.address + 2;
612
+ console.log(`Reading Meter Data from Model ${model.id} at base address: ${baseAddr}`);
539
613
  try {
540
- // This is a simplified implementation
541
- // Actual register offsets depend on specific meter model
614
+ // Model 201 (single phase meter) - Correct register offsets from Sunspec
615
+ // All offsets are from data start (after ID and Length)
616
+ console.log(`Meter is Model 201 (Single Phase Meter)`);
617
+ // Model 201 register offsets according to Sunspec specification:
618
+ const powerOffset = 18; // W - Total Real Power (int16) at offset 18
619
+ const powerSFOffset = 21; // W_SF - Power scale factor at offset 21
620
+ const freqOffset = 32; // Hz - Frequency (uint16) at offset 32
621
+ const freqSFOffset = 35; // Hz_SF - Frequency scale factor at offset 35
622
+ const exportOffset = 38; // TotWhExp - Total Wh Exported (acc32) at offset 38-39
623
+ const importOffset = 46; // TotWhImp - Total Wh Imported (acc32) at offset 46-47
624
+ const energySFOffset = 4; // TotWh_SF - Total Energy scale factor at offset 4
625
+ // Read scale factors
626
+ const powerSF = await this.readRegisterValue(baseAddr + powerSFOffset, 1, 'int16');
627
+ const freqSF = await this.readRegisterValue(baseAddr + freqSFOffset, 1, 'int16');
628
+ const energySF = await this.readRegisterValue(baseAddr + energySFOffset, 1, 'int16');
629
+ console.log(`Meter Scale Factors: Power_SF=${powerSF}, Freq_SF=${freqSF}, Energy_SF=${energySF}`);
630
+ // Read raw values
631
+ const powerAddr = baseAddr + powerOffset;
632
+ const powerRaw = await this.readRegisterValue(powerAddr, 1, 'int16');
633
+ console.log(`Meter Total Power: address=${powerAddr}, raw=0x${powerRaw.toString(16).toUpperCase()} (${powerRaw}), SF=${powerSF}`);
634
+ const freqAddr = baseAddr + freqOffset;
635
+ const freqRaw = await this.readRegisterValue(freqAddr, 1, 'uint16');
636
+ console.log(`Meter Frequency: address=${freqAddr}, raw=0x${freqRaw.toString(16).toUpperCase()} (${freqRaw}), SF=${freqSF}`);
637
+ const exportAddr = baseAddr + exportOffset;
638
+ const exportRaw = await this.readRegisterValue(exportAddr, 2, 'acc32');
639
+ console.log(`Meter Export Energy: address=${exportAddr}, raw=0x${exportRaw.toString(16).toUpperCase()} (${exportRaw}), SF=${energySF}`);
640
+ const importAddr = baseAddr + importOffset;
641
+ const importRaw = await this.readRegisterValue(importAddr, 2, 'acc32');
642
+ console.log(`Meter Import Energy: address=${importAddr}, raw=0x${importRaw.toString(16).toUpperCase()} (${importRaw}), SF=${energySF}`);
643
+ // Calculate final values with scale factors
644
+ const totalPower = this.applyScaleFactor(powerRaw, powerSF, 'int16');
645
+ const frequency = this.applyScaleFactor(freqRaw, freqSF);
646
+ const exportedEnergy = !this.isUnimplementedValue(exportRaw, 'uint32')
647
+ ? exportRaw * Math.pow(10, energySF) // Regular number, not BigInt
648
+ : undefined;
649
+ const importedEnergy = !this.isUnimplementedValue(importRaw, 'uint32')
650
+ ? importRaw * Math.pow(10, energySF) // Regular number, not BigInt
651
+ : undefined;
652
+ console.log('Meter Final Values:', {
653
+ totalPower,
654
+ frequency,
655
+ exportedEnergy,
656
+ importedEnergy
657
+ });
542
658
  return {
543
659
  blockNumber: model.id,
544
- totalPower: await this.readRegisterWithScaleFactor(baseAddr + 10, baseAddr + 11),
545
- frequency: await this.readRegisterWithScaleFactor(baseAddr + 20, baseAddr + 21)
660
+ totalPower,
661
+ frequency,
662
+ exportedEnergy,
663
+ importedEnergy
546
664
  };
547
665
  }
548
666
  catch (error) {
@@ -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.6';
12
+ exports.SDK_VERSION = '0.0.8';
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.6";
8
+ export declare const SDK_VERSION = "0.0.8";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
@@ -99,6 +99,15 @@ export class SunspecInverter extends BaseSunspecDevice {
99
99
  const inverterData = await this.sunspecClient.readInverterData();
100
100
  const mpptDataList = await this.sunspecClient.readAllMPPTData();
101
101
  if (inverterData) {
102
+ // Log what we're sending
103
+ console.log('Preparing Inverter Message:', {
104
+ pvPowerW: inverterData.dcPower,
105
+ acPower: inverterData.acPower,
106
+ voltageL1: inverterData.voltageAN,
107
+ voltageL2: inverterData.voltageBN,
108
+ voltageL3: inverterData.voltageCN,
109
+ stringsCount: mpptDataList.length
110
+ });
102
111
  const inverterMessage = {
103
112
  id: randomUUID(),
104
113
  message: EnyoDataBusMessageEnum.InverterValuesUpdateV1,
@@ -113,8 +122,8 @@ export class SunspecInverter extends BaseSunspecDevice {
113
122
  activePowerLimitationW: inverterData.acPower || 0,
114
123
  state: this.mapOperatingState(inverterData.operatingState),
115
124
  voltageL1: inverterData.voltageAN || 0,
116
- voltageL2: inverterData.voltageBN ?? undefined, // Use null if undefined (unimplemented phase)
117
- voltageL3: inverterData.voltageCN ?? undefined, // Use null if undefined (unimplemented phase)
125
+ voltageL2: inverterData.voltageBN ?? undefined, // Use undefined if unimplemented phase
126
+ voltageL3: inverterData.voltageCN ?? undefined, // Use undefined if unimplemented phase
118
127
  strings: this.mapMPPTToStrings(mpptDataList)
119
128
  }
120
129
  };
@@ -79,7 +79,7 @@ export interface SunspecInverterData extends SunspecBlock {
79
79
  apparentPower?: number;
80
80
  reactivePower?: number;
81
81
  powerFactor?: number;
82
- acEnergy?: bigint;
82
+ acEnergy?: number;
83
83
  dcCurrent?: number;
84
84
  dcVoltage?: number;
85
85
  dcPower?: number;
@@ -109,7 +109,7 @@ export interface SunspecMPPTData extends SunspecBlock {
109
109
  dcVoltageSF?: number;
110
110
  dcPower?: number;
111
111
  dcPowerSF?: number;
112
- dcEnergy?: bigint;
112
+ dcEnergy?: number;
113
113
  dcEnergySF?: number;
114
114
  timestamp?: number;
115
115
  temperature?: number;
@@ -141,9 +141,9 @@ export interface SunspecMeterData extends SunspecBlock {
141
141
  phaseAPower?: number;
142
142
  phaseBPower?: number;
143
143
  phaseCPower?: number;
144
- totalEnergy?: bigint;
145
- exportedEnergy?: bigint;
146
- importedEnergy?: bigint;
144
+ totalEnergy?: number;
145
+ exportedEnergy?: number;
146
+ importedEnergy?: number;
147
147
  voltage?: number;
148
148
  current?: number;
149
149
  frequency?: number;
@@ -276,11 +276,14 @@ export class SunspecModbusClient {
276
276
  console.error('No inverter model found');
277
277
  return null;
278
278
  }
279
+ console.warn('IMPORTANT: Working with single-phase inverter, but 3-phase is expected!');
279
280
  return this.readSinglePhaseInverterData(singlePhaseModel);
280
281
  }
282
+ console.log(`Found 3-phase inverter model 103 at address ${model.address} with length ${model.length}`);
281
283
  const baseAddr = model.address + 2; // Skip ID and Length
282
284
  try {
283
285
  // Read all scale factors first using fault-tolerant reader
286
+ console.log(`Reading Inverter Data from Model 103 at base address: ${baseAddr}`);
284
287
  const scaleFactors = await this.readInverterScaleFactors(baseAddr);
285
288
  // Read values using fault-tolerant reader with proper data types
286
289
  // Read raw voltage values to check for unimplemented phases
@@ -297,7 +300,12 @@ export class SunspecModbusClient {
297
300
  blockAddress: model.address,
298
301
  blockLength: model.length,
299
302
  // AC Current values - Offsets 2-5
300
- acCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 2, 1, 'uint16'), scaleFactors.A_SF),
303
+ acCurrent: this.applyScaleFactor(await (async () => {
304
+ const addr = baseAddr + 2;
305
+ const raw = await this.readRegisterValue(addr, 1, 'uint16');
306
+ console.log(`AC Current: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw})`);
307
+ return raw;
308
+ })(), scaleFactors.A_SF),
301
309
  phaseACurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 3, 1, 'uint16'), scaleFactors.A_SF),
302
310
  phaseBCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 4, 1, 'uint16'), scaleFactors.A_SF),
303
311
  phaseCCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 5, 1, 'uint16'), scaleFactors.A_SF),
@@ -310,16 +318,36 @@ export class SunspecModbusClient {
310
318
  voltageBN: this.applyScaleFactor(voltageBNRaw, scaleFactors.V_SF),
311
319
  voltageCN: this.applyScaleFactor(voltageCNRaw, scaleFactors.V_SF),
312
320
  // Power values - Offsets 14, 18, 20, 22
313
- acPower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 14, 1, 'int16'), scaleFactors.W_SF),
321
+ acPower: this.applyScaleFactor(await (async () => {
322
+ const addr = baseAddr + 14;
323
+ const raw = await this.readRegisterValue(addr, 1, 'int16');
324
+ console.log(`AC Power (W): address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw}), SF=${scaleFactors.W_SF}`);
325
+ return raw;
326
+ })(), scaleFactors.W_SF, 'int16'),
314
327
  apparentPower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 18, 1, 'uint16'), scaleFactors.VA_SF),
315
328
  reactivePower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 20, 1, 'int16'), scaleFactors.VAr_SF),
316
329
  powerFactor: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 22, 1, 'int16'), scaleFactors.PF_SF),
317
330
  // Frequency - Offset 16
318
331
  frequency: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 16, 1, 'uint16'), scaleFactors.Hz_SF),
319
332
  // DC values - Offsets 27, 28, 30
320
- dcCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 27, 1, 'uint16'), scaleFactors.DCA_SF),
321
- dcVoltage: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 28, 1, 'uint16'), scaleFactors.DCV_SF),
322
- dcPower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 30, 1, 'int16'), scaleFactors.DCW_SF),
333
+ dcCurrent: this.applyScaleFactor(await (async () => {
334
+ const addr = baseAddr + 27;
335
+ const raw = await this.readRegisterValue(addr, 1, 'uint16');
336
+ console.log(`DC Current: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw})`);
337
+ return raw;
338
+ })(), scaleFactors.DCA_SF),
339
+ dcVoltage: this.applyScaleFactor(await (async () => {
340
+ const addr = baseAddr + 28;
341
+ const raw = await this.readRegisterValue(addr, 1, 'uint16');
342
+ console.log(`DC Voltage: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw})`);
343
+ return raw;
344
+ })(), scaleFactors.DCV_SF),
345
+ dcPower: this.applyScaleFactor(await (async () => {
346
+ const addr = baseAddr + 30;
347
+ const raw = await this.readRegisterValue(addr, 1, 'int16');
348
+ console.log(`DC Power: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw}), SF=${scaleFactors.DCW_SF}`);
349
+ return raw;
350
+ })(), scaleFactors.DCW_SF, 'int16'),
323
351
  // Temperature values - Offsets 32, 34, 35, 36
324
352
  cabinetTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 32, 1, 'int16'), scaleFactors.Tmp_SF),
325
353
  heatSinkTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 34, 1, 'int16'), scaleFactors.Tmp_SF),
@@ -337,8 +365,20 @@ export class SunspecModbusClient {
337
365
  vendorEvents4: await this.readRegisterValue(baseAddr + 50, 2, 'uint32')
338
366
  };
339
367
  // Read AC Energy (32-bit accumulator) - Offset 24-25
340
- const acEnergy = await this.readRegisterValue(baseAddr + 24, 2, 'acc32');
341
- data.acEnergy = BigInt(acEnergy) * BigInt(Math.pow(10, scaleFactors.WH_SF));
368
+ const acEnergyAddr = baseAddr + 24;
369
+ const acEnergy = await this.readRegisterValue(acEnergyAddr, 2, 'acc32');
370
+ console.log(`AC Energy: address=${acEnergyAddr}, raw=0x${acEnergy.toString(16).toUpperCase()} (${acEnergy}), SF=${scaleFactors.WH_SF}`);
371
+ data.acEnergy = !this.isUnimplementedValue(acEnergy, 'uint32')
372
+ ? acEnergy * Math.pow(10, scaleFactors.WH_SF) // Regular number with scale factor
373
+ : undefined;
374
+ // Log final calculated values
375
+ console.log('Inverter Final Values:', {
376
+ acPower: data.acPower,
377
+ voltageAN: data.voltageAN,
378
+ voltageBN: data.voltageBN,
379
+ voltageCN: data.voltageCN,
380
+ acCurrent: data.acCurrent
381
+ });
342
382
  return data;
343
383
  }
344
384
  catch (error) {
@@ -354,15 +394,53 @@ export class SunspecModbusClient {
354
394
  // Implementation would be similar but simplified
355
395
  const baseAddr = model.address + 2;
356
396
  try {
357
- // Simplified implementation for single phase
397
+ console.log(`Reading Single-Phase Inverter Data from Model 101 at base address: ${baseAddr}`);
398
+ // Read scale factors for single phase model
399
+ const scaleFactors = {
400
+ A_SF: await this.readRegisterValue(baseAddr + 6, 1, 'int16'),
401
+ V_SF: await this.readRegisterValue(baseAddr + 13, 1, 'int16'),
402
+ W_SF: await this.readRegisterValue(baseAddr + 10, 1, 'int16'),
403
+ Hz_SF: await this.readRegisterValue(baseAddr + 12, 1, 'int16'),
404
+ DCA_SF: await this.readRegisterValue(baseAddr + 18, 1, 'int16'),
405
+ DCV_SF: await this.readRegisterValue(baseAddr + 19, 1, 'int16'),
406
+ DCW_SF: await this.readRegisterValue(baseAddr + 21, 1, 'int16')
407
+ };
408
+ console.log('Single-Phase Inverter Scale Factors:', JSON.stringify(scaleFactors, null, 2));
409
+ // Read raw values with logging
410
+ const acCurrentAddr = baseAddr + 2;
411
+ const acCurrentRaw = await this.readRegisterValue(acCurrentAddr, 1, 'uint16');
412
+ console.log(`AC Current: address=${acCurrentAddr}, raw=0x${acCurrentRaw.toString(16).toUpperCase()} (${acCurrentRaw})`);
413
+ const voltageAddr = baseAddr + 7;
414
+ const voltageRaw = await this.readRegisterValue(voltageAddr, 1, 'uint16');
415
+ console.log(`AC Voltage: address=${voltageAddr}, raw=0x${voltageRaw.toString(16).toUpperCase()} (${voltageRaw})`);
416
+ const acPowerAddr = baseAddr + 9;
417
+ const acPowerRaw = await this.readRegisterValue(acPowerAddr, 1, 'int16');
418
+ console.log(`AC Power: address=${acPowerAddr}, raw=0x${acPowerRaw.toString(16).toUpperCase()} (${acPowerRaw}), SF=${scaleFactors.W_SF}`);
419
+ const freqAddr = baseAddr + 11;
420
+ const freqRaw = await this.readRegisterValue(freqAddr, 1, 'uint16');
421
+ console.log(`Frequency: address=${freqAddr}, raw=0x${freqRaw.toString(16).toUpperCase()} (${freqRaw})`);
422
+ const dcCurrentAddr = baseAddr + 14;
423
+ const dcCurrentRaw = await this.readRegisterValue(dcCurrentAddr, 1, 'uint16');
424
+ console.log(`DC Current: address=${dcCurrentAddr}, raw=0x${dcCurrentRaw.toString(16).toUpperCase()} (${dcCurrentRaw})`);
425
+ const dcVoltageAddr = baseAddr + 15;
426
+ const dcVoltageRaw = await this.readRegisterValue(dcVoltageAddr, 1, 'uint16');
427
+ console.log(`DC Voltage: address=${dcVoltageAddr}, raw=0x${dcVoltageRaw.toString(16).toUpperCase()} (${dcVoltageRaw})`);
428
+ const dcPowerAddr = baseAddr + 20;
429
+ const dcPowerRaw = await this.readRegisterValue(dcPowerAddr, 1, 'int16');
430
+ console.log(`DC Power: address=${dcPowerAddr}, raw=0x${dcPowerRaw.toString(16).toUpperCase()} (${dcPowerRaw}), SF=${scaleFactors.DCW_SF}`);
431
+ const stateAddr = baseAddr + 24;
432
+ const stateRaw = await this.readRegisterValue(stateAddr, 1, 'uint16');
433
+ console.log(`Operating State: address=${stateAddr}, raw=0x${stateRaw.toString(16).toUpperCase()} (${stateRaw})`);
358
434
  return {
359
435
  blockNumber: 101,
360
- voltageAN: await this.readRegisterWithScaleFactor(baseAddr + 7, baseAddr + 13), // PhVphA with V_SF
361
- acCurrent: await this.readRegisterWithScaleFactor(baseAddr + 2, baseAddr + 6),
362
- acPower: await this.readRegisterWithScaleFactor(baseAddr + 9, baseAddr + 10),
363
- frequency: await this.readRegisterWithScaleFactor(baseAddr + 11, baseAddr + 12),
364
- dcPower: await this.readRegisterWithScaleFactor(baseAddr + 20, baseAddr + 21),
365
- operatingState: await this.readRegisterValue(baseAddr + 24, 1)
436
+ voltageAN: this.applyScaleFactor(voltageRaw, scaleFactors.V_SF),
437
+ acCurrent: this.applyScaleFactor(acCurrentRaw, scaleFactors.A_SF),
438
+ acPower: this.applyScaleFactor(acPowerRaw, scaleFactors.W_SF, 'int16'),
439
+ frequency: this.applyScaleFactor(freqRaw, scaleFactors.Hz_SF),
440
+ dcCurrent: this.applyScaleFactor(dcCurrentRaw, scaleFactors.DCA_SF),
441
+ dcVoltage: this.applyScaleFactor(dcVoltageRaw, scaleFactors.DCV_SF),
442
+ dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'int16'),
443
+ operatingState: stateRaw
366
444
  };
367
445
  }
368
446
  catch (error) {
@@ -400,11 +478,6 @@ export class SunspecModbusClient {
400
478
  if (this.isUnimplementedValue(value, dataType)) {
401
479
  return undefined;
402
480
  }
403
- // Validate scale factor is within reasonable range (-10 to +10)
404
- if (Math.abs(scaleFactor) > 10) {
405
- console.warn(`Scale factor ${scaleFactor} is outside reasonable range, clamping to ±10`);
406
- scaleFactor = Math.max(-10, Math.min(10, scaleFactor));
407
- }
408
481
  return value * Math.pow(10, scaleFactor);
409
482
  }
410
483
  /**
@@ -471,7 +544,7 @@ export class SunspecModbusClient {
471
544
  // DC Energy - Offset 15-16 (32-bit accumulator)
472
545
  // Only calculate if value is not unimplemented
473
546
  dcEnergy: !this.isUnimplementedValue(dcEnergyRaw, 'uint32')
474
- ? BigInt(dcEnergyRaw) * BigInt(Math.pow(10, scaleFactors.DCWH_SF))
547
+ ? dcEnergyRaw * Math.pow(10, scaleFactors.DCWH_SF) // Regular number with scale factor
475
548
  : undefined,
476
549
  dcEnergySF: scaleFactors.DCWH_SF,
477
550
  // Timestamp - Offset 18-19 (32-bit)
@@ -533,13 +606,58 @@ export class SunspecModbusClient {
533
606
  return null;
534
607
  }
535
608
  const baseAddr = model.address + 2;
609
+ console.log(`Reading Meter Data from Model ${model.id} at base address: ${baseAddr}`);
536
610
  try {
537
- // This is a simplified implementation
538
- // Actual register offsets depend on specific meter model
611
+ // Model 201 (single phase meter) - Correct register offsets from Sunspec
612
+ // All offsets are from data start (after ID and Length)
613
+ console.log(`Meter is Model 201 (Single Phase Meter)`);
614
+ // Model 201 register offsets according to Sunspec specification:
615
+ const powerOffset = 18; // W - Total Real Power (int16) at offset 18
616
+ const powerSFOffset = 21; // W_SF - Power scale factor at offset 21
617
+ const freqOffset = 32; // Hz - Frequency (uint16) at offset 32
618
+ const freqSFOffset = 35; // Hz_SF - Frequency scale factor at offset 35
619
+ const exportOffset = 38; // TotWhExp - Total Wh Exported (acc32) at offset 38-39
620
+ const importOffset = 46; // TotWhImp - Total Wh Imported (acc32) at offset 46-47
621
+ const energySFOffset = 4; // TotWh_SF - Total Energy scale factor at offset 4
622
+ // Read scale factors
623
+ const powerSF = await this.readRegisterValue(baseAddr + powerSFOffset, 1, 'int16');
624
+ const freqSF = await this.readRegisterValue(baseAddr + freqSFOffset, 1, 'int16');
625
+ const energySF = await this.readRegisterValue(baseAddr + energySFOffset, 1, 'int16');
626
+ console.log(`Meter Scale Factors: Power_SF=${powerSF}, Freq_SF=${freqSF}, Energy_SF=${energySF}`);
627
+ // Read raw values
628
+ const powerAddr = baseAddr + powerOffset;
629
+ const powerRaw = await this.readRegisterValue(powerAddr, 1, 'int16');
630
+ console.log(`Meter Total Power: address=${powerAddr}, raw=0x${powerRaw.toString(16).toUpperCase()} (${powerRaw}), SF=${powerSF}`);
631
+ const freqAddr = baseAddr + freqOffset;
632
+ const freqRaw = await this.readRegisterValue(freqAddr, 1, 'uint16');
633
+ console.log(`Meter Frequency: address=${freqAddr}, raw=0x${freqRaw.toString(16).toUpperCase()} (${freqRaw}), SF=${freqSF}`);
634
+ const exportAddr = baseAddr + exportOffset;
635
+ const exportRaw = await this.readRegisterValue(exportAddr, 2, 'acc32');
636
+ console.log(`Meter Export Energy: address=${exportAddr}, raw=0x${exportRaw.toString(16).toUpperCase()} (${exportRaw}), SF=${energySF}`);
637
+ const importAddr = baseAddr + importOffset;
638
+ const importRaw = await this.readRegisterValue(importAddr, 2, 'acc32');
639
+ console.log(`Meter Import Energy: address=${importAddr}, raw=0x${importRaw.toString(16).toUpperCase()} (${importRaw}), SF=${energySF}`);
640
+ // Calculate final values with scale factors
641
+ const totalPower = this.applyScaleFactor(powerRaw, powerSF, 'int16');
642
+ const frequency = this.applyScaleFactor(freqRaw, freqSF);
643
+ const exportedEnergy = !this.isUnimplementedValue(exportRaw, 'uint32')
644
+ ? exportRaw * Math.pow(10, energySF) // Regular number, not BigInt
645
+ : undefined;
646
+ const importedEnergy = !this.isUnimplementedValue(importRaw, 'uint32')
647
+ ? importRaw * Math.pow(10, energySF) // Regular number, not BigInt
648
+ : undefined;
649
+ console.log('Meter Final Values:', {
650
+ totalPower,
651
+ frequency,
652
+ exportedEnergy,
653
+ importedEnergy
654
+ });
539
655
  return {
540
656
  blockNumber: model.id,
541
- totalPower: await this.readRegisterWithScaleFactor(baseAddr + 10, baseAddr + 11),
542
- frequency: await this.readRegisterWithScaleFactor(baseAddr + 20, baseAddr + 21)
657
+ totalPower,
658
+ frequency,
659
+ exportedEnergy,
660
+ importedEnergy
543
661
  };
544
662
  }
545
663
  catch (error) {
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.6";
8
+ export declare const SDK_VERSION = "0.0.8";
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.6';
8
+ export const SDK_VERSION = '0.0.8';
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.6",
3
+ "version": "0.0.8",
4
4
  "description": "enyo Energy Sunspec SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",