Skip to content

rate_add_io_slots: 'already underway' check rounds to the 30-min block, can treat a not-yet-started dispatch as trusted #4808

Open

Description

@chalfontchubby

Follow-up from review on #4483 (raised by @Speshman, comment #4483 (comment)).

In rate_add_io_slots() (octopus.py), current_block = (self.minutes_now // 30) * 30, and each dispatch's start_minutes is floored to the same 30-minute settlement boundary before the "already underway or completed, trust it regardless of current need" check (needed = ... or (slot_start <= current_block) or ...). Because both sides are rounded down independently, a dispatch that actually starts partway through the current settlement period (e.g. 10:20) reads as already-started at any point from 10:00 onward, not just from 10:20.

Practical effect: if the car's real need changes between 10:00 and 10:20 (e.g. it's unplugged or reaches full SoC), a dispatch starting at 10:20 is still trusted as "already underway" from 10:00, when it hasn't started yet.

Proposed fix: capture the dispatch's raw (pre-floor) start time separately from the 30-min-rounded slot_start used for writing into rates[], and compare that raw start against self.minutes_now for the "already underway" decision specifically.

Scope: contained to rate_add_io_slots() in octopus.py, ~10-15 lines, plus one new test for a mid-period future dispatch start. Follow-up PR to stack on #4483.

Activity

  1. springfall2008 commented on Aug 28, 2026

    @springfall2008
    Owner

    Automated first-pass triage — a maintainer will review before any action is taken.

    Classification: bug
    Priority: priority_low (see reasoning below)

    What I checked

    This issue describes code that is not on main — it exists only in the still-open PR #4483 (fix/iog-limit-future-slots-by-ev-soc, authored by @chalfontchubby, same as this issue). I confirmed this by resetting the local clone to current main (v8.53.5-10-gc2135caa) and reading rate_add_io_slots() in apps/predbat/octopus.py directly — there is no current_block, needed, or per-slot "trust it, already underway" logic there at all yet. I then pulled PR #4483's diff to check the report against the code it actually describes.

    Verified root cause

    The report is accurate. Two things combine:

    1. Existing code on main (unrelated to fix(octopus): don't rely on future IOG dispatch slots the car no longer needs #4483, so this line number is stable): apps/predbat/octopus.py:3061 floors the dispatch's raw start to the 30-minute settlement boundary — start_minutes = (start_minutes // plan_interval_minutes) * plan_interval_minutes — before any "already underway" decision is made. The true per-minute dispatch start returned by decode_octopus_slot(..., raw=True) (minute-precision, via minutes_to_time()) is discarded at that point and never retained.
    2. PR fix(octopus): don't rely on future IOG dispatch slots the car no longer needs #4483's new check then compares two values derived from that same floored boundary — slot_start <= current_block, where current_block = (self.minutes_now // 30) * 30 — so it can't distinguish a dispatch that started exactly at the top of the block from one that starts anywhere up to 29 minutes into it.

    This isn't just theoretical: self.minutes_now (predbat.py:652) advances in PREDICT_STEP (5-minute) increments, which is finer than the 30-minute settlement block — so a real Predbat cycle at, say, 10:05 or 10:10 will indeed see current_block == 600 and trust a 10:20 dispatch as already-underway, exactly as described.

    The proposed fix (capture the raw start separately, compare it to self.minutes_now directly rather than current_block) is the right shape for a fix.

    Other checks

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions