mirror of
https://github.com/jpawlowski/hass.tibber_prices.git
synced 2026-03-29 21:03:40 +00:00
fix(binary_sensor): remove 6-hour lookahead limit for period icons
Simplified _has_future_periods() to check for ANY future periods instead of limiting to 6-hour window. This ensures icons show 'waiting' state whenever periods are scheduled, not just within artificial time limit. Also added pragmatic fallback in timing calculator _find_next_period(): when skip_current=True but only one future period exists, return it anyway instead of showing 'unknown'. This prevents timing sensors from showing unknown during active periods. Changes: - binary_sensor/definitions.py: Removed PERIOD_LOOKAHEAD_HOURS constant - binary_sensor/core.py: Simplified _has_future_periods() logic - sensor/calculators/timing.py: Added pragmatic fallback for single period Impact: Better user experience - icons always show future periods, timing sensors show values even during edge cases.
This commit is contained in:
parent
f373c01fbb
commit
2d0febdab3
3 changed files with 15 additions and 24 deletions
|
|
@ -21,7 +21,6 @@ from .attributes import (
|
|||
get_price_intervals_attributes,
|
||||
get_tomorrow_data_available_attributes,
|
||||
)
|
||||
from .definitions import PERIOD_LOOKAHEAD_HOURS
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Callable
|
||||
|
|
@ -46,11 +45,6 @@ class TibberPricesBinarySensor(TibberPricesEntity, BinarySensorEntity):
|
|||
self._attr_unique_id = f"{coordinator.config_entry.entry_id}_{entity_description.key}"
|
||||
self._state_getter: Callable | None = self._get_value_getter()
|
||||
self._time_sensitive_remove_listener: Callable | None = None
|
||||
self._lifecycle_remove_listener: Callable | None = None
|
||||
|
||||
# Register for lifecycle push updates if this sensor depends on connection state
|
||||
if entity_description.key in ("connection", "tomorrow_data_available"):
|
||||
self._lifecycle_remove_listener = coordinator.register_lifecycle_callback(self.async_write_ha_state)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""When entity is added to hass."""
|
||||
|
|
@ -71,11 +65,6 @@ class TibberPricesBinarySensor(TibberPricesEntity, BinarySensorEntity):
|
|||
self._time_sensitive_remove_listener()
|
||||
self._time_sensitive_remove_listener = None
|
||||
|
||||
# Remove lifecycle listener if registered
|
||||
if self._lifecycle_remove_listener:
|
||||
self._lifecycle_remove_listener()
|
||||
self._lifecycle_remove_listener = None
|
||||
|
||||
@callback
|
||||
def _handle_time_sensitive_update(self, time_service: TibberPricesTimeService) -> None:
|
||||
"""
|
||||
|
|
@ -270,10 +259,10 @@ class TibberPricesBinarySensor(TibberPricesEntity, BinarySensorEntity):
|
|||
|
||||
def _has_future_periods(self) -> bool:
|
||||
"""
|
||||
Check if there are periods starting within the next 6 hours.
|
||||
Check if there are any future periods.
|
||||
|
||||
Returns True if any period starts between now and PERIOD_LOOKAHEAD_HOURS from now.
|
||||
This provides a practical planning horizon instead of hard midnight cutoff.
|
||||
Returns True if any period starts in the future (no time limit).
|
||||
This ensures icons show "waiting" state whenever periods are scheduled.
|
||||
"""
|
||||
attrs = self._get_sensor_attributes()
|
||||
if not attrs or "periods" not in attrs:
|
||||
|
|
@ -282,15 +271,15 @@ class TibberPricesBinarySensor(TibberPricesEntity, BinarySensorEntity):
|
|||
time = self.coordinator.time
|
||||
periods = attrs.get("periods", [])
|
||||
|
||||
# Check if any period starts within the look-ahead window
|
||||
# Check if any period starts in the future (no time limit)
|
||||
for period in periods:
|
||||
start_str = period.get("start")
|
||||
if start_str:
|
||||
# Already datetime object (periods come from coordinator.data)
|
||||
start_time = start_str if not isinstance(start_str, str) else time.parse_datetime(start_str)
|
||||
|
||||
# Period starts in the future but within our horizon
|
||||
if start_time and time.is_time_within_horizon(start_time, hours=PERIOD_LOOKAHEAD_HOURS):
|
||||
# Period starts in the future
|
||||
if start_time and time.is_in_future(start_time):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ from homeassistant.components.binary_sensor import (
|
|||
)
|
||||
from homeassistant.const import EntityCategory
|
||||
|
||||
# Look-ahead window for future period detection (hours)
|
||||
# Icons will show "waiting" state if a period starts within this window
|
||||
PERIOD_LOOKAHEAD_HOURS = 6
|
||||
# Period lookahead removed - icons show "waiting" state if ANY future periods exist
|
||||
# No artificial time limit - show all periods until midnight
|
||||
|
||||
ENTITY_DESCRIPTIONS = (
|
||||
BinarySensorEntityDescription(
|
||||
|
|
|
|||
|
|
@ -158,7 +158,8 @@ class TibberPricesTimingCalculator(TibberPricesBaseCalculator):
|
|||
|
||||
Args:
|
||||
periods: List of period dictionaries
|
||||
skip_current: If True, skip the first future period (to get next-next)
|
||||
skip_current: If True, try to skip the first future period (to get next-next)
|
||||
If only one future period exists, return it anyway (pragmatic fallback)
|
||||
|
||||
Returns:
|
||||
Next period dict or None if no future periods
|
||||
|
|
@ -173,11 +174,13 @@ class TibberPricesTimingCalculator(TibberPricesBaseCalculator):
|
|||
# Sort by start time to ensure correct order
|
||||
future_periods.sort(key=lambda p: p["start"])
|
||||
|
||||
# Return second period if skip_current=True (next-next), otherwise first (next)
|
||||
# If skip_current requested and we have multiple periods, return second
|
||||
# If only one period left, return it anyway (pragmatic: better than showing unknown)
|
||||
if skip_current and len(future_periods) > 1:
|
||||
return future_periods[1]
|
||||
if not skip_current and future_periods:
|
||||
return future_periods[0]
|
||||
|
||||
# Default: return first future period
|
||||
return future_periods[0] if future_periods else None
|
||||
|
||||
return None
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue