Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions custom_components/growatt_modbus/device_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@
}

THREE_PHASE_SENSORS: Set[str] = {
"ac_voltage_r", "ac_voltage_s", "ac_voltage_t", # Phase voltages
"ac_voltage_rs", "ac_voltage_st", "ac_voltage_tr", # Line-to-line voltages
"ac_current_r", "ac_current_s", "ac_current_t",
"ac_power_r", "ac_power_s", "ac_power_t",
"ac_current_r", "ac_current_s", "ac_current_t", # Phase currents
"ac_power_r", "ac_power_s", "ac_power_t", # Phase powers
"ac_frequency",
}

Expand Down
73 changes: 69 additions & 4 deletions custom_components/growatt_modbus/growatt_modbus.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,27 @@ class GrowattData:
pv3_power: float = 0.0 # W
pv_total_power: float = 0.0 # W

# AC Output
# AC Output (generic - usually Phase R for 3-phase)
ac_voltage: float = 0.0 # V
ac_current: float = 0.0 # A
ac_power: float = 0.0 # W
ac_frequency: float = 0.0 # Hz

# Three-Phase AC Output (individual phases)
ac_voltage_r: float = 0.0 # V (Phase R/L1)
ac_current_r: float = 0.0 # A (Phase R/L1)
ac_power_r: float = 0.0 # W (Phase R/L1)
ac_voltage_s: float = 0.0 # V (Phase S/L2)
ac_current_s: float = 0.0 # A (Phase S/L2)
ac_power_s: float = 0.0 # W (Phase S/L2)
ac_voltage_t: float = 0.0 # V (Phase T/L3)
ac_current_t: float = 0.0 # A (Phase T/L3)
ac_power_t: float = 0.0 # W (Phase T/L3)

# Line-to-Line Voltages (3-phase only)
ac_voltage_rs: float = 0.0 # V
ac_voltage_st: float = 0.0 # V
ac_voltage_tr: float = 0.0 # V

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

# AC Output
# AC Output (generic - will use Phase R via alias for 3-phase)
ac_voltage_addr = self._find_register_by_name('ac_voltage')
ac_current_addr = self._find_register_by_name('ac_current')
ac_power_addr = self._find_register_by_name('ac_power_low')
ac_freq_addr = self._find_register_by_name('ac_frequency')

if ac_voltage_addr:
data.ac_voltage = self._get_register_value(ac_voltage_addr) or 0.0
if ac_current_addr:
Expand All @@ -510,6 +526,51 @@ def read_all_data(self) -> Optional[GrowattData]:
data.ac_power = self._get_register_value(ac_power_addr) or 0.0
if ac_freq_addr:
data.ac_frequency = self._get_register_value(ac_freq_addr) or 0.0

# Three-Phase AC Output (individual phases)
# Phase R
ac_voltage_r_addr = self._find_register_by_name('ac_voltage_r')
ac_current_r_addr = self._find_register_by_name('ac_current_r')
ac_power_r_addr = self._find_register_by_name('ac_power_r_low')
if ac_voltage_r_addr:
data.ac_voltage_r = self._get_register_value(ac_voltage_r_addr) or 0.0
if ac_current_r_addr:
data.ac_current_r = self._get_register_value(ac_current_r_addr) or 0.0
if ac_power_r_addr:
data.ac_power_r = self._get_register_value(ac_power_r_addr) or 0.0

# Phase S
ac_voltage_s_addr = self._find_register_by_name('ac_voltage_s')
ac_current_s_addr = self._find_register_by_name('ac_current_s')
ac_power_s_addr = self._find_register_by_name('ac_power_s_low')
if ac_voltage_s_addr:
data.ac_voltage_s = self._get_register_value(ac_voltage_s_addr) or 0.0
if ac_current_s_addr:
data.ac_current_s = self._get_register_value(ac_current_s_addr) or 0.0
if ac_power_s_addr:
data.ac_power_s = self._get_register_value(ac_power_s_addr) or 0.0

# Phase T
ac_voltage_t_addr = self._find_register_by_name('ac_voltage_t')
ac_current_t_addr = self._find_register_by_name('ac_current_t')
ac_power_t_addr = self._find_register_by_name('ac_power_t_low')
if ac_voltage_t_addr:
data.ac_voltage_t = self._get_register_value(ac_voltage_t_addr) or 0.0
if ac_current_t_addr:
data.ac_current_t = self._get_register_value(ac_current_t_addr) or 0.0
if ac_power_t_addr:
data.ac_power_t = self._get_register_value(ac_power_t_addr) or 0.0

# Line-to-Line Voltages
ac_voltage_rs_addr = self._find_register_by_name('line_voltage_rs')
ac_voltage_st_addr = self._find_register_by_name('line_voltage_st')
ac_voltage_tr_addr = self._find_register_by_name('line_voltage_tr')
if ac_voltage_rs_addr:
data.ac_voltage_rs = self._get_register_value(ac_voltage_rs_addr) or 0.0
if ac_voltage_st_addr:
data.ac_voltage_st = self._get_register_value(ac_voltage_st_addr) or 0.0
if ac_voltage_tr_addr:
data.ac_voltage_tr = self._get_register_value(ac_voltage_tr_addr) or 0.0

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


def _find_register_by_name(self, name: str) -> Optional[int]:
"""Find register address by its name"""
"""Find register address by its name or alias"""
input_regs = self.register_map['input_registers']
for addr, reg_info in input_regs.items():
# Check exact name match
if reg_info['name'] == name:
return addr
# Check alias match (for 3-phase compatibility)
if reg_info.get('alias') == name:
return addr
return None

def _read_energy_breakdown(self, data: GrowattData) -> None:
Expand Down
13 changes: 7 additions & 6 deletions custom_components/growatt_modbus/profiles/mod.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@
# === AC OUTPUT - THREE PHASE ===
# Grid Frequency (shared across all phases)
37: {'name': 'ac_frequency', 'scale': 0.01, 'unit': 'Hz', 'desc': 'AC output frequency'},

# Phase R (L1) - AC Output
38: {'name': 'ac_voltage_r', 'scale': 0.1, 'unit': 'V', 'desc': 'Phase R AC voltage'},
39: {'name': 'ac_current_r', 'scale': 0.1, 'unit': 'A', 'desc': 'Phase R AC current'},
40: {'name': 'ac_power_r_high', 'scale': 1, 'unit': '', 'pair': 41},
41: {'name': 'ac_power_r_low', 'scale': 1, 'unit': '', 'pair': 40, 'combined_scale': 0.1, 'combined_unit': 'VA'},

# Generic AC aliases (point to Phase R for compatibility with generic code)
# These allow the standard ac_voltage/current/power fields to work
38: {'name': 'ac_voltage_r', 'scale': 0.1, 'unit': 'V', 'desc': 'Phase R AC voltage', 'alias': 'ac_voltage'},
39: {'name': 'ac_current_r', 'scale': 0.1, 'unit': 'A', 'desc': 'Phase R AC current', 'alias': 'ac_current'},
40: {'name': 'ac_power_r_high', 'scale': 1, 'unit': '', 'pair': 41, 'alias': 'ac_power_high'},
41: {'name': 'ac_power_r_low', 'scale': 1, 'unit': '', 'pair': 40, 'combined_scale': 0.1, 'combined_unit': 'VA', 'alias': 'ac_power_low'},

# Phase S (L2) - AC Output
42: {'name': 'ac_voltage_s', 'scale': 0.1, 'unit': 'V', 'desc': 'Phase S AC voltage'},
Expand Down
10 changes: 5 additions & 5 deletions custom_components/growatt_modbus/profiles/sph_tl3.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
# AC Grid Frequency
37: {'name': 'ac_frequency', 'scale': 0.01, 'unit': 'Hz'},

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

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