Commit graph

722 commits

Author SHA1 Message Date
Julian Pawlowski
ac09e5f235 fix(docs): avoid mdx/ssg runtime error in energy-tax formula
Replace the inline KaTeX block in the Energy Price & Tax Breakdown
section with a plain inline equation string.

The previous expression caused a Docusaurus SSG runtime failure on the
sensors page (ReferenceError during static rendering).

Impact: User docs build now succeeds consistently for the sensors page.
2026-04-09 18:41:46 +00:00
Julian Pawlowski
aee1920292 chore(pre-commit): add docusaurus build guard for changed docs sites
Add a local pre-commit hook that builds Docusaurus when files under
docs/user or docs/developer are staged.

Introduced scripts/docs/build-changed-sites to detect which docs site
was touched and run only the required npm build(s).

Impact: Prevents broken MDX/Docusaurus changes from being committed by
failing fast in pre-commit before CI.
2026-04-09 18:41:41 +00:00
Julian Pawlowski
06eedee410 docs: update links for energy and tax fields in actions documentation 2026-04-09 18:35:05 +00:00
Julian Pawlowski
9c4ac6bce4 docs(user): document energy price and tax breakdown
Add new section 'Energy Price & Tax Breakdown' to sensors.md:
- Attribute overview table (interval, min/max, daily avg sensors)
- Use cases: solar feed-in/net metering, price composition analysis,
  dashboard cost breakdown with example YAML templates
- Cache transition note for gradual data availability after update

Add 'Energy & Tax Fields in get_chartdata' section to actions.md:
- Parameter documentation with defaults
- Example service call YAML
- ApexCharts integration example with custom field names

Impact: Users can discover and utilize the new energy/tax attributes
with ready-to-use automation and dashboard examples.
2026-04-09 18:28:06 +00:00
Julian Pawlowski
d1b25e9cfe feat(services): add energy/tax fields to get_chartdata action
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.
2026-04-09 18:27:53 +00:00
Julian Pawlowski
edabb49309 feat(sensors): expose energy/tax breakdown as sensor attributes
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.
2026-04-09 18:27:36 +00:00
Julian Pawlowski
f5dcf04aab feat(api): add energy and tax fields to Tibber GraphQL queries
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.
2026-04-09 18:27:21 +00:00
Julian Pawlowski
e1da4cfa89 chroe(dev): update Home Assistant version in bootstrap script to 2026.4.1
Some checks are pending
Deploy Docusaurus Documentation (Dual Sites) / Build and Deploy Documentation Sites (push) Waiting to run
Lint / Ruff (push) Waiting to run
Validate / Hassfest validation (push) Waiting to run
Validate / HACS validation (push) Waiting to run
2026-04-09 17:13:03 +00:00
Julian Pawlowski
50dc874274 feat(brand): add local brand images for HA brands proxy API
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.
2026-04-09 17:06:13 +00:00
Julian Pawlowski
124824a2ea test(sensors): update timer assignment tests for renamed/new trend sensors
test_trend_sensors_use_quarter_hour_timer():
  - Replaced price_trend_Xh keys with price_outlook_Xh
  - Added 7 price_trajectory_Xh keys to the assertion list
  - Updated docstring from "price trend" to "price outlook/trajectory"

Impact: Test suite passes with renamed and new sensor keys.
2026-04-09 16:09:14 +00:00
Julian Pawlowski
cbf5e1a3fe docs(sensors): rename trend→outlook, document price_trajectory sensors
Updated user documentation to reflect renamed and new sensors.

sensors.md:
  - Section renamed "Simple Trend Sensors" → "Price Outlook Sensors (1h–12h)"
  - All price_trend_Xh entity references → price_outlook_Xh
  - Callout box updated: explains that outlook sensors can mislead at a
    price minimum and recommends combining with trajectory sensors
  - New section "Price Trajectory Sensors (2h–12h)" added before
    "Current Price Trend":
    - Table showing which halves are compared per window
    - Callout box with the 4 outlook+trajectory combination patterns
      (falling+rising = AT the minimum, etc.)
    - Key attributes table (first_half_avg, second_half_avg, half_diff_%)
  - "Trend Sensors vs Average Sensors" → "Outlook & Trajectory Sensors vs
    Average Sensors"

icon-colors.md:
  - "Price trend sensors (e.g., price_trend_3h)" → "Price outlook sensors
    (e.g., price_outlook_3h)"
  - Example entity updated to sensor.<home_name>_price_outlook_3h

automation-examples.md:
  - All price_trend_1h/2h/3h/4h/6h references → price_outlook_Xh
  - current_price_trend and next_price_trend_change unchanged (correct names)

Impact: Documentation matches actual entity names. New trajectory section
helps users understand when to use outlook vs trajectory sensors together.
2026-04-09 16:09:04 +00:00
Julian Pawlowski
2b96ccc650 feat(translations): add price_outlook_Xh and price_trajectory_Xh strings
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.
2026-04-09 16:08:54 +00:00
Julian Pawlowski
33f57ff077 feat(sensors)!: rename price_trend_Xh → price_outlook_Xh, add price_trajectory_Xh
Renamed 8 sensors to clarify what they actually measure, and added 7 new
sensors for a different (and often more useful) calculation.

--- WHY THE RENAME ---

The old name "price_trend_Xh" implied the sensor shows where prices are
heading. It doesn't — it compares CURRENT price vs the FUTURE WINDOW AVERAGE.
At a price minimum, it shows "strongly_falling" (because the cheap minimum
pulls the average below your current high price), which is the opposite of
intuitive. The name "price_outlook_Xh" correctly conveys: "is now cheaper
or more expensive than the next Nh on average?"

--- NEW: price_trajectory_Xh ---

These sensors compare FIRST HALF vs SECOND HALF of the window, revealing
actual price direction within the window:

  price_trajectory_2h: avg(hour 1) vs avg(hour 2)
  price_trajectory_3h: avg(first 1.5h) vs avg(second 1.5h)
  price_trajectory_4h: avg(first 2h) vs avg(second 2h)
  price_trajectory_5h: avg(first 2.5h) vs avg(second 2.5h)
  price_trajectory_6h: avg(first 3h) vs avg(second 3h)
  price_trajectory_8h: avg(first 4h) vs avg(second 4h)
  price_trajectory_12h: avg(first 6h) vs avg(second 6h)

The key use case: at a price minimum, price_outlook_Xh shows "strongly_falling"
but price_trajectory_Xh shows "rising" — correctly revealing the upcoming
reversal. "outlook: falling + trajectory: rising" = you're AT the minimum.

--- IMPLEMENTATION ---

sensor/calculators/trend.py:
  - get_price_outlook_value() (was: get_price_trend_value())
  - New: get_price_trajectory_value(*, hours: int)
  - New: _calculate_first_half_average(hours, next_interval_start)
  - New: get_trajectory_attributes() → first_half_avg, second_half_avg, half_diff_%
  - clear_trend_cache() also resets _trajectory_attributes

sensor/definitions.py:
  - 8 SensorEntityDescription entries: key/translation_key price_trend_Xh → price_outlook_Xh
  - New PRICE_TRAJECTORY_SENSORS tuple (2h–5h enabled by default, 6h/8h/12h disabled)

sensor/value_getters.py:
  - 8 lambda entries renamed
  - 7 new trajectory lambda entries added

sensor/attributes/trend.py:
  - startswith("price_trend_") → startswith("price_outlook_")
  - New elif branch routing price_trajectory_* to cached trajectory_attributes

sensor/core.py:
  - startswith checks updated for both prefix families
  - cached_data dict extended with "trajectory_attributes"

coordinator/constants.py:
  - TIME_SENSITIVE_ENTITY_KEYS: 8 renamed + 7 new trajectory keys added

config_flow_handlers/entity_check.py:
  - volatility + price_trend affected-entity lists: 8 renamed + 7 new

BREAKING CHANGE: Sensors price_trend_1h, price_trend_2h, price_trend_3h,
price_trend_4h, price_trend_5h, price_trend_6h, price_trend_8h,
price_trend_12h have been removed without a deprecation period.

Migration:
  Replace price_trend_Xh → price_outlook_Xh everywhere (automations,
  dashboards, templates). Behavior is identical — only the entity name
  changed. If you want to detect actual price direction within the window
  (e.g. "are prices rising or falling right now?"), use the new
  price_trajectory_Xh sensors instead.

Impact: Users must update automations and dashboards. Entity IDs change from
sensor.<home>_price_trend_Xh to sensor.<home>_price_outlook_Xh. New
price_trajectory_Xh sensors provide complementary direction information.
2026-04-09 16:08:42 +00:00
Julian Pawlowski
d0b6ea0e1a fix(sensors)!: fix DURATION sensors displaying in minutes instead of hours
Some checks failed
Validate / HACS validation (push) Has been cancelled
Lint / Ruff (push) Has been cancelled
Validate / Hassfest validation (push) Has been cancelled
Added `suggested_unit_of_measurement=UnitOfTime.HOURS` to all 7 DURATION
sensors to prevent HA from auto-selecting minutes as the display unit.
Without this, HA would pick "min" for small values (e.g., 0.75 h) and then
display large values as "1238 Min." instead of the intended "20 Std. 38 Min."

Affected sensors:
- trend_change_in_minutes
- best_price_period_duration / peak_price_period_duration
- best_price_remaining_minutes / peak_price_remaining_minutes
- best_price_next_in_minutes / peak_price_next_in_minutes

BREAKING CHANGE: Sensor state unit changes from minutes to hours for users
whose entity registry stored "min" as the display unit (the previous default).
Automations using the raw state value (e.g., `state < 60` for "less than 60
minutes") must be updated to use hours (e.g., `state < 1`).
The state attributes `remaining_minutes` and `next_in_minutes` continue to
provide integer minutes and are unaffected.

Impact: Duration sensors now display dynamically as "X h Y min" (e.g.,
"1 h 15 min") instead of a large minutes value like "1238 Min.". Users who
manually customized the unit in HA settings are not affected.
2026-04-08 08:01:16 +00:00
Julian Pawlowski
aa0f543ec5 fix: ensure SVG backgrounds are solid to prevent transparency issues
Some checks failed
Lint / Ruff (push) Waiting to run
Validate / Hassfest validation (push) Waiting to run
Validate / HACS validation (push) Waiting to run
Auto-Tag on Version Bump / Check and create version tag (push) Has been cancelled
Deploy Docusaurus Documentation (Dual Sites) / Build and Deploy Documentation Sites (push) Has been cancelled
2026-04-07 15:32:52 +00:00
Julian Pawlowski
a4a43e3d34 fix: update default Copilot model version to 4.6 2026-04-07 15:22:29 +00:00
Julian Pawlowski
4efd6b7267 feat: add versioned sidebars for user and developer documentation 2026-04-07 15:19:10 +00:00
Julian Pawlowski
bb176135f6 fix(ci): ensure release notes end with newline before heredoc delimiter
cliff.toml has trim=true which strips git-cliff's trailing newline.
When written to GITHUB_OUTPUT via heredoc, the closing delimiter was
appended to the last content line instead of its own line, causing
"Matching delimiter not found" error.

Added printf '\n' in the workflow and echo "" in generate-notes to
guarantee a newline before the heredoc closing delimiter.

Impact: Release workflow no longer fails when generating release notes.
2026-04-07 15:16:03 +00:00
Julian Pawlowski
c160063067 Merge branch 'main' of https://github.com/jpawlowski/hass.tibber_prices 2026-04-07 15:09:58 +00:00
Julian Pawlowski
8bd3ef85c0 fix(ci): use random heredoc delimiter in release workflow
$GITHUB_OUTPUT heredoc blocks used literal 'EOF' as delimiter, which
breaks parsing if generated release notes contain 'EOF' on its own line.

Replace static 'EOF' with openssl rand -hex 16 random delimiter in
both the version-warning and release-notes output blocks.

Impact: Release workflow no longer fails when commit message bodies
contain 'EOF'.
2026-04-07 15:09:56 +00:00
github-actions[bot]
48d088281b docs: add version snapshot v0.29.0 and cleanup old versions [skip ci] 2026-04-07 15:09:08 +00:00
Julian Pawlowski
070905e880 chore(release): bump version to 0.29.0 2026-04-07 15:07:08 +00:00
Julian Pawlowski
b7cf4442bd feat: enhance mermaid lightbox interaction with improved accessibility and hover hints 2026-04-07 15:06:23 +00:00
Julian Pawlowski
dba96e38e0 fix(css): enhance mermaid lightbox styling for better theme integration 2026-04-07 14:58:10 +00:00
Julian Pawlowski
ebc3c38007 Add @docusaurus/faster dependency to package.json 2026-04-07 14:50:57 +00:00
Julian Pawlowski
86c5db179e fix(css): adjust width of mermaid lightbox inner card for better responsiveness 2026-04-07 14:46:51 +00:00
dependabot[bot]
c7bd0b7a93
chore(deps): bump the react group in /docs/developer with 2 updates (#103)
Bumps the react group in /docs/developer with 2 updates: [react](https://github.com/facebook/react/tree/HEAD/packages/react) and [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom).


Updates `react` from 19.2.1 to 19.2.4
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.4/packages/react)

Updates `react-dom` from 19.2.1 to 19.2.4
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.4/packages/react-dom)

---
updated-dependencies:
- dependency-name: react
  dependency-version: 19.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: react
- dependency-name: react-dom
  dependency-version: 19.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: react
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 16:39:58 +02:00
dependabot[bot]
688cf0d5a3
chore(deps-dev): bump typescript from 5.6.3 to 6.0.2 in /docs/user (#102)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.6.3 to 6.0.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.6.3...v6.0.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 6.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 16:38:53 +02:00
dependabot[bot]
de577c83a6
chore(deps-dev): bump typescript from 5.6.3 to 6.0.2 in /docs/developer (#104)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.6.3 to 6.0.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.6.3...v6.0.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 6.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 16:37:15 +02:00
dependabot[bot]
fd3c949e90
chore(deps): bump the react group in /docs/user with 2 updates (#101)
Bumps the react group in /docs/user with 2 updates: [react](https://github.com/facebook/react/tree/HEAD/packages/react) and [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom).


Updates `react` from 19.2.1 to 19.2.4
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.4/packages/react)

Updates `react-dom` from 19.2.1 to 19.2.4
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.4/packages/react-dom)

---
updated-dependencies:
- dependency-name: react
  dependency-version: 19.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: react
- dependency-name: react-dom
  dependency-version: 19.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: react
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 16:36:34 +02:00
dependabot[bot]
fc8ec33f11
chore(deps): bump home-assistant/actions (#100)
Bumps [home-assistant/actions](https://github.com/home-assistant/actions) from 5752577ea7cc5aefb064b0b21432f18fe4d6ba90 to f6f29a7ee3fa0eccadf3620a7b9ee00ab54ec03b.
- [Release notes](https://github.com/home-assistant/actions/releases)
- [Commits](5752577ea7...f6f29a7ee3)

---
updated-dependencies:
- dependency-name: home-assistant/actions
  dependency-version: f6f29a7ee3fa0eccadf3620a7b9ee00ab54ec03b
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 16:36:07 +02:00
Julian Pawlowski
f4fecc3ee0 feat(deps): add npm package updates for user and developer documentation directories 2026-04-07 14:32:12 +00:00
Julian Pawlowski
5f52dd2524 chore: update dependencies to version 3.10.0 in package.json 2026-04-07 14:31:25 +00:00
Julian Pawlowski
db900c2a4b fix(docs): update links in automation examples and intro documentation 2026-04-07 14:25:30 +00:00
Julian Pawlowski
3aa8a43e3a fix(docs): commit missing versioned_sidebars for all existing versions
versioned_docs/ was already tracked but versioned_sidebars/ was never
committed. Docusaurus requires both to render sidebar navigation for
old versions — without the sidebar files, all versioned pages show
no navigation.

Adds sidebar snapshots for user and developer docs:
  v0.21.0, v0.22.0, v0.22.1, v0.23.0, v0.23.1, v0.24.0, v0.27.0, v0.28.0

Future versions: CI (docusaurus.yml) runs docs:version on each stable
tag push, which generates both versioned_docs/ and versioned_sidebars/.
The workflow should be updated to commit these files back, or they need
to be added manually after each release.

Impact: Sidebar navigation now appears correctly for all existing
versioned documentation pages.
2026-04-07 14:16:53 +00:00
Julian Pawlowski
9fea34b8b4 fix(deps): remove unnecessary peer dependencies from package-lock.json 2026-04-07 14:09:27 +00:00
Julian Pawlowski
552db6ef7d feat(docs): add click-to-zoom lightbox for Mermaid diagrams
Swizzled @docusaurus/theme-mermaid's Mermaid component to wrap
every diagram with a portal-based lightbox overlay.

An expand icon appears on diagram hover. Clicking opens the SVG
in a full-screen overlay (90vw × 85vh, scrollable). Closes via
backdrop click, Escape key, or close button. SSR-safe, no
external dependencies. Matches Tibber electric color theme.

Impact: Users can inspect complex flowcharts (e.g. the Options
Flow wizard) without squinting at small embedded diagrams.
2026-04-07 14:09:19 +00:00
Julian Pawlowski
1c25ac1fb0 feat(docs): improve Giscus comment UX for maintainer clarity
Switched Giscus mapping from 'pathname' to 'og:title' with strict=1.
Discussions are now titled after the readable page title (e.g.
'Chart Examples | Tibber Prices Integration') instead of the URL path,
making them immediately identifiable in the GitHub Discussions list.

Added a small hint above every comment box pointing users to open
a dedicated Discussion on GitHub for new questions/ideas, so
page-specific comments don't accumulate unrelated threads.

Note: Existing Discussion #94 (pathname-mapped) will no longer appear
on chart-examples — a new og:title-mapped discussion will be created
on the next comment. #94 remains visible on GitHub.

Impact: Maintainer can identify discussion origin at a glance.
Users are guided toward proper Discussion threads for new topics.
2026-04-07 14:01:37 +00:00
Julian Pawlowski
d8f005d3bb docs: explain how to find the config entry_id
Added a dedicated 'Finding Your Entry ID' section to actions.md
explaining the two workflows: dropdown in the Action UI vs.
'Copy Config Entry ID' from the integration's three-dot menu in YAML.

Added matching :::info callouts to chart-examples.md and
automation-examples.md where entry_id: YOUR_ENTRY_ID appears in code
examples, and a new 'Config Entry ID' entry in the glossary.

Addresses user confusion reported in GitHub Discussions #94.

Impact: Users no longer get stuck on YOUR_ENTRY_ID placeholders.
Both GUI and YAML workflows are clearly explained at the point of need.
2026-04-07 14:01:33 +00:00
Julian Pawlowski
190c979e9c docs(user): comprehensive trend decision model and automation guides
sensors.md:
- Added "How to Use Trend Sensors for Decisions" section with :::danger
  "Common Misconception — Don't Wait for Stable!" box
- Comparison table (rising/falling/stable → what it means → action)
- Basic automation YAML pattern
- Multi-window combination table (1h + 6h → interpretation)
- Dashboard quick-glance guide
- Documented trend_change_in_minutes sensor

automation-examples.md:
- Replaced placeholder with full automation examples
- V-shaped price days explanation with mermaid timeline
- "Ride the Full Cheap Wave" heat pump automation
- "Pre-Emptive Start Before Best Price" pattern
- "Protect Against Rising Prices" EV charging automation
- "Multi-Window Trend Strategy" (1h + 6h + best_price_period)
- Sensor Combination Quick Reference table
- Volatility-based automation examples
- Best hour detection automation
- ApexCharts card configuration guide

Other docs: trend-related updates to concepts, configuration,
glossary, installation, period-calculation, troubleshooting.

Impact: Users have comprehensive guides for trend-based automations
with real YAML examples and clear decision frameworks.
2026-04-07 13:45:40 +00:00
Julian Pawlowski
5d673e65b4 feat(translations): add trend sensor descriptions and decision model tips
Standard translations (5 languages):
- Added config flow labels/descriptions for trend change confirmation,
  min price change, and min price change strongly
- Updated strongly threshold descriptions (6% → 9%)
- Added trend_change_in_minutes sensor name

Custom translations (5 languages):
- Rewritten usage_tips for all 8 trend sensors (1h-12h) with action-
  oriented decision guide: "rising = ACT NOW", "falling = WAIT"
- Addresses common misconception ("rising" ≠ "too late")
- Added trend_change_in_minutes description and tips
- Updated long_descriptions: clarified shared-base behavior, corrected
  threshold references from >5% to ±3%/±9%
- Updated next_price_trend_change: direction-group explanation

Impact: Users understand trend sensors as decision tools, not trajectory
indicators. All 5 languages (en/de/nb/nl/sv) updated consistently.
2026-04-07 13:45:13 +00:00
Julian Pawlowski
798de5946d feat(config_flow): add trend confirmation and noise floor settings
Added 3 new config fields to price trend options step:
- Trend Change Confirmation (2-6 intervals slider)
- Min Price Change for trend (display-unit-aware slider)
- Min Price Change for strong trend (display-unit-aware slider)

Price change sliders scale between base currency (EUR/NOK) storage and
display unit (ct/øre) presentation using get_display_unit_factor().
Added migration in __init__.py to convert old display-unit values to
base currency format.

Impact: Users can tune trend sensitivity: higher confirmation = fewer
false changes, higher min price change = no trends from tiny fluctuations.
2026-04-07 13:44:47 +00:00
Julian Pawlowski
91efeed90f feat(sensors): add trend_change_in_minutes countdown sensor
New duration sensor showing time until next price trend change as hours
(e.g., 2.25 h). Registered in MINUTE_UPDATE_ENTITY_KEYS for per-minute
updates. Shares cached attributes with next_price_trend_change timestamp
sensor.

Added trend attributes to _unrecorded_attributes (threshold/volatility/diff
attributes excluded from recorder). Updated timer group size test expectation
from 6 to 7.

Impact: Users can display a live countdown to the next trend change on
dashboards and use it in automations (e.g., "if < 0.25 h, prepare").
2026-04-07 13:44:22 +00:00
Julian Pawlowski
90e2c3c1dc feat(trend): add direction-group detection, noise floor, and confirmation hysteresis
Refactored trend calculator with direction-group-based trend change detection
(rising/strongly_rising treated as same group, falling/strongly_falling as same
group). Added minimum absolute price change thresholds (noise floor) to prevent
spurious trends at low price levels. Both percentage AND absolute conditions
must now be met.

Updated strongly threshold defaults from ±6% to ±9% (3x base for perceptual
scaling). Added missing strongly thresholds and new config keys to
get_default_options(). calculate_price_trend() now returns volatility_factor
as 4th tuple element for threshold transparency.

Added CONF_PRICE_TREND_CHANGE_CONFIRMATION (default: 3 intervals = 45min)
and CONF_PRICE_TREND_MIN_PRICE_CHANGE / _STRONGLY with validation limits.

Updated tests for new 4-tuple return value.

Impact: More stable trend detection — fewer false trend changes during low-price
periods. Direction-group logic prevents noise from "rising ↔ strongly_rising"
oscillations. Users can fine-tune noise floor for their market.
2026-04-07 13:44:01 +00:00
Julian Pawlowski
4d9b1545b0 feat(release): enhance AI prompt for generating user-focused release notes
Some checks are pending
Auto-Tag on Version Bump / Check and create version tag (push) Waiting to run
Deploy Docusaurus Documentation (Dual Sites) / Build and Deploy Documentation Sites (push) Waiting to run
Lint / Ruff (push) Waiting to run
Validate / Hassfest validation (push) Waiting to run
Validate / HACS validation (push) Waiting to run
2026-04-06 15:28:17 +00:00
Julian Pawlowski
a978b645cf feat: add footer to release notes with coffee donation link 2026-04-06 15:18:07 +00:00
github-actions[bot]
da3aa3bf1e docs: add version snapshot v0.28.0 and cleanup old versions [skip ci] 2026-04-06 14:40:08 +00:00
Julian Pawlowski
8c04e9f924 chore(release): bump version to 0.28.0 2026-04-06 14:37:08 +00:00
Julian Pawlowski
8f05f8cac7 perf(interval_pool): hoist fetch_groups and precompute period criteria
- Move UTC import from inline (inside _has_real_gaps_in_range) to
  module-level in manager.py
- Hoist get_fetch_groups() out of while loop in _get_cached_intervals:
  eliminates ~384 function calls per invocation
- Pre-compute criteria_by_day dict in build_periods before the for-loop:
  eliminates ~381 redundant NamedTuple constructions per call; only
  ref_price/avg_price vary by day (max 3 entries), flex/min_distance/
  reverse_sort are constant throughout

Impact: Reduces unnecessary object creation during the hot paths called
every 15 minutes and during all relaxation phases.
2026-04-06 14:35:33 +00:00
Julian Pawlowski
636bd7a797 refactor(sensor): replace redundant pass-through lambdas with direct references
PLW0108: Three lambdas were simple pass-throughs that added no value:

  lambda data: aggregate_level_data(data)  →  aggregate_level_data
  lambda: lifecycle_calculator.get_lifecycle_state()  →  lifecycle_calculator.get_lifecycle_state

Affected files:
  sensor/calculators/rolling_hour.py (line 115)
  sensor/helpers.py (line 139)
  sensor/value_getters.py (line 220)

Impact: No behaviour change. Linter now passes with zero warnings.
2026-04-06 14:28:51 +00:00