Neuer Optimizer/Logik für mehrere Hybrid ESSes

Ok, dann kommen wir doch der Konfiguration mal etwas näher, d.h. folgende Speichersysteme sind konfiguriert?
ess0 Sax?
ess1 Fenecon (DC)
ess4 Yelon (DC)?

Wenn ich dass jetzt nutze um den Screenshot von gestern zu bewerten, bedeutet dass, das der Sax mit 739.0 W entladen sollte, obwohl er einen Soc von 0% hatte.
Entweder passt hier die Implementierung von dem Sax nicht und er erlaubt ein Discharge was er dann nicht umsetzt, oder die Sortierung der ESS passen nicht, sprich die PowerSetPoints werden den falschen ESSen zugewiesen.

Um hier weiter unterstützen zu können, wäre neben der Konfiguration, also welche Controller gibt es und wie sind die konfiguriert, noch das Debug-Log wichtig.
Dabei wären folgende Zeilen wichtig (das log von heute ist leider nicht vollständig):

[ACTIVE] PowerSetPoint: -35.0, Direction: CHARGE
[ACTIVE] ess1: PVProduction: 0.0, min: -35.0, max: -35.0
[ACTIVE] ess0: PVProduction: 0.0, min: 0.0, max: 0.0
[ACTIVE] → remaining power required after pv production solved: -35.0
[ACTIVE] → remaining power required after ess already discharging solved: -35.0
[ACTIVE] ess1: PVProduction: 0.0, min: -35.0, max: -35.0 → ess1 EQUALS -35.0
[ACTIVE] ess0: PVProduction: 0.0, min: 0.0, max: 0.0 → ess0 EQUALS 0.0
[ACTIVE] → remaining power required after solving using all ess: 0.0
[ACTIVE] Add Constraint for ess1: LESS_OR_EQUALS -35.0
[ACTIVE] Add Constraint for ess0: LESS_OR_EQUALS 0.0
[ACTIVE] Solved Solution for ess1: EQUALS -35.0 (should be equal to added constraints!!)
[ACTIVE] Solved Solution for ess0: EQUALS 0.0 (should be equal to added constraints!!)

Wenn ich die Teil-Logausschnitte von heute versuche zu kombinieren, müsste der PowerSetPoint 621.0 W sein.
Der ess0 möchte eine Beladung von 68W (-68.0). Ggf. eine Zwangsbeladung? Da der Logauszug fehlt, kann ich hier nur raten.
Der ess4 soll 689W AC-Leistung erzeugen (689.0). Wieviel DC-Leistung generiert wird, kann ich mangels Informationen zur Konfiguration nicht sehen, da ich nicht weiß welcher charger zum ess4 gehört. Kombiniere ich die anderen Debug-Outputs, müssten es etwa 101W PV sein, d.h. hier soll die Batterie entladen werden.

Jetzt vergleiche ich die generierten Setpoint-Vorgaben mit dem, was die ESS an AC-Leistung liefern (lt. Log):
ess0 -68.0 W SOLL → -60.0 W IST → Passt.
ess4 689.0 W SOLL → -27.0 W IST → Passt nicht. Der ess4 macht nicht dass was er soll. Daher fehlen 662W. Die kommen nun vom Grid.

Mit den anderen Optimizern bestehen keine Probleme?

Kann es sein, dass hier evtl. irgendwo die Sortierung im Optimizer nicht passt, spricht entweder die Vorgaben an die falschen ESS übergeben werden oder die Boundaries min/max nicht zu den jeweiligen ESSen gehören? Mit vollständigem Debug-Logauszug wäre dass besser zu erkennen.

Nach ausgiebigen Testen würde ich sagen, dass du den Optimizer als PR stellen könntest - was hältst du davon? Bei mir funktioniert es nun endlich einwandfrei (das war kein Code - Problem).

Folgende Punkte sind noch offen:

  • Code aufräumen (Logging entfernen oder auf Logging-Klasse umbauen)
  • Umgang mit Reactive Power Vorgaben klären/implementieren
  • Implementation der JUnit Tests

Ich habe aktuell bei mir implementiert, dass bei einer Reactive Power Vorgabe != 0 der Optimizer beendet wird (“return null”), sodass der nächste Optimizer genutzt wird. So wird aber vermutlich kein erfolgreicher JUnit Test möglich sein.

Gibt es irgendwo sinnvoll Hinweise wie mit einer Reactive Power Vorgabe umgegangen werden kann/soll?

Alle oben genannten offenen Punkte sind jetzt abgeschlossen.

  • Der Umgang mit Reactive Power Vorgaben wurde implementiert
  • JUnit Tests wurden implementiert
  • Der Quellcode wurde aufgeräumt
  • Ein paar weitere Optimierungen wurden vorgenommen
  • Der Branch wurde auf den aktuellen develop branch des main repo angehoben

Die Änderungen habe ich soeben in meinen Fork hochgeladen. Alle JUnit Tests laufen durch, jedoch habe ich die neue Version noch nicht auf meinem System getestet.

@Sn0w3y hättest du die Möglichkeit die neue Version noch mal im Live-Betrieb zu testen? Sollte das alles zufriedenstellend laufen würde ich die Implementierung als PR stellen.

Hi,

ich habe die neue Version noch nicht getestet, aber kann eine Sache noch nicht ganz nachvollziehen:

Wieso belädt er den Speicher, anstatt das Haus damit zu versorgen? Das bleibt auch so, bis zu einem gewissen Grenzwert (unbekannt).

Grüße!

Wenn ich raten soll, würde ich auf einen EssLimitTotalDischarge Controller im MIN_SOC (oder auch im FORCE_CHARGE_SOC) state tippen.

Im MIN_SOC state setzt der Controller für den ESS (=Hybrid-Inverter) AC-seitig einen Constraint für ActivePower <= 0. ActivePower (AC-Leistung) <= 0 bedeutet, dass keine positive AC-Leistung vom Hybrid-Inverter abgegeben werden darf/soll, ergo muss sämtliche DC erzeugte Leistung von diesem Hybrid-Inverter in die Batterie gehen.

Ich habe mir den Controller angepasst, sodass ich den HybridModus zwischen TARGET_AC und TARGET_DC konfigurieren kann, wie auch im EssFixActivePower Controller vorgesehen. Wenn gewünscht, kann ich dass gerne auch als PR zur Verfügung stellen.

Falls ich die Situation analysieren soll, benötige ich etwas mehr Input.

Liebe Grüße

Hey,

bei mir gibt es so einen Controller nicht.

Leider funktioniert das ganze nicht wirklich zuverlässig. Siehe Screenshot:

4.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[REACTIVE] Add Constraint for ess4: EQUALS 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[REACTIVE] Add Constraint for ess1: EQUALS 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[REACTIVE] PowerSetPoint: 0.0, Direction: KEEP_ZERO4.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[REACTIVE] Add Constraint for ess0: EQUALS 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] Add Constraint for ess4: EQUALS 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] Add Constraint for ess1: EQUALS 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] → remaining power required after solving using all ess: 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] Add Constraint for ess0: EQUALS 3485.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] ess4: PVProduction: 0.0, min: -3680.0, max: 0.0 → ess4 EQUALS 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] ess0: PVProduction: 0.0, min: -6515.0, max: 5000.0 → ess0 EQUALS 3485.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] ess1: PVProduction: 0.0, min: -1515.0, max: 10000.0 → ess1 EQUALS 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] → remaining power required after ess already discharging solved: 3485.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] → remaining power required after pv production solved: 3485.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] ess4: PVProduction: 0.0, min: -3680.0, max: 0.0 → EQUALS 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] ess1: PVProduction: 0.0, min: -1515.0, max: 10000.0 → EQUALS 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] ess0: PVProduction: 0.0, min: -6515.0, max: 5000.0 → EQUALS 0.04.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPower[ACTIVE] PowerSetPoint: 3485.0, Direction: DISCHARGE4.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPoweress1 does not report PV production4.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPoweress4 does not report PV production4.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.optimizers.PreferDcPoweress0 does not report PV production4.2.2026, 11:55:40INFOio.openems.edge.ess.core.power.Solver- Channel [SetActivePowerEquals]+ess3P EQUALS 3485

Naja, eigentlich macht er das was er soll.

  • SetActivePowerEquals 3485 (AC-Seitige Entladung von 3485W gewünscht)
  • ess0, ess1, ess4 reporten keine PV Produktion (somit keine DC-Optimierung möglich)
  • Verteilung erfolgt nach Order (Highest SOC ESS first)
    • ess0 → Entladung erlaubt (min: -6515.0, max: 5000.0) → Entladung 3485W

Damit der Optimizer DC optimiert arbeiten kann muss er die PV Produktion kennen. Dafür muss im ManagedSymmetricEss die Methode getPvProduction implementiert werden. Am Beispiel GoodWeEss wie folgt (in GoodWeEssImpl.java):

public Integer getPvProduction() {
	return calculatePvProduction();
}

Die Reihenfolge der Debug-Logauszüge scheinen zudem nicht zu passen, kannst du dass nochmal prüfen? Und was ist ess0, ess1 und ess4?