Compare commits

...

4 Commits

Author SHA1 Message Date
Daniel Hjelseth Høyer
765d7699f3 Tibber, handle failed update
Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>
2026-03-25 11:18:37 +01:00
Daniel Hjelseth Høyer
98d636274a Tibber, handle failed update
Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>
2026-03-24 08:29:28 +01:00
Daniel Hjelseth Høyer
56423f5712 Tibber, handle failed update
Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>
2026-03-24 06:35:58 +01:00
Daniel Hjelseth Høyer
e55f89a800 Tibber, handle failed update
Signed-off-by: Daniel Hjelseth Høyer <github@dahoiv.net>
2026-03-22 08:25:37 +01:00
2 changed files with 38 additions and 19 deletions

View File

@@ -272,8 +272,8 @@ class TibberPriceCoordinator(DataUpdateCoordinator[dict[str, TibberHomeData]]):
update_interval=timedelta(minutes=1),
)
def _seconds_until_next_15_minute(self) -> float:
"""Return seconds until the next 15-minute boundary (0, 15, 30, 45) in UTC."""
def _time_until_next_15_minute(self) -> timedelta:
"""Return time until the next 15-minute boundary (0, 15, 30, 45) in UTC."""
now = dt_util.utcnow()
next_minute = ((now.minute // 15) + 1) * 15
if next_minute >= 60:
@@ -284,7 +284,7 @@ class TibberPriceCoordinator(DataUpdateCoordinator[dict[str, TibberHomeData]]):
next_run = now.replace(
minute=next_minute, second=0, microsecond=0, tzinfo=dt_util.UTC
)
return (next_run - now).total_seconds()
return next_run - now
async def _async_update_data(self) -> dict[str, TibberHomeData]:
"""Update data via API and return per-home data for sensors."""
@@ -292,22 +292,21 @@ class TibberPriceCoordinator(DataUpdateCoordinator[dict[str, TibberHomeData]]):
self.hass
)
active_homes = tibber_connection.get_homes(only_active=True)
today_start = dt_util.start_of_local_day()
today_end = today_start + timedelta(days=1)
def _has_prices_today(home: tibber.TibberHome) -> bool:
"""Return True if the home has any prices today."""
for start in home.price_total:
start_dt = dt_util.as_local(datetime.fromisoformat(str(start)))
if today_start <= start_dt < today_end:
return True
return False
homes_to_update = [home for home in active_homes if not _has_prices_today(home)]
try:
await asyncio.gather(
tibber_connection.fetch_consumption_data_active_homes(),
tibber_connection.fetch_production_data_active_homes(),
)
now = dt_util.now()
homes_to_update = [
home
for home in active_homes
if (
(last_data_timestamp := home.last_data_timestamp) is None
or (last_data_timestamp - now).total_seconds() < 11 * 3600
)
]
if homes_to_update:
await asyncio.gather(
*(home.update_info_and_price_info() for home in homes_to_update)
@@ -319,7 +318,7 @@ class TibberPriceCoordinator(DataUpdateCoordinator[dict[str, TibberHomeData]]):
result = {home.home_id: _build_home_data(home) for home in active_homes}
self.update_interval = timedelta(seconds=self._seconds_until_next_15_minute())
self.update_interval = self._time_until_next_15_minute()
return result

View File

@@ -6,6 +6,7 @@ import datetime as dt
from datetime import datetime
from typing import TYPE_CHECKING, Any, Final
import tibber
import voluptuous as vol
from homeassistant.core import (
@@ -52,7 +53,26 @@ async def __get_prices(call: ServiceCall) -> ServiceResponse:
tibber_prices: dict[str, Any] = {}
now = dt_util.now()
today_start = dt_util.start_of_local_day()
today_end = today_start + dt.timedelta(days=1)
tomorrow_end = today_start + dt.timedelta(days=2)
def _has_valid_prices(home: tibber.TibberHome) -> bool:
"""Return True if the home has valid prices."""
for start in home.price_total:
start_dt = dt_util.as_local(datetime.fromisoformat(str(start)))
if now.hour >= 13:
if today_end <= start_dt < tomorrow_end:
return True
elif today_start <= start_dt < today_end:
return True
return False
for tibber_home in tibber_connection.get_homes(only_active=True):
if not _has_valid_prices(tibber_home):
await tibber_home.update_info_and_price_info()
home_nickname = tibber_home.name
price_data = [