From 259ee66c5ea75435f1b508de98d2df26e89d9d17 Mon Sep 17 00:00:00 2001 From: Trefor Southwell <48591903+springfall2008@users.noreply.github.com> Date: Mon, 29 Jan 2024 21:22:51 +0000 Subject: [PATCH 1/2] Async fetch history to avoid timeouts --- apps/predbat/predbat.py | 42 +++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/apps/predbat/predbat.py b/apps/predbat/predbat.py index 15c6c1cb2..95040d34b 100644 --- a/apps/predbat/predbat.py +++ b/apps/predbat/predbat.py @@ -18,7 +18,7 @@ import os import yaml -THIS_VERSION = "v7.15.4" +THIS_VERSION = "v7.15.5" TIME_FORMAT = "%Y-%m-%dT%H:%M:%S%z" TIME_FORMAT_SECONDS = "%Y-%m-%dT%H:%M:%S.%f%z" TIME_FORMAT_OCTOPUS = "%Y-%m-%d %H:%M:%S%z" @@ -995,10 +995,10 @@ def find_charge_curve(self): if soc_kwh_sensor and charge_rate_sensor and battery_power_sensor and predbat_status_sensor: battery_power_sensor = battery_power_sensor.replace("number.", "sensor.") # Workaround as old template had number. self.log("Find charge curve with sensors {} and {} and {} and {}".format(soc_kwh_sensor, charge_rate_sensor, predbat_status_sensor, battery_power_sensor)) - soc_kwh_data = self.base.get_history(entity_id=soc_kwh_sensor, days=self.base.max_days_previous) - charge_rate_data = self.base.get_history(entity_id=charge_rate_sensor, days=self.base.max_days_previous) - predbat_status_data = self.base.get_history(entity_id=predbat_status_sensor, days=self.base.max_days_previous) - battery_power_data = self.base.get_history(entity_id=battery_power_sensor, days=self.base.max_days_previous) + soc_kwh_data = self.base.get_history_async(entity_id=soc_kwh_sensor, days=self.base.max_days_previous) + charge_rate_data = self.base.get_history_async(entity_id=charge_rate_sensor, days=self.base.max_days_previous) + predbat_status_data = self.base.get_history_async(entity_id=predbat_status_sensor, days=self.base.max_days_previous) + battery_power_data = self.base.get_history_async(entity_id=battery_power_sensor, days=self.base.max_days_previous) if soc_kwh_data and charge_rate_data and charge_rate_data and battery_power_data: soc_kwh = self.base.minute_data( @@ -3035,6 +3035,32 @@ def load_car_energy(self, now_utc): self.log("Car charging hold {} threshold {}".format(self.car_charging_hold, self.car_charging_threshold * 60.0)) return self.car_charging_energy + async def get_history_async_hook(self, result, entity_id, days): + """ + Async function to get history from HA + """ + if days: + result['data'] = await self.get_history(entity_id=entity_id, days=days) + else: + result['data'] = await self.get_history(entity_id=entity_id) + + def get_history_async(self, entity_id, days=None): + """ + Async function to get history from HA using Async task + """ + result = {} + task = self.create_task(self.get_history_async_hook(result, entity_id=entity_id, days=days)) + cnt = 0 + while not task.done() and (cnt < 120): + time.sleep(0.05) + cnt += 0.05 + + if 'data' in result: + return result['data'] + else: + self.log("Failure to fetch history for {}".format(entity_id)) + raise ValueError + def minute_data_import_export(self, now_utc, key, scale=1.0): """ Download one or more entities for import/export data @@ -3046,7 +3072,7 @@ def minute_data_import_export(self, now_utc, key, scale=1.0): import_today = {} for entity_id in entity_ids: try: - history = self.get_history(entity_id=entity_id, days=self.max_days_previous) + history = self.get_history_async(entity_id=entity_id, days=self.max_days_previous) except (ValueError, TypeError): history = [] @@ -3072,7 +3098,7 @@ def minute_data_load(self, now_utc, entity_name, max_days_previous): load_minutes = {} age_days = None for entity_id in entity_ids: - history = self.get_history(entity_id=entity_id, days=max_days_previous) + history = self.get_history_async(entity_id=entity_id, days=max_days_previous) if history: item = history[0][0] try: @@ -10842,7 +10868,7 @@ def load_user_config(self, quiet=True, register=False): # Get from history? if ha_value is None: - history = self.get_history(entity_id=entity) + history = self.get_history_async(entity_id=entity) if history: history = history[0] ha_value = history[-1]["state"] From 923c3f0b5f0898f97e8cdf338195d42762191498 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 21:24:24 +0000 Subject: [PATCH 2/2] [pre-commit.ci lite] apply automatic fixes --- apps/predbat/predbat.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/predbat/predbat.py b/apps/predbat/predbat.py index 95040d34b..febff66c4 100644 --- a/apps/predbat/predbat.py +++ b/apps/predbat/predbat.py @@ -3040,9 +3040,9 @@ async def get_history_async_hook(self, result, entity_id, days): Async function to get history from HA """ if days: - result['data'] = await self.get_history(entity_id=entity_id, days=days) + result["data"] = await self.get_history(entity_id=entity_id, days=days) else: - result['data'] = await self.get_history(entity_id=entity_id) + result["data"] = await self.get_history(entity_id=entity_id) def get_history_async(self, entity_id, days=None): """ @@ -3052,11 +3052,11 @@ def get_history_async(self, entity_id, days=None): task = self.create_task(self.get_history_async_hook(result, entity_id=entity_id, days=days)) cnt = 0 while not task.done() and (cnt < 120): - time.sleep(0.05) + time.sleep(0.05) cnt += 0.05 - if 'data' in result: - return result['data'] + if "data" in result: + return result["data"] else: self.log("Failure to fetch history for {}".format(entity_id)) raise ValueError