diff --git a/docs/user/docs/actions.md b/docs/user/docs/actions.md
index cdcfbb2..13e4b37 100644
--- a/docs/user/docs/actions.md
+++ b/docs/user/docs/actions.md
@@ -166,7 +166,7 @@ Returns data points like:
}
```
-**Use case — Solar feed-in chart:** Overlay the energy price (what you earn by exporting) alongside the total price to visualize the best export windows. See [Sensors — Energy Price & Tax Breakdown](sensors.md#energy-price--tax-breakdown) for more use cases.
+**Use case — Solar feed-in chart:** Overlay the energy price (what you earn by exporting) alongside the total price to visualize the best export windows. See [Energy & Tax Attributes](sensors-energy-tax.md) for more use cases.
---
diff --git a/docs/user/docs/automation-examples.md b/docs/user/docs/automation-examples.md
index 3eb59b0..ecc949f 100644
--- a/docs/user/docs/automation-examples.md
+++ b/docs/user/docs/automation-examples.md
@@ -7,7 +7,7 @@
- [Price-Based Automations](#price-based-automations)
- [Volatility-Aware Automations](#volatility-aware-automations)
- [Best Hour Detection](#best-hour-detection)
-- [ApexCharts Cards](#apexcharts-cards)
+- [Charts & Visualizations](#charts--visualizations)
---
@@ -269,7 +269,7 @@ automation:
:::tip Why "rising" means "act now"
-A common misconception: **"rising" does NOT mean "too late"**. It means your current price is **lower** than the future average — so right now is actually a good time. See [How to Use Trend Sensors for Decisions](sensors.md#how-to-use-trend-sensors-for-decisions) in the sensor documentation for details.
+A common misconception: **"rising" does NOT mean "too late"**. It means your current price is **lower** than the future average — so right now is actually a good time. See [How to Use Trend Sensors for Decisions](sensors-trends.md#how-to-use-trend-sensors-for-decisions) in the sensor documentation for details.
:::
### Sensor Combination Quick Reference
@@ -502,97 +502,6 @@ automation:
---
-## ApexCharts Cards
+## Charts & Visualizations
-> ⚠️ **IMPORTANT:** The `tibber_prices.get_apexcharts_yaml` service generates a **basic example configuration** as a starting point. It is NOT a complete solution for all ApexCharts features.
->
-> This integration is primarily a **data provider**. Due to technical limitations (segmented time periods, service API usage), many advanced ApexCharts features require manual customization or may not be compatible.
->
-> **For advanced customization:** Use the `get_chartdata` service directly to build charts tailored to your specific needs. Community contributions with improved configurations are welcome!
-
-The `tibber_prices.get_apexcharts_yaml` service generates basic ApexCharts card configuration examples for visualizing electricity prices.
-
-:::info Finding your Entry ID (`entry_id`)
-The examples below contain `entry_id: YOUR_CONFIG_ENTRY_ID`. This value identifies which Tibber home (integration instance) the action targets.
-
-**In the Action UI (Developer Tools → Actions or the automation editor):** The `entry_id` field is a **dropdown** — just select your Tibber home and HA fills in the correct ID automatically.
-
-**In YAML:** Go to **Settings → Devices & Services**, find the **Tibber Prices** card, open the **⋮** (three-dot) menu, and choose **"Copy Config Entry ID"**. Paste the copied value in place of `YOUR_CONFIG_ENTRY_ID`.
-:::
-
-### Prerequisites
-
-**Required:**
-
-- [ApexCharts Card](https://github.com/RomRider/apexcharts-card) - Install via HACS
-
-**Optional (for rolling window mode):**
-
-- [Config Template Card](https://github.com/iantrich/config-template-card) - Install via HACS
-
-### Installation
-
-1. Open HACS → Frontend
-2. Search for "ApexCharts Card" and install
-3. (Optional) Search for "Config Template Card" and install if you want rolling window mode
-
-### Example: Fixed Day View
-
-```yaml
-# Generate configuration via automation/script
-service: tibber_prices.get_apexcharts_yaml
-data:
- entry_id: YOUR_CONFIG_ENTRY_ID
- day: today # or "yesterday", "tomorrow"
- level_type: rating_level # or "level" for 5-level view
-response_variable: apexcharts_config
-```
-
-Then copy the generated YAML into your Lovelace dashboard.
-
-### Example: Rolling 48h Window
-
-For a dynamic chart that automatically adapts to data availability:
-
-```yaml
-service: tibber_prices.get_apexcharts_yaml
-data:
- entry_id: YOUR_CONFIG_ENTRY_ID
- day: rolling_window # Or omit for same behavior (default)
- level_type: rating_level
-response_variable: apexcharts_config
-```
-
-**Behavior:**
-
-- **When tomorrow data available** (typically after ~13:00): Shows today + tomorrow
-- **When tomorrow data not available**: Shows yesterday + today
-- **Fixed 48h span:** Always shows full 48 hours
-
-**Auto-Zoom Variant:**
-
-For progressive zoom-in throughout the day:
-
-```yaml
-service: tibber_prices.get_apexcharts_yaml
-data:
- entry_id: YOUR_CONFIG_ENTRY_ID
- day: rolling_window_autozoom
- level_type: rating_level
-response_variable: apexcharts_config
-```
-
-- Same data loading as rolling window
-- **Progressive zoom:** Graph span starts at ~26h in the morning and decreases to ~14h by midnight
-- **Updates every 15 minutes:** Always shows 2h lookback + remaining time until midnight
-
-**Note:** Rolling window modes require Config Template Card to dynamically adjust the time range.
-
-### Features
-
-- Color-coded price levels/ratings (green = cheap, yellow = normal, red = expensive)
-- Best price period highlighting (semi-transparent green overlay)
-- Automatic NULL insertion for clean gaps
-- Translated labels based on your Home Assistant language
-- Interactive zoom and pan
-- Live marker showing current time
+> **Looking for chart configurations?** See the **[Chart Examples Guide](chart-examples.md)** for ApexCharts card configurations, rolling window modes, and more.
diff --git a/docs/user/docs/chart-examples.md b/docs/user/docs/chart-examples.md
index 49ad602..17db73d 100644
--- a/docs/user/docs/chart-examples.md
+++ b/docs/user/docs/chart-examples.md
@@ -291,7 +291,7 @@ cards:
## Next Steps
- **[Actions Guide](actions.md)**: Complete documentation of `get_apexcharts_yaml` parameters
-- **[Chart Metadata Sensor](sensors.md#chart-metadata)**: Learn about dynamic Y-axis scaling
+- **[Chart Metadata Sensor](sensors-overview.md#chart-metadata)**: Learn about dynamic Y-axis scaling
- **[Period Calculation Guide](period-calculation.md)**: Configure best price period detection
---
diff --git a/docs/user/docs/concepts.md b/docs/user/docs/concepts.md
index f0befd2..e225143 100644
--- a/docs/user/docs/concepts.md
+++ b/docs/user/docs/concepts.md
@@ -93,7 +93,7 @@ Some days show distinctive price curve shapes:
- **V-shaped**: Prices drop sharply, hit a brief minimum, then rise sharply again (common during short midday solar surplus)
- **U-shaped**: Prices drop to a low level and stay there for an extended period before rising (common during nighttime or extended low-demand periods)
-**Why this matters:** On these days, the Best Price Period may be short (1–2 hours, covering only the absolute minimum), but prices can remain favorable for 4–6 hours. By combining [trend sensors](sensors.md#trend-sensors) with [price levels](sensors.md#core-price-sensors) in automations, you can ride the full cheap wave instead of only using the detected period.
+**Why this matters:** On these days, the Best Price Period may be short (1–2 hours, covering only the absolute minimum), but prices can remain favorable for 4–6 hours. By combining [trend sensors](sensors-trends.md) with [price levels](sensors-ratings-levels.md) in automations, you can ride the full cheap wave instead of only using the detected period.
See [Automation Examples → V-Shaped Days](automation-examples.md#understanding-v-shaped-price-days) for practical patterns.
@@ -110,5 +110,5 @@ Each home gets its own set of sensors with unique entity IDs.
💡 **Next Steps:**
- [Glossary](glossary.md) - Detailed term definitions
-- [Sensors](sensors.md) - How to use sensor data
+- [Sensors Overview](sensors-overview.md) - How to use sensor data
- [Automation Examples](automation-examples.md) - Practical use cases
diff --git a/docs/user/docs/configuration.md b/docs/user/docs/configuration.md
index 7a15806..1cff410 100644
--- a/docs/user/docs/configuration.md
+++ b/docs/user/docs/configuration.md
@@ -121,7 +121,7 @@ Configure when trend sensors report rising/falling:
| **Falling** | -3% | Future average this much below current → "falling" |
| **Strongly falling** | -9% | Future average far below current → "strongly_falling" |
-Thresholds are [volatility-adaptive](sensors.md#trend-sensors): automatically widened on volatile days to prevent constant state changes.
+Thresholds are [volatility-adaptive](sensors-trends.md): automatically widened on volatile days to prevent constant state changes.
### Step 9: Chart Data Export (Legacy)
@@ -184,7 +184,7 @@ This setting applies to:
- Hourly smoothed prices (current hour, next hour)
- Future forecast sensors (next 1h, 2h, 3h, ... 12h)
-See the **[Sensors Guide](sensors.md#average-price-sensors)** for detailed examples.
+See the **[Average Sensors](sensors-average.md)** for detailed examples.
#### Choosing Your Display
diff --git a/docs/user/docs/dynamic-icons.md b/docs/user/docs/dynamic-icons.md
index 8bcbe6c..4393886 100644
--- a/docs/user/docs/dynamic-icons.md
+++ b/docs/user/docs/dynamic-icons.md
@@ -176,5 +176,5 @@ The exact icons are chosen to be intuitive and meaningful in the Home Assistant
## See Also
- [Dynamic Icon Colors](icon-colors.md) - Color your icons based on state
-- [Sensors Reference](sensors.md) - Complete list of available sensors
+- [Sensors Overview](sensors-overview.md) - Complete list of available sensors
- [Automation Examples](automation-examples.md) - Use dynamic icons in automations
diff --git a/docs/user/docs/glossary.md b/docs/user/docs/glossary.md
index ab5d9b5..7c763ec 100644
--- a/docs/user/docs/glossary.md
+++ b/docs/user/docs/glossary.md
@@ -115,5 +115,5 @@ Quick reference for terms used throughout the documentation.
💡 **See Also:**
- [Core Concepts](concepts.md) - In-depth explanations
-- [Sensors](sensors.md) - How sensors use these concepts
+- [Sensors Overview](sensors-overview.md) - How sensors use these concepts
- [Period Calculation](period-calculation.md) - Deep dive into period detection
diff --git a/docs/user/docs/icon-colors.md b/docs/user/docs/icon-colors.md
index b8dce54..1e88062 100644
--- a/docs/user/docs/icon-colors.md
+++ b/docs/user/docs/icon-colors.md
@@ -484,6 +484,6 @@ styles:
## See Also
-- [Sensors Reference](sensors.md) - Complete list of available sensors
+- [Sensors Overview](sensors-overview.md) - Complete list of available sensors
- [Automation Examples](automation-examples.md) - Use color-coded sensors in automations
- [Configuration Guide](configuration.md) - Adjust thresholds for price levels and ratings
diff --git a/docs/user/docs/intro.md b/docs/user/docs/intro.md
index 243d9f6..ccd761c 100644
--- a/docs/user/docs/intro.md
+++ b/docs/user/docs/intro.md
@@ -15,7 +15,7 @@ This is an independent, community-maintained custom integration. It is **not** a
- **[Installation](installation.md)** - How to install via HACS and configure the integration
- **[Configuration](configuration.md)** - Setting up your Tibber API token and price thresholds
- **[Period Calculation](period-calculation.md)** - How Best/Peak Price periods are calculated and configured
-- **[Sensors](sensors.md)** - Available sensors, their states, and attributes
+- **[Sensors](sensors-overview.md)** - Available sensors, their states, and attributes
- **[Dynamic Icons](dynamic-icons.md)** - State-based automatic icon changes
- **[Dynamic Icon Colors](icon-colors.md)** - Using icon_color attribute for color-coded dashboards
- **[Actions](actions.md)** - Custom actions (service endpoints) and how to use them
diff --git a/docs/user/docs/period-calculation.md b/docs/user/docs/period-calculation.md
index 493d947..ca5ec15 100644
--- a/docs/user/docs/period-calculation.md
+++ b/docs/user/docs/period-calculation.md
@@ -9,15 +9,9 @@ Learn how Best Price and Peak Price periods work, and how to configure them for
- [Quick Start](#quick-start)
- [How It Works](#how-it-works)
- [Configuration Guide](#configuration-guide)
-- [Understanding Relaxation](#understanding-relaxation)
+- [Understanding Relaxation](#understanding-relaxation) → [Full Guide](period-relaxation.md)
- [Common Scenarios](#common-scenarios)
- [Troubleshooting](#troubleshooting)
- - [Fewer Periods Than Configured](#fewer-periods-than-configured)
- - [No Periods Found](#no-periods-found)
- - [Periods Split Into Small Pieces](#periods-split-into-small-pieces)
- - [Understanding Sensor Attributes](#understanding-sensor-attributes)
- - [Midnight Price Classification Changes](#midnight-price-classification-changes)
-- [Advanced Topics](#advanced-topics)
- [Advanced Topics](#advanced-topics)
---
@@ -357,104 +351,14 @@ best_price_max_level: cheap # Only show objectively CHEAP periods
## Understanding Relaxation
-### What Is Relaxation?
+Sometimes strict filters find too few periods. **Relaxation automatically loosens filters** until a minimum number of periods is found — enabled by default.
-Sometimes, strict filters find too few periods (or none). **Relaxation automatically loosens filters** until a minimum number of periods is found.
+**Key benefits:**
+- Each day gets exactly the flexibility it needs (per-day independence)
+- Uses a matrix approach: N flex levels × 2 filter combinations
+- Stops as soon as enough periods are found
-### How to Enable
-
-```yaml
-enable_min_periods_best: true
-min_periods_best: 2 # Try to find at least 2 periods per day
-relaxation_attempts_best: 11 # Flex levels to test (default: 11 steps = 22 filter combinations)
-```
-
-**ℹ️ Good news:** Relaxation is **enabled by default** with sensible settings. Most users don't need to change anything here!
-
-Set the matching `relaxation_attempts_peak` value when tuning Peak Price periods. Both sliders accept 1-12 attempts, and the default of 11 flex levels translates to 22 filter-combination tries (11 flex levels × 2 filter combos) for each of Best and Peak calculations. Lower it for quick feedback, or raise it when either sensor struggles to hit the minimum-period target on volatile days.
-
-### Why Relaxation Is Better Than Manual Tweaking
-
-**Problem with manual settings:**
-- You set flex to 25% → Works great on Monday (volatile prices)
-- Same 25% flex on Tuesday (flat prices) → Finds "best price" periods that aren't really cheap
-- You're stuck with one setting for all days
-
-**Solution with relaxation:**
-- Monday (volatile): Uses flex 15% (original) → Finds 2 perfect periods ✓
-- Tuesday (flat): Escalates to flex 21% → Finds 2 decent periods ✓
-- Wednesday (mixed): Uses flex 18% → Finds 2 good periods ✓
-
-**Each day gets exactly the flexibility it needs!**
-
-### How It Works (Adaptive Matrix)
-
-Relaxation uses a **matrix approach** - trying _N_ flexibility levels (your configured **relaxation attempts**) with 2 filter combinations per level. With the default of 11 attempts, that means 11 flex levels × 2 filter combinations = **22 total filter-combination tries per day**; fewer attempts mean fewer flex increases, while more attempts extend the search further before giving up.
-
-**Important:** The flexibility increment is **fixed at 3% per step** (hard-coded for reliability). This means:
-- Base flex 15% → 18% → 21% → 24% → ... → 48% (with 11 attempts)
-- Base flex 20% → 23% → 26% → 29% → ... → 50% (with 11 attempts)
-
-#### Phase Matrix
-
-For each day, the system tries:
-
-```mermaid
-flowchart TD
- Start["Start: base flex
(e.g. 15%)"] --> A1
-
- subgraph Attempt1["Attempt 1 — flex 15%"]
- A1["Your filters"] -->|not enough| A2["Level = any"]
- end
-
- A2 -->|not enough| B1
-
- subgraph Attempt2["Attempt 2 — flex 18%"]
- B1["Your filters"] -->|not enough| B2["Level = any"]
- end
-
- B2 -->|not enough| C1
-
- subgraph Attempt3["Attempt 3 — flex 21%"]
- C1["Your filters"] --> C2["Level = any"]
- end
-
- C1 -->|"✅ enough"| Done
- A1 -->|"✅ enough"| Done
- A2 -->|"✅ enough"| Done
- B1 -->|"✅ enough"| Done
- B2 -->|"✅ enough"| Done
- C2 -->|"✅ / not enough → next …"| Done
-
- Done["✅ Done
stops at first success"]
-
- style Start fill:#e6f7ff,stroke:#00b9e7,stroke-width:2px
- style Done fill:#e6fff5,stroke:#00c853,stroke-width:2px
- style Attempt1 fill:#f0f9ff,stroke:#00b9e7
- style Attempt2 fill:#fff9e6,stroke:#ffb800
- style Attempt3 fill:#fff0f0,stroke:#ff8a80
-```
-
-Each attempt adds +3% flexibility and tries two filter combinations. The system **stops as soon as enough periods are found** — it doesn't keep trying the full matrix.
-
-### Choosing the Number of Attempts
-
-- **Default (11 attempts)** balances speed and completeness for most grids (22 combinations per day for both Best and Peak)
-- **Lower (4-8 attempts)** if you only want mild relaxation and keep processing time minimal (reaches ~27-39% flex)
-- **Higher (12 attempts)** for extremely volatile days when you must reach near the 50% maximum (24 combinations)
-- Remember: each additional attempt adds two more filter combinations because every new flex level still runs both filter overrides (original + level=any)
-
-#### Per-Day Independence
-
-**Critical:** Each day relaxes **independently**:
-
-```
-Day 1: Finds 2 periods with flex 15% (original) → No relaxation needed
-Day 2: Needs flex 21% + level=any → Uses relaxed settings
-Day 3: Finds 2 periods with flex 15% (original) → No relaxation needed
-```
-
-**Why?** Price patterns vary daily. Some days have clear cheap/expensive windows (strict filters work), others don't (relaxation needed).
+**→ [Full Relaxation Guide](period-relaxation.md)** — How it works, the adaptive matrix, choosing attempts, and diagnostics.
---
diff --git a/docs/user/docs/period-relaxation.md b/docs/user/docs/period-relaxation.md
new file mode 100644
index 0000000..da0ac9c
--- /dev/null
+++ b/docs/user/docs/period-relaxation.md
@@ -0,0 +1,129 @@
+# Understanding Relaxation
+
+> **Entity ID tip:** `` is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. **Can't find a sensor?** Use the **[Entity Reference (All Languages)](sensor-reference.md)** to search by name in your language.
+
+Relaxation is the automatic filter-loosening mechanism that ensures your [Best/Peak Price periods](period-calculation.md) always find results — even on days with unusual price patterns.
+
+---
+
+## What Is Relaxation?
+
+Sometimes, strict filters find too few periods (or none). **Relaxation automatically loosens filters** until a minimum number of periods is found.
+
+## How to Enable
+
+```yaml
+enable_min_periods_best: true
+min_periods_best: 2 # Try to find at least 2 periods per day
+relaxation_attempts_best: 11 # Flex levels to test (default: 11 steps = 22 filter combinations)
+```
+
+**Good news:** Relaxation is **enabled by default** with sensible settings. Most users don't need to change anything here!
+
+Set the matching `relaxation_attempts_peak` value when tuning Peak Price periods. Both sliders accept 1-12 attempts, and the default of 11 flex levels translates to 22 filter-combination tries (11 flex levels × 2 filter combos) for each of Best and Peak calculations. Lower it for quick feedback, or raise it when either sensor struggles to hit the minimum-period target on volatile days.
+
+## Why Relaxation Is Better Than Manual Tweaking
+
+**Problem with manual settings:**
+- You set flex to 25% → Works great on Monday (volatile prices)
+- Same 25% flex on Tuesday (flat prices) → Finds "best price" periods that aren't really cheap
+- You're stuck with one setting for all days
+
+**Solution with relaxation:**
+- Monday (volatile): Uses flex 15% (original) → Finds 2 perfect periods ✓
+- Tuesday (flat): Escalates to flex 21% → Finds 2 decent periods ✓
+- Wednesday (mixed): Uses flex 18% → Finds 2 good periods ✓
+
+**Each day gets exactly the flexibility it needs!**
+
+## How It Works (Adaptive Matrix)
+
+Relaxation uses a **matrix approach** - trying _N_ flexibility levels (your configured **relaxation attempts**) with 2 filter combinations per level. With the default of 11 attempts, that means 11 flex levels × 2 filter combinations = **22 total filter-combination tries per day**; fewer attempts mean fewer flex increases, while more attempts extend the search further before giving up.
+
+**Important:** The flexibility increment is **fixed at 3% per step** (hard-coded for reliability). This means:
+- Base flex 15% → 18% → 21% → 24% → ... → 48% (with 11 attempts)
+- Base flex 20% → 23% → 26% → 29% → ... → 50% (with 11 attempts)
+
+### Phase Matrix
+
+For each day, the system tries:
+
+```mermaid
+flowchart TD
+ Start["Start: base flex
(e.g. 15%)"] --> A1
+
+ subgraph Attempt1["Attempt 1 — flex 15%"]
+ A1["Your filters"] -->|not enough| A2["Level = any"]
+ end
+
+ A2 -->|not enough| B1
+
+ subgraph Attempt2["Attempt 2 — flex 18%"]
+ B1["Your filters"] -->|not enough| B2["Level = any"]
+ end
+
+ B2 -->|not enough| C1
+
+ subgraph Attempt3["Attempt 3 — flex 21%"]
+ C1["Your filters"] --> C2["Level = any"]
+ end
+
+ C1 -->|"✅ enough"| Done
+ A1 -->|"✅ enough"| Done
+ A2 -->|"✅ enough"| Done
+ B1 -->|"✅ enough"| Done
+ B2 -->|"✅ enough"| Done
+ C2 -->|"✅ / not enough → next …"| Done
+
+ Done["✅ Done
stops at first success"]
+
+ style Start fill:#e6f7ff,stroke:#00b9e7,stroke-width:2px
+ style Done fill:#e6fff5,stroke:#00c853,stroke-width:2px
+ style Attempt1 fill:#f0f9ff,stroke:#00b9e7
+ style Attempt2 fill:#fff9e6,stroke:#ffb800
+ style Attempt3 fill:#fff0f0,stroke:#ff8a80
+```
+
+Each attempt adds +3% flexibility and tries two filter combinations. The system **stops as soon as enough periods are found** — it doesn't keep trying the full matrix.
+
+## Choosing the Number of Attempts
+
+- **Default (11 attempts)** balances speed and completeness for most grids (22 combinations per day for both Best and Peak)
+- **Lower (4-8 attempts)** if you only want mild relaxation and keep processing time minimal (reaches ~27-39% flex)
+- **Higher (12 attempts)** for extremely volatile days when you must reach near the 50% maximum (24 combinations)
+- Remember: each additional attempt adds two more filter combinations because every new flex level still runs both filter overrides (original + level=any)
+
+## Per-Day Independence
+
+**Critical:** Each day relaxes **independently**:
+
+```
+Day 1: Finds 2 periods with flex 15% (original) → No relaxation needed
+Day 2: Needs flex 21% + level=any → Uses relaxed settings
+Day 3: Finds 2 periods with flex 15% (original) → No relaxation needed
+```
+
+**Why?** Price patterns vary daily. Some days have clear cheap/expensive windows (strict filters work), others don't (relaxation needed).
+
+## Diagnosing Relaxation Behavior
+
+Check the period sensor attributes to understand what happened:
+
+```yaml
+# Entity: binary_sensor._best_price_period
+
+relaxation_active: true # This day needed relaxation
+relaxation_level: "price_diff_18.0%+level_any" # Found at 18% flex, level filter removed
+min_periods_configured: 2 # Your target
+periods_found_total: 3 # What was actually found
+```
+
+| Attribute | Meaning |
+|-----------|---------|
+| `relaxation_active: false` | Original filters were sufficient |
+| `relaxation_active: true` | Filters were loosened to find enough periods |
+| `relaxation_level` | Shows exactly which flex% and filter combo succeeded |
+| `relaxation_incomplete: true` | All attempts exhausted, still short of target |
+| `flat_days_detected: 1` | Uniform prices → target reduced to 1 (expected) |
+
+**See also:** [Period Calculation — Troubleshooting](period-calculation.md#troubleshooting) for more diagnostic guidance.
diff --git a/docs/user/docs/sensor-reference.md b/docs/user/docs/sensor-reference.md
index b4719d0..e345aeb 100644
--- a/docs/user/docs/sensor-reference.md
+++ b/docs/user/docs/sensor-reference.md
@@ -29,7 +29,7 @@ You can also use your browser's built-in search (**Ctrl+F** / **Cmd+F**) to sear
Sensors marked ❌ must be enabled manually via
**Settings → Devices & Services → Entities** → find the entity → toggle **Enabled**.
-**Detailed documentation:** See the **[Sensors Guide](sensors.md)** for detailed
+**Detailed documentation:** See the **[Sensors Overview](sensors-overview.md)** for detailed
explanations of each sensor's purpose, attributes, and automation examples.
---
@@ -51,32 +51,32 @@ explanations of each sensor's purpose, attributes, and automation examples.
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `current_hour_average_price` | ⌀ Hourly Price Current | ⌀ Stunden-Preis aktuell | ⌀ Timepris nåværende | ⌀ Uurprijs Huidig | ⌀ Timpris aktuell | ✅ |
-| `next_hour_average_price` | ⌀ Hourly Price Next | ⌀ Stunden-Preis nächste Stunde | ⌀ Timepris neste | ⌀ Uurprijs Volgend | ⌀ Timpris nästa | ✅ |
+| `current_hour_average_price` | ⌀ Hourly Price Current | ⌀ Stunden-Preis aktuell | ⌀ Timepris nåværende | ⌀ Uurprijs Huidig | ⌀ Timpris aktuell | ✅ |
+| `next_hour_average_price` | ⌀ Hourly Price Next | ⌀ Stunden-Preis nächste Stunde | ⌀ Timepris neste | ⌀ Uurprijs Volgend | ⌀ Timpris nästa | ✅ |
### Daily Statistics
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `lowest_price_today` | Today's Lowest Price | Mindestpreis heute | Dagens laveste pris | Laagste Prijs Vandaag | Dagens lägsta pris | ✅ |
-| `highest_price_today` | Today's Highest Price | Höchstpreis heute | Dagens høyeste pris | Hoogste Prijs Vandaag | Dagens högsta pris | ✅ |
-| `average_price_today` | ⌀ Price Today | ⌀ Preis heute | ⌀ Pris i dag | ⌀ Prijs Vandaag | ⌀ Pris idag | ✅ |
-| `lowest_price_tomorrow` | Tomorrow's Lowest Price | Mindestpreis morgen | Morgendagens laveste pris | Laagste Prijs Morgen | Morgondagens lägsta pris | ✅ |
-| `highest_price_tomorrow` | Tomorrow's Highest Price | Höchstpreis morgen | Morgendagens høyeste pris | Hoogste Prijs Morgen | Morgondagens högsta pris | ✅ |
-| `average_price_tomorrow` | ⌀ Price Tomorrow | ⌀ Preis morgen | ⌀ Pris i morgen | ⌀ Prijs Morgen | ⌀ Pris imorgon | ✅ |
+| `lowest_price_today` | Today's Lowest Price | Mindestpreis heute | Dagens laveste pris | Laagste Prijs Vandaag | Dagens lägsta pris | ✅ |
+| `highest_price_today` | Today's Highest Price | Höchstpreis heute | Dagens høyeste pris | Hoogste Prijs Vandaag | Dagens högsta pris | ✅ |
+| `average_price_today` | ⌀ Price Today | ⌀ Preis heute | ⌀ Pris i dag | ⌀ Prijs Vandaag | ⌀ Pris idag | ✅ |
+| `lowest_price_tomorrow` | Tomorrow's Lowest Price | Mindestpreis morgen | Morgendagens laveste pris | Laagste Prijs Morgen | Morgondagens lägsta pris | ✅ |
+| `highest_price_tomorrow` | Tomorrow's Highest Price | Höchstpreis morgen | Morgendagens høyeste pris | Hoogste Prijs Morgen | Morgondagens högsta pris | ✅ |
+| `average_price_tomorrow` | ⌀ Price Tomorrow | ⌀ Preis morgen | ⌀ Pris i morgen | ⌀ Prijs Morgen | ⌀ Pris imorgon | ✅ |
### 24h Window Sensors
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `trailing_price_average` | ⌀ Price Trailing 24h | ⌀ Preis nachlaufend 24h | ⌀ Pris glidende 24t | ⌀ Prijs Afgelopen 24u | ⌀ Pris glidande 24h | ❌ |
-| `leading_price_average` | ⌀ Price Leading 24h | ⌀ Preis vorlaufend 24h | ⌀ Pris fremtidig 24t | ⌀ Prijs Komende 24u | ⌀ Pris framåt 24h | ❌ |
-| `trailing_price_min` | Trailing 24h Minimum Price | 24h-Mindestpreis nachlaufend | Glidende 24t minimumspris | Afgelopen 24u Minimumprijs | Glidande 24h minimipris | ❌ |
-| `trailing_price_max` | Trailing 24h Maximum Price | 24h-Höchstpreis nachlaufend | Glidende 24t maksimumspris | Afgelopen 24u Maximumprijs | Glidande 24h maximipris | ❌ |
-| `leading_price_min` | Leading 24h Minimum Price | 24h-Mindestpreis vorlaufend | Fremtidig 24t minimumspris | Komende 24u Minimumprijs | Framåt 24h minimipris | ❌ |
-| `leading_price_max` | Leading 24h Maximum Price | 24h-Höchstpreis vorlaufend | Fremtidig 24t maksimumspris | Komende 24u Maximumprijs | Framåt 24h maximipris | ❌ |
+| `trailing_price_average` | ⌀ Price Trailing 24h | ⌀ Preis nachlaufend 24h | ⌀ Pris glidende 24t | ⌀ Prijs Afgelopen 24u | ⌀ Pris glidande 24h | ❌ |
+| `leading_price_average` | ⌀ Price Leading 24h | ⌀ Preis vorlaufend 24h | ⌀ Pris fremtidig 24t | ⌀ Prijs Komende 24u | ⌀ Pris framåt 24h | ❌ |
+| `trailing_price_min` | Trailing 24h Minimum Price | 24h-Mindestpreis nachlaufend | Glidende 24t minimumspris | Afgelopen 24u Minimumprijs | Glidande 24h minimipris | ❌ |
+| `trailing_price_max` | Trailing 24h Maximum Price | 24h-Höchstpreis nachlaufend | Glidende 24t maksimumspris | Afgelopen 24u Maximumprijs | Glidande 24h maximipris | ❌ |
+| `leading_price_min` | Leading 24h Minimum Price | 24h-Mindestpreis vorlaufend | Fremtidig 24t minimumspris | Komende 24u Minimumprijs | Framåt 24h minimipris | ❌ |
+| `leading_price_max` | Leading 24h Maximum Price | 24h-Höchstpreis vorlaufend | Fremtidig 24t maksimumspris | Komende 24u Maximumprijs | Framåt 24h maximipris | ❌ |
### Future Price Averages
@@ -97,28 +97,28 @@ explanations of each sensor's purpose, attributes, and automation examples.
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `current_interval_price_level` | Current Price Level | Aktuelles Preisniveau | Nåværende prisnivå | Huidig Prijsniveau | Aktuell prisnivå | ✅ |
-| `next_interval_price_level` | Next Price Level | Nächstes Preisniveau | Neste prisnivå | Volgend Prijsniveau | Nästa prisnivå | ✅ |
-| `previous_interval_price_level` | Previous Price Level | Vorheriges Preisniveau | Forrige prisnivå | Vorig Prijsniveau | Föregående prisnivå | ❌ |
-| `current_hour_price_level` | Current Hour Price Level | Aktuelles Stunden-Preisniveau | Nåværende timepris nivå | Huidig Uur Prijsniveau | Aktuell timprisnivå | ✅ |
-| `next_hour_price_level` | Next Hour Price Level | Nächstes Stunden-Preisniveau | Neste timepris nivå | Volgend Uur Prijsniveau | Nästa timprisnivå | ✅ |
-| `yesterday_price_level` | Yesterday's Price Level | Preisniveau gestern | Prisnivå i går | Gisteren Prijsniveau | Gårdagens prisnivå | ❌ |
-| `today_price_level` | Today's Price Level | Preisniveau heute | Prisnivå i dag | Vandaag Prijsniveau | Dagens prisnivå | ✅ |
-| `tomorrow_price_level` | Tomorrow's Price Level | Preisniveau morgen | Prisnivå i morgen | Morgen Prijsniveau | Morgondagens prisnivå | ✅ |
+| `current_interval_price_level` | Current Price Level | Aktuelles Preisniveau | Nåværende prisnivå | Huidig Prijsniveau | Aktuell prisnivå | ✅ |
+| `next_interval_price_level` | Next Price Level | Nächstes Preisniveau | Neste prisnivå | Volgend Prijsniveau | Nästa prisnivå | ✅ |
+| `previous_interval_price_level` | Previous Price Level | Vorheriges Preisniveau | Forrige prisnivå | Vorig Prijsniveau | Föregående prisnivå | ❌ |
+| `current_hour_price_level` | Current Hour Price Level | Aktuelles Stunden-Preisniveau | Nåværende timepris nivå | Huidig Uur Prijsniveau | Aktuell timprisnivå | ✅ |
+| `next_hour_price_level` | Next Hour Price Level | Nächstes Stunden-Preisniveau | Neste timepris nivå | Volgend Uur Prijsniveau | Nästa timprisnivå | ✅ |
+| `yesterday_price_level` | Yesterday's Price Level | Preisniveau gestern | Prisnivå i går | Gisteren Prijsniveau | Gårdagens prisnivå | ❌ |
+| `today_price_level` | Today's Price Level | Preisniveau heute | Prisnivå i dag | Vandaag Prijsniveau | Dagens prisnivå | ✅ |
+| `tomorrow_price_level` | Tomorrow's Price Level | Preisniveau morgen | Prisnivå i morgen | Morgen Prijsniveau | Morgondagens prisnivå | ✅ |
### Price Rating Sensors
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `current_interval_price_rating` | Current Price Rating | Aktuelle Preisbewertung | Nåværende prisvurdering | Huidige Prijsbeoordeling | Aktuellt prisbetyg | ❌ |
-| `next_interval_price_rating` | Next Price Rating | Nächste Preisbewertung | Neste prisvurdering | Volgende Prijsbeoordeling | Nästa prisbetyg | ❌ |
-| `previous_interval_price_rating` | Previous Price Rating | Vorherige Preisbewertung | Forrige prisvurdering | Vorige Prijsbeoordeling | Föregående prisbetyg | ❌ |
-| `current_hour_price_rating` | Current Hour Price Rating | Aktuelle Stunden-Preisbewertung | Nåværende timeprisvurdering | Huidig Uur Prijsbeoordeling | Aktuellt timprisbetyg | ❌ |
-| `next_hour_price_rating` | Next Hour Price Rating | Nächste Stunden-Preisbewertung | Neste timeprisvurdering | Volgend Uur Prijsbeoordeling | Nästa timprisbetyg | ❌ |
-| `yesterday_price_rating` | Yesterday's Price Rating | Preisbewertung gestern | Prisvurdering i går | Gisteren Prijsbeoordeling | Gårdagens prisbetyg | ❌ |
-| `today_price_rating` | Today's Price Rating | Preisbewertung heute | Prisvurdering i dag | Vandaag Prijsbeoordeling | Dagens prisbetyg | ❌ |
-| `tomorrow_price_rating` | Tomorrow's Price Rating | Preisbewertung morgen | Prisvurdering i morgen | Morgen Prijsbeoordeling | Morgondagens prisbetyg | ❌ |
+| `current_interval_price_rating` | Current Price Rating | Aktuelle Preisbewertung | Nåværende prisvurdering | Huidige Prijsbeoordeling | Aktuellt prisbetyg | ❌ |
+| `next_interval_price_rating` | Next Price Rating | Nächste Preisbewertung | Neste prisvurdering | Volgende Prijsbeoordeling | Nästa prisbetyg | ❌ |
+| `previous_interval_price_rating` | Previous Price Rating | Vorherige Preisbewertung | Forrige prisvurdering | Vorige Prijsbeoordeling | Föregående prisbetyg | ❌ |
+| `current_hour_price_rating` | Current Hour Price Rating | Aktuelle Stunden-Preisbewertung | Nåværende timeprisvurdering | Huidig Uur Prijsbeoordeling | Aktuellt timprisbetyg | ❌ |
+| `next_hour_price_rating` | Next Hour Price Rating | Nächste Stunden-Preisbewertung | Neste timeprisvurdering | Volgend Uur Prijsbeoordeling | Nästa timprisbetyg | ❌ |
+| `yesterday_price_rating` | Yesterday's Price Rating | Preisbewertung gestern | Prisvurdering i går | Gisteren Prijsbeoordeling | Gårdagens prisbetyg | ❌ |
+| `today_price_rating` | Today's Price Rating | Preisbewertung heute | Prisvurdering i dag | Vandaag Prijsbeoordeling | Dagens prisbetyg | ❌ |
+| `tomorrow_price_rating` | Tomorrow's Price Rating | Preisbewertung morgen | Prisvurdering i morgen | Morgen Prijsbeoordeling | Morgondagens prisbetyg | ❌ |
| `daily_rating` | Daily Price Rating | Tägliche Preisbewertung | Daglig prisvurdering | Dagelijkse Prijsbeoordeling | Dagligt prisbetyg | ✅ |
| `monthly_rating` | Monthly Price Rating | Monatliche Preisbewertung | Månedlig prisvurdering | Maandelijkse Prijsbeoordeling | Månatligt prisbetyg | ✅ |
@@ -127,8 +127,8 @@ explanations of each sensor's purpose, attributes, and automation examples.
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `current_price_trend` | Current Price Trend | Aktueller Preistrend | Nåværende pristrend | Huidige Prijstrend | Aktuell pristrend | ✅ |
-| `next_price_trend_change` | Next Price Trend Change | Nächste Trendänderung | Neste trendendring | Volgende Prijstrend Wijziging | Nästa pristrendändring | ✅ |
+| `current_price_trend` | Current Price Trend | Aktueller Preistrend | Nåværende pristrend | Huidige Prijstrend | Aktuell pristrend | ✅ |
+| `next_price_trend_change` | Next Price Trend Change | Nächste Trendänderung | Neste trendendring | Volgende Prijstrend Wijziging | Nästa pristrendändring | ✅ |
| `next_price_trend_change_in` | Next Price Trend Change In | Nächste Trendänderung in | Neste trendendring om | Volgende Prijstrend Wijziging over | Nästa pristrendändring om | ✅ |
| `price_outlook_1h` | Price Outlook (1h) | Preisausblick (1h) | Prisutblikk (1t) | Prijsvooruitzicht (1u) | Prisöversikt (1h) | ✅ |
| `price_outlook_2h` | Price Outlook (2h) | Preisausblick (2h) | Prisutblikk (2t) | Prijsvooruitzicht (2u) | Prisöversikt (2h) | ✅ |
@@ -151,34 +151,34 @@ explanations of each sensor's purpose, attributes, and automation examples.
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `today_volatility` | Today's Price Volatility | Volatilität heute | Volatilitet i dag | Vandaag Prijsvolatiliteit | Dagens prisvolatilitet | ✅ |
-| `tomorrow_volatility` | Tomorrow's Price Volatility | Volatilität morgen | Volatilitet i morgen | Morgen Prijsvolatiliteit | Morgondagens prisvolatilitet | ❌ |
+| `today_volatility` | Today's Price Volatility | Volatilität heute | Volatilitet i dag | Vandaag Prijsvolatiliteit | Dagens prisvolatilitet | ✅ |
+| `tomorrow_volatility` | Tomorrow's Price Volatility | Volatilität morgen | Volatilitet i morgen | Morgen Prijsvolatiliteit | Morgondagens prisvolatilitet | ❌ |
| `next_24h_volatility` | Next 24h Price Volatility | Volatilität der nächsten 24h | Volatilitet neste 24t | Komende 24u Prijsvolatiliteit | Nästa 24h prisvolatilitet | ❌ |
-| `today_tomorrow_volatility` | Today+Tomorrow Price Volatility | Volatilität heute+morgen | Volatilitet i dag+i morgen | Vandaag+Morgen Prijsvolatiliteit | Idag+Imorgon prisvolatilitet | ❌ |
+| `today_tomorrow_volatility` | Today+Tomorrow Price Volatility | Volatilität heute+morgen | Volatilitet i dag+i morgen | Vandaag+Morgen Prijsvolatiliteit | Idag+Imorgon prisvolatilitet | ❌ |
### Best Price Timing
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `best_price_end_time` | Best Price End | Bestpreis endet | Beste pris slutter | Beste Prijs Einde | Bästa pris slutar | ✅ |
-| `best_price_period_duration` | Best Price Duration | Bestpreis Dauer | Beste pris varighet | Beste Prijs Duur | Bästa pris varaktighet | ❌ |
-| `best_price_remaining_minutes` | Best Price Remaining Time | Bestpreis verbleibend | Beste pris gjenværende tid | Beste Prijs Resterende Tijd | Bästa pris återstående tid | ✅ |
-| `best_price_progress` | Best Price Progress | Bestpreis Fortschritt | Beste pris fremgang | Beste Prijs Voortgang | Bästa pris framsteg | ✅ |
-| `best_price_next_start_time` | Best Price Start | Bestpreis startet | Beste pris starter | Beste Prijs Start | Bästa pris startar | ✅ |
-| `best_price_next_in_minutes` | Best Price Starts In | Bestpreis startet in | Beste pris starter om | Beste Prijs Start Over | Bästa pris startar om | ✅ |
+| `best_price_end_time` | Best Price End | Bestpreis endet | Beste pris slutter | Beste Prijs Einde | Bästa pris slutar | ✅ |
+| `best_price_period_duration` | Best Price Duration | Bestpreis Dauer | Beste pris varighet | Beste Prijs Duur | Bästa pris varaktighet | ❌ |
+| `best_price_remaining_minutes` | Best Price Remaining Time | Bestpreis verbleibend | Beste pris gjenværende tid | Beste Prijs Resterende Tijd | Bästa pris återstående tid | ✅ |
+| `best_price_progress` | Best Price Progress | Bestpreis Fortschritt | Beste pris fremgang | Beste Prijs Voortgang | Bästa pris framsteg | ✅ |
+| `best_price_next_start_time` | Best Price Start | Bestpreis startet | Beste pris starter | Beste Prijs Start | Bästa pris startar | ✅ |
+| `best_price_next_in_minutes` | Best Price Starts In | Bestpreis startet in | Beste pris starter om | Beste Prijs Start Over | Bästa pris startar om | ✅ |
### Peak Price Timing
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `peak_price_end_time` | Peak Price End | Spitzenpreis endet | Topppris slutter | Piekprijs Einde | Topppris slutar | ✅ |
-| `peak_price_period_duration` | Peak Price Duration | Spitzenpreis Dauer | Topppris varighet | Piekprijs Duur | Topppris varaktighet | ❌ |
-| `peak_price_remaining_minutes` | Peak Price Remaining Time | Spitzenpreis verbleibend | Topppris gjenværende tid | Piekprijs Resterende Tijd | Topppris återstående tid | ✅ |
-| `peak_price_progress` | Peak Price Progress | Spitzenpreis Fortschritt | Topppris fremgang | Piekprijs Voortgang | Topppris framsteg | ✅ |
-| `peak_price_next_start_time` | Peak Price Start | Spitzenpreis startet | Topppris starter | Piekprijs Start | Topppris startar | ✅ |
-| `peak_price_next_in_minutes` | Peak Price Starts In | Spitzenpreis startet in | Topppris starter om | Piekprijs Start Over | Topppris startar om | ✅ |
+| `peak_price_end_time` | Peak Price End | Spitzenpreis endet | Topppris slutter | Piekprijs Einde | Topppris slutar | ✅ |
+| `peak_price_period_duration` | Peak Price Duration | Spitzenpreis Dauer | Topppris varighet | Piekprijs Duur | Topppris varaktighet | ❌ |
+| `peak_price_remaining_minutes` | Peak Price Remaining Time | Spitzenpreis verbleibend | Topppris gjenværende tid | Piekprijs Resterende Tijd | Topppris återstående tid | ✅ |
+| `peak_price_progress` | Peak Price Progress | Spitzenpreis Fortschritt | Topppris fremgang | Piekprijs Voortgang | Topppris framsteg | ✅ |
+| `peak_price_next_start_time` | Peak Price Start | Spitzenpreis startet | Topppris starter | Piekprijs Start | Topppris startar | ✅ |
+| `peak_price_next_in_minutes` | Peak Price Starts In | Spitzenpreis startet in | Topppris starter om | Piekprijs Start Over | Topppris startar om | ✅ |
### Home & Metering Metadata
@@ -215,8 +215,8 @@ explanations of each sensor's purpose, attributes, and automation examples.
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `best_price_period` | Best Price Period | Bestpreis-Zeitraum | Lavpris-periode | Beste Prijs Periode | Bästa Prisperiod | ✅ |
-| `peak_price_period` | Peak Price Period | Spitzenpreis-Zeitraum | Toppris-periode | Piekprijs Periode | Topprisperiod | ✅ |
+| `best_price_period` | Best Price Period | Bestpreis-Zeitraum | Lavpris-periode | Beste Prijs Periode | Bästa Prisperiod | ✅ |
+| `peak_price_period` | Peak Price Period | Spitzenpreis-Zeitraum | Toppris-periode | Piekprijs Periode | Topprisperiod | ✅ |
| `connection` | Tibber API Connection | Tibber-API-Verbindung | Tibber API-tilkobling | Tibber API Verbinding | Tibber API-anslutning | ✅ |
| `tomorrow_data_available` | Tomorrow's Data Available | Morgige Daten verfügbar | Morgendagens data tilgjengelig | Morgen Gegevens Beschikbaar | Morgondagens data tillgänglig | ✅ |
| `has_ventilation_system` | Has Ventilation System | Hat Lüftungsanlage | Har ventilasjonsanlegg | Heeft Ventilatiesysteem | Har ventilationssystem | ❌ |
@@ -230,11 +230,11 @@ explanations of each sensor's purpose, attributes, and automation examples.
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `best_price_flex_override` | Best Price: Flexibility | Bestpreis: Flexibilität | Beste pris: Fleksibilitet | Beste prijs: Flexibiliteit | Bästa pris: Flexibilitet | ❌ |
-| `best_price_min_distance_override` | Best Price: Minimum Distance | Bestpreis: Mindestabstand | Beste pris: Minimumsavstand | Beste prijs: Minimale afstand | Bästa pris: Minimiavstånd | ❌ |
-| `best_price_min_period_length_override` | Best Price: Minimum Period Length | Bestpreis: Mindestperiodenlänge | Beste pris: Minimum periodelengde | Beste prijs: Minimale periodelengte | Bästa pris: Minsta periodlängd | ❌ |
-| `best_price_min_periods_override` | Best Price: Minimum Periods | Bestpreis: Mindestperioden | Beste pris: Minimum perioder | Beste prijs: Minimum periodes | Bästa pris: Minsta antal perioder | ❌ |
-| `best_price_relaxation_attempts_override` | Best Price: Relaxation Attempts | Bestpreis: Lockerungsversuche | Beste pris: Lemping forsøk | Beste prijs: Versoepeling pogingen | Bästa pris: Lättnadsförsök | ❌ |
+| `best_price_flex_override` | Best Price: Flexibility | Bestpreis: Flexibilität | Beste pris: Fleksibilitet | Beste prijs: Flexibiliteit | Bästa pris: Flexibilitet | ❌ |
+| `best_price_min_distance_override` | Best Price: Minimum Distance | Bestpreis: Mindestabstand | Beste pris: Minimumsavstand | Beste prijs: Minimale afstand | Bästa pris: Minimiavstånd | ❌ |
+| `best_price_min_period_length_override` | Best Price: Minimum Period Length | Bestpreis: Mindestperiodenlänge | Beste pris: Minimum periodelengde | Beste prijs: Minimale periodelengte | Bästa pris: Minsta periodlängd | ❌ |
+| `best_price_min_periods_override` | Best Price: Minimum Periods | Bestpreis: Mindestperioden | Beste pris: Minimum perioder | Beste prijs: Minimum periodes | Bästa pris: Minsta antal perioder | ❌ |
+| `best_price_relaxation_attempts_override` | Best Price: Relaxation Attempts | Bestpreis: Lockerungsversuche | Beste pris: Lemping forsøk | Beste prijs: Versoepeling pogingen | Bästa pris: Lättnadsförsök | ❌ |
| `best_price_gap_count_override` | Best Price: Gap Tolerance | Bestpreis: Lückentoleranz | Beste pris: Gaptoleranse | Beste prijs: Gap tolerantie | Bästa pris: Glaptolerans | ❌ |
### Peak Price Configuration
@@ -242,11 +242,11 @@ explanations of each sensor's purpose, attributes, and automation examples.
| Entity ID suffix | 🇬🇧 English | 🇩🇪 Deutsch | 🇳🇴 Norsk | 🇳🇱 Nederlands | 🇸🇪 Svenska | Default |
|---|---|---|---|---|---|---|
-| `peak_price_flex_override` | Peak Price: Flexibility | Spitzenpreis: Flexibilität | Topppris: Fleksibilitet | Piekprijs: Flexibiliteit | Topppris: Flexibilitet | ❌ |
-| `peak_price_min_distance_override` | Peak Price: Minimum Distance | Spitzenpreis: Mindestabstand | Topppris: Minimumsavstand | Piekprijs: Minimale afstand | Topppris: Minimiavstånd | ❌ |
-| `peak_price_min_period_length_override` | Peak Price: Minimum Period Length | Spitzenpreis: Mindestperiodenlänge | Topppris: Minimum periodelengde | Piekprijs: Minimale periodelengte | Topppris: Minsta periodlängd | ❌ |
-| `peak_price_min_periods_override` | Peak Price: Minimum Periods | Spitzenpreis: Mindestperioden | Topppris: Minimum perioder | Piekprijs: Minimum periodes | Topppris: Minsta antal perioder | ❌ |
-| `peak_price_relaxation_attempts_override` | Peak Price: Relaxation Attempts | Spitzenpreis: Lockerungsversuche | Topppris: Lemping forsøk | Piekprijs: Versoepeling pogingen | Topppris: Lättnadsförsök | ❌ |
+| `peak_price_flex_override` | Peak Price: Flexibility | Spitzenpreis: Flexibilität | Topppris: Fleksibilitet | Piekprijs: Flexibiliteit | Topppris: Flexibilitet | ❌ |
+| `peak_price_min_distance_override` | Peak Price: Minimum Distance | Spitzenpreis: Mindestabstand | Topppris: Minimumsavstand | Piekprijs: Minimale afstand | Topppris: Minimiavstånd | ❌ |
+| `peak_price_min_period_length_override` | Peak Price: Minimum Period Length | Spitzenpreis: Mindestperiodenlänge | Topppris: Minimum periodelengde | Piekprijs: Minimale periodelengte | Topppris: Minsta periodlängd | ❌ |
+| `peak_price_min_periods_override` | Peak Price: Minimum Periods | Spitzenpreis: Mindestperioden | Topppris: Minimum perioder | Piekprijs: Minimum periodes | Topppris: Minsta antal perioder | ❌ |
+| `peak_price_relaxation_attempts_override` | Peak Price: Relaxation Attempts | Spitzenpreis: Lockerungsversuche | Topppris: Lemping forsøk | Piekprijs: Versoepeling pogingen | Topppris: Lättnadsförsök | ❌ |
| `peak_price_gap_count_override` | Peak Price: Gap Tolerance | Spitzenpreis: Lückentoleranz | Topppris: Gaptoleranse | Piekprijs: Gap tolerantie | Topppris: Glaptolerans | ❌ |
## Switch Entities (Configuration Overrides)
diff --git a/docs/user/docs/sensors-average.md b/docs/user/docs/sensors-average.md
new file mode 100644
index 0000000..730808b
--- /dev/null
+++ b/docs/user/docs/sensors-average.md
@@ -0,0 +1,194 @@
+# Average & Statistics Sensors
+
+> **Entity ID tip:** `` is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. **Can't find a sensor?** Use the **[Entity Reference (All Languages)](sensor-reference.md)** to search by name in your language.
+
+The integration provides several sensors that calculate average electricity prices over different time windows. These sensors show a **typical** price value that represents the overall price level, helping you make informed decisions about when to use electricity.
+
+## Available Average Sensors
+
+| Sensor | Description | Time Window |
+|--------|-------------|-------------|
+| Average Price Today | Typical price for current calendar day | 00:00 - 23:59 today |
+| Average Price Tomorrow | Typical price for next calendar day | 00:00 - 23:59 tomorrow |
+| Trailing Price Average | Typical price for last 24 hours | Rolling 24h backward |
+| Leading Price Average | Typical price for next 24 hours | Rolling 24h forward |
+| Current Hour Average | Smoothed price around current time | 5 intervals (~75 min) |
+| Next Hour Average | Smoothed price around next hour | 5 intervals (~75 min) |
+| **Next N Hours Average** (`next_avg_1h`–`next_avg_12h`) | Future price forecast | 1h, 2h, 3h, 4h, 5h, 6h, 8h, 12h |
+
+## Configurable Display: Median vs Mean
+
+All average sensors support **two different calculation methods** for the state value:
+
+- **Median** (default): The "middle value" when all prices are sorted. Resistant to extreme price spikes, shows the **typical** price level you experienced.
+- **Arithmetic Mean**: The mathematical average including all prices. Better for **cost calculations** but affected by extreme spikes.
+
+**Why two values matter:**
+
+```yaml
+# Example price data for one day:
+# Prices: 10, 12, 13, 15, 80 ct/kWh (one extreme spike)
+#
+# Median = 13 ct/kWh ← "Typical" price level (middle value)
+# Mean = 26 ct/kWh ← Mathematical average (affected by spike)
+```
+
+The median shows you what price level was **typical** during that period, while the mean shows the actual **average cost** if you consumed evenly throughout the period.
+
+## Configuring the Display
+
+You can choose which value is displayed in the sensor state:
+
+1. Go to **Settings → Devices & Services → Tibber Prices**
+2. Click **Configure** on your home
+3. Navigate to **Step 6: Average Sensor Display Settings**
+4. Choose between:
+ - **Median** (default) - Shows typical price level, resistant to spikes
+ - **Arithmetic Mean** - Shows actual mathematical average
+
+**Important:** Both values are **always available** as sensor attributes, regardless of your choice! This ensures your automations continue to work if you change the display setting.
+
+## Using Both Values in Automations
+
+Both `price_mean` and `price_median` are always available as attributes:
+
+```yaml
+# Example: Get both values regardless of display setting
+sensor:
+ - platform: template
+ sensors:
+ daily_price_analysis:
+ friendly_name: "Daily Price Analysis"
+ value_template: >
+ {% set median = state_attr('sensor._price_today', 'price_median') %}
+ {% set mean = state_attr('sensor._price_today', 'price_mean') %}
+ {% set current = states('sensor._current_electricity_price') | float %}
+
+ {% if current < median %}
+ Below typical ({{ ((1 - current/median) * 100) | round(1) }}% cheaper)
+ {% elif current < mean %}
+ Typical price range
+ {% else %}
+ Above average ({{ ((current/mean - 1) * 100) | round(1) }}% more expensive)
+ {% endif %}
+```
+
+## Practical Examples
+
+**Example 1: Smart dishwasher control**
+
+Run dishwasher only when price is significantly below the daily typical level:
+
+
+Show YAML: Automation — start dishwasher when cheap
+
+```yaml
+automation:
+ - alias: "Start Dishwasher When Cheap"
+ trigger:
+ - platform: state
+ entity_id: binary_sensor._best_price_period
+ to: "on"
+ condition:
+ # Only if current price is at least 20% below typical (median)
+ - condition: template
+ value_template: >
+ {% set current = states('sensor._current_electricity_price') | float %}
+ {% set median = state_attr('sensor._price_today', 'price_median') | float %}
+ {{ current < (median * 0.8) }}
+ action:
+ - service: switch.turn_on
+ entity_id: switch.dishwasher
+```
+
+
+
+**Example 2: Cost-aware heating control**
+
+Use mean for actual cost calculations:
+
+
+Show YAML: Automation — cost-aware heating control
+
+```yaml
+automation:
+ - alias: "Heating Budget Control"
+ trigger:
+ - platform: time
+ at: "06:00:00"
+ action:
+ # Calculate expected daily heating cost
+ - variables:
+ mean_price: "{{ state_attr('sensor._price_today', 'price_mean') | float }}"
+ heating_kwh_per_day: 15 # Estimated consumption
+ daily_cost: "{{ (mean_price * heating_kwh_per_day / 100) | round(2) }}"
+ - service: notify.mobile_app
+ data:
+ title: "Heating Cost Estimate"
+ message: "Expected cost today: €{{ daily_cost }} (avg price: {{ mean_price }} ct/kWh)"
+```
+
+
+
+**Example 3: Smart charging based on rolling average**
+
+Use trailing average to understand recent price trends:
+
+
+Show YAML: Automation — EV charging based on rolling average
+
+```yaml
+automation:
+ - alias: "EV Charging - Price Trend Based"
+ trigger:
+ - platform: state
+ entity_id: sensor.ev_battery_level
+ condition:
+ # Start charging if current price < 90% of recent 24h average
+ - condition: template
+ value_template: >
+ {% set current = states('sensor._current_electricity_price') | float %}
+ {% set trailing_avg = state_attr('sensor._price_trailing_24h', 'price_median') | float %}
+ {{ current < (trailing_avg * 0.9) }}
+ # And battery < 80%
+ - condition: numeric_state
+ entity_id: sensor.ev_battery_level
+ below: 80
+ action:
+ - service: switch.turn_on
+ entity_id: switch.ev_charger
+```
+
+
+
+## Key Attributes
+
+All average sensors provide these attributes:
+
+| Attribute | Description | Example |
+|-----------|-------------|---------|
+| `price_mean` | Arithmetic mean (always available) | 25.3 ct/kWh |
+| `price_median` | Median value (always available) | 22.1 ct/kWh |
+| `interval_count` | Number of intervals included | 96 |
+| `timestamp` | Reference time for calculation | 2025-12-18T00:00:00+01:00 |
+
+**Note:** The `price_mean` and `price_median` attributes are **always present** regardless of which value you configured for display. This ensures automation compatibility when changing the display setting.
+
+## When to Use Which Value
+
+**Use Median for:**
+- ✅ Comparing "typical" price levels across days
+- ✅ Determining if current price is unusually high/low
+- ✅ User-facing displays ("What was today like?")
+- ✅ Volatility analysis (comparing typical vs extremes)
+
+**Use Mean for:**
+- ✅ Cost calculations and budgeting
+- ✅ Energy cost estimations
+- ✅ Comparing actual average costs between periods
+- ✅ Financial planning and forecasting
+
+**Both values tell different stories:**
+- High median + much higher mean = Expensive spikes occurred
+- Low median + higher mean = Generally cheap with occasional spikes
+- Similar median and mean = Stable prices (low volatility)
diff --git a/docs/user/docs/sensors-energy-tax.md b/docs/user/docs/sensors-energy-tax.md
new file mode 100644
index 0000000..1f844f6
--- /dev/null
+++ b/docs/user/docs/sensors-energy-tax.md
@@ -0,0 +1,110 @@
+# Energy & Tax Attributes
+
+> **Entity ID tip:** `` is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. **Can't find a sensor?** Use the **[Entity Reference (All Languages)](sensor-reference.md)** to search by name in your language.
+
+Most price sensors include **energy price** and **tax** attributes that break down the total price into its components:
+
+```
+total = energy_price + tax
+```
+
+These attributes appear on **all price sensors that display a raw price** (not on percentage, level, or trend sensors). The `energy_price` is the raw spot/market price, while `tax` includes all fees, surcharges, and taxes added by your electricity provider.
+
+:::note Transition After Update
+After updating the integration, the `energy_price` and `tax` attributes will appear gradually as new price data is fetched from the Tibber API. Existing cached intervals (up to ~2 days old) won't have these fields yet — the attributes will simply be absent until fresh data replaces them. No action needed.
+:::
+
+## Where These Attributes Appear
+
+| Sensor Type | `energy_price` | `tax` | Notes |
+|-------------|:-:|:-:|-------|
+| Current/Next/Previous Interval Price | ✅ | ✅ | Single interval values |
+| Rolling Hour Average | ✅ | ✅ | Averaged across 5 intervals |
+| Daily Min/Max/Average | ✅ | ✅ | Aggregated for the day |
+| Trailing/Leading 24h | ✅ | ✅ | Aggregated across window |
+| Future Average (N-hour) | ✅ | ✅ | Averaged across future window |
+| Levels, Ratings, Trends | ❌ | ❌ | Not price sensors |
+| Volatility | ❌ | ❌ | Statistical, not price |
+
+## Use Cases
+
+### Solar Feed-In & Net Metering (Saldering)
+
+In countries like the Netherlands, solar feed-in compensation is based on the **raw energy/spot price**, not the total consumer price. The `energy_price` attribute gives you exactly this value — no more reverse-engineering from the total price with fragile template calculations.
+
+
+Show YAML: Automation — solar export or consume decision
+
+```yaml
+# Example: Decide whether to export solar power or consume it
+# Compare energy price (what you'd earn by exporting) vs. total price (what you'd pay)
+automation:
+ - alias: "Solar: Export or Consume"
+ trigger:
+ - platform: numeric_state
+ entity_id: sensor.solar_production_power
+ above: 2000 # Producing more than 2 kW
+ condition:
+ - condition: template
+ value_template: >
+ {% set energy = state_attr('sensor._current_electricity_price', 'energy_price') %}
+ {% set total = states('sensor._current_electricity_price') | float %}
+ {# Export when energy price is high relative to total — you earn more #}
+ {{ energy is not none and energy > (total * 0.4) }}
+ action:
+ - service: switch.turn_off
+ entity_id: switch.battery_charging # Don't charge battery, export instead
+```
+
+
+
+### Price Composition Analysis
+
+Understand how your electricity price is structured — useful for comparing across days or spotting trends in market prices vs. fees:
+
+
+Show YAML: Template sensor — electricity tax share percentage
+
+```yaml
+# Template sensor showing tax share
+template:
+ - sensor:
+ - name: "Electricity Tax Share"
+ unit_of_measurement: "%"
+ state: >
+ {% set tax = state_attr('sensor._current_electricity_price', 'tax') %}
+ {% set total = states('sensor._current_electricity_price') | float %}
+ {% if tax is not none and total > 0 %}
+ {{ ((tax / total) * 100) | round(1) }}
+ {% else %}
+ unavailable
+ {% endif %}
+```
+
+
+
+### Dashboard: Daily Cost Breakdown
+
+Show users how today's average price splits into energy vs. tax:
+
+```yaml
+# Mushroom chips card showing the split
+type: custom:mushroom-chips-card
+chips:
+ - type: template
+ icon: mdi:flash
+ content: >
+ ⚡ {{ state_attr('sensor._price_today', 'energy_price_mean') | round(1) }} ct
+ - type: template
+ icon: mdi:receipt-text
+ content: >
+ 🏛️ {{ state_attr('sensor._price_today', 'tax_mean') | round(1) }} ct
+```
+
+## Country-Specific Calculations
+
+The composition of the `tax` field varies by country (Norway, Sweden, Germany, Netherlands each have different fee structures). For detailed examples of how to build country-specific calculations using `input_number` helpers and template sensors — including **Dutch solar feed-in compensation (saldering)** — see the **[Community Examples](community-examples.md#country-specific-price-calculations)** page.
+
+## In Chart Data Actions
+
+The `energy_price` and `tax` fields are also available in the `get_chartdata` action. See [Actions — Energy & Tax Fields](./actions.md#energy--tax-fields-in-get_chartdata) for details.
diff --git a/docs/user/docs/sensors-overview.md b/docs/user/docs/sensors-overview.md
new file mode 100644
index 0000000..d0bbb1a
--- /dev/null
+++ b/docs/user/docs/sensors-overview.md
@@ -0,0 +1,183 @@
+# Sensors Overview
+
+> **Tip:** Many sensors have dynamic icons and colors! See the **[Dynamic Icons Guide](dynamic-icons.md)** and **[Dynamic Icon Colors Guide](icon-colors.md)** to enhance your dashboards.
+
+> **Entity ID tip:** `` is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. **Can't find a sensor?** Use the **[Entity Reference (All Languages)](sensor-reference.md)** to search by name in your language.
+
+The integration provides **100+ sensors** organized by purpose. This page gives a quick overview and links to detailed guides for each sensor family.
+
+| Sensor Family | Purpose | Guide |
+|---|---|---|
+| **Binary Sensors** | Period on/off indicators | [below](#binary-sensors) |
+| **Core Price** | Current, next, previous interval prices | [below](#core-price-sensors) |
+| **Average & Statistics** | Daily averages, rolling averages, median/mean | [Average Sensors](sensors-average.md) |
+| **Ratings & Levels** | Price classification (3-level ratings, 5-level API levels) | [Ratings & Levels](sensors-ratings-levels.md) |
+| **Min/Max** | Daily and rolling 24h extremes | [below](#minmax-sensors) |
+| **Volatility** | Price fluctuation analysis | [Volatility Sensors](sensors-volatility.md) |
+| **Trends** | Price outlook, trajectory, direction | [Trend Sensors](sensors-trends.md) |
+| **Timing** | Period countdown, progress, duration | [Timing Sensors](sensors-timing.md) |
+| **Energy & Tax** | Spot price and tax breakdown | [Energy & Tax](sensors-energy-tax.md) |
+| **Diagnostic** | Chart metadata, data export | [below](#diagnostic-sensors) |
+
+---
+
+## Binary Sensors
+
+### Best Price Period & Peak Price Period
+
+These binary sensors indicate when you're in a detected best or peak price period. See the **[Period Calculation Guide](period-calculation.md)** for a detailed explanation of how these periods are calculated and configured.
+
+**Quick overview:**
+
+- Best Price Period: Turns ON during periods with significantly lower prices than the daily average
+- Peak Price Period: Turns ON during periods with significantly higher prices than the daily average
+
+Both sensors include rich attributes with period details, intervals, relaxation status, and more.
+
+## Core Price Sensors
+
+The integration provides price sensors for the **current**, **next**, and **previous** 15-minute interval. Each exposes the total price as sensor state, with `energy_price` and `tax` available as attributes (see [Energy & Tax Breakdown](sensors-energy-tax.md)).
+
+**Next N Hours Average** sensors (`next_avg_1h`–`next_avg_12h`) provide future price forecasts for 1h, 2h, 3h, 4h, 5h, 6h, 8h, and 12h windows.
+
+For detailed average sensor behavior (median vs mean, configuration, automation examples), see **[Average & Statistics Sensors](sensors-average.md)**.
+
+## Min/Max Sensors
+
+These sensors show the lowest and highest prices for calendar days and rolling windows:
+
+### Daily Min/Max
+
+| Sensor | Description |
+|--------|-------------|
+| Today's Lowest Price | Minimum price today (00:00–23:59) |
+| Today's Highest Price | Maximum price today (00:00–23:59) |
+| Tomorrow's Lowest Price | Minimum price tomorrow |
+| Tomorrow's Highest Price | Maximum price tomorrow |
+
+### 24-Hour Rolling Min/Max
+
+| Sensor | Description |
+|--------|-------------|
+| Trailing Price Min | Lowest price in the last 24 hours |
+| Trailing Price Max | Highest price in the last 24 hours |
+| Leading Price Min | Lowest price in the next 24 hours |
+| Leading Price Max | Highest price in the next 24 hours |
+
+### Key Attributes
+
+All min/max sensors include:
+
+| Attribute | Description |
+|-----------|-------------|
+| `timestamp` | When the extreme price occurs/occurred |
+| `price_diff_from_daily_min` | Difference from daily minimum |
+| `price_diff_from_daily_min_%` | Percentage difference |
+
+## Diagnostic Sensors
+
+### Chart Metadata
+
+**Entity ID:** `sensor._chart_metadata`
+
+> **✨ New Feature**: This sensor provides dynamic chart configuration metadata for optimal visualization. Perfect for use with the `get_apexcharts_yaml` action!
+
+This diagnostic sensor provides essential chart configuration values as sensor attributes, enabling dynamic Y-axis scaling and optimal chart appearance in rolling window modes.
+
+**Key Features:**
+
+- **Dynamic Y-Axis Bounds**: Automatically calculates optimal `yaxis_min` and `yaxis_max` for your price data
+- **Automatic Updates**: Refreshes when price data changes (coordinator updates)
+- **Lightweight**: Metadata-only mode (no data processing) for fast response
+- **State Indicator**: Shows `pending` (initialization), `ready` (data available), or `error` (service call failed)
+
+**Attributes:**
+
+- **`timestamp`**: When the metadata was last fetched
+- **`yaxis_min`**: Suggested minimum value for Y-axis (optimal scaling)
+- **`yaxis_max`**: Suggested maximum value for Y-axis (optimal scaling)
+- **`currency`**: Currency code (e.g., "EUR", "NOK")
+- **`resolution`**: Interval duration in minutes (usually 15)
+- **`error`**: Error message if service call failed
+
+**Usage:**
+
+The `tibber_prices.get_apexcharts_yaml` action **automatically uses this sensor** for dynamic Y-axis scaling in `rolling_window` and `rolling_window_autozoom` modes! No manual configuration needed - just enable the action's result with `config-template-card` and the sensor provides optimal Y-axis bounds automatically.
+
+See the **[Chart Examples Guide](chart-examples.md)** for practical examples!
+
+---
+
+### Chart Data Export
+
+**Entity ID:** `sensor._chart_data_export`
+**Default State:** Disabled (must be manually enabled)
+
+> **⚠️ Legacy Feature**: This sensor is maintained for backward compatibility. For new integrations, use the **`tibber_prices.get_chartdata`** action instead, which offers more flexibility and better performance.
+
+This diagnostic sensor provides cached chart-friendly price data that can be consumed by chart cards (ApexCharts, custom cards, etc.).
+
+**Key Features:**
+
+- **Configurable via Options Flow**: Service parameters can be configured through the integration's options menu (Step 7 of 7)
+- **Automatic Updates**: Data refreshes on coordinator updates (every 15 minutes)
+- **Attribute-Based Output**: Chart data is stored in sensor attributes for easy access
+- **State Indicator**: Shows `pending` (before first call), `ready` (data available), or `error` (service call failed)
+
+**Important Notes:**
+
+- ⚠️ Disabled by default - must be manually enabled in entity settings
+- ⚠️ Consider using the action instead for better control and flexibility
+- ⚠️ Configuration updates require HA restart
+
+**Attributes:**
+
+The sensor exposes chart data with metadata in attributes:
+
+- **`timestamp`**: When the data was last fetched
+- **`error`**: Error message if service call failed
+- **`data`** (or custom name): Array of price data points in configured format
+
+**Configuration:**
+
+To configure the sensor's output format:
+
+1. Go to **Settings → Devices & Services → Tibber Prices**
+2. Click **Configure** on your Tibber home
+3. Navigate through the options wizard to **Step 7: Chart Data Export Settings**
+4. Configure output format, filters, field names, and other options
+5. Save and restart Home Assistant
+
+**Available Settings:**
+
+See the `tibber_prices.get_chartdata` action documentation for a complete list of available parameters. All action parameters can be configured through the options flow.
+
+**Example Usage:**
+
+```yaml
+# ApexCharts card consuming the sensor
+type: custom:apexcharts-card
+series:
+ - entity: sensor._chart_data_export
+ data_generator: |
+ return entity.attributes.data;
+```
+
+**Migration Path:**
+
+If you're currently using this sensor, consider migrating to the action:
+
+```yaml
+# Old approach (sensor)
+- service: apexcharts_card.update
+ data:
+ entity: sensor._chart_data_export
+
+# New approach (action)
+- service: tibber_prices.get_chartdata
+ data:
+ entry_id: YOUR_CONFIG_ENTRY_ID
+ day: ["today", "tomorrow"]
+ output_format: array_of_objects
+ response_variable: chart_data
+```
diff --git a/docs/user/docs/sensors-ratings-levels.md b/docs/user/docs/sensors-ratings-levels.md
new file mode 100644
index 0000000..cbd18d8
--- /dev/null
+++ b/docs/user/docs/sensors-ratings-levels.md
@@ -0,0 +1,140 @@
+# Ratings & Levels
+
+> **Entity ID tip:** `` is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. **Can't find a sensor?** Use the **[Entity Reference (All Languages)](sensor-reference.md)** to search by name in your language.
+
+The integration provides **two** classification systems for electricity prices. Both are useful, but serve different purposes.
+
+## Ratings vs Levels at a Glance
+
+| | Ratings | Levels |
+|--|---------|--------|
+| **Source** | Calculated by integration | Provided by Tibber API |
+| **Scale** | 3 levels (LOW, NORMAL, HIGH) | 5 levels (VERY_CHEAP → VERY_EXPENSIVE) |
+| **Basis** | Trailing 24h average | Daily min/max range |
+| **Best for** | Automations (simple thresholds) | Dashboard displays (fine granularity) |
+| **Configurable** | Yes (thresholds) | Gap tolerance only |
+| **Automation attribute** | `rating_level` (always lowercase English) | `level` (always uppercase English) |
+
+**Which to use?**
+
+- **Automations**: Use **ratings** (3 simple states, configurable thresholds, hysteresis)
+- **Dashboards**: Use **levels** (5 color-coded states, more visual granularity)
+- **Advanced automations**: Combine both (e.g., "LOW rating AND VERY_CHEAP level")
+
+---
+
+## Rating Sensors
+
+Rating sensors classify prices relative to the **trailing 24-hour average**, answering: "Is the current price cheap, normal, or expensive compared to recent history?"
+
+### How Ratings Work
+
+The integration calculates a **percentage difference** between the current price and the trailing 24-hour average:
+
+```
+difference = ((current_price - trailing_avg) / abs(trailing_avg)) × 100%
+```
+
+This percentage is then classified:
+
+| Rating | Condition (default) | Meaning |
+|--------|---------------------|---------|
+| **LOW** | difference ≤ -10% | Significantly below recent average |
+| **NORMAL** | -10% < difference < +10% | Within normal range |
+| **HIGH** | difference ≥ +10% | Significantly above recent average |
+
+**Hysteresis** (default 2%) prevents flickering: once a rating enters LOW, it must cross -8% (not -10%) to return to NORMAL. This avoids rapid switching at threshold boundaries.
+
+```mermaid
+stateDiagram-v2
+ direction LR
+
+ LOW: 🟢 LOW
price ≤ −10%
+ NORMAL: 🟡 NORMAL
−10% … +10%
+ HIGH: 🔴 HIGH
price ≥ +10%
+
+ LOW --> NORMAL: crosses −8%
(hysteresis)
+ NORMAL --> LOW: drops below −10%
+ NORMAL --> HIGH: rises above +10%
+ HIGH --> NORMAL: crosses +8%
(hysteresis)
+```
+
+> **The 2% gap** between entering (−10%) and leaving (−8%) a state prevents the sensor from flickering back and forth when prices hover near a threshold.
+
+### Available Rating Sensors
+
+| Sensor | Scope | Description |
+|--------|-------|-------------|
+| Current Price Rating | Current interval | Rating of the current 15-minute price |
+| Next Price Rating | Next interval | Rating for the upcoming 15-minute price |
+| Previous Price Rating | Previous interval | Rating for the past 15-minute price |
+| Current Hour Price Rating | Rolling 5-interval | Smoothed rating around the current hour |
+| Next Hour Price Rating | Rolling 5-interval | Smoothed rating around the next hour |
+| Yesterday's Price Rating | Calendar day | Aggregated rating for yesterday |
+| Today's Price Rating | Calendar day | Aggregated rating for today |
+| Tomorrow's Price Rating | Calendar day | Aggregated rating for tomorrow |
+
+### Key Attributes
+
+| Attribute | Description | Example |
+|-----------|-------------|---------|
+| `rating_level` | Language-independent rating (always lowercase) | `low` |
+| `difference` | Percentage difference from trailing average | `-12.5` |
+| `trailing_avg_24h` | The reference average used for classification | `22.3` |
+
+### Usage in Automations
+
+**Best Practice:** Always use the `rating_level` attribute (lowercase English) instead of the sensor state (which is translated to your HA language):
+
+```yaml
+# ✅ Correct — language-independent
+condition:
+ - condition: template
+ value_template: >
+ {{ state_attr('sensor._current_price_rating', 'rating_level') == 'low' }}
+
+# ❌ Avoid — breaks when HA language changes
+condition:
+ - condition: state
+ entity_id: sensor._current_price_rating
+ state: "Low" # "Niedrig" in German, "Lav" in Norwegian...
+```
+
+### Configuration
+
+Rating thresholds can be adjusted in the options flow:
+
+1. Go to **Settings → Devices & Services → Tibber Prices → Configure**
+2. Navigate to **Price Rating Thresholds**
+3. Adjust LOW/HIGH thresholds, hysteresis, and gap tolerance
+
+See [Configuration](configuration.md#step-3-price-rating-thresholds) for details.
+
+---
+
+## Level Sensors
+
+Level sensors show the **Tibber API's own price classification** with a 5-level scale:
+
+| Level | Meaning | Numeric Value |
+|-------|---------|---------------|
+| **VERY_CHEAP** | Exceptionally low | -2 |
+| **CHEAP** | Below average | -1 |
+| **NORMAL** | Typical range | 0 |
+| **EXPENSIVE** | Above average | +1 |
+| **VERY_EXPENSIVE** | Exceptionally high | +2 |
+
+### Available Level Sensors
+
+| Sensor | Scope |
+|--------|-------|
+| Current Price Level | Current interval |
+| Next Price Level | Next interval |
+| Previous Price Level | Previous interval |
+| Current Hour Price Level | Rolling 5-interval window |
+| Next Hour Price Level | Rolling 5-interval window |
+| Yesterday's Price Level | Calendar day (aggregated) |
+| Today's Price Level | Calendar day (aggregated) |
+| Tomorrow's Price Level | Calendar day (aggregated) |
+
+**Gap tolerance** smoothing is applied to prevent isolated level flickers (e.g., a single NORMAL between two CHEAPs → corrected to CHEAP). Configure in [options flow](configuration.md#step-4-price-level-gap-tolerance).
diff --git a/docs/user/docs/sensors-timing.md b/docs/user/docs/sensors-timing.md
new file mode 100644
index 0000000..9618369
--- /dev/null
+++ b/docs/user/docs/sensors-timing.md
@@ -0,0 +1,95 @@
+# Timing Sensors
+
+> **Entity ID tip:** `` is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. **Can't find a sensor?** Use the **[Entity Reference (All Languages)](sensor-reference.md)** to search by name in your language.
+
+Timing sensors provide **real-time information about Best Price and Peak Price periods**: when they start, end, how long they last, and your progress through them.
+
+```mermaid
+stateDiagram-v2
+ direction LR
+
+ IDLE: ⏸️ IDLE
No active period
+ ACTIVE: ▶️ ACTIVE
In period
+ GRACE: ⏳ GRACE
60s buffer
+
+ IDLE --> ACTIVE: period starts
+ ACTIVE --> GRACE: period ends
+ GRACE --> IDLE: 60s elapsed
+ GRACE --> ACTIVE: new period starts
(within grace)
+```
+
+**IDLE** = waiting for next period (shows countdown via `next_in_minutes`). **ACTIVE** = inside a period (shows `progress` 0–100% and `remaining_minutes`). **GRACE** = short buffer after a period ends, allowing back-to-back periods to merge seamlessly.
+
+## Available Timing Sensors
+
+For each period type (Best Price and Peak Price):
+
+| Sensor | When Period Active | When No Active Period |
+|--------|-------------------|----------------------|
+| End Time | Current period's end time | Next period's end time |
+| Period Duration | Current period length (minutes) | Next period length |
+| Remaining Minutes | Minutes until current period ends | 0 |
+| Progress | 0–100% through current period | 0 |
+| Next Start Time | When next-next period starts | When next period starts |
+| Next In Minutes | Minutes to next-next period | Minutes to next period |
+
+## Usage Examples
+
+### Show Countdown to Next Cheap Window
+
+```yaml
+type: custom:mushroom-entity-card
+entity: sensor._best_price_next_in_minutes
+name: Next Cheap Window
+icon: mdi:clock-fast
+```
+
+### Display Period Progress Bar
+
+
+Show YAML: Bar card for period progress
+
+```yaml
+type: custom:bar-card
+entity: sensor._best_price_progress
+name: Best Price Progress
+min: 0
+max: 100
+severity:
+ - from: 0
+ to: 50
+ color: green
+ - from: 50
+ to: 80
+ color: orange
+ - from: 80
+ to: 100
+ color: red
+```
+
+
+
+### Notify When Period Is Almost Over
+
+
+Show YAML: Automation — notify when best price period is ending
+
+```yaml
+automation:
+ - alias: "Warn: Best Price Ending Soon"
+ trigger:
+ - platform: numeric_state
+ entity_id: sensor._best_price_remaining_minutes
+ below: 15
+ condition:
+ - condition: numeric_state
+ entity_id: sensor._best_price_remaining_minutes
+ above: 0
+ action:
+ - service: notify.mobile_app
+ data:
+ title: "Best Price Ending Soon"
+ message: "Only {{ states('sensor._best_price_remaining_minutes') }} minutes left!"
+```
+
+
diff --git a/docs/user/docs/sensors-trends.md b/docs/user/docs/sensors-trends.md
new file mode 100644
index 0000000..752c27c
--- /dev/null
+++ b/docs/user/docs/sensors-trends.md
@@ -0,0 +1,266 @@
+# Trend Sensors
+
+> **Entity ID tip:** `` is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. **Can't find a sensor?** Use the **[Entity Reference (All Languages)](sensor-reference.md)** to search by name in your language.
+
+Trend sensors help you understand **whether to act now or wait**. The integration provides two complementary families:
+
+- **Price Outlook Sensors (1h–12h):** Compare current price vs. future window average — "Is now cheaper than the next Nh on average?"
+- **Price Trajectory Sensors (2h–12h):** Compare first half vs. second half of the window — "Are prices rising or falling *within* the window?"
+
+---
+
+## Price Outlook Sensors (1h–12h)
+
+These sensors compare the **current price** with the **average price** of the next N hours:
+
+| Sensor | Compares Against |
+|--------|-----------------|
+| **Price Outlook (1h)** (`price_outlook_1h`) | Average of next 1 hour |
+| **Price Outlook (2h)** (`price_outlook_2h`) | Average of next 2 hours |
+| **Price Outlook (3h)** (`price_outlook_3h`) | Average of next 3 hours |
+| **Price Outlook (4h)** (`price_outlook_4h`) | Average of next 4 hours |
+| **Price Outlook (5h)** (`price_outlook_5h`) | Average of next 5 hours |
+| **Price Outlook (6h)** (`price_outlook_6h`) | Average of next 6 hours |
+| **Price Outlook (8h)** (`price_outlook_8h`) | Average of next 8 hours |
+| **Price Outlook (12h)** (`price_outlook_12h`) | Average of next 12 hours |
+
+:::info Same Starting Point — All Outlook Sensors Use Your Current Price
+All outlook sensors share the **same base: your current 15-minute price**. They differ only in how far ahead they average. The windows **overlap** — the 3h average includes ALL intervals from the 1h and 2h windows, plus one more hour.
+
+**This means:**
+- `price_outlook_3h` shows "current price vs. average of the **entire** next 3 hours" — **not** "what happens between hour 2 and hour 3"
+- If 1h shows `falling` but 6h shows `rising`: near-term prices are below your current price, but looking at the full 6h window (which includes expensive evening hours), the overall average is above your current price
+- Larger windows smooth out short-term fluctuations — a 30-minute price spike affects the 1h average more than the 6h average
+
+**⚠️ At a price minimum, outlook sensors can be misleading!** If you're at the minimum and prices are about to rise, `price_outlook_3h` may still show `strongly_falling` because the cheap minimum pulls the 3h average below your current high price. Use `price_trajectory_3h` to see the direction *within* the window.
+:::
+
+**States:** Each sensor has one of five states:
+
+```mermaid
+stateDiagram-v2
+ direction LR
+
+ SF: ⬇️⬇️ strongly_falling
−2 · future ≤ −9%
+ F: ⬇️ falling
−1 · future ≤ −3%
+ S: ➡️ stable
0 · within ±3%
+ R: ⬆️ rising
+1 · future ≥ +3%
+ SR: ⬆️⬆️ strongly_rising
+2 · future ≥ +9%
+
+ SF --> F: price recovers
+ F --> S: approaches average
+ S --> R: future rises
+ R --> SR: accelerates
+ SR --> R: slows down
+ R --> S: stabilizes
+ S --> F: future drops
+ F --> SF: accelerates
+```
+
+| State | Meaning | `trend_value` |
+|-------|---------|---------------|
+| `strongly_falling` | Prices will drop significantly | -2 |
+| `falling` | Prices will drop | -1 |
+| `stable` | Prices staying roughly the same | 0 |
+| `rising` | Prices will increase | +1 |
+| `strongly_rising` | Prices will increase significantly | +2 |
+
+**Key attributes:**
+
+| Attribute | Description | Example |
+|-----------|-------------|---------|
+| `trend_value` | Numeric value for automations (-2 to +2) | `-1` |
+| `trend_Nh_%` | Percentage difference from current price | `-12.3` |
+| `next_Nh_avg` | Average price in the future window | `18.5` |
+| `second_half_Nh_avg` | Average price in later half of window | `16.2` |
+| `threshold_rising_%` | Active rising threshold after volatility adjustment | `3.0` |
+| `threshold_rising_strongly_%` | Active strongly-rising threshold after volatility adjustment | `4.8` |
+| `threshold_falling_%` | Active falling threshold after volatility adjustment | `-3.0` |
+| `threshold_falling_strongly_%` | Active strongly-falling threshold after volatility adjustment | `-4.8` |
+| `volatility_factor` | Applied multiplier (0.6 = low, 1.0 = moderate, 1.4 = high volatility) | `0.8` |
+
+**Tip:** The `trend_value` attribute (`-2` to `+2`) is ideal for automations — use numeric comparisons instead of matching translated state strings.
+
+---
+
+## Price Trajectory Sensors (2h–12h)
+
+These sensors compare the **first half** of the future window against the **second half** — revealing the price *direction within* the window.
+
+| Sensor | Compares |
+|--------|----------|
+| **Price Trajectory (2h)** (`price_trajectory_2h`) | Avg of hour 1 vs avg of hour 2 |
+| **Price Trajectory (3h)** (`price_trajectory_3h`) | Avg of first 1.5h vs avg of second 1.5h |
+| **Price Trajectory (4h)** (`price_trajectory_4h`) | Avg of first 2h vs avg of second 2h |
+| **Price Trajectory (5h)** (`price_trajectory_5h`) | Avg of first 2.5h vs avg of second 2.5h |
+| **Price Trajectory (6h)** (`price_trajectory_6h`) | Avg of first 3h vs avg of second 3h |
+| **Price Trajectory (8h)** (`price_trajectory_8h`) | Avg of first 4h vs avg of second 4h |
+| **Price Trajectory (12h)** (`price_trajectory_12h`) | Avg of first 6h vs avg of second 6h |
+
+**States:** Same 5-level scale as outlook sensors (`strongly_falling` → `strongly_rising`).
+
+:::info Why trajectory sensors complement outlook sensors
+**At a price minimum** — the exact moment you should act — `price_outlook_3h` may show `strongly_falling` because the cheap minimum pulls the entire 3h average below your current high price. But `price_trajectory_3h` shows `rising` because the second half (after the minimum) is more expensive than the first half.
+
+| Combination | Interpretation |
+|-------------|----------------|
+| Outlook `falling` + Trajectory `rising` | **You're AT the minimum** — act now |
+| Outlook `falling` + Trajectory `falling` | Prices still dropping — wait |
+| Outlook `rising` + Trajectory `rising` | Strong signal to act now |
+| Outlook `rising` + Trajectory `falling` | Short spike, then cheaper — wait |
+:::
+
+**Key attributes:**
+
+| Attribute | Description | Example |
+|-----------|-------------|---------|
+| `trend_value` | Numeric value for automations (-2 to +2) | `1` |
+| `first_half_avg` | Average price in first half of window | `12.4` |
+| `second_half_avg` | Average price in second half of window | `18.1` |
+| `half_diff_%` | Percentage difference (second vs first half) | `46.0` |
+
+---
+
+## Current Price Trend
+
+**Entity ID:** `sensor._current_price_trend`
+
+This sensor shows the **currently active trend direction** based on a 3-hour future outlook with volatility-adaptive thresholds.
+
+Unlike the simple trend sensors that always compare current price vs future average, the current price trend represents the **ongoing trend** — it remains stable between updates and only changes when the underlying price direction actually shifts.
+
+**States:** Same 5-level scale as simple trends.
+
+**Key attributes:**
+
+| Attribute | Description | Example |
+|-----------|-------------|---------|
+| `previous_direction` | Price direction before the current trend started | `falling` |
+| `price_direction_duration_minutes` | How long prices have been moving in this direction | `45` |
+| `price_direction_since` | Timestamp when prices started moving in this direction | `2025-11-08T14:00:00+01:00` |
+
+---
+
+## Next Price Trend Change
+
+**Entity ID:** `sensor._next_price_trend_change`
+
+This sensor predicts **when the current trend will change** by scanning future intervals. It requires 3 consecutive intervals (configurable: 2–6) confirming the new trend before reporting a change (hysteresis), which prevents false alarms from short-lived price spikes.
+
+**Important:** Only **direction changes** count as trend changes. The five states are grouped into three directions:
+
+| Direction | States |
+|-----------|--------|
+| **falling** | `strongly_falling`, `falling` |
+| **stable** | `stable` |
+| **rising** | `rising`, `strongly_rising` |
+
+A change from `rising` to `strongly_rising` (same direction) is **not** reported as a trend change — only actual reversals like `rising` → `stable` or `falling` → `rising`.
+
+**State:** Timestamp of the next trend change (or unavailable if no change predicted).
+
+**Key attributes:**
+
+| Attribute | Description | Example |
+|-----------|-------------|---------|
+| `direction` | What the trend will change TO | `rising` |
+| `from_direction` | Current trend (will change FROM) | `falling` |
+| `minutes_until_change` | Minutes until trend changes | `90` |
+| `price_at_change` | Price at the change point | `13.8` |
+| `price_avg_after_change` | Average price after change | `18.1` |
+| `threshold_rising_%` | Active rising threshold after volatility adjustment | `3.0` |
+| `threshold_rising_strongly_%` | Active strongly-rising threshold after volatility adjustment | `4.8` |
+| `threshold_falling_%` | Active falling threshold after volatility adjustment | `-3.0` |
+| `threshold_falling_strongly_%` | Active strongly-falling threshold after volatility adjustment | `-4.8` |
+| `volatility_factor` | Applied multiplier (0.6 = low, 1.0 = moderate, 1.4 = high volatility) | `0.8` |
+
+---
+
+## How to Use Trend Sensors for Decisions
+
+:::danger Common Misconception — Don't "Wait for Stable"!
+A natural intuition is to treat trend states like a stock ticker:
+
+- ❌ "It's **falling** → I'll wait until it reaches **stable** (the bottom)"
+- ❌ "It's **rising** → too late, I missed the best price"
+- ❌ "It's **stable** → now is the perfect time to act!"
+
+**This is wrong.** Trend sensors don't show a trajectory — they show a **comparison** between your current price and future prices. The correct interpretation is the opposite:
+
+| State | What the Sensor Calculates | ✅ Correct Action |
+|-------|---------------------------|-------------------|
+| `falling` | Current price **higher** than future average | **WAIT** — cheaper prices are coming |
+| `strongly_falling` | Current price **much higher** than future average | **DEFINITELY WAIT** — significant savings ahead |
+| `stable` | Current price **≈ equal** to future average | **Timing doesn't matter** — start whenever convenient |
+| `rising` | Current price **lower** than future average | **ACT NOW** — it only gets more expensive |
+| `strongly_rising` | Current price **much lower** than future average | **ACT IMMEDIATELY** — best price right now |
+
+**"Rising" is NOT "too late" — it means NOW is the best time because prices will be higher later.**
+:::
+
+### Basic Automation Pattern
+
+For most appliances (dishwasher, washing machine, dryer), a single outlook sensor is enough:
+
+```yaml
+# Example: Start dishwasher when prices are favorable
+trigger:
+ - platform: state
+ entity_id: sensor.my_home_price_outlook_3h
+condition:
+ - condition: numeric_state
+ entity_id: sensor.my_home_price_outlook_3h
+ attribute: trend_value
+ # rising (1) or strongly_rising (2) = act now
+ above: 0
+action:
+ - service: switch.turn_on
+ target:
+ entity_id: switch.dishwasher
+```
+
+### Combining Multiple Windows
+
+When short-term and long-term trends disagree, you get richer insight:
+
+| 1h Outlook | 6h Outlook | Interpretation | Recommendation |
+|----------|----------|---------------|----------------|
+| `rising` | `rising` | Prices going up across the board | **Start now** |
+| `falling` | `falling` | Prices dropping across the board | **Wait** |
+| `falling` | `rising` | Brief dip, then expensive evening | **Wait briefly**, then start during the dip |
+| `rising` | `falling` | Short spike, but cheaper hours ahead | **Wait** if you can — better prices coming |
+| `stable` | any | Short-term doesn't matter | Use the **longer window** for your decision |
+
+### Dashboard Quick-Glance
+
+On your dashboard, trend sensors give an instant overview:
+
+- 🟢 All **falling/strongly_falling** → "Relax, prices are dropping — wait"
+- 🔴 All **rising/strongly_rising** → "Start everything you can — it only gets more expensive"
+- 🟡 **Mixed** → Compare short-term vs. long-term sensors, or check the Best Price Period sensor
+
+---
+
+## Outlook & Trajectory vs Average Sensors
+
+Both sensor families provide future price information, but serve different purposes:
+
+| | Outlook/Trajectory Sensors | Average Sensors |
+|--|---------------------------|-----------------|
+| **Purpose** | Dashboard display, quick visual overview | Automations, precise numeric comparisons |
+| **Output** | Classification (falling/stable/rising) | Exact price values (ct/kWh) |
+| **Best for** | "Should I worry about prices?" | "Is the future average below 15 ct?" |
+| **Use in** | Dashboard icons, status displays | Template conditions, numeric thresholds |
+
+**Design principle:** Use **trend sensors** (enum) for visual feedback at a glance, use **average sensors** (numeric) for precise decision-making in automations.
+
+## Configuration
+
+Trend thresholds can be adjusted in the options flow:
+
+1. Go to **Settings → Devices & Services → Tibber Prices**
+2. Click **Configure** on your home
+3. Navigate to **📈 Price Trend Thresholds**
+4. Adjust the rising/falling and strongly rising/falling percentages
+
+The thresholds are **volatility-adaptive**: on days with high price volatility, thresholds are widened automatically to prevent constant state changes. This means the trend sensors give more stable readings during volatile market conditions.
diff --git a/docs/user/docs/sensors-volatility.md b/docs/user/docs/sensors-volatility.md
new file mode 100644
index 0000000..92c094b
--- /dev/null
+++ b/docs/user/docs/sensors-volatility.md
@@ -0,0 +1,99 @@
+# Volatility Sensors
+
+> **Entity ID tip:** `` is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. **Can't find a sensor?** Use the **[Entity Reference (All Languages)](sensor-reference.md)** to search by name in your language.
+
+Volatility sensors help you understand how much electricity prices fluctuate over a given period. Instead of just looking at the absolute price, they measure the **relative price variation**, which is a great indicator of whether it's a good day for price-based energy optimization.
+
+The calculation is based on the **Coefficient of Variation (CV)**, a standardized statistical measure defined as:
+
+`CV = (Standard Deviation / Arithmetic Mean) * 100%`
+
+This results in a percentage that shows how much prices deviate from the average. A low CV means stable prices, while a high CV indicates significant price swings and thus, a high potential for saving money by shifting consumption.
+
+The sensor's state can be `low`, `moderate`, `high`, or `very_high`, based on configurable thresholds.
+
+## Available Volatility Sensors
+
+| Sensor | Description | Time Window |
+|---|---|---|
+| Today's Price Volatility | Volatility for the current calendar day | 00:00 - 23:59 today |
+| Tomorrow's Price Volatility | Volatility for the next calendar day | 00:00 - 23:59 tomorrow |
+| **Next 24h Price Volatility** (`next_24h_volatility`) | Volatility for the next 24 hours from now | Rolling 24h forward |
+| Today + Tomorrow Price Volatility | Volatility across both today and tomorrow | Up to 48 hours |
+
+## Configuration
+
+You can adjust the CV thresholds that determine the volatility level:
+1. Go to **Settings → Devices & Services → Tibber Prices**.
+2. Click **Configure**.
+3. Go to the **Price Volatility Thresholds** step.
+
+Default thresholds are:
+- **Moderate:** 15%
+- **High:** 30%
+- **Very High:** 50%
+
+## Key Attributes
+
+All volatility sensors provide these attributes:
+
+| Attribute | Description | Example |
+|---|---|---|
+| `price_coefficient_variation_%` | The calculated Coefficient of Variation | `23.5` |
+| `price_spread` | The difference between the highest and lowest price | `12.3` |
+| `price_min` | The lowest price in the period | `10.2` |
+| `price_max` | The highest price in the period | `22.5` |
+| `price_mean` | The arithmetic mean of all prices in the period | `15.1` |
+| `interval_count` | Number of price intervals included in the calculation | `96` |
+
+## Usage in Automations & Best Practices
+
+You can use the volatility sensor to decide if a price-based optimization is worth it. For example, if your solar battery has conversion losses, you might only want to charge and discharge it on days with high volatility.
+
+### Best Practice: Use the `price_volatility` Attribute
+
+For automations, it is strongly recommended to use the `price_volatility` attribute instead of the sensor's main state.
+
+- **Why?** The main `state` of the sensor is translated into your Home Assistant language (e.g., "Hoch" in German). If you change your system language, automations based on this state will break. The `price_volatility` attribute is **always in lowercase English** (`"low"`, `"moderate"`, `"high"`, `"very_high"`) and therefore provides a stable, language-independent value.
+
+**Good Example (Robust Automation):**
+This automation triggers only if the volatility is classified as `high` or `very_high`, respecting your central settings and working independently of the system language.
+```yaml
+automation:
+ - alias: "Enable battery optimization only on volatile days"
+ trigger:
+ - platform: template
+ value_template: >
+ {{ state_attr('sensor._today_s_price_volatility', 'price_volatility') in ['high', 'very_high'] }}
+ action:
+ - service: input_boolean.turn_on
+ entity_id: input_boolean.battery_optimization_enabled
+```
+
+---
+
+### Avoid Hard-Coding Numeric Thresholds
+
+You might be tempted to use the numeric `price_coefficient_variation_%` attribute directly in your automations. This is not recommended.
+
+- **Why?** The integration provides central configuration options for the volatility thresholds. By using the classified `price_volatility` attribute, your automations automatically adapt if you decide to change what you consider "high" volatility (e.g., changing the threshold from 30% to 35%). Hard-coding values means you would have to find and update them in every single automation.
+
+**Bad Example (Brittle Automation):**
+This automation uses a hard-coded value. If you later change the "High" threshold in the integration's options to 35%, this automation will not respect that change and might trigger at the wrong time.
+```yaml
+automation:
+ - alias: "Brittle - Enable battery optimization"
+ trigger:
+ #
+ # BAD: Avoid hard-coding numeric values
+ #
+ - platform: numeric_state
+ entity_id: sensor._today_s_price_volatility
+ attribute: price_coefficient_variation_%
+ above: 30
+ action:
+ - service: input_boolean.turn_on
+ entity_id: input_boolean.battery_optimization_enabled
+```
+
+By following the "Good Example", your automations become simpler, more readable, and much easier to maintain.
diff --git a/docs/user/docs/sensors.md b/docs/user/docs/sensors.md
deleted file mode 100644
index f4c4aa8..0000000
--- a/docs/user/docs/sensors.md
+++ /dev/null
@@ -1,1038 +0,0 @@
----
-comments: false
----
-
-# Sensors
-
-> **Tip:** Many sensors have dynamic icons and colors! See the **[Dynamic Icons Guide](dynamic-icons.md)** and **[Dynamic Icon Colors Guide](icon-colors.md)** to enhance your dashboards.
-
-> **Entity ID tip:** `` is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. **Can't find a sensor?** Use the **[Entity Reference (All Languages)](sensor-reference.md)** to search by name in your language.
-
-## Binary Sensors
-
-### Best Price Period & Peak Price Period
-
-These binary sensors indicate when you're in a detected best or peak price period. See the **[Period Calculation Guide](period-calculation.md)** for a detailed explanation of how these periods are calculated and configured.
-
-**Quick overview:**
-
-- Best Price Period: Turns ON during periods with significantly lower prices than the daily average
-- Peak Price Period: Turns ON during periods with significantly higher prices than the daily average
-
-Both sensors include rich attributes with period details, intervals, relaxation status, and more.
-
-## Core Price Sensors
-
-### Average Price Sensors
-
-The integration provides several sensors that calculate average electricity prices over different time windows. These sensors show a **typical** price value that represents the overall price level, helping you make informed decisions about when to use electricity.
-
-#### Available Average Sensors
-
-| Sensor | Description | Time Window |
-|--------|-------------|-------------|
-| Average Price Today | Typical price for current calendar day | 00:00 - 23:59 today |
-| Average Price Tomorrow | Typical price for next calendar day | 00:00 - 23:59 tomorrow |
-| Trailing Price Average | Typical price for last 24 hours | Rolling 24h backward |
-| Leading Price Average | Typical price for next 24 hours | Rolling 24h forward |
-| Current Hour Average | Smoothed price around current time | 5 intervals (~75 min) |
-| Next Hour Average | Smoothed price around next hour | 5 intervals (~75 min) |
-| **Next N Hours Average** (`next_avg_1h`–`next_avg_12h`) | Future price forecast | 1h, 2h, 3h, 4h, 5h, 6h, 8h, 12h |
-
-#### Configurable Display: Median vs Mean
-
-All average sensors support **two different calculation methods** for the state value:
-
-- **Median** (default): The "middle value" when all prices are sorted. Resistant to extreme price spikes, shows the **typical** price level you experienced.
-- **Arithmetic Mean**: The mathematical average including all prices. Better for **cost calculations** but affected by extreme spikes.
-
-**Why two values matter:**
-
-```yaml
-# Example price data for one day:
-# Prices: 10, 12, 13, 15, 80 ct/kWh (one extreme spike)
-#
-# Median = 13 ct/kWh ← "Typical" price level (middle value)
-# Mean = 26 ct/kWh ← Mathematical average (affected by spike)
-```
-
-The median shows you what price level was **typical** during that period, while the mean shows the actual **average cost** if you consumed evenly throughout the period.
-
-#### Configuring the Display
-
-You can choose which value is displayed in the sensor state:
-
-1. Go to **Settings → Devices & Services → Tibber Prices**
-2. Click **Configure** on your home
-3. Navigate to **Step 6: Average Sensor Display Settings**
-4. Choose between:
- - **Median** (default) - Shows typical price level, resistant to spikes
- - **Arithmetic Mean** - Shows actual mathematical average
-
-**Important:** Both values are **always available** as sensor attributes, regardless of your choice! This ensures your automations continue to work if you change the display setting.
-
-#### Using Both Values in Automations
-
-Both `price_mean` and `price_median` are always available as attributes:
-
-```yaml
-# Example: Get both values regardless of display setting
-sensor:
- - platform: template
- sensors:
- daily_price_analysis:
- friendly_name: "Daily Price Analysis"
- value_template: >
- {% set median = state_attr('sensor._price_today', 'price_median') %}
- {% set mean = state_attr('sensor._price_today', 'price_mean') %}
- {% set current = states('sensor._current_electricity_price') | float %}
-
- {% if current < median %}
- Below typical ({{ ((1 - current/median) * 100) | round(1) }}% cheaper)
- {% elif current < mean %}
- Typical price range
- {% else %}
- Above average ({{ ((current/mean - 1) * 100) | round(1) }}% more expensive)
- {% endif %}
-```
-
-#### Practical Examples
-
-**Example 1: Smart dishwasher control**
-
-Run dishwasher only when price is significantly below the daily typical level:
-
-
-Show YAML: Automation — start dishwasher when cheap
-
-```yaml
-automation:
- - alias: "Start Dishwasher When Cheap"
- trigger:
- - platform: state
- entity_id: binary_sensor._best_price_period
- to: "on"
- condition:
- # Only if current price is at least 20% below typical (median)
- - condition: template
- value_template: >
- {% set current = states('sensor._current_electricity_price') | float %}
- {% set median = state_attr('sensor._price_today', 'price_median') | float %}
- {{ current < (median * 0.8) }}
- action:
- - service: switch.turn_on
- entity_id: switch.dishwasher
-```
-
-
-
-**Example 2: Cost-aware heating control**
-
-Use mean for actual cost calculations:
-
-
-Show YAML: Automation — cost-aware heating control
-
-```yaml
-automation:
- - alias: "Heating Budget Control"
- trigger:
- - platform: time
- at: "06:00:00"
- action:
- # Calculate expected daily heating cost
- - variables:
- mean_price: "{{ state_attr('sensor._price_today', 'price_mean') | float }}"
- heating_kwh_per_day: 15 # Estimated consumption
- daily_cost: "{{ (mean_price * heating_kwh_per_day / 100) | round(2) }}"
- - service: notify.mobile_app
- data:
- title: "Heating Cost Estimate"
- message: "Expected cost today: €{{ daily_cost }} (avg price: {{ mean_price }} ct/kWh)"
-```
-
-
-
-**Example 3: Smart charging based on rolling average**
-
-Use trailing average to understand recent price trends:
-
-
-Show YAML: Automation — EV charging based on rolling average
-
-```yaml
-automation:
- - alias: "EV Charging - Price Trend Based"
- trigger:
- - platform: state
- entity_id: sensor.ev_battery_level
- condition:
- # Start charging if current price < 90% of recent 24h average
- - condition: template
- value_template: >
- {% set current = states('sensor._current_electricity_price') | float %}
- {% set trailing_avg = state_attr('sensor._price_trailing_24h', 'price_median') | float %}
- {{ current < (trailing_avg * 0.9) }}
- # And battery < 80%
- - condition: numeric_state
- entity_id: sensor.ev_battery_level
- below: 80
- action:
- - service: switch.turn_on
- entity_id: switch.ev_charger
-```
-
-
-
-#### Key Attributes
-
-All average sensors provide these attributes:
-
-| Attribute | Description | Example |
-|-----------|-------------|---------|
-| `price_mean` | Arithmetic mean (always available) | 25.3 ct/kWh |
-| `price_median` | Median value (always available) | 22.1 ct/kWh |
-| `interval_count` | Number of intervals included | 96 |
-| `timestamp` | Reference time for calculation | 2025-12-18T00:00:00+01:00 |
-
-**Note:** The `price_mean` and `price_median` attributes are **always present** regardless of which value you configured for display. This ensures automation compatibility when changing the display setting.
-
-#### When to Use Which Value
-
-**Use Median for:**
-- ✅ Comparing "typical" price levels across days
-- ✅ Determining if current price is unusually high/low
-- ✅ User-facing displays ("What was today like?")
-- ✅ Volatility analysis (comparing typical vs extremes)
-
-**Use Mean for:**
-- ✅ Cost calculations and budgeting
-- ✅ Energy cost estimations
-- ✅ Comparing actual average costs between periods
-- ✅ Financial planning and forecasting
-
-**Both values tell different stories:**
-- High median + much higher mean = Expensive spikes occurred
-- Low median + higher mean = Generally cheap with occasional spikes
-- Similar median and mean = Stable prices (low volatility)
-
-
-
-## Volatility Sensors
-
-Volatility sensors help you understand how much electricity prices fluctuate over a given period. Instead of just looking at the absolute price, they measure the **relative price variation**, which is a great indicator of whether it's a good day for price-based energy optimization.
-
-The calculation is based on the **Coefficient of Variation (CV)**, a standardized statistical measure defined as:
-
-`CV = (Standard Deviation / aAithmetic Mean) * 100%`
-
-This results in a percentage that shows how much prices deviate from the average. A low CV means stable prices, while a high CV indicates significant price swings and thus, a high potential for saving money by shifting consumption.
-
-The sensor's state can be `low`, `moderate`, `high`, or `very_high`, based on configurable thresholds.
-
-### Available Volatility Sensors
-
-| Sensor | Description | Time Window |
-|---|---|---|
-| Today's Price Volatility | Volatility for the current calendar day | 00:00 - 23:59 today |
-| Tomorrow's Price Volatility | Volatility for the next calendar day | 00:00 - 23:59 tomorrow |
-| **Next 24h Price Volatility** (`next_24h_volatility`) | Volatility for the next 24 hours from now | Rolling 24h forward |
-| Today + Tomorrow Price Volatility | Volatility across both today and tomorrow | Up to 48 hours |
-
-### Configuration
-
-You can adjust the CV thresholds that determine the volatility level:
-1. Go to **Settings → Devices & Services → Tibber Prices**.
-2. Click **Configure**.
-3. Go to the **Price Volatility Thresholds** step.
-
-Default thresholds are:
-- **Moderate:** 15%
-- **High:** 30%
-- **Very High:** 50%
-
-### Key Attributes
-
-All volatility sensors provide these attributes:
-
-| Attribute | Description | Example |
-|---|---|---|
-| `price_coefficient_variation_%` | The calculated Coefficient of Variation | `23.5` |
-| `price_spread` | The difference between the highest and lowest price | `12.3` |
-| `price_min` | The lowest price in the period | `10.2` |
-| `price_max` | The highest price in the period | `22.5` |
-| `price_mean` | The arithmetic mean of all prices in the period | `15.1` |
-| `interval_count` | Number of price intervals included in the calculation | `96` |
-
-### Usage in Automations & Best Practices
-
-You can use the volatility sensor to decide if a price-based optimization is worth it. For example, if your solar battery has conversion losses, you might only want to charge and discharge it on days with high volatility.
-
-**Best Practice: Use the `price_volatility` Attribute**
-
-For automations, it is strongly recommended to use the `price_volatility` attribute instead of the sensor's main state.
-
-- **Why?** The main `state` of the sensor is translated into your Home Assistant language (e.g., "Hoch" in German). If you change your system language, automations based on this state will break. The `price_volatility` attribute is **always in lowercase English** (`"low"`, `"moderate"`, `"high"`, `"very_high"`) and therefore provides a stable, language-independent value.
-
-**Good Example (Robust Automation):**
-This automation triggers only if the volatility is classified as `high` or `very_high`, respecting your central settings and working independently of the system language.
-```yaml
-automation:
- - alias: "Enable battery optimization only on volatile days"
- trigger:
- - platform: template
- value_template: >
- {{ state_attr('sensor._today_s_price_volatility', 'price_volatility') in ['high', 'very_high'] }}
- action:
- - service: input_boolean.turn_on
- entity_id: input_boolean.battery_optimization_enabled
-```
-
----
-
-**Avoid Hard-Coding Numeric Thresholds**
-
-You might be tempted to use the numeric `price_coefficient_variation_%` attribute directly in your automations. This is not recommended.
-
-- **Why?** The integration provides central configuration options for the volatility thresholds. By using the classified `price_volatility` attribute, your automations automatically adapt if you decide to change what you consider "high" volatility (e.g., changing the threshold from 30% to 35%). Hard-coding values means you would have to find and update them in every single automation.
-
-**Bad Example (Brittle Automation):**
-This automation uses a hard-coded value. If you later change the "High" threshold in the integration's options to 35%, this automation will not respect that change and might trigger at the wrong time.
-```yaml
-automation:
- - alias: "Brittle - Enable battery optimization"
- trigger:
- #
- # BAD: Avoid hard-coding numeric values
- #
- - platform: numeric_state
- entity_id: sensor._today_s_price_volatility
- attribute: price_coefficient_variation_%
- above: 30
- action:
- - service: input_boolean.turn_on
- entity_id: input_boolean.battery_optimization_enabled
-```
-
-By following the "Good Example", your automations become simpler, more readable, and much easier to maintain.
-
-## Rating Sensors
-
-Rating sensors classify prices relative to the **trailing 24-hour average**, answering: "Is the current price cheap, normal, or expensive compared to recent history?"
-
-### How Ratings Work
-
-The integration calculates a **percentage difference** between the current price and the trailing 24-hour average:
-
-```
-difference = ((current_price - trailing_avg) / abs(trailing_avg)) × 100%
-```
-
-This percentage is then classified:
-
-| Rating | Condition (default) | Meaning |
-|--------|---------------------|---------|
-| **LOW** | difference ≤ -10% | Significantly below recent average |
-| **NORMAL** | -10% < difference < +10% | Within normal range |
-| **HIGH** | difference ≥ +10% | Significantly above recent average |
-
-**Hysteresis** (default 2%) prevents flickering: once a rating enters LOW, it must cross -8% (not -10%) to return to NORMAL. This avoids rapid switching at threshold boundaries.
-
-```mermaid
-stateDiagram-v2
- direction LR
-
- LOW: 🟢 LOW
price ≤ −10%
- NORMAL: 🟡 NORMAL
−10% … +10%
- HIGH: 🔴 HIGH
price ≥ +10%
-
- LOW --> NORMAL: crosses −8%
(hysteresis)
- NORMAL --> LOW: drops below −10%
- NORMAL --> HIGH: rises above +10%
- HIGH --> NORMAL: crosses +8%
(hysteresis)
-```
-
-> **The 2% gap** between entering (−10%) and leaving (−8%) a state prevents the sensor from flickering back and forth when prices hover near a threshold.
-
-### Available Rating Sensors
-
-| Sensor | Scope | Description |
-|--------|-------|-------------|
-| Current Price Rating | Current interval | Rating of the current 15-minute price |
-| Next Price Rating | Next interval | Rating for the upcoming 15-minute price |
-| Previous Price Rating | Previous interval | Rating for the past 15-minute price |
-| Current Hour Price Rating | Rolling 5-interval | Smoothed rating around the current hour |
-| Next Hour Price Rating | Rolling 5-interval | Smoothed rating around the next hour |
-| Yesterday's Price Rating | Calendar day | Aggregated rating for yesterday |
-| Today's Price Rating | Calendar day | Aggregated rating for today |
-| Tomorrow's Price Rating | Calendar day | Aggregated rating for tomorrow |
-
-### Ratings vs Levels
-
-The integration provides **two** classification systems that serve different purposes:
-
-| | Ratings | Levels |
-|--|---------|--------|
-| **Source** | Calculated by integration | Provided by Tibber API |
-| **Scale** | 3 levels (LOW, NORMAL, HIGH) | 5 levels (VERY_CHEAP → VERY_EXPENSIVE) |
-| **Basis** | Trailing 24h average | Daily min/max range |
-| **Best for** | Automations (simple thresholds) | Dashboard displays (fine granularity) |
-| **Configurable** | Yes (thresholds) | Gap tolerance only |
-| **Automation attribute** | `rating_level` (always lowercase English) | `level` (always uppercase English) |
-
-**Which to use?**
-
-- **Automations**: Use **ratings** (3 simple states, configurable thresholds, hysteresis)
-- **Dashboards**: Use **levels** (5 color-coded states, more visual granularity)
-- **Advanced automations**: Combine both (e.g., "LOW rating AND VERY_CHEAP level")
-
-### Key Attributes
-
-| Attribute | Description | Example |
-|-----------|-------------|---------|
-| `rating_level` | Language-independent rating (always lowercase) | `low` |
-| `difference` | Percentage difference from trailing average | `-12.5` |
-| `trailing_avg_24h` | The reference average used for classification | `22.3` |
-
-### Usage in Automations
-
-**Best Practice:** Always use the `rating_level` attribute (lowercase English) instead of the sensor state (which is translated to your HA language):
-
-```yaml
-# ✅ Correct — language-independent
-condition:
- - condition: template
- value_template: >
- {{ state_attr('sensor._current_price_rating', 'rating_level') == 'low' }}
-
-# ❌ Avoid — breaks when HA language changes
-condition:
- - condition: state
- entity_id: sensor._current_price_rating
- state: "Low" # "Niedrig" in German, "Lav" in Norwegian...
-```
-
-### Configuration
-
-Rating thresholds can be adjusted in the options flow:
-
-1. Go to **Settings → Devices & Services → Tibber Prices → Configure**
-2. Navigate to **Price Rating Thresholds**
-3. Adjust LOW/HIGH thresholds, hysteresis, and gap tolerance
-
-See [Configuration](configuration.md#step-3-price-rating-thresholds) for details.
-
-## Level Sensors
-
-Level sensors show the **Tibber API's own price classification** with a 5-level scale:
-
-| Level | Meaning | Numeric Value |
-|-------|---------|---------------|
-| **VERY_CHEAP** | Exceptionally low | -2 |
-| **CHEAP** | Below average | -1 |
-| **NORMAL** | Typical range | 0 |
-| **EXPENSIVE** | Above average | +1 |
-| **VERY_EXPENSIVE** | Exceptionally high | +2 |
-
-### Available Level Sensors
-
-| Sensor | Scope |
-|--------|-------|
-| Current Price Level | Current interval |
-| Next Price Level | Next interval |
-| Previous Price Level | Previous interval |
-| Current Hour Price Level | Rolling 5-interval window |
-| Next Hour Price Level | Rolling 5-interval window |
-| Yesterday's Price Level | Calendar day (aggregated) |
-| Today's Price Level | Calendar day (aggregated) |
-| Tomorrow's Price Level | Calendar day (aggregated) |
-
-**Gap tolerance** smoothing is applied to prevent isolated level flickers (e.g., a single NORMAL between two CHEAPs → corrected to CHEAP). Configure in [options flow](configuration.md#step-4-price-level-gap-tolerance).
-
-## Min/Max Sensors
-
-These sensors show the lowest and highest prices for calendar days and rolling windows:
-
-### Daily Min/Max
-
-| Sensor | Description |
-|--------|-------------|
-| Today's Lowest Price | Minimum price today (00:00–23:59) |
-| Today's Highest Price | Maximum price today (00:00–23:59) |
-| Tomorrow's Lowest Price | Minimum price tomorrow |
-| Tomorrow's Highest Price | Maximum price tomorrow |
-
-### 24-Hour Rolling Min/Max
-
-| Sensor | Description |
-|--------|-------------|
-| Trailing Price Min | Lowest price in the last 24 hours |
-| Trailing Price Max | Highest price in the last 24 hours |
-| Leading Price Min | Lowest price in the next 24 hours |
-| Leading Price Max | Highest price in the next 24 hours |
-
-### Key Attributes
-
-All min/max sensors include:
-
-| Attribute | Description |
-|-----------|-------------|
-| `timestamp` | When the extreme price occurs/occurred |
-| `price_diff_from_daily_min` | Difference from daily minimum |
-| `price_diff_from_daily_min_%` | Percentage difference |
-
-## Energy Price & Tax Breakdown
-
-Many price sensors expose the **raw energy price** (spot price) and the **tax component** as additional attributes. These are sourced directly from the Tibber API's `energy` and `tax` fields, which together make up the `total` price you see in the sensor state:
-
-`total = energy + tax`
-
-### Where These Attributes Appear
-
-| Sensor Group | Attributes | Description |
-|---|---|---|
-| **Current/Next/Previous Interval Price** | `energy_price`, `tax` | Raw values for that specific 15-minute interval |
-| **Today's/Tomorrow's Min/Max Price** | `energy_price`, `tax` | Values from the interval with the extreme price |
-| **Today's/Tomorrow's Average Price** | `energy_price_mean`, `energy_price_median`, `tax_mean`, `tax_median` | Mean and median values across all intervals of the day |
-
-:::note Transition After Update
-After updating the integration, the `energy_price` and `tax` attributes will appear gradually as new price data is fetched from the Tibber API. Existing cached intervals (up to ~2 days old) won't have these fields yet — the attributes will simply be absent until fresh data replaces them. No action needed.
-:::
-
-### Use Cases
-
-#### Solar Feed-In & Net Metering (Saldering)
-
-In countries like the Netherlands, solar feed-in compensation is based on the **raw energy/spot price**, not the total consumer price. The `energy_price` attribute gives you exactly this value — no more reverse-engineering from the total price with fragile template calculations.
-
-
-Show YAML: Automation — solar export or consume decision
-
-```yaml
-# Example: Decide whether to export solar power or consume it
-# Compare energy price (what you'd earn by exporting) vs. total price (what you'd pay)
-automation:
- - alias: "Solar: Export or Consume"
- trigger:
- - platform: numeric_state
- entity_id: sensor.solar_production_power
- above: 2000 # Producing more than 2 kW
- condition:
- - condition: template
- value_template: >
- {% set energy = state_attr('sensor._current_electricity_price', 'energy_price') %}
- {% set total = states('sensor._current_electricity_price') | float %}
- {# Export when energy price is high relative to total — you earn more #}
- {{ energy is not none and energy > (total * 0.4) }}
- action:
- - service: switch.turn_off
- entity_id: switch.battery_charging # Don't charge battery, export instead
-```
-
-
-
-#### Price Composition Analysis
-
-Understand how your electricity price is structured — useful for comparing across days or spotting trends in market prices vs. fees:
-
-
-Show YAML: Template sensor — electricity tax share percentage
-
-```yaml
-# Template sensor showing tax share
-template:
- - sensor:
- - name: "Electricity Tax Share"
- unit_of_measurement: "%"
- state: >
- {% set tax = state_attr('sensor._current_electricity_price', 'tax') %}
- {% set total = states('sensor._current_electricity_price') | float %}
- {% if tax is not none and total > 0 %}
- {{ ((tax / total) * 100) | round(1) }}
- {% else %}
- unavailable
- {% endif %}
-```
-
-
-
-#### Dashboard: Daily Cost Breakdown
-
-Show users how today's average price splits into energy vs. tax:
-
-```yaml
-# Mushroom chips card showing the split
-type: custom:mushroom-chips-card
-chips:
- - type: template
- icon: mdi:flash
- content: >
- ⚡ {{ state_attr('sensor._price_today', 'energy_price_mean') | round(1) }} ct
- - type: template
- icon: mdi:receipt-text
- content: >
- 🏛️ {{ state_attr('sensor._price_today', 'tax_mean') | round(1) }} ct
-```
-
-### Country-Specific Calculations
-
-The composition of the `tax` field varies by country (Norway, Sweden, Germany, Netherlands each have different fee structures). For detailed examples of how to build country-specific calculations using `input_number` helpers and template sensors — including **Dutch solar feed-in compensation (saldering)** — see the **[Community Examples](community-examples.md#country-specific-price-calculations)** page.
-
-### In Chart Data Actions
-
-The `energy_price` and `tax` fields are also available in the `get_chartdata` action. See [Actions — Energy & Tax Fields](./actions.md#energy--tax-fields-in-get_chartdata) for details.
-
-## Timing Sensors
-
-Timing sensors provide **real-time information about Best Price and Peak Price periods**: when they start, end, how long they last, and your progress through them.
-
-```mermaid
-stateDiagram-v2
- direction LR
-
- IDLE: ⏸️ IDLE
No active period
- ACTIVE: ▶️ ACTIVE
In period
- GRACE: ⏳ GRACE
60s buffer
-
- IDLE --> ACTIVE: period starts
- ACTIVE --> GRACE: period ends
- GRACE --> IDLE: 60s elapsed
- GRACE --> ACTIVE: new period starts
(within grace)
-```
-
-**IDLE** = waiting for next period (shows countdown via `next_in_minutes`). **ACTIVE** = inside a period (shows `progress` 0–100% and `remaining_minutes`). **GRACE** = short buffer after a period ends, allowing back-to-back periods to merge seamlessly.
-
-### Available Timing Sensors
-
-For each period type (Best Price and Peak Price):
-
-| Sensor | When Period Active | When No Active Period |
-|--------|-------------------|----------------------|
-| End Time | Current period's end time | Next period's end time |
-| Period Duration | Current period length (minutes) | Next period length |
-| Remaining Minutes | Minutes until current period ends | 0 |
-| Progress | 0–100% through current period | 0 |
-| Next Start Time | When next-next period starts | When next period starts |
-| Next In Minutes | Minutes to next-next period | Minutes to next period |
-
-### Usage Examples
-
-**Show countdown to next cheap window:**
-
-```yaml
-type: custom:mushroom-entity-card
-entity: sensor._best_price_next_in_minutes
-name: Next Cheap Window
-icon: mdi:clock-fast
-```
-
-**Display period progress bar:**
-
-
-Show YAML: Bar card for period progress
-
-```yaml
-type: custom:bar-card
-entity: sensor._best_price_progress
-name: Best Price Progress
-min: 0
-max: 100
-severity:
- - from: 0
- to: 50
- color: green
- - from: 50
- to: 80
- color: orange
- - from: 80
- to: 100
- color: red
-```
-
-
-
-**Automation: notify when period is almost over:**
-
-
-Show YAML: Automation — notify when best price period is ending
-
-```yaml
-automation:
- - alias: "Warn: Best Price Ending Soon"
- trigger:
- - platform: numeric_state
- entity_id: sensor._best_price_remaining_minutes
- below: 15
- condition:
- - condition: numeric_state
- entity_id: sensor._best_price_remaining_minutes
- above: 0
- action:
- - service: notify.mobile_app
- data:
- title: "Best Price Ending Soon"
- message: "Only {{ states('sensor._best_price_remaining_minutes') }} minutes left!"
-```
-
-
-
-## Trend Sensors
-
-Trend sensors help you understand **whether to act now or wait**. The integration provides two complementary families:
-
-- **Price Outlook Sensors (1h–12h):** Compare current price vs. future window average — "Is now cheaper than the next Nh on average?"
-- **Price Trajectory Sensors (2h–12h):** Compare first half vs. second half of the window — "Are prices rising or falling *within* the window?"
-
-### Price Outlook Sensors (1h–12h)
-
-These sensors compare the **current price** with the **average price** of the next N hours:
-
-| Sensor | Compares Against |
-|--------|-----------------|
-| **Price Outlook (1h)** (`price_outlook_1h`) | Average of next 1 hour |
-| **Price Outlook (2h)** (`price_outlook_2h`) | Average of next 2 hours |
-| **Price Outlook (3h)** (`price_outlook_3h`) | Average of next 3 hours |
-| **Price Outlook (4h)** (`price_outlook_4h`) | Average of next 4 hours |
-| **Price Outlook (5h)** (`price_outlook_5h`) | Average of next 5 hours |
-| **Price Outlook (6h)** (`price_outlook_6h`) | Average of next 6 hours |
-| **Price Outlook (8h)** (`price_outlook_8h`) | Average of next 8 hours |
-| **Price Outlook (12h)** (`price_outlook_12h`) | Average of next 12 hours |
-
-:::info Same Starting Point — All Outlook Sensors Use Your Current Price
-All outlook sensors share the **same base: your current 15-minute price**. They differ only in how far ahead they average. The windows **overlap** — the 3h average includes ALL intervals from the 1h and 2h windows, plus one more hour.
-
-**This means:**
-- `price_outlook_3h` shows "current price vs. average of the **entire** next 3 hours" — **not** "what happens between hour 2 and hour 3"
-- If 1h shows `falling` but 6h shows `rising`: near-term prices are below your current price, but looking at the full 6h window (which includes expensive evening hours), the overall average is above your current price
-- Larger windows smooth out short-term fluctuations — a 30-minute price spike affects the 1h average more than the 6h average
-
-**⚠️ At a price minimum, outlook sensors can be misleading!** If you're at the minimum and prices are about to rise, `price_outlook_3h` may still show `strongly_falling` because the cheap minimum pulls the 3h average below your current high price. Use `price_trajectory_3h` to see the direction *within* the window.
-:::
-
-**States:** Each sensor has one of five states:
-
-```mermaid
-stateDiagram-v2
- direction LR
-
- SF: ⬇️⬇️ strongly_falling
−2 · future ≤ −9%
- F: ⬇️ falling
−1 · future ≤ −3%
- S: ➡️ stable
0 · within ±3%
- R: ⬆️ rising
+1 · future ≥ +3%
- SR: ⬆️⬆️ strongly_rising
+2 · future ≥ +9%
-
- SF --> F: price recovers
- F --> S: approaches average
- S --> R: future rises
- R --> SR: accelerates
- SR --> R: slows down
- R --> S: stabilizes
- S --> F: future drops
- F --> SF: accelerates
-```
-
-| State | Meaning | `trend_value` |
-|-------|---------|---------------|
-| `strongly_falling` | Prices will drop significantly | -2 |
-| `falling` | Prices will drop | -1 |
-| `stable` | Prices staying roughly the same | 0 |
-| `rising` | Prices will increase | +1 |
-| `strongly_rising` | Prices will increase significantly | +2 |
-
-**Key attributes:**
-
-| Attribute | Description | Example |
-|-----------|-------------|---------|
-| `trend_value` | Numeric value for automations (-2 to +2) | `-1` |
-| `trend_Nh_%` | Percentage difference from current price | `-12.3` |
-| `next_Nh_avg` | Average price in the future window | `18.5` |
-| `second_half_Nh_avg` | Average price in later half of window | `16.2` |
-| `threshold_rising_%` | Active rising threshold after volatility adjustment | `3.0` |
-| `threshold_rising_strongly_%` | Active strongly-rising threshold after volatility adjustment | `4.8` |
-| `threshold_falling_%` | Active falling threshold after volatility adjustment | `-3.0` |
-| `threshold_falling_strongly_%` | Active strongly-falling threshold after volatility adjustment | `-4.8` |
-| `volatility_factor` | Applied multiplier (0.6 = low, 1.0 = moderate, 1.4 = high volatility) | `0.8` |
-
-**Tip:** The `trend_value` attribute (`-2` to `+2`) is ideal for automations — use numeric comparisons instead of matching translated state strings.
-
-### Price Trajectory Sensors (2h–12h)
-
-These sensors compare the **first half** of the future window against the **second half** — revealing the price *direction within* the window.
-
-| Sensor | Compares |
-|--------|----------|
-| **Price Trajectory (2h)** (`price_trajectory_2h`) | Avg of hour 1 vs avg of hour 2 |
-| **Price Trajectory (3h)** (`price_trajectory_3h`) | Avg of first 1.5h vs avg of second 1.5h |
-| **Price Trajectory (4h)** (`price_trajectory_4h`) | Avg of first 2h vs avg of second 2h |
-| **Price Trajectory (5h)** (`price_trajectory_5h`) | Avg of first 2.5h vs avg of second 2.5h |
-| **Price Trajectory (6h)** (`price_trajectory_6h`) | Avg of first 3h vs avg of second 3h |
-| **Price Trajectory (8h)** (`price_trajectory_8h`) | Avg of first 4h vs avg of second 4h |
-| **Price Trajectory (12h)** (`price_trajectory_12h`) | Avg of first 6h vs avg of second 6h |
-
-**States:** Same 5-level scale as outlook sensors (`strongly_falling` → `strongly_rising`).
-
-:::info Why trajectory sensors complement outlook sensors
-**At a price minimum** — the exact moment you should act — `price_outlook_3h` may show `strongly_falling` because the cheap minimum pulls the entire 3h average below your current high price. But `price_trajectory_3h` shows `rising` because the second half (after the minimum) is more expensive than the first half.
-
-| Combination | Interpretation |
-|-------------|----------------|
-| Outlook `falling` + Trajectory `rising` | **You're AT the minimum** — act now |
-| Outlook `falling` + Trajectory `falling` | Prices still dropping — wait |
-| Outlook `rising` + Trajectory `rising` | Strong signal to act now |
-| Outlook `rising` + Trajectory `falling` | Short spike, then cheaper — wait |
-:::
-
-**Key attributes:**
-
-| Attribute | Description | Example |
-|-----------|-------------|---------|
-| `trend_value` | Numeric value for automations (-2 to +2) | `1` |
-| `first_half_avg` | Average price in first half of window | `12.4` |
-| `second_half_avg` | Average price in second half of window | `18.1` |
-| `half_diff_%` | Percentage difference (second vs first half) | `46.0` |
-
-### Current Price Trend
-
-**Entity ID:** `sensor._current_price_trend`
-
-This sensor shows the **currently active trend direction** based on a 3-hour future outlook with volatility-adaptive thresholds.
-
-Unlike the simple trend sensors that always compare current price vs future average, the current price trend represents the **ongoing trend** — it remains stable between updates and only changes when the underlying price direction actually shifts.
-
-**States:** Same 5-level scale as simple trends.
-
-**Key attributes:**
-
-| Attribute | Description | Example |
-|-----------|-------------|---------|
-| `previous_direction` | Price direction before the current trend started | `falling` |
-| `price_direction_duration_minutes` | How long prices have been moving in this direction | `45` |
-| `price_direction_since` | Timestamp when prices started moving in this direction | `2025-11-08T14:00:00+01:00` |
-
-### Next Price Trend Change
-
-**Entity ID:** `sensor._next_price_trend_change`
-
-This sensor predicts **when the current trend will change** by scanning future intervals. It requires 3 consecutive intervals (configurable: 2–6) confirming the new trend before reporting a change (hysteresis), which prevents false alarms from short-lived price spikes.
-
-**Important:** Only **direction changes** count as trend changes. The five states are grouped into three directions:
-
-| Direction | States |
-|-----------|--------|
-| **falling** | `strongly_falling`, `falling` |
-| **stable** | `stable` |
-| **rising** | `rising`, `strongly_rising` |
-
-A change from `rising` to `strongly_rising` (same direction) is **not** reported as a trend change — only actual reversals like `rising` → `stable` or `falling` → `rising`.
-
-**State:** Timestamp of the next trend change (or unavailable if no change predicted).
-
-**Key attributes:**
-
-| Attribute | Description | Example |
-|-----------|-------------|---------|
-| `direction` | What the trend will change TO | `rising` |
-| `from_direction` | Current trend (will change FROM) | `falling` |
-| `minutes_until_change` | Minutes until trend changes | `90` |
-| `price_at_change` | Price at the change point | `13.8` |
-| `price_avg_after_change` | Average price after change | `18.1` |
-| `threshold_rising_%` | Active rising threshold after volatility adjustment | `3.0` |
-| `threshold_rising_strongly_%` | Active strongly-rising threshold after volatility adjustment | `4.8` |
-| `threshold_falling_%` | Active falling threshold after volatility adjustment | `-3.0` |
-| `threshold_falling_strongly_%` | Active strongly-falling threshold after volatility adjustment | `-4.8` |
-| `volatility_factor` | Applied multiplier (0.6 = low, 1.0 = moderate, 1.4 = high volatility) | `0.8` |
-
-### How to Use Trend Sensors for Decisions
-
-:::danger Common Misconception — Don't "Wait for Stable"!
-A natural intuition is to treat trend states like a stock ticker:
-
-- ❌ "It's **falling** → I'll wait until it reaches **stable** (the bottom)"
-- ❌ "It's **rising** → too late, I missed the best price"
-- ❌ "It's **stable** → now is the perfect time to act!"
-
-**This is wrong.** Trend sensors don't show a trajectory — they show a **comparison** between your current price and future prices. The correct interpretation is the opposite:
-
-| State | What the Sensor Calculates | ✅ Correct Action |
-|-------|---------------------------|-------------------|
-| `falling` | Current price **higher** than future average | **WAIT** — cheaper prices are coming |
-| `strongly_falling` | Current price **much higher** than future average | **DEFINITELY WAIT** — significant savings ahead |
-| `stable` | Current price **≈ equal** to future average | **Timing doesn't matter** — start whenever convenient |
-| `rising` | Current price **lower** than future average | **ACT NOW** — it only gets more expensive |
-| `strongly_rising` | Current price **much lower** than future average | **ACT IMMEDIATELY** — best price right now |
-
-**"Rising" is NOT "too late" — it means NOW is the best time because prices will be higher later.**
-:::
-
-#### Basic Automation Pattern
-
-For most appliances (dishwasher, washing machine, dryer), a single outlook sensor is enough:
-
-```yaml
-# Example: Start dishwasher when prices are favorable
-trigger:
- - platform: state
- entity_id: sensor.my_home_price_outlook_3h
-condition:
- - condition: numeric_state
- entity_id: sensor.my_home_price_outlook_3h
- attribute: trend_value
- # rising (1) or strongly_rising (2) = act now
- above: 0
-action:
- - service: switch.turn_on
- target:
- entity_id: switch.dishwasher
-```
-
-#### Combining Multiple Windows
-
-When short-term and long-term trends disagree, you get richer insight:
-
-| 1h Outlook | 6h Outlook | Interpretation | Recommendation |
-|----------|----------|---------------|----------------|
-| `rising` | `rising` | Prices going up across the board | **Start now** |
-| `falling` | `falling` | Prices dropping across the board | **Wait** |
-| `falling` | `rising` | Brief dip, then expensive evening | **Wait briefly**, then start during the dip |
-| `rising` | `falling` | Short spike, but cheaper hours ahead | **Wait** if you can — better prices coming |
-| `stable` | any | Short-term doesn't matter | Use the **longer window** for your decision |
-
-#### Dashboard Quick-Glance
-
-On your dashboard, trend sensors give an instant overview:
-
-- 🟢 All **falling/strongly_falling** → "Relax, prices are dropping — wait"
-- 🔴 All **rising/strongly_rising** → "Start everything you can — it only gets more expensive"
-- 🟡 **Mixed** → Compare short-term vs. long-term sensors, or check the Best Price Period sensor
-
-### Outlook & Trajectory Sensors vs Average Sensors
-
-Both sensor families provide future price information, but serve different purposes:
-
-| | Outlook/Trajectory Sensors | Average Sensors |
-|--|---------------------------|-----------------|
-| **Purpose** | Dashboard display, quick visual overview | Automations, precise numeric comparisons |
-| **Output** | Classification (falling/stable/rising) | Exact price values (ct/kWh) |
-| **Best for** | "Should I worry about prices?" | "Is the future average below 15 ct?" |
-| **Use in** | Dashboard icons, status displays | Template conditions, numeric thresholds |
-
-**Design principle:** Use **trend sensors** (enum) for visual feedback at a glance, use **average sensors** (numeric) for precise decision-making in automations.
-
-### Configuration
-
-Trend thresholds can be adjusted in the options flow:
-
-1. Go to **Settings → Devices & Services → Tibber Prices**
-2. Click **Configure** on your home
-3. Navigate to **📈 Price Trend Thresholds**
-4. Adjust the rising/falling and strongly rising/falling percentages
-
-The thresholds are **volatility-adaptive**: on days with high price volatility, thresholds are widened automatically to prevent constant state changes. This means the trend sensors give more stable readings during volatile market conditions.
-
-## Diagnostic Sensors
-
-### Chart Metadata
-
-**Entity ID:** `sensor._chart_metadata`
-
-> **✨ New Feature**: This sensor provides dynamic chart configuration metadata for optimal visualization. Perfect for use with the `get_apexcharts_yaml` action!
-
-This diagnostic sensor provides essential chart configuration values as sensor attributes, enabling dynamic Y-axis scaling and optimal chart appearance in rolling window modes.
-
-**Key Features:**
-
-- **Dynamic Y-Axis Bounds**: Automatically calculates optimal `yaxis_min` and `yaxis_max` for your price data
-- **Automatic Updates**: Refreshes when price data changes (coordinator updates)
-- **Lightweight**: Metadata-only mode (no data processing) for fast response
-- **State Indicator**: Shows `pending` (initialization), `ready` (data available), or `error` (service call failed)
-
-**Attributes:**
-
-- **`timestamp`**: When the metadata was last fetched
-- **`yaxis_min`**: Suggested minimum value for Y-axis (optimal scaling)
-- **`yaxis_max`**: Suggested maximum value for Y-axis (optimal scaling)
-- **`currency`**: Currency code (e.g., "EUR", "NOK")
-- **`resolution`**: Interval duration in minutes (usually 15)
-- **`error`**: Error message if service call failed
-
-**Usage:**
-
-The `tibber_prices.get_apexcharts_yaml` action **automatically uses this sensor** for dynamic Y-axis scaling in `rolling_window` and `rolling_window_autozoom` modes! No manual configuration needed - just enable the action's result with `config-template-card` and the sensor provides optimal Y-axis bounds automatically.
-
-See the **[Chart Examples Guide](chart-examples.md)** for practical examples!
-
----
-
-### Chart Data Export
-
-**Entity ID:** `sensor._chart_data_export`
-**Default State:** Disabled (must be manually enabled)
-
-> **⚠️ Legacy Feature**: This sensor is maintained for backward compatibility. For new integrations, use the **`tibber_prices.get_chartdata`** service instead, which offers more flexibility and better performance.
-
-This diagnostic sensor provides cached chart-friendly price data that can be consumed by chart cards (ApexCharts, custom cards, etc.).
-
-**Key Features:**
-
-- **Configurable via Options Flow**: Service parameters can be configured through the integration's options menu (Step 7 of 7)
-- **Automatic Updates**: Data refreshes on coordinator updates (every 15 minutes)
-- **Attribute-Based Output**: Chart data is stored in sensor attributes for easy access
-- **State Indicator**: Shows `pending` (before first call), `ready` (data available), or `error` (service call failed)
-
-**Important Notes:**
-
-- ⚠️ Disabled by default - must be manually enabled in entity settings
-- ⚠️ Consider using the service instead for better control and flexibility
-- ⚠️ Configuration updates require HA restart
-
-**Attributes:**
-
-The sensor exposes chart data with metadata in attributes:
-
-- **`timestamp`**: When the data was last fetched
-- **`error`**: Error message if service call failed
-- **`data`** (or custom name): Array of price data points in configured format
-
-**Configuration:**
-
-To configure the sensor's output format:
-
-1. Go to **Settings → Devices & Services → Tibber Prices**
-2. Click **Configure** on your Tibber home
-3. Navigate through the options wizard to **Step 7: Chart Data Export Settings**
-4. Configure output format, filters, field names, and other options
-5. Save and restart Home Assistant
-
-**Available Settings:**
-
-See the `tibber_prices.get_chartdata` service documentation below for a complete list of available parameters. All service parameters can be configured through the options flow.
-
-**Example Usage:**
-
-```yaml
-# ApexCharts card consuming the sensor
-type: custom:apexcharts-card
-series:
- - entity: sensor._chart_data_export
- data_generator: |
- return entity.attributes.data;
-```
-
-**Migration Path:**
-
-If you're currently using this sensor, consider migrating to the service:
-
-```yaml
-# Old approach (sensor)
-- service: apexcharts_card.update
- data:
- entity: sensor._chart_data_export
-
-# New approach (service)
-- service: tibber_prices.get_chartdata
- data:
- entry_id: YOUR_CONFIG_ENTRY_ID
- day: ["today", "tomorrow"]
- output_format: array_of_objects
- response_variable: chart_data
-```
diff --git a/docs/user/sidebars.ts b/docs/user/sidebars.ts
index 2c6ca8f..dbcd3d9 100644
--- a/docs/user/sidebars.ts
+++ b/docs/user/sidebars.ts
@@ -31,25 +31,47 @@ const sidebars: SidebarsConfig = {
},
{
type: 'category',
- label: '📊 Features',
- items: ['sensors', 'sensor-reference', 'period-calculation', 'dynamic-icons', 'icon-colors', 'actions'],
+ label: '📊 Sensors',
+ items: [
+ 'sensors-overview',
+ 'sensors-average',
+ 'sensors-ratings-levels',
+ 'sensors-volatility',
+ 'sensors-trends',
+ 'sensors-timing',
+ 'sensors-energy-tax',
+ ],
collapsible: true,
collapsed: false,
},
{
type: 'category',
- label: '🎨 Visualization',
- items: ['dashboard-examples', 'chart-examples'],
+ label: '⏰ Price Periods',
+ items: ['period-calculation', 'period-relaxation'],
collapsible: true,
collapsed: false,
},
{
type: 'category',
- label: '🤖 Automation',
+ label: '🎨 Dashboards & Charts',
+ items: ['dynamic-icons', 'icon-colors', 'dashboard-examples', 'chart-examples'],
+ collapsible: true,
+ collapsed: false,
+ },
+ {
+ type: 'category',
+ label: '🤖 Automations',
items: ['automation-examples'],
collapsible: true,
collapsed: false,
},
+ {
+ type: 'category',
+ label: '📖 Reference',
+ items: ['sensor-reference', 'actions'],
+ collapsible: true,
+ collapsed: false,
+ },
{
type: 'category',
label: '👥 Community',
diff --git a/docs/user/src/components/EntitySearch.tsx b/docs/user/src/components/EntitySearch.tsx
index 2de5b9f..be0d27d 100644
--- a/docs/user/src/components/EntitySearch.tsx
+++ b/docs/user/src/components/EntitySearch.tsx
@@ -27,9 +27,16 @@ const MAX_RESULTS = 12;
/** Display names for doc page back-links (from data-refs attribute). */
const DOC_NAMES: Record = {
- sensors: 'Sensors Guide',
+ 'sensors-overview': 'Sensors Overview',
+ 'sensors-average': 'Average Sensors',
+ 'sensors-ratings-levels': 'Ratings & Levels',
+ 'sensors-volatility': 'Volatility',
+ 'sensors-trends': 'Trends',
+ 'sensors-timing': 'Timing',
+ 'sensors-energy-tax': 'Energy & Tax',
configuration: 'Configuration',
'period-calculation': 'Period Calculation',
+ 'period-relaxation': 'Relaxation',
'automation-examples': 'Automation Examples',
actions: 'Actions',
};
@@ -151,9 +158,10 @@ export default function EntitySearch(): React.ReactElement {
if (docRefs.length > 0 && firstCell && !firstCell.querySelector('.entity-back-links')) {
const span = document.createElement('span');
span.className = 'entity-back-links';
- docRefs.forEach((slug) => {
+ docRefs.forEach((ref) => {
+ const slug = ref.split('#')[0];
const a = document.createElement('a');
- a.href = slug;
+ a.href = ref;
a.className = 'entity-back-link';
a.title = DOC_NAMES[slug] ?? slug;
a.setAttribute('aria-label', `View in: ${DOC_NAMES[slug] ?? slug}`);
diff --git a/scripts/docs/generate-sensor-reference b/scripts/docs/generate-sensor-reference
index eaacfb0..c7ba21c 100755
--- a/scripts/docs/generate-sensor-reference
+++ b/scripts/docs/generate-sensor-reference
@@ -337,37 +337,66 @@ def load_all_disabled() -> dict[str, set[str]]:
return result
+def _heading_to_anchor(heading_text: str) -> str:
+ """Convert a Markdown heading to a Docusaurus-style anchor slug."""
+ text = heading_text.strip().lower()
+ # Remove inline code backticks and common Markdown formatting
+ text = re.sub(r"[`*_]", "", text)
+ # Replace non-alphanumeric (except hyphens) with hyphens
+ text = re.sub(r"[^a-z0-9-]+", "-", text)
+ # Collapse multiple hyphens and strip leading/trailing hyphens
+ return re.sub(r"-{2,}", "-", text).strip("-")
+
+
def scan_doc_refs() -> dict[str, list[str]]:
"""
Scan doc markdown files for EntityRef usage.
- Returns: {entity_key: [doc_slug, ...]}
+ Returns: {entity_key: [doc_slug#anchor, ...]}
+ Each value includes the section anchor of the nearest heading above the EntityRef.
"""
refs: dict[str, list[str]] = {}
docs_dir = REPO_ROOT / "docs" / "user" / "docs"
entity_ref_pattern = re.compile(r']*?\bid="([^"]+)"')
also_pattern = re.compile(r'\balso="([^"]+)"')
+ heading_pattern = re.compile(r"^(#{2,6})\s+(.+)$", re.MULTILINE)
for md_file in sorted(docs_dir.glob("*.md")):
if md_file.name == "sensor-reference.md":
continue
slug = md_file.stem
text = md_file.read_text(encoding="utf-8")
+
+ # Build list of (position, anchor) for all headings in this file
+ headings: list[tuple[int, str]] = [
+ (h_match.start(), _heading_to_anchor(h_match.group(2))) for h_match in heading_pattern.finditer(text)
+ ]
+
+ def _ref_with_anchor(pos: int, *, _headings: list[tuple[int, str]] = headings, _slug: str = slug) -> str:
+ """Return 'slug#anchor' for the nearest heading above pos."""
+ anchor = ""
+ for h_pos, h_anchor in reversed(_headings):
+ if h_pos < pos:
+ anchor = h_anchor
+ break
+ return f"{_slug}#{anchor}" if anchor else _slug
+
+ def _add_ref(key: str, ref: str) -> None:
+ refs.setdefault(key, [])
+ if ref not in refs[key]:
+ refs[key].append(ref)
+
for match in entity_ref_pattern.finditer(text):
key = match.group(1)
- refs.setdefault(key, [])
- if slug not in refs[key]:
- refs[key].append(slug)
+ ref = _ref_with_anchor(match.start())
+ _add_ref(key, ref)
# Check for 'also' prop in the same tag
tag_end = text.find(">", match.start())
if tag_end != -1:
tag_text = text[match.start() : tag_end]
also_match = also_pattern.search(tag_text)
if also_match:
- also_key = also_match.group(1)
- refs.setdefault(also_key, [])
- if slug not in refs[also_key]:
- refs[also_key].append(slug)
+ _add_ref(also_match.group(1), ref)
return refs
@@ -411,7 +440,7 @@ You can also use your browser's built-in search (**Ctrl+F** / **Cmd+F**) to sear
Sensors marked ❌ must be enabled manually via
**Settings → Devices & Services → Entities** → find the entity → toggle **Enabled**.
-**Detailed documentation:** See the **[Sensors Guide](sensors.md)** for detailed
+**Detailed documentation:** See the **[Sensors Overview](sensors-overview.md)** for detailed
explanations of each sensor's purpose, attributes, and automation examples.
---