hass.tibber_prices/docs/user/versioned_docs/version-v0.31.0/plan-charging-action.md

7.8 KiB
Raw Permalink Blame History

Plan Charging Action

The plan_charging action turns battery parameters into a complete cost-minimized charging schedule. Instead of manually computing energy, duration, and power, you describe the battery (capacity, current SoC, target SoC, max power) and the action returns a per-interval plan with SoC progression, cost totals, and segment grouping.

:::warning Experimental The plan_charging action is experimental and still undergoing testing. Its parameters, response format, and behavior may change in future releases. Use it in automations with care, and please report any issues. :::

:::tip When to use this If you already know the duration in minutes and just need the cheapest time window, use find_cheapest_hours or find_cheapest_block. Use plan_charging when you know your battery/EV parameters and want the integration to compute the duration, account for charging losses, and produce a SoC progression. :::

At a Glance

Situation Example
Home battery: "Charge from 20% to 80%, efficiency 0.92" current_soc_percent: 20, target_soc_percent: 80, battery_capacity_kwh: 10
EV with 3-phase charger: "Use 1/2/3 phases as needed" charge_power_steps_w: [1380, 4140, 11000]
Battery with modulation: "30 W 1200 W continuous" min_charge_power_w: 30, max_charge_power_w: 1200
Deadline-aware: "At least 50% before next peak" must_reach_soc_percent: 50, must_reach_by_event: next_peak_period
Arbitrage: "Only charge if later discharge is profitable" expected_discharge_price: 0.28, reserve_for_discharge: true

Required Inputs

Field Description
max_charge_power_w Maximum charging power in watts (upper bound for every interval).
current_soc_percent or current_soc_kwh Current battery state of charge.
target_soc_percent or target_soc_kwh Desired battery state of charge.
battery_capacity_kwh Required when you use percent values.

All other inputs (deadline, power steps, grid limit, economics, search range) are optional.

Choosing Between Fixed / Continuous / Stepped Power

Mode Trigger Behavior
Fixed Only max_charge_power_w set Every selected interval charges at full power. Last interval may over-shoot the target slightly (rounding up).
Continuous Add min_charge_power_w Planner can reduce the final partial interval down to the minimum power — no over-shoot.
Stepped Add charge_power_steps_w: [a, b, c] Planner picks the smallest allowed step that covers the remaining energy. Mutually exclusive with min_charge_power_w.

Deadlines

Combine a minimum SoC with a deadline:

  • must_reach_soc_percent / must_reach_soc_kwh — the minimum you need by the deadline.
  • Then pick one of:
    • must_reach_by — absolute datetime.
    • must_reach_by_event — one of midnight, next_peak_period, next_best_period_end.

The planner runs a two-pass schedule: first guarantee the minimum SoC before the deadline using the cheapest pre-deadline intervals, then fill the remaining target with the cheapest intervals from the full search range.

Economics (Arbitrage)

For "charge cheap now, discharge expensive later" use cases:

  • discharging_efficiency — fraction still usable when discharged (default 1.0).
  • expected_discharge_price — expected price per kWh at discharge time (in your configured display unit).
  • reserve_for_discharge — when true, discards intervals that are unprofitable given the round-trip efficiency.
  • max_cost_per_kwh — a hard ceiling; any interval above this price is discarded before scheduling.

The response's economics.break_even_price tells you the maximum charging price at which the round-trip still breaks even.

Examples

Home battery — charge from 20% to 80% overnight

Show YAML
service: tibber_prices.plan_charging
data:
  battery_capacity_kwh: 10
  current_soc_percent: 20
  target_soc_percent: 80
  charging_efficiency: 0.92
  max_charge_power_w: 2500
  search_scope: remaining_today
response_variable: plan

EV — 3-phase, at least 50% before next peak period

Show YAML
service: tibber_prices.plan_charging
data:
  battery_capacity_kwh: 60
  current_soc_percent: 30
  target_soc_percent: 80
  must_reach_soc_percent: 50
  must_reach_by_event: next_peak_period
  max_charge_power_w: 11000
  charge_power_steps_w: [1380, 4140, 11000]
  grid_import_limit_w: 16000
response_variable: plan

Battery arbitrage — only if profitable

Show YAML
service: tibber_prices.plan_charging
data:
  battery_capacity_kwh: 10
  current_soc_percent: 10
  target_soc_percent: 100
  charging_efficiency: 0.92
  discharging_efficiency: 0.92
  expected_discharge_price: 0.28   # ct/kWh value expected when discharging
  reserve_for_discharge: true
  max_charge_power_w: 3000
  search_scope: next_48h
response_variable: plan

Response Structure

The response contains the following top-level keys:

Key Description
intervals_found true when a schedule was produced.
battery Normalized SoC / capacity / efficiency / achieved_soc_kwh (what you actually reach with the returned schedule).
charging Mode, total duration, total energy, total cost, and the schedule block.
charging.schedule segments[], intervals[], segment_count, seconds_until_start, seconds_until_end, and price statistics.
deadline Present when a deadline was set — includes must_reach_by, must_reach_soc_kwh, achieved_soc_kwh, deadline_met.
economics Present when any economic parameter was set — includes break_even_price, expected_net_savings, round_trip_efficiency.
price_comparison Difference between the selected schedule and the most expensive equivalent window.
relaxation_applied / relaxation_steps Whether the schedule was relaxed to fit available data.
reason Stable reason code when no schedule was found (see below).

Per-Interval Fields

Each entry in charging.schedule.intervals[] includes:

  • starts_at, ends_at, price, level, rating_level
  • power_w — power assigned to this interval (watts)
  • grid_energy_kwh — energy drawn from the grid
  • stored_energy_kwh — energy actually stored after losses
  • soc_after_kwh, soc_after_percent — cumulative SoC after this interval

Reason Codes

When no schedule is found, reason contains one of:

Code Meaning
already_at_target Current SoC is already at or above target — no charging needed.
no_data_in_range The search range has no price data.
no_intervals_matching_level_filter min_price_level / max_price_level filtered everything out.
no_intervals_after_economic_filter max_cost_per_kwh or reserve_for_discharge filtered everything out.
energy_unreachable The energy needed cannot be charged within the available intervals + power limits.
energy_unreachable_by_deadline The minimum SoC cannot be reached before the deadline with the available intervals.
selection_above_distance_threshold min_distance_from_avg is not satisfied by the cheapest selection.