From 809924e50e4350458065103e7245fe0b08fb651c Mon Sep 17 00:00:00 2001 From: Hellowlol Date: Sun, 26 Mar 2023 17:41:56 +0200 Subject: [PATCH 1/3] first pass --- custom_components/nordpool/aio_price.py | 5 +++++ custom_components/nordpool/manifest.json | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/custom_components/nordpool/aio_price.py b/custom_components/nordpool/aio_price.py index fc0ec8f..39d84d2 100644 --- a/custom_components/nordpool/aio_price.py +++ b/custom_components/nordpool/aio_price.py @@ -5,6 +5,8 @@ from dateutil import tz from dateutil.parser import parse as parse_dt +import backoff +import aiohttp from nordpool.elspot import Prices from .misc import add_junk @@ -177,6 +179,7 @@ async def _fetch_json(self, data_type, end_date=None): endDate=end_date.strftime("%d-%m-%Y"), ) + @backoff.on_exception(backoff.expo, (aiohttp.ClientError, KeyError), logger=_LOGGER) async def fetch(self, data_type, end_date=None, areas=None): """ Fetch data from API. @@ -201,6 +204,8 @@ async def fetch(self, data_type, end_date=None, areas=None): if areas is None: areas = [] + raise KeyError + # now = datetime.utcnow() # timezone_for_data = now.astimezone(tz.gettz(ts)) # stock = datetime.utcnow().astimezone(tz.gettz("Europe/Stockholm")) diff --git a/custom_components/nordpool/manifest.json b/custom_components/nordpool/manifest.json index c148264..350b7ca 100644 --- a/custom_components/nordpool/manifest.json +++ b/custom_components/nordpool/manifest.json @@ -13,7 +13,8 @@ "iot_class": "cloud_polling", "issue_tracker": "https://github.com/custom-components/nordpool/issues", "requirements": [ - "nordpool>=0.2" + "nordpool>=0.2", + "backoff" ], "version": "0.0.11" -} +} \ No newline at end of file From 98dddb30d753318cd4d52a1444923655ace6de1b Mon Sep 17 00:00:00 2001 From: Hellowlol Date: Sun, 26 Mar 2023 19:30:39 +0200 Subject: [PATCH 2/3] remove async_call_later --- custom_components/nordpool/__init__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/custom_components/nordpool/__init__.py b/custom_components/nordpool/__init__.py index a0b7d33..09538ab 100644 --- a/custom_components/nordpool/__init__.py +++ b/custom_components/nordpool/__init__.py @@ -9,7 +9,7 @@ from homeassistant.core import Config, HomeAssistant from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.dispatcher import async_dispatcher_send -from homeassistant.helpers.event import async_call_later, async_track_time_change +from homeassistant.helpers.event import async_track_time_change from homeassistant.util import dt as dt_utils from pytz import timezone @@ -73,9 +73,6 @@ async def _update(self, type_="today", dt=None): data = await spot.hourly(end_date=dt) if data: self._data[currency][type_] = data["areas"] - else: - _LOGGER.info("Some crap happened, retrying request later.") - async_call_later(hass, 20, partial(self._update, type_=type_, dt=dt)) async def update_today(self, _: datetime): """Update today's prices""" From 3953f37f32e0df5695b4359d28a6858c631d0c5d Mon Sep 17 00:00:00 2001 From: Hellowlol Date: Sun, 26 Mar 2023 22:18:17 +0200 Subject: [PATCH 3/3] some cleanup --- custom_components/nordpool/__init__.py | 2 +- custom_components/nordpool/aio_price.py | 85 ++++++------------------ custom_components/nordpool/manifest.json | 2 +- custom_components/nordpool/misc.py | 13 ++++ custom_components/nordpool/sensor.py | 12 ++-- 5 files changed, 39 insertions(+), 75 deletions(-) diff --git a/custom_components/nordpool/__init__.py b/custom_components/nordpool/__init__.py index 09538ab..6b18935 100644 --- a/custom_components/nordpool/__init__.py +++ b/custom_components/nordpool/__init__.py @@ -32,7 +32,7 @@ NAME = DOMAIN -VERSION = "0.0.11" +VERSION = "0.0.13" ISSUEURL = "https://github.com/custom-components/nordpool/issues" STARTUP = f""" diff --git a/custom_components/nordpool/aio_price.py b/custom_components/nordpool/aio_price.py index 39d84d2..5a947b0 100644 --- a/custom_components/nordpool/aio_price.py +++ b/custom_components/nordpool/aio_price.py @@ -9,7 +9,7 @@ import aiohttp from nordpool.elspot import Prices -from .misc import add_junk +from .misc import add_junk, exceptions_raiser _LOGGER = logging.getLogger(__name__) @@ -143,8 +143,6 @@ def join_result_for_correct_time(results, dt): else: fin["areas"][key]["values"].append(val) - # _LOGGER.debug("Combines result: %s", fin) - return fin @@ -179,6 +177,8 @@ async def _fetch_json(self, data_type, end_date=None): endDate=end_date.strftime("%d-%m-%Y"), ) + # Add more exceptions as we find them. KeyError is raised when the api return + # junk due to currency not being available in the data. @backoff.on_exception(backoff.expo, (aiohttp.ClientError, KeyError), logger=_LOGGER) async def fetch(self, data_type, end_date=None, areas=None): """ @@ -204,69 +204,22 @@ async def fetch(self, data_type, end_date=None, areas=None): if areas is None: areas = [] - raise KeyError - - # now = datetime.utcnow() - # timezone_for_data = now.astimezone(tz.gettz(ts)) - # stock = datetime.utcnow().astimezone(tz.gettz("Europe/Stockholm")) - # if stock.utcoffset(now) == timezone_for_data.utcoffset(now): - # pass - - # compare utc offset - if self.timeezone == tz.gettz("Europe/Stockholm"): - data = await self._fetch_json(data_type, end_date) - return self._parse_json(data, areas) - else: - yesterday = datetime.now() - timedelta(days=1) - today = datetime.now() - tomorrow = datetime.now() + timedelta(days=1) - - # days = [yesterday, today, tomorrow] - # Workaround for api changes. - # Disabled for now as nordpool have fixed the api endpoint that we used. - # if self.currency != "EUR": - # # Only need to check for today price - # # as this is only available for dk, nor, se - # # and all of them are in the correct timezone. - # days = [today, tomorrow] - # idx_list = COUNTRY_BASE_PAGE.values() - # stuff = [] - # for d in days: - # dat = {"areas": {}} - # for pageidx in idx_list: - # task = self._io( - # self.API_URL_CURRENCY % pageidx, - # currency=self.currency, - # endDate=d.strftime("%d-%m-%Y"), - # ) - # data = await task - # - # try: - # jd = self._parse_json(data, areas) - # - # for key, value in jd.get("areas").items(): - # dat["areas"][key] = value - # - # except Exception as e: - # _LOGGER.debug("Error with %s %s", d, pageidx) - # raise - # - # stuff.append(dat) - # - # return join_result_for_correct_time(stuff, end_date) - - # else: - - jobs = [ - self._fetch_json(data_type, yesterday), - self._fetch_json(data_type, today), - self._fetch_json(data_type, tomorrow), - ] - - res = await asyncio.gather(*jobs) - - raw = [self._parse_json(i, areas) for i in res] - return join_result_for_correct_time(raw, end_date) + yesterday = datetime.now() - timedelta(days=1) + today = datetime.now() + tomorrow = datetime.now() + timedelta(days=1) + + jobs = [ + self._fetch_json(data_type, yesterday), + self._fetch_json(data_type, today), + self._fetch_json(data_type, tomorrow), + ] + + res = await asyncio.gather(*jobs) + + raw = [self._parse_json(i, areas) for i in res] + # Just to test should be removed + # exceptions_raiser() + return join_result_for_correct_time(raw, end_date) async def hourly(self, end_date=None, areas=None): """Helper to fetch hourly data, see Prices.fetch()""" diff --git a/custom_components/nordpool/manifest.json b/custom_components/nordpool/manifest.json index 350b7ca..1c4c4e7 100644 --- a/custom_components/nordpool/manifest.json +++ b/custom_components/nordpool/manifest.json @@ -16,5 +16,5 @@ "nordpool>=0.2", "backoff" ], - "version": "0.0.11" + "version": "0.0.13" } \ No newline at end of file diff --git a/custom_components/nordpool/misc.py b/custom_components/nordpool/misc.py index ef26aa7..e950abf 100644 --- a/custom_components/nordpool/misc.py +++ b/custom_components/nordpool/misc.py @@ -23,6 +23,19 @@ _LOGGER = logging.getLogger(__name__) +def exceptions_raiser(): + """Utility to check that all exceptions are raised.""" + import aiohttp + import random + + exs = [KeyError, aiohttp.ClientError, None, None, None] + got = random.choice(exs) + if got is None: + pass + else: + raise got + + def round_decimal(number, decimal_places=3): decimal_value = Decimal(number) return decimal_value.quantize(Decimal(10) ** -decimal_places) diff --git a/custom_components/nordpool/sensor.py b/custom_components/nordpool/sensor.py index faf9d9e..a5008dc 100644 --- a/custom_components/nordpool/sensor.py +++ b/custom_components/nordpool/sensor.py @@ -12,11 +12,7 @@ from homeassistant.util import dt as dt_utils # Import sensor entity and classes. -from homeassistant.components.sensor import ( - SensorDeviceClass, - SensorEntity, - SensorStateClass, -) +from homeassistant.components.sensor import SensorDeviceClass, SensorEntity from jinja2 import pass_context from . import ( @@ -139,7 +135,7 @@ async def async_setup_entry(hass, config_entry, async_add_devices): class NordpoolSensor(SensorEntity): "Sensors data" _attr_device_class = SensorDeviceClass.MONETARY - _attr_state_class = SensorStateClass.MEASUREMENT + _attr_suggested_display_precision = None def __init__( self, @@ -158,7 +154,9 @@ def __init__( self._area = area self._currency = currency or _REGIONS[area][0] self._price_type = price_type + # Should be depricated in a future version self._precision = precision + self._attr_suggested_display_precision = precision self._low_price_cutoff = low_price_cutoff self._use_cents = use_cents self._api = api @@ -425,7 +423,7 @@ def extra_state_attributes(self) -> dict: "raw_tomorrow": self.raw_tomorrow, "current_price": self.current_price, "additional_costs_current_hour": self.additional_costs, - "price_in_cents": self._use_cents + "price_in_cents": self._use_cents, } def _add_raw(self, data) -> list: