@@ -162,10 +162,23 @@ The first selected source becomes your highest priority, and the integration wil
162162- ** Rate limiting** - Minimum 15-minute intervals
163163- ** Automatic retries** - Exponential backoff for failed requests (2s → 6s → 18s)
164164- ** Data caching** - Persistent storage with TTL
165- - ** Source fallback** - Try all sources in priority order
165+ - ** Intelligent interval validation** - DST-aware validation ensures complete data:
166+ - ** Normal days** : Expects 96 intervals (15-min × 96 = 24 hours)
167+ - ** DST spring forward** : Expects 92 intervals (23 hours)
168+ - ** DST fall back** : Expects 100 intervals (25 hours)
169+ - ** Strict validation** : Allows only 1 missing interval (15 minutes) tolerance
170+ - ** Automatic fallback** : Switches to alternative sources when data is incomplete
171+ - ** Source fallback** - Try all sources in priority order until complete data is found
166172- ** Daily health check** - All configured sources validated once per day during special windows
167173- ** Source health monitoring** - Track which sources are working vs failed, with retry schedules
168174
175+ ** Example:** If ENTSO-E returns 94/96 intervals (missing 30 minutes), the system automatically:
176+ 1 . Detects incomplete data (94 < 95 minimum required)
177+ 2 . Logs warning about missing intervals
178+ 3 . Tries next configured source (e.g., Energy Charts)
179+ 4 . Uses complete data from working source
180+ 5 . Caches complete result for future requests
181+
169182## Architecture
170183
171184** Data Flow:** API Client → Parser → Timezone Conversion → Currency Conversion → Cache → Sensors
@@ -178,7 +191,12 @@ The first selected source becomes your highest priority, and the integration wil
178191### Timezone & Interval Handling
179192
180193- ** Source timezone detection** - Each API has known timezone behavior
181- - ** DST transitions** - Handles 92-100 intervals on transition days
194+ - ** DST transitions** - Handles 92-100 intervals on transition days automatically
195+ - ** Interval validation** - Ensures data completeness before acceptance:
196+ - Validates exact interval count matches expected (92/96/100 depending on DST)
197+ - Tolerates 1 missing interval (15 minutes) for API timing edge cases
198+ - Rejects incomplete data (2+ missing intervals = 30+ minutes)
199+ - Automatically tries alternative sources when primary source is incomplete
182200- ** 15-minute alignment** - All data normalized to :00, :15, :30, :45 boundaries
183201- ** Home Assistant integration** - Displays in your configured timezone
184202
@@ -328,41 +346,62 @@ The price sensors expose interval prices through attributes in a standardized fo
328346` ` ` json
329347{
330348 " today_interval_prices " : [
331- {"time": "2025-10-14T00:00:00+02:00", "value": 0.0856},
332- {"time": "2025-10-14T00:15:00+02:00", "value": 0.0842},
349+ {"time": "2025-10-14T00:00:00+02:00", "value": 0.0856, "raw_value": 0.0754 },
350+ {"time": "2025-10-14T00:15:00+02:00", "value": 0.0842, "raw_value": 0.0740 },
333351 ...
334352 ],
335353 " tomorrow_interval_prices " : [
336- {"time": "2025-10-15T00:00:00+02:00", "value": 0.0891},
354+ {"time": "2025-10-15T00:00:00+02:00", "value": 0.0891, "raw_value": 0.0789 },
337355 ...
338356 ]
339357}
340358```
341359
342360** Key Points:**
343- - Each price entry contains a ` time ` (ISO 8601 datetime string) and ` value ` (float)
344- - Times are in your Home Assistant's configured timezone
361+ - Each price entry contains:
362+ - ` time ` : ISO 8601 datetime string in your Home Assistant timezone
363+ - ` value ` : Final consumer price (with VAT, tariffs, and energy taxes applied)
364+ - ` raw_value ` : Market spot price (currency and unit converted only, no VAT/fees) _ (New in v1.6.0)_
345365- List contains 96 entries for a normal day (15-minute intervals)
346366- During DST transitions: 92 entries (spring) or 100 entries (fall)
347367- Compatible with EV Smart Charging, ApexCharts, and custom automations
348368
369+ ** Price Calculation:**
370+ ```
371+ value = ((raw_value + additional_tariff + energy_tax) × (1 + VAT%)) × display_unit_multiplier
372+ ```
373+
374+ When no VAT, tariffs, or taxes are configured, ` raw_value ` equals ` value ` .
375+
349376** Using in Templates:**
350377``` yaml
351- # Get price at 14:00
378+ # Get final consumer price at 14:00
352379{{ state_attr('sensor.gespot_current_price_se3', 'today_interval_prices')
353380 | selectattr('time', 'search', 'T14:00')
354381 | map(attribute='value')
355382 | first }}
356383
384+ # Get raw market price at 14:00 (without VAT/fees)
385+ {{ state_attr('sensor.gespot_current_price_se3', 'today_interval_prices')
386+ | selectattr('time', 'search', 'T14:00')
387+ | map(attribute='raw_value')
388+ | first }}
389+
357390# Get all prices above 0.10
358391{{ state_attr('sensor.gespot_current_price_se3', 'today_interval_prices')
359392 | map(attribute='value')
360393 | select('>', 0.10)
361394 | list }}
362395
363- # Count hours with negative prices
396+ # Compare market prices to final prices
397+ {% set prices = state_attr('sensor.gespot_current_price_se3', 'today_interval_prices') %}
398+ Market avg : {{ prices | map(attribute='raw_value') | average | round(4) }}
399+ Final avg : {{ prices | map(attribute='value') | average | round(4) }}
400+ Difference : {{ ((prices | map(attribute='value') | average) - (prices | map(attribute='raw_value') | average)) | round(4) }}
401+
402+ # Count hours with negative prices (on market)
364403{{ state_attr('sensor.gespot_current_price_se3', 'today_interval_prices')
365- | map(attribute='value ')
404+ | map(attribute='raw_value ')
366405 | select('<', 0)
367406 | list
368407 | length }}
@@ -404,7 +443,12 @@ Then set this sensor as your energy cost sensor in the Energy Dashboard settings
404443- **No data** - Check area is supported by selected source
405444- **API key errors** - Verify ENTSO-E API key if using that source
406445- **Missing tomorrow prices** - Available after 13:00 CET daily
407- - **96 data points** - Correct! 15-minute intervals = 96 per day
446+ - **96 data points** - Correct! 15-minute intervals = 96 per day (92 on DST spring, 100 on DST fall)
447+ - **Incomplete data warnings** - If you see warnings about incomplete intervals:
448+ - System automatically tries alternative sources
449+ - Check ` active_source` in sensor attributes to see which source is being used
450+ - Configure multiple sources for better reliability
451+ - Example : ` [NL] Incomplete today data from entsoe: 94/96 intervals (missing 2)` → System switches to Energy Charts
408452
409453**Source Health Monitoring:**
410454
0 commit comments