hass.tibber_prices/custom_components/tibber_prices/services.yaml
Julian Pawlowski b93eedf00e feat(services): add power-profile-weighted window selection
Add `include_current_interval` parameter to `find_cheapest_block` and
`find_cheapest_schedule` services, controlling whether the currently
active price interval can be the start of the selected window.

Add power-profile weighting to `find_cheapest_contiguous_window`: accepts
an optional `power_profile` list that weights each interval's price by
relative power draw (e.g. heat-up phase heavier than steady state). Without
a profile the behaviour is unchanged (uniform weighting).

Extend search-range tests and add price-window unit tests covering weighted
and unweighted scenarios, edge cases, and sequential scheduling interactions.
Update scheduling-actions documentation with parameter and profile examples.

Impact: Users can now model appliances with non-uniform power draw (e.g. heat
pumps, washing machines) to find truly cheapest windows based on actual energy
cost rather than average price.
2026-05-03 22:16:08 +00:00

1498 lines
35 KiB
YAML

get_price:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices
start_time:
required: true
example: "2025-11-01T00:00:00+01:00"
selector:
datetime:
end_time:
required: true
example: "2025-11-02T00:00:00+01:00"
selector:
datetime:
get_apexcharts_yaml:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices
day:
required: false
example: today
selector:
select:
options:
- yesterday
- today
- tomorrow
- rolling_window
- rolling_window_autozoom
translation_key: day
level_type:
required: false
default: rating_level
example: rating_level
selector:
select:
options:
- rating_level
- level
translation_key: level_type
resolution:
required: false
default: interval
example: interval
selector:
select:
options:
- interval
- hourly
translation_key: resolution
price_source:
required: false
default: total
example: energy
selector:
select:
options:
- total
- energy
- tax
translation_key: price_source
highlight_best_price:
required: false
default: true
example: true
selector:
boolean:
highlight_peak_price:
required: false
example: false
selector:
boolean:
get_chartdata:
fields:
general:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices
selection:
collapsed: true
fields:
day:
required: false
selector:
select:
options:
- yesterday
- today
- tomorrow
multiple: true
translation_key: day
resolution:
required: false
default: interval
example: hourly
selector:
select:
options:
- interval
- hourly
translation_key: resolution
price_source:
required: false
default: total
example: energy
selector:
select:
options:
- total
- energy
- tax
translation_key: price_source
filters:
collapsed: true
fields:
level_filter:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
multiple: true
translation_key: level_filter
rating_level_filter:
required: false
selector:
select:
options:
- low
- normal
- high
multiple: true
translation_key: rating_level_filter
period_filter:
required: false
selector:
select:
options:
- best_price
- peak_price
translation_key: period_filter
transformation:
collapsed: true
fields:
subunit_currency:
required: false
example: true
selector:
boolean:
round_decimals:
required: false
example: 2
selector:
number:
min: 0
max: 10
mode: box
insert_nulls:
required: false
default: none
selector:
select:
options:
- none
- segments
- all
translation_key: insert_nulls
connect_segments:
required: false
selector:
boolean:
add_trailing_null:
required: false
selector:
boolean:
format:
collapsed: true
fields:
output_format:
required: false
default: array_of_objects
example: array_of_objects
selector:
select:
options:
- array_of_objects
- array_of_arrays
translation_key: output_format
data_key:
required: false
example: prices
selector:
text:
metadata:
required: false
default: include
selector:
select:
options:
- include
- only
- none
translation_key: metadata
arrays_of_objects:
collapsed: true
fields:
include_level:
required: false
example: true
selector:
boolean:
include_rating_level:
required: false
example: true
selector:
boolean:
include_average:
required: false
selector:
boolean:
include_energy:
required: false
selector:
boolean:
include_tax:
required: false
selector:
boolean:
start_time_field:
required: false
example: time
selector:
text:
end_time_field:
required: false
example: end
selector:
text:
price_field:
required: false
example: price
selector:
text:
level_field:
required: false
selector:
text:
rating_level_field:
required: false
selector:
text:
average_field:
required: false
selector:
text:
energy_field:
required: false
selector:
text:
tax_field:
required: false
selector:
text:
arrays_of_arrays:
collapsed: true
fields:
array_fields:
required: false
selector:
text:
refresh_user_data:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices
find_cheapest_block:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices
duration:
required: true
selector:
duration:
search_scope:
required: false
selector:
select:
options:
- today
- tomorrow
- remaining_today
- next_24h
- next_48h
translation_key: search_scope
include_current_interval:
required: false
default: true
selector:
boolean:
search_range:
collapsed: true
fields:
search_start:
required: false
example: "2026-04-11T06:00:00+02:00"
selector:
datetime:
search_end:
required: false
example: "2026-04-12T00:00:00+02:00"
selector:
datetime:
must_finish_by:
required: false
example: "2026-04-12T07:00:00+02:00"
selector:
datetime:
time_alternatives:
collapsed: true
fields:
search_start_time:
required: false
example: "06:00:00"
selector:
time:
search_start_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_end_time:
required: false
example: "23:00:00"
selector:
time:
search_end_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_start_offset_minutes:
required: false
example: 60
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
search_end_offset_minutes:
required: false
example: 480
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
price_filter:
collapsed: true
fields:
max_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
min_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
search_tuning:
collapsed: true
fields:
smooth_outliers:
required: false
default: true
selector:
boolean:
min_distance_from_avg:
required: false
selector:
number:
min: 0.1
max: 50.0
step: 0.1
unit_of_measurement: "%"
mode: box
allow_relaxation:
required: false
default: true
selector:
boolean:
duration_flexibility_minutes:
required: false
selector:
number:
min: 0
max: 120
step: 15
unit_of_measurement: "min"
mode: box
cost_estimation:
collapsed: true
fields:
power_profile:
required: false
selector:
object:
output:
collapsed: true
fields:
include_comparison_details:
required: false
selector:
boolean:
use_base_unit:
required: false
selector:
boolean:
find_most_expensive_block:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices
duration:
required: true
selector:
duration:
search_scope:
required: false
selector:
select:
options:
- today
- tomorrow
- remaining_today
- next_24h
- next_48h
translation_key: search_scope
include_current_interval:
required: false
default: true
selector:
boolean:
search_range:
collapsed: true
fields:
search_start:
required: false
example: "2026-04-11T06:00:00+02:00"
selector:
datetime:
search_end:
required: false
example: "2026-04-12T00:00:00+02:00"
selector:
datetime:
must_finish_by:
required: false
example: "2026-04-12T07:00:00+02:00"
selector:
datetime:
time_alternatives:
collapsed: true
fields:
search_start_time:
required: false
example: "06:00:00"
selector:
time:
search_start_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_end_time:
required: false
example: "23:00:00"
selector:
time:
search_end_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_start_offset_minutes:
required: false
example: 60
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
search_end_offset_minutes:
required: false
example: 480
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
price_filter:
collapsed: true
fields:
max_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
min_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
search_tuning:
collapsed: true
fields:
smooth_outliers:
required: false
default: true
selector:
boolean:
min_distance_from_avg:
required: false
selector:
number:
min: 0.1
max: 50.0
step: 0.1
unit_of_measurement: "%"
mode: box
allow_relaxation:
required: false
default: true
selector:
boolean:
duration_flexibility_minutes:
required: false
selector:
number:
min: 0
max: 120
step: 15
unit_of_measurement: "min"
mode: box
cost_estimation:
collapsed: true
fields:
power_profile:
required: false
selector:
object:
output:
collapsed: true
fields:
include_comparison_details:
required: false
selector:
boolean:
use_base_unit:
required: false
selector:
boolean:
find_cheapest_hours:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices
duration:
required: true
selector:
duration:
min_segment_duration:
required: false
selector:
duration:
search_scope:
required: false
selector:
select:
options:
- today
- tomorrow
- remaining_today
- next_24h
- next_48h
translation_key: search_scope
include_current_interval:
required: false
default: true
selector:
boolean:
search_range:
collapsed: true
fields:
search_start:
required: false
example: "2026-04-11T06:00:00+02:00"
selector:
datetime:
search_end:
required: false
example: "2026-04-12T00:00:00+02:00"
selector:
datetime:
must_finish_by:
required: false
example: "2026-04-12T07:00:00+02:00"
selector:
datetime:
time_alternatives:
collapsed: true
fields:
search_start_time:
required: false
example: "06:00:00"
selector:
time:
search_start_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_end_time:
required: false
example: "23:00:00"
selector:
time:
search_end_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_start_offset_minutes:
required: false
example: 60
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
search_end_offset_minutes:
required: false
example: 480
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
price_filter:
collapsed: true
fields:
max_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
min_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
search_tuning:
collapsed: true
fields:
smooth_outliers:
required: false
default: true
selector:
boolean:
min_distance_from_avg:
required: false
selector:
number:
min: 0.1
max: 50.0
step: 0.1
unit_of_measurement: "%"
mode: box
allow_relaxation:
required: false
default: true
selector:
boolean:
duration_flexibility_minutes:
required: false
selector:
number:
min: 0
max: 120
step: 15
unit_of_measurement: "min"
mode: box
cost_estimation:
collapsed: true
fields:
power_profile:
required: false
selector:
object:
output:
collapsed: true
fields:
include_comparison_details:
required: false
selector:
boolean:
use_base_unit:
required: false
selector:
boolean:
find_most_expensive_hours:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices
duration:
required: true
selector:
duration:
min_segment_duration:
required: false
selector:
duration:
search_scope:
required: false
selector:
select:
options:
- today
- tomorrow
- remaining_today
- next_24h
- next_48h
translation_key: search_scope
include_current_interval:
required: false
default: true
selector:
boolean:
search_range:
collapsed: true
fields:
search_start:
required: false
example: "2026-04-11T06:00:00+02:00"
selector:
datetime:
search_end:
required: false
example: "2026-04-12T00:00:00+02:00"
selector:
datetime:
must_finish_by:
required: false
example: "2026-04-12T07:00:00+02:00"
selector:
datetime:
time_alternatives:
collapsed: true
fields:
search_start_time:
required: false
example: "06:00:00"
selector:
time:
search_start_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_end_time:
required: false
example: "23:00:00"
selector:
time:
search_end_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_start_offset_minutes:
required: false
example: 60
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
search_end_offset_minutes:
required: false
example: 480
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
price_filter:
collapsed: true
fields:
max_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
min_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
search_tuning:
collapsed: true
fields:
smooth_outliers:
required: false
default: true
selector:
boolean:
min_distance_from_avg:
required: false
selector:
number:
min: 0.1
max: 50.0
step: 0.1
unit_of_measurement: "%"
mode: box
allow_relaxation:
required: false
default: true
selector:
boolean:
duration_flexibility_minutes:
required: false
selector:
number:
min: 0
max: 120
step: 15
unit_of_measurement: "min"
mode: box
cost_estimation:
collapsed: true
fields:
power_profile:
required: false
selector:
object:
output:
collapsed: true
fields:
include_comparison_details:
required: false
selector:
boolean:
use_base_unit:
required: false
selector:
boolean:
find_cheapest_schedule:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices
tasks:
required: true
example: '[{"name": "dishwasher", "duration": "02:00:00"}, {"name": "washing_machine", "duration": "01:30:00"}]'
selector:
object:
gap_minutes:
required: false
default: 0
selector:
number:
min: 0
max: 120
unit_of_measurement: min
mode: box
sequential:
required: false
default: false
selector:
boolean:
search_scope:
required: false
selector:
select:
options:
- today
- tomorrow
- remaining_today
- next_24h
- next_48h
translation_key: search_scope
include_current_interval:
required: false
default: true
selector:
boolean:
search_range:
collapsed: true
fields:
search_start:
required: false
example: "2026-04-11T06:00:00+02:00"
selector:
datetime:
search_end:
required: false
example: "2026-04-12T00:00:00+02:00"
selector:
datetime:
must_finish_by:
required: false
example: "2026-04-12T07:00:00+02:00"
selector:
datetime:
time_alternatives:
collapsed: true
fields:
search_start_time:
required: false
example: "06:00:00"
selector:
time:
search_start_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_end_time:
required: false
example: "23:00:00"
selector:
time:
search_end_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_start_offset_minutes:
required: false
example: 60
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
search_end_offset_minutes:
required: false
example: 480
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
price_filter:
collapsed: true
fields:
max_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
min_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
search_tuning:
collapsed: true
fields:
smooth_outliers:
required: false
default: true
selector:
boolean:
allow_relaxation:
required: false
default: true
selector:
boolean:
duration_flexibility_minutes:
required: false
selector:
number:
min: 0
max: 120
step: 15
unit_of_measurement: "min"
mode: box
output:
collapsed: true
fields:
include_comparison_details:
required: false
selector:
boolean:
use_base_unit:
required: false
selector:
boolean:
plan_charging:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices
battery:
collapsed: false
fields:
max_charge_power_w:
required: true
example: 11000
selector:
number:
min: 1
max: 100000
step: 100
unit_of_measurement: "W"
mode: box
battery_capacity_kwh:
required: false
example: 50.0
selector:
number:
min: 0.1
max: 1000
step: 0.1
unit_of_measurement: "kWh"
mode: box
current_soc_percent:
required: false
example: 20
selector:
number:
min: 0
max: 100
step: 0.1
unit_of_measurement: "%"
mode: box
current_soc_kwh:
required: false
example: 10.0
selector:
number:
min: 0
max: 1000
step: 0.1
unit_of_measurement: "kWh"
mode: box
target_soc_percent:
required: false
example: 80
selector:
number:
min: 0
max: 100
step: 0.1
unit_of_measurement: "%"
mode: box
target_soc_kwh:
required: false
example: 40.0
selector:
number:
min: 0
max: 1000
step: 0.1
unit_of_measurement: "kWh"
mode: box
charging_efficiency:
required: false
default: 1.0
selector:
number:
min: 0.5
max: 1.0
step: 0.01
mode: box
charging:
collapsed: true
fields:
min_charge_power_w:
required: false
example: 1400
selector:
number:
min: 1
max: 100000
step: 100
unit_of_measurement: "W"
mode: box
charge_power_steps_w:
required: false
example: [1380, 4140, 11000]
selector:
object:
grid_import_limit_w:
required: false
example: 16000
selector:
number:
min: 1
max: 100000
step: 100
unit_of_measurement: "W"
mode: box
min_charge_duration_minutes:
required: false
example: 30
selector:
number:
min: 15
max: 240
step: 15
unit_of_measurement: "min"
mode: box
max_cycles_per_day:
required: false
example: 2
selector:
number:
min: 1
max: 20
step: 1
mode: box
search_scope:
required: false
selector:
select:
options:
- today
- tomorrow
- remaining_today
- next_24h
- next_48h
translation_key: search_scope
include_current_interval:
required: false
default: true
selector:
boolean:
search_range:
collapsed: true
fields:
search_start:
required: false
example: "2026-04-11T06:00:00+02:00"
selector:
datetime:
search_end:
required: false
example: "2026-04-12T00:00:00+02:00"
selector:
datetime:
must_finish_by:
required: false
example: "2026-04-12T07:00:00+02:00"
selector:
datetime:
deadline:
collapsed: true
fields:
must_reach_soc_percent:
required: false
example: 50
selector:
number:
min: 0
max: 100
step: 0.1
unit_of_measurement: "%"
mode: box
must_reach_soc_kwh:
required: false
example: 25.0
selector:
number:
min: 0
max: 1000
step: 0.1
unit_of_measurement: "kWh"
mode: box
must_reach_by:
required: false
example: "2026-04-11T17:00:00+02:00"
selector:
datetime:
must_reach_by_event:
required: false
selector:
select:
options:
- midnight
- next_peak_period
- next_best_period_end
translation_key: charging_deadline_event
time_alternatives:
collapsed: true
fields:
search_start_time:
required: false
example: "06:00:00"
selector:
time:
search_start_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_end_time:
required: false
example: "23:00:00"
selector:
time:
search_end_day_offset:
required: false
default: 0
selector:
number:
min: -7
max: 2
mode: box
search_start_offset_minutes:
required: false
example: 60
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
search_end_offset_minutes:
required: false
example: 480
selector:
number:
min: -10080
max: 10080
unit_of_measurement: min
mode: box
price_filter:
collapsed: true
fields:
max_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
min_price_level:
required: false
selector:
select:
options:
- very_cheap
- cheap
- normal
- expensive
- very_expensive
translation_key: level_filter
search_tuning:
collapsed: true
fields:
smooth_outliers:
required: false
default: true
selector:
boolean:
min_distance_from_avg:
required: false
selector:
number:
min: 0.1
max: 50.0
step: 0.1
unit_of_measurement: "%"
mode: box
allow_relaxation:
required: false
default: true
selector:
boolean:
duration_flexibility_minutes:
required: false
selector:
number:
min: 0
max: 120
step: 15
unit_of_measurement: "min"
mode: box
economics:
collapsed: true
fields:
discharging_efficiency:
required: false
default: 1.0
selector:
number:
min: 0.5
max: 1.0
step: 0.01
mode: box
expected_discharge_price:
required: false
example: 0.28
selector:
number:
min: 0
max: 100000
step: 0.0001
mode: box
reserve_for_discharge:
required: false
default: false
selector:
boolean:
max_cost_per_kwh:
required: false
example: 0.18
selector:
number:
min: 0
max: 100000
step: 0.0001
mode: box
output:
collapsed: true
fields:
include_comparison_details:
required: false
selector:
boolean:
use_base_unit:
required: false
selector:
boolean:
debug_clear_tomorrow:
fields:
entry_id:
required: false
example: "1234567890abcdef"
selector:
config_entry:
integration: tibber_prices