Skip to content

Commit

Permalink
✨ new options (optional)
Browse files Browse the repository at this point in the history
Feature request: add pull of "Einheiten" and old data #1
Feature request: Set pull intervall #2
correction of value seperator  #3

Signed-off-by: Ludy87 <Ludy87@users.noreply.github.com>
  • Loading branch information
Ludy87 committed May 7, 2022
1 parent 29028ce commit 40b0f6d
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 39 deletions.
12 changes: 12 additions & 0 deletions custom_components/ecotrend_ista/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
CONF_CONTROLLER,
CONF_EMAIL,
CONF_PASSWORD,
CONF_UNIT,
CONF_UPDATE_FREQUENCY,
CONF_YEAR,
CONF_YEARMONTH,
DEFAULT_SCAN_INTERVAL_TIME,
DOMAIN,
)
Expand All @@ -30,6 +33,9 @@
{
vol.Required(CONF_EMAIL): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_UNIT, default=""): cv.string,
vol.Optional(CONF_YEAR, default=[]): cv.ensure_list,
vol.Optional(CONF_YEARMONTH, default=[]): cv.ensure_list,
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): cv.time_period,
}
)
Expand All @@ -43,7 +49,10 @@
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
hass.data[CONF_EMAIL] = []
hass.data[CONF_PASSWORD] = []
hass.data[CONF_UNIT] = []
hass.data[CONF_UPDATE_FREQUENCY] = []
hass.data[CONF_YEAR] = []
hass.data[CONF_YEARMONTH] = []
hass.data[DOMAIN] = []
success = False
for controller_config in config[DOMAIN]:
Expand All @@ -59,7 +68,10 @@ async def _setup_controller(hass: HomeAssistant, controller_config, config: Conf
position = len(hass.data[DOMAIN])
hass.data[CONF_EMAIL].append(email)
hass.data[CONF_PASSWORD].append(password)
hass.data[CONF_UNIT].append(controller_config[CONF_UNIT])
hass.data[CONF_UPDATE_FREQUENCY].append(controller_config[CONF_SCAN_INTERVAL])
hass.data[CONF_YEAR].append(controller_config[CONF_YEAR])
hass.data[CONF_YEARMONTH].append(controller_config[CONF_YEARMONTH])
hass.data[DOMAIN].append(eco)

for platform in PLATFORMS:
Expand Down
6 changes: 5 additions & 1 deletion custom_components/ecotrend_ista/const.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
DOMAIN = "ecotrend_ista"

DEFAULT_SCAN_INTERVAL_TIME = 3 * 60 * 10
DEFAULT_SCAN_INTERVAL_TIME = 11 * 60 * 60

CONF_CONTROLLER = "controller"
CONF_EMAIL = "email"
CONF_PASSWORD = "password"
CONF_UPDATE_FREQUENCY = "update_frequency"

CONF_UNIT = "unit"
CONF_YEARMONTH = "yearmonth"
CONF_YEAR = "year"

CONF_TYPE_HEATING = "heating"
CONF_TYPE_HEATWATER = "warmwater"
69 changes: 69 additions & 0 deletions custom_components/ecotrend_ista/entity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Entity ecotrend-ista."""
from __future__ import annotations

import logging
import datetime

from typing import Any, Dict, Mapping

from homeassistant.components.sensor import SensorEntity, SensorEntityDescription
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import StateType

from pyecotrend_ista import pyecotrend_ista as ista

from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)


class EcoEntity(SensorEntity, RestoreEntity):
def __init__(
self, controller: ista.PyEcotrendIsta, description: SensorEntityDescription, consum: Dict[str, Any], unit: str
) -> None:
self._controller = controller
self._supportCode = controller.getSupportCode()
self.entity_description = description
self._consum = consum
self._name = "{}".format(self._consum.get("entity_id"))
self._attr_unique_id = self._name
self._attr_last_reset = datetime.datetime.now()
self._unit = unit

@property
def name(self) -> str | None:
"""Return the name of the entity."""
return self._name

@property
def native_unit_of_measurement(self) -> str | None:
"""Return the unit of measurement of this entity, if any."""
return self._consum.get("unit{}".format(self._unit))

@property
def native_value(self) -> StateType:
"""Return the value reported by the sensor."""
return float(str(self._consum.get("value{}".format(self._unit))).replace(",", "."))

@property
def device_info(self) -> DeviceInfo:
"""Return a device description for device registry."""
return DeviceInfo(
identifiers={(DOMAIN, self._attr_unique_id)},
manufacturer="ista",
name=self._name,
)

@property
def extra_state_attributes(self) -> Mapping[str, Any] | None:
"""Return entity specific state attributes.
Implemented by platform classes. Convention for attribute names
is lowercase snake_case.
"""
return {
"unit": self._consum.get("unit"),
"value": float(str(self._consum.get("value")).replace(",", ".")),
"unitkwh": self._consum.get("unitkwh"),
"valuekwh": float(str(self._consum.get("valuekwh")).replace(",", ".")),
}
158 changes: 120 additions & 38 deletions custom_components/ecotrend_ista/sensor.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"""Support for reading status from ecotren-ists."""
from __future__ import annotations

import logging

from datetime import timedelta
from typing import Any, List
from typing import Any, Dict, List
from .entity import EcoEntity

from homeassistant.components.sensor import (
SensorDeviceClass,
Expand All @@ -13,17 +15,20 @@
)
from homeassistant.const import ENERGY_KILO_WATT_HOUR
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import Throttle

from .const import (
CONF_CONTROLLER,
CONF_UNIT,
CONF_TYPE_HEATING,
CONF_TYPE_HEATWATER,
CONF_UPDATE_FREQUENCY,
CONF_YEAR,
CONF_YEARMONTH,
DOMAIN,
)

Expand Down Expand Up @@ -61,59 +66,136 @@ async def async_setup_platform(
return
controller: ista.PyEcotrendIsta = hass.data[DOMAIN][discovery_info[CONF_CONTROLLER]]
_LOGGER.debug(f"PyEcotrendIsta version: {controller.getVersion()}")
consums: List[Any] = await controller.consum_small()
unit = hass.data[CONF_UNIT][discovery_info[CONF_CONTROLLER]]
updateTime = hass.data[CONF_UPDATE_FREQUENCY][discovery_info[CONF_CONTROLLER]]
sc: str = controller.getSupportCode()
year: List[str] = hass.data[CONF_YEAR][discovery_info[CONF_CONTROLLER]]
yearmonth: List[str] = hass.data[CONF_YEARMONTH][discovery_info[CONF_CONTROLLER]]

entities: List[EcoSensor] = []
device_id: List[str] = []

consums: List[Dict[str, Any]] = await controller.getConsumsNow()

sc: str = controller.getSupportCode().lower()

entities: List[Any] = []

for description in SENSOR_TYPES:
for consum in consums:
if "type" in consum:
if consums:
for consum in consums:
if description.key in consum["type"]:
entities.append(EcoSensor(description, consum, sc, controller, updateTime))
if not device_id or consum.get("entity_id") not in device_id:
entities.append(EcoSensor(controller, description, consum, updateTime, unit))
device_id.append(consum.get("entity_id", ""))
if yearmonth:
for ym in yearmonth:
ymL: List[str] = ym.split(".")
if len(ymL) != 2:
_LOGGER.error("wrong format! just format in yyyy.m")
continue
yyyy = int(ymL[0])
m = int(ymL[1])

consumsyearmonth: Dict[str, Any] = await controller.getConsumById(
"{}_{}_{}_{}".format(description.key, yyyy, m, sc)
) # warmwasser_yyyy_m_xxxxxxxxx
if consumsyearmonth:
if not device_id or consumsyearmonth.get("entity_id") not in device_id:
entities.append(
EcoYearMonthSensor(controller, description, consumsyearmonth, updateTime, yyyy, m, unit)
)
device_id.append(consumsyearmonth.get("entity_id", ""))
_LOGGER.debug("load yearmonth")
if year:
for y in year:
consumsyear: List[Dict[str, Any]] = await controller.getConsumsByYear(y)
if consumsyear:
for consum in consumsyear:
if not device_id or consum.get("entity_id") not in device_id:
entities.append(EcoYearSensor(controller, description, consum, updateTime, y, unit))
device_id.append(consum.get("entity_id", ""))
_LOGGER.debug("load year")

add_entities(entities, True)


class EcoSensor(SensorEntity, RestoreEntity):
class EcoYearSensor(EcoEntity, SensorEntity, RestoreEntity):
def __init__(
self,
controller: ista.PyEcotrendIsta,
description: SensorEntityDescription,
consum: List[Any],
supportCode: str,
consum: Dict[str, Any],
updateTime: timedelta,
year: str,
unit: str,
) -> None:
super().__init__(controller, description, consum, unit)
self.scan_interval = updateTime
self.async_update = Throttle(self.scan_interval)(self._async_update)
_LOGGER.debug(f"EcoYearSensor set Sensor: {self.entity_description.key} | update interval: {updateTime}")

self._year = year

async def _async_update(self) -> None:
consum: Dict[str, Any] = await self._controller.getConsumById(self._name) # warmwasser_yyyy_m_xxxxxxxxx
if self.entity_description.key == consum.get("type"):
self._attr_native_value = consum.get("valuekwh")
_LOGGER.debug(
"Updating EcoYearSensor: %s | Verbrauch: %s",
self._name,
str(self._attr_native_value),
)


class EcoYearMonthSensor(EcoEntity, SensorEntity, RestoreEntity):
def __init__(
self,
controller: ista.PyEcotrendIsta,
description: SensorEntityDescription,
consum: Dict[str, Any],
updateTime: timedelta,
year: int,
month: int,
unit: str,
) -> None:
self._attr_name = f"{description.name} {supportCode}".title()
self._attr_unique_id = f"{DOMAIN}.{description.key}_{supportCode}"
self._attr_unit_of_measurement = description.native_unit_of_measurement
self._controller = controller
self.entity_description = description
self._consum = consum
self._attr_native_value = self._consum["valuekwh"]
self._supportCode = supportCode
super().__init__(controller, description, consum, unit)
self.scan_interval = updateTime
self.async_update = Throttle(self.scan_interval)(self._async_update)
_LOGGER.debug(f"set Sensor: {self.entity_description.key} | update interval: {updateTime}")
_LOGGER.debug(f"EcoYearMonthSensor set Sensor: {self.entity_description.key} | update interval: {updateTime}")

@property
def device_info(self) -> DeviceInfo:
"""Return a device description for device registry."""
return DeviceInfo(
identifiers={(DOMAIN, self._supportCode)},
manufacturer="ista",
name=self._attr_name,
)
self._year = year
self._month = month

async def _async_update(self) -> None:
consum: Dict[str, Any] = await self._controller.getConsumById(self._name) # warmwasser_yyyy_m_xxxxxxxxx
if self.entity_description.key == consum.get("type"):
self._attr_native_value = consum.get("valuekwh")
_LOGGER.debug(
"Updating EcoYearMonthSensor: %s | Verbrauch: %s",
self._name,
str(self._attr_native_value),
)


class EcoSensor(EcoEntity, SensorEntity, RestoreEntity):
def __init__(
self,
controller: ista.PyEcotrendIsta,
description: SensorEntityDescription,
consum: Dict[str, Any],
updateTime: timedelta,
unit: str,
) -> None:
super().__init__(controller, description, consum, unit)
self.scan_interval = updateTime
self.async_update = Throttle(self.scan_interval)(self._async_update)
_LOGGER.debug(f"set EcoSensor: {self.entity_description.key} | update interval: {updateTime}")

async def _async_update(self) -> None:
consums: List[Any] = await self._controller.consum_small()
for consum in consums:
if "type" in consum:
if self.entity_description.key in consum["type"]:
self._attr_native_value = consum["valuekwh"]
_LOGGER.debug(
"Updating sensor: %s | Verbrauch: %s",
self._attr_name,
str(self._attr_native_value),
)
consum: Dict[str, Any] = await self._controller.getConsumById(self._name, True) # warmwasser_xxxxxxxxx
if self.entity_description.key == consum.get("type"):
self._attr_native_value = consum.get("valuekwh")
_LOGGER.debug(
"Updating EcoSensor: %s | Verbrauch: %s",
self._name,
str(self._attr_native_value),
)

0 comments on commit 40b0f6d

Please sign in to comment.