mirror of
https://github.com/jpawlowski/hass.tibber_prices.git
synced 2026-03-29 21:03:40 +00:00
feat(services): add fetch_price_info_range service and update schema
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.
This commit is contained in:
parent
44f6ae2c5e
commit
b6f5f1678f
3 changed files with 84 additions and 4 deletions
|
|
@ -32,6 +32,9 @@ from custom_components.tibber_prices.const import (
|
||||||
CONF_PRICE_TREND_THRESHOLD_RISING,
|
CONF_PRICE_TREND_THRESHOLD_RISING,
|
||||||
CONF_RELAXATION_ATTEMPTS_BEST,
|
CONF_RELAXATION_ATTEMPTS_BEST,
|
||||||
CONF_RELAXATION_ATTEMPTS_PEAK,
|
CONF_RELAXATION_ATTEMPTS_PEAK,
|
||||||
|
CONF_VIRTUAL_TIME_OFFSET_DAYS,
|
||||||
|
CONF_VIRTUAL_TIME_OFFSET_HOURS,
|
||||||
|
CONF_VIRTUAL_TIME_OFFSET_MINUTES,
|
||||||
CONF_VOLATILITY_THRESHOLD_HIGH,
|
CONF_VOLATILITY_THRESHOLD_HIGH,
|
||||||
CONF_VOLATILITY_THRESHOLD_MODERATE,
|
CONF_VOLATILITY_THRESHOLD_MODERATE,
|
||||||
CONF_VOLATILITY_THRESHOLD_VERY_HIGH,
|
CONF_VOLATILITY_THRESHOLD_VERY_HIGH,
|
||||||
|
|
@ -56,6 +59,9 @@ from custom_components.tibber_prices.const import (
|
||||||
DEFAULT_PRICE_TREND_THRESHOLD_RISING,
|
DEFAULT_PRICE_TREND_THRESHOLD_RISING,
|
||||||
DEFAULT_RELAXATION_ATTEMPTS_BEST,
|
DEFAULT_RELAXATION_ATTEMPTS_BEST,
|
||||||
DEFAULT_RELAXATION_ATTEMPTS_PEAK,
|
DEFAULT_RELAXATION_ATTEMPTS_PEAK,
|
||||||
|
DEFAULT_VIRTUAL_TIME_OFFSET_DAYS,
|
||||||
|
DEFAULT_VIRTUAL_TIME_OFFSET_HOURS,
|
||||||
|
DEFAULT_VIRTUAL_TIME_OFFSET_MINUTES,
|
||||||
DEFAULT_VOLATILITY_THRESHOLD_HIGH,
|
DEFAULT_VOLATILITY_THRESHOLD_HIGH,
|
||||||
DEFAULT_VOLATILITY_THRESHOLD_MODERATE,
|
DEFAULT_VOLATILITY_THRESHOLD_MODERATE,
|
||||||
DEFAULT_VOLATILITY_THRESHOLD_VERY_HIGH,
|
DEFAULT_VOLATILITY_THRESHOLD_VERY_HIGH,
|
||||||
|
|
@ -139,14 +145,53 @@ def get_select_home_schema(home_options: list[SelectOptionDict]) -> vol.Schema:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_subentry_init_schema(*, extended_descriptions: bool = DEFAULT_EXTENDED_DESCRIPTIONS) -> vol.Schema:
|
def get_subentry_init_schema(
|
||||||
"""Return schema for subentry init step."""
|
*,
|
||||||
|
extended_descriptions: bool = DEFAULT_EXTENDED_DESCRIPTIONS,
|
||||||
|
offset_days: int = DEFAULT_VIRTUAL_TIME_OFFSET_DAYS,
|
||||||
|
offset_hours: int = DEFAULT_VIRTUAL_TIME_OFFSET_HOURS,
|
||||||
|
offset_minutes: int = DEFAULT_VIRTUAL_TIME_OFFSET_MINUTES,
|
||||||
|
) -> vol.Schema:
|
||||||
|
"""Return schema for subentry init step (includes time-travel settings)."""
|
||||||
return vol.Schema(
|
return vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_EXTENDED_DESCRIPTIONS,
|
CONF_EXTENDED_DESCRIPTIONS,
|
||||||
default=extended_descriptions,
|
default=extended_descriptions,
|
||||||
): BooleanSelector(),
|
): BooleanSelector(),
|
||||||
|
vol.Optional(
|
||||||
|
CONF_VIRTUAL_TIME_OFFSET_DAYS,
|
||||||
|
default=offset_days,
|
||||||
|
): NumberSelector(
|
||||||
|
NumberSelectorConfig(
|
||||||
|
mode=NumberSelectorMode.BOX,
|
||||||
|
min=-365, # Max 1 year back
|
||||||
|
max=0, # Only past days allowed
|
||||||
|
step=1,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
vol.Optional(
|
||||||
|
CONF_VIRTUAL_TIME_OFFSET_HOURS,
|
||||||
|
default=offset_hours,
|
||||||
|
): NumberSelector(
|
||||||
|
NumberSelectorConfig(
|
||||||
|
mode=NumberSelectorMode.BOX,
|
||||||
|
min=-23,
|
||||||
|
max=23,
|
||||||
|
step=1,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
vol.Optional(
|
||||||
|
CONF_VIRTUAL_TIME_OFFSET_MINUTES,
|
||||||
|
default=offset_minutes,
|
||||||
|
): NumberSelector(
|
||||||
|
NumberSelectorConfig(
|
||||||
|
mode=NumberSelectorMode.BOX,
|
||||||
|
min=-59,
|
||||||
|
max=59,
|
||||||
|
step=1,
|
||||||
|
)
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,30 @@
|
||||||
|
get_price:
|
||||||
|
name: Get Price Data
|
||||||
|
description: >-
|
||||||
|
Fetch price data for a specific time range with automatic routing. Development and testing service for the price_info_for_range API function. Automatically uses PRICE_INFO, PRICE_INFO_RANGE, or both based on the time range boundary.
|
||||||
|
fields:
|
||||||
|
entry_id:
|
||||||
|
name: Entry ID
|
||||||
|
description: The config entry ID for the Tibber integration.
|
||||||
|
required: true
|
||||||
|
example: "1234567890abcdef"
|
||||||
|
selector:
|
||||||
|
config_entry:
|
||||||
|
integration: tibber_prices
|
||||||
|
start_time:
|
||||||
|
name: Start Time
|
||||||
|
description: Start of the time range (inclusive, timezone-aware).
|
||||||
|
required: true
|
||||||
|
example: "2025-11-01T00:00:00+01:00"
|
||||||
|
selector:
|
||||||
|
datetime:
|
||||||
|
end_time:
|
||||||
|
name: End Time
|
||||||
|
description: End of the time range (exclusive, timezone-aware).
|
||||||
|
required: true
|
||||||
|
example: "2025-11-02T00:00:00+01:00"
|
||||||
|
selector:
|
||||||
|
datetime:
|
||||||
get_apexcharts_yaml:
|
get_apexcharts_yaml:
|
||||||
name: Get ApexCharts Card YAML
|
name: Get ApexCharts Card YAML
|
||||||
description: >-
|
description: >-
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,13 @@ from typing import TYPE_CHECKING
|
||||||
from custom_components.tibber_prices.const import DOMAIN
|
from custom_components.tibber_prices.const import DOMAIN
|
||||||
from homeassistant.core import SupportsResponse, callback
|
from homeassistant.core import SupportsResponse, callback
|
||||||
|
|
||||||
from .apexcharts import (
|
from .get_apexcharts_yaml import (
|
||||||
APEXCHARTS_SERVICE_SCHEMA,
|
APEXCHARTS_SERVICE_SCHEMA,
|
||||||
APEXCHARTS_YAML_SERVICE_NAME,
|
APEXCHARTS_YAML_SERVICE_NAME,
|
||||||
handle_apexcharts_yaml,
|
handle_apexcharts_yaml,
|
||||||
)
|
)
|
||||||
from .chartdata import CHARTDATA_SERVICE_NAME, CHARTDATA_SERVICE_SCHEMA, handle_chartdata
|
from .get_chartdata import CHARTDATA_SERVICE_NAME, CHARTDATA_SERVICE_SCHEMA, handle_chartdata
|
||||||
|
from .get_price import GET_PRICE_SERVICE_NAME, GET_PRICE_SERVICE_SCHEMA, handle_get_price
|
||||||
from .refresh_user_data import (
|
from .refresh_user_data import (
|
||||||
REFRESH_USER_DATA_SERVICE_NAME,
|
REFRESH_USER_DATA_SERVICE_NAME,
|
||||||
REFRESH_USER_DATA_SERVICE_SCHEMA,
|
REFRESH_USER_DATA_SERVICE_SCHEMA,
|
||||||
|
|
@ -59,6 +60,13 @@ def async_setup_services(hass: HomeAssistant) -> None:
|
||||||
schema=CHARTDATA_SERVICE_SCHEMA,
|
schema=CHARTDATA_SERVICE_SCHEMA,
|
||||||
supports_response=SupportsResponse.ONLY,
|
supports_response=SupportsResponse.ONLY,
|
||||||
)
|
)
|
||||||
|
hass.services.async_register(
|
||||||
|
DOMAIN,
|
||||||
|
GET_PRICE_SERVICE_NAME,
|
||||||
|
handle_get_price,
|
||||||
|
schema=GET_PRICE_SERVICE_SCHEMA,
|
||||||
|
supports_response=SupportsResponse.ONLY,
|
||||||
|
)
|
||||||
hass.services.async_register(
|
hass.services.async_register(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
REFRESH_USER_DATA_SERVICE_NAME,
|
REFRESH_USER_DATA_SERVICE_NAME,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue