Repository navigation
feat(ohme): take the car plan from Ohme's own schedule when Predbat is not controlling the charger - #5401
Merged
Conversation
…s not controlling the charger With ohme_automatic on, ohme_control off and a tariff that is not Octopus Intelligent, Predbat built a car charging plan of its own that nothing carried out, while the charger followed Ohme's schedule (#5399). Ohme's session slots are now the car plan in that case, through the same path Intelligent dispatches take, but labelled as a charger schedule so they earn no cheap rate: import rates are untouched and the car is costed at the tariff, split wherever the rate changes. The choice between Intelligent dispatches, a charger schedule and Predbat-led control is re-made on every poll rather than once at start-up, so a move on or off an Intelligent tariff is followed without a restart. Fixes #5399 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Mode transitions can lose wiring or charger-release retries, and schedule pricing can use stale rates.
Review effort: Balanced
Findings: 1
Open (4)
What changed in this PR
Updates Ohme integration so Predbat models Ohme’s schedule when Predbat is not controlling the charger.
Changes:
- Adds charger-schedule dispatch handling without off-peak pricing.
- Dynamically switches between Ohme, Predbat, and Intelligent scheduling.
- Adds tests and documentation for the new behavior.
| File | Description |
|---|---|
docs/components.md |
Documents Ohme schedule behavior. |
docs/car-charging.md |
Explains plan ownership and pricing. |
apps/predbat/const.py |
Defines the charger-schedule source. |
apps/predbat/ohme.py |
Adds dynamic schedule selection and wiring. |
apps/predbat/octopus.py |
Prices charger schedules at tariff rates. |
apps/predbat/tests/test_ohme.py |
Tests Ohme modes and transitions. |
apps/predbat/tests/test_octopus_slots.py |
Tests tariff splitting and rate preservation. |
apps/predbat/tests/test_multi_car_iog.py |
Tests end-to-end car-plan selection. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…y a lost wiring or hand-back Review feedback on #5401: - load_octopus_slots() runs before the cycle's rates are built, so a charger schedule was costed on the previous cycle's rate_import: empty after a restart, a day out after midnight. The slots are now marked and priced again by reprice_charger_schedule_slots() once the rates are known, in place so a cancellation made in between is kept. - The slot wiring was only applied on the poll that changed the mode, so a session fetch or publish failing on that poll lost it for good. It is now compared against what was last wired, and made on the next poll. - A charger hand-back that failed part way was not retried, as control had already stood down. It is now retried on every poll until the charger is released. - docs: an explicit ohme_automatic_octopus_intelligent: false on an Intelligent tariff is not the first row of the table. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 5, 2026
Merged
Open
chalfontchubby
added a commit
that referenced
this pull request
Oct 6, 2026
…its own schedule stays the car plan otherwise Main's #5401 now takes the car plan from Ohme's own schedule when Predbat is not controlling the charger, so a default user already gets a plan that matches what the charger will do. Turning control on by default would override that schedule - one the user may have set up deliberately - with max charge, which also overrides the Ohme app's target. ohme_control goes back to a false default; GE and Zappi keep their automatic defaults. The size and limit guard for an unset ohme_control goes, as there is no unset default any more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes #5399.
The problem
With
ohme_automatic: true,ohme_controloff and a tariff that is not Octopus Intelligent, Predbat built a car charging plan of its own and modelled it as load. Nothing carried that plan out: the charger kept following Ohme's schedule. The issue has an example of a 78 kWh, £21 car charge in the plan while the charger was drawing 0 W.What this changes
When Predbat is not the one starting and stopping the charger, the car plan now comes from Ohme.
ohme_automaticon)ohme_automatic_octopus_intelligent: trueohme_control: trueThis is the default for the third row, with no new option. In that row:
car_charging_slots.octopus_intelligent_dynamic).car_charging_battery_size,car_charging_limitand the Ohme battery percentage no longer size the charge, because the model limit is uncapped as it is for Intelligent slots.How it works
charger-schedule. The Ohme component adds it to the dispatches it publishes onbinary_sensor.predbat_ohme_slot_activewhen in the new mode.dispatch_billed_off_peak()rejects it. That one test is shared byrate_add_io_slots()andload_octopus_slots(), so both the rate overlay and the slot cost drop the cheap rate.load_octopus_slots()priced a slot not billed off-peak at the import rate at its start. The prediction chargesmax(0, slot rate - import rate)on the car's energy, so an Ohme slot running from a dearer band into a cheaper one would have picked up a premium that does not exist.split_slot_by_rate()splitscharger-scheduleslots at each rate change. Other sources are not affected.ohme_controlfollows the same change: it stands down and releases the charger when Intelligent takes over, and resumes when it leaves.Protecting existing Intelligent setups
octopus_intelligent_slotalready points at another entity (the HA Octopus Energy integration, or the Octopus component's own dispatches), the Ohme component leaves it alone.ohme_automatic_octopus_intelligent: trueorfalseis never overridden by the tariff.Not covered
watts x hours, which overstates what the car takes. That figure now goes into the modelled car load. The docs say so.ohme_controlon, read only hands the charger back to Ohme but the plan stays Predbat's.ohme_controldefault on, that still holds, but Charger control on automatically: GE, Ohme and Zappi follow their automatic setup, Octopus per car, guest charging (stage 2, stacked on #5284) #5311 also readsis_chargerfrom theoctopus_intelligent_slotsensor, which in the new mode is Ohme's.switch.predbat_octopus_intelligent_chargingon, which is the default.Testing
test_ohme.py: when the new mode applies, the wiring, the published source, the first run in each mode, and four tariff-change tests (onto Intelligent, off it, a gap in the tariff data, and withohme_control).test_octopus_slots.py: acharger-scheduleslot is split by rate and costed at the tariff, changes no import rate and marks nothing as a dispatch; the same slot with no source is still stamped at the low rate.test_multi_car_iog.py: drives the realfetch_sensor_data_cars()andfetch_sensor_data_car_planning()to check Ohme's schedule becomes the plan,plan_car_charging()is not called, and no schedule means no plan../run_all --quickpasses.Docs: new section "Which car charging plan Predbat shows" in
docs/car-charging.md, and the Ohme entry indocs/components.md.🤖 Generated with Claude Code