Skip to content

PreferDcPowerOptimizer for improved multi-ESS hybrid coordination#3661

Open
timo-schlegel wants to merge 17 commits intoOpenEMS:developfrom
timo-schlegel:feature/PreferDcPowerOptimizer
Open

PreferDcPowerOptimizer for improved multi-ESS hybrid coordination#3661
timo-schlegel wants to merge 17 commits intoOpenEMS:developfrom
timo-schlegel:feature/PreferDcPowerOptimizer

Conversation

@timo-schlegel
Copy link
Copy Markdown
Contributor

@timo-schlegel timo-schlegel commented Mar 29, 2026

Summary

As discussed in the OpenEMS community thread:
https://community.openems.io/t/neuer-optimizer-logik-fur-mehrere-hybrid-esses/10138

This PR introduces the PreferDcPowerOptimizer to improve behavior for systems with multiple hybrid ESS by prioritizing DC (PV) power and coordinating ESS usage.

Motivation

In multi-ESS hybrid systems, current behavior can lead to inefficient operation:

  • Battery discharge despite available PV power
  • Uncoordinated usage of multiple ESS
  • Missing prioritization of DC-coupled generation

Core Concept

The optimizer follows a strict prioritization strategy for active and reactive power distribution.


Active Power Distribution

Priority order:

  1. Fulfill constraints on each ESS first

  2. Distribute available PV production

  3. Distribute remaining power using currently active ESS

    • ESS already discharging (due to PV or constraints)
  4. Distribute remaining power across all ESS if required

Distribution Order

When distributing power:

  • Discharge: prefer ESS with higher SoC
  • Charge: prefer ESS with lower SoC

Reactive Power Distribution

Step 1: Weighted Distribution (by priority)

Reactive power is distributed using calculated weights based on the following strategies (in priority order):

USE_DISCHARGING_ESS

Distribute reactive power proportional to the active power of all currently discharging ESS.
Only discharging ESS are used if they are sufficient.

(weight = activePowerOfThisEss / activePowerOfAllDischargingEss)

USE_IDLE_ESS

If discharging ESS are not sufficient:
Distribute reactive power proportional to the available reactive power capacity of all idle ESS.

(weight = maxQofThisEss / maxQTotalOfAllIdleEss)

USE_ALL_ESS

If still not sufficient:
Distribute reactive power proportional to the available reactive power capacity across all ESS.

(weight = maxQofThisEss / maxQTotalOfAllEss)

Constraints on ESS are respected in all cases.


Step 2: Fallback Distribution

If all weight strategies are exhausted and reactive power is still not fully distributed:

  1. Distribute remaining reactive power using discharging ESS (ordered)
  2. Then using idle ESS (ordered)
  3. Finally using all ESS (ordered)

Distribution Order

  • Discharge: prefer ESS with higher SoC
  • Charge: prefer ESS with lower SoC

Changes

Optimizer

  • Added PreferDcPowerOptimizer

ESS Extensions

  • Introduced getPvProduction() in HybridEss

  • Implemented in:

    • GoodWeEssImpl
    • KacoBlueplanetHybrid10EssImpl
    • SamsungEssImpl
    • EssFeneconCommercial40Impl

Impact

  • Improved efficiency in multi-ESS hybrid systems
  • Reduced unnecessary battery cycling
  • Better utilization of PV production
  • Deterministic and transparent prioritization logic

Fix NPE when allConstraints.size is smaller than allInverter.size.
This occurs when constraint coefficients are missing for an ESS,
for example, at startup when Ess-Power is not (yet) fully initialized.

Fix NPE at KEEP_ZERO and change KEEP_ZERO handling by trying to solve zero as a solution,
as there could be forced discharges or forced charges that may not allow a zero setpoint.
Use LESS_OR_EQUALS (on charge) and GREATER_OR_EQUALS (on discharge) instead of EQUALS
- Logic added to limit the maximum charge and discharge power to the lower and upper boundaries (as a safety measure).
- Logic added to first force all ESSs to positive/negative/zero according to the target direction before attempting to set the power setpoints.
- Return the result of the solved system, instead of creating a new sorted array.
- Implementation of reactive power handling
- Implementation of JUnit tests
- Code cleanup and improved logging handling
- Minor changes (e.g. improvement of getMinPowerFromEss, getMaxPowerFromEss)
- Changed logging during debugMode to info instead of debug topic
- Changed pvProduction in AbstractDummyManagedSymmetricEss from int to Integer
- Removed class name from info logging when ess does not report PV production
- Skip distribution of PV production on KEEP_ZERO
- This also skips the logging of this part in debug mode
- Ensure ESS constraints are prioritized during solving
- Add tests for ESS constraint use cases
Resolve merge conflicts by incorporating both changes.
Follow-up to interface extension in ManagedSymmetricEss

Implemented in:
- AbstractGoodWe
- KacoBlueplanetHybrid10EssImpl
- SamsungEssImpl
- EssFeneconCommercial40Impl
- Move getPvProduction() from ManagedSymmetricEss to HybridEss
- Move getPvProduction() from AbstractDummyManagedSymmetricEss to DummyHybridEss
- Move GoodWe implementation from AbstractGoodWe to GoodWeEssImpl
- Adjust ESS implementations: KacoBlueplanetHybrid10EssImpl, SamsungEssImpl, EssFeneconCommercial40Impl
- Update PreferDcPower to use getPvProduction() from HybridEss
- Update PreferDcPower tests to use DummyHybridEss instead of DummyManagedSymmetricEss
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 29, 2026

Codecov Report

❌ Patch coverage is 71.90227% with 161 lines in your changes missing coverage. Please review.

Additional details and impacted files
@@              Coverage Diff              @@
##             develop    #3661      +/-   ##
=============================================
+ Coverage      59.93%   60.20%   +0.27%     
  Complexity       104      104              
=============================================
  Files           3191     3202      +11     
  Lines         140414   141568    +1154     
  Branches       10254    10554     +300     
=============================================
+ Hits           84146    85216    +1070     
+ Misses         53143    53104      -39     
- Partials        3125     3248     +123     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant