Skip to content

Commit

Permalink
Handle missing prices from Tibber api (#320)
Browse files Browse the repository at this point in the history
* Handle missing prices from Tibber api

* none

Signed-off-by: Daniel Hjelseth Høyer <[email protected]>

* none

Signed-off-by: Daniel Hjelseth Høyer <[email protected]>

* style

Signed-off-by: Daniel Hjelseth Høyer <[email protected]>

---------

Signed-off-by: Daniel Hjelseth Høyer <[email protected]>
  • Loading branch information
Danielhiversen authored Nov 11, 2024
1 parent f1dbe16 commit f91c4da
Showing 1 changed file with 47 additions and 11 deletions.
58 changes: 47 additions & 11 deletions tibber/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ def __init__(self, home_id: str, tibber_control: Tibber) -> None:
self._rt_listener: None | asyncio.Task[Any] = None
self._rt_callback: Callable[..., Any] | None = None
self._rt_stopped: bool = True
self._has_real_time_consumption: None | bool = None
self._real_time_consumption_suggested_disabled: dt.datetime | None = None

async def _fetch_data(self, hourly_data: HourlyData) -> None:
"""Update hourly consumption or production data asynchronously."""
Expand Down Expand Up @@ -200,13 +202,41 @@ async def update_info(self) -> None:
"""Update home info and the current price info asynchronously."""
if data := await self._tibber_control.execute(UPDATE_INFO % self._home_id):
self.info = data
self._update_has_real_time_consumption()

async def update_info_and_price_info(self) -> None:
"""Update home info and all price info asynchronously."""
if data := await self._tibber_control.execute(UPDATE_INFO_PRICE % self._home_id):
self.info = data
self._update_has_real_time_consumption()
await self.update_price_info()

def _update_has_real_time_consumption(self) -> None:
try:
_has_real_time_consumption = self.info["viewer"]["home"]["features"]["realTimeConsumptionEnabled"]
except (KeyError, TypeError):
self._has_real_time_consumption = None
return
if self._has_real_time_consumption is None:
self._has_real_time_consumption = _has_real_time_consumption
return

if self._has_real_time_consumption is True and _has_real_time_consumption is False:
now = dt.datetime.now(tz=dt.UTC)
if self._real_time_consumption_suggested_disabled is None:
self._real_time_consumption_suggested_disabled = now
self._has_real_time_consumption = None
elif now - self._real_time_consumption_suggested_disabled > dt.timedelta(hours=1):
self._real_time_consumption_suggested_disabled = None
self._has_real_time_consumption = False
else:
self._has_real_time_consumption = None
return

if _has_real_time_consumption is True:
self._real_time_consumption_suggested_disabled = None
self._has_real_time_consumption = _has_real_time_consumption

async def update_current_price_info(self) -> None:
"""Update just the current price info asynchronously."""
query = UPDATE_CURRENT_PRICE % self.home_id
Expand All @@ -224,24 +254,33 @@ async def update_current_price_info(self) -> None:
if price_info:
self._current_price_info = price_info

async def update_price_info(self) -> None:
async def update_price_info(self, retry: bool = True) -> None:
"""Update the current price info, todays price info
and tomorrows price info asynchronously.
"""
price_info = await self._tibber_control.execute(PRICE_INFO % self.home_id)
if not price_info:
_LOGGER.error("Could not find price info.")
return
self._price_info = {}
self._level_info = {}
if self.has_active_subscription:
if retry:
_LOGGER.debug("Could not find price info. Retrying...")
return await self.update_price_info(retry=False)
_LOGGER.error("Could not find price info.")
return None
data = price_info["viewer"]["home"]["currentSubscription"]["priceRating"]["hourly"]["entries"]
if not data:
_LOGGER.error("Could not find price info. %s", price_info)
return
if self.has_active_subscription:
if retry:
_LOGGER.debug("Could not find price info data. Retrying...")
return await self.update_price_info(retry=False)
_LOGGER.error("Could not find price info data. %s", price_info)
return None
self._price_info = {}
self._level_info = {}
for row in data:
self._price_info[row.get("time")] = row.get("total")
self._level_info[row.get("time")] = row.get("level")
self.last_data_timestamp = dt.datetime.fromisoformat(data[-1]["time"])
return None

@property
def current_price_total(self) -> float | None:
Expand Down Expand Up @@ -287,10 +326,7 @@ def has_active_subscription(self) -> bool:
@property
def has_real_time_consumption(self) -> None | bool:
"""Return home id."""
try:
return self.info["viewer"]["home"]["features"]["realTimeConsumptionEnabled"]
except (KeyError, TypeError):
return None
return self._has_real_time_consumption

@property
def has_production(self) -> bool:
Expand Down

0 comments on commit f91c4da

Please sign in to comment.