@@ -410,6 +410,7 @@ def read_all_data(self) -> Optional[GrowattData]:
410410 has_base_range = any (0 <= addr < 1000 for addr in addresses )
411411 has_storage_range = any (1000 <= addr < 2000 for addr in addresses )
412412 has_3000_range = any (3000 <= addr < 4000 for addr in addresses )
413+ has_31000_range = any (31000 <= addr < 32000 for addr in addresses )
413414
414415 # Read base range (0-124) if needed - SPH models
415416 if has_base_range :
@@ -435,18 +436,31 @@ def read_all_data(self) -> Optional[GrowattData]:
435436 for i , value in enumerate (registers ):
436437 self ._register_cache [1000 + i ] = value
437438
438- # Read 3000 range if needed - MIN models
439+ # Read 3000 range if needed - MIN/MOD models
439440 if has_3000_range :
440- logger .debug ("Reading 3000 range (3000-3110)" )
441- registers = self .read_input_registers (3000 , 111 )
441+ logger .debug ("Reading 3000 range (3000-3250)" )
442+ # Extended range to cover MOD battery registers up to 3250
443+ registers = self .read_input_registers (3000 , 251 )
442444 if registers is None :
443445 logger .error ("Failed to read main input register block" )
444446 return None
445-
447+
446448 # Populate cache
447449 for i , value in enumerate (registers ):
448450 self ._register_cache [3000 + i ] = value
449-
451+
452+ # Read 31000 range if needed - MOD extended battery/BMS range
453+ if has_31000_range :
454+ logger .debug ("Reading 31000 range (31100-31300)" )
455+ registers = self .read_input_registers (31100 , 201 )
456+ if registers is None :
457+ logger .warning ("Failed to read extended battery register block (31100+)" )
458+ # Don't return None - continue with what we have
459+ else :
460+ # Populate cache
461+ for i , value in enumerate (registers ):
462+ self ._register_cache [31100 + i ] = value
463+
450464 # Now extract values using the register map
451465 try :
452466 # Status
@@ -678,31 +692,53 @@ def _read_battery_data(self, data: GrowattData) -> None:
678692 data .battery_temp = self ._get_register_value (addr ) or 0.0
679693 logger .debug (f"Battery temp from reg { addr } : { data .battery_temp } °C" )
680694
681- # Charge power (try to read from registers first)
682- addr = self ._find_register_by_name ('charge_power_low' )
695+ # Battery power (signed: positive=charging, negative=discharging)
696+ # Try new signed battery_power register first (MOD series @ 31126)
697+ addr = self ._find_register_by_name ('battery_power_low' )
683698 if addr :
684699 raw_low = self ._register_cache .get (addr , 0 )
685- pair_addr = self ._find_register_by_name ('charge_power_high ' )
700+ pair_addr = self ._find_register_by_name ('battery_power_high ' )
686701 raw_high = self ._register_cache .get (pair_addr , 0 ) if pair_addr else 0
687- data .charge_power = self ._get_register_value (addr ) or 0.0
688- logger .debug (f"Charge power: HIGH={ raw_high } (reg { pair_addr } ), LOW={ raw_low } (reg { addr } ) → { data .charge_power } W" )
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" )
702+ battery_power = self ._get_register_value (addr ) or 0.0
703+ logger .debug (f"Battery power (signed): HIGH={ raw_high } (reg { pair_addr } ), LOW={ raw_low } (reg { addr } ) → { battery_power } W" )
693704
694- # Discharge power (try to read from registers first)
695- addr = self ._find_register_by_name ('discharge_power_low' )
696- if addr :
697- raw_low = self ._register_cache .get (addr , 0 )
698- pair_addr = self ._find_register_by_name ('discharge_power_high' )
699- raw_high = self ._register_cache .get (pair_addr , 0 ) if pair_addr else 0
700- data .discharge_power = self ._get_register_value (addr ) or 0.0
701- 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" )
705+ # Split into charge/discharge based on sign
706+ if battery_power > 0 :
707+ data .charge_power = battery_power
708+ data .discharge_power = 0.0
709+ logger .debug (f" → Charging: { data .charge_power } W" )
710+ elif battery_power < 0 :
711+ data .charge_power = 0.0
712+ data .discharge_power = abs (battery_power )
713+ logger .debug (f" → Discharging: { data .discharge_power } W" )
714+ else :
715+ data .charge_power = 0.0
716+ data .discharge_power = 0.0
717+ else :
718+ # Fallback: Try old separate charge/discharge registers (SPH series)
719+ addr = self ._find_register_by_name ('charge_power_low' )
720+ if addr :
721+ raw_low = self ._register_cache .get (addr , 0 )
722+ pair_addr = self ._find_register_by_name ('charge_power_high' )
723+ raw_high = self ._register_cache .get (pair_addr , 0 ) if pair_addr else 0
724+ data .charge_power = self ._get_register_value (addr ) or 0.0
725+ logger .debug (f"Charge power: HIGH={ raw_high } (reg { pair_addr } ), LOW={ raw_low } (reg { addr } ) → { data .charge_power } W" )
726+ elif data .battery_voltage > 0 and data .battery_current < 0 :
727+ # Fallback: Calculate from V×I when charging (negative current)
728+ data .charge_power = data .battery_voltage * abs (data .battery_current )
729+ logger .debug (f"Charge power (calculated): { data .battery_voltage } V × { abs (data .battery_current )} A = { data .charge_power } W" )
730+
731+ addr = self ._find_register_by_name ('discharge_power_low' )
732+ if addr :
733+ raw_low = self ._register_cache .get (addr , 0 )
734+ pair_addr = self ._find_register_by_name ('discharge_power_high' )
735+ raw_high = self ._register_cache .get (pair_addr , 0 ) if pair_addr else 0
736+ data .discharge_power = self ._get_register_value (addr ) or 0.0
737+ logger .debug (f"Discharge power: HIGH={ raw_high } (reg { pair_addr } ), LOW={ raw_low } (reg { addr } ) → { data .discharge_power } W" )
738+ elif data .battery_voltage > 0 and data .battery_current > 0 :
739+ # Fallback: Calculate from V×I when discharging (positive current)
740+ data .discharge_power = data .battery_voltage * data .battery_current
741+ logger .debug (f"Discharge power (calculated): { data .battery_voltage } V × { data .battery_current } A = { data .discharge_power } W" )
706742
707743 # Charge energy today
708744 addr = self ._find_register_by_name ('charge_energy_today_low' )
0 commit comments