ModbusAttr Device (Marstek Venus E) reduziert FHEM Performance

Begonnen von Dracolein, 06 April 2026, 18:13:42

Vorheriges Thema - Nächstes Thema

Dracolein

Hallo zusammen,

ich habe mich in den letzten Tagen in die Modbus Thematik reingenerdet. Mein Ziel war es, den neuen Marstek Venus E 3.0 für FHEM lesbar und steuerbar zu machen. Technisch habe ich es inzwischen störungsfrei am laufen. Während 3 Hilfs-Devices nur zur aktiven Steuerung dienen und hier ignoriert werden können, liegt mein Fokus auf dem Main-Device vom Typ ModbusAttr.

Der Grund für diesen Thread bzw. mein "Problem": Meine FHEM Instanz ist nun spürbar deutlich weniger performant, als ich es seit Jahren gewöhnt bin. Einfachste Steuerbefehle (Licht an) haben plötzlich Delays von 1-3 Sekunden, was ich so nicht hinnehmen möchte. Im Folgenden gebe ich das Device als Raw-Code hier mit und hoffe auf Eure Expertise speziell mit Fokus, ob ich irgendwelche Attribute doof / falsch / Suboptimal / whatever definiert habe und dadurch Performance leidet?

Was ich schon getan habe:
- Polling auf 30 Sekunden raufgesetzt
- Register rausgelöscht, die ich nicht unbedingt benötige
- polldelay für diverse Register definiert

Sonstiges:
- FHEM (auf Raspberry Pi) via LAN im Netzwerk
- Batteriespeicher via LAN im Netzwerk
- feste IP-Adressen
- Schnittstelle am Batteriespeicher: Modbus-TCP
- Geräte-Pings im niedrigsten ms-Bereich (also eig. top)

Ich frage mehrere Register gleichzeitig in einem Block ab, die nicht zusammenhängen und Abfragelücken haben. Kann das ein Problem sein?

defmod MarstekVenus01 ModbusAttr 1 30 192.168.178.112:502 TCP
attr MarstekVenus01 comment !!! ACHTUNG: STEUERUNG ÜBER DEVICE dummy_MarstekBefehl !!!\
ACPower        - AC-Leistung in Watt. Positiv = Bezug aus Netz, Negativ = Einspeisung ins Netz\
BattPower      - Batterieleistung in Watt. Positiv = Laden, Negativ = Entladen\
BattVoltage    - Batteriespannung in Volt\
SoC            - State of Charge, Ladestand in Prozent\
TempInternal   - Innentemperatur des Wechselrichters in Grad Celsius\
InverterState  - Aktueller Betriebszustand: Standby/Bereit/Laden/Entladen/USV/Update\
ControlMode    - Externe Steuerung freischalten: 21930=Ein, 21947=Aus. (Muss einmalig auf 21930 gesetzt werden bevor Steuerbefehle wirken)\
Betriebsmodus  - Grundlegende Strategie: Eigenverbrauch / KI-Optimierung / Manuell\
ForceMode      - Aktiver Ladebefehl im Manuell-Modus: Aus / Laden / Entladen\
SetChargePower    - Ladeleistung in Watt (0-2500W), wirkt wenn ForceMode=Laden\
SetDischargePower - Entladeleistung in Watt (0-2500W), wirkt wenn ForceMode=Entladen\
ChargeToSoC    - Ziel-Ladestand in Prozent, Laden/Entladen stoppt automatisch bei diesem Wert
attr MarstekVenus01 dev-h-combine 20
attr MarstekVenus01 dev-h-defPoll 1
attr MarstekVenus01 dev-timing-commDelay 1
attr MarstekVenus01 dev-timing-sendDelay 0.5
attr MarstekVenus01 dev-timing-timeout 4
attr MarstekVenus01 dev-type-i16-len 1
attr MarstekVenus01 dev-type-i16-unpack s>
attr MarstekVenus01 dev-type-u16-len 1
attr MarstekVenus01 dev-type-u16-unpack n
attr MarstekVenus01 group Marstek
attr MarstekVenus01 icon battery_100
attr MarstekVenus01 obj-h30001-format %.0f
attr MarstekVenus01 obj-h30001-reading BattPower
attr MarstekVenus01 obj-h30001-type i16
attr MarstekVenus01 obj-h30006-format %.0f
attr MarstekVenus01 obj-h30006-reading ACPower
attr MarstekVenus01 obj-h30006-type i16
attr MarstekVenus01 obj-h30100-expr $val * 0.01
attr MarstekVenus01 obj-h30100-format %.2f
attr MarstekVenus01 obj-h30100-reading BattVoltage
attr MarstekVenus01 obj-h30100-type u16
attr MarstekVenus01 obj-h35000-expr $val * 0.1
attr MarstekVenus01 obj-h35000-format %.1f
attr MarstekVenus01 obj-h35000-polldelay x10
attr MarstekVenus01 obj-h35000-reading TempInternal
attr MarstekVenus01 obj-h35000-type i16
attr MarstekVenus01 obj-h35100-map 0:Standby,1:Bereit,2:Laden,3:Entladen,4:USV,5:Update
attr MarstekVenus01 obj-h35100-reading InverterState
attr MarstekVenus01 obj-h35100-type u16
attr MarstekVenus01 obj-h37005-format %.0f
attr MarstekVenus01 obj-h37005-polldelay x10
attr MarstekVenus01 obj-h37005-reading SoC
attr MarstekVenus01 obj-h37005-type u16
attr MarstekVenus01 obj-h42000-poll 0
attr MarstekVenus01 obj-h42000-reading ControlMode
attr MarstekVenus01 obj-h42000-set 1
attr MarstekVenus01 obj-h42000-type u16
attr MarstekVenus01 obj-h42010-map 0:Aus,1:Laden,2:Entladen
attr MarstekVenus01 obj-h42010-poll 1
attr MarstekVenus01 obj-h42010-reading ForceMode
attr MarstekVenus01 obj-h42010-set 1
attr MarstekVenus01 obj-h42010-type u16
attr MarstekVenus01 obj-h42011-max 100
attr MarstekVenus01 obj-h42011-min 10
attr MarstekVenus01 obj-h42011-poll 1
attr MarstekVenus01 obj-h42011-reading ChargeToSoC
attr MarstekVenus01 obj-h42011-set 1
attr MarstekVenus01 obj-h42011-type u16
attr MarstekVenus01 obj-h42020-max 2500
attr MarstekVenus01 obj-h42020-min 0
attr MarstekVenus01 obj-h42020-poll 1
attr MarstekVenus01 obj-h42020-reading SetChargePower
attr MarstekVenus01 obj-h42020-set 1
attr MarstekVenus01 obj-h42020-type u16
attr MarstekVenus01 obj-h42021-max 2500
attr MarstekVenus01 obj-h42021-min 0
attr MarstekVenus01 obj-h42021-poll 1
attr MarstekVenus01 obj-h42021-reading SetDischargePower
attr MarstekVenus01 obj-h42021-set 1
attr MarstekVenus01 obj-h42021-type u16
attr MarstekVenus01 obj-h43000-map 0:Manuell,1:Eigenverbrauch,2:KI-Optimierung
attr MarstekVenus01 obj-h43000-poll 1
attr MarstekVenus01 obj-h43000-reading Betriebsmodus
attr MarstekVenus01 obj-h43000-set 1
attr MarstekVenus01 obj-h43000-type u16
attr MarstekVenus01 stateFormat {ReadingsVal($name,"SoC","?") . "% | " . ReadingsVal($name,"InverterState","?") . " | " . ReadingsVal($name,"BattPower","?") . "W"}
attr MarstekVenus01 userReadings ACPower_log {\
    my $last_age = ReadingsAge("MarstekVenus01", "ACPower_log", 9999);;;;\
    my $last_val = ReadingsNum("MarstekVenus01", "ACPower_log", 0);;;;\
    my $current  = ReadingsNum("MarstekVenus01", "ACPower", 0);;;;\
    return ($last_age >= 900 || abs($current - $last_val) >= 100) ? $current : undef;;;;\
},\
  SoC_log {\
    my $last = ReadingsAge("MarstekVenus01", "SoC_log", 9999);;;;\
    return $last >= 900 ? ReadingsNum("MarstekVenus01", "SoC", 0) : undef;;;;\
  }

setstate MarstekVenus01 100% | Bereit | 0W
setstate MarstekVenus01 2026-04-06 17:58:47 ACPower 0
setstate MarstekVenus01 2026-04-06 17:48:13 ACPower_log 0
setstate MarstekVenus01 2026-04-06 17:58:47 BattPower 0
setstate MarstekVenus01 2026-04-06 17:58:48 BattVoltage 53.52
setstate MarstekVenus01 2026-04-06 17:58:51 Betriebsmodus Eigenverbrauch
setstate MarstekVenus01 2026-04-05 20:48:12 ChargeToSoC 100
setstate MarstekVenus01 2026-04-05 20:43:52 ControlMode 21947
setstate MarstekVenus01 2026-04-05 20:43:50 ForceMode Aus
setstate MarstekVenus01 2026-04-06 17:58:49 InverterState Bereit
setstate MarstekVenus01 2026-04-05 20:19:47 SetChargePower 200
setstate MarstekVenus01 2026-04-05 19:34:35 SetDischargePower 300
setstate MarstekVenus01 2026-04-06 17:55:53 SoC 100
setstate MarstekVenus01 2026-04-06 17:45:42 SoC_log 100
setstate MarstekVenus01 2026-04-06 17:56:16 TempInternal 22.6
setstate MarstekVenus01 2026-04-06 12:14:22 state opened

Raspberry Pi 4 mit FHEM; FTUI Dashboard auf Asus 15,6" VT168H Touchscreen; ZigBee mit ConBee2 USB-Stick; div. Shelly 2.5; integr. Gaszähler mit ESP8266 & ESPEasy;

SuMiHe

Hi Dracolein,

hab grad Dein post gefunden, da ich auch seit ein paar Tagen am gleichen Thema bastele. Ich kann Deinen Ansatz super gebrauchen :-). Ich hab Deine Version mal 1:1 auf einem Testsystem installiert (auf einem RasPi 4) und kann keinen nennenswerten Performancenachteil spüren bzw messen. Bei mir läuft es auch auf meinem Realen System IntelCeleron unter pve im container, 2 Kerne, 1GB Ram top.

Gruß Mirko
Gruß Mirko

Dracolein

Habe folgende Attribute editiert, seither sind die "Lags" (blocking?) weitgehend verschwunden

attr MarstekVenus01 dev-h-combine 10
attr MarstekVenus01 dev-h-defPoll 1
attr MarstekVenus01 dev-timing-commDelay 0.2
attr MarstekVenus01 dev-timing-sendDelay 0.2
attr MarstekVenus01 dev-timing-timeout 3
Raspberry Pi 4 mit FHEM; FTUI Dashboard auf Asus 15,6" VT168H Touchscreen; ZigBee mit ConBee2 USB-Stick; div. Shelly 2.5; integr. Gaszähler mit ESP8266 & ESPEasy;

SuMiHe

Also ich hatte dein Dev jetzt durchgehend am laufen, keine Probleme.

Bei mir: Fhem Server per LAN im Netz, Speicher per RS485->Wlan da Router direkt daneben und Ports alle belegt.
Gruß Mirko

Dracolein

#4
Ich teile informativ, wie ich den Marstek aus FHEM heraus steuere:

1.) scheint es ein Keepalive-Signal zu benötigen, um die Karre im Eingriffsmodus zu halten, wenn man längere Zeit manuell steuern will, dazu gibts pauschal ein at-Device:

defmod at_MarstekKeepAlive at +*00:00:25 {\
  if (ReadingsVal("MarstekVenus01","ForceMode","Aus") ne "Aus") {\
    fhem("set MarstekVenus01 ControlMode 21930")\
  }\
}
attr at_MarstekKeepAlive comment Alle 25 Sekunden wird geprüft ob der Marstek gerade per ForceMode gesteuert wird. \
Nur wenn ja, wird ControlMode erneuert. Das verhindert dass der Marstek die externe Steuerung nach ~15 Sekunden selbst abschaltet \
ohne dass im Normalbetrieb unnötig Register geschrieben werden.
attr at_MarstekKeepAlive group Marstek
attr at_MarstekKeepAlive room Befehle,Photovoltaik

Ein Dummy-Device dient zum Erzeugen von steuerbaren Readings:
defmod dummy_MarstekBefehl dummy
attr dummy_MarstekBefehl comment Erst die Leistung setzen, dann den Befehl, Beispiel:\
set dummy_MarstekBefehlLeistung 300\
set dummy_MarstekBefehl Befehl Laden\
\
Befehle:\
Laden    - Lädt mit eingestellter Leistung (ForceMode)\
Entladen - Entlädt mit eingestellter Leistung (ForceMode)\
Standby  - Manueller Modus ohne Zeitfenster, weder laden noch entladen\
Stop     - Beendet externe Steuerung, Marstek kehrt in Eigenverbrauch zurück
attr dummy_MarstekBefehl group Marstek
attr dummy_MarstekBefehl readingList Befehl Leistung
attr dummy_MarstekBefehl room Photovoltaik
attr dummy_MarstekBefehl setList Befehl:Laden,Entladen,Standby,Stop Leistung:50,100,200,300,500,800,1000,1500,2000,2500
attr dummy_MarstekBefehl stateFormat Befehl

Das DOIF-Device übernimmt Steuerbefehle und führt sie aus:
defmod MarstekDOIF DOIF ([dummy_MarstekBefehl:Befehl] eq "Laden")\
  (set MarstekVenus01 ControlMode 21930)\
  (set MarstekVenus01 SetChargePower [MarstekBefehl:Leistung])\
  (set MarstekVenus01 ForceMode Laden)\
DOELSEIF ([dummy_MarstekBefehl:Befehl] eq "Entladen")\
  (set MarstekVenus01 ControlMode 21930)\
  (set MarstekVenus01 SetDischargePower [MarstekBefehl:Leistung])\
  (set MarstekVenus01 ForceMode Entladen)\
DOELSEIF ([dummy_MarstekBefehl:Befehl] eq "Standby")\
  (set MarstekVenus01 ControlMode 21930)\
  (set MarstekVenus01 ForceMode Aus)\
  (set MarstekVenus01 Betriebsmodus Manuell)\
DOELSE\
  (set MarstekVenus01 ForceMode Aus)\
  (set MarstekVenus01 Betriebsmodus Eigenverbrauch)\
  (set MarstekVenus01 ControlMode 21947)
attr MarstekDOIF do always
attr MarstekDOIF group Marstek
attr MarstekDOIF room Photovoltaik
attr MarstekDOIF wait 0,2,1:0,2,1:0,1,1:0,1,1

Somit braucht es dann nur noch beispielsweise:
Zitatset dummy_MarstekBefehlLeistung 375

gefolgt von
Zitatset dummy_MarstekBefehl Befehl Laden

und die Batterie versetzt sich in den Modus "Manuell" und beginnt mit 375 Watt zu laden, bis ein anderer Befehl gesendet wird. Wie oben im Device als Kommentar hinterlegt:
Befehle:
Laden    - Lädt mit eingestellter Leistung (ForceMode)
Entladen - Entlädt mit eingestellter Leistung (ForceMode)
Standby  - Manueller Modus ohne Zeitfenster, weder laden noch entladen
Stop     - Beendet externe Steuerung, Marstek kehrt in Eigenverbrauch zurüc

Raspberry Pi 4 mit FHEM; FTUI Dashboard auf Asus 15,6" VT168H Touchscreen; ZigBee mit ConBee2 USB-Stick; div. Shelly 2.5; integr. Gaszähler mit ESP8266 & ESPEasy;