From b654016384fe9500d693d1a7ba8e4048a62a13f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Eld=C3=A9n?= Date: Tue, 20 Jun 2023 22:26:44 +0200 Subject: [PATCH] proper non-hours --- custom_components/peaqev/manifest.json | 2 +- .../peaqev/peaqservice/hub/hub.py | 84 ++++++++++--------- .../peaqev/sensors/money_sensor.py | 13 ++- .../peaqev/sensors/money_sensor_helpers.py | 41 +++++++-- 4 files changed, 82 insertions(+), 58 deletions(-) diff --git a/custom_components/peaqev/manifest.json b/custom_components/peaqev/manifest.json index 763072e8..b7deb8a4 100644 --- a/custom_components/peaqev/manifest.json +++ b/custom_components/peaqev/manifest.json @@ -22,7 +22,7 @@ "iot_class": "calculated", "issue_tracker": "https://github.com/elden1337/hass-peaq/issues", "requirements": [ - "peaqevcore==19.0.0a8" + "peaqevcore==19.0.0a14" ], "version": "3.0.0a0" } \ No newline at end of file diff --git a/custom_components/peaqev/peaqservice/hub/hub.py b/custom_components/peaqev/peaqservice/hub/hub.py index 42e0835d..b532db11 100644 --- a/custom_components/peaqev/peaqservice/hub/hub.py +++ b/custom_components/peaqev/peaqservice/hub/hub.py @@ -11,45 +11,51 @@ from peaqevcore.services.prediction.prediction import Prediction from peaqevcore.services.threshold.thresholdbase import ThresholdBase -from custom_components.peaqev.peaqservice.chargecontroller.chargecontroller_factory import \ - ChargeControllerFactory -from custom_components.peaqev.peaqservice.chargecontroller.ichargecontroller import \ - IChargeController -from custom_components.peaqev.peaqservice.chargertypes.chargertype_factory import \ - ChargerTypeFactory -from custom_components.peaqev.peaqservice.chargertypes.icharger_type import \ - IChargerType -from custom_components.peaqev.peaqservice.chargertypes.models.chargertypes_enum import \ - ChargerType -from custom_components.peaqev.peaqservice.hub.factories.hourselection_factory import \ - HourselectionFactory -from custom_components.peaqev.peaqservice.hub.factories.threshold_factory import \ - ThresholdFactory -from custom_components.peaqev.peaqservice.hub.hub_initializer import \ - HubInitializer -from custom_components.peaqev.peaqservice.hub.max_min_controller import \ - MaxMinController -from custom_components.peaqev.peaqservice.hub.models.hub_options import \ - HubOptions -from custom_components.peaqev.peaqservice.hub.nordpool.nordpool import \ - NordPoolUpdater -from custom_components.peaqev.peaqservice.hub.observer.observer_coordinator import \ - Observer -from custom_components.peaqev.peaqservice.hub.sensors.hubsensors_factory import \ - HubSensorsFactory -from custom_components.peaqev.peaqservice.hub.sensors.ihub_sensors import \ - HubSensors +from custom_components.peaqev.peaqservice.chargecontroller.chargecontroller_factory import ( + ChargeControllerFactory, +) +from custom_components.peaqev.peaqservice.chargecontroller.ichargecontroller import ( + IChargeController, +) +from custom_components.peaqev.peaqservice.chargertypes.chargertype_factory import ( + ChargerTypeFactory, +) +from custom_components.peaqev.peaqservice.chargertypes.icharger_type import IChargerType +from custom_components.peaqev.peaqservice.chargertypes.models.chargertypes_enum import ( + ChargerType, +) +from custom_components.peaqev.peaqservice.hub.factories.hourselection_factory import ( + HourselectionFactory, +) +from custom_components.peaqev.peaqservice.hub.factories.threshold_factory import ( + ThresholdFactory, +) +from custom_components.peaqev.peaqservice.hub.hub_initializer import HubInitializer +from custom_components.peaqev.peaqservice.hub.max_min_controller import MaxMinController +from custom_components.peaqev.peaqservice.hub.models.hub_options import HubOptions +from custom_components.peaqev.peaqservice.hub.nordpool.nordpool import NordPoolUpdater +from custom_components.peaqev.peaqservice.hub.observer.observer_coordinator import ( + Observer, +) +from custom_components.peaqev.peaqservice.hub.sensors.hubsensors_factory import ( + HubSensorsFactory, +) +from custom_components.peaqev.peaqservice.hub.sensors.ihub_sensors import HubSensors from custom_components.peaqev.peaqservice.hub.servicecalls import ServiceCalls -from custom_components.peaqev.peaqservice.hub.state_changes.istate_changes import \ - IStateChanges -from custom_components.peaqev.peaqservice.hub.state_changes.state_changes_factory import \ - StateChangesFactory -from custom_components.peaqev.peaqservice.powertools.powertools_factory import \ - PowerToolsFactory -from custom_components.peaqev.peaqservice.util.constants import \ - CHARGERCONTROLLER +from custom_components.peaqev.peaqservice.hub.state_changes.istate_changes import ( + IStateChanges, +) +from custom_components.peaqev.peaqservice.hub.state_changes.state_changes_factory import ( + StateChangesFactory, +) +from custom_components.peaqev.peaqservice.powertools.powertools_factory import ( + PowerToolsFactory, +) +from custom_components.peaqev.peaqservice.util.constants import CHARGERCONTROLLER from custom_components.peaqev.peaqservice.util.extensionmethods import ( - async_iscoroutine, nametoid) + async_iscoroutine, + nametoid, +) _LOGGER = logging.getLogger(__name__) @@ -195,9 +201,6 @@ async def async_set_chargingtracker_entities(self) -> list: def _set_observers(self) -> None: self.observer.add("prices changed", self.async_update_prices) - # self.observer.add( - # "monthly average price changed", self.async_update_average_monthly_price - # ) self.observer.add( "weekly average price changed", self.async_update_average_weekly_price ) @@ -242,6 +245,7 @@ async def async_request_sensor_data(self, *args) -> dict | any: "prices": partial(getattr, self.hours, "prices", []), "prices_tomorrow": partial(getattr, self.hours, "prices_tomorrow", []), "non_hours": partial(getattr, self, "non_hours", []), + "future_hours": partial(getattr, self.hours, "future_hours", []), "caution_hours": partial(getattr, self.hours, "caution_hours", []), "dynamic_caution_hours": partial( getattr, self, "dynamic_caution_hours", {} diff --git a/custom_components/peaqev/sensors/money_sensor.py b/custom_components/peaqev/sensors/money_sensor.py index 11b0e5f0..92584401 100644 --- a/custom_components/peaqev/sensors/money_sensor.py +++ b/custom_components/peaqev/sensors/money_sensor.py @@ -9,8 +9,7 @@ from homeassistant.helpers.restore_state import RestoreEntity -from custom_components.peaqev.peaqservice.chargecontroller.const import \ - CHARGING_ALLOWED +from custom_components.peaqev.peaqservice.chargecontroller.const import CHARGING_ALLOWED from custom_components.peaqev.peaqservice.util.constants import HOURCONTROLLER from custom_components.peaqev.sensors.money_sensor_helpers import * from custom_components.peaqev.sensors.sensorbase import SensorBase @@ -57,7 +56,6 @@ async def async_update(self) -> None: "non_hours", "dynamic_caution_hours", "currency", - "offsets", "average_nordpool_data", "use_cent", "current_peak", @@ -68,19 +66,18 @@ async def async_update(self) -> None: "max_price", "min_price", "average_30", + "future_hours", ) if ret is not None: self._state = await self.async_state_display( ret.get("non_hours", []), ret.get("dynamic_caution_hours", {}) ) - self._nonhours = set_non_hours_display( - ret.get("non_hours", []), ret.get("prices_tomorrow", []) - ) + self._all_hours = set_all_hours_display(ret.get("future_hours", [])) + self._nonhours = set_non_hours_display(ret.get("non_hours", [])) self._dynamic_caution_hours = set_caution_hours_display( ret.get("dynamic_caution_hours", {}) ) self._currency = ret.get("currency") - self._offsets = ret.get("offsets", {}) self._current_peak = ret.get("current_peak") self._max_charge = set_total_charge(ret.get("max_charge")) self._average_nordpool_data = ret.get("average_nordpool_data", []) @@ -138,7 +135,7 @@ def extra_state_attributes(self) -> dict: "Nordpool average 30 days": self._average_data_30, "nordpool_average_this_month": self._average_data_current_month, "Nordpool average data": self._average_nordpool_data, - "offsets": self._offsets, + "All hours": self._all_hours, } if self.hub.options.price.dynamic_top_price: attr_dict["Max price based on"] = self._max_price_based_on diff --git a/custom_components/peaqev/sensors/money_sensor_helpers.py b/custom_components/peaqev/sensors/money_sensor_helpers.py index e6029a56..b6e0e386 100644 --- a/custom_components/peaqev/sensors/money_sensor_helpers.py +++ b/custom_components/peaqev/sensors/money_sensor_helpers.py @@ -1,4 +1,8 @@ -from datetime import datetime +from datetime import datetime, timedelta +import logging +from peaqevcore.services.hoursselection_service_new.models.hour_price import HourPrice + +_LOGGER = logging.getLogger(__name__) def calculate_stop_len(nonhours) -> str: @@ -67,25 +71,44 @@ def set_total_charge(max_charge) -> str: return f"{max_charge[0]} kWh" -def set_non_hours_display(non_hours: list, prices_tomorrow: list) -> list: +def set_all_hours_display(future_hours: list[HourPrice]) -> dict: + ret = {} + for h in future_hours: + dtstr = f"{h.dt.hour:02d}:{h.dt.minute:02d}" + if h.dt.date() == datetime.now().date(): + dtstr = f"Today {dtstr}" + else: + dtstr = f"Tomorrow {dtstr}" + + match h.permittance: + case 0: + ret[dtstr] = "Stop" + case 1: + ret[dtstr] = "Start" + case _: + ret[dtstr] = f"Caution {str(h.permittance * 100)}%" + return ret + + +def set_non_hours_display(non_hours: list[datetime]) -> list: ret = [] - now = datetime.now().replace(minute=0,second=0,microsecond=0) + now = datetime.now().replace(minute=0, second=0, microsecond=0) for i in non_hours: - if i < now and len(prices_tomorrow) > 0: + if i.date() > now.date(): ret.append(f"{str(i.hour)}⁺¹") - elif i >= now: + elif i.date() == now.date(): ret.append(str(i.hour)) return ret -def set_caution_hours_display(dynamic_caution_hours: dict) -> dict: +def set_caution_hours_display(dynamic_caution_hours: dict[datetime, float]) -> dict: ret = {} if len(dynamic_caution_hours) > 0: for h in dynamic_caution_hours: - if h < datetime.now().hour: - hh = f"{h}⁺¹" + if h.date() > datetime.now().date(): + hh = f"{h.hour}⁺¹" else: - hh = h + hh = h.hour ret[hh] = f"{str((int(dynamic_caution_hours.get(h, 0) * 100)))}%" return ret