mirror of
https://github.com/jpawlowski/hass.tibber_prices.git
synced 2026-05-28 18:43:40 +00:00
refactor: remove dead code across integration
Remove unused functions, constants, and entity definitions that were left over from previous refactorings. All removed code was either superseded by better implementations or never actually called. Removed functions: - entity_utils/helpers.py: translate_level(), translate_rating_level() (HA handles ENUM translation automatically via translations/*.json) - entity_utils/attributes.py: build_timestamp_attribute(), build_period_attributes() (superseded by inline implementations) - sensor/helpers.py: get_hourly_price_value(), aggregate_window_data() (replaced by Calculator Pattern in sensor/calculators/) Removed constants and definitions: - const.py: CONF_CHART_DATA_CONFIG (DATA_CHART_CONFIG is the active one), PRICE_LEVEL_OPTIONS, PRICE_RATING_OPTIONS, VOLATILITY_OPTIONS, PRICE_TREND_OPTIONS (never imported; options defined inline in definitions.py due to HA import timing constraints), async_get_home_type_translation() (sync version used instead) - coordinator/core.py: FRESH_TO_CACHED_SECONDS (leftover from old caching strategy, never referenced) - switch/definitions.py: BEST_PRICE_SWITCH_ENTITIES (duplicate of BEST_PRICE_SWITCH_ENTITY_DESCRIPTIONS using base class instead of custom TibberPricesSwitchEntityDescription subclass) Cleanup: - entity_utils/__init__.py: Remove exports for deleted functions - sensor/helpers.py: Remove now-unused imports (timedelta, get_intervals_for_day_offsets, get_price_value, Callable) - entity_utils/helpers.py: Remove unused get_price_level_translation import after translate_level() removal - sensor/definitions.py: Update 7x "Keep in sync with *_OPTIONS" comments to reference individual PRICE_LEVEL_*/PRICE_RATING_*/ VOLATILITY_* constants instead Impact: No user-visible changes. Reduces codebase by ~130 lines. Improves maintainability by eliminating misleading dead code.
This commit is contained in:
parent
d6bd933e90
commit
2f704a35a3
8 changed files with 10 additions and 272 deletions
|
|
@ -68,7 +68,6 @@ CONF_RELAXATION_ATTEMPTS_BEST = "relaxation_attempts_best"
|
||||||
CONF_ENABLE_MIN_PERIODS_PEAK = "enable_min_periods_peak"
|
CONF_ENABLE_MIN_PERIODS_PEAK = "enable_min_periods_peak"
|
||||||
CONF_MIN_PERIODS_PEAK = "min_periods_peak"
|
CONF_MIN_PERIODS_PEAK = "min_periods_peak"
|
||||||
CONF_RELAXATION_ATTEMPTS_PEAK = "relaxation_attempts_peak"
|
CONF_RELAXATION_ATTEMPTS_PEAK = "relaxation_attempts_peak"
|
||||||
CONF_CHART_DATA_CONFIG = "chart_data_config" # YAML config for chart data export
|
|
||||||
|
|
||||||
ATTRIBUTION = "Data provided by Tibber"
|
ATTRIBUTION = "Data provided by Tibber"
|
||||||
|
|
||||||
|
|
@ -487,40 +486,6 @@ PRICE_TREND_STABLE = "stable"
|
||||||
PRICE_TREND_RISING = "rising"
|
PRICE_TREND_RISING = "rising"
|
||||||
PRICE_TREND_STRONGLY_RISING = "strongly_rising"
|
PRICE_TREND_STRONGLY_RISING = "strongly_rising"
|
||||||
|
|
||||||
# Sensor options (lowercase versions for ENUM device class)
|
|
||||||
# NOTE: These constants define the valid enum options, but they are not used directly
|
|
||||||
# in sensor/definitions.py due to import timing issues. Instead, the options are defined inline
|
|
||||||
# in the SensorEntityDescription objects. Keep these in sync with sensor/definitions.py!
|
|
||||||
PRICE_LEVEL_OPTIONS = [
|
|
||||||
PRICE_LEVEL_VERY_CHEAP.lower(),
|
|
||||||
PRICE_LEVEL_CHEAP.lower(),
|
|
||||||
PRICE_LEVEL_NORMAL.lower(),
|
|
||||||
PRICE_LEVEL_EXPENSIVE.lower(),
|
|
||||||
PRICE_LEVEL_VERY_EXPENSIVE.lower(),
|
|
||||||
]
|
|
||||||
|
|
||||||
PRICE_RATING_OPTIONS = [
|
|
||||||
PRICE_RATING_LOW.lower(),
|
|
||||||
PRICE_RATING_NORMAL.lower(),
|
|
||||||
PRICE_RATING_HIGH.lower(),
|
|
||||||
]
|
|
||||||
|
|
||||||
VOLATILITY_OPTIONS = [
|
|
||||||
VOLATILITY_LOW.lower(),
|
|
||||||
VOLATILITY_MODERATE.lower(),
|
|
||||||
VOLATILITY_HIGH.lower(),
|
|
||||||
VOLATILITY_VERY_HIGH.lower(),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Trend options for enum sensors (lowercase versions for ENUM device class)
|
|
||||||
PRICE_TREND_OPTIONS = [
|
|
||||||
PRICE_TREND_STRONGLY_FALLING,
|
|
||||||
PRICE_TREND_FALLING,
|
|
||||||
PRICE_TREND_STABLE,
|
|
||||||
PRICE_TREND_RISING,
|
|
||||||
PRICE_TREND_STRONGLY_RISING,
|
|
||||||
]
|
|
||||||
|
|
||||||
# Valid options for best price maximum level filter
|
# Valid options for best price maximum level filter
|
||||||
# Sorted from cheap to expensive: user selects "up to how expensive"
|
# Sorted from cheap to expensive: user selects "up to how expensive"
|
||||||
BEST_PRICE_MAX_LEVEL_OPTIONS = [
|
BEST_PRICE_MAX_LEVEL_OPTIONS = [
|
||||||
|
|
@ -1019,26 +984,6 @@ def get_price_level_translation(
|
||||||
return get_translation(["sensor", "current_interval_price_level", "price_levels", level], language)
|
return get_translation(["sensor", "current_interval_price_level", "price_levels", level], language)
|
||||||
|
|
||||||
|
|
||||||
async def async_get_home_type_translation(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
home_type: str,
|
|
||||||
language: str = "en",
|
|
||||||
) -> str | None:
|
|
||||||
"""
|
|
||||||
Get a localized translation for a home type asynchronously.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
hass: HomeAssistant instance
|
|
||||||
home_type: The home type (e.g., APARTMENT, HOUSE, etc.)
|
|
||||||
language: The language code (defaults to English)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The localized home type if found, None otherwise
|
|
||||||
|
|
||||||
"""
|
|
||||||
return await async_get_translation(hass, ["home_types", home_type], language)
|
|
||||||
|
|
||||||
|
|
||||||
def get_home_type_translation(
|
def get_home_type_translation(
|
||||||
home_type: str,
|
home_type: str,
|
||||||
language: str = "en",
|
language: str = "en",
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,6 @@ from .time_service import TibberPricesTimeService
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Lifecycle state transition thresholds
|
|
||||||
FRESH_TO_CACHED_SECONDS = 300 # 5 minutes
|
|
||||||
|
|
||||||
|
|
||||||
def get_connection_state(coordinator: TibberPricesDataUpdateCoordinator) -> bool | None:
|
def get_connection_state(coordinator: TibberPricesDataUpdateCoordinator) -> bool | None:
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -21,15 +21,11 @@ from __future__ import annotations
|
||||||
from .attributes import (
|
from .attributes import (
|
||||||
add_description_attributes,
|
add_description_attributes,
|
||||||
async_add_description_attributes,
|
async_add_description_attributes,
|
||||||
build_period_attributes,
|
|
||||||
build_timestamp_attribute,
|
|
||||||
)
|
)
|
||||||
from .colors import add_icon_color_attribute, get_icon_color
|
from .colors import add_icon_color_attribute, get_icon_color
|
||||||
from .helpers import (
|
from .helpers import (
|
||||||
find_rolling_hour_center_index,
|
find_rolling_hour_center_index,
|
||||||
get_price_value,
|
get_price_value,
|
||||||
translate_level,
|
|
||||||
translate_rating_level,
|
|
||||||
)
|
)
|
||||||
from .icons import (
|
from .icons import (
|
||||||
get_binary_sensor_icon,
|
get_binary_sensor_icon,
|
||||||
|
|
@ -46,8 +42,6 @@ __all__ = [
|
||||||
"add_description_attributes",
|
"add_description_attributes",
|
||||||
"add_icon_color_attribute",
|
"add_icon_color_attribute",
|
||||||
"async_add_description_attributes",
|
"async_add_description_attributes",
|
||||||
"build_period_attributes",
|
|
||||||
"build_timestamp_attribute",
|
|
||||||
"find_rolling_hour_center_index",
|
"find_rolling_hour_center_index",
|
||||||
"get_binary_sensor_icon",
|
"get_binary_sensor_icon",
|
||||||
"get_dynamic_icon",
|
"get_dynamic_icon",
|
||||||
|
|
@ -59,6 +53,4 @@ __all__ = [
|
||||||
"get_rating_sensor_icon",
|
"get_rating_sensor_icon",
|
||||||
"get_trend_icon",
|
"get_trend_icon",
|
||||||
"get_volatility_sensor_icon",
|
"get_volatility_sensor_icon",
|
||||||
"translate_level",
|
|
||||||
"translate_rating_level",
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -10,45 +10,6 @@ if TYPE_CHECKING:
|
||||||
from ..data import TibberPricesConfigEntry # noqa: TID252
|
from ..data import TibberPricesConfigEntry # noqa: TID252
|
||||||
|
|
||||||
|
|
||||||
def build_timestamp_attribute(interval_data: dict | None) -> str | None:
|
|
||||||
"""
|
|
||||||
Build timestamp attribute from interval data.
|
|
||||||
|
|
||||||
Extracts startsAt field consistently across all sensors.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
interval_data: Interval data dictionary containing startsAt field
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
ISO format timestamp string or None
|
|
||||||
|
|
||||||
"""
|
|
||||||
if not interval_data:
|
|
||||||
return None
|
|
||||||
return interval_data.get("startsAt")
|
|
||||||
|
|
||||||
|
|
||||||
def build_period_attributes(period_data: dict) -> dict:
|
|
||||||
"""
|
|
||||||
Build common period attributes (start, end, duration, timestamp).
|
|
||||||
|
|
||||||
Used by binary sensors for period-based entities.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
period_data: Period data dictionary
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Dictionary with common period attributes
|
|
||||||
|
|
||||||
"""
|
|
||||||
return {
|
|
||||||
"start": period_data.get("start"),
|
|
||||||
"end": period_data.get("end"),
|
|
||||||
"duration_minutes": period_data.get("duration_minutes"),
|
|
||||||
"timestamp": period_data.get("start"), # Timestamp = period start
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def add_description_attributes( # noqa: PLR0913, PLR0912
|
def add_description_attributes( # noqa: PLR0913, PLR0912
|
||||||
attributes: dict,
|
attributes: dict,
|
||||||
platform: str,
|
platform: str,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ Common helper functions for entities across platforms.
|
||||||
|
|
||||||
This module provides utility functions used by both sensor and binary_sensor platforms:
|
This module provides utility functions used by both sensor and binary_sensor platforms:
|
||||||
- Price value conversion (major/subunit currency units)
|
- Price value conversion (major/subunit currency units)
|
||||||
- Translation helpers (price levels, ratings)
|
|
||||||
- Time-based calculations (rolling hour center index)
|
- Time-based calculations (rolling hour center index)
|
||||||
|
|
||||||
These functions operate on entity-level concepts (states, translations) but are
|
These functions operate on entity-level concepts (states, translations) but are
|
||||||
|
|
@ -14,7 +14,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from custom_components.tibber_prices.const import get_display_unit_factor, get_price_level_translation
|
from custom_components.tibber_prices.const import get_display_unit_factor
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
@ -22,7 +22,6 @@ if TYPE_CHECKING:
|
||||||
from custom_components.tibber_prices.coordinator.time_service import TibberPricesTimeService
|
from custom_components.tibber_prices.coordinator.time_service import TibberPricesTimeService
|
||||||
from custom_components.tibber_prices.data import TibberPricesConfigEntry
|
from custom_components.tibber_prices.data import TibberPricesConfigEntry
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
|
||||||
|
|
||||||
|
|
||||||
def get_price_value(
|
def get_price_value(
|
||||||
|
|
@ -62,54 +61,6 @@ def get_price_value(
|
||||||
return round(price * 100, 2)
|
return round(price * 100, 2)
|
||||||
|
|
||||||
|
|
||||||
def translate_level(hass: HomeAssistant, level: str) -> str:
|
|
||||||
"""
|
|
||||||
Translate price level to the user's language.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
hass: HomeAssistant instance for language configuration
|
|
||||||
level: Price level to translate (e.g., VERY_CHEAP, NORMAL, etc.)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Translated level string, or original level if translation not found
|
|
||||||
|
|
||||||
"""
|
|
||||||
if not hass:
|
|
||||||
return level
|
|
||||||
|
|
||||||
language = hass.config.language or "en"
|
|
||||||
translated = get_price_level_translation(level, language)
|
|
||||||
if translated:
|
|
||||||
return translated
|
|
||||||
|
|
||||||
if language != "en":
|
|
||||||
fallback = get_price_level_translation(level, "en")
|
|
||||||
if fallback:
|
|
||||||
return fallback
|
|
||||||
|
|
||||||
return level
|
|
||||||
|
|
||||||
|
|
||||||
def translate_rating_level(rating: str) -> str:
|
|
||||||
"""
|
|
||||||
Translate price rating level to the user's language.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
rating: Price rating to translate (e.g., LOW, NORMAL, HIGH)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Translated rating string, or original rating if translation not found
|
|
||||||
|
|
||||||
Note:
|
|
||||||
Currently returns the rating as-is. Translation mapping for ratings
|
|
||||||
can be added here when needed, similar to translate_level().
|
|
||||||
|
|
||||||
"""
|
|
||||||
# For now, ratings are returned as-is
|
|
||||||
# Add translation mapping here when needed
|
|
||||||
return rating
|
|
||||||
|
|
||||||
|
|
||||||
def find_rolling_hour_center_index(
|
def find_rolling_hour_center_index(
|
||||||
all_prices: list[dict],
|
all_prices: list[dict],
|
||||||
current_time: datetime,
|
current_time: datetime,
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ INTERVAL_PRICE_SENSORS = (
|
||||||
|
|
||||||
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
||||||
# import timing issues with Home Assistant's entity platform initialization.
|
# import timing issues with Home Assistant's entity platform initialization.
|
||||||
# Keep in sync with PRICE_LEVEL_OPTIONS in const.py!
|
# Keep in sync with PRICE_LEVEL_* constants in const.py!
|
||||||
INTERVAL_LEVEL_SENSORS = (
|
INTERVAL_LEVEL_SENSORS = (
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key="current_interval_price_level",
|
key="current_interval_price_level",
|
||||||
|
|
@ -126,7 +126,7 @@ INTERVAL_LEVEL_SENSORS = (
|
||||||
|
|
||||||
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
||||||
# import timing issues with Home Assistant's entity platform initialization.
|
# import timing issues with Home Assistant's entity platform initialization.
|
||||||
# Keep in sync with PRICE_RATING_OPTIONS in const.py!
|
# Keep in sync with PRICE_RATING_* constants in const.py!
|
||||||
INTERVAL_RATING_SENSORS = (
|
INTERVAL_RATING_SENSORS = (
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key="current_interval_price_rating",
|
key="current_interval_price_rating",
|
||||||
|
|
@ -184,7 +184,7 @@ ROLLING_HOUR_PRICE_SENSORS = (
|
||||||
|
|
||||||
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
||||||
# import timing issues with Home Assistant's entity platform initialization.
|
# import timing issues with Home Assistant's entity platform initialization.
|
||||||
# Keep in sync with PRICE_LEVEL_OPTIONS in const.py!
|
# Keep in sync with PRICE_LEVEL_* constants in const.py!
|
||||||
ROLLING_HOUR_LEVEL_SENSORS = (
|
ROLLING_HOUR_LEVEL_SENSORS = (
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key="current_hour_price_level",
|
key="current_hour_price_level",
|
||||||
|
|
@ -206,7 +206,7 @@ ROLLING_HOUR_LEVEL_SENSORS = (
|
||||||
|
|
||||||
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
||||||
# import timing issues with Home Assistant's entity platform initialization.
|
# import timing issues with Home Assistant's entity platform initialization.
|
||||||
# Keep in sync with PRICE_RATING_OPTIONS in const.py!
|
# Keep in sync with PRICE_RATING_* constants in const.py!
|
||||||
ROLLING_HOUR_RATING_SENSORS = (
|
ROLLING_HOUR_RATING_SENSORS = (
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key="current_hour_price_rating",
|
key="current_hour_price_rating",
|
||||||
|
|
@ -288,7 +288,7 @@ DAILY_STAT_SENSORS = (
|
||||||
|
|
||||||
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
||||||
# import timing issues with Home Assistant's entity platform initialization.
|
# import timing issues with Home Assistant's entity platform initialization.
|
||||||
# Keep in sync with PRICE_LEVEL_OPTIONS in const.py!
|
# Keep in sync with PRICE_LEVEL_* constants in const.py!
|
||||||
DAILY_LEVEL_SENSORS = (
|
DAILY_LEVEL_SENSORS = (
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key="yesterday_price_level",
|
key="yesterday_price_level",
|
||||||
|
|
@ -319,7 +319,7 @@ DAILY_LEVEL_SENSORS = (
|
||||||
|
|
||||||
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
||||||
# import timing issues with Home Assistant's entity platform initialization.
|
# import timing issues with Home Assistant's entity platform initialization.
|
||||||
# Keep in sync with PRICE_RATING_OPTIONS in const.py!
|
# Keep in sync with PRICE_RATING_* constants in const.py!
|
||||||
DAILY_RATING_SENSORS = (
|
DAILY_RATING_SENSORS = (
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key="yesterday_price_rating",
|
key="yesterday_price_rating",
|
||||||
|
|
@ -692,7 +692,7 @@ PRICE_TRAJECTORY_SENSORS = (
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
# NOTE: Enum options are defined inline (not imported from const.py) to avoid
|
||||||
# import timing issues with Home Assistant's entity platform initialization.
|
# import timing issues with Home Assistant's entity platform initialization.
|
||||||
# Keep in sync with VOLATILITY_OPTIONS in const.py!
|
# Keep in sync with VOLATILITY_* constants in const.py!
|
||||||
|
|
||||||
VOLATILITY_SENSORS = (
|
VOLATILITY_SENSORS = (
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
|
|
|
||||||
|
|
@ -5,29 +5,18 @@ This module contains helper functions specific to the sensor platform:
|
||||||
- aggregate_price_data: Calculate average price from window data
|
- aggregate_price_data: Calculate average price from window data
|
||||||
- aggregate_level_data: Aggregate price levels from intervals
|
- aggregate_level_data: Aggregate price levels from intervals
|
||||||
- aggregate_rating_data: Aggregate price ratings from intervals
|
- aggregate_rating_data: Aggregate price ratings from intervals
|
||||||
- aggregate_window_data: Unified aggregation based on value type
|
|
||||||
- get_hourly_price_value: Get price for specific hour with offset
|
|
||||||
|
|
||||||
For shared helper functions (used by both sensor and binary_sensor platforms),
|
For shared helper functions (used by both sensor and binary_sensor platforms),
|
||||||
see entity_utils/helpers.py:
|
see entity_utils/helpers.py:
|
||||||
- get_price_value: Price unit conversion
|
- get_price_value: Price unit conversion
|
||||||
- translate_level: Price level translation
|
|
||||||
- translate_rating_level: Rating level translation
|
|
||||||
- find_rolling_hour_center_index: Rolling hour window calculations
|
- find_rolling_hour_center_index: Rolling hour window calculations
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from custom_components.tibber_prices.coordinator.time_service import TibberPricesTimeService
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
|
||||||
|
|
||||||
from custom_components.tibber_prices.const import get_display_unit_factor
|
from custom_components.tibber_prices.const import get_display_unit_factor
|
||||||
from custom_components.tibber_prices.coordinator.helpers import get_intervals_for_day_offsets
|
|
||||||
from custom_components.tibber_prices.entity_utils.helpers import get_price_value
|
|
||||||
from custom_components.tibber_prices.utils.average import calculate_mean, calculate_median
|
from custom_components.tibber_prices.utils.average import calculate_mean, calculate_median
|
||||||
from custom_components.tibber_prices.utils.price import (
|
from custom_components.tibber_prices.utils.price import (
|
||||||
aggregate_price_levels,
|
aggregate_price_levels,
|
||||||
|
|
@ -35,7 +24,7 @@ from custom_components.tibber_prices.utils.price import (
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from collections.abc import Callable
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
|
||||||
|
|
||||||
def aggregate_average_data(
|
def aggregate_average_data(
|
||||||
|
|
@ -106,90 +95,3 @@ def aggregate_rating_data(
|
||||||
|
|
||||||
aggregated, _ = aggregate_price_rating(differences, threshold_low, threshold_high)
|
aggregated, _ = aggregate_price_rating(differences, threshold_low, threshold_high)
|
||||||
return aggregated.lower() if aggregated else None
|
return aggregated.lower() if aggregated else None
|
||||||
|
|
||||||
|
|
||||||
def aggregate_window_data(
|
|
||||||
window_data: list[dict],
|
|
||||||
value_type: str,
|
|
||||||
threshold_low: float,
|
|
||||||
threshold_high: float,
|
|
||||||
config_entry: ConfigEntry,
|
|
||||||
) -> str | float | None:
|
|
||||||
"""
|
|
||||||
Aggregate data from multiple intervals based on value type.
|
|
||||||
|
|
||||||
Unified helper that routes to appropriate aggregation function.
|
|
||||||
|
|
||||||
NOTE: This function is legacy code - rolling_hour calculator has its own implementation.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
window_data: List of price interval dictionaries.
|
|
||||||
value_type: Type of value to aggregate ('price', 'level', or 'rating').
|
|
||||||
threshold_low: Low threshold for rating calculation.
|
|
||||||
threshold_high: High threshold for rating calculation.
|
|
||||||
config_entry: Config entry to get display unit configuration.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Aggregated value (price as float, level/rating as str), or None if no data.
|
|
||||||
|
|
||||||
"""
|
|
||||||
# Map value types to aggregation functions
|
|
||||||
aggregators: dict[str, Callable] = {
|
|
||||||
"price": lambda data: aggregate_average_data(data, config_entry)[0], # Use only average from tuple
|
|
||||||
"level": aggregate_level_data,
|
|
||||||
"rating": lambda data: aggregate_rating_data(data, threshold_low, threshold_high),
|
|
||||||
}
|
|
||||||
|
|
||||||
aggregator = aggregators.get(value_type)
|
|
||||||
if aggregator:
|
|
||||||
return aggregator(window_data)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_hourly_price_value(
|
|
||||||
coordinator_data: dict,
|
|
||||||
*,
|
|
||||||
hour_offset: int,
|
|
||||||
in_euro: bool,
|
|
||||||
time: TibberPricesTimeService,
|
|
||||||
) -> float | None:
|
|
||||||
"""
|
|
||||||
Get price for current hour or with offset.
|
|
||||||
|
|
||||||
Legacy helper for hourly price access (not used by Calculator Pattern).
|
|
||||||
Kept for potential backward compatibility.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
coordinator_data: Coordinator data dict
|
|
||||||
hour_offset: Hour offset from current time (positive=future, negative=past)
|
|
||||||
in_euro: If True, return price in base currency (EUR), else minor (cents/øre)
|
|
||||||
time: TibberPricesTimeService instance (required)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Price value, or None if not found
|
|
||||||
|
|
||||||
"""
|
|
||||||
# Use TimeService to get the current time in the user's timezone
|
|
||||||
now = time.now()
|
|
||||||
|
|
||||||
# Calculate the exact target datetime (not just the hour)
|
|
||||||
# This properly handles day boundaries
|
|
||||||
target_datetime = now.replace(microsecond=0) + timedelta(hours=hour_offset)
|
|
||||||
target_hour = target_datetime.hour
|
|
||||||
target_date = target_datetime.date()
|
|
||||||
|
|
||||||
# Get all intervals (yesterday, today, tomorrow) via helper
|
|
||||||
all_intervals = get_intervals_for_day_offsets(coordinator_data, [-1, 0, 1])
|
|
||||||
|
|
||||||
# Search through all intervals to find the matching hour
|
|
||||||
for price_data in all_intervals:
|
|
||||||
# Parse the timestamp and convert to local time
|
|
||||||
starts_at = time.get_interval_time(price_data)
|
|
||||||
if starts_at is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Compare using both hour and date for accuracy
|
|
||||||
if starts_at.hour == target_hour and starts_at.date() == target_date:
|
|
||||||
return get_price_value(float(price_data["total"]), in_euro=in_euro)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
|
||||||
|
|
@ -34,16 +34,6 @@ class TibberPricesSwitchEntityDescription(SwitchEntityDescription):
|
||||||
# BEST PRICE PERIOD CONFIGURATION OVERRIDES (Boolean)
|
# BEST PRICE PERIOD CONFIGURATION OVERRIDES (Boolean)
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
BEST_PRICE_SWITCH_ENTITIES = (
|
|
||||||
SwitchEntityDescription(
|
|
||||||
key="best_price_enable_relaxation_override",
|
|
||||||
translation_key="best_price_enable_relaxation_override",
|
|
||||||
icon="mdi:arrow-down-bold-circle",
|
|
||||||
entity_category=EntityCategory.CONFIG,
|
|
||||||
entity_registry_enabled_default=False,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Custom descriptions with extra fields
|
# Custom descriptions with extra fields
|
||||||
BEST_PRICE_SWITCH_ENTITY_DESCRIPTIONS = (
|
BEST_PRICE_SWITCH_ENTITY_DESCRIPTIONS = (
|
||||||
TibberPricesSwitchEntityDescription(
|
TibberPricesSwitchEntityDescription(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue