-
Notifications
You must be signed in to change notification settings - Fork 117
Add Anker Solix support #3292
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
Open
seaspotter
wants to merge
30
commits into
openWB:master
Choose a base branch
from
seaspotter:anker_solix
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Add Anker Solix support #3292
Changes from 25 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
1ba739b
Add Vendor class for Anker devices
seaspotter ec0f1e2
Add files via upload
seaspotter 5ee0335
Add Anker configuration and setup classes
seaspotter ef13f0b
Add files via upload
seaspotter 92489b8
Add Anker device implementation in device.py
seaspotter 6fd9196
Add AnkerInverter class for inverter management
seaspotter e0c7c60
Add AnkerCounterVersion enum for device versions
seaspotter ca326bb
Add AnkerCounter class with initialization and update methods
seaspotter 395ecbb
Delete packages/modules/devices/anker/anker_solix/version.py
seaspotter 2113e2d
Add AnkerBat class for battery management
seaspotter 31e7f91
Refactor Modbus client usage in AnkerBat class
seaspotter 90b49ac
Refactor counter.py to use SimCounter and update client
seaspotter c2dcb76
Refactor inverter.py to use ModbusTcpClient_ directly
seaspotter 5f6cb8b
Add device_id to KwargsDict in AnkerBat
seaspotter 68e7ee2
Add device_id to KwargsDict and initialize in AnkerCounter
seaspotter df1aa1b
Add device_id to KwargsDict and initialize
seaspotter a98267a
Change default modbus_id from 100 to 1
seaspotter 9c8a84a
Update power limit handling and component descriptor
seaspotter c2a0cc5
Refactor imports and update read_input_registers calls
seaspotter 45cd964
Refactor imports and clean up inverter.py
seaspotter 4ed6b49
flake8
seaspotter 85196ee
Remove unused import from inverter.py
seaspotter 29a3adc
flake8
seaspotter 86872f2
flake8
seaspotter 65f8d71
flake8
seaspotter a15005d
Add IP config for counter
seaspotter 5fcbf47
flake8
seaspotter 18f0665
flake8
seaspotter 85476de
flake8
seaspotter 737c316
Add dc_power
seaspotter File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Empty file.
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| #!/usr/bin/env python3 | ||
| import logging | ||
| from typing import Any, Optional, TypedDict | ||
|
|
||
| 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, Endian, ModbusTcpClient_ | ||
| from modules.common.simcount import SimCounter | ||
| from modules.common.store import get_bat_value_store | ||
| from modules.devices.anker.anker_solix.config import AnkerBatSetup | ||
| from modules.common.utils.peak_filter import PeakFilter | ||
| from modules.common.component_type import ComponentType | ||
|
|
||
| log = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class KwargsDict(TypedDict): | ||
| device_id: int | ||
| client: ModbusTcpClient_ | ||
|
|
||
|
|
||
| class AnkerBat(AbstractBat): | ||
| def __init__(self, component_config: AnkerBatSetup, **kwargs: Any) -> None: | ||
| self.component_config = component_config | ||
| self.kwargs: KwargsDict = kwargs | ||
|
|
||
| def initialize(self) -> None: | ||
| self.__device_id: int = self.kwargs['device_id'] | ||
| self.client: ModbusTcpClient_ = self.kwargs['client'] | ||
| self.sim_counter = SimCounter(self.__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) | ||
| self.last_mode = 'Undefined' | ||
|
|
||
| def update(self) -> None: | ||
| unit = self.component_config.configuration.modbus_id | ||
|
|
||
| power = self.client.read_input_registers(10008, ModbusDataType.INT_32, | ||
| wordorder=Endian.Little, unit=unit) * -1 | ||
| soc = self.client.read_input_registers(10014, ModbusDataType.UINT_16, unit=unit) | ||
|
|
||
| self.peak_filter.check_values(power) | ||
| imported, exported = self.sim_counter.sim_count(power) | ||
| bat_state = BatState( | ||
| power=power, | ||
| soc=soc, | ||
| 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: | ||
| log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") | ||
| if self.last_mode is not None: | ||
| self.client.write_register(10064, 0, data_type=ModbusDataType.UINT_16, unit=unit) | ||
| self.last_mode = None | ||
| else: | ||
| if self.last_mode != 'limited': | ||
| self.client.write_register(10064, 3, data_type=ModbusDataType.UINT_16, unit=unit) | ||
| self.last_mode = 'limited' | ||
|
|
||
| # Berechne power value: 0 = stop, != 0 = multipliziere mit -1 | ||
| # Laut Doku ist der min Wert 100W, ggf. noch Anpassung für power_limit=0 notwendig | ||
|
|
||
| power_value = 0 if power_limit == 0 else int(power_limit) * -1 | ||
| self.client.write_register(10071, power_value, data_type=ModbusDataType.INT_32, unit=unit) | ||
| log.debug("Aktive Batteriesteuerung angefordert, angeforderte Leistung: {power_value} W") | ||
|
|
||
| def power_limit_controllable(self) -> bool: | ||
| return True | ||
|
|
||
|
|
||
| component_descriptor = ComponentDescriptor(configuration_factory=AnkerBatSetup) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| from typing import Optional | ||
|
|
||
| from modules.common.component_setup import ComponentSetup | ||
| from ..vendor import vendor_descriptor | ||
|
|
||
|
|
||
| class AnkerConfiguration: | ||
| def __init__(self, ip_address: Optional[str] = None, port: int = 502): | ||
| self.ip_address = ip_address | ||
| self.port = port | ||
|
|
||
|
|
||
| class Anker: | ||
| def __init__(self, | ||
| name: str = "Anker", | ||
| type: str = "anker", | ||
| id: int = 0, | ||
| configuration: AnkerConfiguration = None) -> None: | ||
| self.name = name | ||
| self.type = type | ||
| self.vendor = vendor_descriptor.configuration_factory().type | ||
| self.id = id | ||
| self.configuration = configuration or AnkerConfiguration() | ||
|
|
||
|
|
||
| class AnkerBatConfiguration: | ||
| def __init__(self, modbus_id: int = 1): | ||
| self.modbus_id = modbus_id | ||
|
|
||
|
|
||
| class AnkerBatSetup(ComponentSetup[AnkerBatConfiguration]): | ||
| def __init__(self, | ||
| name: str = "Anker Speicher", | ||
| type: str = "bat", | ||
| id: int = 0, | ||
| configuration: AnkerBatConfiguration = None) -> None: | ||
| super().__init__(name, type, id, configuration or AnkerBatConfiguration()) | ||
|
|
||
|
|
||
| class AnkerCounterConfiguration: | ||
| def __init__(self, energy_meter: bool = True, modbus_id: int = 1): | ||
| self.energy_meter = energy_meter | ||
| self.modbus_id = modbus_id | ||
|
|
||
|
|
||
| class AnkerCounterSetup(ComponentSetup[AnkerCounterConfiguration]): | ||
| def __init__(self, | ||
| name: str = "Anker Zähler", | ||
| type: str = "counter", | ||
| id: int = 0, | ||
| configuration: AnkerCounterConfiguration = None) -> None: | ||
| super().__init__(name, type, id, configuration or AnkerCounterConfiguration()) | ||
|
|
||
|
|
||
| class AnkerInverterConfiguration: | ||
| def __init__(self, mppt: bool = False, modbus_id: int = 1): | ||
| self.mppt = mppt | ||
| self.modbus_id = modbus_id | ||
|
|
||
|
|
||
| class AnkerInverterSetup(ComponentSetup[AnkerInverterConfiguration]): | ||
| def __init__(self, | ||
| name: str = "Anker Wechselrichter", | ||
| type: str = "inverter", | ||
| id: int = 0, | ||
| configuration: AnkerInverterConfiguration = None) -> None: | ||
| super().__init__(name, type, id, configuration or AnkerInverterConfiguration()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| #!/usr/bin/env python3 | ||
| from typing import Any, TypedDict | ||
|
|
||
| from modules.common.abstract_device import AbstractCounter | ||
| from modules.common.component_state import CounterState | ||
| from modules.common.component_type import ComponentDescriptor | ||
| from modules.common.fault_state import ComponentInfo, FaultState | ||
| from modules.common.modbus import ModbusDataType, Endian, ModbusTcpClient_ | ||
| from modules.common.simcount import SimCounter | ||
| from modules.common.store import get_counter_value_store | ||
| from modules.devices.anker.anker_solix.config import AnkerCounterSetup | ||
| from modules.common.utils.peak_filter import PeakFilter | ||
| from modules.common.component_type import ComponentType | ||
|
|
||
|
|
||
| class KwargsDict(TypedDict): | ||
| device_id: int | ||
| client: ModbusTcpClient_ | ||
|
|
||
|
|
||
| class AnkerCounter(AbstractCounter): | ||
| def __init__(self, component_config: AnkerCounterSetup, **kwargs: Any) -> None: | ||
| self.component_config = component_config | ||
| self.kwargs: KwargsDict = kwargs | ||
|
|
||
| def initialize(self) -> None: | ||
| self.__device_id: int = self.kwargs['device_id'] | ||
| self.client: ModbusTcpClient_ = self.kwargs['client'] | ||
| self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") | ||
| self.store = get_counter_value_store(self.component_config.id) | ||
| self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) | ||
| self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state) | ||
|
|
||
| def update(self): | ||
| unit = self.component_config.configuration.modbus_id | ||
|
|
||
| power = self.client.read_input_registers(10644, ModbusDataType.INT_32, | ||
| wordorder=Endian.Little, unit=unit) * -1 | ||
| powers = self.client.read_input_registers(10638, [ModbusDataType.INT_32] * 3, | ||
| wordorder=Endian.Little, unit=unit) | ||
| voltages = self.client.read_input_registers(10632, [ModbusDataType.UINT_16] * 3, | ||
| wordorder=Endian.Little, unit=unit) | ||
| currents = self.client.read_input_registers(10666, [ModbusDataType.INT_16] * 3, | ||
| wordorder=Endian.Little, unit=unit) | ||
|
|
||
| voltages = [value / 10 for value in voltages] | ||
| currents = [value / -100 for value in currents] | ||
|
|
||
| self.peak_filter.check_values(power) | ||
| imported, exported = self.sim_counter.sim_count(power) | ||
| counter_state = CounterState( | ||
| imported=imported, | ||
| exported=exported, | ||
| power=power, | ||
| powers=powers, | ||
| voltages=voltages, | ||
| currents=currents | ||
| ) | ||
| self.store.set(counter_state) | ||
|
|
||
|
|
||
| component_descriptor = ComponentDescriptor(configuration_factory=AnkerCounterSetup) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| #!/usr/bin/env python3 | ||
| import logging | ||
| from typing import Iterable, Union | ||
|
|
||
| from modules.common.abstract_device import DeviceDescriptor | ||
| from modules.common.component_context import SingleComponentUpdateContext | ||
| from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater | ||
| from modules.common.modbus import ModbusTcpClient_ | ||
| from modules.devices.anker.anker_solix.bat import AnkerBat | ||
| from modules.devices.anker.anker_solix.config import Anker, AnkerBatSetup, AnkerCounterSetup, AnkerInverterSetup | ||
| from modules.devices.anker.anker_solix.counter import AnkerCounter | ||
| from modules.devices.anker.anker_solix.inverter import AnkerInverter | ||
|
|
||
| log = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| def create_device(device_config: Anker): | ||
| client = None | ||
|
|
||
| def create_bat_component(component_config: AnkerBatSetup): | ||
| nonlocal client | ||
| return AnkerBat(component_config, device_id=device_config.id, client=client) | ||
|
|
||
| def create_counter_component(component_config: AnkerCounterSetup): | ||
| nonlocal client | ||
| return AnkerCounter(component_config, device_id=device_config.id, client=client) | ||
|
|
||
| def create_inverter_component(component_config: AnkerInverterSetup): | ||
| nonlocal client | ||
| return AnkerInverter(component_config, device_id=device_config.id, client=client) | ||
|
|
||
| def update_components(components: Iterable[Union[AnkerBat, AnkerCounter, AnkerInverter]]): | ||
| nonlocal client | ||
| with client: | ||
| for component in components: | ||
| with SingleComponentUpdateContext(component.fault_state): | ||
| component.update() | ||
|
|
||
| def initializer(): | ||
| nonlocal client | ||
| client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) | ||
|
|
||
| return ConfigurableDevice( | ||
| device_config=device_config, | ||
| initializer=initializer, | ||
| component_factory=ComponentFactoryByType( | ||
| bat=create_bat_component, | ||
| counter=create_counter_component, | ||
| inverter=create_inverter_component, | ||
| ), | ||
| component_updater=MultiComponentUpdater(update_components) | ||
| ) | ||
|
|
||
|
|
||
| device_descriptor = DeviceDescriptor(configuration_factory=Anker) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| #!/usr/bin/env python3 | ||
| from typing import TypedDict, Any | ||
|
|
||
| from modules.common.abstract_device import AbstractInverter | ||
| from modules.common.component_state import InverterState | ||
| from modules.common.component_type import ComponentDescriptor | ||
| from modules.common.fault_state import ComponentInfo, FaultState | ||
| from modules.common.modbus import ModbusDataType, Endian, ModbusTcpClient_ | ||
| from modules.common.simcount import SimCounter | ||
| from modules.common.store import get_inverter_value_store | ||
| from modules.devices.anker.anker_solix.config import AnkerInverterSetup | ||
| from modules.common.utils.peak_filter import PeakFilter | ||
| from modules.common.component_type import ComponentType | ||
|
|
||
|
|
||
| class KwargsDict(TypedDict): | ||
| device_id: int | ||
| client: ModbusTcpClient_ | ||
|
|
||
|
|
||
| class AnkerInverter(AbstractInverter): | ||
| def __init__(self, component_config: AnkerInverterSetup, **kwargs: Any) -> None: | ||
| self.component_config = component_config | ||
| self.kwargs: KwargsDict = kwargs | ||
|
|
||
| def initialize(self) -> None: | ||
| self.__device_id: int = self.kwargs['device_id'] | ||
| self.client: ModbusTcpClient_ = self.kwargs['client'] | ||
| self.sim_counter = SimCounter(self.__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) | ||
|
|
||
| def update(self) -> None: | ||
| unit = self.component_config.configuration.modbus_id | ||
|
|
||
| # Register 10002 ist die PV_power also die DC Leistung, eine AC Leistung gibt es so nicht | ||
| power = self.client.read_input_registers(10002, ModbusDataType.INT_32, | ||
| wordorder=Endian.Little, unit=unit) * -1 | ||
|
|
||
| self.peak_filter.check_values(power) | ||
| imported, exported = self.sim_counter.sim_count(power) | ||
| inverter_state = InverterState( | ||
| power=power, | ||
| imported=imported, | ||
| exported=exported | ||
| ) | ||
| self.store.set(inverter_state) | ||
|
|
||
|
|
||
| component_descriptor = ComponentDescriptor(configuration_factory=AnkerInverterSetup) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| from pathlib import Path | ||
|
|
||
| from modules.common.abstract_device import DeviceDescriptor | ||
| from modules.devices.vendors import VendorGroup | ||
|
|
||
|
|
||
| class Vendor: | ||
| def __init__(self): | ||
| self.type = Path(__file__).parent.name | ||
| self.vendor = "Anker" | ||
| self.group = VendorGroup.VENDORS.value | ||
|
|
||
|
|
||
| vendor_descriptor = DeviceDescriptor(configuration_factory=Vendor) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Der Wechselrichter kann mit der DC-Leistung leider nicht angebunden werden, da alle anderen Leistungen AC sind und dann nicht miteinander verrechnet werden können.
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.
Ja ist mir bewusst Lena, es gibt noch eine "Load Power" Register 10010 die die AC Leistung sein könnte, aber mangels Hardware kann ich es halt leider nicht testen. Kann man halt dann ggf noch anpassen wenn es mal User mit dem Setup gibt. Es kann aber auch ein ganz anderer Wert sein, daher erscheint es mir dennoch am besten erstmal die PV Leistung zu nehmen?
https://github.com/anker-charging/ha-anker-solix-official/blob/5eb27a1a4616afc4786d0171dd574f0a24224852/custom_components/anker_solix_official/config/8fcbb87c685781b1d70d784a79eb923098955df2aaf199095ce7767bb70b913d.yaml#L127
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.
Dann nimm Register 10002 für dc_power und "Load Power" für power. Dann ist zumindest das DC-Power-Register an der richtigen Stelle.
Klar, ohne Hardware ist das schwierig für Dich. Eigentlich sollte es recht schnell auffallen, weil Hausverbrauch, Ladekosten, .. nicht passen, aber das wird nicht unbedingt so klar mit einer nicht plausiblen PV-Leistung in Verbindung gebracht.
Uh oh!
There was an error while loading. Please reload this page.
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.
Mach ich, aber dann solltet ihr anderswo auch konsequent sein wenn keine DC Leistung als "power" verwendet werden soll :) Siehe: https://github.com/openWB/core/blob/master/packages/modules/devices/solakon/solakon_one/inverter.py#L32
Oder bei Victron wenn die Leistung der MPPTs hergenommen wird, ist das auch nur DC Leistung beim inverter :)
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.
Danke für den Hinweis. Wir sehen uns die vorhandenen Module mittelfristig nochmal an. Kann gut sein, dass in der Vergangenheit da nicht so sauber gearbeitet wurde.
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.
Gerne, vllt ist es ja ein denkbarer Ansatz wenns nur die PV Leistung gibt diese zwar im Modul als "dc_power" anzugeben, wenn keine "power" vorhanden ist, ersatzweise dann aber "dc_power" für die Anzeige herzunehmen mit ggf. Infomeldung?
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.
Wenn Ströme aus der Wirkleistung berechnet werden, sollte die Ungenauigkeit nicht sehr groß sein, da ein WR in der Regel nur sehr wenig Blindleistung produziert. Bei der Wandlung von DC nach AC hingegen treten größere Verluste auf. Die sollte man nicht vernachlässigen.
Uh oh!
There was an error while loading. Please reload this page.
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.
Der Kommentar passt irgendwie gar nicht in die Diskussion, was haben die Ströme mit der Leistung zu tun?Es geht ja darum wie verfahren wird wenn eben (wie beim Solakon oder auch bei den Victron MPPTs) gar keine AC Leistung als Register vorhanden ist. So hat Andreas das aber jetzt auch mit dem aktuellen PR (#3294) eingebunden, weil es nur die DC Leistung gibt. Soll laut euch ja aber eigentlich nicht sein?
Wenn es aber keine AC Leistung gibt, ist es doch immer noch besser die DC Leistung zu nehmen statt gar nichts? So ist (vermute ich) auch die Denkweise bei Andreas dazu gewesen. Nur sauberer wäre es ja das dann auch als dc_power zu deklarieren und wenn in einem Invertermodul kein "power" vorhanden ist, dann eben ersatzweise "dc_power" zu nehmen für die Anzeige der Leistung, statt gar nichts. Und dann eben vllt noch als Infomeldung im Modul zu schreiben: "Achtung der Wechselrichter gibt als Leistung nur die PV Leistung aus und kann somit in der Leistungsbilanz etwas abweichen".
Um das noch zu verfollständigen: auch bei allen DC angebundenen Batterien ist "power" immer eine DC Leistung und niemals eine AC Leistung, auch das ist in der Leistungsbilanz nicht ganz sauber :) Aber vermutlich vernachlässigbar.
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.
Wie schon geschrieben, wir sehen uns das generell nochmal an. Aktuell passt das zeitlich mit den Vorbereitungen des Release 2.2.0 leider nicht.