When include_current_interval=False, the search_start was set to the raw
now timestamp (e.g. 14:47:00.167996). The interval pool index iterates in
15-minute steps from that exact value, so keys like 14:47:00, 15:02:00, …
never matched any cached interval (which are always on :00/:15/:30/:45
boundaries), causing no data to be found and returning no_data_in_range.
Fix: replace `now` with `ceil_to_next_quarter_hour(now)` which is always
`floor(now) + 15min`. This skips the interval that is currently in progress
(14:30–14:45 interval) and starts at the first interval that hasn't begun
yet (15:00), consistent with the intent of include_current_interval=False.
Fixes#190
User-Impact: find_cheapest_block/find_most_expensive_block/find_cheapest_hours
with include_current_interval=false and search_scope=next_24h (or no scope)
no longer returns no_data_in_range when data is available.
Agent-Logs-Url: https://github.com/jpawlowski/hass.tibber_prices/sessions/0ea804f9-7c98-4e5a-b40f-469954fa9daa
Co-authored-by: jpawlowski <75446+jpawlowski@users.noreply.github.com>
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.
_resolve_time_with_day_offset() was calling dt_util.now() internally
instead of using the injected now parameter. This caused incorrect date
calculations in tests and any caller that passes a specific reference time.
Also add missing price_rank_* sensor keys to TIME_SENSITIVE_ENTITY_KEYS
in coordinator/constants.py so quarter-hour refresh is registered for all
11 price rank sensors (current/next/previous interval and hour variants).
Rename dt as dt_utils → dt as dt_util (ICN001) across 11 files to follow
the project-wide import alias convention. Apply ruff auto-fixes for import
ordering and collapsing single-item imports throughout the codebase.
Released-Bug: no
New services for finding optimal electricity price windows:
- find_cheapest_block: Cheapest contiguous time block (e.g., dishwasher)
- find_cheapest_hours: Cheapest N hours, non-contiguous (e.g., EV charging)
- find_cheapest_schedule: Multi-task scheduling with no-overlap (e.g., shared circuit)
- find_most_expensive_block: Most expensive contiguous block (peak avoidance)
- find_most_expensive_hours: Most expensive N hours (consumption shifting)
Key features:
- Flexible search range (today, tomorrow, today+tomorrow, rolling window)
- Power profile support for variable consumption patterns
- Price level filtering (e.g., only CHEAP/VERY_CHEAP intervals)
- Comparison details showing savings vs. alternatives
- Sliding window algorithm (O(n)) for block search, greedy scheduling
for multi-task optimization
Also includes:
- Shared validation utilities (search range, price level, power profile)
- entry_id now optional on all services (auto-selects single home)
- Input validation for existing services (time range, filter conflicts)
- Service icons for all new and existing services
- Translations for all 5 languages (en, de, nb, nl, sv)
- Removed 10 unused config.error translation keys (replaced by exceptions)
- Tests for price window algorithms and search range resolution
Impact: Users can find optimal time windows for appliances, EV charging,
and multi-device scheduling via HA service calls. Existing services
improved with optional entry_id and better input validation.