Laden ohne die Hausbatterie zu leeren
Re: Laden ohne die Hausbatterie zu leeren
15,6 kwp PV, E3DC Speicher mit 18kw, Tesla Model 3 und eine openWB Pro+
Re: Laden ohne die Hausbatterie zu leeren
So dank der neuen docu müsste es für solaredge jetzt funktionieren . Testen kann ich es selbst erst nach Weihnachten , auf eigene Gefahr .
Code: Alles auswählen
bat.py ersetzen in Solaredge
Code: Alles auswählen
der Controll Mode 4 muss gesetzt werden , ich habe die Funktion auf dem Script jetzt entfernt , weil ich der Meinung bin das openwb keine Konfiguration ändern sollte am Fremdsystem , der Modus 4 Remote 0xE004 muss durch den User aktiv gesetzt werden
Code: Alles auswählen
#!/usr/bin/env python3
"""
Dieses Skript ermöglicht die optionale Steuerung von SolarEdge-Batterien über Modbus.
Für eine Fernsteuerung der Batterie muss der Wert des Registers StorageConf_CtrlMode (0xE004) auf "4" (Remote) gesetzt sein.
Die Steuerung erfolgt über das Setzen von Leistungsbegrenzungen, Abfrage des Ladezustands (SOC) und der Batterieleistung.
"""
import logging
from typing import Optional, Dict, Union
from pymodbus.payload import BinaryPayloadDecoder, BinaryPayloadBuilder
from pymodbus.constants import Endian
from dataclass_utils import dataclass_from_dict
from modules.common import modbus
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.simcount import SimCounter
from modules.common.store import get_bat_value_store
from modules.devices.solaredge.solaredge.config import SolaredgeBatSetup
# Initialisiere Logger für die Debug- und Fehlerausgabe
log = logging.getLogger(__name__)
class SolaredgeConfig:
"""
Konfigurationsklasse für SolarEdge-Registeradressen.
Diese Klasse zentralisiert Adressen, um Änderungen einfach umzusetzen.
"""
def __init__(self):
# Register für Leistungsbegrenzung
self.power_limit_register = 0xE010 # Maximal erlaubte Lade-/Entladeleistung
# Register für den Ladezustand der Batterie (State of Charge - SOC)
self.soc_register = 0xE184 # SOC in Prozent
# Register für aktuelle Batterieleistung
self.power_register = 0xE174 # Momentanleistung der Batterie
class SolaredgeBat(AbstractBat):
"""
Klasse zur Steuerung eines SolarEdge-Speichersystems.
Ermöglicht Modbus-Kommunikation zum Lesen und Schreiben von Parametern.
"""
def __init__(self,
device_id: int,
component_config: Union[Dict, SolaredgeBatSetup],
tcp_client: modbus.ModbusTcpClient_,
config: SolaredgeConfig) -> None:
"""
Initialisiert die SolarEdge-Batterie-Klasse.
:param device_id: Eindeutige ID des Geräts für die Kommunikation.
:param component_config: Konfigurationseinstellungen für die Batterie.
:param tcp_client: Modbus-TCP-Client für die Kommunikation.
:param config: Instanz der Konfigurationsklasse mit Registeradressen.
"""
self.__device_id = device_id # Geräte-ID
self.component_config = dataclass_from_dict(SolaredgeBatSetup, component_config)
self.__tcp_client = tcp_client # Modbus-TCP-Client für Lese-/Schreiboperationen
self.config = config # SolarEdge-Registerkonfiguration
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher")
self.store = get_bat_value_store(self.component_config.id) # Interner Zustandsspeicher
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
def set_power_limit(self, power_limit: Optional[int]) -> None:
"""
Setzt die Leistungsbegrenzung für das Laden/Entladen.
:param power_limit: Die gewünschte Begrenzung in Watt.
- Ein positiver Wert aktiviert die Steuerung.
- None oder -1 setzt die Begrenzung zurück (keine Limitierung).
"""
unit = self.component_config.configuration.modbus_id
register = self.config.power_limit_register
try:
if power_limit is None:
power_limit = -1
log.debug("Keine Leistungsbegrenzung angegeben. Begrenzung wird deaktiviert (-1).")
# Versuch, den Wert direkt als INT32 zu schreiben
try:
current_limit = self.__tcp_client.read_holding_registers(register, ModbusDataType.INT_32, unit=unit)
if current_limit == power_limit:
log.debug(f"Aktuelle Leistungsbegrenzung ({current_limit} W) entspricht dem Sollwert ({power_limit} W). Kein Schreibvorgang erforderlich.")
return
self.__tcp_client.write_registers(register, power_limit, ModbusDataType.INT_32, unit=unit)
log.info(f"Leistungsbegrenzung erfolgreich auf {power_limit} W gesetzt.")
except Exception as e:
log.warning(f"Direkte INT32-Verarbeitung fehlgeschlagen: {e}. Wechsel zu manueller Dekodierung.")
# Fallback auf manuelle Zerlegung und Schreiben
builder = BinaryPayloadBuilder(byteorder=Endian.Little, wordorder=Endian.Little)
builder.add_32bit_int(power_limit)
registers = builder.to_registers()
self.__tcp_client.write_registers(register, registers, unit=unit)
log.info(f"Leistungsbegrenzung erfolgreich (Fallback) auf {power_limit} W gesetzt.")
except Exception as e:
log.error(f"Fehler beim Setzen der Leistungsbegrenzung: {e}")
raise
def get_power_limit(self) -> Optional[int]:
"""
Liest die aktuell eingestellte Leistungsbegrenzung.
:return: Der aktuelle Wert der Leistungsbegrenzung in Watt (INT32).
"""
unit = self.component_config.configuration.modbus_id
register = self.config.power_limit_register
try:
# Direkt INT32 lesen
try:
current_limit = self.__tcp_client.read_holding_registers(register, ModbusDataType.INT_32, unit=unit)
log.debug(f"Aktuelle Leistungsbegrenzung aus Register {register}: {current_limit} W")
return current_limit
except Exception as e:
log.warning(f"Direkte INT32-Verarbeitung fehlgeschlagen: {e}. Wechsel zu manueller Dekodierung.")
# Fallback auf manuelle Dekodierung
response = self.__tcp_client.read_holding_registers(register, count=2, unit=unit)
if response.isError():
raise Exception(f"Fehler beim Lesen der Leistungsbegrenzung aus Register {register}.")
decoder = BinaryPayloadDecoder.fromRegisters(
response.registers, byteorder=Endian.Little, wordorder=Endian.Little
)
current_limit = decoder.decode_32bit_int()
log.debug(f"Aktuelle Leistungsbegrenzung (Fallback) aus Register {register}: {current_limit} W")
return current_limit
except Exception as e:
log.error(f"Fehler beim Lesen der Leistungsbegrenzung: {e}")
raise
# Beschreibung der Konfigurationskomponente
component_descriptor = ComponentDescriptor(configuration_factory=SolaredgeBatSetup)
Zuletzt geändert von Basti am So Dez 22, 2024 2:25 pm, insgesamt 8-mal geändert.
-
- Beiträge: 208
- Registriert: Mi Feb 17, 2021 11:09 am
- Has thanked: 1 time
- Been thanked: 4 times
Re: Laden ohne die Hausbatterie zu leeren
Bei E3DC müsste das eigentlich recht einfach zu übernehmen sein, E3DC-Control kann das ja auch schon mWn. Vielleicht kann sich ein Entwickler mal mit Eberhard @eba-M via github kurzschließen?
Ich bin leider auch nicht für programmiertechnisches zu gebrauchen. Er hat ja schon mit E3DC-Control ein Steuerprogramm des E3DC auf die Beine gestellt, was auch die WB Steuerung übernimmt, und er ist sowieso dabei für seine Software eine openWB Übernahme mit aufzunehmen (meine seine Tochter hat eine openWB). Wenn er das von der einen Seite macht, kann man das sicherlich auch von der anderen Seite übernehmen.
https://github.com/Eba-M/E3DC-Control
Ich bin leider auch nicht für programmiertechnisches zu gebrauchen. Er hat ja schon mit E3DC-Control ein Steuerprogramm des E3DC auf die Beine gestellt, was auch die WB Steuerung übernimmt, und er ist sowieso dabei für seine Software eine openWB Übernahme mit aufzunehmen (meine seine Tochter hat eine openWB). Wenn er das von der einen Seite macht, kann man das sicherlich auch von der anderen Seite übernehmen.
https://github.com/Eba-M/E3DC-Control
PV: 29,99kWp an E3DC S10 Pro 45,5kWh, div. Hoymiles ModulWR (HMT-2250, HMT-1800, HM-1500, HM-800), DTU Pro-S/Pro. Wärmepumpe.
openWB Standalone, 2 x openWB Series2 standard+, alle Software 2.x
openWB Standalone, 2 x openWB Series2 standard+, alle Software 2.x
-
- Beiträge: 3650
- Registriert: Sa Feb 20, 2021 9:55 am
- Has thanked: 10 times
- Been thanked: 99 times
Re: Laden ohne die Hausbatterie zu leeren
Die Herausforderung sind die unterschiedlichen Programmiersprachen. E3dc-Control basiert auf der Beispielimplementierung von e3dc und die ist in C. Das muss man kompilieren, die openWB ist in Skriptsprachen implementiert, die ohne kompilieren laufen.
Einer der Gründe, warum das in C ist, ist vielleicht die mitgelieferte AES-Bibliothek, die für die verschlüsselte Kommunikation mit dem S10 benötigt wird. Und das ist das, was ich mit erhöhtem Implementierungsaufwand meine. Für eine nahtlose Integration in die openWB müsste nicht nur die Ansteuerung an sich, sondern auch noch der AES-Part portiert werden. Oder man findet eine passende in Python o.ä. Oder man bei C, muss dafür dann aber die Installationsrroutine für das e3dc-Modul um eine Kompilier-Routine erweitern.
Wesentlich einfacher wäre eine REST-API, da kommt die Verschlüsselung über https und muss nicht separat implementiert werden.
Einer der Gründe, warum das in C ist, ist vielleicht die mitgelieferte AES-Bibliothek, die für die verschlüsselte Kommunikation mit dem S10 benötigt wird. Und das ist das, was ich mit erhöhtem Implementierungsaufwand meine. Für eine nahtlose Integration in die openWB müsste nicht nur die Ansteuerung an sich, sondern auch noch der AES-Part portiert werden. Oder man findet eine passende in Python o.ä. Oder man bei C, muss dafür dann aber die Installationsrroutine für das e3dc-Modul um eine Kompilier-Routine erweitern.
Wesentlich einfacher wäre eine REST-API, da kommt die Verschlüsselung über https und muss nicht separat implementiert werden.
openWB-series2, openWB-Buchse, E3/DC S10pro+19.5kWh, 30kWp Ost-Süd, Model 3 und Ion
Re: Laden ohne die Hausbatterie zu leeren
So kleine Anpassung , es muss zuerst der Control Mode gesetzt werden . Erst dann können die Werte gesetzt werden. Ich habe das angepasst , das Schreiben erfolgt jetzt via float32 und little endian . Habe Kommentare hinzugefügt damit der Code besser lesbar ist und evtl. Leute helfen können .Adressen ausgelagert für die Übersicht .
Habt Nachsicht , ich mach das gerade alles am Handy
Habt Nachsicht , ich mach das gerade alles am Handy
- mrinas
- Beiträge: 2277
- Registriert: Mi Jan 29, 2020 10:12 pm
- Has thanked: 36 times
- Been thanked: 34 times
Re: Laden ohne die Hausbatterie zu leeren
Ich hätte auch eine Steuerung für SMA hybrid als PR fertig, mir fehlt aktuell lediglich die Sonne um das Testen zu können. Batterie ist zuletzt chronisch leer.
15,2kWp SMA (SB4000TL-21, SB3.0, STP6.0-SE + BYD HVS, EnergyMeter), openWB Standard+, openWB Pro, Smart #1 (ersetzt den e2008), Tesla Model Y LR.
Re: Laden ohne die Hausbatterie zu leeren
Ihr müsst E3DC machen, das ist der hot shit
Spass beiseite, ich muss euch bewundern, für mich ist das chinesisch.....
Spass beiseite, ich muss euch bewundern, für mich ist das chinesisch.....
15,6 kwp PV, E3DC Speicher mit 18kw, Tesla Model 3 und eine openWB Pro+
Re: Laden ohne die Hausbatterie zu leeren
Naja theoretisch kannst du über Menü S10 auf sunspec umstellen und dann sollte auch das solaredge / sunspec Script funktionieren . Aber mit E3DC habe ich mich lange nicht mehr beschäftigt .
Ansonsten Python-e3dc über rscp
Ansonsten Python-e3dc über rscp
-
- Beiträge: 3650
- Registriert: Sa Feb 20, 2021 9:55 am
- Has thanked: 10 times
- Been thanked: 99 times
Re: Laden ohne die Hausbatterie zu leeren
Nur lesend. Schreiben geht nur per rscp.
openWB-series2, openWB-Buchse, E3/DC S10pro+19.5kWh, 30kWp Ost-Süd, Model 3 und Ion
-
- Beiträge: 1452
- Registriert: Di Sep 03, 2019 4:13 pm
- Has thanked: 23 times
- Been thanked: 21 times
Re: Laden ohne die Hausbatterie zu leeren
Vielleicht Off-Topic, aber bei SMA und sunspec muss man wohl aufpassen, welche Register beschrieben werden.
Im victron forum - da das ESS nun auch SMA -WR dynamisch regeln kann - ist das Thema aufgetaucht.
Wer die falschen Register zu oft nutzt, kann den Flash-Speicher des WR schrotten oder erreichen, das der WR sich tot stellt.
Ausserdem muss man evtl. aufpassen, ob der SMA Homemanager mit verbaut ist oder nicht, wenn man den WR ansprechen will.
Einige Infos, hier: https://community.victronenergy.com/t/v ... ry/14183/1