@enyo-energy/sunspec-sdk 0.0.30 → 0.0.32

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.
@@ -230,6 +230,22 @@ class SunspecModbusClient {
230
230
  }
231
231
  // If custom base address provided, try it first (1-based, then 0-based variant)
232
232
  if (customBaseAddress !== undefined) {
233
+ console.log(`Detect models for custom base address '${customBaseAddress}' ...`);
234
+ // Try 0-based at custom address
235
+ try {
236
+ const sunspecId = await this.modbusClient.readRegisterStringValue(customBaseAddress, 2);
237
+ if (sunspecId.includes('SunS')) {
238
+ console.log(`Detected 0-based addressing mode (base address: ${customBaseAddress})`);
239
+ return {
240
+ baseAddress: customBaseAddress,
241
+ isZeroBased: true,
242
+ nextAddress: customBaseAddress + 2
243
+ };
244
+ }
245
+ }
246
+ catch (error) {
247
+ console.debug(`Could not read SunS at ${customBaseAddress}:`, error);
248
+ }
233
249
  // Try 1-based at custom address (customBaseAddress + 1)
234
250
  try {
235
251
  const sunspecId = await this.modbusClient.readRegisterStringValue(customBaseAddress + 1, 2);
@@ -245,54 +261,41 @@ class SunspecModbusClient {
245
261
  catch (error) {
246
262
  console.debug(`Could not read SunS at ${customBaseAddress + 1}:`, error);
247
263
  }
248
- // Try 0-based at custom address
264
+ }
265
+ else {
266
+ // Try 1-based addressing first (most common)
249
267
  try {
250
- const sunspecId = await this.modbusClient.readRegisterStringValue(customBaseAddress, 2);
268
+ const sunspecId = await this.modbusClient.readRegisterStringValue(40001, 2);
251
269
  if (sunspecId.includes('SunS')) {
252
- console.log(`Detected 0-based addressing mode (base address: ${customBaseAddress})`);
270
+ console.log('Detected 1-based addressing mode (base address: 40001)');
253
271
  return {
254
- baseAddress: customBaseAddress,
255
- isZeroBased: true,
256
- nextAddress: customBaseAddress + 2
272
+ baseAddress: 40001,
273
+ isZeroBased: false,
274
+ nextAddress: 40003
257
275
  };
258
276
  }
259
277
  }
260
278
  catch (error) {
261
- console.debug(`Could not read SunS at ${customBaseAddress}:`, error);
279
+ console.debug('Could not read SunS at 40001:', error);
262
280
  }
263
- }
264
- // Try 1-based addressing first (most common)
265
- try {
266
- const sunspecId = await this.modbusClient.readRegisterStringValue(40001, 2);
267
- if (sunspecId.includes('SunS')) {
268
- console.log('Detected 1-based addressing mode (base address: 40001)');
269
- return {
270
- baseAddress: 40001,
271
- isZeroBased: false,
272
- nextAddress: 40003
273
- };
281
+ // Try 0-based addressing
282
+ try {
283
+ const sunspecId = await this.modbusClient.readRegisterStringValue(40000, 2);
284
+ if (sunspecId.includes('SunS')) {
285
+ console.log('Detected 0-based addressing mode (base address: 40000)');
286
+ return {
287
+ baseAddress: 40000,
288
+ isZeroBased: true,
289
+ nextAddress: 40002
290
+ };
291
+ }
274
292
  }
275
- }
276
- catch (error) {
277
- console.debug('Could not read SunS at 40001:', error);
278
- }
279
- // Try 0-based addressing
280
- try {
281
- const sunspecId = await this.modbusClient.readRegisterStringValue(40000, 2);
282
- if (sunspecId.includes('SunS')) {
283
- console.log('Detected 0-based addressing mode (base address: 40000)');
284
- return {
285
- baseAddress: 40000,
286
- isZeroBased: true,
287
- nextAddress: 40002
288
- };
293
+ catch (error) {
294
+ console.debug('Could not read SunS at 40000:', error);
289
295
  }
290
296
  }
291
- catch (error) {
292
- console.debug('Could not read SunS at 40000:', error);
293
- }
294
297
  const addressesChecked = customBaseAddress !== undefined
295
- ? `${customBaseAddress}, ${customBaseAddress + 1}, 40000, or 40001`
298
+ ? `${customBaseAddress}, ${customBaseAddress + 1}`
296
299
  : '40000 or 40001';
297
300
  throw new Error(`Device is not SunSpec compliant - "SunS" identifier not found at addresses ${addressesChecked}`);
298
301
  }
@@ -522,64 +525,44 @@ class SunspecModbusClient {
522
525
  const voltageANRaw = await this.readRegisterValue(baseAddr + 10, 1, 'uint16');
523
526
  const voltageBNRaw = await this.readRegisterValue(baseAddr + 11, 1, 'uint16');
524
527
  const voltageCNRaw = await this.readRegisterValue(baseAddr + 12, 1, 'uint16');
528
+ // Read raw values for fields that need IIFEs removed
529
+ const acCurrentRaw = await this.readRegisterValue(baseAddr + 2, 1, 'uint16');
530
+ const acPowerRaw = await this.readRegisterValue(baseAddr + 14, 1, 'int16');
531
+ const dcCurrentRaw = await this.readRegisterValue(baseAddr + 27, 1, 'uint16');
532
+ const dcVoltageRaw = await this.readRegisterValue(baseAddr + 28, 1, 'uint16');
533
+ const dcPowerRaw = await this.readRegisterValue(baseAddr + 30, 1, 'int16');
525
534
  const data = {
526
535
  blockNumber: 103,
527
536
  blockAddress: model.address,
528
537
  blockLength: model.length,
529
538
  // AC Current values - Offsets 2-5
530
- acCurrent: this.applyScaleFactor(await (async () => {
531
- const addr = baseAddr + 2;
532
- const raw = await this.readRegisterValue(addr, 1, 'uint16');
533
- console.log(`AC Current: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw})`);
534
- return raw;
535
- })(), scaleFactors.A_SF, 'uint16', 'AC Current'),
536
- phaseACurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 3, 1, 'uint16'), scaleFactors.A_SF, 'uint16', 'Phase A Current'),
537
- phaseBCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 4, 1, 'uint16'), scaleFactors.A_SF, 'uint16', 'Phase B Current'),
538
- phaseCCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 5, 1, 'uint16'), scaleFactors.A_SF, 'uint16', 'Phase C Current'),
539
+ acCurrent: this.applyScaleFactor(acCurrentRaw, scaleFactors.A_SF, 'uint16', 'AC Current', 2, 103),
540
+ phaseACurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 3, 1, 'uint16'), scaleFactors.A_SF, 'uint16', 'Phase A Current', 3, 103),
541
+ phaseBCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 4, 1, 'uint16'), scaleFactors.A_SF, 'uint16', 'Phase B Current', 4, 103),
542
+ phaseCCurrent: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 5, 1, 'uint16'), scaleFactors.A_SF, 'uint16', 'Phase C Current', 5, 103),
539
543
  // Voltage values - Offsets 7-12
540
- voltageAB: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 7, 1, 'uint16'), scaleFactors.V_SF, 'uint16', 'Voltage AB'),
541
- voltageBC: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 8, 1, 'uint16'), scaleFactors.V_SF, 'uint16', 'Voltage BC'),
542
- voltageCA: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 9, 1, 'uint16'), scaleFactors.V_SF, 'uint16', 'Voltage CA'),
543
- // Apply scale factor with unimplemented value checking
544
- voltageAN: this.applyScaleFactor(voltageANRaw, scaleFactors.V_SF, 'uint16', 'Voltage AN'),
545
- voltageBN: this.applyScaleFactor(voltageBNRaw, scaleFactors.V_SF, 'uint16', 'Voltage BN'),
546
- voltageCN: this.applyScaleFactor(voltageCNRaw, scaleFactors.V_SF, 'uint16', 'Voltage CN'),
544
+ voltageAB: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 7, 1, 'uint16'), scaleFactors.V_SF, 'uint16', 'Voltage AB', 7, 103),
545
+ voltageBC: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 8, 1, 'uint16'), scaleFactors.V_SF, 'uint16', 'Voltage BC', 8, 103),
546
+ voltageCA: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 9, 1, 'uint16'), scaleFactors.V_SF, 'uint16', 'Voltage CA', 9, 103),
547
+ voltageAN: this.applyScaleFactor(voltageANRaw, scaleFactors.V_SF, 'uint16', 'Voltage AN', 10, 103),
548
+ voltageBN: this.applyScaleFactor(voltageBNRaw, scaleFactors.V_SF, 'uint16', 'Voltage BN', 11, 103),
549
+ voltageCN: this.applyScaleFactor(voltageCNRaw, scaleFactors.V_SF, 'uint16', 'Voltage CN', 12, 103),
547
550
  // Power values - Offsets 14, 18, 20, 22
548
- acPower: this.applyScaleFactor(await (async () => {
549
- const addr = baseAddr + 14;
550
- const raw = await this.readRegisterValue(addr, 1, 'int16');
551
- console.log(`AC Power (W): address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw}), SF=${scaleFactors.W_SF}`);
552
- return raw;
553
- })(), scaleFactors.W_SF, 'int16', 'AC Power'),
554
- apparentPower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 18, 1, 'uint16'), scaleFactors.VA_SF, 'uint16', 'Apparent Power'),
555
- reactivePower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 20, 1, 'int16'), scaleFactors.VAr_SF, 'int16', 'Reactive Power'),
556
- powerFactor: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 22, 1, 'int16'), scaleFactors.PF_SF, 'int16', 'Power Factor'),
551
+ acPower: this.applyScaleFactor(acPowerRaw, scaleFactors.W_SF, 'int16', 'AC Power', 14, 103),
552
+ apparentPower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 18, 1, 'uint16'), scaleFactors.VA_SF, 'uint16', 'Apparent Power', 18, 103),
553
+ reactivePower: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 20, 1, 'int16'), scaleFactors.VAr_SF, 'int16', 'Reactive Power', 20, 103),
554
+ powerFactor: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 22, 1, 'int16'), scaleFactors.PF_SF, 'int16', 'Power Factor', 22, 103),
557
555
  // Frequency - Offset 16
558
- frequency: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 16, 1, 'uint16'), scaleFactors.Hz_SF, 'uint16', 'Frequency'),
556
+ frequency: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 16, 1, 'uint16'), scaleFactors.Hz_SF, 'uint16', 'Frequency', 16, 103),
559
557
  // DC values - Offsets 27, 28, 30
560
- dcCurrent: this.applyScaleFactor(await (async () => {
561
- const addr = baseAddr + 27;
562
- const raw = await this.readRegisterValue(addr, 1, 'uint16');
563
- console.log(`DC Current: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw})`);
564
- return raw;
565
- })(), scaleFactors.DCA_SF, 'uint16', 'DC Current'),
566
- dcVoltage: this.applyScaleFactor(await (async () => {
567
- const addr = baseAddr + 28;
568
- const raw = await this.readRegisterValue(addr, 1, 'uint16');
569
- console.log(`DC Voltage: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw})`);
570
- return raw;
571
- })(), scaleFactors.DCV_SF, 'uint16', 'DC Voltage'),
572
- dcPower: this.applyScaleFactor(await (async () => {
573
- const addr = baseAddr + 30;
574
- const raw = await this.readRegisterValue(addr, 1, 'int16');
575
- console.log(`DC Power: address=${addr}, raw=0x${raw.toString(16).toUpperCase()} (${raw}), SF=${scaleFactors.DCW_SF}`);
576
- return raw;
577
- })(), scaleFactors.DCW_SF, 'int16', 'DC Power'),
558
+ dcCurrent: this.applyScaleFactor(dcCurrentRaw, scaleFactors.DCA_SF, 'uint16', 'DC Current', 27, 103),
559
+ dcVoltage: this.applyScaleFactor(dcVoltageRaw, scaleFactors.DCV_SF, 'uint16', 'DC Voltage', 28, 103),
560
+ dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'int16', 'DC Power', 30, 103),
578
561
  // Temperature values - Offsets 32, 34, 35, 36
579
- cabinetTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 32, 1, 'int16'), scaleFactors.Tmp_SF, 'int16', 'Cabinet Temperature'),
580
- heatSinkTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 34, 1, 'int16'), scaleFactors.Tmp_SF, 'int16', 'Heat Sink Temperature'),
581
- transformerTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 35, 1, 'int16'), scaleFactors.Tmp_SF, 'int16', 'Transformer Temperature'),
582
- otherTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 36, 1, 'int16'), scaleFactors.Tmp_SF, 'int16', 'Other Temperature'),
562
+ cabinetTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 32, 1, 'int16'), scaleFactors.Tmp_SF, 'int16', 'Cabinet Temperature', 32, 103),
563
+ heatSinkTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 34, 1, 'int16'), scaleFactors.Tmp_SF, 'int16', 'Heat Sink Temperature', 34, 103),
564
+ transformerTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 35, 1, 'int16'), scaleFactors.Tmp_SF, 'int16', 'Transformer Temperature', 35, 103),
565
+ otherTemperature: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 36, 1, 'int16'), scaleFactors.Tmp_SF, 'int16', 'Other Temperature', 36, 103),
583
566
  // Status values - Offsets 38, 39
584
567
  operatingState: await this.readRegisterValue(baseAddr + 38, 1, 'uint16'),
585
568
  vendorState: await this.readRegisterValue(baseAddr + 39, 1, 'uint16'),
@@ -591,11 +574,20 @@ class SunspecModbusClient {
591
574
  vendorEvents3: await this.readRegisterValue(baseAddr + 48, 2, 'uint32'),
592
575
  vendorEvents4: await this.readRegisterValue(baseAddr + 50, 2, 'uint32')
593
576
  };
577
+ // Log non-scaled fields
578
+ this.logRegisterRead(103, 38, 'Operating State', data.operatingState, 'enum16');
579
+ this.logRegisterRead(103, 39, 'Vendor State', data.vendorState, 'uint16');
580
+ this.logRegisterRead(103, 40, 'Events', data.events, 'bitfield32');
581
+ this.logRegisterRead(103, 42, 'Events2', data.events2, 'bitfield32');
582
+ this.logRegisterRead(103, 44, 'Vendor Events 1', data.vendorEvents1, 'bitfield32');
583
+ this.logRegisterRead(103, 46, 'Vendor Events 2', data.vendorEvents2, 'bitfield32');
584
+ this.logRegisterRead(103, 48, 'Vendor Events 3', data.vendorEvents3, 'bitfield32');
585
+ this.logRegisterRead(103, 50, 'Vendor Events 4', data.vendorEvents4, 'bitfield32');
594
586
  // Read AC Energy (32-bit accumulator) - Offset 24-25
595
- const acEnergyAddr = baseAddr + 24;
596
- const acEnergy = await this.readRegisterValue(acEnergyAddr, 2, 'uint32');
587
+ const acEnergy = await this.readRegisterValue(baseAddr + 24, 2, 'uint32');
588
+ this.logRegisterRead(103, 24, 'AC Energy', acEnergy, 'acc32');
597
589
  data.acEnergy = !this.isUnimplementedValue(acEnergy, 'acc32')
598
- ? acEnergy * Math.pow(10, scaleFactors.WH_SF) // Regular number with scale factor
590
+ ? acEnergy * Math.pow(10, scaleFactors.WH_SF)
599
591
  : undefined;
600
592
  return data;
601
593
  }
@@ -623,41 +615,32 @@ class SunspecModbusClient {
623
615
  DCV_SF: await this.readRegisterValue(baseAddr + 19, 1, 'int16'),
624
616
  DCW_SF: await this.readRegisterValue(baseAddr + 21, 1, 'int16')
625
617
  };
626
- console.log('Single-Phase Inverter Scale Factors:', JSON.stringify(scaleFactors, null, 2));
627
- // Read raw values with logging
628
- const acCurrentAddr = baseAddr + 2;
629
- const acCurrentRaw = await this.readRegisterValue(acCurrentAddr, 1, 'uint16');
630
- console.log(`AC Current: address=${acCurrentAddr}, raw=0x${acCurrentRaw.toString(16).toUpperCase()} (${acCurrentRaw})`);
631
- const voltageAddr = baseAddr + 7;
632
- const voltageRaw = await this.readRegisterValue(voltageAddr, 1, 'uint16');
633
- console.log(`AC Voltage: address=${voltageAddr}, raw=0x${voltageRaw.toString(16).toUpperCase()} (${voltageRaw})`);
634
- const acPowerAddr = baseAddr + 9;
635
- const acPowerRaw = await this.readRegisterValue(acPowerAddr, 1, 'int16');
636
- console.log(`AC Power: address=${acPowerAddr}, raw=0x${acPowerRaw.toString(16).toUpperCase()} (${acPowerRaw}), SF=${scaleFactors.W_SF}`);
637
- const freqAddr = baseAddr + 11;
638
- const freqRaw = await this.readRegisterValue(freqAddr, 1, 'uint16');
639
- console.log(`Frequency: address=${freqAddr}, raw=0x${freqRaw.toString(16).toUpperCase()} (${freqRaw})`);
640
- const dcCurrentAddr = baseAddr + 14;
641
- const dcCurrentRaw = await this.readRegisterValue(dcCurrentAddr, 1, 'uint16');
642
- console.log(`DC Current: address=${dcCurrentAddr}, raw=0x${dcCurrentRaw.toString(16).toUpperCase()} (${dcCurrentRaw})`);
643
- const dcVoltageAddr = baseAddr + 15;
644
- const dcVoltageRaw = await this.readRegisterValue(dcVoltageAddr, 1, 'uint16');
645
- console.log(`DC Voltage: address=${dcVoltageAddr}, raw=0x${dcVoltageRaw.toString(16).toUpperCase()} (${dcVoltageRaw})`);
646
- const dcPowerAddr = baseAddr + 20;
647
- const dcPowerRaw = await this.readRegisterValue(dcPowerAddr, 1, 'int16');
648
- console.log(`DC Power: address=${dcPowerAddr}, raw=0x${dcPowerRaw.toString(16).toUpperCase()} (${dcPowerRaw}), SF=${scaleFactors.DCW_SF}`);
649
- const stateAddr = baseAddr + 24;
650
- const stateRaw = await this.readRegisterValue(stateAddr, 1, 'uint16');
651
- console.log(`Operating State: address=${stateAddr}, raw=0x${stateRaw.toString(16).toUpperCase()} (${stateRaw})`);
618
+ this.logRegisterRead(101, 6, 'A_SF', scaleFactors.A_SF, 'int16');
619
+ this.logRegisterRead(101, 13, 'V_SF', scaleFactors.V_SF, 'int16');
620
+ this.logRegisterRead(101, 10, 'W_SF', scaleFactors.W_SF, 'int16');
621
+ this.logRegisterRead(101, 12, 'Hz_SF', scaleFactors.Hz_SF, 'int16');
622
+ this.logRegisterRead(101, 18, 'DCA_SF', scaleFactors.DCA_SF, 'int16');
623
+ this.logRegisterRead(101, 19, 'DCV_SF', scaleFactors.DCV_SF, 'int16');
624
+ this.logRegisterRead(101, 21, 'DCW_SF', scaleFactors.DCW_SF, 'int16');
625
+ // Read raw values
626
+ const acCurrentRaw = await this.readRegisterValue(baseAddr + 2, 1, 'uint16');
627
+ const voltageRaw = await this.readRegisterValue(baseAddr + 7, 1, 'uint16');
628
+ const acPowerRaw = await this.readRegisterValue(baseAddr + 9, 1, 'int16');
629
+ const freqRaw = await this.readRegisterValue(baseAddr + 11, 1, 'uint16');
630
+ const dcCurrentRaw = await this.readRegisterValue(baseAddr + 14, 1, 'uint16');
631
+ const dcVoltageRaw = await this.readRegisterValue(baseAddr + 15, 1, 'uint16');
632
+ const dcPowerRaw = await this.readRegisterValue(baseAddr + 20, 1, 'int16');
633
+ const stateRaw = await this.readRegisterValue(baseAddr + 24, 1, 'uint16');
634
+ this.logRegisterRead(101, 24, 'Operating State', stateRaw, 'enum16');
652
635
  return {
653
636
  blockNumber: 101,
654
- voltageAN: this.applyScaleFactor(voltageRaw, scaleFactors.V_SF, 'uint16', 'Single Phase Voltage'),
655
- acCurrent: this.applyScaleFactor(acCurrentRaw, scaleFactors.A_SF, 'uint16', 'Single Phase AC Current'),
656
- acPower: this.applyScaleFactor(acPowerRaw, scaleFactors.W_SF, 'int16', 'Single Phase AC Power'),
657
- frequency: this.applyScaleFactor(freqRaw, scaleFactors.Hz_SF, 'uint16', 'Single Phase Frequency'),
658
- dcCurrent: this.applyScaleFactor(dcCurrentRaw, scaleFactors.DCA_SF, 'uint16', 'Single Phase DC Current'),
659
- dcVoltage: this.applyScaleFactor(dcVoltageRaw, scaleFactors.DCV_SF, 'uint16', 'Single Phase DC Voltage'),
660
- dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'int16', 'Single Phase DC Power'),
637
+ voltageAN: this.applyScaleFactor(voltageRaw, scaleFactors.V_SF, 'uint16', 'Voltage AN', 7, 101),
638
+ acCurrent: this.applyScaleFactor(acCurrentRaw, scaleFactors.A_SF, 'uint16', 'AC Current', 2, 101),
639
+ acPower: this.applyScaleFactor(acPowerRaw, scaleFactors.W_SF, 'int16', 'AC Power', 9, 101),
640
+ frequency: this.applyScaleFactor(freqRaw, scaleFactors.Hz_SF, 'uint16', 'Frequency', 11, 101),
641
+ dcCurrent: this.applyScaleFactor(dcCurrentRaw, scaleFactors.DCA_SF, 'uint16', 'DC Current', 14, 101),
642
+ dcVoltage: this.applyScaleFactor(dcVoltageRaw, scaleFactors.DCV_SF, 'uint16', 'DC Voltage', 15, 101),
643
+ dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'int16', 'DC Power', 20, 101),
661
644
  operatingState: stateRaw
662
645
  };
663
646
  }
@@ -684,24 +667,55 @@ class SunspecModbusClient {
684
667
  DCW_SF: await this.readRegisterValue(baseAddr + 31, 1, 'int16'), // Offset 31
685
668
  Tmp_SF: await this.readRegisterValue(baseAddr + 36, 1, 'int16') // Offset 36
686
669
  };
687
- console.log('Inverter Scale Factors:', JSON.stringify(scaleFactors, null, 2));
670
+ this.logRegisterRead(103, 6, 'A_SF', scaleFactors.A_SF, 'int16');
671
+ this.logRegisterRead(103, 13, 'V_SF', scaleFactors.V_SF, 'int16');
672
+ this.logRegisterRead(103, 15, 'W_SF', scaleFactors.W_SF, 'int16');
673
+ this.logRegisterRead(103, 17, 'Hz_SF', scaleFactors.Hz_SF, 'int16');
674
+ this.logRegisterRead(103, 19, 'VA_SF', scaleFactors.VA_SF, 'int16');
675
+ this.logRegisterRead(103, 21, 'VAr_SF', scaleFactors.VAr_SF, 'int16');
676
+ this.logRegisterRead(103, 23, 'PF_SF', scaleFactors.PF_SF, 'int16');
677
+ this.logRegisterRead(103, 26, 'WH_SF', scaleFactors.WH_SF, 'int16');
678
+ this.logRegisterRead(103, 28, 'DCA_SF', scaleFactors.DCA_SF, 'int16');
679
+ this.logRegisterRead(103, 29, 'DCV_SF', scaleFactors.DCV_SF, 'int16');
680
+ this.logRegisterRead(103, 31, 'DCW_SF', scaleFactors.DCW_SF, 'int16');
681
+ this.logRegisterRead(103, 36, 'Tmp_SF', scaleFactors.Tmp_SF, 'int16');
688
682
  return scaleFactors;
689
683
  }
690
684
  /**
691
685
  * Apply scale factor to a value
692
686
  * Returns undefined if the value is unimplemented or scale factor is out of range
693
687
  */
694
- applyScaleFactor(value, scaleFactor, dataType = 'uint16', fieldName) {
688
+ applyScaleFactor(value, scaleFactor, dataType = 'uint16', fieldName, offset, modelId) {
695
689
  // Check for unimplemented values
696
690
  if (this.isUnimplementedValue(value, dataType)) {
697
691
  return undefined;
698
692
  }
699
693
  const scaledValue = value * Math.pow(10, scaleFactor);
700
- // Log the raw and scaled values in decimal format
701
- const fieldPrefix = fieldName ? `${fieldName}: ` : '';
702
- console.log(`Scale Factor Applied - ${fieldPrefix}raw=${value} (decimal), SF=${scaleFactor}, scaled=${scaledValue}`);
694
+ // Log the raw and scaled values
695
+ if (offset !== undefined && modelId !== undefined && fieldName) {
696
+ const hex = value >= 0 ? value.toString(16).toUpperCase() : (value >>> 0).toString(16).toUpperCase();
697
+ console.log(`[Model ${modelId}] offset ${offset}: ${fieldName} raw=${value} (0x${hex}), SF=${scaleFactor}, scaled=${scaledValue}`);
698
+ }
699
+ else {
700
+ const fieldPrefix = fieldName ? `${fieldName}: ` : '';
701
+ console.log(`Scale Factor Applied - ${fieldPrefix}raw=${value} (decimal), SF=${scaleFactor}, scaled=${scaledValue}`);
702
+ }
703
703
  return scaledValue;
704
704
  }
705
+ logRegisterRead(modelId, offset, fieldName, rawValue, dataType) {
706
+ const typeInfo = dataType ? ` (${dataType})` : '';
707
+ if (rawValue === undefined) {
708
+ console.log(`[Model ${modelId}] offset ${offset}: ${fieldName} = -${typeInfo}`);
709
+ return;
710
+ }
711
+ if (typeof rawValue === 'number') {
712
+ const hex = rawValue >= 0 ? rawValue.toString(16).toUpperCase() : (rawValue >>> 0).toString(16).toUpperCase();
713
+ console.log(`[Model ${modelId}] offset ${offset}: ${fieldName} = ${rawValue} (0x${hex})${typeInfo}`);
714
+ }
715
+ else {
716
+ console.log(`[Model ${modelId}] offset ${offset}: ${fieldName} = "${rawValue}"${typeInfo}`);
717
+ }
718
+ }
705
719
  /**
706
720
  * Read MPPT Scale Factors for a specific module
707
721
  * Returns the scale factors for DC Current, DC Voltage, DC Power, and DC Energy
@@ -735,10 +749,10 @@ class SunspecModbusClient {
735
749
  DCW_SF, // Power Scale Factor
736
750
  DCWH_SF, // Energy Scale Factor
737
751
  };
738
- console.log(` DCA_SF (Current): ${DCA_SF} at register ${moduleAddr + 2}`);
739
- console.log(` DCV_SF (Voltage): ${DCV_SF} at register ${moduleAddr + 3}`);
740
- console.log(` DCW_SF (Power): ${DCW_SF} at register ${moduleAddr + 4}`);
741
- console.log(` DCWH_SF (Energy): ${DCWH_SF} at register ${moduleAddr + 5}`);
752
+ this.logRegisterRead(160, 2, 'DCA_SF', DCA_SF, 'int16');
753
+ this.logRegisterRead(160, 3, 'DCV_SF', DCV_SF, 'int16');
754
+ this.logRegisterRead(160, 4, 'DCW_SF', DCW_SF, 'int16');
755
+ this.logRegisterRead(160, 5, 'DCWH_SF', DCWH_SF, 'int16');
742
756
  return scaleFactors;
743
757
  }
744
758
  catch (error) {
@@ -768,7 +782,6 @@ class SunspecModbusClient {
768
782
  console.error(`Failed to read scale factors for MPPT module ${moduleId}`);
769
783
  return null;
770
784
  }
771
- console.log(`MPPT Module ${moduleId} Scale Factors:`, JSON.stringify(scaleFactors, null, 2));
772
785
  const id = await this.readRegisterValue(moduleAddr, 1, 'uint16');
773
786
  const idString = await this.readRegisterValue(moduleAddr + 1, 8, 'string');
774
787
  const dcCurrentRaw = await this.readRegisterValue(moduleAddr + 9, 1, 'uint16');
@@ -777,6 +790,8 @@ class SunspecModbusClient {
777
790
  const dcEnergyRaw = await this.readRegisterValue(moduleAddr + 12, 2, 'uint32');
778
791
  const temperatureRaw = await this.readRegisterValue(moduleAddr + 16, 1, 'int16');
779
792
  const dcst = await this.readRegisterValue(moduleAddr + 17, 1, 'uint16');
793
+ this.logRegisterRead(160, 0, `MPPT ${moduleId} ID`, id, 'uint16');
794
+ this.logRegisterRead(160, 1, `MPPT ${moduleId} String ID`, idString, 'string');
780
795
  // Map the DC module state to human-readable name
781
796
  // Check if this module is actually implemented/connected
782
797
  // If all key values are unimplemented, this module doesn't exist
@@ -790,24 +805,28 @@ class SunspecModbusClient {
790
805
  // Note: There appears to be a temperature scale factor in the original model,
791
806
  // but it's not in the current register map. We'll apply a default scale factor.
792
807
  const temperatureScaleFactor = -1; // Common default for temperature readings
808
+ this.logRegisterRead(160, 12, `MPPT ${moduleId} DC Energy`, dcEnergyRaw, 'acc32');
809
+ const timestampRaw = await this.readRegisterValue(moduleAddr + 14, 2, 'uint32');
810
+ this.logRegisterRead(160, 14, `MPPT ${moduleId} Timestamp`, timestampRaw, 'uint32');
811
+ this.logRegisterRead(160, 17, `MPPT ${moduleId} Operating State`, dcst, 'enum16');
793
812
  const data = {
794
813
  blockNumber: 160,
795
814
  blockAddress: model.address,
796
815
  blockLength: model.length,
797
816
  id: id,
798
817
  stringId: idString,
799
- dcCurrent: this.applyScaleFactor(dcCurrentRaw, scaleFactors.DCA_SF, 'uint16', `MPPT ${moduleId} DC Current`),
818
+ dcCurrent: this.applyScaleFactor(dcCurrentRaw, scaleFactors.DCA_SF, 'uint16', `MPPT ${moduleId} DC Current`, 9, 160),
800
819
  dcCurrentSF: scaleFactors.DCA_SF,
801
- dcVoltage: this.applyScaleFactor(dcVoltageRaw, scaleFactors.DCV_SF, 'uint16', `MPPT ${moduleId} DC Voltage`),
820
+ dcVoltage: this.applyScaleFactor(dcVoltageRaw, scaleFactors.DCV_SF, 'uint16', `MPPT ${moduleId} DC Voltage`, 10, 160),
802
821
  dcVoltageSF: scaleFactors.DCV_SF,
803
- dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'uint16', `MPPT ${moduleId} DC Power`),
822
+ dcPower: this.applyScaleFactor(dcPowerRaw, scaleFactors.DCW_SF, 'uint16', `MPPT ${moduleId} DC Power`, 11, 160),
804
823
  dcPowerSF: scaleFactors.DCW_SF,
805
824
  dcEnergy: !this.isUnimplementedValue(dcEnergyRaw, 'acc32')
806
- ? dcEnergyRaw * Math.pow(10, scaleFactors.DCWH_SF) // Regular number with scale factor
825
+ ? dcEnergyRaw * Math.pow(10, scaleFactors.DCWH_SF)
807
826
  : undefined,
808
827
  dcEnergySF: scaleFactors.DCWH_SF,
809
- timestamp: await this.readRegisterValue(moduleAddr + 14, 2, 'uint32'),
810
- temperature: this.applyScaleFactor(temperatureRaw, temperatureScaleFactor, 'int16', `MPPT ${moduleId} Temperature`),
828
+ timestamp: timestampRaw,
829
+ temperature: this.applyScaleFactor(temperatureRaw, temperatureScaleFactor, 'int16', `MPPT ${moduleId} Temperature`, 16, 160),
811
830
  temperatureSF: temperatureScaleFactor,
812
831
  operatingState: dcst,
813
832
  };
@@ -900,6 +919,238 @@ class SunspecModbusClient {
900
919
  return `UNKNOWN(${state})`;
901
920
  }
902
921
  }
922
+ /**
923
+ * Map battery type to human-readable name (Model 802)
924
+ */
925
+ mapBatteryType(typ) {
926
+ switch (typ) {
927
+ case sunspec_interfaces_js_1.SunspecBatteryType.NOT_APPLICABLE_UNKNOWN:
928
+ return "NOT_APPLICABLE_UNKNOWN";
929
+ case sunspec_interfaces_js_1.SunspecBatteryType.LEAD_ACID:
930
+ return "LEAD_ACID";
931
+ case sunspec_interfaces_js_1.SunspecBatteryType.NICKEL_METAL_HYDRIDE:
932
+ return "NICKEL_METAL_HYDRIDE";
933
+ case sunspec_interfaces_js_1.SunspecBatteryType.NICKEL_CADMIUM:
934
+ return "NICKEL_CADMIUM";
935
+ case sunspec_interfaces_js_1.SunspecBatteryType.LITHIUM_ION:
936
+ return "LITHIUM_ION";
937
+ case sunspec_interfaces_js_1.SunspecBatteryType.CARBON_ZINC:
938
+ return "CARBON_ZINC";
939
+ case sunspec_interfaces_js_1.SunspecBatteryType.ZINC_CHLORIDE:
940
+ return "ZINC_CHLORIDE";
941
+ case sunspec_interfaces_js_1.SunspecBatteryType.ALKALINE:
942
+ return "ALKALINE";
943
+ case sunspec_interfaces_js_1.SunspecBatteryType.RECHARGEABLE_ALKALINE:
944
+ return "RECHARGEABLE_ALKALINE";
945
+ case sunspec_interfaces_js_1.SunspecBatteryType.SODIUM_SULFUR:
946
+ return "SODIUM_SULFUR";
947
+ case sunspec_interfaces_js_1.SunspecBatteryType.FLOW:
948
+ return "FLOW";
949
+ case sunspec_interfaces_js_1.SunspecBatteryType.SUPER_CAPACITOR:
950
+ return "SUPER_CAPACITOR";
951
+ case sunspec_interfaces_js_1.SunspecBatteryType.OTHER:
952
+ return "OTHER";
953
+ default:
954
+ if (this.isUnimplementedValue(typ, 'enum16')) {
955
+ return "NOT_IMPLEMENTED";
956
+ }
957
+ return `UNKNOWN(${typ})`;
958
+ }
959
+ }
960
+ /**
961
+ * Map battery bank state to human-readable name (Model 802)
962
+ */
963
+ mapBatteryBankState(state) {
964
+ switch (state) {
965
+ case sunspec_interfaces_js_1.SunspecBatteryBankState.DISCONNECTED:
966
+ return "DISCONNECTED";
967
+ case sunspec_interfaces_js_1.SunspecBatteryBankState.INITIALIZING:
968
+ return "INITIALIZING";
969
+ case sunspec_interfaces_js_1.SunspecBatteryBankState.CONNECTED:
970
+ return "CONNECTED";
971
+ case sunspec_interfaces_js_1.SunspecBatteryBankState.STANDBY:
972
+ return "STANDBY";
973
+ case sunspec_interfaces_js_1.SunspecBatteryBankState.SOC_PROTECTION:
974
+ return "SOC_PROTECTION";
975
+ case sunspec_interfaces_js_1.SunspecBatteryBankState.SUSPENDING:
976
+ return "SUSPENDING";
977
+ case sunspec_interfaces_js_1.SunspecBatteryBankState.FAULT:
978
+ return "FAULT";
979
+ default:
980
+ if (this.isUnimplementedValue(state, 'enum16')) {
981
+ return "NOT_IMPLEMENTED";
982
+ }
983
+ return `UNKNOWN(${state})`;
984
+ }
985
+ }
986
+ /**
987
+ * Read Model 802 scale factors (offsets 52-63)
988
+ */
989
+ async readBatteryBaseScaleFactors(baseAddr) {
990
+ const scaleFactors = {
991
+ AHRtg_SF: await this.readRegisterValue(baseAddr + 52, 1, 'int16'),
992
+ WHRtg_SF: await this.readRegisterValue(baseAddr + 53, 1, 'int16'),
993
+ WChaDisChaMax_SF: await this.readRegisterValue(baseAddr + 54, 1, 'int16'),
994
+ DisChaRte_SF: await this.readRegisterValue(baseAddr + 55, 1, 'int16'),
995
+ SoC_SF: await this.readRegisterValue(baseAddr + 56, 1, 'int16'),
996
+ DoD_SF: await this.readRegisterValue(baseAddr + 57, 1, 'int16'),
997
+ SoH_SF: await this.readRegisterValue(baseAddr + 58, 1, 'int16'),
998
+ V_SF: await this.readRegisterValue(baseAddr + 59, 1, 'int16'),
999
+ CellV_SF: await this.readRegisterValue(baseAddr + 60, 1, 'int16'),
1000
+ A_SF: await this.readRegisterValue(baseAddr + 61, 1, 'int16'),
1001
+ AMax_SF: await this.readRegisterValue(baseAddr + 62, 1, 'int16'),
1002
+ W_SF: await this.readRegisterValue(baseAddr + 63, 1, 'int16'),
1003
+ };
1004
+ this.logRegisterRead(802, 52, 'AHRtg_SF', scaleFactors.AHRtg_SF, 'int16');
1005
+ this.logRegisterRead(802, 53, 'WHRtg_SF', scaleFactors.WHRtg_SF, 'int16');
1006
+ this.logRegisterRead(802, 54, 'WChaDisChaMax_SF', scaleFactors.WChaDisChaMax_SF, 'int16');
1007
+ this.logRegisterRead(802, 55, 'DisChaRte_SF', scaleFactors.DisChaRte_SF, 'int16');
1008
+ this.logRegisterRead(802, 56, 'SoC_SF', scaleFactors.SoC_SF, 'int16');
1009
+ this.logRegisterRead(802, 57, 'DoD_SF', scaleFactors.DoD_SF, 'int16');
1010
+ this.logRegisterRead(802, 58, 'SoH_SF', scaleFactors.SoH_SF, 'int16');
1011
+ this.logRegisterRead(802, 59, 'V_SF', scaleFactors.V_SF, 'int16');
1012
+ this.logRegisterRead(802, 60, 'CellV_SF', scaleFactors.CellV_SF, 'int16');
1013
+ this.logRegisterRead(802, 61, 'A_SF', scaleFactors.A_SF, 'int16');
1014
+ this.logRegisterRead(802, 62, 'AMax_SF', scaleFactors.AMax_SF, 'int16');
1015
+ this.logRegisterRead(802, 63, 'W_SF', scaleFactors.W_SF, 'int16');
1016
+ return scaleFactors;
1017
+ }
1018
+ /**
1019
+ * Read battery base data from Model 802 (Battery Base)
1020
+ */
1021
+ async readBatteryBaseData() {
1022
+ const model = this.findModel(sunspec_interfaces_js_1.SunspecModelId.BatteryBase);
1023
+ if (!model) {
1024
+ console.log('Battery Base model 802 not found');
1025
+ return null;
1026
+ }
1027
+ const baseAddr = model.address;
1028
+ console.log(`Reading Battery Base Data from Model 802 at base address: ${baseAddr}`);
1029
+ try {
1030
+ // Read scale factors first (offsets 52-63)
1031
+ const sf = await this.readBatteryBaseScaleFactors(baseAddr);
1032
+ // Read raw values
1033
+ const ahRtgRaw = await this.readRegisterValue(baseAddr + 2, 1, 'uint16');
1034
+ const whRtgRaw = await this.readRegisterValue(baseAddr + 3, 1, 'uint16');
1035
+ const wChaRteMaxRaw = await this.readRegisterValue(baseAddr + 4, 1, 'uint16');
1036
+ const wDisChaRteMaxRaw = await this.readRegisterValue(baseAddr + 5, 1, 'uint16');
1037
+ const disChaRteRaw = await this.readRegisterValue(baseAddr + 6, 1, 'uint16');
1038
+ const soCMaxRaw = await this.readRegisterValue(baseAddr + 7, 1, 'uint16');
1039
+ const soCMinRaw = await this.readRegisterValue(baseAddr + 8, 1, 'uint16');
1040
+ const soCRsvMaxRaw = await this.readRegisterValue(baseAddr + 9, 1, 'uint16');
1041
+ const soCRsvMinRaw = await this.readRegisterValue(baseAddr + 10, 1, 'uint16');
1042
+ const soCRaw = await this.readRegisterValue(baseAddr + 11, 1, 'uint16');
1043
+ const doDRaw = await this.readRegisterValue(baseAddr + 12, 1, 'uint16');
1044
+ const soHRaw = await this.readRegisterValue(baseAddr + 13, 1, 'uint16');
1045
+ const nCycRaw = await this.readRegisterValue(baseAddr + 14, 2, 'uint32');
1046
+ const chaStRaw = await this.readRegisterValue(baseAddr + 16, 1, 'uint16');
1047
+ const locRemCtlRaw = await this.readRegisterValue(baseAddr + 17, 1, 'uint16');
1048
+ const typRaw = await this.readRegisterValue(baseAddr + 21, 1, 'uint16');
1049
+ const stateRaw = await this.readRegisterValue(baseAddr + 22, 1, 'uint16');
1050
+ const evt1Raw = await this.readRegisterValue(baseAddr + 26, 2, 'uint32');
1051
+ const evt2Raw = await this.readRegisterValue(baseAddr + 28, 2, 'uint32');
1052
+ const evtVnd1Raw = await this.readRegisterValue(baseAddr + 30, 2, 'uint32');
1053
+ const evtVnd2Raw = await this.readRegisterValue(baseAddr + 32, 2, 'uint32');
1054
+ const vRaw = await this.readRegisterValue(baseAddr + 34, 1, 'uint16');
1055
+ const vMaxRaw = await this.readRegisterValue(baseAddr + 35, 1, 'uint16');
1056
+ const vMinRaw = await this.readRegisterValue(baseAddr + 36, 1, 'uint16');
1057
+ const cellVMaxRaw = await this.readRegisterValue(baseAddr + 37, 1, 'uint16');
1058
+ const cellVMaxStrRaw = await this.readRegisterValue(baseAddr + 38, 1, 'uint16');
1059
+ const cellVMaxModRaw = await this.readRegisterValue(baseAddr + 39, 1, 'uint16');
1060
+ const cellVMinRaw = await this.readRegisterValue(baseAddr + 40, 1, 'uint16');
1061
+ const cellVMinStrRaw = await this.readRegisterValue(baseAddr + 41, 1, 'uint16');
1062
+ const cellVMinModRaw = await this.readRegisterValue(baseAddr + 42, 1, 'uint16');
1063
+ const cellVAvgRaw = await this.readRegisterValue(baseAddr + 43, 1, 'uint16');
1064
+ const aRaw = await this.readRegisterValue(baseAddr + 44, 1, 'int16');
1065
+ const aChaMaxRaw = await this.readRegisterValue(baseAddr + 45, 1, 'uint16');
1066
+ const aDisChaMaxRaw = await this.readRegisterValue(baseAddr + 46, 1, 'uint16');
1067
+ const wRaw = await this.readRegisterValue(baseAddr + 47, 1, 'int16');
1068
+ const reqInvStateRaw = await this.readRegisterValue(baseAddr + 48, 1, 'uint16');
1069
+ const reqWRaw = await this.readRegisterValue(baseAddr + 49, 1, 'int16');
1070
+ const setOpRaw = await this.readRegisterValue(baseAddr + 50, 1, 'uint16');
1071
+ const setInvStateRaw = await this.readRegisterValue(baseAddr + 51, 1, 'uint16');
1072
+ // Map enum fields
1073
+ const chaStName = this.mapBatteryChargeState(chaStRaw);
1074
+ const typName = this.mapBatteryType(typRaw);
1075
+ const stateName = this.mapBatteryBankState(stateRaw);
1076
+ // Log non-scaled fields
1077
+ this.logRegisterRead(802, 14, 'nCyc', nCycRaw, 'uint32');
1078
+ this.logRegisterRead(802, 16, 'chaSt', chaStRaw, 'enum16');
1079
+ this.logRegisterRead(802, 17, 'locRemCtl', locRemCtlRaw, 'enum16');
1080
+ this.logRegisterRead(802, 21, 'typ', typRaw, 'enum16');
1081
+ this.logRegisterRead(802, 22, 'state', stateRaw, 'enum16');
1082
+ this.logRegisterRead(802, 26, 'evt1', evt1Raw, 'bitfield32');
1083
+ this.logRegisterRead(802, 28, 'evt2', evt2Raw, 'bitfield32');
1084
+ this.logRegisterRead(802, 30, 'evtVnd1', evtVnd1Raw, 'bitfield32');
1085
+ this.logRegisterRead(802, 32, 'evtVnd2', evtVnd2Raw, 'bitfield32');
1086
+ this.logRegisterRead(802, 38, 'cellVMaxStr', cellVMaxStrRaw, 'uint16');
1087
+ this.logRegisterRead(802, 39, 'cellVMaxMod', cellVMaxModRaw, 'uint16');
1088
+ this.logRegisterRead(802, 41, 'cellVMinStr', cellVMinStrRaw, 'uint16');
1089
+ this.logRegisterRead(802, 42, 'cellVMinMod', cellVMinModRaw, 'uint16');
1090
+ this.logRegisterRead(802, 48, 'reqInvState', reqInvStateRaw, 'enum16');
1091
+ this.logRegisterRead(802, 50, 'setOp', setOpRaw, 'enum16');
1092
+ this.logRegisterRead(802, 51, 'setInvState', setInvStateRaw, 'enum16');
1093
+ const data = {
1094
+ blockNumber: 802,
1095
+ blockAddress: model.address,
1096
+ blockLength: model.length,
1097
+ // Nameplate
1098
+ ahRtg: this.applyScaleFactor(ahRtgRaw, sf.AHRtg_SF, 'uint16', 'AH Rating', 2, 802),
1099
+ whRtg: this.applyScaleFactor(whRtgRaw, sf.WHRtg_SF, 'uint16', 'WH Rating', 3, 802),
1100
+ wChaRteMax: this.applyScaleFactor(wChaRteMaxRaw, sf.WChaDisChaMax_SF, 'uint16', 'Max Charge Rate', 4, 802),
1101
+ wDisChaRteMax: this.applyScaleFactor(wDisChaRteMaxRaw, sf.WChaDisChaMax_SF, 'uint16', 'Max Discharge Rate', 5, 802),
1102
+ // SoC/Health
1103
+ disChaRte: this.applyScaleFactor(disChaRteRaw, sf.DisChaRte_SF, 'uint16', 'Self Discharge Rate', 6, 802),
1104
+ soCMax: this.applyScaleFactor(soCMaxRaw, sf.SoC_SF, 'uint16', 'SoC Max', 7, 802),
1105
+ soCMin: this.applyScaleFactor(soCMinRaw, sf.SoC_SF, 'uint16', 'SoC Min', 8, 802),
1106
+ soCRsvMax: this.applyScaleFactor(soCRsvMaxRaw, sf.SoC_SF, 'uint16', 'SoC Reserve Max', 9, 802),
1107
+ soCRsvMin: this.applyScaleFactor(soCRsvMinRaw, sf.SoC_SF, 'uint16', 'SoC Reserve Min', 10, 802),
1108
+ soC: this.applyScaleFactor(soCRaw, sf.SoC_SF, 'uint16', 'State of Charge', 11, 802),
1109
+ doD: this.applyScaleFactor(doDRaw, sf.DoD_SF, 'uint16', 'Depth of Discharge', 12, 802),
1110
+ soH: this.applyScaleFactor(soHRaw, sf.SoH_SF, 'uint16', 'State of Health', 13, 802),
1111
+ // Status
1112
+ nCyc: !this.isUnimplementedValue(nCycRaw, 'uint32') ? nCycRaw : undefined,
1113
+ chaSt: !this.isUnimplementedValue(chaStRaw, 'enum16') ? chaStRaw : undefined,
1114
+ chaStName,
1115
+ locRemCtl: !this.isUnimplementedValue(locRemCtlRaw, 'enum16') ? locRemCtlRaw : undefined,
1116
+ typ: !this.isUnimplementedValue(typRaw, 'enum16') ? typRaw : undefined,
1117
+ typName,
1118
+ state: !this.isUnimplementedValue(stateRaw, 'enum16') ? stateRaw : undefined,
1119
+ stateName,
1120
+ // Events
1121
+ evt1: !this.isUnimplementedValue(evt1Raw, 'bitfield32') ? evt1Raw : undefined,
1122
+ evt2: !this.isUnimplementedValue(evt2Raw, 'bitfield32') ? evt2Raw : undefined,
1123
+ evtVnd1: !this.isUnimplementedValue(evtVnd1Raw, 'bitfield32') ? evtVnd1Raw : undefined,
1124
+ evtVnd2: !this.isUnimplementedValue(evtVnd2Raw, 'bitfield32') ? evtVnd2Raw : undefined,
1125
+ // Voltage
1126
+ v: this.applyScaleFactor(vRaw, sf.V_SF, 'uint16', 'Battery Voltage', 34, 802),
1127
+ vMax: this.applyScaleFactor(vMaxRaw, sf.V_SF, 'uint16', 'Max Battery Voltage', 35, 802),
1128
+ vMin: this.applyScaleFactor(vMinRaw, sf.V_SF, 'uint16', 'Min Battery Voltage', 36, 802),
1129
+ cellVMax: this.applyScaleFactor(cellVMaxRaw, sf.CellV_SF, 'uint16', 'Max Cell Voltage', 37, 802),
1130
+ cellVMaxStr: !this.isUnimplementedValue(cellVMaxStrRaw, 'uint16') ? cellVMaxStrRaw : undefined,
1131
+ cellVMaxMod: !this.isUnimplementedValue(cellVMaxModRaw, 'uint16') ? cellVMaxModRaw : undefined,
1132
+ cellVMin: this.applyScaleFactor(cellVMinRaw, sf.CellV_SF, 'uint16', 'Min Cell Voltage', 40, 802),
1133
+ cellVMinStr: !this.isUnimplementedValue(cellVMinStrRaw, 'uint16') ? cellVMinStrRaw : undefined,
1134
+ cellVMinMod: !this.isUnimplementedValue(cellVMinModRaw, 'uint16') ? cellVMinModRaw : undefined,
1135
+ cellVAvg: this.applyScaleFactor(cellVAvgRaw, sf.CellV_SF, 'uint16', 'Avg Cell Voltage', 43, 802),
1136
+ // Current
1137
+ a: this.applyScaleFactor(aRaw, sf.A_SF, 'int16', 'Battery Current', 44, 802),
1138
+ aChaMax: this.applyScaleFactor(aChaMaxRaw, sf.AMax_SF, 'uint16', 'Max Charge Current', 45, 802),
1139
+ aDisChaMax: this.applyScaleFactor(aDisChaMaxRaw, sf.AMax_SF, 'uint16', 'Max Discharge Current', 46, 802),
1140
+ // Power
1141
+ w: this.applyScaleFactor(wRaw, sf.W_SF, 'int16', 'Battery Power', 47, 802),
1142
+ reqInvState: !this.isUnimplementedValue(reqInvStateRaw, 'enum16') ? reqInvStateRaw : undefined,
1143
+ reqW: this.applyScaleFactor(reqWRaw, sf.W_SF, 'int16', 'Requested Power', 49, 802),
1144
+ setOp: !this.isUnimplementedValue(setOpRaw, 'enum16') ? setOpRaw : undefined,
1145
+ setInvState: !this.isUnimplementedValue(setInvStateRaw, 'enum16') ? setInvStateRaw : undefined,
1146
+ };
1147
+ return data;
1148
+ }
1149
+ catch (error) {
1150
+ console.error(`Error reading battery base data: ${error}`);
1151
+ return null;
1152
+ }
1153
+ }
903
1154
  /**
904
1155
  * Read battery data from Model 124 (Basic Storage Controls)
905
1156
  */
@@ -934,7 +1185,14 @@ class SunspecModbusClient {
934
1185
  InBatV_SF: await this.readRegisterValue(baseAddr + 24, 1, 'int16'),
935
1186
  InOutWRte_SF: await this.readRegisterValue(baseAddr + 25, 1, 'int16')
936
1187
  };
937
- console.log('Battery Scale Factors:', JSON.stringify(scaleFactors, null, 2));
1188
+ this.logRegisterRead(124, 18, 'WChaMax_SF', scaleFactors.WChaMax_SF, 'int16');
1189
+ this.logRegisterRead(124, 19, 'WChaDisChaGra_SF', scaleFactors.WChaDisChaGra_SF, 'int16');
1190
+ this.logRegisterRead(124, 20, 'VAChaMax_SF', scaleFactors.VAChaMax_SF, 'int16');
1191
+ this.logRegisterRead(124, 21, 'MinRsvPct_SF', scaleFactors.MinRsvPct_SF, 'int16');
1192
+ this.logRegisterRead(124, 22, 'ChaState_SF', scaleFactors.ChaState_SF, 'int16');
1193
+ this.logRegisterRead(124, 23, 'StorAval_SF', scaleFactors.StorAval_SF, 'int16');
1194
+ this.logRegisterRead(124, 24, 'InBatV_SF', scaleFactors.InBatV_SF, 'int16');
1195
+ this.logRegisterRead(124, 25, 'InOutWRte_SF', scaleFactors.InOutWRte_SF, 'int16');
938
1196
  // Read raw values
939
1197
  const wChaMaxRaw = await this.readRegisterValue(baseAddr + 2, 1, 'uint16');
940
1198
  const wChaGraRaw = await this.readRegisterValue(baseAddr + 3, 1, 'uint16');
@@ -952,43 +1210,42 @@ class SunspecModbusClient {
952
1210
  const inOutWRteRvrtTmsRaw = await this.readRegisterValue(baseAddr + 15, 1, 'uint16');
953
1211
  const inOutWRteRmpTmsRaw = await this.readRegisterValue(baseAddr + 16, 1, 'uint16');
954
1212
  const chaGriSetRaw = await this.readRegisterValue(baseAddr + 17, 1, 'uint16');
955
- // Map charge state to human-readable name
1213
+ // Map charge state and log non-scaled fields
956
1214
  const chaStName = this.mapBatteryChargeState(chaStRaw);
957
- console.log(`Battery Charge State: ${chaStRaw} (${chaStName})`);
958
- // Log storage control mode
959
- if (!this.isUnimplementedValue(storCtlModRaw, 'bitfield16')) {
960
- const chargeEnabled = (storCtlModRaw & sunspec_interfaces_js_1.SunspecStorageControlMode.CHARGE) !== 0;
961
- const dischargeEnabled = (storCtlModRaw & sunspec_interfaces_js_1.SunspecStorageControlMode.DISCHARGE) !== 0;
962
- console.log(`Storage Control Mode: 0x${storCtlModRaw.toString(16)} (Charge: ${chargeEnabled}, Discharge: ${dischargeEnabled})`);
963
- }
1215
+ this.logRegisterRead(124, 5, 'storCtlMod', storCtlModRaw, 'bitfield16');
1216
+ this.logRegisterRead(124, 11, 'chaSt', chaStRaw, 'enum16');
1217
+ this.logRegisterRead(124, 14, 'inOutWRteWinTms', inOutWRteWinTmsRaw, 'uint16');
1218
+ this.logRegisterRead(124, 15, 'inOutWRteRvrtTms', inOutWRteRvrtTmsRaw, 'uint16');
1219
+ this.logRegisterRead(124, 16, 'inOutWRteRmpTms', inOutWRteRmpTmsRaw, 'uint16');
1220
+ this.logRegisterRead(124, 17, 'chaGriSet', chaGriSetRaw, 'enum16');
964
1221
  // Calculate actual values with scale factors
965
1222
  const data = {
966
1223
  blockNumber: 124,
967
1224
  blockAddress: model.address,
968
1225
  blockLength: model.length,
969
1226
  // Control settings
970
- wChaMax: this.applyScaleFactor(wChaMaxRaw, scaleFactors.WChaMax_SF, 'uint16', 'Max Charge Power'),
1227
+ wChaMax: this.applyScaleFactor(wChaMaxRaw, scaleFactors.WChaMax_SF, 'uint16', 'Max Charge Power', 2, 124),
971
1228
  wChaMaxSF: scaleFactors.WChaMax_SF,
972
- wChaGra: this.applyScaleFactor(wChaGraRaw, scaleFactors.WChaDisChaGra_SF, 'uint16', 'Charge Rate Gradient'),
973
- wDisChaGra: this.applyScaleFactor(wDisChaGraRaw, scaleFactors.WChaDisChaGra_SF, 'uint16', 'Discharge Rate Gradient'),
1229
+ wChaGra: this.applyScaleFactor(wChaGraRaw, scaleFactors.WChaDisChaGra_SF, 'uint16', 'Charge Rate Gradient', 3, 124),
1230
+ wDisChaGra: this.applyScaleFactor(wDisChaGraRaw, scaleFactors.WChaDisChaGra_SF, 'uint16', 'Discharge Rate Gradient', 4, 124),
974
1231
  wChaDisChaGraSF: scaleFactors.WChaDisChaGra_SF,
975
1232
  storCtlMod: !this.isUnimplementedValue(storCtlModRaw, 'bitfield16') ? storCtlModRaw : undefined,
976
- vaChaMax: this.applyScaleFactor(vaChaMaxRaw, scaleFactors.VAChaMax_SF, 'uint16', 'Max Charging VA'),
1233
+ vaChaMax: this.applyScaleFactor(vaChaMaxRaw, scaleFactors.VAChaMax_SF, 'uint16', 'Max Charging VA', 6, 124),
977
1234
  vaChaMaxSF: scaleFactors.VAChaMax_SF,
978
- minRsvPct: this.applyScaleFactor(minRsvPctRaw, scaleFactors.MinRsvPct_SF, 'uint16', 'Min Reserve Percent'),
1235
+ minRsvPct: this.applyScaleFactor(minRsvPctRaw, scaleFactors.MinRsvPct_SF, 'uint16', 'Min Reserve Percent', 7, 124),
979
1236
  minRsvPctSF: scaleFactors.MinRsvPct_SF,
980
1237
  // Status values
981
- chaState: this.applyScaleFactor(chaStateRaw, scaleFactors.ChaState_SF, 'uint16', 'State of Charge'),
1238
+ chaState: this.applyScaleFactor(chaStateRaw, scaleFactors.ChaState_SF, 'uint16', 'State of Charge', 8, 124),
982
1239
  chaStateSF: scaleFactors.ChaState_SF,
983
- storAval: this.applyScaleFactor(storAvalRaw, scaleFactors.StorAval_SF, 'uint16', 'Available Storage'),
1240
+ storAval: this.applyScaleFactor(storAvalRaw, scaleFactors.StorAval_SF, 'uint16', 'Available Storage', 9, 124),
984
1241
  storAvalSF: scaleFactors.StorAval_SF,
985
- inBatV: this.applyScaleFactor(inBatVRaw, scaleFactors.InBatV_SF, 'uint16', 'Battery Voltage'),
1242
+ inBatV: this.applyScaleFactor(inBatVRaw, scaleFactors.InBatV_SF, 'uint16', 'Battery Voltage', 10, 124),
986
1243
  inBatVSF: scaleFactors.InBatV_SF,
987
1244
  chaSt: !this.isUnimplementedValue(chaStRaw, 'enum16') ? chaStRaw : undefined,
988
1245
  chaStName: chaStName,
989
1246
  // Rate control
990
- outWRte: this.applyScaleFactor(outWRteRaw, scaleFactors.InOutWRte_SF, 'int16', 'Discharge Rate'),
991
- inWRte: this.applyScaleFactor(inWRteRaw, scaleFactors.InOutWRte_SF, 'int16', 'Charge Rate'),
1247
+ outWRte: this.applyScaleFactor(outWRteRaw, scaleFactors.InOutWRte_SF, 'int16', 'Discharge Rate', 12, 124),
1248
+ inWRte: this.applyScaleFactor(inWRteRaw, scaleFactors.InOutWRte_SF, 'int16', 'Charge Rate', 13, 124),
992
1249
  inOutWRteSF: scaleFactors.InOutWRte_SF,
993
1250
  // Timing parameters
994
1251
  inOutWRteWinTms: !this.isUnimplementedValue(inOutWRteWinTmsRaw, 'uint16') ? inOutWRteWinTmsRaw : undefined,
@@ -1013,8 +1270,43 @@ class SunspecModbusClient {
1013
1270
  }
1014
1271
  return data;
1015
1272
  }
1273
+ else if (model.id === 802) {
1274
+ // Model 802: Battery Base
1275
+ console.log('Using Model 802 (Battery Base)');
1276
+ const baseData = await this.readBatteryBaseData();
1277
+ if (!baseData) {
1278
+ return null;
1279
+ }
1280
+ // Derive charge/discharge power from w field
1281
+ let chargePower;
1282
+ let dischargePower;
1283
+ if (baseData.w !== undefined) {
1284
+ if (baseData.w >= 0) {
1285
+ chargePower = baseData.w;
1286
+ dischargePower = 0;
1287
+ }
1288
+ else {
1289
+ chargePower = 0;
1290
+ dischargePower = Math.abs(baseData.w);
1291
+ }
1292
+ }
1293
+ return {
1294
+ blockNumber: 802,
1295
+ blockAddress: model.address,
1296
+ blockLength: model.length,
1297
+ soc: baseData.soC,
1298
+ soh: baseData.soH,
1299
+ voltage: baseData.v,
1300
+ current: baseData.a,
1301
+ chaSt: baseData.chaSt,
1302
+ chaStName: baseData.chaStName,
1303
+ status: baseData.state,
1304
+ chargePower,
1305
+ dischargePower,
1306
+ };
1307
+ }
1016
1308
  else {
1017
- // Handle other battery models (802, 803) if needed
1309
+ // Handle other battery models (803) if needed
1018
1310
  console.log(`Battery Model ${model.id} reading not yet implemented`);
1019
1311
  return {
1020
1312
  blockNumber: model.id,
@@ -1145,6 +1437,9 @@ class SunspecModbusClient {
1145
1437
  MinRsvPct_SF: await this.readRegisterValue(baseAddr + 21, 1, 'int16'),
1146
1438
  InOutWRte_SF: await this.readRegisterValue(baseAddr + 25, 1, 'int16')
1147
1439
  };
1440
+ this.logRegisterRead(124, 18, 'WChaMax_SF', scaleFactors.WChaMax_SF, 'int16');
1441
+ this.logRegisterRead(124, 21, 'MinRsvPct_SF', scaleFactors.MinRsvPct_SF, 'int16');
1442
+ this.logRegisterRead(124, 25, 'InOutWRte_SF', scaleFactors.InOutWRte_SF, 'int16');
1148
1443
  // Read raw values
1149
1444
  const wChaMaxRaw = await this.readRegisterValue(baseAddr + 2, 1, 'uint16');
1150
1445
  const storCtlModRaw = await this.readRegisterValue(baseAddr + 5, 1, 'uint16');
@@ -1152,14 +1447,16 @@ class SunspecModbusClient {
1152
1447
  const outWRteRaw = await this.readRegisterValue(baseAddr + 12, 1, 'int16');
1153
1448
  const inWRteRaw = await this.readRegisterValue(baseAddr + 13, 1, 'int16');
1154
1449
  const chaGriSetRaw = await this.readRegisterValue(baseAddr + 17, 1, 'uint16');
1450
+ this.logRegisterRead(124, 5, 'storCtlMod', storCtlModRaw, 'bitfield16');
1451
+ this.logRegisterRead(124, 17, 'chaGriSet', chaGriSetRaw, 'enum16');
1155
1452
  // Apply scale factors and return control settings
1156
1453
  return {
1157
1454
  storCtlMod: !this.isUnimplementedValue(storCtlModRaw, 'bitfield16') ? storCtlModRaw : undefined,
1158
1455
  chaGriSet: !this.isUnimplementedValue(chaGriSetRaw, 'enum16') ? chaGriSetRaw : undefined,
1159
- wChaMax: this.applyScaleFactor(wChaMaxRaw, scaleFactors.WChaMax_SF, 'uint16'),
1160
- inWRte: this.applyScaleFactor(inWRteRaw, scaleFactors.InOutWRte_SF, 'int16'),
1161
- outWRte: this.applyScaleFactor(outWRteRaw, scaleFactors.InOutWRte_SF, 'int16'),
1162
- minRsvPct: this.applyScaleFactor(minRsvPctRaw, scaleFactors.MinRsvPct_SF, 'uint16')
1456
+ wChaMax: this.applyScaleFactor(wChaMaxRaw, scaleFactors.WChaMax_SF, 'uint16', 'Max Charge Power', 2, 124),
1457
+ inWRte: this.applyScaleFactor(inWRteRaw, scaleFactors.InOutWRte_SF, 'int16', 'Charge Rate', 13, 124),
1458
+ outWRte: this.applyScaleFactor(outWRteRaw, scaleFactors.InOutWRte_SF, 'int16', 'Discharge Rate', 12, 124),
1459
+ minRsvPct: this.applyScaleFactor(minRsvPctRaw, scaleFactors.MinRsvPct_SF, 'uint16', 'Min Reserve Percent', 7, 124)
1163
1460
  };
1164
1461
  }
1165
1462
  catch (error) {
@@ -1230,25 +1527,21 @@ class SunspecModbusClient {
1230
1527
  const powerSF = await this.readRegisterValue(baseAddr + powerSFOffset, 1, 'int16');
1231
1528
  const freqSF = await this.readRegisterValue(baseAddr + freqSFOffset, 1, 'int16');
1232
1529
  const energySF = await this.readRegisterValue(baseAddr + energySFOffset, 1, 'int16');
1233
- console.log(`Meter Scale Factors: Power_SF=${powerSF}, Freq_SF=${freqSF}, Energy_SF=${energySF}`);
1530
+ this.logRegisterRead(model.id, powerSFOffset, 'W_SF', powerSF, 'int16');
1531
+ this.logRegisterRead(model.id, freqSFOffset, 'Hz_SF', freqSF, 'int16');
1532
+ this.logRegisterRead(model.id, energySFOffset, 'TotWh_SF', energySF, 'int16');
1234
1533
  // Read raw values
1235
- const powerAddr = baseAddr + powerOffset;
1236
- const powerRaw = await this.readRegisterValue(powerAddr, 1, 'int16');
1237
- console.log(`Meter Total Power: address=${powerAddr}, raw=0x${powerRaw.toString(16).toUpperCase()} (${powerRaw}), SF=${powerSF}`);
1238
- const freqAddr = baseAddr + freqOffset;
1239
- const freqRaw = await this.readRegisterValue(freqAddr, 1, 'uint16');
1240
- console.log(`Meter Frequency: address=${freqAddr}, raw=0x${freqRaw.toString(16).toUpperCase()} (${freqRaw}), SF=${freqSF}`);
1241
- const exportAddr = baseAddr + exportOffset;
1242
- const exportRaw = await this.readRegisterValue(exportAddr, 2, 'uint32');
1243
- console.log(`Meter Export Energy: address=${exportAddr}, raw=0x${exportRaw.toString(16).toUpperCase()} (${exportRaw}), SF=${energySF}`);
1244
- const importAddr = baseAddr + importOffset;
1245
- const importRaw = await this.readRegisterValue(importAddr, 2, 'uint32');
1246
- console.log(`Meter Import Energy: address=${importAddr}, raw=0x${importRaw.toString(16).toUpperCase()} (${importRaw}), SF=${energySF}`);
1534
+ const powerRaw = await this.readRegisterValue(baseAddr + powerOffset, 1, 'int16');
1535
+ const freqRaw = await this.readRegisterValue(baseAddr + freqOffset, 1, 'uint16');
1536
+ const exportRaw = await this.readRegisterValue(baseAddr + exportOffset, 2, 'uint32');
1537
+ const importRaw = await this.readRegisterValue(baseAddr + importOffset, 2, 'uint32');
1538
+ this.logRegisterRead(model.id, exportOffset, 'TotWhExp', exportRaw, 'acc32');
1539
+ this.logRegisterRead(model.id, importOffset, 'TotWhImp', importRaw, 'acc32');
1247
1540
  // Calculate final values with scale factors
1248
- const totalPower = this.applyScaleFactor(powerRaw, powerSF, 'int16', 'Meter Total Power');
1249
- const frequency = this.applyScaleFactor(freqRaw, freqSF, 'uint16', 'Meter Frequency');
1250
- const exportedEnergy = this.applyScaleFactor(exportRaw, energySF, "acc32");
1251
- const importedEnergy = this.applyScaleFactor(importRaw, energySF, "acc32");
1541
+ const totalPower = this.applyScaleFactor(powerRaw, powerSF, 'int16', 'Total Power', powerOffset, model.id);
1542
+ const frequency = this.applyScaleFactor(freqRaw, freqSF, 'uint16', 'Frequency', freqOffset, model.id);
1543
+ const exportedEnergy = this.applyScaleFactor(exportRaw, energySF, "acc32", 'Exported Energy', exportOffset, model.id);
1544
+ const importedEnergy = this.applyScaleFactor(importRaw, energySF, "acc32", 'Imported Energy', importOffset, model.id);
1252
1545
  return {
1253
1546
  blockNumber: model.id,
1254
1547
  totalPower,
@@ -1282,30 +1575,26 @@ class SunspecModbusClient {
1282
1575
  const versionAddr = baseAddr + 40; // Offset 40-47 (8 registers) from data start
1283
1576
  const serialAddr = baseAddr + 48; // Offset 48-63 (16 registers) from data start
1284
1577
  const deviceAddrAddr = baseAddr + 64; // Offset 64 from data start
1285
- console.log(`Reading manufacturer from address ${manufacturerAddr} (16 registers)`);
1286
1578
  const manufacturer = await this.readRegisterValue(manufacturerAddr, 16, 'string');
1287
- console.log(`Manufacturer raw value: "${manufacturer}"`);
1288
- console.log(`Reading model from address ${modelAddr} (16 registers)`);
1579
+ this.logRegisterRead(1, 0, 'Manufacturer', manufacturer, 'string');
1289
1580
  const modelName = await this.readRegisterValue(modelAddr, 16, 'string');
1290
- console.log(`Model raw value: "${modelName}"`);
1291
- console.log(`Reading options from address ${optionsAddr} (8 registers)`);
1581
+ this.logRegisterRead(1, 16, 'Model', modelName, 'string');
1292
1582
  const options = await this.readRegisterValue(optionsAddr, 8, 'string');
1293
- console.log(`Reading version from address ${versionAddr} (8 registers)`);
1583
+ this.logRegisterRead(1, 32, 'Options', options, 'string');
1294
1584
  const version = await this.readRegisterValue(versionAddr, 8, 'string');
1295
- console.log(`Reading serial from address ${serialAddr} (16 registers)`);
1585
+ this.logRegisterRead(1, 40, 'Version', version, 'string');
1296
1586
  const serialNumber = await this.readRegisterValue(serialAddr, 16, 'string');
1297
- console.log(`Reading device address from address ${deviceAddrAddr}`);
1587
+ this.logRegisterRead(1, 48, 'Serial Number', serialNumber, 'string');
1298
1588
  const deviceAddress = await this.readRegisterValue(deviceAddrAddr, 1, 'uint16');
1299
- const result = {
1300
- manufacturer: manufacturer,
1589
+ this.logRegisterRead(1, 64, 'Device Address', deviceAddress, 'uint16');
1590
+ return {
1591
+ manufacturer,
1301
1592
  model: modelName,
1302
- options: options,
1303
- version: version,
1304
- serialNumber: serialNumber,
1305
- deviceAddress: deviceAddress
1593
+ options,
1594
+ version,
1595
+ serialNumber,
1596
+ deviceAddress
1306
1597
  };
1307
- console.log('Common Block Data:', JSON.stringify(result, null, 2));
1308
- return result;
1309
1598
  }
1310
1599
  catch (error) {
1311
1600
  console.error(`Error reading common block: ${error}`);
@@ -1361,47 +1650,64 @@ class SunspecModbusClient {
1361
1650
  MaxRmpRte_SF: await this.readRegisterValue(baseAddr + 30, 1, 'int16'),
1362
1651
  ECPNomHz_SF: await this.readRegisterValue(baseAddr + 31, 1, 'int16')
1363
1652
  };
1653
+ this.logRegisterRead(121, 22, 'WMax_SF', scaleFactors.WMax_SF, 'int16');
1654
+ this.logRegisterRead(121, 23, 'VRef_SF', scaleFactors.VRef_SF, 'int16');
1655
+ this.logRegisterRead(121, 24, 'VRefOfs_SF', scaleFactors.VRefOfs_SF, 'int16');
1656
+ this.logRegisterRead(121, 25, 'VMinMax_SF', scaleFactors.VMinMax_SF, 'int16');
1657
+ this.logRegisterRead(121, 26, 'VAMax_SF', scaleFactors.VAMax_SF, 'int16');
1658
+ this.logRegisterRead(121, 27, 'VArMax_SF', scaleFactors.VArMax_SF, 'int16');
1659
+ this.logRegisterRead(121, 28, 'WGra_SF', scaleFactors.WGra_SF, 'int16');
1660
+ this.logRegisterRead(121, 29, 'PFMin_SF', scaleFactors.PFMin_SF, 'int16');
1661
+ this.logRegisterRead(121, 30, 'MaxRmpRte_SF', scaleFactors.MaxRmpRte_SF, 'int16');
1662
+ this.logRegisterRead(121, 31, 'ECPNomHz_SF', scaleFactors.ECPNomHz_SF, 'int16');
1663
+ // Read non-scaled fields first for logging
1664
+ const vArActRaw = await this.readRegisterValue(baseAddr + 17, 1, 'uint16');
1665
+ const clcTotVARaw = await this.readRegisterValue(baseAddr + 18, 1, 'uint16');
1666
+ const connPhRaw = await this.readRegisterValue(baseAddr + 21, 1, 'uint16');
1667
+ this.logRegisterRead(121, 17, 'VArAct', vArActRaw, 'enum16');
1668
+ this.logRegisterRead(121, 18, 'ClcTotVA', clcTotVARaw, 'enum16');
1669
+ this.logRegisterRead(121, 21, 'ConnPh', connPhRaw, 'enum16');
1364
1670
  return {
1365
1671
  blockNumber: 121,
1366
1672
  blockAddress: model.address,
1367
1673
  blockLength: model.length,
1368
1674
  // Power settings - Offset 2
1369
- WMax: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 2, 1, 'uint16'), scaleFactors.WMax_SF, 'uint16', 'Max Power'),
1675
+ WMax: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 2, 1, 'uint16'), scaleFactors.WMax_SF, 'uint16', 'Max Power', 2, 121),
1370
1676
  WMax_SF: scaleFactors.WMax_SF,
1371
1677
  // Voltage settings - Offsets 3-6
1372
- VRef: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 3, 1, 'uint16'), scaleFactors.VRef_SF, 'uint16', 'Voltage Reference'),
1678
+ VRef: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 3, 1, 'uint16'), scaleFactors.VRef_SF, 'uint16', 'Voltage Reference', 3, 121),
1373
1679
  VRef_SF: scaleFactors.VRef_SF,
1374
- VRefOfs: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 4, 1, 'int16'), scaleFactors.VRefOfs_SF, 'int16', 'Voltage Reference Offset'),
1680
+ VRefOfs: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 4, 1, 'int16'), scaleFactors.VRefOfs_SF, 'int16', 'Voltage Reference Offset', 4, 121),
1375
1681
  VRefOfs_SF: scaleFactors.VRefOfs_SF,
1376
- VMax: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 5, 1, 'uint16'), scaleFactors.VMinMax_SF, 'uint16', 'Max Voltage'),
1377
- VMin: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 6, 1, 'uint16'), scaleFactors.VMinMax_SF, 'uint16', 'Min Voltage'),
1682
+ VMax: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 5, 1, 'uint16'), scaleFactors.VMinMax_SF, 'uint16', 'Max Voltage', 5, 121),
1683
+ VMin: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 6, 1, 'uint16'), scaleFactors.VMinMax_SF, 'uint16', 'Min Voltage', 6, 121),
1378
1684
  VMinMax_SF: scaleFactors.VMinMax_SF,
1379
1685
  // Apparent power settings - Offset 7
1380
- VAMax: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 7, 1, 'uint16'), scaleFactors.VAMax_SF, 'uint16', 'Max Apparent Power'),
1686
+ VAMax: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 7, 1, 'uint16'), scaleFactors.VAMax_SF, 'uint16', 'Max Apparent Power', 7, 121),
1381
1687
  VAMax_SF: scaleFactors.VAMax_SF,
1382
1688
  // Reactive power settings - Offsets 8-11
1383
- VArMaxQ1: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 8, 1, 'int16'), scaleFactors.VArMax_SF, 'int16', 'Max Reactive Power Q1'),
1384
- VArMaxQ2: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 9, 1, 'int16'), scaleFactors.VArMax_SF, 'int16', 'Max Reactive Power Q2'),
1385
- VArMaxQ3: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 10, 1, 'int16'), scaleFactors.VArMax_SF, 'int16', 'Max Reactive Power Q3'),
1386
- VArMaxQ4: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 11, 1, 'int16'), scaleFactors.VArMax_SF, 'int16', 'Max Reactive Power Q4'),
1689
+ VArMaxQ1: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 8, 1, 'int16'), scaleFactors.VArMax_SF, 'int16', 'Max Reactive Power Q1', 8, 121),
1690
+ VArMaxQ2: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 9, 1, 'int16'), scaleFactors.VArMax_SF, 'int16', 'Max Reactive Power Q2', 9, 121),
1691
+ VArMaxQ3: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 10, 1, 'int16'), scaleFactors.VArMax_SF, 'int16', 'Max Reactive Power Q3', 10, 121),
1692
+ VArMaxQ4: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 11, 1, 'int16'), scaleFactors.VArMax_SF, 'int16', 'Max Reactive Power Q4', 11, 121),
1387
1693
  VArMax_SF: scaleFactors.VArMax_SF,
1388
1694
  // Ramp rate settings - Offset 12
1389
- WGra: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 12, 1, 'uint16'), scaleFactors.WGra_SF, 'uint16', 'Power Ramp Rate'),
1695
+ WGra: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 12, 1, 'uint16'), scaleFactors.WGra_SF, 'uint16', 'Power Ramp Rate', 12, 121),
1390
1696
  WGra_SF: scaleFactors.WGra_SF,
1391
1697
  // Power factor settings - Offsets 13-16
1392
- PFMinQ1: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 13, 1, 'int16'), scaleFactors.PFMin_SF, 'int16', 'Min Power Factor Q1'),
1393
- PFMinQ2: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 14, 1, 'int16'), scaleFactors.PFMin_SF, 'int16', 'Min Power Factor Q2'),
1394
- PFMinQ3: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 15, 1, 'int16'), scaleFactors.PFMin_SF, 'int16', 'Min Power Factor Q3'),
1395
- PFMinQ4: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 16, 1, 'int16'), scaleFactors.PFMin_SF, 'int16', 'Min Power Factor Q4'),
1698
+ PFMinQ1: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 13, 1, 'int16'), scaleFactors.PFMin_SF, 'int16', 'Min Power Factor Q1', 13, 121),
1699
+ PFMinQ2: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 14, 1, 'int16'), scaleFactors.PFMin_SF, 'int16', 'Min Power Factor Q2', 14, 121),
1700
+ PFMinQ3: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 15, 1, 'int16'), scaleFactors.PFMin_SF, 'int16', 'Min Power Factor Q3', 15, 121),
1701
+ PFMinQ4: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 16, 1, 'int16'), scaleFactors.PFMin_SF, 'int16', 'Min Power Factor Q4', 16, 121),
1396
1702
  PFMin_SF: scaleFactors.PFMin_SF,
1397
1703
  // Other settings - Offsets 17-21
1398
- VArAct: await this.readRegisterValue(baseAddr + 17, 1, 'uint16'),
1399
- ClcTotVA: await this.readRegisterValue(baseAddr + 18, 1, 'uint16'),
1400
- MaxRmpRte: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 19, 1, 'uint16'), scaleFactors.MaxRmpRte_SF, 'uint16', 'Max Ramp Rate'),
1704
+ VArAct: vArActRaw,
1705
+ ClcTotVA: clcTotVARaw,
1706
+ MaxRmpRte: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 19, 1, 'uint16'), scaleFactors.MaxRmpRte_SF, 'uint16', 'Max Ramp Rate', 19, 121),
1401
1707
  MaxRmpRte_SF: scaleFactors.MaxRmpRte_SF,
1402
- ECPNomHz: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 20, 1, 'uint16'), scaleFactors.ECPNomHz_SF, 'uint16', 'Nominal Frequency'),
1708
+ ECPNomHz: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 20, 1, 'uint16'), scaleFactors.ECPNomHz_SF, 'uint16', 'Nominal Frequency', 20, 121),
1403
1709
  ECPNomHz_SF: scaleFactors.ECPNomHz_SF,
1404
- ConnPh: await this.readRegisterValue(baseAddr + 21, 1, 'uint16')
1710
+ ConnPh: connPhRaw
1405
1711
  };
1406
1712
  }
1407
1713
  catch (error) {
@@ -1426,38 +1732,74 @@ class SunspecModbusClient {
1426
1732
  OutPFSet_SF: await this.readRegisterValue(baseAddr + 22, 1, 'int16'),
1427
1733
  VArPct_SF: await this.readRegisterValue(baseAddr + 23, 1, 'int16')
1428
1734
  };
1735
+ this.logRegisterRead(123, 21, 'WMaxLimPct_SF', scaleFactors.WMaxLimPct_SF, 'int16');
1736
+ this.logRegisterRead(123, 22, 'OutPFSet_SF', scaleFactors.OutPFSet_SF, 'int16');
1737
+ this.logRegisterRead(123, 23, 'VArPct_SF', scaleFactors.VArPct_SF, 'int16');
1738
+ // Read non-scaled fields
1739
+ const connWinTmsRaw = await this.readRegisterValue(baseAddr, 1, 'uint16');
1740
+ const connRvrtTmsRaw = await this.readRegisterValue(baseAddr + 1, 1, 'uint16');
1741
+ const connRaw = await this.readRegisterValue(baseAddr + 2, 1, 'uint16');
1742
+ const wMaxLimPctWinTmsRaw = await this.readRegisterValue(baseAddr + 4, 1, 'uint16');
1743
+ const wMaxLimPctRvrtTmsRaw = await this.readRegisterValue(baseAddr + 5, 1, 'uint16');
1744
+ const wMaxLimPctRmpTmsRaw = await this.readRegisterValue(baseAddr + 6, 1, 'uint16');
1745
+ const wMaxLimEnaRaw = await this.readRegisterValue(baseAddr + 7, 1, 'uint16');
1746
+ const outPFSetWinTmsRaw = await this.readRegisterValue(baseAddr + 9, 1, 'uint16');
1747
+ const outPFSetRvrtTmsRaw = await this.readRegisterValue(baseAddr + 10, 1, 'uint16');
1748
+ const outPFSetRmpTmsRaw = await this.readRegisterValue(baseAddr + 11, 1, 'uint16');
1749
+ const outPFSetEnaRaw = await this.readRegisterValue(baseAddr + 12, 1, 'uint16');
1750
+ const vArPctWinTmsRaw = await this.readRegisterValue(baseAddr + 16, 1, 'uint16');
1751
+ const vArPctRvrtTmsRaw = await this.readRegisterValue(baseAddr + 17, 1, 'uint16');
1752
+ const vArPctRmpTmsRaw = await this.readRegisterValue(baseAddr + 18, 1, 'uint16');
1753
+ const vArPctModRaw = await this.readRegisterValue(baseAddr + 19, 1, 'uint16');
1754
+ const vArPctEnaRaw = await this.readRegisterValue(baseAddr + 20, 1, 'uint16');
1755
+ this.logRegisterRead(123, 0, 'Conn_WinTms', connWinTmsRaw, 'uint16');
1756
+ this.logRegisterRead(123, 1, 'Conn_RvrtTms', connRvrtTmsRaw, 'uint16');
1757
+ this.logRegisterRead(123, 2, 'Conn', connRaw, 'enum16');
1758
+ this.logRegisterRead(123, 4, 'WMaxLimPct_WinTms', wMaxLimPctWinTmsRaw, 'uint16');
1759
+ this.logRegisterRead(123, 5, 'WMaxLimPct_RvrtTms', wMaxLimPctRvrtTmsRaw, 'uint16');
1760
+ this.logRegisterRead(123, 6, 'WMaxLimPct_RmpTms', wMaxLimPctRmpTmsRaw, 'uint16');
1761
+ this.logRegisterRead(123, 7, 'WMaxLim_Ena', wMaxLimEnaRaw, 'enum16');
1762
+ this.logRegisterRead(123, 9, 'OutPFSet_WinTms', outPFSetWinTmsRaw, 'uint16');
1763
+ this.logRegisterRead(123, 10, 'OutPFSet_RvrtTms', outPFSetRvrtTmsRaw, 'uint16');
1764
+ this.logRegisterRead(123, 11, 'OutPFSet_RmpTms', outPFSetRmpTmsRaw, 'uint16');
1765
+ this.logRegisterRead(123, 12, 'OutPFSet_Ena', outPFSetEnaRaw, 'enum16');
1766
+ this.logRegisterRead(123, 16, 'VArPct_WinTms', vArPctWinTmsRaw, 'uint16');
1767
+ this.logRegisterRead(123, 17, 'VArPct_RvrtTms', vArPctRvrtTmsRaw, 'uint16');
1768
+ this.logRegisterRead(123, 18, 'VArPct_RmpTms', vArPctRmpTmsRaw, 'uint16');
1769
+ this.logRegisterRead(123, 19, 'VArPct_Mod', vArPctModRaw, 'enum16');
1770
+ this.logRegisterRead(123, 20, 'VArPct_Ena', vArPctEnaRaw, 'enum16');
1429
1771
  const controls = {
1430
1772
  blockNumber: 123,
1431
1773
  blockAddress: model.address,
1432
1774
  blockLength: model.length,
1433
1775
  // Connection control - Offsets 0-2
1434
- Conn_WinTms: await this.readRegisterValue(baseAddr, 1, 'uint16'),
1435
- Conn_RvrtTms: await this.readRegisterValue(baseAddr + 1, 1, 'uint16'),
1436
- Conn: await this.readRegisterValue(baseAddr + 2, 1, 'uint16'),
1776
+ Conn_WinTms: connWinTmsRaw,
1777
+ Conn_RvrtTms: connRvrtTmsRaw,
1778
+ Conn: connRaw,
1437
1779
  // Power limit control - Offsets 3-7
1438
- WMaxLimPct: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 3, 1, 'uint16'), scaleFactors.WMaxLimPct_SF, 'uint16', 'Power Limit Percentage'),
1780
+ WMaxLimPct: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 3, 1, 'uint16'), scaleFactors.WMaxLimPct_SF, 'uint16', 'Power Limit Percentage', 3, 123),
1439
1781
  WMaxLimPct_SF: scaleFactors.WMaxLimPct_SF,
1440
- WMaxLimPct_WinTms: await this.readRegisterValue(baseAddr + 4, 1, 'uint16'),
1441
- WMaxLimPct_RvrtTms: await this.readRegisterValue(baseAddr + 5, 1, 'uint16'),
1442
- WMaxLimPct_RmpTms: await this.readRegisterValue(baseAddr + 6, 1, 'uint16'),
1443
- WMaxLim_Ena: await this.readRegisterValue(baseAddr + 7, 1, 'uint16'),
1782
+ WMaxLimPct_WinTms: wMaxLimPctWinTmsRaw,
1783
+ WMaxLimPct_RvrtTms: wMaxLimPctRvrtTmsRaw,
1784
+ WMaxLimPct_RmpTms: wMaxLimPctRmpTmsRaw,
1785
+ WMaxLim_Ena: wMaxLimEnaRaw,
1444
1786
  // Power factor control - Offsets 8-12
1445
- OutPFSet: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 8, 1, 'int16'), scaleFactors.OutPFSet_SF, 'int16', 'Output Power Factor Set'),
1787
+ OutPFSet: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 8, 1, 'int16'), scaleFactors.OutPFSet_SF, 'int16', 'Output Power Factor Set', 8, 123),
1446
1788
  OutPFSet_SF: scaleFactors.OutPFSet_SF,
1447
- OutPFSet_WinTms: await this.readRegisterValue(baseAddr + 9, 1, 'uint16'),
1448
- OutPFSet_RvrtTms: await this.readRegisterValue(baseAddr + 10, 1, 'uint16'),
1449
- OutPFSet_RmpTms: await this.readRegisterValue(baseAddr + 11, 1, 'uint16'),
1450
- OutPFSet_Ena: await this.readRegisterValue(baseAddr + 12, 1, 'uint16'),
1789
+ OutPFSet_WinTms: outPFSetWinTmsRaw,
1790
+ OutPFSet_RvrtTms: outPFSetRvrtTmsRaw,
1791
+ OutPFSet_RmpTms: outPFSetRmpTmsRaw,
1792
+ OutPFSet_Ena: outPFSetEnaRaw,
1451
1793
  // Reactive power control - Offsets 13-20
1452
- VArWMaxPct: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 13, 1, 'int16'), scaleFactors.VArPct_SF, 'int16', 'Reactive Power at Max Power %'),
1453
- VArMaxPct: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 14, 1, 'int16'), scaleFactors.VArPct_SF, 'int16', 'Max Reactive Power %'),
1454
- VArAvalPct: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 15, 1, 'int16'), scaleFactors.VArPct_SF, 'int16', 'Available Reactive Power %'),
1794
+ VArWMaxPct: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 13, 1, 'int16'), scaleFactors.VArPct_SF, 'int16', 'Reactive Power at Max Power %', 13, 123),
1795
+ VArMaxPct: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 14, 1, 'int16'), scaleFactors.VArPct_SF, 'int16', 'Max Reactive Power %', 14, 123),
1796
+ VArAvalPct: this.applyScaleFactor(await this.readRegisterValue(baseAddr + 15, 1, 'int16'), scaleFactors.VArPct_SF, 'int16', 'Available Reactive Power %', 15, 123),
1455
1797
  VArPct_SF: scaleFactors.VArPct_SF,
1456
- VArPct_WinTms: await this.readRegisterValue(baseAddr + 16, 1, 'uint16'),
1457
- VArPct_RvrtTms: await this.readRegisterValue(baseAddr + 17, 1, 'uint16'),
1458
- VArPct_RmpTms: await this.readRegisterValue(baseAddr + 18, 1, 'uint16'),
1459
- VArPct_Mod: await this.readRegisterValue(baseAddr + 19, 1, 'uint16'),
1460
- VArPct_Ena: await this.readRegisterValue(baseAddr + 20, 1, 'uint16')
1798
+ VArPct_WinTms: vArPctWinTmsRaw,
1799
+ VArPct_RvrtTms: vArPctRvrtTmsRaw,
1800
+ VArPct_RmpTms: vArPctRmpTmsRaw,
1801
+ VArPct_Mod: vArPctModRaw,
1802
+ VArPct_Ena: vArPctEnaRaw
1461
1803
  };
1462
1804
  return controls;
1463
1805
  }