@@ -72,27 +72,11 @@ class GrowattData:
7272 pv3_power : float = 0.0 # W
7373 pv_total_power : float = 0.0 # W
7474
75- # AC Output (generic - usually Phase R for 3-phase)
75+ # AC Output
7676 ac_voltage : float = 0.0 # V
7777 ac_current : float = 0.0 # A
7878 ac_power : float = 0.0 # W
7979 ac_frequency : float = 0.0 # Hz
80-
81- # Three-Phase AC Output (individual phases)
82- ac_voltage_r : float = 0.0 # V (Phase R/L1)
83- ac_current_r : float = 0.0 # A (Phase R/L1)
84- ac_power_r : float = 0.0 # W (Phase R/L1)
85- ac_voltage_s : float = 0.0 # V (Phase S/L2)
86- ac_current_s : float = 0.0 # A (Phase S/L2)
87- ac_power_s : float = 0.0 # W (Phase S/L2)
88- ac_voltage_t : float = 0.0 # V (Phase T/L3)
89- ac_current_t : float = 0.0 # A (Phase T/L3)
90- ac_power_t : float = 0.0 # W (Phase T/L3)
91-
92- # Line-to-Line Voltages (3-phase only)
93- ac_voltage_rs : float = 0.0 # V
94- ac_voltage_st : float = 0.0 # V
95- ac_voltage_tr : float = 0.0 # V
9680
9781 # Power Flow (storage/hybrid models)
9882 power_to_user : float = 0.0 # W
@@ -426,7 +410,6 @@ def read_all_data(self) -> Optional[GrowattData]:
426410 has_base_range = any (0 <= addr < 1000 for addr in addresses )
427411 has_storage_range = any (1000 <= addr < 2000 for addr in addresses )
428412 has_3000_range = any (3000 <= addr < 4000 for addr in addresses )
429- has_31000_range = any (31000 <= addr < 32000 for addr in addresses )
430413
431414 # Read base range (0-124) if needed - SPH models
432415 if has_base_range :
@@ -452,31 +435,18 @@ def read_all_data(self) -> Optional[GrowattData]:
452435 for i , value in enumerate (registers ):
453436 self ._register_cache [1000 + i ] = value
454437
455- # Read 3000 range if needed - MIN/MOD models
438+ # Read 3000 range if needed - MIN models
456439 if has_3000_range :
457- logger .debug ("Reading 3000 range (3000-3250)" )
458- # Extended range to cover MOD battery registers up to 3250
459- registers = self .read_input_registers (3000 , 251 )
440+ logger .debug ("Reading 3000 range (3000-3110)" )
441+ registers = self .read_input_registers (3000 , 111 )
460442 if registers is None :
461443 logger .error ("Failed to read main input register block" )
462444 return None
463-
445+
464446 # Populate cache
465447 for i , value in enumerate (registers ):
466448 self ._register_cache [3000 + i ] = value
467-
468- # Read 31000 range if needed - MOD extended battery/BMS range
469- if has_31000_range :
470- logger .debug ("Reading 31000 range (31100-31300)" )
471- registers = self .read_input_registers (31100 , 201 )
472- if registers is None :
473- logger .warning ("Failed to read extended battery register block (31100+)" )
474- # Don't return None - continue with what we have
475- else :
476- # Populate cache
477- for i , value in enumerate (registers ):
478- self ._register_cache [31100 + i ] = value
479-
449+
480450 # Now extract values using the register map
481451 try :
482452 # Status
@@ -526,12 +496,12 @@ def read_all_data(self) -> Optional[GrowattData]:
526496 # Calculate from strings if not available
527497 data .pv_total_power = data .pv1_power + data .pv2_power + data .pv3_power
528498
529- # AC Output (generic - will use Phase R via alias for 3-phase)
499+ # AC Output
530500 ac_voltage_addr = self ._find_register_by_name ('ac_voltage' )
531501 ac_current_addr = self ._find_register_by_name ('ac_current' )
532502 ac_power_addr = self ._find_register_by_name ('ac_power_low' )
533503 ac_freq_addr = self ._find_register_by_name ('ac_frequency' )
534-
504+
535505 if ac_voltage_addr :
536506 data .ac_voltage = self ._get_register_value (ac_voltage_addr ) or 0.0
537507 if ac_current_addr :
@@ -540,51 +510,6 @@ def read_all_data(self) -> Optional[GrowattData]:
540510 data .ac_power = self ._get_register_value (ac_power_addr ) or 0.0
541511 if ac_freq_addr :
542512 data .ac_frequency = self ._get_register_value (ac_freq_addr ) or 0.0
543-
544- # Three-Phase AC Output (individual phases)
545- # Phase R
546- ac_voltage_r_addr = self ._find_register_by_name ('ac_voltage_r' )
547- ac_current_r_addr = self ._find_register_by_name ('ac_current_r' )
548- ac_power_r_addr = self ._find_register_by_name ('ac_power_r_low' )
549- if ac_voltage_r_addr :
550- data .ac_voltage_r = self ._get_register_value (ac_voltage_r_addr ) or 0.0
551- if ac_current_r_addr :
552- data .ac_current_r = self ._get_register_value (ac_current_r_addr ) or 0.0
553- if ac_power_r_addr :
554- data .ac_power_r = self ._get_register_value (ac_power_r_addr ) or 0.0
555-
556- # Phase S
557- ac_voltage_s_addr = self ._find_register_by_name ('ac_voltage_s' )
558- ac_current_s_addr = self ._find_register_by_name ('ac_current_s' )
559- ac_power_s_addr = self ._find_register_by_name ('ac_power_s_low' )
560- if ac_voltage_s_addr :
561- data .ac_voltage_s = self ._get_register_value (ac_voltage_s_addr ) or 0.0
562- if ac_current_s_addr :
563- data .ac_current_s = self ._get_register_value (ac_current_s_addr ) or 0.0
564- if ac_power_s_addr :
565- data .ac_power_s = self ._get_register_value (ac_power_s_addr ) or 0.0
566-
567- # Phase T
568- ac_voltage_t_addr = self ._find_register_by_name ('ac_voltage_t' )
569- ac_current_t_addr = self ._find_register_by_name ('ac_current_t' )
570- ac_power_t_addr = self ._find_register_by_name ('ac_power_t_low' )
571- if ac_voltage_t_addr :
572- data .ac_voltage_t = self ._get_register_value (ac_voltage_t_addr ) or 0.0
573- if ac_current_t_addr :
574- data .ac_current_t = self ._get_register_value (ac_current_t_addr ) or 0.0
575- if ac_power_t_addr :
576- data .ac_power_t = self ._get_register_value (ac_power_t_addr ) or 0.0
577-
578- # Line-to-Line Voltages
579- ac_voltage_rs_addr = self ._find_register_by_name ('line_voltage_rs' )
580- ac_voltage_st_addr = self ._find_register_by_name ('line_voltage_st' )
581- ac_voltage_tr_addr = self ._find_register_by_name ('line_voltage_tr' )
582- if ac_voltage_rs_addr :
583- data .ac_voltage_rs = self ._get_register_value (ac_voltage_rs_addr ) or 0.0
584- if ac_voltage_st_addr :
585- data .ac_voltage_st = self ._get_register_value (ac_voltage_st_addr ) or 0.0
586- if ac_voltage_tr_addr :
587- data .ac_voltage_tr = self ._get_register_value (ac_voltage_tr_addr ) or 0.0
588513
589514 # Power Flow (if available - storage/hybrid models)
590515 power_to_user_addr = self ._find_register_by_name ('power_to_user_low' )
@@ -686,15 +611,11 @@ def write_register(self, register: int, value: int) -> bool:
686611
687612
688613 def _find_register_by_name (self , name : str ) -> Optional [int ]:
689- """Find register address by its name or alias """
614+ """Find register address by its name"""
690615 input_regs = self .register_map ['input_registers' ]
691616 for addr , reg_info in input_regs .items ():
692- # Check exact name match
693617 if reg_info ['name' ] == name :
694618 return addr
695- # Check alias match (for 3-phase compatibility)
696- if reg_info .get ('alias' ) == name :
697- return addr
698619 return None
699620
700621 def _read_energy_breakdown (self , data : GrowattData ) -> None :
@@ -757,53 +678,31 @@ def _read_battery_data(self, data: GrowattData) -> None:
757678 data .battery_temp = self ._get_register_value (addr ) or 0.0
758679 logger .debug (f"Battery temp from reg { addr } : { data .battery_temp } °C" )
759680
760- # Battery power (signed: positive=charging, negative=discharging)
761- # Try new signed battery_power register first (MOD series @ 31126)
762- addr = self ._find_register_by_name ('battery_power_low' )
681+ # Charge power (try to read from registers first)
682+ addr = self ._find_register_by_name ('charge_power_low' )
763683 if addr :
764684 raw_low = self ._register_cache .get (addr , 0 )
765- pair_addr = self ._find_register_by_name ('battery_power_high ' )
685+ pair_addr = self ._find_register_by_name ('charge_power_high ' )
766686 raw_high = self ._register_cache .get (pair_addr , 0 ) if pair_addr else 0
767- battery_power = self ._get_register_value (addr ) or 0.0
768- logger .debug (f"Battery power (signed): HIGH={ raw_high } (reg { pair_addr } ), LOW={ raw_low } (reg { addr } ) → { battery_power } W" )
769-
770- # Split into charge/discharge based on sign
771- if battery_power > 0 :
772- data .charge_power = battery_power
773- data .discharge_power = 0.0
774- logger .debug (f" → Charging: { data .charge_power } W" )
775- elif battery_power < 0 :
776- data .charge_power = 0.0
777- data .discharge_power = abs (battery_power )
778- logger .debug (f" → Discharging: { data .discharge_power } W" )
779- else :
780- data .charge_power = 0.0
781- data .discharge_power = 0.0
782- else :
783- # Fallback: Try old separate charge/discharge registers (SPH series)
784- addr = self ._find_register_by_name ('charge_power_low' )
785- if addr :
786- raw_low = self ._register_cache .get (addr , 0 )
787- pair_addr = self ._find_register_by_name ('charge_power_high' )
788- raw_high = self ._register_cache .get (pair_addr , 0 ) if pair_addr else 0
789- data .charge_power = self ._get_register_value (addr ) or 0.0
790- logger .debug (f"Charge power: HIGH={ raw_high } (reg { pair_addr } ), LOW={ raw_low } (reg { addr } ) → { data .charge_power } W" )
791- elif data .battery_voltage > 0 and data .battery_current < 0 :
792- # Fallback: Calculate from V×I when charging (negative current)
793- data .charge_power = data .battery_voltage * abs (data .battery_current )
794- logger .debug (f"Charge power (calculated): { data .battery_voltage } V × { abs (data .battery_current )} A = { data .charge_power } W" )
795-
796- addr = self ._find_register_by_name ('discharge_power_low' )
797- if addr :
798- raw_low = self ._register_cache .get (addr , 0 )
799- pair_addr = self ._find_register_by_name ('discharge_power_high' )
800- raw_high = self ._register_cache .get (pair_addr , 0 ) if pair_addr else 0
801- data .discharge_power = self ._get_register_value (addr ) or 0.0
802- logger .debug (f"Discharge power: HIGH={ raw_high } (reg { pair_addr } ), LOW={ raw_low } (reg { addr } ) → { data .discharge_power } W" )
803- elif data .battery_voltage > 0 and data .battery_current > 0 :
804- # Fallback: Calculate from V×I when discharging (positive current)
805- data .discharge_power = data .battery_voltage * data .battery_current
806- logger .debug (f"Discharge power (calculated): { data .battery_voltage } V × { data .battery_current } A = { data .discharge_power } W" )
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" )
693+
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" )
807706
808707 # Charge energy today
809708 addr = self ._find_register_by_name ('charge_energy_today_low' )
0 commit comments