Skip to content

Commit 7b73fc3

Browse files
committed
Fix MOD series battery sensors showing zero values
PROBLEM: User reported battery sensors (SOC, voltage, current, power) showing zero even though register scan shows valid non-zero data. Register scan showed: - Battery voltage: 73.26V (register 3169) ✓ - Battery current: 0.3A (register 3170) ✓ - Battery SOC: 14% (register 3171) ✓ - Battery temp: 36.8°C (register 3176) ✓ - Battery power registers 3178-3180: MISSING on this hardware ✗ ROOT CAUSES: 1. Naming mismatch: Code looks for 'charge_power_low' but MOD profile had 'battery_charge_power_low' → registers not found → zero values 2. Missing hardware: Registers 3178-3180 don't exist on some MOD inverters 3. Missing field: battery_current was in register map but not in dataclass FIXES: 1. Renamed MOD battery power registers to match expected naming: - battery_discharge_power_low → discharge_power_low - battery_charge_power_low → charge_power_low 2. Added battery_current field to GrowattData dataclass 3. Enhanced _read_battery_data() to: - Read battery_current from register 3170 - Fallback to calculate power from V×I when registers missing: * charge_power = V × |I| when current < 0 (charging) * discharge_power = V × I when current > 0 (discharging) 4. Updated battery_current sensor condition to show when battery_voltage > 0 5. Added documentation notes about missing registers on some MOD hardware RESULT: Battery sensors now display correct values from registers. When power registers (3178-3181) are missing, power is calculated from voltage × current.
1 parent 796ba80 commit 7b73fc3

3 files changed

Lines changed: 31 additions & 14 deletions

File tree

custom_components/growatt_modbus/growatt_modbus.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class GrowattData:
100100

101101
# Battery (storage/hybrid models)
102102
battery_voltage: float = 0.0 # V
103+
battery_current: float = 0.0 # A (signed: +discharge, -charge)
103104
battery_soc: float = 0.0 # %
104105
battery_temp: float = 0.0 # °C
105106
charge_power: float = 0.0 # W
@@ -658,36 +659,50 @@ def _read_battery_data(self, data: GrowattData) -> None:
658659
if addr:
659660
data.battery_voltage = self._get_register_value(addr) or 0.0
660661
logger.debug(f"Battery voltage from reg {addr}: {data.battery_voltage}V")
661-
662+
663+
# Battery current (signed: positive=discharge, negative=charge)
664+
addr = self._find_register_by_name('battery_current')
665+
if addr:
666+
data.battery_current = self._get_register_value(addr) or 0.0
667+
logger.debug(f"Battery current from reg {addr}: {data.battery_current}A")
668+
662669
# Battery SOC
663670
addr = self._find_register_by_name('battery_soc')
664671
if addr:
665672
data.battery_soc = self._get_register_value(addr) or 0.0
666673
logger.debug(f"Battery SOC from reg {addr}: {data.battery_soc}%")
667-
674+
668675
# Battery temperature
669676
addr = self._find_register_by_name('battery_temp')
670677
if addr:
671678
data.battery_temp = self._get_register_value(addr) or 0.0
672679
logger.debug(f"Battery temp from reg {addr}: {data.battery_temp}°C")
673-
674-
# Charge power
680+
681+
# Charge power (try to read from registers first)
675682
addr = self._find_register_by_name('charge_power_low')
676683
if addr:
677684
raw_low = self._register_cache.get(addr, 0)
678685
pair_addr = self._find_register_by_name('charge_power_high')
679686
raw_high = self._register_cache.get(pair_addr, 0) if pair_addr else 0
680687
data.charge_power = self._get_register_value(addr) or 0.0
681688
logger.debug(f"Charge power: HIGH={raw_high} (reg {pair_addr}), LOW={raw_low} (reg {addr}) → {data.charge_power}W")
682-
683-
# Discharge power
689+
elif data.battery_voltage > 0 and data.battery_current < 0:
690+
# Fallback: Calculate from V×I when charging (negative current)
691+
data.charge_power = data.battery_voltage * abs(data.battery_current)
692+
logger.debug(f"Charge power (calculated): {data.battery_voltage}V × {abs(data.battery_current)}A = {data.charge_power}W")
693+
694+
# Discharge power (try to read from registers first)
684695
addr = self._find_register_by_name('discharge_power_low')
685696
if addr:
686697
raw_low = self._register_cache.get(addr, 0)
687698
pair_addr = self._find_register_by_name('discharge_power_high')
688699
raw_high = self._register_cache.get(pair_addr, 0) if pair_addr else 0
689700
data.discharge_power = self._get_register_value(addr) or 0.0
690701
logger.debug(f"Discharge power: HIGH={raw_high} (reg {pair_addr}), LOW={raw_low} (reg {addr}) → {data.discharge_power}W")
702+
elif data.battery_voltage > 0 and data.battery_current > 0:
703+
# Fallback: Calculate from V×I when discharging (positive current)
704+
data.discharge_power = data.battery_voltage * data.battery_current
705+
logger.debug(f"Discharge power (calculated): {data.battery_voltage}V × {data.battery_current}A = {data.discharge_power}W")
691706

692707
# Charge energy today
693708
addr = self._find_register_by_name('charge_energy_today_low')
@@ -726,7 +741,7 @@ def _read_battery_data(self, data: GrowattData) -> None:
726741
logger.debug(f"Discharge energy total: HIGH={raw_high} (reg {pair_addr}), LOW={raw_low} (reg {addr}) → {data.discharge_energy_total} kWh")
727742

728743
if data.battery_voltage > 0:
729-
logger.info(f"Battery summary: {data.battery_voltage}V, {data.battery_soc}%, {data.battery_temp}°C, Charge={data.charge_power}W, Discharge={data.discharge_power}W")
744+
logger.info(f"Battery summary: {data.battery_voltage}V, {data.battery_current}A, {data.battery_soc}%, {data.battery_temp}°C, Charge={data.charge_power}W, Discharge={data.discharge_power}W")
730745

731746
except Exception as e:
732747
logger.debug(f"Battery data not available: {e}")

custom_components/growatt_modbus/profiles/mod.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,14 @@
123123
3170: {'name': 'battery_current', 'scale': 0.1, 'unit': 'A', 'signed': True},
124124
3171: {'name': 'battery_soc', 'scale': 1, 'unit': '%'},
125125
3176: {'name': 'battery_temp', 'scale': 0.1, 'unit': '°C'},
126-
127-
# Battery Power (32-bit)
128-
3178: {'name': 'battery_discharge_power_high', 'scale': 1, 'unit': '', 'pair': 3179},
129-
3179: {'name': 'battery_discharge_power_low', 'scale': 1, 'unit': '', 'pair': 3178, 'combined_scale': 0.1, 'combined_unit': 'W'},
130-
3180: {'name': 'battery_charge_power_high', 'scale': 1, 'unit': '', 'pair': 3181},
131-
3181: {'name': 'battery_charge_power_low', 'scale': 1, 'unit': '', 'pair': 3180, 'combined_scale': 0.1, 'combined_unit': 'W'},
126+
127+
# NOTE: Registers 3178-3180 don't exist on some MOD hardware
128+
# If your inverter doesn't have these, battery power will be calculated from V×I
129+
# Battery Power (32-bit) - OPTIONAL, may not exist on all MOD hardware
130+
3178: {'name': 'discharge_power_high', 'scale': 1, 'unit': '', 'pair': 3179},
131+
3179: {'name': 'discharge_power_low', 'scale': 1, 'unit': '', 'pair': 3178, 'combined_scale': 0.1, 'combined_unit': 'W'},
132+
3180: {'name': 'charge_power_high', 'scale': 1, 'unit': '', 'pair': 3181},
133+
3181: {'name': 'charge_power_low', 'scale': 1, 'unit': '', 'pair': 3180, 'combined_scale': 0.1, 'combined_unit': 'W'},
132134
},
133135
'holding_registers': {
134136
# Basic control

custom_components/growatt_modbus/sensor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@
450450
"state_class": SensorStateClass.MEASUREMENT,
451451
"unit": UnitOfElectricCurrent.AMPERE,
452452
"attr": "battery_current",
453-
"condition": lambda data: hasattr(data, 'battery_current') and data.battery_current > 0,
453+
"condition": lambda data: hasattr(data, 'battery_current') and data.battery_voltage > 0,
454454
},
455455
"battery_soc": {
456456
"name": "Battery SOC",

0 commit comments

Comments
 (0)