Skip to content

Commit 5ba3c5f

Browse files
authored
Sungrow Battery Readings improvements (#2713)
* Delete firmware.py * Read all currents together * Delete Firmware * Improve Register handling without Firmware * flake8 * flake8 * flake8 * flake8 * Create registers.py * Update registers.py * Update registers.py * Updated to ENUMs
1 parent ff20159 commit 5ba3c5f

5 files changed

Lines changed: 67 additions & 55 deletions

File tree

packages/modules/devices/sungrow/sungrow/bat.py

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
from modules.common.simcount import SimCounter
1111
from modules.common.store import get_bat_value_store
1212
from modules.devices.sungrow.sungrow.config import SungrowBatSetup, Sungrow
13-
from modules.devices.sungrow.sungrow.version import Version
14-
from modules.devices.sungrow.sungrow.firmware import Firmware
13+
from modules.devices.sungrow.sungrow.registers import RegMode
1514

1615
log = logging.getLogger(__name__)
1716

@@ -33,52 +32,70 @@ def initialize(self) -> None:
3332
self.store = get_bat_value_store(self.component_config.id)
3433
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
3534
self.last_mode = 'Undefined'
36-
self.firmware_check = self.check_firmware_register()
35+
self.register_check = self.detect_register_check()
3736

38-
def check_firmware_register(self) -> bool:
39-
if Firmware(self.device_config.configuration.firmware) == Firmware.v1:
40-
return False
37+
def detect_register_check(self) -> RegMode:
38+
# Battery register availability test
4139
unit = self.device_config.configuration.modbus_id
40+
4241
try:
4342
self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32,
4443
wordorder=Endian.Little, unit=unit)
45-
log.debug("Wechselrichter Firmware ist größer gleich 95.09")
46-
return True
44+
self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit)
45+
log.debug("Battery register check: using new_registers (5213/5630).")
46+
return RegMode.NEW_REGISTERS
47+
except Exception:
48+
pass
49+
50+
try:
51+
self.__tcp_client.read_input_registers(13000, ModbusDataType.UINT_16, unit=unit)
52+
log.debug("Battery register check: using old_registers (13021 + 13000 bits for sign).")
53+
return RegMode.OLD_REGISTERS
4754
except Exception:
48-
log.debug("Wechselrichter Firmware ist kleiner als 95.09")
49-
return False
55+
pass
56+
57+
log.debug("Battery register check: using fallback (13021 + total vs PV power).")
58+
return RegMode.FALLBACK
5059

5160
def update(self) -> None:
5261
unit = self.device_config.configuration.modbus_id
53-
5462
soc = int(self.__tcp_client.read_input_registers(13022, ModbusDataType.UINT_16, unit=unit) / 10)
55-
version = Version(self.device_config.configuration.version)
56-
57-
if Firmware(self.device_config.configuration.firmware) == Firmware.v2:
58-
if self.firmware_check: # Firmware >= 95.09
59-
bat_current = self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit) * -0.1
60-
bat_power = self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32,
61-
wordorder=Endian.Little, unit=unit) * -1
62-
else: # Firmware between 95.03 and 95.09
63-
bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1
64-
if version == Version.SH:
65-
bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.INT_16, unit=unit)
66-
elif version == Version.SH_winet_dongle:
67-
bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, unit=unit)
68-
total_power = self.__tcp_client.read_input_registers(13033, ModbusDataType.INT_32,
69-
wordorder=Endian.Little, unit=unit)
70-
pv_power = self.__tcp_client.read_input_registers(5016, ModbusDataType.UINT_32,
71-
wordorder=Endian.Little, unit=unit)
72-
if total_power > pv_power:
73-
bat_power = bat_power * -1
74-
else: # Firmware.v1 (Firmware < 95.03)
63+
64+
# === Mode 1: new_registers ===
65+
if self.register_check == RegMode.NEW_REGISTERS:
66+
bat_current = self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit) * -0.1
67+
bat_power = self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32,
68+
wordorder=Endian.Little, unit=unit) * -1
69+
70+
# === Mode 2: old_registers ===
71+
elif self.register_check == RegMode.OLD_REGISTERS:
7572
bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1
7673
bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, unit=unit)
77-
if version in (Version.SH, Version.SH_winet_dongle):
78-
resp = self.__tcp_client._delegate.read_input_registers(13000, 1, unit=unit)
79-
binary = bin(resp.registers[0])[2:].zfill(8)
80-
if binary[5] == "1":
81-
bat_power = bat_power * -1
74+
75+
resp = self.__tcp_client._delegate.read_input_registers(13000, 1, unit=unit)
76+
running_state = resp.registers[0]
77+
is_charging = (running_state & 0x02) != 0
78+
is_discharging = (running_state & 0x04) != 0
79+
80+
if is_discharging:
81+
bat_power = -abs(bat_power)
82+
elif is_charging:
83+
bat_power = abs(bat_power)
84+
85+
# === Mode 3: fallback ===
86+
else:
87+
bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1
88+
bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, unit=unit)
89+
90+
total_power = self.__tcp_client.read_input_registers(13033, ModbusDataType.INT_32,
91+
wordorder=Endian.Little, unit=unit)
92+
pv_power = self.__tcp_client.read_input_registers(5016, ModbusDataType.UINT_32,
93+
wordorder=Endian.Little, unit=unit)
94+
95+
if total_power > pv_power:
96+
bat_power = -abs(bat_power)
97+
else:
98+
bat_power = abs(bat_power)
8299

83100
currents = [bat_current / 3] * 3
84101

packages/modules/devices/sungrow/sungrow/config.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from modules.common.component_setup import ComponentSetup
44
from modules.devices.sungrow.sungrow.version import Version
5-
from modules.devices.sungrow.sungrow.firmware import Firmware
65
from ..vendor import vendor_descriptor
76

87

@@ -11,13 +10,11 @@ def __init__(self,
1110
ip_address: Optional[str] = None,
1211
port: int = 502,
1312
modbus_id: int = 1,
14-
version: Version = Version.SG,
15-
firmware: Firmware = Firmware.v1):
13+
version: Version = Version.SG):
1614
self.ip_address = ip_address
1715
self.port = port
1816
self.modbus_id = modbus_id
1917
self.version = version
20-
self.firmware = firmware
2118

2219

2320
class Sungrow:

packages/modules/devices/sungrow/sungrow/firmware.py

Lines changed: 0 additions & 6 deletions
This file was deleted.

packages/modules/devices/sungrow/sungrow/inverter.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,17 @@ def update(self) -> float:
3838
dc_power = self.__tcp_client.read_input_registers(5016, ModbusDataType.UINT_32,
3939
wordorder=Endian.Little, unit=unit) * -1
4040

41-
current_L1 = self.__tcp_client.read_input_registers(13030, ModbusDataType.INT_16, unit=unit) * -0.1
42-
current_L2 = self.__tcp_client.read_input_registers(13031, ModbusDataType.INT_16, unit=unit) * -0.1
43-
current_L3 = self.__tcp_client.read_input_registers(13032, ModbusDataType.INT_16, unit=unit) * -0.1
44-
currents = [current_L1, current_L2, current_L3]
45-
else:
41+
currents = self.__tcp_client.read_input_registers(13030, [ModbusDataType.INT_16]*3, unit=unit)
42+
currents = [value * -0.1 for value in currents]
43+
44+
elif self.device_config.configuration.version in (Version.SG, Version.SG_winet_dongle):
4645
power = self.__tcp_client.read_input_registers(5030, ModbusDataType.INT_32,
4746
wordorder=Endian.Little, unit=unit) * -1
4847
dc_power = self.__tcp_client.read_input_registers(5016, ModbusDataType.UINT_32,
4948
wordorder=Endian.Little, unit=unit) * -1
5049

51-
current_L1 = self.__tcp_client.read_input_registers(5021, ModbusDataType.UINT_16, unit=unit) * -0.1
52-
current_L2 = self.__tcp_client.read_input_registers(5022, ModbusDataType.UINT_16, unit=unit) * -0.1
53-
current_L3 = self.__tcp_client.read_input_registers(5023, ModbusDataType.UINT_16, unit=unit) * -0.1
54-
currents = [current_L1, current_L2, current_L3]
50+
currents = self.__tcp_client.read_input_registers(5021, [ModbusDataType.INT_16]*3, unit=unit)
51+
currents = [value * -0.1 for value in currents]
5552

5653
imported, exported = self.sim_counter.sim_count(power)
5754

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from enum import Enum
2+
3+
4+
class RegMode(Enum):
5+
NEW_REGISTERS = "new_registers"
6+
OLD_REGISTERS = "old_registers"
7+
FALLBACK = "fallback"

0 commit comments

Comments
 (0)