Repository navigation
Solis Hybridwechselrichter S-Serie #3284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5aa95b6
13ee3f2
23a166c
0b05636
5f50d4c
abffab2
171658d
1a2d82c
4241a10
1596f63
d7fb25d
12797aa
989cd4b
c3b47a5
a98a8c7
56674ea
4742181
247a996
3c44ff2
40a1e42
3e256af
4cf8897
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,16 @@ | ||
| #!/usr/bin/env python3 | ||
| import logging | ||
| from typing import TypedDict, Any | ||
| from typing import TypedDict, Any, Optional | ||
|
|
||
| from modules.common.abstract_device import AbstractBat | ||
| from modules.common.component_state import BatState | ||
| from modules.common.component_type import ComponentDescriptor | ||
| from modules.common.fault_state import ComponentInfo, FaultState | ||
| from modules.common.modbus import ModbusDataType, ModbusTcpClient_ | ||
| from modules.common.simcount import SimCounter | ||
| from modules.common.store import get_bat_value_store | ||
| from modules.devices.solis.solis.config import SolisBatSetup | ||
| from modules.devices.solis.solis.version import SolisVersion | ||
| from modules.common.utils.peak_filter import PeakFilter | ||
| from modules.common.component_type import ComponentType | ||
|
|
||
|
|
@@ -17,6 +19,8 @@ | |
|
|
||
| class KwargsDict(TypedDict): | ||
| client: ModbusTcpClient_ | ||
| device_id: int | ||
| version: SolisVersion | ||
|
|
||
|
|
||
| class SolisBat(AbstractBat): | ||
|
|
@@ -26,6 +30,8 @@ def __init__(self, component_config: SolisBatSetup, **kwargs: Any) -> None: | |
|
|
||
| def initialize(self) -> None: | ||
| self.client: ModbusTcpClient_ = self.kwargs['client'] | ||
| self.version: SolisVersion = self.kwargs['version'] | ||
| self.sim_counter = SimCounter(self.kwargs['device_id'], self.component_config.id, prefix="speicher") | ||
| self.store = get_bat_value_store(self.component_config.id) | ||
| self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) | ||
| self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state) | ||
|
|
@@ -35,19 +41,45 @@ def update(self) -> None: | |
|
|
||
| power = self.client.read_input_registers(33149, ModbusDataType.INT_32, unit=unit) | ||
| soc = self.client.read_input_registers(33139, ModbusDataType.UINT_16, unit=unit) | ||
| # Geladen in kWh | ||
| imported = self.client.read_input_registers(33161, ModbusDataType.UINT_32, unit=unit) * 1000 | ||
| # Entladen in kWh | ||
| exported = self.client.read_input_registers(33165, ModbusDataType.UINT_32, unit=unit) * 1000 | ||
| bat_current = self.client.read_input_registers(33134, ModbusDataType.INT_16, unit=unit) * -0.1 | ||
|
|
||
| imported, exported = self.peak_filter.check_values(power, imported, exported) | ||
| currents = [bat_current / 3] * 3 | ||
|
|
||
| self.peak_filter.check_values(power) | ||
| imported, exported = self.sim_counter.sim_count(power) | ||
| bat_state = BatState( | ||
| power=power, | ||
| soc=soc, | ||
| currents=currents, | ||
| imported=imported, | ||
| exported=exported | ||
| ) | ||
| self.store.set(bat_state) | ||
|
|
||
| def set_power_limit(self, power_limit: Optional[int]) -> None: | ||
| unit = self.component_config.configuration.modbus_id | ||
|
|
||
| if power_limit is None: | ||
| self.client.write_register(43135, 0, data_type=ModbusDataType.UINT_16, unit=unit) | ||
| log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") | ||
| elif power_limit == 0: | ||
| self.client.write_register(43135, 1, data_type=ModbusDataType.UINT_16, unit=unit) | ||
| self.client.write_register(43136, 0, data_type=ModbusDataType.UINT_16, unit=unit) | ||
| log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht geladen/entladen") | ||
| elif power_limit < 0: | ||
| self.client.write_register(43135, 2, data_type=ModbusDataType.UINT_16, unit=unit) | ||
| power_value = int(abs(power_limit) / 10) | ||
| self.client.write_register(43129, power_value, data_type=ModbusDataType.UINT_16, unit=unit) | ||
| log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W entladen für den Hausverbrauch") | ||
|
Comment on lines
+69
to
+73
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @seaspotter Ist das richtig?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ja Copilot hat rechts es muss der absolut Wert übergeben werden, es gibt für Charging und Discharging 2 Register jeweils u16 also erwarten beide einen positiven Wert |
||
| elif power_limit > 0: | ||
| self.client.write_register(43135, 1, data_type=ModbusDataType.UINT_16, unit=unit) | ||
| power_value = int(power_limit / 10) | ||
| self.client.write_register(43136, power_value, data_type=ModbusDataType.UINT_16, unit=unit) | ||
| log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W geladen") | ||
|
|
||
| def power_limit_controllable(self) -> bool: | ||
| # Nur die S-Serie sollte die Speichersteuerung können | ||
| return self.version == SolisVersion.hybrid_s | ||
|
|
||
|
|
||
| component_descriptor = ComponentDescriptor(configuration_factory=SolisBatSetup) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,6 @@ | |
| from modules.devices.solis.solis.counter import SolisCounter | ||
| from modules.devices.solis.solis.inverter import SolisInverter | ||
| from modules.devices.solis.solis.config import Solis, SolisBatSetup, SolisCounterSetup, SolisInverterSetup | ||
| from modules.devices.solis.solis.version import SolisVersion | ||
|
|
||
| log = logging.getLogger(__name__) | ||
|
|
||
|
|
@@ -20,17 +19,21 @@ def create_device(device_config: Solis): | |
|
|
||
| def create_bat_component(component_config: SolisBatSetup): | ||
| nonlocal client | ||
| return SolisBat(component_config, client=client) | ||
| return SolisBat(component_config, | ||
| client=client, | ||
| device_id=device_config.id, | ||
| version=device_config.configuration.version) | ||
|
|
||
|
Comment on lines
20
to
26
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. erledigt |
||
| def create_counter_component(component_config: SolisCounterSetup): | ||
| nonlocal client | ||
| return SolisCounter(component_config, version=SolisVersion(device_config.configuration.version), client=client) | ||
| return SolisCounter(component_config, client=client, version=device_config.configuration.version) | ||
|
|
||
| def create_inverter_component(component_config: SolisInverterSetup): | ||
| nonlocal client | ||
| return SolisInverter(component_config, | ||
| version=SolisVersion(device_config.configuration.version), | ||
| client=client) | ||
| client=client, | ||
| device_id=device_config.id, | ||
| version=device_config.configuration.version) | ||
|
|
||
| def update_components(components: Iterable[Union[SolisBat, SolisCounter, SolisInverter]]): | ||
| nonlocal client | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ | |
| from modules.common.component_type import ComponentDescriptor | ||
| from modules.common.fault_state import ComponentInfo, FaultState | ||
| from modules.common.modbus import ModbusDataType, ModbusTcpClient_ | ||
| from modules.common.simcount import SimCounter | ||
| from modules.common.store import get_inverter_value_store | ||
| from modules.devices.solis.solis.config import SolisInverterSetup | ||
| from modules.devices.solis.solis.version import SolisVersion | ||
|
|
@@ -14,6 +15,7 @@ | |
|
|
||
| class KwargsDict(TypedDict): | ||
| client: ModbusTcpClient_ | ||
| device_id: int | ||
| version: SolisVersion | ||
|
|
||
|
|
||
|
|
@@ -25,6 +27,7 @@ def __init__(self, component_config: SolisInverterSetup, **kwargs: Any) -> None: | |
| def initialize(self) -> None: | ||
| self.client: ModbusTcpClient_ = self.kwargs['client'] | ||
| self.version: SolisVersion = self.kwargs['version'] | ||
| self.sim_counter = SimCounter(self.kwargs['device_id'], self.component_config.id, prefix="pv") | ||
| self.store = get_inverter_value_store(self.component_config.id) | ||
| self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) | ||
| self.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state) | ||
|
|
@@ -33,15 +36,24 @@ def update(self) -> None: | |
| unit = self.component_config.configuration.modbus_id | ||
|
|
||
| if self.version == SolisVersion.inverter: | ||
| power = self.client.read_input_registers(3004, ModbusDataType.UINT_32, unit=unit) * -1 | ||
| exported = self.client.read_input_registers(3008, ModbusDataType.UINT_32, unit=unit) * 1000 | ||
| elif self.version == SolisVersion.hybrid: | ||
| power = self.client.read_input_registers(33057, ModbusDataType.UINT_32, unit=unit) * -1 | ||
| exported = self.client.read_input_registers(33029, ModbusDataType.UINT_32, unit=unit) * 1000 | ||
|
|
||
| _, exported = self.peak_filter.check_values(power, None, exported) | ||
| # Für Stringwechselrichter -1 bei Modbus Registers | ||
| power = self.client.read_input_registers(3004, ModbusDataType.INT_32, unit=unit) * -1 | ||
| dc_power = self.client.read_input_registers(3006, ModbusDataType.UINT_32, unit=unit) * -1 | ||
| currents = self.client.read_input_registers(3036, [ModbusDataType.UINT_16]*3, unit=unit) | ||
| elif self.version in (SolisVersion.hybrid, SolisVersion.hybrid_s): | ||
| power = self.client.read_input_registers(33079, ModbusDataType.INT_32, unit=unit) * -1 | ||
| dc_power = self.client.read_input_registers(33057, ModbusDataType.UINT_32, unit=unit) * -1 | ||
| currents = self.client.read_input_registers(33076, [ModbusDataType.UINT_16]*3, unit=unit) | ||
|
Comment on lines
+40
to
+46
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. passt zur Doku |
||
|
|
||
| currents = [value * -0.1 for value in currents] | ||
|
|
||
| self.peak_filter.check_values(power) | ||
| imported, exported = self.sim_counter.sim_count(power) | ||
|
Comment on lines
+50
to
+51
|
||
| inverter_state = InverterState( | ||
| power=power, | ||
| dc_power=dc_power, | ||
| currents=currents, | ||
| imported=imported, | ||
| exported=exported | ||
| ) | ||
| self.store.set(inverter_state) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,3 +4,4 @@ | |
| class SolisVersion(Enum): | ||
| inverter = "inverter" | ||
| hybrid = "hybrid" | ||
| hybrid_s = "hybrid_s" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
erledigt