From 0c59e2bc086ebcc4a040cfefd918a4f570ac36b8 Mon Sep 17 00:00:00 2001 From: Thomas Papendieck <14850347+tpd-opitz@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:30:50 +0200 Subject: [PATCH 1/5] Update tariff.py - add retry on timeout --- .../energycharts/tariff.py | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/packages/modules/electricity_tariffs/energycharts/tariff.py b/packages/modules/electricity_tariffs/energycharts/tariff.py index 7d878e6a55..223087adbc 100644 --- a/packages/modules/electricity_tariffs/energycharts/tariff.py +++ b/packages/modules/electricity_tariffs/energycharts/tariff.py @@ -1,33 +1,58 @@ +import logging +import random +import requests +import time from typing import Dict from datetime import datetime, timedelta - from helpermodules import timecheck - from modules.common import req from modules.common.abstract_device import DeviceDescriptor from modules.common.component_state import TariffState from modules.electricity_tariffs.energycharts.config import EnergyChartsTariffConfiguration from modules.electricity_tariffs.energycharts.config import EnergyChartsTariff +MAX_RETRIES = 10 +MAX_DELAY = 10 +log = logging.getLogger(__name__) + +def get_tomorrow_last_hour_timestamp() -> int: + tomorrow = datetime.now() + timedelta(days=1) + last_hour = tomorrow.replace(hour=23, minute=59, second=59, microsecond=0) + return int(last_hour.timestamp()) -def fetch_prices(config: EnergyChartsTariffConfiguration) -> Dict[int, float]: - tomorrow = datetime.now() + timedelta(1) +def create_request_url(config: EnergyChartsTariffConfiguration) -> str: start_time = timecheck.create_unix_timestamp_current_full_hour() - end_time = int(tomorrow.timestamp()) + end_time = get_tomorrow_last_hour_timestamp() url = f'https://api.energy-charts.info/price?bzn={config.country}&start={start_time}&end={end_time}' - raw_prices = req.get_http_session().get(url).json() - price_arr = [] - for price in raw_prices['price']: - price_arr.append((float(price + (config.surcharge*10))/1000000)) # €/MWh -> €/Wh + Aufschlag + log.debug("fetching tariffs: %s",url) + return url + +def parse_response(config: EnergyChartsTariffConfiguration, raw_prices: dict) -> Dict[str, float]: prices: Dict[int, float] = {} - prices = dict(zip([str(int(unix_seconds)) for unix_seconds in raw_prices['unix_seconds']], price_arr)) + for timestamp, price_per_MWh in zip(raw_prices['unix_seconds'], raw_prices['price']): + prices[str(int(timestamp))] = float(price_per_MWh + (config.surcharge*10))/1000000 + log.debug("converted prices: %s : %s", len(prices), prices) return prices +def fetch_prices(config: EnergyChartsTariffConfiguration) -> Dict[str, float]: + url = create_request_url(config) + for attempt in range(MAX_RETRIES): + attempt += 1 # starte lesefreundlich mit 1 + try: + response = req.get_http_session().get(url, timeout=(10, 20)) + response.raise_for_status() + return parse_response(config, response.json()); + except requests.exceptions.Timeout as e: + if MAX_RETRIES > attempt: + delay = (attempt) * random.uniform(attempt, MAX_DELAY) + log.warning(f"Timeout beim Abrufen der Preise (Versuch {attempt}/{MAX_RETRIES}) : {str(e)}" + f", neuer Versuch in {delay:.1f} Sekunden...") + time.sleep(delay) + raise Exception("Timeout beim Abrufen der Preise nach {MAX_RETRIES} Versuchen") def create_electricity_tariff(config: EnergyChartsTariff): def updater(): return TariffState(prices=fetch_prices(config.configuration)) return updater - device_descriptor = DeviceDescriptor(configuration_factory=EnergyChartsTariff) From edc3f8b7993cfc407857fd90b6d55cdf2e6d18d1 Mon Sep 17 00:00:00 2001 From: Thomas Papendieck <14850347+tpd-opitz@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:48:00 +0200 Subject: [PATCH 2/5] Update tariff.py fix Flake8 formatting errors --- .../energycharts/tariff.py | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/packages/modules/electricity_tariffs/energycharts/tariff.py b/packages/modules/electricity_tariffs/energycharts/tariff.py index 223087adbc..44a9880832 100644 --- a/packages/modules/electricity_tariffs/energycharts/tariff.py +++ b/packages/modules/electricity_tariffs/energycharts/tariff.py @@ -15,11 +15,13 @@ MAX_DELAY = 10 log = logging.getLogger(__name__) + def get_tomorrow_last_hour_timestamp() -> int: tomorrow = datetime.now() + timedelta(days=1) last_hour = tomorrow.replace(hour=23, minute=59, second=59, microsecond=0) return int(last_hour.timestamp()) + def create_request_url(config: EnergyChartsTariffConfiguration) -> str: start_time = timecheck.create_unix_timestamp_current_full_hour() end_time = get_tomorrow_last_hour_timestamp() @@ -27,32 +29,37 @@ def create_request_url(config: EnergyChartsTariffConfiguration) -> str: log.debug("fetching tariffs: %s",url) return url + def parse_response(config: EnergyChartsTariffConfiguration, raw_prices: dict) -> Dict[str, float]: prices: Dict[int, float] = {} for timestamp, price_per_MWh in zip(raw_prices['unix_seconds'], raw_prices['price']): - prices[str(int(timestamp))] = float(price_per_MWh + (config.surcharge*10))/1000000 + prices[str(int(timestamp))] = float(price_per_MWh + (config.surcharge*10))/1000000 log.debug("converted prices: %s : %s", len(prices), prices) return prices + def fetch_prices(config: EnergyChartsTariffConfiguration) -> Dict[str, float]: url = create_request_url(config) for attempt in range(MAX_RETRIES): - attempt += 1 # starte lesefreundlich mit 1 - try: - response = req.get_http_session().get(url, timeout=(10, 20)) - response.raise_for_status() - return parse_response(config, response.json()); - except requests.exceptions.Timeout as e: - if MAX_RETRIES > attempt: - delay = (attempt) * random.uniform(attempt, MAX_DELAY) - log.warning(f"Timeout beim Abrufen der Preise (Versuch {attempt}/{MAX_RETRIES}) : {str(e)}" - f", neuer Versuch in {delay:.1f} Sekunden...") - time.sleep(delay) + attempt += 1 # one-based indexing + try: + response = req.get_http_session().get(url, timeout=(10, 20)) + response.raise_for_status() + return parse_response(config, response.json()) + except requests.exceptions.Timeout as e: + if MAX_RETRIES > attempt: + delay = (attempt) * random.uniform(attempt, MAX_DELAY) + log.warning(f"Timeout beim Abrufen der Preise (Versuch {attempt}/{MAX_RETRIES}) : {str(e)}" + f", neuer Versuch in {delay:.1f} Sekunden...") + time.sleep(delay) raise Exception("Timeout beim Abrufen der Preise nach {MAX_RETRIES} Versuchen") + def create_electricity_tariff(config: EnergyChartsTariff): def updater(): return TariffState(prices=fetch_prices(config.configuration)) return updater + device_descriptor = DeviceDescriptor(configuration_factory=EnergyChartsTariff) + From d062816f793cae5a8253c0088c5990bdfa18ab0d Mon Sep 17 00:00:00 2001 From: Thomas Papendieck <14850347+tpd-opitz@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:52:24 +0200 Subject: [PATCH 3/5] Update tariff.py fix flake8 errors --- .../energycharts/tariff.py | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/modules/electricity_tariffs/energycharts/tariff.py b/packages/modules/electricity_tariffs/energycharts/tariff.py index 44a9880832..e7ca19c979 100644 --- a/packages/modules/electricity_tariffs/energycharts/tariff.py +++ b/packages/modules/electricity_tariffs/energycharts/tariff.py @@ -26,7 +26,7 @@ def create_request_url(config: EnergyChartsTariffConfiguration) -> str: start_time = timecheck.create_unix_timestamp_current_full_hour() end_time = get_tomorrow_last_hour_timestamp() url = f'https://api.energy-charts.info/price?bzn={config.country}&start={start_time}&end={end_time}' - log.debug("fetching tariffs: %s",url) + log.debug("fetching tariffs: %s", url) return url @@ -41,17 +41,17 @@ def parse_response(config: EnergyChartsTariffConfiguration, raw_prices: dict) -> def fetch_prices(config: EnergyChartsTariffConfiguration) -> Dict[str, float]: url = create_request_url(config) for attempt in range(MAX_RETRIES): - attempt += 1 # one-based indexing - try: - response = req.get_http_session().get(url, timeout=(10, 20)) - response.raise_for_status() - return parse_response(config, response.json()) - except requests.exceptions.Timeout as e: - if MAX_RETRIES > attempt: - delay = (attempt) * random.uniform(attempt, MAX_DELAY) - log.warning(f"Timeout beim Abrufen der Preise (Versuch {attempt}/{MAX_RETRIES}) : {str(e)}" - f", neuer Versuch in {delay:.1f} Sekunden...") - time.sleep(delay) + attempt += 1 # one-based indexing + try: + response = req.get_http_session().get(url, timeout=(10, 20)) + response.raise_for_status() + return parse_response(config, response.json()) + except requests.exceptions.Timeout as e: + if MAX_RETRIES > attempt: + delay = (attempt) * random.uniform(attempt, MAX_DELAY) + log.warning(f"Timeout beim Abrufen der Preise (Versuch {attempt}/{MAX_RETRIES}) : {str(e)}" + f", neuer Versuch in {delay:.1f} Sekunden...") + time.sleep(delay) raise Exception("Timeout beim Abrufen der Preise nach {MAX_RETRIES} Versuchen") From 9b2693a05a4366e22134f9314f6cf66a6174f370 Mon Sep 17 00:00:00 2001 From: Thomas Papendieck <14850347+tpd-opitz@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:54:28 +0200 Subject: [PATCH 4/5] Update tariff.py flake8 errors last line --- packages/modules/electricity_tariffs/energycharts/tariff.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/modules/electricity_tariffs/energycharts/tariff.py b/packages/modules/electricity_tariffs/energycharts/tariff.py index e7ca19c979..77037c0420 100644 --- a/packages/modules/electricity_tariffs/energycharts/tariff.py +++ b/packages/modules/electricity_tariffs/energycharts/tariff.py @@ -62,4 +62,3 @@ def updater(): device_descriptor = DeviceDescriptor(configuration_factory=EnergyChartsTariff) - From 576a16917796b87bc2b61a624913c67fe4c4a64f Mon Sep 17 00:00:00 2001 From: Thomas Papendieck <14850347+tpd-opitz@users.noreply.github.com> Date: Wed, 20 Aug 2025 14:14:06 +0200 Subject: [PATCH 5/5] Update packages/modules/electricity_tariffs/energycharts/tariff.py simpify end time calculation Co-authored-by: benderl --- packages/modules/electricity_tariffs/energycharts/tariff.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/modules/electricity_tariffs/energycharts/tariff.py b/packages/modules/electricity_tariffs/energycharts/tariff.py index 77037c0420..70668920f6 100644 --- a/packages/modules/electricity_tariffs/energycharts/tariff.py +++ b/packages/modules/electricity_tariffs/energycharts/tariff.py @@ -17,9 +17,8 @@ def get_tomorrow_last_hour_timestamp() -> int: - tomorrow = datetime.now() + timedelta(days=1) - last_hour = tomorrow.replace(hour=23, minute=59, second=59, microsecond=0) - return int(last_hour.timestamp()) + tomorrow = datetime.now() + timedelta(days=2) + return int(tomorrow.timestamp()) def create_request_url(config: EnergyChartsTariffConfiguration) -> str: