E3DC Maestro – Intelligent battery control for E3DC home storage systems (HACS Custom Integration)

Hey everyone,

I built a HACS custom integration for automated, intelligent control of E3DC home storage systems:

:point_right: [GitHub - TommiG1/hacs-e3dc-maestro · GitHub]

It builds on top of e3dc_rscp (Thanks to @Torben78 (torbennehmer (Torben Nehmer) · GitHub) and adds a full control engine with 17 prioritized phases: seasonal charge corridor, curtailment guard, HT/NT protection, spreading, PV delay, pre-discharge, EVCC integration, wallbox & heat pump control, auto-optimizer and more — all configurable via UI, no YAML needed.

Runs fully local, no cloud required. Compatible with all E3DC systems (RSCP tags are identical across devices).

Note: AI360 must be disabled in the E3DC settings, otherwise it overrides Maestro’s control commands.

Feedback and PRs welcome!

1 Like

Impressive work!

1 Like

Hey, I think your E3DC Maestro is great and I’m trying to implement it myself. I have a somewhat unusual setup. I have 14.5 kWp directly connected to the E3DC and an older 10.5 kWp PV system connected to an external source via a smart meter.

Now my question is, should I configure a helper system and feed Maestro with data from both systems, for example, for the PV forecast and power output, or should I only use the power directly connected to the E3DC? I’m not entirely sure how your tool works best.

What inverter power rating should I specify?

Thanks for this great tool!

Hello Roedi,

In your setup, I would not use only the PV that is directly connected to the E3DC. Maestro works best when it sees the total PV generation that actually affects your house consumption and grid export. So if possible, I would feed it the combined production of both systems.

For that reason, I would recommend creating a helper or template sensor that combines the 14.5 kWp E3DC PV and the 10.5 kWp external PV into one total PV power sensor. The same applies to the PV forecast: if you can provide a forecast for the total site production, that will give better results than using only the E3DC-side array.

For the inverter power setting, use only the real AC power rating of the E3DC inverter, not the total DC size of both PV systems. So if your E3DC inverter is rated for 12 kW AC, set 12000 W, even though your total PV size is 25.0 kWp.

One important detail: for the installed PV power value, the correct number depends on how your export limit is defined. If your feed-in limit applies to the whole site, use the total 25.0 kWp. If it applies only to the E3DC-connected system, use only the 14.5 kWp.

So the short version is:
Use both PV systems for PV power and forecast if possible, but set inverter power only to the actual E3DC inverter AC rating.

My setup is a bit special, but it is probably very similar to yours: I have an E3DC S10 Pro with 12 kW AC inverter power and 9 kW DC on the E3DC side, plus an additional external inverter with 6 kW AC. That additional inverter is not wired directly into the E3DC inverter path, but it is measured through the external power meter input of the E3DC, so the E3DC already sees and reports the total PV production of the whole system.

In a setup like that, the important question is not “how many inverters do I have physically?”, but “what does the PV sensor used by Maestro actually represent?”. If the PV sensor already shows the combined production of both the E3DC PV and the external inverter, then Maestro should also be configured consistently with that combined view.

So in that case I would configure it like this:

  • Use the E3DC PV sensor that already reports the total PV yield.

  • Do not configure an additional generation sensor, because the external inverter is already included in the E3DC total.

  • Set inverter power to the total AC inverter power represented by that PV sensor. In my case that would be 12 kW + 6 kW = 18,000 W.

  • Set installed PV power to the total installed DC power of both PV systems together.

The practical rule is:
If your chosen PV sensor already includes the extra inverter via the external E3DC meter, configure Maestro for the combined system. If your PV sensor only shows the PV directly connected to the E3DC, then use only the E3DC-side values.

Hey, can you tell me why Maestro briefly charged the battery twice this morning and then once up to 60%? And now it’s slowly exporting power again. I have a fixed electricity tariff, so this doesn’t make any sense to me. Did I overlook something in the config?

Thanks roedi

Hi! I had to take a closer second look at your charts — and you're right, the battery was charged from the grid this morning, not just hit by a house-load spike. Here's what I see:

Timeline from your chart:

  • 6:00–7:30: SoC flat at ~13%, "Geladen heute" counter at zero → the small grid spikes (~13 kW for ~5 min each) at 6:15 and 7:00 are short house-load peaks (heating element / heat pump start), not battery charging.
  • ~7:40–8:50: Grid import sits at a steady 10–12 kW for over an hour, "Geladen heute" jumps from ~0.5 to ~11 kWh, and SoC rises from 13% → 60%. That's roughly 4.7 kWh pulled from the grid into the battery — this is real Maestro grid charging, not house load.
  • From ~8:50 on: PV ramps up, battery sits at 60%, and the 1 kW export begins.

What in Maestro's code can actually cause grid → battery charging?

There are only four paths in the rule engine that bypass the "no grid charging" guard:

PhaseWhen
PHASE_EMERGENCYSoC < charge_threshold (default 15%)
PHASE_FEED_IN_LIMITonly with PV surplus → ruled out at 7:40
PHASE_CURTAILMENT_GUARDonly with PV surplus → ruled out
tariff_class == TARIFF_LOWdynamic tariff price ≤ cheap_threshold, or a tariff slot of class low is active

Emergency alone only charges up to charge_threshold + hysteresis (≈17%) and then stops — it cannot explain the run all the way to 60%.

⇒ The most likely cause: a low-tariff charging path is active in your config. That means one of:

  1. dynamic_tariff_enabled = true with a price sensor (Tibber, aWATTar etc.) that returned a price ≤ your cheap_threshold this morning. The engine then thinks "cheap grid power, fill the battery" and pulls up to max_grid_charge_kwh.
  2. A tariff slot configured with class_=TARIFF_LOW covering the early-morning window (e.g. a leftover night-tariff schedule).
  3. auto_mode_enabled with the cost objective — the optimizer can set a morning cap or grid-charge strategy on its own.

On a fixed tariff, none of these should be on. My guess is that during initial setup the dynamic tariff option got enabled by mistake (or a price-sensor entity is referenced that's reporting low values).

What to check / fix:

  1. Open your Maestro config and make sure dynamic_tariff_enabled is off
  2. Check that there are no custom tariff slots of class low configured
  3. Disable auto_mode_enabled (the optimizer can re-introduce grid-charging strategies overnight)
  4. Verify charge_threshold is at a sane value (15% is fine; anything higher would force longer emergency charging)

One more thing — I just pushed a new release with several fixes around exactly these edge cases, and it now includes a built-in decision log that records every phase transition with the input state (PV / house / grid / SoC / reason). That should make it much easier to see why Maestro chose to charge from the grid at any given moment. Please update via HACS to the latest version.

Important: the detailed [decide] log lines are only written when debug logging is enabled for the integration. Add this to your configuration.yaml and restart Home Assistant:

logger:
  default: warning
  logs:
    custom_components.e3dc_maestro: debug

After the next morning cycle either:

  • check the new decision log entity in your dashboard, or
  • send me the [decide] log lines from that morning:
sudo docker logs --since 12h homeassistant 2>&1 | grep '\[decide\]' | grep '08:'

With those we can pin down the exact phase that triggered the grid charge and confirm the fix.

Thank you for your reply.

I followed your steps and checked the following:

  1. Dynamic tariff is set to off.
  2. No tariff slot is configured.
  3. auto_mode was on -> I have now set it to off.
  4. charge_threshold is set to 15.
    charge_target is set to 100%.

I searched for the 60% and found the following:
Could it be related to the 60% shown in the screenshot? Probably not, right?

I also adjusted the logs and installed the new version. I will report back tomorrow.

Thank you very much for your help so far.

Hi,

good detective work — but no, the 60 % in that screenshot is unrelated to what you saw this morning. Let me explain:

That field is the activation threshold of the pre-discharge action (morgen_vorentladung). The logic is:

  • Run the action only if the current SoC is above 60 %
  • Then discharge the battery down to the 35 % target, to make room for tomorrow's PV

So this action never charges the battery — it only discharges. It cannot be the cause of the morning grid charging you observed.

What was most likely the actual cause

Looking at your settings, the prime suspect is that auto_mode was on.

The auto-optimiser can autonomously raise the daily charge target and trigger forward-looking / gentle-charge phases based on the PV forecast, even without a dynamic tariff. With charge_target = 100 % and a pessimistic forecast for the day, that can result in grid charging in the early morning hours.

Now that you've switched auto_mode off, the system should behave purely reactive (PV → battery → grid, no proactive grid pulls). Please report back tomorrow.

If you want to be 100 % sure, enable debug logging:

logger:
  logs:
    custom_components.e3dc_maestro: debug

Then any morning charging activity will appear as e.g. [decide] phase=gentle_charge ... reason=... and we can pinpoint exactly which rule triggered it.


One more recommendation, since you're on a fixed tariff

With a fixed tariff I'd suggest going one step further: disable the morning pre-discharge entirely and instead lower the daily charge target (e.g. to 80–90 %). The reasoning:

  • Pre-discharging only pays off when there's a price spread between night and day (dynamic tariff) or when you're consistently hitting the feed-in limit. On a fixed tariff, neither applies.
  • Each pre-discharge → re-charge round-trip is a full extra cycle. Battery wear costs roughly 15–20 ct/kWh of throughput, while a curtailed kWh only costs you the feed-in compensation (~5–8 ct).
  • Net result: losing a few kWh to curtailment is cheaper than the additional cycling — and much gentler on the battery.

Lowering the charge target achieves the same goal (room for tomorrow's PV) without any extra cycle — the battery simply isn't filled all the way overnight, so the morning sun fills the remaining headroom on its own.

Rule of thumb:

Setupcharge_targetPre-dischargeauto_mode
Fixed tariff80–90 %offoff
Dynamic tariff (Tibber, aWATTar, …)100 %optionalmay help

Hope that helps — looking forward to your update tomorrow!

Okay, I hadn’t looked at it from that perspective. My thought was that I could create “space” for new PV production that might otherwise be lost due to a potentially full battery and the legally required curtailment.

Thanks Roedi

These are the settings I used with a 70% power limit. I’ve been running it this way successfully for days now.

1 Like

Hi Roedi,

I have just released a new version today (V0.3.0) containing several optimizations regarding the "Auto" option. When "Auto" is used in conjunction with "Cost," issues of this nature should now be resolved. It is crucial, however, that you enter the actual cost figures and system details—specifically acquisition costs, as well as import and export tariffs—via the integration settings.
I currently have this running in my development environment with no active custom settings—simply "Auto" set to "Cost." For my taste, the results are outstanding, particularly when using a fixed-rate tariff.
Give it a try!

1 Like

Hey, thanks for your work and the updates.

Unfortunately, I can’t provide any new information about my issue yet, because my Home Assistant storage ran full and I already had enough trouble just getting it running again.

Yesterday evening I quickly installed the latest version and updated the dashboards. I actually wanted to check everything this morning, but I didn’t get that far again.

Yesterday evening the battery was full and only discharged down to 89%. After that, the status changed to reserve_protection and it would not continue discharging anymore.

What could be causing this now?

According to the documentation, this seems to be related to the seasonal backup reserve, but:

  • Winter reserve is set to 15%

  • Backup reserve during equinox is set to 10%

So I would expect it to discharge further.

I’ll check all settings again later today and hopefully tomorrow I can give you more information about the original issue.

Thanks Roedi :slight_smile:

Please install the last update release which I have provided today and activate only auto on cost and activate maximum the spreading mode.

It is important that you go through the device settings once after the update and store all costs and parameters correctly. This is the basis for the auto mode.

Hey, finally I can give you some feedback. I’ve now reconfigured everything once again and I have to say that with Auto enabled and the setting on cost optimization, charging is working really well at least over the last two days. Thank you very much!

However, I still noticed a few things for which you probably already have a solution:

  1. I had Adaptive Reserve enabled together with Notstromreserve enabled, Reserve Winter set to 15%, and Reserve Äquinoktium set to 10%. Yesterday evening, Maestro did not discharge the battery after reaching 90%. I later disabled Adaptive Reserve, and immediately afterwards the discharge process started. (Screenshots) Why?

  2. Some entities are unknown in the dashboard:

2.1.: dashboards/e3dc_maestro.yaml -> Einstellungen -> Abschnitt System -> 1. Entität -> number.e3dc_maestro_powerfaktor

2.2.: dashboards/maestro_dashboards.yaml -> Dashboard -> Echtzeit Übersicht: the labels “Aktuelle Regelphase” and “Letzte Aktion” are swapped with the displayed text.

2.3.: dashboards/maestro_dashboards.yaml -> Dashboard -> Echtzeit Übersicht -> Raster Karte 4 -> Ende heute -> sensor.e3dc_maestro_saisonales_ladeende_stunde -> unknown entity

2.4.: dashboards/maestro_dashboards.yaml -> Cockpit -> Live-Tuning -> Moring-Cap 3. -> 3. Entität -> number.e3dc_maestro_moring_cap_aktiv_bis_uhr_gmt -> unknown entity

2.5.: dashboards/maestro_dashboards.yaml -> Zeitplanung -> Saisonales Ladeende & Astro-Modus -> sensor.e3dc_maestro_saisonales_ladeende_stunde -> entity not found

2.6.: dashboards/maestro_dashboards.yaml -> System -> Moring-Cap & Schonladung -> 3. Entität -> number.e3dc_maestro_morning_cap_aktiv_bis_uhr_gmt -> unknown entity

2.6.: dashboards/maestro_dashboards.yaml -> Diagnose -> Diagnose-Sensoren -> 2. Entität -> sensor.e3dc_maestro_saisonales_aldeende_stunde -> unknown entity

2.7.: When I click “Ausführen” in the help sections, I always end up on my own default dashboard page instead of your help section.

In general, I would also appreciate more information for some settings explaining what they do and how they behave. Personally, it would already be enough for me if this was documented on GitHub, because for some setting names you really have to think multiple times before understanding their purpose.

Thanks again for your work and all the updates!

Best regards,
Roedi

Hey Roedi, thanks for the detailed feedback – very helpful!

1. Adaptive Reserve blocking discharge at 90 %

This is a confirmed bug – thank you for catching it! The internal cap for the adaptive reserve calculation (adaptive_reserve_max_soc) had a default of 90 %, which is far too high for an emergency reserve. For any average 24 h house load above roughly 150 W on a typical 10 kWh battery, the formula produced a result above 90 % and got clamped to that ceiling – effectively locking the battery at ~90 % regardless of your winter/equinox settings.

Fix included in the next release:

  • Default cap lowered from 90 %35 %
  • The cap is now also exposed in the device settings, so you can adjust it if needed
  • Help section Hilfe → Adaptive Reserve updated with explanation and example

Workaround until the update: disable Adaptive Reserve – the static seasonal reserve (your 15 % / 10 % settings) will take effect immediately.


2. Unknown entities in the dashboard

Three of the issues you reported are real bugs in the dashboard YAML (now fixed in the next release):

  • number.e3dc_maestro_powerfaktor – this entity was removed in an earlier migration but the reference was left in by mistake
  • number.e3dc_maestro_morning_cap_aktiv_bis_uhr_gmt – the correct entity ID ends in _lokal, not _gmt
  • sensor.e3dc_maestro_saisonales_ladeende_stunde – correct ID is _saisonales_ladeende_uhrzeit

For the remaining issues (labels appearing swapped, “Ausführen” leading to the wrong page): these are almost certainly caused by not importing the dashboard as raw YAML. If the dashboard is edited via the UI editor, Home Assistant reorganises the YAML internally and breaks custom card features such as navigate actions and Mushroom template layouts.

Please re-import the dashboard via the raw configuration editor:

  1. Open the dashboard
  2. Three-dot menu → Edit dashboardRaw configuration editor
  3. Paste the full content of dashboards/maestro_dashboard.yaml from the latest release
  4. Save

After that, all labels and navigation buttons should work as intended.


3. Documentation

Agreed – the settings descriptions could be much clearer. I’ll continue extending the in-dashboard help pages (Hilfe → …) and the GitHub README for the less obvious parameters (Adaptive Reserve, Morning-Cap, Spreading, …).

Thanks again for the thorough report! The next release with the fixes will be out shortly.

Best,
Tommi

1 Like

Hey, thanks for your detailed reply. You’ve really been pushing out one update after another lately… I’ll definitely keep an eye on the new features over the next few days. I’ve already configured them on my side for now.

However, I already have to disappoint you regarding the dashboard help links. I imported the dashboards via RAW as described (which is how I’ve always done it), but the help pages always redirect me to the dashboard that is set as the default one.

In my setup, the Maestro dashboard is not the default dashboard, and I don’t want to configure it as the default either.

Roedi

Thanks for the report! The help buttons use hardcoded paths like /e3dc-maestro/help-..., which only works if your dashboard's URL path in HA is exactly e3dc-maestro.

Please check under Settings → Dashboards what URL slug your Maestro dashboard has. If you gave it a different name when importing (e.g. maestro or e3dc), the links won't resolve and HA falls back to the default dashboard.

Fix: Either set the dashboard's URL path to e3dc-maestro, or delete and re-create it — enter e3dc-maestro as the URL when prompted, then paste the RAW YAML as usual.

1 Like

Hey,

I noticed a few more small things:

  1. In the decision helper it sometimes says things like:
    “Seasonal charging corridor: target SoC 90% – charging power is adjusted to 200 W in order to reach the corridor as planned.”
    However, at those times the battery is usually charging with significantly less power. Unfortunately I can only attach one screenshot, but I think you probably know what I mean.

  2. The logic is actually supposed to provide smoother charging behavior, but today I noticed quite a few charging peaks throughout the day. Could you take another look at that?

PS: The issue with the help links was actually caused by me renaming the dashboards. I’ve fixed that now.

Roedi

Hey, I’ve looked into it a bit more now:

I very often have the problem that the battery only charges with around 200–300 watts, and then it doesn’t get sufficiently full by the evening. It becomes especially noticeable when it starts raining from around 4 PM, like yesterday evening.

In the evening, the target SoC suddenly increases, but the PV power is no longer sufficient to actually reach this target.

Is there any way to make the battery charge faster once the SoC cap time is reached?

I already set the gentle charging parameter to 0.45, but without any major improvement.
I also disabled Auto Mode two days ago. That actually made it worse because it kept moving the SoC cap from 10 AM to 12 PM, which reduced the available charging time by another two hours.

Roedi

Hi,

Thanks for the detailed follow-up — the screenshot and your settings make the behaviour much clearer.

Why you often see only 200–300 W

In corridor phase, Maestro does not necessarily use all available PV. Several limits stack:

  1. Gentle charging (Schonladung) — With the switch on and factor 0.45, the computed limit is multiplied by 0.45. In your screenshot that’s roughly 612 W → ~275 W (Schonladung × 45%). That matches what you see on the battery. Raising the factor from 0.35 to 0.45 does not help much while gentle charging stays enabled; for full corridor power you need the switch off or factor 1.0.
  2. Load spreading (Ladeverteilung) — By default this spreads the remaining energy evenly until charge-end time (remaining kWh ÷ remaining hours). With many hours left, that intentionally keeps charge power low even on sunny days; surplus goes to grid export.
  3. Intraday target SoC — The target on the dashboard rises through the day (linear ramp to your daily goal). If you’re behind that ramp when PV drops (e.g. rain from ~4 pm), the evening target jumps up but PV can’t catch up.
  4. Morning cap + Auto mode — Morning cap only controls when charging is allowed, not how fast it is afterwards. Auto optimisation can push “active until” later (e.g. 10 → 12 o’clock) to reduce midday curtailment — that matches your experience when disabling Auto made things worse.
  5. Charge ramp (Anlauf) — Power increases only by X W per cycle; that can keep you in the low hundreds of watts for a while.

There is no separate “turbo after morning cap” mode. After the cap time, normal corridor/spreading rules still apply.

Faster charging — practical steps

Goal Suggestion
Much more power in corridor Turn gentle charging off or set factor to 1.0
Use midday PV instead of export Try disabling load spreading (trade-off: less smooth profile)
More charging time Earlier morning cap “active until” (e.g. 9–10 h), or keep Auto on and override the cap hour if needed
Catch up when SoC is low Enable fast-charge floor (full PV surplus until floor SoC, e.g. 30–40%)
Less ramp lag Increase charge power ramp (W/cycle)
Late shortfall only After configured charge-end hour, Maestro can remove the cap if SoC is still below target — helps late gaps, not rain at 4 pm

Reference config that works well (example from a live system)

For comparison, here is a setup on a ~19 kWp / 17.5 kWh system (Maestro 0.3.7) that charges aggressively when PV is available:

  • Gentle charging: OFF (not 0.45)
  • Advanced corridor: ON, lower/upper 1500 / 9000 W
  • Fast-charge floor: ON until 30% SoC (full PV surplus below that)
  • Load spreading: ON, daily target 100%, summer charge-end 18:00
  • Morning cap (manual): OFF; Auto mode: ON (cost objective) — optimises only morning cap timing, not gentle charging
  • Min charge power: 50 W (not 300 W)
  • PV forecast delay: ON, with 30% SoC floor so charging isn’t blocked when the battery is still low

Full parameter list (for copy/compare):
beispiel-konfiguration-betrieb.md (GitHub)

Suggested order to try

  1. Disable gentle charging (or factor 1.0) and watch “Letzte Aktion” — the Schonladung × …% line should disappear and limits should be much higher.
  2. If still too slow at midday: disable load spreading temporarily and see if the battery uses more of your PV.
  3. Revisit morning cap / Auto: earlier “active until” gives a longer effective window.
  4. Enable fast-charge floor if you often start the day low.

If you can post another screenshot after step 1 (phase + “Letzte Aktion” + target charge power), we can narrow it down further.

Hope that helps — cheers