Repository navigation
Ohme: without ohme_control Predbat plans its own car charge that nothing carries out; take the plan from Ohme instead #5399
Description
Summary
With ohme_automatic: true, ohme_control off and a tariff that is not Octopus Intelligent, Predbat builds its own car charging plan and models it as load, but nothing carries that plan out: Ohme keeps charging to its own schedule. The plan Predbat shows can be completely different from what the charger will do.
When Predbat is not controlling the charger, the car plan should come from Ohme. Today there is no configuration that does this without also treating the slots as Octopus Intelligent dispatches.
What happens
OhmeAPI.automatic_config() sets:
car_charging_planned→binary_sensor.predbat_ohme_connected(on whenever a car is plugged in and wants charge)car_charging_soc→sensor.predbat_ohme_battery_percent
octopus_intelligent_slot is only pointed at binary_sensor.predbat_ohme_slot_active when octopus_intelligent_wanted() is true (Intelligent tariff detected, or ohme_automatic_octopus_intelligent: true). Otherwise fetch_sensor_data_car_planning() takes the elif self.car_charging_planned[car_n] or self.car_charging_now[car_n] branch and calls plan_car_charging().
So on any other tariff, plugging the car in makes Predbat plan a charge from the Ohme SoC to the limit, starting in the first available low-rate window. With ohme_control off, that plan is never sent to the charger.
Example (one install, 5 Oct 2026, Cosy-style three-rate tariff, v9.3.x)
Ohme's own session, as published on binary_sensor.predbat_ohme_slot_active:
planned_dispatches: [{start: 2026-10-05T01:18:17+0100, end: 2026-10-05T08:37:28+0100, energy: -56.22, location: AT_HOME}]
sensor.predbat_ohme_status = plugged_in, sensor.predbat_ohme_mode = max_charge, sensor.predbat_ohme_power_watts = 0
Predbat's plan at 08:10 the same morning:
Car 0 plan charging from 28.0kWh to 100.0% (100.0kWh), with slots [...], ready by 07:00:00
Car 0 charging plan is: [{'start': 490, 'end': 780, 'kwh': 35.767, 'average': 31.56, 'cost': 1128.8, 'octopus': False},
{'start': 780, 'end': 960, 'kwh': 22.2, 'average': 15.48, 'cost': 343.66, 'octopus': False},
{'start': 1140, 'end': 1305, 'kwh': 20.295, 'average': 31.56, 'cost': 640.5, 'octopus': False}]
That is 78 kWh and about £21 of car charging in the plan, with "hold for car" on most of the day's slots, while the charger is drawing 0 W and Ohme's own session ends at 08:37. The plan re-forms every cycle for as long as the car stays plugged in.
Two things make it worse, though neither is the cause:
car_charging_battery_sizewas left at the 100 kWh default, so 28 % was read as 72 kWh to add.- The Ohme battery percent is an estimate. On this install it sat at exactly 19 for six days, and read 28 the morning after a 21 kWh session.
Why the existing options do not cover it
ohme_control: truemakes the plan real, but hands the charger to Predbat. A user who wants Ohme to keep scheduling the car has no use for it.ohme_automatic_octopus_intelligent: truedoes take the slots from Ohme, but throughoctopus_intelligent_slot, sorate_add_io_slots()also prices them as cheap dispatch windows. That is wrong on a non-Intelligent tariff (see Ohme: session slots priced as Octopus dispatch windows, and watts x duration overstates energy 2.5x #4952 for the same pricing concern).
Proposal
When ohme_automatic is on, ohme_control is off and the Intelligent wiring is not in use, take the car charging slots from Ohme's session (planned_dispatches on binary_sensor.predbat_ohme_slot_active) as car load only, with no change to import rates, instead of calling plan_car_charging().
This could be the default for that combination, or sit behind a new option (for example ohme_automatic_plan: true) if changing the default is too risky. Either way the docs for ohme_automatic should say which plan the user is looking at.
If Ohme has no session slots, Predbat should plan no car charge, and leave a car that is charging anyway to the existing dynamic load handling.
Related
- Ohme: session slots priced as Octopus dispatch windows, and watts x duration overstates energy 2.5x #4952: the slot energy is
watts x hours, which overstates what Ohme expects to deliver. The 56.22 kWh above is that calculation (7.68 kW x 7.32 h), so this proposal depends on that being fixed to give a sensible load. - Ohme can't read EVs SOC and scheduling unused charging slots, Octopus (I think) doesn't give cheap electric if car not charging #4443: Ohme cannot read the car's SoC and schedules slots that go unused.
Code references checked against main at ee401ec: apps/predbat/ohme.py (automatic_config, octopus_intelligent_wanted, control_charge), apps/predbat/fetch.py (fetch_sensor_data_car_planning), apps/predbat/plan.py (plan_car_charging).
Activity
springfall2008 commentedon Oct 5, 2026
Automated first-pass triage — this is an automated review; a maintainer will check it before any action is taken.
Classification: enhancement (design proposal — current behaviour is documented, in that
ohme_controlis the documented execution path for the car plan, but nothing tells anohme_automatic-only user which plan they are looking at). No priority set for a feature request.What I verified against main (ee401ec, v9.3.5) — every code reference in the report matches the current tree:
OhmeAPI.automatic_config()wirescar_charging_planned→binary_sensor.predbat_ohme_connectedandcar_charging_soc→sensor.predbat_ohme_battery_percent(apps/predbat/ohme.py:499-500).octopus_intelligent_slotis pointed atbinary_sensor.predbat_ohme_slot_activeonly inautomatic_config_octopus_intelligent()(apps/predbat/ohme.py:539), which runs only whenoctopus_intelligent_wanted()returns true (apps/predbat/ohme.py:463-487) — on a non-Intelligent tariff with the flag left unset it returns False.fetch_sensor_data_car_planning()takes thecar_charging_planned[car_n] or car_charging_now[car_n]branch and callsplan_car_charging()(apps/predbat/fetch.py:1410-1422) — the quoted plan lines match this code's logging exactly.enable_control()returns early whenohme_controlis false (apps/predbat/ohme.py:303-316), socontrol_charge()(driven atapps/predbat/ohme.py:297) never runs, and no other code sends the car plan to the charger — every consumer ofcar_charging_slotsis model/display-side (prediction holds, plan HTML/JSON, car sensors, compare).So the reported behaviour is real on main: with
ohme_automatic: true,ohme_control: falseand a non-Intelligent tariff, Predbat models a car charge that nothing carries out, while Ohme follows its own schedule.There is also genuinely no configuration today that reaches "Ohme's schedule as car load only":
ohme_automatic_octopus_intelligent: trueroutes the slots throughoctopus_intelligent_slot→rate_add_io_slots(), pricing them as dispatch windows (#4952), and theoctopus_intelligent_slot_action_configalternate source lands in the same IOG slot pipeline (apps/predbat/fetch.py:1487-1514).Feasibility: the proposed data source already exists —
publish_data()publishesplanned_dispatchesonbinary_sensor.predbat_ohme_slot_active(apps/predbat/ohme.py:799-818), the same attribute the standardoctopus_intelligent_slotreader consumes (apps/predbat/fetch.py:1498) — so a load-only path is new wiring, as proposed, not new plumbing.Related:
watts × hoursoverstates slot energy ~2.5x versus Ohme's ownestimatedSoc, and prices the session as IOG windows. The 56.22 kWh quoted here is exactly that formula, so an Ohme-sourced car load only makes sense once that lands.ohme_automatic, non-Intelligent setup before changing anything.No tests run — the report's claims are code-verified and this is a proposal, so there is nothing here a test would settle.
feat(ohme): take the car plan from Ohme's own schedule when Predbat i…