We have no way to programmatically detect whether the Recorder statistics
have been fixed. Dismissing the Repairs notification does not mean the
problem is resolved, only that the user has seen it.
Revert to delete + create on every async_setup_entry when the flag is set.
This guarantees the issue is visible after every restart until the user
explicitly acknowledges completion by re-saving the display settings in
the options flow.
Remove the dismissed_version auto-clear logic that was treating dismissal
as acknowledgement (it was not).
Update all 5 translation files: replace "Dismiss this notice" with
instructions to re-save display settings as the only way to permanently
close the notification.
Released-Bug: no
async_create_issue preserves dismissed_version when called with the same
issue_id. This means that if a user had previously dismissed the repair
issue, changing the currency mode again would set the flag but the issue
would stay hidden (because it still has a dismissed_version).
Fix: use delete + create in the options flow when mode_changed=True.
This resets dismissed_version so the new instance is always visible.
The __init__.py path (HA restart with flag set) continues to use plain
async_create_issue so that a restart alone does not un-dismiss an issue
the user already acknowledged.
Released-Bug: no
The previous implementation used delete + create on every async_setup_entry,
which reset dismissed_version and forced the issue to reappear after every
HA restart regardless of whether the user had dismissed it.
Fix: use async_create_issue (internally get-or-create, preserves
dismissed_version when params are unchanged) instead of delete + create.
The options flow still uses delete + create when the mode changes again,
ensuring the issue is forced into view for any new change.
Also auto-clear the DATA_STATISTICS_REVIEW_REQUIRED flag from
config_entry.data when the issue is detected as dismissed on setup,
so the flag does not linger indefinitely after the user has acknowledged
the issue.
Released-Bug: no
_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
Add DATA_STATISTICS_REVIEW_REQUIRED flag to config_entry.data. Set on
currency mode change, cleared on same-mode save. On every async_setup_entry
with flag set, delete and recreate the repair issue so it reappears after
HA restart even if previously dismissed.
Repair issue text explains that HA Recorder shows its own unit-change
dialog (delayed) and recommends deleting old statistic data rather than
re-labeling, which would leave wrong values with the new unit.
Impact: Users are notified to review statistics and automations after
switching between base/subunit currency mode. Notification persists across
HA restarts until acknowledged by saving display settings again.
Add get_display_precision() to const.py returning DISPLAY_PRECISION_SUBUNIT (2)
or DISPLAY_PRECISION_BASE (4) based on config. Replace hardcoded round(..., 2)
with get_display_precision() in all calculators and attribute builders.
Add _update_suggested_precision() to sensor core; syncs entity registry
suggested_display_precision on every coordinator update.
Interval price sensors get full precision (2 or 4 dp); other MONETARY sensors
get half precision (1 or 2 dp) as sensible default.
Impact: Price sensor states and attributes now correctly use 4 decimal places
in base-currency mode (was always 2). Display precision in dashboards updates
automatically when currency mode changes.
Refactor the contribution guidelines to enhance readability and consistency in formatting. Adjusted code blocks and list formatting for better visual structure.
Impact: Contributors will find it easier to follow the guidelines when contributing to the project.
---
docs(README): update automation examples for better readability
Reformatted YAML automation examples in the README to improve clarity and consistency. Indentation and structure were adjusted for better understanding.
Impact: Users will have clearer examples for setting up automations with the integration.
---
chore(manifest): streamline manifest file formatting
Consolidated formatting in the manifest file for consistency. Adjusted the codeowners and requirements sections for a cleaner look.
User-Impact: none
---
chore(pyproject): enhance project configuration for better linting and testing
Updated the pyproject.toml file to improve linting configurations and testing options. Added specific rules for ruff and pytest to align with project standards.
User-Impact: none
---
chore(manifest_schema): simplify JSON schema for integration manifest
Refined the manifest schema by consolidating enum definitions for better readability and maintenance.
User-Impact: none
---
chore(prettier): add Prettier configuration for consistent code formatting
Introduced a Prettier configuration file to standardize code formatting across the project, ensuring consistency in style.
User-Impact: none
Updated color and icon logic to include additional keys for price trends, outlooks, and trajectories. This improves the visual representation of price changes in the UI.
Impact: Users will see more accurate color coding and icons for price trends and forecasts.
Improve error handling for API fetch failures by implementing a fallback to cached intervals. This ensures the system can continue functioning during transient API issues.
Impact: Users experience fewer interruptions when the API is temporarily unavailable, as cached data will be used seamlessly.
Modified error messages in multiple language translation files to remove unnecessary curly braces around the template placeholder for improved clarity.
Impact: Users will see clearer error messages when invalid array_fields are provided.
Improved validation logic for service parameters in find_cheapest_hours, find_cheapest_schedule, and chartdata services. Added checks for unique task names, ensured that segment durations do not exceed total duration, and clarified error messages for better user understanding.
Impact: Users will receive clearer error messages and improved validation when using the services, leading to a more robust experience.
Updated the filter logic to include period_filter alongside level_filter and rating_level_filter for segment definitions. This change ensures that users can utilize period_filter effectively when defining segments.
Impact: Users can now use period_filter in addition to existing filters for more flexible segment definitions.
Updated sensor definitions to enhance clarity and maintain consistency by removing the diagnostic entity category from day pattern sensors.
Impact: No user-facing changes.
Updated the long descriptions and usage tips for the price trend change sensors in multiple languages (de, en, nb, nl, sv) to provide clearer guidance on detection mechanics and expected behavior during V-shaped price days.
Impact: Users will have a better understanding of how the sensors operate and can make more informed decisions regarding automation based on price trends.
Refactor the period extension logic to clarify the handling of primary and fallback price levels. Update the documentation to reflect the changes in how periods extend into adjacent intervals.
Impact: Users will benefit from clearer price extension behavior and improved performance in period calculations.
Replace CV with IQR% as the primary indicator for flat-day detection
in _compute_day_effective_min(). CV is inflated by isolated price spikes
(a single spike at 2× the average pushes CV to 15-25% while the core
price band stays flat), causing the flat-day adaptation to be missed.
IQR% (spread of the central 50% of prices / median) is unaffected by
tail outliers and correctly identifies "flat core + spike" days.
Threshold: LOW_IQR_PCT_FLAT_DAY_THRESHOLD = 15.0%
- IQR% ≈ 1.35 × CV for symmetric data, so 15% ≈ old CV threshold of 10%
- Extra headroom catches flat days with a single outlier (IQR%~3%,
CV~20%) that were previously missed
CV retained as fallback for edge cases where iqr_pct is None
(near-zero or negative median prices).
Impact: Flat days with a single isolated price spike are now correctly
identified, reducing unnecessary relaxation iterations on those days.
Rename the three existing price rank sensors from price_rank_* to
current_interval_price_rank_* to clarify they rank the current
quarter-hour interval's price, not a daily aggregate — consistent with
current_interval_price_level / current_interval_price_rating naming.
Add 8 new rank sensors covering additional subjects and reference windows:
- next_interval_price_rank_{today,today_tomorrow}
- previous_interval_price_rank_{today,today_tomorrow}
- current_hour_price_rank_{today,today_tomorrow} (5-interval rolling avg)
- next_hour_price_rank_{today,today_tomorrow} (5-interval rolling avg)
All new sensors are disabled by default. The volatility calculator gains a
subject parameter (_get_subject_price / _get_subject_price_attr_key /
_get_rolling_hour_avg_price) to select which price to rank. Sensor key
routing in value_getters.py and attributes/__init__.py updated accordingly.
No migration entries needed — the original price_rank_* sensors were never
released to users.
All 5 translation files updated. sensor-reference.md regenerated (129 entities).
Impact: Users can now track price rank for the next interval (look-ahead),
the previous interval (logging), and rolling hourly averages — for both
same-day and two-day reference windows.
Add entity descriptions, long descriptions, and usage tips for the three new
price_rank_* sensors and the updated volatility sensors with IQR attributes.
Plain-language terms are used as primary labels (e.g. "typical price band",
"price rank"); technical terms are included parenthetically for experts
(e.g. "IQR", "percentile rank", "Tukey fences") in all five languages.
Impact: Sensors show descriptive help text in the entity detail view, making it
easier for users to understand what each sensor measures without consulting
external documentation.
Add entity name translations for price_rank_today, price_rank_tomorrow, and
price_rank_today_tomorrow sensors in English, German, Norwegian, Dutch, and
Swedish.
Impact: Sensor display names appear correctly in the Home Assistant UI for all
supported languages.
Add three new price rank sensors that show where today's/tomorrow's/combined
average price falls relative to all intervals in the evaluated window:
- price_rank_today: today's average price percentile rank (0–100%)
- price_rank_tomorrow: tomorrow's average price percentile rank
- price_rank_today_tomorrow: combined today+tomorrow percentile rank
Extend all volatility sensors with IQR-based band statistics:
- price_typical_spread: interquartile range (IQR) in currency subunit
- price_typical_spread_%: IQR as percentage of daily average
- price_spike_count: number of intervals outside Tukey fences (outliers)
Add calculate_iqr_stats() utility function in utils/price.py that computes
the 25th/75th percentiles, IQR, outer fences (Q1 - 1.5×IQR / Q3 + 1.5×IQR),
and outlier count for any list of price values. Entity keys and attribute
names use plain language (`price_rank`, `price_typical_spread`) as primary
labels; technical terms (percentile rank, IQR) are included parenthetically
in descriptions and documentation.
Impact: Users can now see where current day prices rank compared to their window and how tightly clustered or spike-prone a day's prices are.
Add structured reason codes to no-result responses for find_cheapest_block,
find_cheapest_hours, and find_cheapest_schedule. Each handler now classifies
why no result was returned: no_data_in_range, no_intervals_matching_level_filter,
insufficient_intervals_after_filter, or insufficient_contiguous_window.
Add include_comparison_details flag to find_cheapest_schedule. When enabled,
each scheduled task includes a price_comparison field showing the most expensive
alternative window (mean, min, max, start, end) for cost-savings context.
Document stable reason code contracts in en.json service descriptions.
Add corresponding field translations to all locales (de, nb, nl, sv).
Impact: Automations and scripts can now react to why no window was found,
and schedules can display concrete savings vs. worst-case pricing.
Consistent naming with the period_count_* family introduced in the
previous commit (period_count_total, period_count_today,
period_count_tomorrow).
periods_remaining was the last attribute in the navigation triplet
using the old plural form. Renamed to period_count_remaining to follow
the established pattern: all countable period metrics use the
period_count_* prefix.
BREAKING CHANGE: periods_remaining renamed to period_count_remaining.
Impact: All four period count attributes now share the same prefix
(period_count_total, period_count_today, period_count_tomorrow,
period_count_remaining), making automation templates more predictable.
Removed periods_found_total and replaced with period_count_today /
period_count_tomorrow. The old attribute counted all periods including
yesterday (coordinator scope), causing a discrepancy vs. the displayed
list (sensor scope, today+tomorrow only).
Renamed periods_total → period_count_total for naming consistency with
the new per-day attributes. Recalculate period_position / period_count_total /
periods_remaining after the today+tomorrow filter so all three navigation
attributes reflect the filtered scope.
period_count_tomorrow is always present (0 when no tomorrow data or no
periods found), enabling automations without default(0) guards.
Removed internal periods_found key from relaxation metadata — it was
only consumed by add_calculation_summary_attributes which is now removed.
BREAKING CHANGE: periods_found_total removed (replace with
period_count_today + period_count_tomorrow). periods_total renamed to
period_count_total.
Impact: Period navigation attributes (position/total/remaining) now
correctly reflect today+tomorrow scope. Per-day counts allow automations
to distinguish "2 periods today, 0 tomorrow" from "1+1".
Phase 3: When geometric bonus intervals cause CV gate failure, strip them
from period edges (unextended boundaries) and set geometric_extension_attempted=True
on the summary. Previously only geometric_extension_active was tracked.
Moved LOW_PRICE_QUALITY_BYPASS_THRESHOLD constant to types.py for shared access.
Phase 4: Add time_range: tuple[datetime, datetime] | None parameter to
build_periods(), calculate_periods(), and calculate_periods_with_relaxation().
Filters candidate intervals to [start, end) without affecting day-wide reference
prices. Refactored _apply_segment_forcing() to use time_range instead of the
restricted_prices list approach.
Impact: Period statistics now accurately reflect when geometric flex extension
was attempted but reverted due to quality gate failure. Segment forcing uses
a cleaner API that preserves full price context for reference calculations.
Phase 3: When geometric bonus intervals cause CV gate failure, strip them
from period edges (unextended boundaries) and set geometric_extension_attempted=True
on the summary. Previously only geometric_extension_active was tracked.
Moved LOW_PRICE_QUALITY_BYPASS_THRESHOLD constant to types.py for shared access.
Phase 4: Add time_range: tuple[datetime, datetime] | None parameter to
build_periods(), calculate_periods(), and calculate_periods_with_relaxation().
Filters candidate intervals to [start, end) without affecting day-wide reference
prices. Refactored _apply_segment_forcing() to use time_range instead of the
restricted_prices list approach.
Impact: Period statistics now accurately reflect when geometric flex extension
was attempted but reverted due to quality gate failure. Segment forcing uses
a cleaner API that preserves full price context for reference calculations.
Uses valley/peak knee points from day pattern analysis to grant extra
flex to price intervals that fall inside detected geometric zones,
making period detection more permissive within V-shape (best price)
or Λ-shape (peak price) price formations.
New options:
- CONF_BEST_PRICE_GEOMETRIC_FLEX (0-25%, default 0 = disabled)
- CONF_PEAK_PRICE_GEOMETRIC_FLEX (0-25%, default 0 = disabled)
Implementation:
- compute_geometric_flex_bonus() in level_filtering.py checks if
interval falls inside valley/peak zone and returns extra_flex
- period_building.py applies geo bonus per-interval via
criteria._replace(flex=...) and sets geometric_bonus_applied flag
- period_statistics.py reports geometric_extension_active and
geometric_extension_intervals in period summaries
- Day patterns threaded through full pipeline:
data_transformation → coordinator/core → periods →
relaxation → calculate_periods → price_context
- UI sliders in both extension_settings sections
- Translations: en, de, nb, nl, sv
Impact: Users with clearly V-shaped or Λ-shaped daily price curves
can enable geometric flex to improve period detection accuracy within
those characteristic shapes without increasing global flex.
After period detection, optionally walk left/right from each period boundary
to absorb adjacent VERY_CHEAP (best price) or VERY_EXPENSIVE (peak price)
intervals (step 7.5 in the pipeline).
New constants: CONF_BEST_PRICE_EXTEND_TO_VERY_CHEAP, CONF_BEST_PRICE_MAX_EXTENSION_INTERVALS,
CONF_PEAK_PRICE_EXTEND_TO_VERY_EXPENSIVE, CONF_PEAK_PRICE_MAX_EXTENSION_INTERVALS.
Defaults: off / 4 intervals (1 hour per side). Hard maximum: 12 intervals (3 hours).
Config stored under "extension_settings" section, reflected in period hash
for correct cache invalidation.
New module: coordinator/period_handlers/shape_extension.py handles the
boundary walk, stat recalculation, and extension_intervals_added bookkeeping.
Impact: Users can opt-in to wider best/peak price windows that include
extreme-level adjacent intervals, reducing missed very cheap/expensive slots
at period edges.
Introduces a new day_pattern.py module that analyses the 15-min price curve
for each calendar day (yesterday/today/tomorrow) and classifies its shape.
New sensors:
day_pattern_yesterday / day_pattern_today / day_pattern_tomorrow
EntityCategory.DIAGNOSTIC, SensorDeviceClass.ENUM
Patterns: valley, peak, double_valley, double_peak, flat, rising, falling, mixed
The detector uses centred-rolling smoothing, prominence-filtered extrema,
Kneedle-based knee detection, and monotone segment building.
Coordinator populates transformed_data["dayPatterns"] after priceInfo enrichment.
Impact: Users can trigger automations based on the shape of the day's price
curve, e.g. pre-heat when tomorrow is a valley day.
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.
Remove unused functions, constants, and entity definitions that were
left over from previous refactorings. All removed code was either
superseded by better implementations or never actually called.
Removed functions:
- entity_utils/helpers.py: translate_level(), translate_rating_level()
(HA handles ENUM translation automatically via translations/*.json)
- entity_utils/attributes.py: build_timestamp_attribute(),
build_period_attributes() (superseded by inline implementations)
- sensor/helpers.py: get_hourly_price_value(), aggregate_window_data()
(replaced by Calculator Pattern in sensor/calculators/)
Removed constants and definitions:
- const.py: CONF_CHART_DATA_CONFIG (DATA_CHART_CONFIG is the active one),
PRICE_LEVEL_OPTIONS, PRICE_RATING_OPTIONS, VOLATILITY_OPTIONS,
PRICE_TREND_OPTIONS (never imported; options defined inline in
definitions.py due to HA import timing constraints),
async_get_home_type_translation() (sync version used instead)
- coordinator/core.py: FRESH_TO_CACHED_SECONDS (leftover from old
caching strategy, never referenced)
- switch/definitions.py: BEST_PRICE_SWITCH_ENTITIES (duplicate of
BEST_PRICE_SWITCH_ENTITY_DESCRIPTIONS using base class instead of
custom TibberPricesSwitchEntityDescription subclass)
Cleanup:
- entity_utils/__init__.py: Remove exports for deleted functions
- sensor/helpers.py: Remove now-unused imports (timedelta,
get_intervals_for_day_offsets, get_price_value, Callable)
- entity_utils/helpers.py: Remove unused get_price_level_translation
import after translate_level() removal
- sensor/definitions.py: Update 7x "Keep in sync with *_OPTIONS"
comments to reference individual PRICE_LEVEL_*/PRICE_RATING_*/
VOLATILITY_* constants instead
Impact: No user-visible changes. Reduces codebase by ~130 lines.
Improves maintainability by eliminating misleading dead code.
Add UP037 to ruff ignore list to preserve quoted TYPE_CHECKING forward
references (PEP 649 lazy eval breaks get_type_hints() at runtime for
TYPE_CHECKING-guarded imports).
Move datetime imports into TYPE_CHECKING blocks in sensor/calculators
timing.py and trend.py (TC003, type-only usage confirmed).
Apply PEP 758 parenthesis-free except clauses across 7 files via
ruff format with target-version=py314.
Update hacs.json minimum HA version to 2026.4.0, the first HA release
requiring Python 3.14.
Impact: Linter config now correctly handles Python 3.14 semantics.
Users need HA >= 2026.4 (Python 3.14) to use this integration.
Adds migrations.py with automatic entity registry migration for renamed
sensor keys. Separated from coordinator/repairs.py (runtime issues) and
__init__.py _migrate_config_options() (config format changes).
- ENTITY_KEY_RENAMES dict maps old→new entity keys (extensible)
- _auto_migrate_entity_keys() updates unique_id, preserves entity_id
- Handles partial migration (new entity already exists → remove old)
- Creates persistent HA repair issue after migration via ir.async_create_issue()
- Called in async_setup_entry() after _migrate_config_options()
Migrates: trend_change_in_minutes → next_price_trend_change_in
Repair issue informs users about:
- Auto-migrated entity renames (entity_id preserved, no action needed)
- Duration sensor value unit change (hours → minutes): update automation
thresholds from `state < 0.25` to `state < 15` for 15-minute checks
All 5 language files (en, de, nb, nl, sv) updated with translations.
BREAKING CHANGE: Duration sensors (remaining time, starts in, period
duration, trend change countdown) now report state values in minutes
instead of hours. Display unit in dashboards remains hours by default.
Update numeric comparisons in automations accordingly.
Impact: Users upgrading from previous releases see an informational
repair notice guiding them through any required automation updates.
Entity renames are handled transparently with no loss of history.
Replaced int(time.minutes_until()) with time.minutes_until_rounded()
in trend calculator (3 locations). The int() call truncated values
(14.7 → 14) while timing sensors used standard rounding (14.7 → 15).
All duration sensors now use the same rounding method
(math.floor(seconds/60 + 0.5)), matching HA's timestamp rendering
behavior.
Impact: Trend countdown values may differ by ±1 minute compared to
previous behavior. Consistency across all duration sensors improved.
Changed native_unit_of_measurement from HOURS to MINUTES for all 7
duration sensors. HA auto-converts to hours for display via
suggested_unit_of_measurement=HOURS.
Sensors affected:
- next_price_trend_change_in
- best_price_period_duration, best_price_remaining_minutes,
best_price_next_in_minutes
- peak_price_period_duration, peak_price_remaining_minutes,
peak_price_next_in_minutes
Removed _minutes_to_hours() conversion function — calculator values
(minutes) are now passed through directly.
BREAKING CHANGE: State values for all duration sensors change from
hours to minutes (e.g. 1.5 → 90). The display unit remains hours
(suggested_unit_of_measurement). Automations using numeric state
comparisons must be updated (multiply old thresholds by 60).
Impact: Users with automations comparing duration sensor states
numerically need to update thresholds. Dashboard display is unchanged
for new installations. Existing installations retain their configured
display unit but the underlying numeric value changes.
Renamed trend_change_in_minutes → next_price_trend_change_in to align
with its sibling sensor next_price_trend_change (timestamp variant).
Follows the established best/peak price naming pattern where related
sensors share a common prefix (e.g. best_price_next_start_time /
best_price_next_in_minutes).
Updated entity key, translation key, friendly names (all 5 languages),
custom translations, coordinator constants, attribute routing, and
cache-clear mapping.
BREAKING CHANGE: Entity ID changes from
sensor.<home>_trend_change_in_minutes to
sensor.<home>_next_price_trend_change_in. Automations and dashboards
referencing the old entity ID must be updated.
Impact: Users with automations or dashboard cards referencing the old
sensor name need to update references. The sensor retains identical
functionality and attributes.
Skip expensive async_write_ha_state() when native_value hasn't changed
since last write. HA's state machine has built-in change detection, but
it only runs AFTER all properties and attributes are evaluated — the
expensive part we now avoid entirely.
Sensor platform (Timer #2 + #3):
- New _write_if_changed() method compares native_value before writing
- Timer #3 (30s, 7 entities): Skips all writes when no period active
- Timer #2 (15min, ~45 entities): Skips enum levels/ratings that stay
constant across quarter-hour intervals
- Replaces data_lifecycle_status-only pattern with unified approach
Binary sensor platform (Timer #2):
- Period sensors only write at actual period boundaries, not every 15min
Coordinator push updates always write (sentinel reset ensures freshness).
Impact: Eliminates asyncio "Executing TimerHandle took 1.4s" warnings
caused by redundant property evaluation in Timer #3 callbacks. Reduces
event loop blocking from ~1.4s to microseconds when values unchanged.
Add four optional parameters to the get_chartdata service:
- include_energy: Include raw energy/spot price (default: false)
- include_tax: Include tax component (default: false)
- energy_field: Custom field name (default: energy_price)
- tax_field: Custom field name (default: tax)
Custom field names allow direct compatibility with ApexCharts
and other charting tools without post-processing.
All code paths (all/segments/none insert_nulls modes) and the
last-interval handler include energy/tax when enabled.
Added translations for all 5 languages (en, de, nl, nb, sv).
Impact: Users can include price composition data in chart exports,
enabling visual breakdowns of energy cost vs. taxes in dashboards.
Add energy_price and tax attributes to interval and daily stat sensors:
- Interval sensors (current/next/previous): energy_price and tax from
the specific 15-minute interval
- Daily min/max sensors: energy_price and tax from the extreme interval
- Daily average sensors: energy_price_mean, energy_price_median,
tax_mean, tax_median — matching the existing mean/median pattern
used for the main price attribute
Calculator caches both mean and median for energy/tax using
calculate_median() from utils/average. All new attributes are
excluded from Recorder to prevent database bloat.
Impact: Users can see price composition (spot price vs. taxes) on
all major price sensors. Enables solar feed-in and net metering
automations based on raw energy prices.
Request `energy` and `tax` fields alongside `total` in both
quarter-hourly price queries. These represent the raw spot price and
the tax/fee component that together make up the total consumer price.
Updated hourly aggregation in formatters.py to carry energy/tax
values through to aggregated output.
Impact: Enables downstream consumers (sensors, services) to expose
price composition data. Useful for solar feed-in compensation and
net metering (saldering) calculations where the raw energy price
is needed separately from taxes.
Added brand/ directory to custom_components/tibber_prices/ with all
8 supported PNG variants, generated from existing SVGs in images/:
- icon.png / dark_icon.png (256×256)
- icon@2x.png / dark_icon@2x.png (512×512)
- logo.png / dark_logo.png (500×128)
- logo@2x.png / dark_logo@2x.png (1000×256)
Local brand images automatically take priority over CDN images and
are served via the HA brands proxy API (/api/brands/integration/).
Silently ignored on HA < 2026.3, no changes to manifest.json needed.
Updated AGENTS.md to document the brand/ directory under "ALLOWED in root".
Impact: Integration icon and logo now display correctly in HA ≥ 2026.3
without requiring a separate submission to the HA brands repository.
Renamed 8 price_trend_Xh entries to price_outlook_Xh and added 15 new
price_trajectory_Xh entries (2h–12h) in all 5 languages (de, en, nb, nl, sv).
translations/ (HA-native: name + 5 states per sensor):
- EN: "Price Outlook (Xh)" / "Price Trajectory (Xh)"
- DE: "Preisausblick (Xh)" / "Preisverlauf (Xh)"
- NB: "Prisutblikk (Xt)" / "Prisforløp (Xt)"
- NL: "Prijsvooruitzicht (Xu)" / "Prijstrajectorie (Xu)"
- SV: "Prisöversikt (Xh)" / "Prisutveckling (Xh)"
custom_translations/ (description + long_description + usage_tips):
- Outlook descriptions updated to explain window-average comparison
semantics (not price direction)
- Trajectory descriptions explain first-half vs second-half logic and
the "outlook: falling + trajectory: rising = you're AT the minimum" pattern
- Trajectory long_description and usage_tips in English for all languages;
description field in native language
Impact: Entity display names update to reflect the corrected semantic meaning.