Skip to content

fix(octopus): count the Intelligent daily cap in dispatch minutes, not half-hour blocks - #5512

Open
springfall2008 wants to merge 5 commits into
mainfrom
fix/octopus-cap-exact-minutes-5510
Open

springfall2008 wants to merge 5 commits into
mainfrom
fix/octopus-cap-exact-minutes-5510

Conversation

@springfall2008

Copy link
Copy Markdown
Owner

This is an automated draft PR generated from issue #5510 — a maintainer should review it before merging.

Fixes #5510

Summary

The Octopus Intelligent daily cap (octopus_slot_max, 6 hours on IOG-SMB) was counted in 30-minute blocks rounded outwards, so a 10-minute dispatch used 30 minutes of it, and the two counters disagreed with each other. Both now count the dispatch's own minutes:

  • Completed dispatches: the start and end Octopus sends, taken as correct.
  • Planned dispatches: the exact planned start and end.
  • Real charging time inside a dispatch is not worked out; that is left to Octopus.

rate_add_io_slots() (rates) and load_octopus_slots() (car plan) now charge the budget through one shared helper, take_cap_minutes(). octopus_slot_max is still set in 30-minute slots in apps.yaml and multiplied out internally, so existing configs are unchanged.

Behaviour changes to check

  • The half hour the budget runs out in stays cheap for the house. The rates are still stamped by whole plan periods: a period with any dispatch minute inside the budget is cheap throughout. The car plan splits at the exact minute. This was the open point in the issue; say if the rates should cut off at the exact minute instead.
  • rate_add_io_slots() now takes dispatches earliest first, as load_octopus_slots() already did, so the budget goes to the same dispatches in both. It used to take them in the order given.
  • The debug log line is now Octopus: Intelligent slot minutes for day N: X of Y max, in minutes.
  • Capped installs will see more dispatches priced off-peak than before whenever their dispatches do not line up with half hours. Uncapped tariffs (48 slots) are effectively unaffected.

Testing

  • New cases in test_rate_add_io_slots.py (run_cap_minutes_tests), each run through both counters: a short completed dispatch, two dispatches in one half hour, overlapping completed and planned dispatches, and a dispatch that crosses the end of the budget.
  • Fails without the fix, passes with it: with octopus.py reverted, rate_add_io_slots fails on all four new cases (rates and car plan); with the fix, rate_add_io_slots and octopus_slots both pass.
  • Existing expectations in test_octopus_slots.py that encoded block counting were updated: eight 60-minute dispatches from 14:05 used to hit the cap after four (three blocks each) and now hit it after six.
  • unit_test.py --quick: all tests passed (4 slow tests skipped).
  • pre-commit passes on the five changed files.

Notes

  • Remaining ways the two counters can differ, all there before this change and left alone:
    • load_octopus_slots() clamps dispatches to today, so it does not see the part of the current midday-to-midday period that fell before midnight; rate_add_io_slots() does.
    • With octopus_slot_low_rate: false the car plan counter does not run at all.
    • Minutes withheld on the rates side (car seen not charging, or no car needs them) use no budget there, and the car plan has no equivalent.
  • The cap is still per car (octopus_slot_max is derived per account but enforced per car #5215), the period is still midday to midday keyed on the dispatch's start, and a past dispatch with zero kWh still uses no budget.
  • Whether Octopus really measures the cap in minutes cannot be checked from the repo; this follows the maintainer's direction on the issue.
  • GitNexus impact reports no callers for either function, because they are reached through the PredBat mixin. By search the callers are fetch.py (both) and output.py (load_octopus_slots()); detect_changes rates the change medium.

🤖 Generated with Claude Code

…t half-hour blocks (#5510)

rate_add_io_slots() charged one 30-minute block per half hour a dispatch
touched and load_octopus_slots() charged max(1, blocks spanned) per dispatch,
so a 10-minute dispatch used 30 minutes of the cap and the two counters
disagreed. Both now charge the dispatch's own minutes, as Octopus sends them
for a completed dispatch and as planned for one still to come, through one
shared helper. octopus_slot_max stays in 30-minute slots in apps.yaml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@springfall2008 springfall2008 self-assigned this Oct 12, 2026
@springfall2008
springfall2008 marked this pull request as ready for review October 12, 2026 17:23
Copilot AI balanced review requested due to automatic review settings October 12, 2026 17:23
…th counters (#5510)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Active zero-kWh dispatches still consume different cap durations in the rate and car-plan counters.

1 open finding
What changed in this PR

Fixes #5510 by accounting for Octopus Intelligent caps in dispatch minutes rather than rounded half-hour blocks.

Changes:

  • Adds shared minute-based cap accounting.
  • Aligns rate and car-plan behavior and updates tests.
  • Clarifies configuration documentation.
File Description
apps/​predbat/​octopus.py Implements minute-based cap accounting.
apps/​predbat/​tests/​test_rate_add_io_slots.py Adds cap regression cases.
apps/​predbat/​tests/​test_octopus_slots.py Updates car-plan expectations.
docs/​car-charging.md Documents minute-based accounting.
docs/​apps-yaml.md Clarifies configuration units.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/predbat/octopus.py
CI and others added 3 commits October 13, 2026 20:44
…its start (#5510)

load_octopus_slots() moved the start of a running dispatch with zero kWh to now
before charging the daily cap, so the car plan counted only what was left of it
while rate_add_io_slots() counted the whole dispatch. The part already gone is
now kept as a part with no load: it goes through the same overlap handling,
uses the budget and emits no car slot.

Eligibility and the budget's midday-to-midday period now go by the whole
dispatch for every part of it, as they do in the rates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Octopus Intelligent 6-hour cap counts rounded half-hour blocks, not the dispatch minutes Octopus reports

2 participants