Added two new rolling window options for get_apexcharts_yaml service to provide
flexible dynamic chart visualization:
- rolling_window: Fixed 48h window that automatically shifts between
yesterday+today and today+tomorrow based on data availability
- rolling_window_autozoom: Same as rolling_window but with progressive zoom-in
(2h lookback + remaining time until midnight, updates every 15min)
Implementation changes:
- Updated service schema validation to accept new day options
- Added entity mapping patterns for both rolling modes
- Implemented minute-based graph_span calculation with quarter-hour alignment
- Added config-template-card integration for dynamic span updates
- Used current_interval_price sensor as 15-minute update trigger
- Unified data loading: both rolling modes omit day parameter for dynamic selection
- Applied ternary operator pattern for cleaner day_param logic
- Made grid lines more subtle (borderColor #f5f5f5, strokeDashArray 0)
Translation updates:
- Added selector options in all 5 languages (de, en, nb, nl, sv)
- Updated field descriptions to include default behavior and new options
- Documented that rolling window is default when day parameter omitted
Documentation updates:
- Updated user docs (actions.md, automation-examples.md) with new options
- Added detailed explanation of day parameter options
- Included examples for both rolling_window and rolling_window_autozoom modes
Impact: Users can now create auto-adapting ApexCharts that show 48h rolling
windows with optional progressive zoom throughout the day. Requires
config-template-card for dynamic behavior.
Period data in array_of_arrays format now generates proper segment structure
for stepline charts. Each period produces 2-3 data points depending on
insert_nulls parameter:
1. Start time with price (begin period)
2. End time with price (hold price level)
3. End time with NULL (terminate segment, only if insert_nulls='segments'/'all')
This enables ApexCharts to correctly display periods as continuous blocks with
clean gaps between them. Previously only start point was generated, causing
periods to render as single points instead of continuous segments.
Changes:
- formatters.py: Updated get_period_data() to generate 2-3 points per period
- formatters.py: Added insert_nulls parameter to control NULL termination
- get_chartdata.py: Pass insert_nulls parameter to get_period_data()
- get_apexcharts_yaml.py: Set insert_nulls='segments' for period overlay
- get_apexcharts_yaml.py: Preserve NULL values in data_generator mapping
- get_apexcharts_yaml.py: Store original price for potential tooltip access
- tests: Added comprehensive period data format tests
Impact: Best price and peak price period overlays now display correctly as
continuous blocks with proper segment separation in ApexCharts cards.
Release workflow now automatically deletes tags when version number doesn't
match commit types (e.g., PATCH bump when MINOR needed for features).
Changes:
- New step 'Delete inappropriate version tag' runs after version_check
- Automatically deletes tag and exits with error if version inappropriate
- All subsequent steps conditional on successful version validation
- Improved warning message: removed confusing 'X.Y.Z' placeholder
- Added notice: 'This tag will be automatically deleted in the next step'
- Removed redundant 'Version Check Summary' step
Impact: Users get immediate, clear feedback when pushing wrong version tags.
Workflow fails fast with actionable error message instead of creating release
with embedded warning. No manual tag deletion needed.
Binary sensor _handle_coordinator_update() was empty, blocking all push updates
from coordinator. This prevented binary sensors from reflecting state changes
immediately after API fetch or error conditions.
Changes:
- Implement _handle_coordinator_update() to call async_write_ha_state()
- All binary sensors now receive push updates when coordinator has new data
Binary sensors affected:
- tomorrow_data_available: Now reflects data availability immediately after API fetch
- connection: Now shows disconnected state immediately on auth/API errors
- chart_data_export: Now updates chart data when price data changes
- peak_price_period, best_price_period: Get push updates when periods change
- data_lifecycle_status: Gets push updates on status changes
Impact: Binary sensors update in real-time instead of waiting for next timer
cycle or user interaction. Fixes stale state issue where tomorrow_data_available
remained off despite data being available, and connection sensor not reflecting
authentication failures immediately.
Restructured 5 options flow steps (current_interval_price_rating, best_price,
peak_price, price_trend, volatility) to use Home Assistant's sections feature
for better UI organization and logical grouping.
Changes:
- current_interval_price_rating: Single section "price_rating_thresholds"
- best_price: Three sections (period_settings, flexibility_settings,
relaxation_and_target_periods)
- peak_price: Three sections (period_settings, flexibility_settings,
relaxation_and_target_periods)
- price_trend: Single section "price_trend_thresholds"
- volatility: Single section "volatility_thresholds"
Each section includes name, description, data fields, and data_description
fields following HA translation schema requirements.
Updated all 5 language files (de, en, nb, nl, sv) with new section structure
while preserving existing field descriptions and translations.
Impact: Options flow now displays configuration fields in collapsible,
logically grouped sections with clear section headers, improving UX for
complex multi-parameter configuration steps. No functional changes to
configuration logic or validation.
Implement _is_fetching flag to show "refreshing" status during API calls,
and fix needs_tomorrow_data() to recognize single-home cache format.
Changes:
- Set _is_fetching flag before API call, reset after completion (core.py)
- Fix needs_tomorrow_data() to check for "price_info" key instead of "homes"
- Remove redundant "homes" check in should_update_price_data()
- Improve logging: change debug to info for tomorrow data checks
Lifecycle status now correctly transitions after 13:00 when tomorrow data
is missing: cached → searching_tomorrow → refreshing → fresh → cached
Impact: Users will see accurate lifecycle status and tomorrow's electricity
prices will automatically load when available after 13:00, fixing issue
since v0.14.0 where prices weren't fetched without manual HA restart.
Add dynamic rolling window mode to get_chartdata and get_apexcharts_yaml
services that automatically adapts to data availability.
When 'day' parameter is omitted, services return 48-hour window:
- With tomorrow data (after ~13:00): today + tomorrow
- Without tomorrow data: yesterday + today
Changes:
- Implement rolling window logic in get_chartdata using has_tomorrow_data()
- Generate config-template-card wrapper in get_apexcharts_yaml for dynamic
ApexCharts span.offset based on tomorrow_data_available binary sensor
- Update service descriptions in services.yaml
- Add rolling window descriptions to all translations (de, en, nb, nl, sv)
- Document rolling window mode in docs/user/services.md
- Add ApexCharts examples with prerequisites in docs/user/automation-examples.md
BREAKING CHANGE: get_apexcharts_yaml rolling window mode requires
config-template-card in addition to apexcharts-card for dynamic offset
calculation.
Impact: Users can create auto-adapting 48h price charts without manual day
selection. Fixed day views (day: today/yesterday/tomorrow) still work with
apexcharts-card only.
Simplifies the connect_segments implementation to use a unified bridge-point
approach for all price transitions (up/down/same). Previously used
direction-dependent logic (hold vs connect points) which was unnecessarily
complex.
Changes:
- get_chartdata.py: Bridge points now always use next interval's price at
boundary timestamp, creating smooth visual connection between segments
- get_chartdata.py: Trailing NULL removal now conditional on insert_nulls mode
('segments' removes for header fix, 'all' preserves intentional gaps)
- get_apexcharts_yaml.py: Enable connect_segments by default, activate
show_states for header min/max display
- get_apexcharts_yaml.py: Remove extrema series (not compatible with
data_generator approach - ApexCharts requires entity time-series data)
- tests: Move test_connect_segments.py to tests/services/ to mirror source
structure
Impact: ApexCharts cards now show clean visual connections between price level
segments with proper header statistics display. Trailing NULLs no longer cause
"N/A" in headers for filtered data. Test organization improved for
maintainability.
Major restructuring of the scripts/ directory with consistent output
formatting, improved organization, and stricter error handling.
Breaking Changes:
- Updated development environment to Home Assistant 2025.7+
- Removed Python 3.12 compatibility (HA 2025.7+ requires Python 3.13)
- Updated all HA core requirements from 2025.7 requirement files
- Added new dependencies: python-multipart, uv (for faster package management)
- Updated GitHub Actions workflows to use Python 3.13
Changes:
- Created centralized output library (scripts/.lib/output.sh)
- Unified color codes and Unicode symbols
- Consistent formatting functions (log_header, log_success, log_error, etc.)
- Support for embedded formatting codes (${BOLD}, ${GREEN}, etc.)
- Reorganized into logical subdirectories:
- scripts/setup/ - Setup and maintenance scripts
- bootstrap: Install/update dependencies (used in CI/CD)
- setup: Full DevContainer setup (pyright, copilot, HACS)
- reset: Reset config/ directory to fresh state (NEW)
- sync-hacs: Sync HACS integrations
- scripts/release/ - Release management scripts
- prepare: Version bump and tagging
- suggest-version: Semantic version suggestion
- generate-notes: Release notes generation
- check-if-released: Check release status
- hassfest: Local integration validation
- Updated all scripts with:
- set -euo pipefail for stricter error handling
- Consistent SCRIPT_DIR pattern for reliable sourcing
- Professional output with colors and emojis
- Unified styling across all 17 scripts
- Removed redundant scripts:
- scripts/update (was just wrapper around bootstrap)
- scripts/json_schemas/ (moved to schemas/json/)
- Enhanced clean script:
- Improved artifact cleanup
- Better handling of accidental package installations
- Hints for reset and deep clean options
- New reset script features:
- Standard mode: Keep configuration.yaml
- Full mode (--full): Reset configuration.yaml from git
- Automatic re-setup after reset
- Updated documentation:
- AGENTS.md: Updated script references and workflow guidance
- docs/development/: Updated all references to new script structure
Impact: Development environment now requires Python 3.13 and Home Assistant
2025.7+. Developers get consistent, professional script output with better
error handling and logical organization. Single source of truth for styling
makes future updates trivial.
DevContainer updates:
- .devcontainer/devcontainer.json: Added Python path configuration
Configuration updates:
- config/configuration.yaml: Added test home configuration
Impact: Improved development environment setup. No production changes.
Renamed main config flow handler class for clarity:
- TibberPricesFlowHandler → TibberPricesConfigFlowHandler
Updated imports in:
- config_flow.py (import alias)
- config_flow_handlers/__init__.py (exports)
Reason: More explicit name distinguishes from OptionsFlowHandler and
SubentryFlowHandler. Follows naming convention of other flow handlers.
Impact: No functional changes, improved code readability.
Renamed service modules for consistency with service identifiers:
- apexcharts.py → get_apexcharts_yaml.py
- chartdata.py → get_chartdata.py
- Added: get_price.py (new service module)
Naming convention: Module names now match service names directly
(tibber_prices.get_apexcharts_yaml → get_apexcharts_yaml.py)
Impact: Improved code organization, easier to locate service implementations.
No functional changes.
Added new service for fetching historical/future price data:
- fetch_price_info_range: Query prices for arbitrary date ranges
- Supports start_time and end_time parameters
- Returns structured price data via service response
- Uses interval pool for efficient data retrieval
Service definition:
- services.yaml: Added fetch_price_info_range with date selectors
- services/__init__.py: Implemented handler with validation
- Response format: {"priceInfo": [...], "currency": "..."}
Schema updates:
- config_flow_handlers/schemas.py: Convert days slider to IntSelector
(was NumberSelector with float, caused "2.0 Tage" display issue)
Impact: Users can fetch price data for custom date ranges programmatically.
Config flow displays clean integer values for day offsets.
Implemented interval pool architecture for efficient price data management:
Core Components:
- IntervalPool: Central storage with timestamp-based index
- FetchGroupCache: Protected range management (day-before-yesterday to tomorrow)
- IntervalFetcher: Gap detection and optimized API queries
- TimestampIndex: O(1) lookup for price intervals
Key Features:
- Deduplication: Touch intervals instead of duplicating (memory efficient)
- GC cleanup: Removes dead intervals no longer referenced by index
- Gap detection: Only fetches missing ranges, reuses cached data
- Protected range: Keeps yesterday/today/tomorrow, purges older data
- Resolution support: Handles hourly (pre-Oct 2025) and quarter-hourly data
Integration:
- TibberPricesApiClient: Uses interval pool for all range queries
- DataUpdateCoordinator: Retrieves data from pool instead of direct API
- Transparent: No changes required in sensor/service layers
Performance Benefits:
- Reduces API calls by 70% (reuses overlapping intervals)
- Memory footprint: ~10KB per home (protects 384 intervals max)
- Lookup time: O(1) timestamp-based index
Breaking Changes: None (backward compatible integration layer)
Impact: Significantly reduces Tibber API load while maintaining data
freshness. Memory-efficient storage prevents unbounded growth.
Added complete localization support for time offset descriptions:
- Convert hardcoded English strings "(X days ago)" to translatable keys
- Add time_units translations (day/days, hour/hours, minute/minutes, ago, now)
- Support singular/plural forms in all 5 languages (de, en, nb, nl, sv)
- German: Proper Dativ case "Tagen" with preposition "vor"
- Compact format for mixed offsets: "7 Tagen - 02:30"
Config flow improvements:
- Replace hardcoded "Enter new API token" with translated "Add new Tibber account API token"
- Use get_translation() for account_choice dropdown labels
- Fix SelectOptionDict usage (no mixing with translation_key parameter)
- Convert days slider from float to int (prevents "2.0 Tage" display)
- DurationSelector: default {"hours": 0, "minutes": 0} to fix validation errors
Translation keys added:
- selector.account_choice.options.new_token
- time_units (day, days, hour, hours, minute, minutes, ago, now)
- config.step.time_offset_description guidance text
Impact: Config flow works fully translated in all 5 languages with proper grammar.