Skip to content

Use actual EV SoC to limit provisional Intelligent Octopus slots used in the Predbat plan #4482

Closed

Description

@Speshman

With an EVSE-controlled Intelligent Octopus Go setup, Octopus controls my Zappi V2 but cannot see the vehicle’s actual SoC. It therefore allocates charging slots based on its own assumption that the car needs enough energy to reach the 100% target configured in Octopus.
Predbat does have the real vehicle SoC through car_charging_soc, together with car_charging_battery_size and car_charging_limit.
The current sequence is often:

  1. Octopus initially allocates more dispatch slots than the car actually needs.
  2. Predbat treats all those slots as future cheap-rate periods.
  3. Predbat freezes or protects the home battery during early slots and plans to charge it during later slots.
  4. The car reaches its real charge limit earlier than Octopus expects and stops drawing power.
  5. Octopus then removes the unused future slots.
  6. Predbat’s planned home-battery charging opportunity disappears, leaving the battery undercharged.
    Could Predbat use the configured real car SoC, battery size and charge limit to estimate the remaining EV energy requirement, then limit the Intelligent Octopus slots it relies on when planning the home battery?
    For example:
    remaining EV energy =
    battery size × (charge limit - current SoC) / 100
    Allowing for the configured charging efficiency or energy scale where appropriate.
    Predbat should continue protecting the home battery from discharging into the car during expected charging slots. However, slots beyond the calculated EV requirement should be considered provisional and should not be relied upon for deferred home-battery charging.
    octopus_intelligent_consider_full helps once the car is full, but it does not fully address the earlier planning problem because Predbat may already have deferred battery charging into surplus slots that later disappear.
    Related: Odd car charging - IOG, Zappi and dumb car #3978 (Odd car charging - IOG, Zappi and dumb car #3978).

Activity

  1. Speshman commented on Aug 11, 2026

    @Speshman
    SponsorContributorAuthor

    Possible implementation
    Looking at current main, most of the required SoC calculation already exists.
    Octopus.load_octopus_slots() in apps/predbat/octopus.py already uses car_charging_soc, car_charging_limit, car_charging_loss and octopus_intelligent_consider_full to:

    • Cap expected EV energy at the remaining battery capacity.
    • Split the final required dispatch into a positive-kWh prefix and zero-kWh remainder.
    • Set subsequent car slots to zero kWh.
      The remaining problem is the separate tariff path. Fetch currently calls:
      import_rates = self.rate_add_io_slots(
      car_n,
      import_rates,
      self.octopus_slots[car_n],
      )
      rate_add_io_slots() processes the original uncapped Octopus dispatches, so every dispatch is added to rate_import as a future cheap period. The home-battery optimiser therefore continues to rely on surplus slots even though car_charging_slots says the car will already be full.
      A possible low-impact implementation would be:
    1. Keep load_octopus_slots() as the source of expected EV charging.
    2. Build a set of 30-minute settlement periods covered by entries in self.car_charging_slots[car_n] where kwh > 0.
    3. When adding Intelligent rates, only apply the cheap-rate override to future periods in that set.
    4. Preserve completed and currently active dispatch periods because their cheap rate is already confirmed.
    5. Preserve the whole 30-minute settlement period if any part contains expected charging.
    6. Leave the underlying tariff unchanged for excluded dispatches, so fixed IOG off-peak periods remain cheap naturally.
      Illustrative logic inside rate_add_io_slots():
      expected_blocks = set()

    if self.octopus_intelligent_limit_future_slots:
    for car_slot in self.car_charging_slots[car_n]:
    if car_slot.get("kwh", 0) <= 0:
    continue

        block_start = (car_slot["start"] // 30) * 30
        block_end = ((car_slot["end"] + 29) // 30) * 30
        expected_blocks.update(range(block_start, block_end, 30))
    

    current_block = (self.minutes_now // 30) * 30
    Then, before applying an Intelligent cheap-rate override:
    slot_block = (minute // 30) * 30

    if (
    self.octopus_intelligent_limit_future_slots
    and slot_block > current_block
    and slot_block not in expected_blocks
    ):
    continue
    For compatibility, this could be a new expert-mode switch, defaulting to off, for example:
    octopus_intelligent_limit_future_slots
    It could require or imply octopus_intelligent_consider_full. Alternatively, the existing switch could be extended, but that would change its documented behaviour, which currently says all Octopus slots remain low-rate.
    Suggested tests:

    • EV needs two of five dispatches: only the first two future periods modify rate_import.
    • The final required charge ends part-way through a dispatch: the whole touched settlement period remains cheap.
    • Car is already at its limit: no unstarted dispatches modify the tariff.
    • Current and completed dispatch periods remain cheap.
    • Feature disabled: existing behaviour remains unchanged.
    • Multi-car dispatches are capped independently and their accepted periods are combined.
    • Fixed 23:30-05:30 IOG off-peak rates remain unaffected.
      This should not require changes to prediction.py or the native prediction kernel because both already consume the resulting car_charging_slots and rate_import data.
  2. chalfontchubby commented on Aug 11, 2026

    @chalfontchubby
    Collaborator

    Nice writeup - thanks. I suspect that was why I switched back to having octopus control my car rather than the charger. Fly in the ointment includes cases when a guest car gets plugged in that isn't visible to predbat.

    Somewhat related to #4270 - where I'm trying to guard against the house switching to charge the battery in a 30 min slot that octopus have granted, but in which the car does not start to charge (you were not plugged in, there were gremlins in the cloud, whatever). In that case Octopus can revoke to cheap slot after it began, so you end up paying full price for energy you thought was cheap. If I can get that or something similar merged it would help prevent charging on slots that get revoked (because the car is full as in your suggestion) but would not prevent predbat planning based on the slots - I suspect both aspects are useful.

  3. chalfontchubby commented on Aug 11, 2026

    @chalfontchubby
    Collaborator

    I'll push a patch to address your suggestion and retract 4270 since it's been sitting there so long. I should be able to do something similar with automations.

    I use a vw integration to pull the car doc but that seems to loose read privileges around every week requiring a reauthentication with 2 factor - bit of a pain. I can see soc via octopus since I have the car registered as a device rather than the charger, tried both but losing fine grain control of my charger wasn't great - octopus set the hypervolt into super eco so any pv being exported went to the car rather than earning more than charging at cheap rate.

  4. chalfontchubby commented on Aug 11, 2026

    @chalfontchubby
    Collaborator

    Thanks for the detailed write-up and implementation sketch - that made this straightforward to build. Opened #4483, which follows the shape you proposed pretty closely: an expected_blocks set built from car_charging_slots[car_n] (only the blocks the car's real SoC/limit still needs positive kWh for), used to gate rate_add_io_slots()'s low-rate treatment for future out-of-window slots only - current/completed dispatches and the fixed 23:30-05:30 window are unaffected regardless.

    One difference from the sketch: it's a plain new switch (octopus_intelligent_limit_future_slots, expert mode, default Off) rather than extending octopus_intelligent_consider_full's existing behaviour, to avoid changing what that switch already means for people relying on it - but it does require consider_full to also be on to do anything (warns at startup if not), matching what you flagged.

    @chalfontchubby noted this is related to (but distinct from) #4270 - that one guards against a slot being revoked for reasons unrelated to the car's SoC (not plugged in, a cloud/EVSE gremlin, etc.), which this SoC-based capping wouldn't catch. Both are worth having.

  5. Speshman commented on Aug 12, 2026

    @Speshman
    SponsorContributorAuthor

    Thanks. in case you need any further info I captured a real charging session that demonstrates the delayed withdrawal of surplus Intelligent dispatches.
    Setup

    • BMW 225xe connected through a Zappi V2
    • Octopus controls the Zappi and cannot see the BMW SoC
    • BMW SoC available separately to Predbat
    • Initial BMW SoC: 3%
    • Octopus target: 100%
    • octopus_intelligent_consider_full: On
    • Predbat car charging rate: 3.6 kW
    • Predbat charging loss: 12%
      Initial plan
      Octopus initially allocated approximately 16.37 kWh, including dispatches extending until 04:30.
      Predbat used the real BMW SoC and initially forecast the car reaching 100% at approximately 03:05. It assigned zero EV demand after that point, despite Octopus continuing to advertise later dispatches.
      What actually happened
      The BMW reported 100% at approximately 02:17 BST. The Zappi changed to Completed and its charging power fell to zero.
      Immediately afterwards, Octopus still advertised future dispatches through 04:30, including:
      02:00-04:00 7.278 kWh
      04:00-04:30 0.614 kWh
      Predbat reacted to the real 100% SoC and recalculated all remaining car demand to zero, but the unused Octopus dispatches remained visible temporarily.
      Approximately 15 minutes later, Octopus shortened the remaining plan to:
      02:00-02:30 1.8195 kWh
      02:30-02:33:57 0.2396 kWh
      The previously advertised period from approximately 02:34-04:30 had disappeared.
      This confirms the sequence described in this issue:
    1. Octopus continues advertising surplus future slots after the car has stopped charging.
    2. There is a delay before Octopus detects the lack of demand.
    3. Octopus then withdraws or shortens the unused future dispatches.
    4. Predbat can know earlier that these slots are surplus because it has the real vehicle SoC.
      This particular session did not leave the house battery undercharged because all withdrawn slots were within the guaranteed 23:30-05:30 IOG off-peak period. The underlying tariff therefore remained cheap after the dispatches disappeared.
      However, it provides direct evidence that surplus dispatches really are withdrawn after a delay. If the same sequence occurs with daytime out-of-window dispatches, Predbat could defer house-battery charging into a slot that subsequently disappears. This supports the approach in PR fix(octopus): don't rely on future IOG dispatch slots the car no longer needs #4483 of excluding future out-of-window dispatch blocks once the real car SoC shows they are no longer required.
  6. Speshman commented on Sep 7, 2026

    @Speshman
    SponsorContributorAuthor

    New live daytime reproduction: car needs 0.11 kWh, but Predbat retains the full 5.259 kWh dispatch window for house-battery planning

    I have captured a new live example of the condition described in this issue. This is a useful reproduction because the Intelligent dispatch is during the daytime, outside the guaranteed 23:30–05:30 Intelligent Octopus Go period.

    Predbat correctly determines that the car needs almost none of the energy in the Octopus dispatch. However, the complete 90-minute dispatch remains represented as a cheap rate and is used in the house-battery plan.

    Environment

    • Predbat: v8.55.0
    • Home Assistant: 2026.9.1
    • Tariff: Intelligent Octopus Go
    • Cheap rate: 3.993p/kWh
    • Normal daytime rate: 29.3222p/kWh
    • Vehicle: BMW 225xe
    • EVSE: Myenergi Zappi V2
    • Octopus controls the Zappi rather than the vehicle
    • Predbat receives the BMW's actual SoC separately
    • Single car
    • Car charge rate configured in Predbat: 3.6 kW
    • Car charging loss: 12%
    • Car energy scale: 1.0
    • octopus_intelligent_consider_full: On
    • Predbat manual car SoC: Off
    • Predbat car smart plan: Off
    • Octopus Intelligent smart charging: On
    • Zappi plug state: EV Connected
    • Zappi state before the dispatch: Paused
    • Actual car charging power before the dispatch: 0 kW
    • Home-battery usable capacity reported to Predbat: 13.62 kWh

    This means the planned car slots described below originate from the Octopus Intelligent dispatch, not Predbat's separate smart car-charging planner.

    Timestamped snapshot

    The main snapshot was captured at:

    2026-09-07 10:18:37 BST
    

    At that point:

    BMW source SoC:             99%
    Predbat car SoC state:      100%
    Car charging power:         0.0 kW
    Zappi plug state:           EV Connected
    Zappi status:               Paused
    Octopus Intelligent state:  SMART_CONTROL_IN_PROGRESS
    Dispatch active now:        No
    Next dispatch:              10:30–12:00 BST
    

    The BMW SoC source had most recently reported at 08:57:30 BST.

    Octopus planned dispatch

    The Octopus Energy integration advertised this future SMART dispatch:

    {
      "start": "2026-09-07T10:30:00+01:00",
      "end": "2026-09-07T12:00:00+01:00",
      "charge_in_kwh": -5.259,
      "source": "SMART"
    }

    The negative energy sign is the convention used by the integration. Its magnitude is a planned 5.259 kWh charge.

    Two additional SMART dispatches were present for the following morning:

    2026-09-08 01:00–04:00: 10.518 kWh
    2026-09-08 04:30–05:00:  0.5965 kWh
    

    Those later dispatches fall inside the normal guaranteed IOG period and are not the focus of this report.

    The relevant daytime dispatch is the 10:30–12:00 period.

    Source tariff data

    The Octopus current-day rate event already supplied all three half-hours of the daytime dispatch at the Intelligent-adjusted rate:

    Period Rate is_intelligent_adjusted
    10:00–10:30 29.3222p/kWh absent/false
    10:30–11:00 3.993p/kWh true
    11:00–11:30 3.993p/kWh true
    11:30–12:00 3.993p/kWh true
    12:00–12:30 29.3222p/kWh absent/false

    The Octopus integration's next-rate sensor also reported:

    Start: 2026-09-07 10:30 BST
    End:   2026-09-07 12:00 BST
    Rate:  0.03993 GBP/kWh
    

    This confirms that the discounted values are already present in the source rate feed before Predbat's explicit Intelligent-slot rate handling.

    Predbat's EV-demand calculation

    Predbat did not assign the full Octopus energy to the car.

    At 10:18 BST, binary_sensor.predbat_car_charging_slot contained:

    planned:
      - start: "09-07 10:30:00"
        end: "09-07 10:32:00"
        kwh: 0.11
        average: 3.99
        cost: 0.44
    
      - start: "09-07 10:32:00"
        end: "09-07 12:00:00"
        kwh: 0
        average: 3.99
        cost: 0

    It also assigned zero car energy to both later overnight SMART dispatches.

    Therefore, Predbat's EV calculation concluded:

    Octopus dispatch energy:        5.259 kWh
    Predbat expected EV energy:     0.110 kWh
    Surplus dispatch energy:        5.149 kWh
    Positive EV demand:             approximately 2 minutes
    Remaining zero-demand period:   approximately 88 minutes
    

    A plan cycle captured around 10:10 BST had estimated 0.28 kWh for the car. By 10:18 BST, this had been refined to 0.11 kWh. Both calculations make the same underlying point: practically the whole 90-minute dispatch is surplus to the car's actual requirement.

    This demonstrates that the octopus_intelligent_consider_full path is working for the EV load forecast. The problem is not that Predbat expects the car to consume all 5.259 kWh.

    Predbat's tariff representation

    Despite assigning zero EV demand after 10:32, Predbat retained the Intelligent rate through noon:

    10:00–10:30: 29.32p/kWh
    10:30–12:00:  3.99p/kWh
    12:00 onward: 29.32p/kWh
    

    The predbat.rates transition data was:

    2026-09-07T10:00:00+0100: 29.32
    2026-09-07T10:30:00+0100: 3.99
    2026-09-07T11:30:00+0100: 3.99
    2026-09-07T12:00:00+0100: 29.32

    Thus the EV-demand path knows that the car no longer needs the dispatch from 10:32, but the tariff path continues to expose all three settlement periods as cheap.

    This is the same separation originally identified in this issue: capping car_charging_slots does not itself remove or restore the already Intelligent-adjusted rate used by the home-battery optimiser.

    Resulting house-battery plan

    At the time of the snapshot, the home battery contained:

    10.49 kWh / 13.62 kWh
    Approximately 77%
    

    Predbat expected it to fall to about 75% before the dispatch and created this best charge window:

    Start:        10:30 BST
    End:          12:00 BST
    Average rate: 3.99p/kWh
    Target:       10.37 kWh / 76%
    

    The detailed plan showed:

    Time Car energy Home-battery action Home-battery target
    10:30 small positive amount Chrg at up to 3.00 kW 76%
    11:00 0 kWh HoldChrg 76%
    11:30 0 kWh HoldChrg 76%
    12:00 0 kWh Demand normal operation

    The optimiser therefore planned around the whole discounted period even though Predbat's own car plan had positive EV demand for only the first two minutes.

    The house-battery target in this particular reproduction is close to its current SoC, so this snapshot does not demonstrate a large undercharge or financial loss by itself. It does, however, directly demonstrate the planning condition in #4482: future house-battery behaviour is being selected using cheap settlement periods that Predbat already knows the car does not need.

    Why this reproduction is useful

    The earlier live reproduction posted here showed Octopus withdrawing surplus slots after the vehicle finished, but those withdrawn slots were inside the guaranteed overnight cheap period. The underlying tariff remained cheap, so that example could not demonstrate the daytime planning risk.

    This new case is the daytime counterpart:

    • The dispatch is outside 23:30–05:30.
    • The car is already at 99%.
    • Predbat expects only 0.11 kWh of EV charging.
    • Predbat explicitly assigns zero EV energy from 10:32–12:00.
    • The Octopus rate feed marks every half-hour from 10:30–12:00 as Intelligent-adjusted.
    • Predbat retains the whole period at 3.99p.
    • Predbat creates a house-battery charge/hold window covering the whole period.

    This is close to the scenario originally described in the issue.

    Expected conservative behaviour

    Using the settlement-block approach previously discussed, the first 10:30–11:00 block could remain trusted because it contains the two minutes of positive expected EV demand.

    The following blocks contain no expected EV demand and are outside the guaranteed tariff window:

    11:00–11:30
    11:30–12:00
    

    Those are the clearest surplus blocks in this reproduction.

    A SoC-based future-slot limiter could restore those blocks to the normal underlying tariff for planning purposes and clear their io_adjusted markers, while leaving the EV charging forecast unchanged.

    This is narrower than rejecting all provisional Intelligent dispatches. It asks only whether Predbat should rely on future out-of-window blocks that its own real-SoC calculation says the car will not need.

    Relationship to subsequent PRs

    My installed v8.55.0 predates the related recent work.

    This reproduction does not settle the broader billing question raised on #4885. It does not yet prove that Octopus will withdraw the surplus 11:00–12:00 period, nor whether those periods would ultimately be billed at the Intelligent or normal rate.

    What it does prove is that the original planning mismatch remains reproducible: Predbat knows from the real car SoC that nearly all the dispatch is unnecessary, but still uses every source-adjusted half-hour when planning the house battery.

    Evidence still to collect

    Useful follow-up evidence from this same event would be:

    • Whether the planned 10:30–12:00 dispatch remains, shortens or disappears after the car stops drawing.
    • Whether started_dispatches records only the part in which the car actually charges.
    • Whether completed_dispatches records the relevant settlement periods.
    • Whether the Octopus rate event continues to mark 11:00–12:00 as Intelligent-adjusted after any dispatch withdrawal.
    • The final billed rate for household import during each affected half-hour.
    • The feat(octopus): log a diagnostic IOG dispatch timeline (#4516 Stage 1) #4948 dispatch timeline after an official stable Predbat release containing it is installed.

    I can provide those as a follow-up if the relevant data becomes available.

    Questions for maintainers

    Does this reproduce the original #4482 condition as intended?

    Given that the car-need calculation reduces the dispatch to 0.11 kWh and zeroes the remaining 88 minutes, would it be reasonable to revisit the SoC-based gate separately from the broader planned versus started versus completed trust policy discussed on #4885?

    If the expected behaviour is that all three daytime half-hours should remain trusted despite only two minutes of predicted EV demand, what billing or API evidence would best establish that the surplus periods remain guaranteed at the Intelligent rate?

    No Predbat settings were changed during this capture.

    Drafted with assistance from OpenAI GPT-5.6 Sol.

  7. Speshman commented on Sep 12, 2026

    @Speshman
    SponsorContributorAuthor

    Follow-up: the surplus daytime blocks were withdrawn and their source rates reverted

    I can now complete the timeline for the 7 September reproduction described above using retained Home Assistant history.

    Timeline

    At 10:18 BST, the previously reported state was:

    • Octopus planned dispatch: 10:30-12:00, 5.259 kWh
    • BMW source SoC: 99%
    • Predbat expected EV energy: 0.11 kWh
    • Positive EV demand: 10:30-10:32
    • Zero EV demand: 10:32-12:00
    • Source rate feed: 3.993p/kWh, is_intelligent_adjusted: true, for 10:30-12:00
    • Predbat planned the home battery around the complete cheap period

    The subsequent history is:

    Time (BST) Evidence
    10:30:29 Octopus rate sensor changed to 3.993p/kWh, covering 10:30-12:00, with is_intelligent_adjusted: true
    10:30:48 Intelligent dispatch entity became active with the complete 10:30-12:00 planned dispatch
    11:00:23 predbat.rates changed so only 10:30-11:00 remained at 3.99p; the rate from 11:00 reverted to 29.32p
    11:00:29 The Octopus source-rate sensor also reverted to 29.3222p from 11:00, with is_intelligent_adjusted: false
    11:00:48 The dispatch became inactive and was shortened to 10:30-10:56:13; started_dispatches recorded 10:30-11:00

    This confirms that the surplus future periods:

    • 11:00-11:30
    • 11:30-12:00

    were withdrawn after Predbat had already used them as future cheap periods in its house-battery plan.

    What this establishes

    The 10:30-11:00 block genuinely started and remained cheap. It had not yet appeared in completed_dispatches, so this supports the maintainer's point that requiring completed_dispatches alone would be too strict.

    However, the two later blocks did not start. They disappeared from the dispatch and both the source integration and Predbat restored the normal rate from 11:00.

    This is the narrower #4482 condition:

    1. Predbat knows from the real EV SoC that the later blocks are not needed.
    2. Predbat nevertheless uses those provisional blocks as future cheap household periods.
    3. Octopus subsequently withdraws them.
    4. The rate correction happens only after an earlier house-battery decision may already have been made.

    This event did not demonstrate a material financial loss because the planned home-battery target was close to its existing SoC. It does demonstrate the planning dependency and subsequent withdrawal.

    Relationship to #5012 and #4889

    #5012 shows a related second path: EV-load filtering can work while a stale discounted rate remains in rate_import_base. A complete solution therefore needs to account for source-adjusted rates as well as rates stamped directly from dispatches.

    #4889 addresses deriving SoC for cars without a real SoC sensor. This reproduction already had a real BMW SoC sensor, so measurement-backed SoC tracking would not by itself address the separate future-rate trust problem.

    Official Octopus guidance

    Octopus's May 2026 explanation says:

    • if smart charging starts during a half-hour, the whole half-hour is off-peak for the EV and home;
    • if the EV is unplugged before the scheduled half-hour begins, neither receives the lower rate.

    https://octopus.energy/blog/intelligent-octopus-go-charge-limit/

    That supports preserving the current/started 10:30-11:00 block while not treating the unstarted 11:00-12:00 surplus blocks as guaranteed. The article says the newer four-rate/Charge Cap behaviour is being rolled out account-by-account, so final billing evidence remains useful where rollout status is uncertain.

    Would this evidence support reconsidering the original narrow SoC-based gate separately from the broader planned/started/completed trust policy?

    Specifically: preserve the fixed 23:30-05:30 window and any half-hour in which managed charging has started, but avoid planning the house battery around future out-of-window blocks which Predbat's own real-SoC calculation says the car will not need.

    Drafted with assistance from OpenAI GPT-5.6 Sol.

  8. chalfontchubby commented on Sep 12, 2026

    @chalfontchubby
    Collaborator

    That would be my preferred position. Trust the overnight slot and any slots with confirmed charging.

    Do not trust other future slots.

    Charge opportunistically if a slot is used by the car.

    @springfall2008 - can we head in that direction somehow?

  9. Speshman commented on Sep 13, 2026

    @Speshman
    SponsorContributorAuthor

    Second live case: home-battery freeze planned in future blocks with zero EV demand

    Thanks @chalfontchubby for #4948 and for confirming the preferred direction. The timeline approach should be particularly useful for this new live example.

    I have another EVSE-controlled IOG session in progress today, 13 September 2026, on Predbat v9.0.2.

    The current 15:30–16:30 dispatch is genuine: the Zappi is charging at approximately 3.505 kW. That block is not the concern.

    Future dispatch versus actual EV requirement

    The Octopus integration currently advertises:

    15:30–16:30     3.5060 kWh
    21:30–00:30    10.5180 kWh
    00:30–01:00     0.1065 kWh
    

    The BMW source SoC was 56% when the plan was calculated.

    Predbat applies the real SoC and reduces the future EV requirement to:

    15:30–16:30     3.51 kWh
    21:30–21:56     1.49 kWh
    21:56–00:30     0.00 kWh
    00:30–01:00     0.00 kWh
    

    predbat.car_soc forecasts:

    16:30            86.89%
    21:55            99.50%
    22:00           100.00%
    

    Predbat therefore knows that the car has no demand after approximately 21:56.

    Home-battery plan

    Despite that, Predbat retains the complete 21:30–01:00 period as a cheap home-battery charge window:

    21:30–01:00
    Rate:       3.99p/kWh
    Target:     2.8 kWh / 25%
    

    The home-battery forecast is:

    21:30       4.945 kWh
    22:00       3.395 kWh
    22:30       2.956 kWh
    01:00       2.956 kWh
    

    It falls to approximately 2.956 kWh and then remains flat through 01:00, consistent with Predbat planning to freeze the battery during the latter part of the surplus dispatch.

    The source rate feed currently marks the future 21:30–23:30 periods as Intelligent-adjusted. The fixed IOG period begins at 23:30, so the most relevant surplus dynamic blocks are:

    22:00–22:30
    22:30–23:00
    23:00–23:30
    

    They contain no predicted EV demand but remain available to the home-battery optimiser.

    This is a pre-withdrawal snapshot. The useful follow-up will be whether Octopus shortens the dispatch after the BMW reaches its target, and whether Predbat's planned freeze disappears or moves as a result.

    Timeline logging

    I expected #4948 to produce a Dispatch timeline heartbeat at 15:30, but I cannot find one in the Supervisor add-on log around that boundary despite the active dispatch and Predbat v9.0.2.

    @chalfontchubby, thank you for adding #4948. Is the timeline written only to the Predbat web log's All view rather than the add-on log output? If so, I will extract that view when the future surplus blocks are withdrawn.

    Relevant Predbat status log excerpt
    2026-09-13 15:30:26 Predbat completed run: Freeze charging, target 71%
    2026-09-13 15:31:59 Predbat completed run: Charging, target 71%-82%
    2026-09-13 15:35:04 Predbat completed run: Charging, target 73%-82%
    

    Drafted with assistance from OpenAI GPT-5.6 Sol.

  10. Speshman commented on Sep 13, 2026

    @Speshman
    SponsorContributorAuthor

    Recovered #4948 timeline: surplus blocks overlap the home-battery plan

    A quick apology to @chalfontchubby: I initially searched the Supervisor/add-on output and local AppDaemon logs, but did not check Predbat's separate All log stream as suggested. Thank you for pointing me in the right direction.

    The timeline messages are deliberately written quietly to Predbat's own log, so they appear in Log → All but not in the Supervisor output I first checked.

    The relevant 15:30 heartbeat is:

    2026-09-13 15:30:01.389488: Octopus: Dispatch timeline car 0 @ 09-13 15:30:00 [-4h..+24h]: ....CC..pp..........Ppppppp.............................
    

    At 15:30 the 56-character timeline starts at 11:30. The future Ppppppp group therefore maps to:

    21:30  P
    22:00  p
    22:30  p
    23:00  p
    23:30  p
    00:00  p
    00:30  p
    

    P means a planned dispatch. Lowercase p means that the planned dispatch overlaps Predbat's previous-cycle home-battery charge plan.

    Predbat's EV forecast in the accompanying snapshot assigned positive car demand only until approximately 21:56 and zero from 21:56–01:00. The timeline therefore directly confirms that the zero-EV-demand period from 22:00–01:00 overlapped the home-battery plan, including the disputed out-of-window blocks from 22:00–23:30.

    The subsequent change-triggered entries corroborate the timeline:

    2026-09-13 15:30:50.357339: Octopus: Dispatch timeline car 0 @ 09-13 15:30:00 [-4h..+24h]: ....CC..sp..........Ppppppp.............................
    2026-09-13 15:35:01.528478: Octopus: Dispatch timeline car 0 @ 09-13 15:35:00 [-4h..+24h]: ...CCC.ssp.........pppppppp............................. *
    2026-09-13 15:55:01.190301: Octopus: Dispatch timeline car 0 @ 09-13 15:55:00 [-4h..+24h]: ...CCCCssp.........pppppppp............................. *
    

    This is the #4948 evidence that was missing from my preceding comment. It confirms the planning overlap before any later dispatch withdrawal; because the car had to be unplugged, this event cannot provide a clean SoC-driven withdrawal outcome.

    Drafted with assistance from OpenAI GPT-5.6 Sol.

  11. 2 remaining items

  12. Speshman commented on Sep 15, 2026

    @Speshman
    SponsorContributorAuthor

    Follow-up evidence: connected EV reached 100%; 06:30 dispatch disappeared and rates reverted

    Capture integrity

    • Predbat: v9.0.2
    • Structured observation window: 2026-09-14 19:59:28 to 2026-09-15 07:14:54 BST (+01:00)
    • The collector completed normally at 07:15:54.
    • The JSONL contains 598 valid, chronological snapshots. The largest gap is 241 seconds, outside the critical changes described below; approximately one-minute snapshots are present around 01:30-01:40 and throughout 06:30-07:00.

    Initial state

    At 19:59:

    • BMW SoC was 63% and the Zappi reported Charging at approximately 3.54 kW.
    • Predbat predicted 4.20 kWh of EV demand:
      • 1.75 kWh during 19:30-20:00
      • 2.45 kWh during 20:30-21:12
      • 0 kWh after 21:12, including the planned 06:30-07:00 dispatch
    • Octopus advertised these SMART dispatches:
      • 19:30-20:00
      • 20:30-21:30
      • 23:00-23:30
      • 01:30-02:00
      • 02:30-04:00
      • 04:30-05:00
      • 06:30-07:00
    • The 06:30-07:00 source rate was 3.993p/kWh with is_intelligent_adjusted: true; Predbat represented it as 3.99p/kWh.
    • Despite assigning that dispatch 0 kWh of EV demand, Predbat scheduled a home-battery top-up from 06:30 to 07:00, initially targeting 11.3 kWh / 100%. Its forecast rose from 10.570 kWh at 06:30 to 11.148 kWh at 07:00.

    Material chronology

    All times are BST.

    Time EV and dispatch evidence Rate evidence Home-battery evidence
    19:59 BMW 63%; Zappi Charging at 3.54 kW. The 06:30-07:00 dispatch was planned for approximately 0.60 kWh, while Predbat assigned it 0 kWh of EV demand. Source adjusted to 3.993p; Predbat 3.99p. 06:30 target 11.3 kWh/100%; forecast 10.570 → 11.148 kWh; Predbat status Charging.
    20:02-20:05 BMW rose to 80%; Zappi changed to EV Connected and EV power fell to zero. Predicted EV demand reduced to 2.27 kWh. The 06:30 dispatch remained. 06:30 remained cheap and adjusted. The 06:30 top-up remained.
    20:55 The 06:30 dispatch still remained. Still cheap and adjusted. 06:30 target reduced to 10.3 kWh/91%, but was not removed.
    23:30 EV remained connected and idle. Guaranteed-period rate was cheap. Home battery began charging at approximately 2.89 kW; Predbat status changed to Charging.
    00:30-00:35 A new Octopus dispatch started. Zappi changed from EV Connected to Charging and reached approximately 3.5 kW. Cheap overnight rate. Home battery continued charging.
    00:59-01:25 BMW progressed through 96% to 100%. Zappi changed to Waiting for EV, charging power fell to zero, and Predbat's total predicted EV demand reached 0.0 kWh at 01:25. The 06:30 slot still carried 0 kWh EV demand. The 06:30 slot remained adjusted and 3.99p. Home battery reached 100% and Predbat changed to Hold charging.
    01:28:39 The 06:30-07:00 dispatch remained advertised. Still adjusted and cheap. The 06:30 target was still present at 10.738 kWh; forecast was flat at 10.738 kWh through 07:00.
    01:30:40 The dispatch remained advertised for the full 06:30-07:00 interval. Still adjusted and cheap. Predbat removed the 06:30 charge target. The forecast changed from 10.738 kWh at 06:30 to 10.440 kWh at 07:00, showing discharge rather than a top-up. No replacement charge target appeared nearby.
    01:34:41 The 06:30-07:00 interval remained, but its advertised energy estimate had reduced to approximately 0.255 kWh. It had not started or completed. Still adjusted and cheap. The 06:30 target remained absent.
    01:37:43 BMW remained 100%. Zappi changed from Waiting for EV to EV Connected, not disconnected. The 06:30-07:00 dispatch disappeared completely from the planned list. It was never shortened in time, started or completed; only its estimated energy reduced before withdrawal. Source changed to 29.3222p/kWh with is_intelligent_adjusted: false. Predbat still showed its stale 3.99p entry in this snapshot. The top-up had already been removed about seven minutes earlier; no further 06:30 plan change occurred with the withdrawal.
    01:40:44 The 06:30 slot also disappeared from Predbat's EV plan. The EV remained connected and idle. Predbat removed the 06:30 3.99p boundary. Its preceding 05:30 rate was 29.32p, so the effective 06:30 period was no longer cheap. The 06:30 charge target remained absent; forecast still fell from 10.739 kWh at 06:30 to 10.441 kWh at 07:00.
    02:16 The completed list gained the actual 01:00-01:30 portion of the overnight charging session. No 06:30 completion ever appeared. Normal source rate remained in effect for 06:30. No 06:30 target.
    05:30 EV remained connected at 100% and zero power. 06:30 remained at the normal rate. Predbat left Hold charging and changed to Demand.
    06:30-07:00 The car remained EV Connected throughout, with 0 kW EV charging. The withdrawn dispatch did not start or complete. Source remained unadjusted at the normal rate; Predbat had no cheap 06:30 override. No charge target was present. Predbat remained in Demand; actual battery power stayed positive, approximately 352-482 W, and SoC fell from 97% to 96% rather than topping up.
    07:14:54 BMW remained 100%, Zappi remained EV Connected, and EV power remained zero. No cheap 06:30 rate remained. No 06:30 target remained.

    #4948 timeline evidence

    The smallest useful sequence is:

    2026-09-15 01:30:01.235233: Octopus: Dispatch timeline car 0 @ 09-15 01:30:00 [-4h..+24h]: ......cs..pppppp..p.....................................
    2026-09-15 01:34:34.628570: Octopus: Dispatch timeline car 0 @ 09-15 01:30:00 [-4h..+24h]: ......CSs.pppppp..P.....................................
    2026-09-15 01:40:01.856151: Octopus: Dispatch timeline car 0 @ 09-15 01:40:00 [-4h..+24h]: .....ccss............................................... *
    

    For the first two lines, the @ 01:30 origin means character zero represents 21:30 the previous evening. The 06:30 slot is therefore the character 18 positions into that line. It changes from p to P while the dispatch itself remains planned.

    The third line has its own @ 01:40 origin, so character zero represents 21:40. The 06:30-07:00 interval falls across the later characters appropriate to that shifted origin; those positions are dots after the dispatch was withdrawn. It should not be compared character-for-character with the first two lines without accounting for that ten-minute origin shift.

    P, S and C represent planned, started and completed dispatch state without prior-cycle battery-plan overlap. Lowercase p, s and c represent the same dispatch states with overlap. The lowercase-to-uppercase change records that the overlap disappeared while the dispatch remained; lowercase does not establish that the dispatch caused the battery plan.

    Observed facts and interpretation

    Observed:

    • The car reached 100% and remained physically plugged through and beyond the final advertised dispatch time. After charging stopped, the Zappi reported Waiting for EV and then EV Connected; no disconnected state was captured.
    • The 06:30-07:00 dispatch initially had zero predicted EV demand but an associated home-battery top-up.
    • Predbat removed that top-up at 01:30 while the dispatch and cheap adjusted rate were still present.
    • The dispatch's energy estimate later reduced, then the dispatch disappeared at 01:37 without starting or completing.
    • The source rate reverted immediately in the 01:37 snapshot. Predbat retained its stale cheap entry for approximately three further minutes, then removed it.
    • Predbat did not retain or move the 06:30 top-up after the dispatch disappeared; it had already removed it and continued forecasting discharge across that period.
    • The battery actually discharged during 06:30-07:00.

    Interpretation:

    This succeeded as the intended clean follow-up because the car was not deliberately unplugged before the last dispatch and the captured plug state confirms it remained connected through 07:00. The evidence shows that a provisional out-of-window dispatch can initially influence Predbat's home-battery plan despite zero calculated EV demand, and that both the dispatch and its Intelligent-adjusted cheap rate can later disappear.

    The ordering does not prove that dispatch withdrawal caused removal of the home-battery target: the target disappeared approximately seven minutes before the dispatch and source-rate withdrawal. The snapshots also do not establish why Octopus withdrew the dispatch. Sampling bounds the observed transitions to the listed snapshot times rather than proving sub-minute ordering inside each interval.

    Maintainer input requested

    @springfall2008, when you have an opportunity, could you please take a look at this evidence and confirm whether it supports addressing the future-slot trust behaviour described in #4482?

    I appreciate that Predbat is maintained in your free time. It would be helpful to know whether this evidence is useful, whether the issue remains actionable, and whether there is any additional supporting evidence or a different test scenario you would like me to collect.

    Drafted with assistance from OpenAI GPT-5.6 Sol.

  13. chalfontchubby commented on Sep 15, 2026

    @chalfontchubby
    Collaborator

    I've restarted work on one of the pr we had in flight. Maybe not based on EV Soc, but initially not trusting future slots until the car is seen charging. That does cover not trusting slots that would exceed the target soc - because it doesn't trust any future slots. For me that is a more general case - but it does then prevent PB exploiting cheap dynamic slots.
    It should prevent/reduce loss due to high priced charging or relying on slots that disappear, but it doesn't maximise the gains of exploiting the extra cheap slots . Lets see where that gets us then iterate.

  14. Speshman commented on Sep 25, 2026

    @Speshman
    SponsorContributorAuthor

    Following the closure of #5110 in favour of #5229, I wanted to check the status of this narrower request. #5229's new opt-in future-slot trust switch looks useful for avoiding reliance on any unconfirmed dispatch, but it does not use the car's real SoC to distinguish future blocks it still needs from surplus blocks Octopus may withdraw. The #5110 closing comment also notes that #4482 is untouched by either PR.

    The live withdrawal and source-rate reversal evidence already posted above remains the reason for this request. Could #4482 remain open as a separate, selective SoC-based follow-up after #5229?


    Drafted with assistance from OpenAI GPT-6 Sol.

  15. chalfontchubby commented on Sep 25, 2026

    @chalfontchubby
    Collaborator

    Yes - keep this open for your issue.I might let 5229 settle for a while and see what else we learn from it. I'm pretty battle scared from 5110 and what went before and will try and land some of my other long lasted pr next

  16. Speshman commented on Sep 30, 2026

    @Speshman
    SponsorContributorAuthor

    Follow-up: first completed trial with octopus_intelligent_trust_slots Off

    I tested the opt-in trust switch from #5229 on an EVSE-controlled IOG setup: BMW 225xe with real SoC supplied to Predbat, Octopus controlling a Zappi V2. consider_full and ignore_unplugged remained On. Predbat ran v9.3.2 during the 29–30 September cycle. All times below are BST.

    The switch did help before charging was confirmed. On 29 September, Predbat saw Octopus’s overnight and 07:30–08:00 planned dispatches, but showed the future car energy as cancelled (?). Its import-rate plan kept 07:30–08:00 at the normal 29.32p/kWh, while preserving the guaranteed 23:30–05:30 cheap tariff.

    Octopus then added an early 18:00–18:30 dispatch and the Zappi began charging. At approximately 18:03, Predbat changed the future 07:30–08:00 rate to 3.99p/kWh. Its car plan nevertheless assigned that future slot 0 kWh. The rate and car-demand paths had diverged again: a confirmed earlier dispatch caused a later, unneeded one to be treated as cheap.

    Overnight, the BMW first reported 100% at 02:54 and the Zappi stopped charging. At 03:03, the Octopus entity still advertised 07:30–08:00; Predbat’s 03:05 rate plan still showed it at 3.99p, with 0 kWh of car demand. At 03:15, the next recorded Octopus update omitted the 07:30 dispatch. Predbat’s car plan was empty by 03:20, and its 03:35 rate plan had returned 07:30 to 29.32p. These are Home Assistant observation times, not necessarily the precise time Octopus changed its upstream plan.

    My private notes from 25–26 and 27–28 September record two earlier 07:30–08:00 withdrawals after the BMW reported full. Those were before this trust-slots trial; this new cycle adds evidence of what happens with the switch Off. None of these observations establishes why Octopus withdrew a slot or what final billing would have been. For this latest cycle, I also cannot show that the house battery selected a 07:30 top-up or incurred a loss.

    I see that #5304 has merged and is included in v9.3.3, which is installed here now. This cycle ran on v9.3.2, before that release. #5304 improves the modelling of a vanishing dispatch, but appears separate from #5229’s rule that seeing the car charge in one slot can make later slots trusted.

    Could future out-of-window settlement blocks with zero forecast EV demand remain provisional after an earlier dispatch has been confirmed, while preserving the fixed 23:30–05:30 tariff and blocks where managed charging has actually started? In this setup the rate feed can already contain an Intelligent-adjusted price, so the question covers that source-adjusted rate as well as Predbat’s own dispatch overlay.

    Drafted with assistance from OpenAI GPT-6 Sol.

  17. chalfontchubby commented on Sep 30, 2026

    @chalfontchubby
    Collaborator

    Not forgotten about you, but there are a few bits of fallout to deal with from 5229 as well. Want to let the dust settle.

  18. Speshman commented on Sep 30, 2026

    @Speshman
    SponsorContributorAuthor

    Just thought I'd grab some new examples as some changes had the potential to impact the issue. I will continue to log and report back any issues/improvements provided by #5304

  19. Speshman commented on Oct 4, 2026

    @Speshman
    SponsorContributorAuthor

    Now running v9.3.4 with the same settings. #5319 addresses preserving a started half-hour, but does not appear to resolve #4482’s separate future zero-demand slot concern. I have not yet verified that behaviour on this release, so I’m not claiming a new reproduction or a fix.

  20. Speshman commented on Oct 5, 2026

    @Speshman
    SponsorContributorAuthor

    Follow-up with a recorded example on v9.3.5, overnight 5 October. All times below are BST (UTC+1).

    • 02:31:57: Actual BMW SoC reached 100%.
    • 02:33:36: Predbat recognised the car was full and forecast 0 kWh EV charging in the advertised 07:30–08:00 dispatch:
      {'start': 450, 'end': 480, 'kwh': 0.0, 'average': 3.8,
       'cost': 0.0, 'soc': 10.0, 'octopus': True}
      
      Nevertheless, its home-battery plan still included:
      05-10 07:30:00 - 05-10 08:00:00 @ 3.8p 87%
      
    • 02:35:50: On detecting that the car was no longer charging, Predbat logged:
      car 0 is in a dispatch but not charging, cancelling its slots -
      keeping the dispatch rate until 10-05 03:00:00 as it charged in this half hour
      
      It removed the future 07:30–08:00 cheap rate and charging window.
    • 02:48:30: The Octopus integration’s dispatch list also withdrew that future slot. The car remained plugged in.

    This shows a useful mitigation: stop-charging detection removed the future rate before Octopus withdrew the slot, while preserving the started half-hour.

    However, the separate #4482 concern remains observable beforehand: a future slot with zero forecast EV demand was still treated as cheap and selected for home-battery charging.

    I’m not claiming financial loss or home-battery undercharging from this example.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions