@enyo-energy/sunspec-sdk 0.0.6 → 0.0.7

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
  };
@@ -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,21 @@ 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');
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}`);
344
374
  data.acEnergy = BigInt(acEnergy) * BigInt(Math.pow(10, scaleFactors.WH_SF));
375
+ // Log final calculated values
376
+ console.log('Inverter Final Values:', {
377
+ acPower: data.acPower,
378
+ dcPower: data.dcPower,
379
+ voltageAN: data.voltageAN,
380
+ voltageBN: data.voltageBN,
381
+ voltageCN: data.voltageCN,
382
+ dcVoltage: data.dcVoltage,
383
+ dcCurrent: data.dcCurrent,
384
+ acCurrent: data.acCurrent
385
+ });
345
386
  return data;
346
387
  }
347
388
  catch (error) {
@@ -357,15 +398,53 @@ class SunspecModbusClient {
357
398
  // Implementation would be similar but simplified
358
399
  const baseAddr = model.address + 2;
359
400
  try {
360
- // Simplified implementation for single phase
401
+ console.log(`Reading Single-Phase Inverter Data from Model 101 at base address: ${baseAddr}`);
402
+ // Read scale factors for single phase model
403
+ const scaleFactors = {
404
+ A_SF: await this.readRegisterValue(baseAddr + 6, 1, 'int16'),
405
+ V_SF: await this.readRegisterValue(baseAddr + 13, 1, 'int16'),
406
+ W_SF: await this.readRegisterValue(baseAddr + 10, 1, 'int16'),
407
+ Hz_SF: await this.readRegisterValue(baseAddr + 12, 1, 'int16'),
408
+ DCA_SF: await this.readRegisterValue(baseAddr + 18, 1, 'int16'),
409
+ DCV_SF: await this.readRegisterValue(baseAddr + 19, 1, 'int16'),
410
+ DCW_SF: await this.readRegisterValue(baseAddr + 21, 1, 'int16')
411
+ };
412
+ console.log('Single-Phase Inverter Scale Factors:', JSON.stringify(scaleFactors, null, 2));
413
+ // Read raw values with logging
414
+ const acCurrentAddr = baseAddr + 2;
415
+ const acCurrentRaw = await this.readRegisterValue(acCurrentAddr, 1, 'uint16');
416
+ console.log(`AC Current: address=${acCurrentAddr}, raw=0x${acCurrentRaw.toString(16).toUpperCase()} (${acCurrentRaw})`);
417
+ const voltageAddr = baseAddr + 7;
418
+ const voltageRaw = await this.readRegisterValue(voltageAddr, 1, 'uint16');
419
+ console.log(`AC Voltage: address=${voltageAddr}, raw=0x${voltageRaw.toString(16).toUpperCase()} (${voltageRaw})`);
420
+ const acPowerAddr = baseAddr + 9;
421
+ const acPowerRaw = await this.readRegisterValue(acPowerAddr, 1, 'int16');
422
+ console.log(`AC Power: address=${acPowerAddr}, raw=0x${acPowerRaw.toString(16).toUpperCase()} (${acPowerRaw}), SF=${scaleFactors.W_SF}`);
423
+ const freqAddr = baseAddr + 11;
424
+ const freqRaw = await this.readRegisterValue(freqAddr, 1, 'uint16');
425
+ console.log(`Frequency: address=${freqAddr}, raw=0x${freqRaw.toString(16).toUpperCase()} (${freqRaw})`);
426
+ const dcCurrentAddr = baseAddr + 14;
427
+ const dcCurrentRaw = await this.readRegisterValue(dcCurrentAddr, 1, 'uint16');
428
+ console.log(`DC Current: address=${dcCurrentAddr}, raw=0x${dcCurrentRaw.toString(16).toUpperCase()} (${dcCurrentRaw})`);
429
+ const dcVoltageAddr = baseAddr + 15;
430
+ const dcVoltageRaw = await this.readRegisterValue(dcVoltageAddr, 1, 'uint16');
431
+ console.log(`DC Voltage: address=${dcVoltageAddr}, raw=0x${dcVoltageRaw.toString(16).toUpperCase()} (${dcVoltageRaw})`);
432
+ const dcPowerAddr = baseAddr + 20;
433
+ const dcPowerRaw = await this.readRegisterValue(dcPowerAddr, 1, 'int16');
434
+ console.log(`DC Power: address=${dcPowerAddr}, raw=0x${dcPowerRaw.toString(16).toUpperCase()} (${dcPowerRaw}), SF=${scaleFactors.DCW_SF}`);
435
+ const stateAddr = baseAddr + 24;
436
+ const stateRaw = await this.readRegisterValue(stateAddr, 1, 'uint16');
437
+ console.log(`Operating State: address=${stateAddr}, raw=0x${stateRaw.toString(16).toUpperCase()} (${stateRaw})`);
361
438
  return {
362
439
  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)
440
+ voltageAN: this.applyScaleFactor(voltageRaw, scaleFactors.V_SF),
441
+ acCurrent: this.applyScaleFactor(acCurrentRaw, scaleFactors.A_SF),
442
+ acPower: this.applyScaleFactor(acPowerRaw, scaleFactors.W_SF, 'int16'),
443
+ frequency: this.applyScaleFactor(freqRaw, scaleFactors.Hz_SF),
444
+ dcCurrent: this.applyScaleFactor(dcCurrentRaw, scaleFactors.DCA_SF),
445
+ dcVoltage: this.applyScaleFactor(dcVoltageRaw, scaleFactors.DCV_SF),
446
+ dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'int16'),
447
+ operatingState: stateRaw
369
448
  };
370
449
  }
371
450
  catch (error) {
@@ -403,11 +482,6 @@ class SunspecModbusClient {
403
482
  if (this.isUnimplementedValue(value, dataType)) {
404
483
  return undefined;
405
484
  }
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
485
  return value * Math.pow(10, scaleFactor);
412
486
  }
413
487
  /**
@@ -536,13 +610,47 @@ class SunspecModbusClient {
536
610
  return null;
537
611
  }
538
612
  const baseAddr = model.address + 2;
613
+ console.log(`Reading Meter Data from Model ${model.id} at base address: ${baseAddr}`);
539
614
  try {
540
- // This is a simplified implementation
541
- // Actual register offsets depend on specific meter model
615
+ // Model 201 (single phase) and 203 (3-phase) have different offsets
616
+ // Model 201: Power at offset 12, Frequency at offset 18
617
+ // Model 203: Power at offset 14, Frequency at offset 24
618
+ const isPowerMeter201 = model.id === 201;
619
+ const powerOffset = isPowerMeter201 ? 12 : 14; // Total Real Power offset
620
+ const powerSFOffset = isPowerMeter201 ? 15 : 17; // Power scale factor offset
621
+ const freqOffset = isPowerMeter201 ? 18 : 24; // Frequency offset
622
+ const freqSFOffset = isPowerMeter201 ? 21 : 27; // Frequency scale factor offset
623
+ const exportOffset = isPowerMeter201 ? 32 : 38; // Total Wh Exported offset
624
+ const importOffset = isPowerMeter201 ? 40 : 46; // Total Wh Imported offset
625
+ const energySFOffset = 4; // Energy scale factor is typically at offset 4
626
+ // Read scale factors
627
+ const powerSF = await this.readRegisterValue(baseAddr + powerSFOffset, 1, 'int16');
628
+ const freqSF = await this.readRegisterValue(baseAddr + freqSFOffset, 1, 'int16');
629
+ const energySF = await this.readRegisterValue(baseAddr + energySFOffset, 1, 'int16');
630
+ console.log(`Meter Scale Factors: Power_SF=${powerSF}, Freq_SF=${freqSF}, Energy_SF=${energySF}`);
631
+ // Read raw values
632
+ const powerAddr = baseAddr + powerOffset;
633
+ const powerRaw = await this.readRegisterValue(powerAddr, 1, 'int16');
634
+ console.log(`Meter Total Power: address=${powerAddr}, raw=0x${powerRaw.toString(16).toUpperCase()} (${powerRaw}), SF=${powerSF}`);
635
+ const freqAddr = baseAddr + freqOffset;
636
+ const freqRaw = await this.readRegisterValue(freqAddr, 1, 'uint16');
637
+ console.log(`Meter Frequency: address=${freqAddr}, raw=0x${freqRaw.toString(16).toUpperCase()} (${freqRaw}), SF=${freqSF}`);
638
+ const exportAddr = baseAddr + exportOffset;
639
+ const exportRaw = await this.readRegisterValue(exportAddr, 2, 'acc32');
640
+ console.log(`Meter Export Energy: address=${exportAddr}, raw=0x${exportRaw.toString(16).toUpperCase()} (${exportRaw}), SF=${energySF}`);
641
+ const importAddr = baseAddr + importOffset;
642
+ const importRaw = await this.readRegisterValue(importAddr, 2, 'acc32');
643
+ console.log(`Meter Import Energy: address=${importAddr}, raw=0x${importRaw.toString(16).toUpperCase()} (${importRaw}), SF=${energySF}`);
542
644
  return {
543
645
  blockNumber: model.id,
544
- totalPower: await this.readRegisterWithScaleFactor(baseAddr + 10, baseAddr + 11),
545
- frequency: await this.readRegisterWithScaleFactor(baseAddr + 20, baseAddr + 21)
646
+ totalPower: this.applyScaleFactor(powerRaw, powerSF, 'int16'),
647
+ frequency: this.applyScaleFactor(freqRaw, freqSF),
648
+ exportedEnergy: !this.isUnimplementedValue(exportRaw, 'uint32')
649
+ ? BigInt(exportRaw) * BigInt(Math.pow(10, energySF))
650
+ : undefined,
651
+ importedEnergy: !this.isUnimplementedValue(importRaw, 'uint32')
652
+ ? BigInt(importRaw) * BigInt(Math.pow(10, energySF))
653
+ : undefined
546
654
  };
547
655
  }
548
656
  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.7';
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.7";
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
  };
@@ -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,21 @@ 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');
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}`);
341
371
  data.acEnergy = BigInt(acEnergy) * BigInt(Math.pow(10, scaleFactors.WH_SF));
372
+ // Log final calculated values
373
+ console.log('Inverter Final Values:', {
374
+ acPower: data.acPower,
375
+ dcPower: data.dcPower,
376
+ voltageAN: data.voltageAN,
377
+ voltageBN: data.voltageBN,
378
+ voltageCN: data.voltageCN,
379
+ dcVoltage: data.dcVoltage,
380
+ dcCurrent: data.dcCurrent,
381
+ acCurrent: data.acCurrent
382
+ });
342
383
  return data;
343
384
  }
344
385
  catch (error) {
@@ -354,15 +395,53 @@ export class SunspecModbusClient {
354
395
  // Implementation would be similar but simplified
355
396
  const baseAddr = model.address + 2;
356
397
  try {
357
- // Simplified implementation for single phase
398
+ console.log(`Reading Single-Phase Inverter Data from Model 101 at base address: ${baseAddr}`);
399
+ // Read scale factors for single phase model
400
+ const scaleFactors = {
401
+ A_SF: await this.readRegisterValue(baseAddr + 6, 1, 'int16'),
402
+ V_SF: await this.readRegisterValue(baseAddr + 13, 1, 'int16'),
403
+ W_SF: await this.readRegisterValue(baseAddr + 10, 1, 'int16'),
404
+ Hz_SF: await this.readRegisterValue(baseAddr + 12, 1, 'int16'),
405
+ DCA_SF: await this.readRegisterValue(baseAddr + 18, 1, 'int16'),
406
+ DCV_SF: await this.readRegisterValue(baseAddr + 19, 1, 'int16'),
407
+ DCW_SF: await this.readRegisterValue(baseAddr + 21, 1, 'int16')
408
+ };
409
+ console.log('Single-Phase Inverter Scale Factors:', JSON.stringify(scaleFactors, null, 2));
410
+ // Read raw values with logging
411
+ const acCurrentAddr = baseAddr + 2;
412
+ const acCurrentRaw = await this.readRegisterValue(acCurrentAddr, 1, 'uint16');
413
+ console.log(`AC Current: address=${acCurrentAddr}, raw=0x${acCurrentRaw.toString(16).toUpperCase()} (${acCurrentRaw})`);
414
+ const voltageAddr = baseAddr + 7;
415
+ const voltageRaw = await this.readRegisterValue(voltageAddr, 1, 'uint16');
416
+ console.log(`AC Voltage: address=${voltageAddr}, raw=0x${voltageRaw.toString(16).toUpperCase()} (${voltageRaw})`);
417
+ const acPowerAddr = baseAddr + 9;
418
+ const acPowerRaw = await this.readRegisterValue(acPowerAddr, 1, 'int16');
419
+ console.log(`AC Power: address=${acPowerAddr}, raw=0x${acPowerRaw.toString(16).toUpperCase()} (${acPowerRaw}), SF=${scaleFactors.W_SF}`);
420
+ const freqAddr = baseAddr + 11;
421
+ const freqRaw = await this.readRegisterValue(freqAddr, 1, 'uint16');
422
+ console.log(`Frequency: address=${freqAddr}, raw=0x${freqRaw.toString(16).toUpperCase()} (${freqRaw})`);
423
+ const dcCurrentAddr = baseAddr + 14;
424
+ const dcCurrentRaw = await this.readRegisterValue(dcCurrentAddr, 1, 'uint16');
425
+ console.log(`DC Current: address=${dcCurrentAddr}, raw=0x${dcCurrentRaw.toString(16).toUpperCase()} (${dcCurrentRaw})`);
426
+ const dcVoltageAddr = baseAddr + 15;
427
+ const dcVoltageRaw = await this.readRegisterValue(dcVoltageAddr, 1, 'uint16');
428
+ console.log(`DC Voltage: address=${dcVoltageAddr}, raw=0x${dcVoltageRaw.toString(16).toUpperCase()} (${dcVoltageRaw})`);
429
+ const dcPowerAddr = baseAddr + 20;
430
+ const dcPowerRaw = await this.readRegisterValue(dcPowerAddr, 1, 'int16');
431
+ console.log(`DC Power: address=${dcPowerAddr}, raw=0x${dcPowerRaw.toString(16).toUpperCase()} (${dcPowerRaw}), SF=${scaleFactors.DCW_SF}`);
432
+ const stateAddr = baseAddr + 24;
433
+ const stateRaw = await this.readRegisterValue(stateAddr, 1, 'uint16');
434
+ console.log(`Operating State: address=${stateAddr}, raw=0x${stateRaw.toString(16).toUpperCase()} (${stateRaw})`);
358
435
  return {
359
436
  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)
437
+ voltageAN: this.applyScaleFactor(voltageRaw, scaleFactors.V_SF),
438
+ acCurrent: this.applyScaleFactor(acCurrentRaw, scaleFactors.A_SF),
439
+ acPower: this.applyScaleFactor(acPowerRaw, scaleFactors.W_SF, 'int16'),
440
+ frequency: this.applyScaleFactor(freqRaw, scaleFactors.Hz_SF),
441
+ dcCurrent: this.applyScaleFactor(dcCurrentRaw, scaleFactors.DCA_SF),
442
+ dcVoltage: this.applyScaleFactor(dcVoltageRaw, scaleFactors.DCV_SF),
443
+ dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'int16'),
444
+ operatingState: stateRaw
366
445
  };
367
446
  }
368
447
  catch (error) {
@@ -400,11 +479,6 @@ export class SunspecModbusClient {
400
479
  if (this.isUnimplementedValue(value, dataType)) {
401
480
  return undefined;
402
481
  }
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
482
  return value * Math.pow(10, scaleFactor);
409
483
  }
410
484
  /**
@@ -533,13 +607,47 @@ export class SunspecModbusClient {
533
607
  return null;
534
608
  }
535
609
  const baseAddr = model.address + 2;
610
+ console.log(`Reading Meter Data from Model ${model.id} at base address: ${baseAddr}`);
536
611
  try {
537
- // This is a simplified implementation
538
- // Actual register offsets depend on specific meter model
612
+ // Model 201 (single phase) and 203 (3-phase) have different offsets
613
+ // Model 201: Power at offset 12, Frequency at offset 18
614
+ // Model 203: Power at offset 14, Frequency at offset 24
615
+ const isPowerMeter201 = model.id === 201;
616
+ const powerOffset = isPowerMeter201 ? 12 : 14; // Total Real Power offset
617
+ const powerSFOffset = isPowerMeter201 ? 15 : 17; // Power scale factor offset
618
+ const freqOffset = isPowerMeter201 ? 18 : 24; // Frequency offset
619
+ const freqSFOffset = isPowerMeter201 ? 21 : 27; // Frequency scale factor offset
620
+ const exportOffset = isPowerMeter201 ? 32 : 38; // Total Wh Exported offset
621
+ const importOffset = isPowerMeter201 ? 40 : 46; // Total Wh Imported offset
622
+ const energySFOffset = 4; // Energy scale factor is typically at offset 4
623
+ // Read scale factors
624
+ const powerSF = await this.readRegisterValue(baseAddr + powerSFOffset, 1, 'int16');
625
+ const freqSF = await this.readRegisterValue(baseAddr + freqSFOffset, 1, 'int16');
626
+ const energySF = await this.readRegisterValue(baseAddr + energySFOffset, 1, 'int16');
627
+ console.log(`Meter Scale Factors: Power_SF=${powerSF}, Freq_SF=${freqSF}, Energy_SF=${energySF}`);
628
+ // Read raw values
629
+ const powerAddr = baseAddr + powerOffset;
630
+ const powerRaw = await this.readRegisterValue(powerAddr, 1, 'int16');
631
+ console.log(`Meter Total Power: address=${powerAddr}, raw=0x${powerRaw.toString(16).toUpperCase()} (${powerRaw}), SF=${powerSF}`);
632
+ const freqAddr = baseAddr + freqOffset;
633
+ const freqRaw = await this.readRegisterValue(freqAddr, 1, 'uint16');
634
+ console.log(`Meter Frequency: address=${freqAddr}, raw=0x${freqRaw.toString(16).toUpperCase()} (${freqRaw}), SF=${freqSF}`);
635
+ const exportAddr = baseAddr + exportOffset;
636
+ const exportRaw = await this.readRegisterValue(exportAddr, 2, 'acc32');
637
+ console.log(`Meter Export Energy: address=${exportAddr}, raw=0x${exportRaw.toString(16).toUpperCase()} (${exportRaw}), SF=${energySF}`);
638
+ const importAddr = baseAddr + importOffset;
639
+ const importRaw = await this.readRegisterValue(importAddr, 2, 'acc32');
640
+ console.log(`Meter Import Energy: address=${importAddr}, raw=0x${importRaw.toString(16).toUpperCase()} (${importRaw}), SF=${energySF}`);
539
641
  return {
540
642
  blockNumber: model.id,
541
- totalPower: await this.readRegisterWithScaleFactor(baseAddr + 10, baseAddr + 11),
542
- frequency: await this.readRegisterWithScaleFactor(baseAddr + 20, baseAddr + 21)
643
+ totalPower: this.applyScaleFactor(powerRaw, powerSF, 'int16'),
644
+ frequency: this.applyScaleFactor(freqRaw, freqSF),
645
+ exportedEnergy: !this.isUnimplementedValue(exportRaw, 'uint32')
646
+ ? BigInt(exportRaw) * BigInt(Math.pow(10, energySF))
647
+ : undefined,
648
+ importedEnergy: !this.isUnimplementedValue(importRaw, 'uint32')
649
+ ? BigInt(importRaw) * BigInt(Math.pow(10, energySF))
650
+ : undefined
543
651
  };
544
652
  }
545
653
  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.7";
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.7';
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.7",
4
4
  "description": "enyo Energy Sunspec SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",