diff --git a/custom_components/ideenergy/__init__.py b/custom_components/ideenergy/__init__.py index c7433e0..6c8fb49 100644 --- a/custom_components/ideenergy/__init__.py +++ b/custom_components/ideenergy/__init__.py @@ -21,6 +21,7 @@ import math from datetime import timedelta +import ideenergy from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant @@ -28,8 +29,6 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.entity import DeviceInfo -import ideenergy - from .barrier import TimeDeltaBarrier, TimeWindowBarrier # NoopBarrier, from .const import ( API_USER_SESSION_TIMEOUT, diff --git a/custom_components/ideenergy/config_flow.py b/custom_components/ideenergy/config_flow.py index bd5786a..68463fd 100644 --- a/custom_components/ideenergy/config_flow.py +++ b/custom_components/ideenergy/config_flow.py @@ -20,6 +20,7 @@ import os from typing import Any +import ideenergy import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_PASSWORD, CONF_USERNAME @@ -27,8 +28,6 @@ from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers.aiohttp_client import async_create_clientsession -import ideenergy - from . import _LOGGER from .const import CONF_CONTRACT, CONFIG_ENTRY_VERSION, DOMAIN diff --git a/custom_components/ideenergy/datacoordinator.py b/custom_components/ideenergy/datacoordinator.py index b7cdc1f..724f968 100644 --- a/custom_components/ideenergy/datacoordinator.py +++ b/custom_components/ideenergy/datacoordinator.py @@ -21,11 +21,10 @@ from datetime import datetime, timedelta, timezone from typing import Any +import ideenergy from homeassistant.core import dt_util from homeassistant.helpers.update_coordinator import DataUpdateCoordinator -import ideenergy - from .barrier import Barrier, BarrierDeniedError from .const import ( DATA_ATTR_HISTORICAL_CONSUMPTION, diff --git a/custom_components/ideenergy/manifest.json b/custom_components/ideenergy/manifest.json index 5a74359..42bc926 100644 --- a/custom_components/ideenergy/manifest.json +++ b/custom_components/ideenergy/manifest.json @@ -1,16 +1,20 @@ { "domain": "ideenergy", "name": "i-DE Energy Monitor", - "codeowners": ["@ldotlopez"], + "codeowners": [ + "@ldotlopez" + ], "config_flow": true, - "dependencies": ["recorder"], + "dependencies": [ + "recorder" + ], "documentation": "https://github.com/ldotlopez/ha-ideenergy", "integration_type": "device", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/ldotlopez/ha-ideenergy/issues", "requirements": [ - "ideenergy==1.0.0", - "homeassistant-historical-sensor==1.0.1" - ], + "ideenergy==1.0.0", + "homeassistant-historical-sensor==2.0.0b0" + ], "version": "2.0.1" -} \ No newline at end of file +} diff --git a/custom_components/ideenergy/sensor.py b/custom_components/ideenergy/sensor.py index 5e4833a..a95a5eb 100644 --- a/custom_components/ideenergy/sensor.py +++ b/custom_components/ideenergy/sensor.py @@ -27,10 +27,11 @@ import itertools import logging +from collections.abc import Callable # import statistics from datetime import datetime, timedelta -from typing import Any, Callable +from typing import Any from homeassistant.components import recorder from homeassistant.components.recorder import statistics @@ -52,9 +53,8 @@ from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.typing import DiscoveryInfoType from homeassistant.util import dt as dtutil -from homeassistant_historical_sensor import HistoricalSensor, HistoricalState +from homeassistant_historical_sensor import HistoricalSensor, HistoricalState, fixes -from . import fixes from .const import DOMAIN from .datacoordinator import ( DATA_ATTR_HISTORICAL_CONSUMPTION, @@ -97,21 +97,26 @@ def async_update_historical(self) -> None: class StatisticsMixin(HistoricalSensor): @property - def statatistic_id(self): + def statistic_id(self): return self.entity_id - def get_statatistic_metadata(self) -> StatisticMetaData: - meta = super().get_statatistic_metadata() | {"has_sum": True} + def get_statistic_metadata(self) -> StatisticMetaData: + meta = super().get_statistic_metadata() | {"has_sum": True} return meta async def async_added_to_hass(self): await super().async_added_to_hass() - await fixes.async_fix_statistics(self.hass, self.get_statatistic_metadata()) + + # + # In 2.0 branch we f**ked statistiscs. + # Remove in future 3.0 series. + # Don't set state_class attributes for historical sensors! + # + await fixes.async_fix_statistics(self.hass, self.get_statistic_metadata()) async def async_calculate_statistic_data( self, hist_states: list[HistoricalState], *, latest: dict | None ) -> list[StatisticData]: - # # Filter out invalid states # @@ -120,7 +125,7 @@ async def async_calculate_statistic_data( hist_states = [x for x in hist_states if x.state not in (0, None)] if len(hist_states) != n_original_hist_states: _LOGGER.warning( - f"{self.statatistic_id}: " + f"{self.statistic_id}: " f"found some weird values in historical statistics" ) @@ -137,13 +142,6 @@ def hour_block_for_hist_state(hist_state: HistoricalState) -> datetime: else: return hist_state.dt.replace(minute=0, second=0, microsecond=0) - # - # Somehow, somewhere, Home Assistant writes invalid statistics - # FIXME: integrate into homeassistant_historical_sensor and remove - # - - await fixes.async_fix_statistics(self.hass, self.get_statatistic_metadata()) - # # Ignore supplied 'lastest' and fetch again from recorder # FIXME: integrate into homeassistant_historical_sensor and remove @@ -153,7 +151,7 @@ def get_last_statistics(): ret = statistics.get_last_statistics( self.hass, 1, - self.statatistic_id, + self.statistic_id, convert_units=True, types={"last_reset", "max", "mean", "min", "state", "sum"}, ) @@ -161,13 +159,13 @@ def get_last_statistics(): return None try: - return ret[self.statatistic_id][0] + return ret[self.statistic_id][0] except (KeyError, IndexError): _LOGGER.debug( - f"{self.statatistic_id}: [bug] found last statistics but doesn't " + f"{self.statistic_id}: [bug] found last statistics but doesn't " f"have matching key or values: {ret!r}" ) - return None + return [] latest = await recorder.get_instance(self.hass).async_add_executor_job( get_last_statistics @@ -183,7 +181,7 @@ def extract_last_sum(latest) -> float: total_accumulated = extract_last_sum(latest) except (KeyError, ValueError): _LOGGER.error( - f"{self.statatistic_id}: [bug] statistics broken (lastest={latest!r})" + f"{self.statistic_id}: [bug] statistics broken (lastest={latest!r})" ) return [] @@ -192,7 +190,7 @@ def extract_last_sum(latest) -> float: ) _LOGGER.debug( - f"{self.statatistic_id}: " + f"{self.statistic_id}: " + f"calculating statistics using {total_accumulated} as base accumulated " + f"(registed at {start_point_local_dt})" ) @@ -301,7 +299,6 @@ class HistoricalConsumption( def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._attr_device_class = SensorDeviceClass.ENERGY - self._attr_state_class = SensorStateClass.MEASUREMENT self._attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR self._attr_entity_registry_enabled_default = False self._attr_state = None @@ -325,7 +322,6 @@ class HistoricalGeneration( def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._attr_device_class = SensorDeviceClass.ENERGY - self._attr_state_class = SensorStateClass.MEASUREMENT self._attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR self._attr_entity_registry_enabled_default = False self._attr_state = None @@ -347,7 +343,6 @@ class HistoricalPowerDemand(HistoricalSensorMixin, IDeEntity, SensorEntity): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._attr_device_class = SensorDeviceClass.POWER - self._attr_state_class = SensorStateClass.MEASUREMENT self._attr_native_unit_of_measurement = UnitOfPower.WATT self._attr_entity_registry_enabled_default = False self._attr_state = None diff --git a/custom_components/ideenergy/updates.py b/custom_components/ideenergy/updates.py index 423b5c0..671f4b6 100644 --- a/custom_components/ideenergy/updates.py +++ b/custom_components/ideenergy/updates.py @@ -18,13 +18,14 @@ import logging -from custom_components.ideenergy.const import DOMAIN from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry, entity_registry from homeassistant.helpers.entity import DeviceInfo from homeassistant.util import slugify +from custom_components.ideenergy.const import DOMAIN + from .entity import IDeEntity from .entity import _build_entity_unique_id as _build_entity_unique_id_v3 from .sensor import AccumulatedConsumption, HistoricalConsumption @@ -150,7 +151,7 @@ def _update_entity_registry_v1( ("historical", HistoricalConsumption), ) - for (old_sensor_type, new_sensor_cls) in migrate: + for old_sensor_type, new_sensor_cls in migrate: entity_id = er.async_get_entity_id( "sensor", "ideenergy", diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..6407d43 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,6 @@ +[tool.isort] +profile = "black" + + +[tool.pyupgrade] +addopts = "--py310-plus"