Skip to content

Commit 5b78a61

Browse files
committed
Fix 3-phase AC sensors showing zero/unknown on MOD and SPH TL3
PROBLEM: User reported 3-phase AC voltage, current, and power sensors showing as "unknown" or not appearing at all on MOD 6000-15000TL3-XH inverter. Register scan showed valid AC data but sensors weren't created. ROOT CAUSES: 1. Register name mismatch: - Profiles defined: 'ac_voltage_r', 'ac_current_r', 'ac_power_r_low' - Code looked for: 'ac_voltage', 'ac_current', 'ac_power_low' - Result: Registers not found → zero values 2. Missing dataclass fields: - GrowattData only had generic ac_voltage/current/power - No individual phase fields (ac_voltage_r/s/t, etc.) 3. Missing sensors from profile: - THREE_PHASE_SENSORS didn't include 'ac_voltage_r/s/t' - Sensors defined but not enabled 4. No code to read individual phases: - Only generic AC reading code existed - Individual 3-phase registers never accessed FIXES: 1. Enhanced register lookup to support aliases: - _find_register_by_name() now checks both 'name' and 'alias' - Allows phase-specific registers to be found by generic names 2. Added generic aliases in profiles (MOD and SPH TL3): - ac_voltage_r → alias 'ac_voltage' - ac_current_r → alias 'ac_current' - ac_power_r_low → alias 'ac_power_low' - Phase R serves as "main" AC output for compatibility 3. Added 3-phase fields to GrowattData dataclass: - ac_voltage_r/s/t, ac_current_r/s/t, ac_power_r/s/t - ac_voltage_rs/st/tr (line-to-line) 4. Added code to read individual 3-phase registers: - Reads all phases R, S, T individually - Reads line-to-line voltages - Populates all phase-specific dataclass fields 5. Updated THREE_PHASE_SENSORS: - Added 'ac_voltage_r', 'ac_voltage_s', 'ac_voltage_t' - Now all phase sensors are enabled RESULT: - Generic AC sensors (ac_voltage/current/power) now work via Phase R alias - Individual phase sensors (R/S/T) now populate with correct values - All 3-phase inverters (MOD, SPH TL3) get full 3-phase monitoring - Backwards compatible with existing configs
1 parent 7b73fc3 commit 5b78a61

4 files changed

Lines changed: 84 additions & 17 deletions

File tree

custom_components/growatt_modbus/device_profiles.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,10 @@
5959
}
6060

6161
THREE_PHASE_SENSORS: Set[str] = {
62+
"ac_voltage_r", "ac_voltage_s", "ac_voltage_t", # Phase voltages
6263
"ac_voltage_rs", "ac_voltage_st", "ac_voltage_tr", # Line-to-line voltages
63-
"ac_current_r", "ac_current_s", "ac_current_t",
64-
"ac_power_r", "ac_power_s", "ac_power_t",
64+
"ac_current_r", "ac_current_s", "ac_current_t", # Phase currents
65+
"ac_power_r", "ac_power_s", "ac_power_t", # Phase powers
6566
"ac_frequency",
6667
}
6768

custom_components/growatt_modbus/growatt_modbus.py

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,27 @@ class GrowattData:
7272
pv3_power: float = 0.0 # W
7373
pv_total_power: float = 0.0 # W
7474

75-
# AC Output
75+
# AC Output (generic - usually Phase R for 3-phase)
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
8096

8197
# Power Flow (storage/hybrid models)
8298
power_to_user: float = 0.0 # W
@@ -496,12 +512,12 @@ def read_all_data(self) -> Optional[GrowattData]:
496512
# Calculate from strings if not available
497513
data.pv_total_power = data.pv1_power + data.pv2_power + data.pv3_power
498514

499-
# AC Output
515+
# AC Output (generic - will use Phase R via alias for 3-phase)
500516
ac_voltage_addr = self._find_register_by_name('ac_voltage')
501517
ac_current_addr = self._find_register_by_name('ac_current')
502518
ac_power_addr = self._find_register_by_name('ac_power_low')
503519
ac_freq_addr = self._find_register_by_name('ac_frequency')
504-
520+
505521
if ac_voltage_addr:
506522
data.ac_voltage = self._get_register_value(ac_voltage_addr) or 0.0
507523
if ac_current_addr:
@@ -510,6 +526,51 @@ def read_all_data(self) -> Optional[GrowattData]:
510526
data.ac_power = self._get_register_value(ac_power_addr) or 0.0
511527
if ac_freq_addr:
512528
data.ac_frequency = self._get_register_value(ac_freq_addr) or 0.0
529+
530+
# Three-Phase AC Output (individual phases)
531+
# Phase R
532+
ac_voltage_r_addr = self._find_register_by_name('ac_voltage_r')
533+
ac_current_r_addr = self._find_register_by_name('ac_current_r')
534+
ac_power_r_addr = self._find_register_by_name('ac_power_r_low')
535+
if ac_voltage_r_addr:
536+
data.ac_voltage_r = self._get_register_value(ac_voltage_r_addr) or 0.0
537+
if ac_current_r_addr:
538+
data.ac_current_r = self._get_register_value(ac_current_r_addr) or 0.0
539+
if ac_power_r_addr:
540+
data.ac_power_r = self._get_register_value(ac_power_r_addr) or 0.0
541+
542+
# Phase S
543+
ac_voltage_s_addr = self._find_register_by_name('ac_voltage_s')
544+
ac_current_s_addr = self._find_register_by_name('ac_current_s')
545+
ac_power_s_addr = self._find_register_by_name('ac_power_s_low')
546+
if ac_voltage_s_addr:
547+
data.ac_voltage_s = self._get_register_value(ac_voltage_s_addr) or 0.0
548+
if ac_current_s_addr:
549+
data.ac_current_s = self._get_register_value(ac_current_s_addr) or 0.0
550+
if ac_power_s_addr:
551+
data.ac_power_s = self._get_register_value(ac_power_s_addr) or 0.0
552+
553+
# Phase T
554+
ac_voltage_t_addr = self._find_register_by_name('ac_voltage_t')
555+
ac_current_t_addr = self._find_register_by_name('ac_current_t')
556+
ac_power_t_addr = self._find_register_by_name('ac_power_t_low')
557+
if ac_voltage_t_addr:
558+
data.ac_voltage_t = self._get_register_value(ac_voltage_t_addr) or 0.0
559+
if ac_current_t_addr:
560+
data.ac_current_t = self._get_register_value(ac_current_t_addr) or 0.0
561+
if ac_power_t_addr:
562+
data.ac_power_t = self._get_register_value(ac_power_t_addr) or 0.0
563+
564+
# Line-to-Line Voltages
565+
ac_voltage_rs_addr = self._find_register_by_name('line_voltage_rs')
566+
ac_voltage_st_addr = self._find_register_by_name('line_voltage_st')
567+
ac_voltage_tr_addr = self._find_register_by_name('line_voltage_tr')
568+
if ac_voltage_rs_addr:
569+
data.ac_voltage_rs = self._get_register_value(ac_voltage_rs_addr) or 0.0
570+
if ac_voltage_st_addr:
571+
data.ac_voltage_st = self._get_register_value(ac_voltage_st_addr) or 0.0
572+
if ac_voltage_tr_addr:
573+
data.ac_voltage_tr = self._get_register_value(ac_voltage_tr_addr) or 0.0
513574

514575
# Power Flow (if available - storage/hybrid models)
515576
power_to_user_addr = self._find_register_by_name('power_to_user_low')
@@ -611,11 +672,15 @@ def write_register(self, register: int, value: int) -> bool:
611672

612673

613674
def _find_register_by_name(self, name: str) -> Optional[int]:
614-
"""Find register address by its name"""
675+
"""Find register address by its name or alias"""
615676
input_regs = self.register_map['input_registers']
616677
for addr, reg_info in input_regs.items():
678+
# Check exact name match
617679
if reg_info['name'] == name:
618680
return addr
681+
# Check alias match (for 3-phase compatibility)
682+
if reg_info.get('alias') == name:
683+
return addr
619684
return None
620685

621686
def _read_energy_breakdown(self, data: GrowattData) -> None:

custom_components/growatt_modbus/profiles/mod.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@
3737
# === AC OUTPUT - THREE PHASE ===
3838
# Grid Frequency (shared across all phases)
3939
37: {'name': 'ac_frequency', 'scale': 0.01, 'unit': 'Hz', 'desc': 'AC output frequency'},
40-
41-
# Phase R (L1) - AC Output
42-
38: {'name': 'ac_voltage_r', 'scale': 0.1, 'unit': 'V', 'desc': 'Phase R AC voltage'},
43-
39: {'name': 'ac_current_r', 'scale': 0.1, 'unit': 'A', 'desc': 'Phase R AC current'},
44-
40: {'name': 'ac_power_r_high', 'scale': 1, 'unit': '', 'pair': 41},
45-
41: {'name': 'ac_power_r_low', 'scale': 1, 'unit': '', 'pair': 40, 'combined_scale': 0.1, 'combined_unit': 'VA'},
40+
41+
# Generic AC aliases (point to Phase R for compatibility with generic code)
42+
# These allow the standard ac_voltage/current/power fields to work
43+
38: {'name': 'ac_voltage_r', 'scale': 0.1, 'unit': 'V', 'desc': 'Phase R AC voltage', 'alias': 'ac_voltage'},
44+
39: {'name': 'ac_current_r', 'scale': 0.1, 'unit': 'A', 'desc': 'Phase R AC current', 'alias': 'ac_current'},
45+
40: {'name': 'ac_power_r_high', 'scale': 1, 'unit': '', 'pair': 41, 'alias': 'ac_power_high'},
46+
41: {'name': 'ac_power_r_low', 'scale': 1, 'unit': '', 'pair': 40, 'combined_scale': 0.1, 'combined_unit': 'VA', 'alias': 'ac_power_low'},
4647

4748
# Phase S (L2) - AC Output
4849
42: {'name': 'ac_voltage_s', 'scale': 0.1, 'unit': 'V', 'desc': 'Phase S AC voltage'},

custom_components/growatt_modbus/profiles/sph_tl3.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@
3333
# AC Grid Frequency
3434
37: {'name': 'ac_frequency', 'scale': 0.01, 'unit': 'Hz'},
3535

36-
# Three-Phase AC Output - Phase R
37-
38: {'name': 'ac_voltage_r', 'scale': 0.1, 'unit': 'V', 'desc': 'Phase R voltage'},
38-
39: {'name': 'ac_current_r', 'scale': 0.1, 'unit': 'A', 'desc': 'Phase R current'},
39-
40: {'name': 'ac_power_r_high', 'scale': 1, 'unit': '', 'pair': 41},
40-
41: {'name': 'ac_power_r_low', 'scale': 1, 'unit': '', 'pair': 40, 'combined_scale': 0.1, 'combined_unit': 'W'},
36+
# Three-Phase AC Output - Phase R (with generic aliases for compatibility)
37+
38: {'name': 'ac_voltage_r', 'scale': 0.1, 'unit': 'V', 'desc': 'Phase R voltage', 'alias': 'ac_voltage'},
38+
39: {'name': 'ac_current_r', 'scale': 0.1, 'unit': 'A', 'desc': 'Phase R current', 'alias': 'ac_current'},
39+
40: {'name': 'ac_power_r_high', 'scale': 1, 'unit': '', 'pair': 41, 'alias': 'ac_power_high'},
40+
41: {'name': 'ac_power_r_low', 'scale': 1, 'unit': '', 'pair': 40, 'combined_scale': 0.1, 'combined_unit': 'W', 'alias': 'ac_power_low'},
4141

4242
# Three-Phase AC Output - Phase S
4343
42: {'name': 'ac_voltage_s', 'scale': 0.1, 'unit': 'V', 'desc': 'Phase S voltage'},

0 commit comments

Comments
 (0)