Skip to content

battery exporting while EV charging and battery set to demand in cheap rate with IOG #5317

Closed

Description

@ragg987

apps_masked.yaml.txt
apps_live_masked.yaml.txt
predbat_debug.yaml.txt
predbat.log

Describe the bug
For the last few nights I have seen 2 issues:

  1. predbat will set battery to Export when EV is charging. Status is set to Exporting but IOG is sending a charge to EV
  2. predbat does not charge the battery when an ad-hoc late dispatch is sent. Status remains Demand despite SOC being well below 100%.

Note that I had manually intervened last night a few times so the trace may well show that predbat stopped exporting (bug 1) and it charged (bug 2).

Expected behaviour

  1. If EV is being charged the battery should not be exporting
  2. battery should take advantage of the cheap slot and charge up

Predbat version

v9.3.2

Environment details

  • Custom LIB (myenergi Libbi) inverter with 10kWh battery
  • Standard HAOS
  • Using bottlecapdave Octopus integration
  • Using myenergi integration

Screenshots
If applicable, add screenshots to help explain your problem. The most useful ones can be your battery chart, the Predbat HTML plan and your current settings in HA.

Log file
Can you capture a log file from the time of the issue, debug mode is not normally required.

You can download the logfile from the WebUI on the Dash tab select predbat.log

Predbat debug yaml file
This is important for any plan related issues.

Once you have captured the issue go to the Web UI, in the Dash tab click on predbat_debug.yaml and wait 30 seconds for it to download. Select 'keep' if your Web Browser thinks the file is dangerous.

The file arrives already named predbat_debug.yaml.txt, so upload it to GitHub as-is - no renaming needed. This will allow your plan to be reproduced and also stores all your settings for review.

If the download link does nothing (the HA Companion app's built-in browser cannot save files, it just shows the content on screen), browse to the debug/ folder under your Predbat config directory instead - with the File editor or Samba add-on - and attach a predbat_debug_<timestamp>.yaml.txt file from there. Predbat keeps a rolling history of these automatically, so there is usually one from around the time of the problem even if you had not turned debug mode on. Files captured before you upgraded to the version that added the .txt suffix keep the old plain-.yaml name until Predbat prunes them, and the per-cycle predbat_debug_HH_MM_SS.yaml files that debug mode itself writes are always plain-.yaml - rename those to .yaml.txt before attaching them.

Activity

  1. springfall2008 commented on Sep 30, 2026

    @springfall2008
    Owner

    This is an automated first-pass triage (a maintainer will review before any action is taken).

    Classification: bug. Priority: medium.

    Both symptoms have one root cause on the Octopus Intelligent side, and it plays out exactly as you describe. I reproduced the whole chain from the attached log (version confirmed as v9.3.2) — both of the symptoms you describe happened on the night it covers.

    What I found

    Predbat mis-judged the car as not charging during dispatches all night, because the only charging evidence it had was the load test, and your load data deliberately excludes the car:

    • With no car_charging_now entity configured (your apps.yaml has it commented out), dynamic_load_car_evidence() falls back to a low-load test on the house load (apps/predbat/fetch.py car_charging_now_value(), apps/predbat/plan.py:405). That test is only sound when the car's energy shows up in the load, which is what the car_energy_reported_load default (True, "inside CT clamp") assumes (apps/predbat/config.py:706).
    • Your install breaks that premise in two ways: load_today is sensor.home_consumption_energy_today_exc_zappi and load_power is sensor.home_essential_power_plus_appliances (both car-free), so the car's ~7 kW charge never appears. The log proves it: while the car was charging the per-hour lines read e.g. Last hour: ... import 8.67kWh, export 0.12kWh, car 6.16kWh, load 0.8kWh — the car's energy is known (and subtracted by the car hold) but never in the load.
    • So during every dispatch the load sits at ~0.7 kW, below the ~4.3 kW threshold which classifies the load as "low" = "no car can be charging" (dynamic_load_classify(), apps/predbat/plan.py:359). After the 5-minute grace, the car's slots are cancelled — logged at 23:45, 01:10, 03:10, 04:15, 04:40 and 08:10 as Octopus Intelligent: car 0 is in a dispatch but not charging, cancelling its slots, while the integration's completed dispatches show -2.8 to -3.5 kWh charged in those very slots.
    • Cancelling also strips the dispatch cheap price from slots outside the fixed 23:30-05:30 IOG window (dynamic_load_car_strip_feed_rates(), apps/predbat/octopus.py:3842): removed the dispatch rate from 30 minutes of cars [0] which are not charging.

    How that produced your two symptoms

    1. Battery exporting while the EV charges — once the car's slots were cancelled, the plan models no car load, so it freely chose export windows over the EV's charging slots (e.g. 03:35-04:01 exporting down to a 38% target, again 04:15-04:25 and 04:45-05:01, all during completed car dispatches). Where the slots were still trusted (e.g. 23:35-23:40) the status was Hold for car — the behaviour you expect.
    2. Battery left on Demand instead of charging a cheap slot — the 08:00-08:30 slot sat outside the 23:30-05:30 window, priced cheap only by the dispatch stamp. At 08:10:02 the false "not charging" verdict stripped that rate, the plan immediately dropped the 08:00-08:30 charge window (which had been present with target 100% since 05:30), moved the day's charging to tonight and stayed Demand with the battery at 82-88% - exactly what you describe. It then flip-flopped between plans for a few minutes as the re-plans alternated.

    I replayed the attached predbat_debug.yaml against current main (it needs --redo, as this dump is missing the pre-computed minute-step forecast data and a plain replay errors on it); the plan isn't itself diagnostic here since the snapshot caught the car outside any dispatch - the timeline above is entirely from the supplied log.

    Immediate workaround - so the state comes from the charger, not the load test, set car_charging_now to a real Zappi entity. Since v9.3.x it accepts a charging-power sensor in watts (charging from 200 W, CAR_CHARGING_NOW_POWER_W, apps/predbat/const.py:95):

    car_charging_now:
      - sensor.myenergi_zappi_22675349_charging

    Check the exact sensor id in Developer Tools as your attachment is masked - the myenergi integration publishes a charging-power sensor per Zappi.

    For the maintainer: Predbat already holds direct evidence that the car is charging - the car_charging_energy sensor rising inside the dispatch (the same signal the car hold consumes, e.g. apps/predbat/plan.py:273 area, which is also what logged car 6.16kWh). It is not consulted when car_charging_now isn't configured, so installs whose load data excludes the car (a common Zappi setup) get false "not charging" verdicts every dispatch. Related but not duplicates: #5316 (opposite direction - the car genuinely stops mid-dispatch and the cancel then removes the cheap slot for the battery), #5012 (unplugged-state handling), and #4281 (a standing request for a knob to suppress battery export while the EV charges - the policy you expect is planner economics once the car load is modelled correctly).

  2. ragg987 commented on Sep 30, 2026

    @ragg987
    Author

    workaround configured and I will watch tonight

  3. chalfontchubby commented on Sep 30, 2026

    @chalfontchubby
    Collaborator

    Where a genuine car_charging_now or car load proxy like that is available, it's always going to be better than predbat trying to guess. But it sounds from the triage like the guess is wired in the wrong place.

  4. chalfontchubby commented on Sep 30, 2026

    @chalfontchubby
    Collaborator

    For the bot - is this a configuration issue? Other than hooking up car_charging_now, are there other configuration things we should watch out that would trigger this?
    Where is sensor.home_consumption_energy_today_exc_zappi setup? Outside pb?
    Based on the configuration, without car charging now are we setup to be blind to the car?

  5. added
    BOT_REVIEWTrigger an autotriage
    and removed
    BOT_TRIAGEDHas been through the triage bot
    on Sep 30, 2026
  6. added
    BOT_TRIAGEDHas been through the triage bot
    and removed
    BOT_REVIEWTrigger an autotriage
    on Sep 30, 2026
  7. chalfontchubby commented on Sep 30, 2026

    @chalfontchubby
    Collaborator

    Posted by Claude on Rik's behalf.

    Short version: please turn off switch.predbat_car_energy_reported_load (in HA, or on the Predbat web UI config page). Your load sensors (sensor.home_consumption_energy_today_exc_zappi and sensor.home_essential_power_plus_appliances) don't include the car, but that switch is still at its default of On, which tells Predbat that they do. That mismatch caused both of the problems you saw. Keep the car_charging_now sensor you added this morning as well.

    Correction to the triage above: it found the right mechanism but the wrong fix. Setting car_charging_now helps, but on its own it leaves a second problem in place.

    With car_energy_reported_load On, Predbat believes the car's charging shows up in your house load. Your setup breaks that assumption in two ways:

    1. The dispatches get cancelled. Predbat sees the house load stay low during a dispatch and concludes that the car can't be charging, so it cancels the Intelligent slots. That's how the battery ended up exporting while the car charged, and how the 08:00 slot lost its cheap rate. The code only runs this low-load test when the switch is On, so turning it Off stops this. car_charging_now also stops it, which is why the workaround helps.
    2. Your load history is under-counted. car_charging_hold (also On) subtracts the Zappi's charged energy from your load history, so the car isn't forecast as house load. Your load already excludes the car, so this subtraction removes real house load and pushes the overnight history towards zero. car_charging_now does not fix this. Turning car_energy_reported_load Off does, because it also turns car_charging_hold off automatically.

    With the switch Off, the battery is still held while the car charges. "Hold for car" is controlled by car_charging_from_battery (Off for you), not by either of these switches. The car's energy is then modelled as coming straight from the grid, which matches how your system is wired.

    Anyone whose load sensor excludes their EV charger should turn this switch Off.

    @ragg987 could you turn the switch Off and let us know after the next night or two whether it's fixed? If we don't hear back, this issue will be closed automatically in about a week.

  8. 5 remaining items

  9. springfall2008 commented on Sep 30, 2026

    @springfall2008
    Owner

    This is an automated follow-up triage review (a maintainer will review before any action is taken).

    What's new since the last review — no new attachments arrived: the reporter confirmed the car_charging_now sensor is configured (they're watching tonight), @chalfontchubby asked questions addressed to the triage bot, and a follow-up posted on Rik's behalf recommended turning switch.predbat_car_energy_reported_load off as the real fix, calling the earlier car_charging_now-only advice incomplete.

    I re-verified the correction's code claims against current main (v9.3.2-46-g57ec7bf1) and they all hold:

    • The low-load fallback that mis-classified the car as "not charging" — cancelling IOG dispatches and stripping their cheap rates — runs only when car_energy_reported_load is On: it sits inside if self.car_energy_reported_load: (plan.py, apps/predbat/plan.py:405); with the switch Off, dynamic_load_car_evidence() returns "no evidence" and there is no mid-dispatch cancel from the load test.
    • car_charging_hold is force-cleared when the switch is Off (fetch.py, apps/predbat/fetch.py:3379, mirrored in the ML component apps/predbat/load_ml_component.py:71), so the second problem — the Zappi session kWh being subtracted from a load series that already excludes the Zappi (get_filtered_load_window(), apps/predbat/fetch.py:381, clamped at zero) — also goes away with the switch.
    • The discharge hold while the car charges applies regardless of the switch (execute.py, apps/predbat/execute.py:769 — it keys on the charging-now state and car_charging_from_battery, explicitly commented as applying "regardless of car_energy_reported_load"). car_charging_from_battery defaults to False (apps/predbat/config.py:954) and your apps.yaml doesn't set it, so "the battery is still held while the car charges" with the switch Off is correct as stated.

    So the correction is accurate; the car_charging_now sensor you added this morning stays, and the switch is what fixes the load-history under-count.

    Answers to the questions posted for the bot:

    • Is this a configuration issue? At the trigger level, yes: car-free load sensors against a default-On car_energy_reported_load (with car_charging_hold following it by default) is exactly the mismatch the switch exists to express, so the framing as configuration is right. It's a particularly easy trap because both switches default On, and nothing warns that the dispatch-cancel test is running on load evidence you never feed it. Priority stays medium.
    • Where is sensor.home_consumption_energy_today_exc_zappi set up? Not by Predbat — load_today in apps.yaml only references it. It must be defined in your HA configuration (utility meter / template sensor on the Energy dashboard), which is also why it can be car-free while Predbat assumes the opposite.
    • Without car_charging_now, was this setup blind to the car? For dispatch supervision, yes: nothing live reported charging state, so the low-load test stood in — and it judges on load alone, it never consults the Zappi energy sensor, which was the only evidence showing the car charging (~6 kWh/h) in the same hours it said "low". Planning and energy accounting were not blind (the Intelligent slot sensor and the Zappi session energy were both read), which is how the battery got held in the slots Predbat still trusted.
    • Other configuration things to watch out for that trigger this? The tripwire to remember: with octopus_intelligent_trust_slots Off (the dynamic mode you're on) and no car_charging_now sensor, Predbat now warns "car(s) [0] have no car_charging_now sensor and are outside the CT clamp, so their Intelligent slots will never be trusted" (apps/predbat/plan.py:577) — that warning firing is the sign the car is effectively unsupervised. If the sensor ever gets removed again, re-check the switch first.

    Assessment — classification and priority are unchanged from the first pass (mechanism as reported, configuration-framed trigger, medium). Two housekeeping notes: the GitHub events API call to establish who applied the configuration label was blocked by permissions in this run, so I have left every label untouched except as stated below; and since the reporter's overnight result with the switch off is still outstanding, I have re-applied waiting_for_user so your next reply triggers another review.

  10. ragg987 commented on Sep 30, 2026

    @ragg987
    Author

    I have updated switch.predbat_car_energy_reported_load in the UI, now off

    Interesting the sensor history shows that the sensor value was - on 22 Sep, and went to default on on 23 Sep @ 13:55. This sensor also does not appear in my apps.yaml. I wonder if this is a new switch and code since ~ 23 Sep update? That might explain why I've not noticed this behaviour before. Prior to this I don't recall battery discharge and EV charge happening concurrently.

    Will monitor and report.

  11. springfall2008 commented on Sep 30, 2026

    @springfall2008
    Owner

    This is an automated follow-up triage review (a maintainer will review before any action is taken).

    What's new since the last review — the reporter has turned switch.predbat_car_energy_reported_load off, so the recommended fix is now applied, and added a timeline observation worth answering: HA's entity history shows the switch unknown (-) on 22 Sep and default-on from 23 Sep 13:55, they note the switch doesn't appear in their apps.yaml, and they ask whether this is new switch/code since the ~23 Sep update — which would explain why they had never seen battery discharge and EV charging happening concurrently before. They're still monitoring and will report back.

    Is it new code? Verified from git history at current main (v9.3.2-46-g57ec7bf1, the same commit the last review used — no relevant new commits have landed since):

    • The switch is not new: car_energy_reported_load was added in New feature to supress car charging hold and correctly model car chargers outside CT clamp #3455 (commit a422ec07, 2026-02-28; shipped in v8.33.8, Feb 2026). Not appearing in apps.yaml is expected — it exists as an HA switch Predbat creates, so it's only in apps.yaml if you put it there.
    • The cancelling behaviour is new, and the instinct behind the question is right in substance: the whole "car is in a dispatch but not charging → cancel its slots and strip the IOG cheap rate" machinery is from commit 079509ca (2026-09-25, plus three same-week review fixes; its parent commit contains no cancellation code at all) and first shipped in v9.3.0 (2026-09-26). The earlier "not charging" work (ae888204, 14 Sep, v9.1.0) only added a display flag. So before v9.3.0 a false "not charging" verdict could not cancel your dispatches: the car's slots were always trusted and the battery was held for the car through them ("Hold for car") — which is exactly why concurrent EV-charge plus battery discharge was never seen on this setup before. On v9.3.2 the false verdicts cancel slots and un-stamp cheap rates, which is what produced both symptoms in the log reviewed earlier.
    • On the exact timing: the 23 Sep -→on flip is an entity-history artefact of an update/restart rather than the code arriving then — v9.3.0 didn't exist until 26 Sep. Your upgrade window (~23 Sep) and the feature's arrival (26 Sep, first run as v9.3.x two days later) genuinely coincide though, and the default-On switch only became consequential when the new supervision code began acting on it — v9.3.2 (28 Sep) was two days old when the attached log was captured.

    Assessment — unchanged from the last review, and re-confirmed at the same HEAD: mechanism as re-verified then (the mis-classifying low-load test runs only under if self.car_energy_reported_load: at apps/predbat/plan.py:405; car_charging_hold force-clears with the switch off at apps/predbat/fetch.py:3379), classification bug with a configuration-framed trigger, priority medium. With the switch off plus the real car_charging_now charging-power sensor now configured, the misfiring load test is out of the picture entirely and dispatch supervision keys on the charger's own evidence — a car only gets cancelled mid-dispatch now if it genuinely isn't charging (the case #5316 tracks, in the opposite direction). Nothing further is needed from configuration.

    Duplicate check — the gh search API was permission-blocked in this run, so the check ran via the issue tracker's search instead: no other open report of this failure direction. Nearest neighbours remain #5316 (opposite direction — genuine mid-dispatch stop; now carries a "fixed" label) and #5286 (closed — the io_adjusted-wipe regression that made the strip a no-op, fixed by PR #5290, already in v9.3.2). Neither is a duplicate of this ticket.

    Since the overnight verification of the fix is still outstanding ("will monitor and report"), waiting_for_user has been re-applied so the next reply triggers another review.

  12. chalfontchubby commented on Sep 30, 2026

    @chalfontchubby
    Collaborator

    I've submitted #5320 to attempt to warn when car we believe car load is included in the house load but can see a car load that indicates otherwise.
    The docs do suggest using car_charging_energy to exclude other non-car loads (heat pump) from the predbat visible load, but that seems highly questionable given the name of it.
    It means we cannot assume car_charging_energy increasing means that a car is indeed charging, but changing the name would disrupt a number of users that followed the old guidance.
    #5318 is filed to consider that.

  13. gcoan commented on Oct 2, 2026

    @gcoan
    Collaborator

    The docs do suggest using car_charging_energy to exclude other non-car loads (heat pump) from the predbat visible load, but that seems highly questionable given the name of it.

    @chalfontchubby car charging energy has certainly been used by some people if they want to exclude some energy sources from the prediction. eg a conservatory heater used occasionally

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

Metadata

Metadata

Labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions