Skip to content

Commit

Permalink
refactor: updates for Home Assistant v2022.05.0+
Browse files Browse the repository at this point in the history
fix: fixed certain sensor features not working due to inheritance

refactor: substituted selectors config to target integration

chore: cleaned up obsolete code

BREAKING CHANGE: removed dev_presentation key completely

BREAKING CHANGE: reset device classes
  • Loading branch information
alryaz committed May 17, 2022
1 parent f9a25ea commit e9978cd
Show file tree
Hide file tree
Showing 10 changed files with 1,762 additions and 2,270 deletions.
1,614 changes: 807 additions & 807 deletions README.md

Large diffs are not rendered by default.

102 changes: 2 additions & 100 deletions custom_components/lkcomu_interrao/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

import asyncio
import logging
import re
from abc import abstractmethod
from datetime import timedelta
from typing import (
Expand All @@ -23,7 +22,6 @@
Iterable,
List,
Mapping,
MutableMapping,
Optional,
Set,
SupportsInt,
Expand All @@ -46,7 +44,7 @@
from homeassistant.helpers import entity_platform
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.typing import ConfigType, HomeAssistantType, StateType
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from homeassistant.util import as_local, utcnow

from custom_components.lkcomu_interrao._util import (
Expand All @@ -61,7 +59,6 @@
ATTR_ACCOUNT_CODE,
ATTR_ACCOUNT_ID,
CONF_ACCOUNTS,
CONF_DEV_PRESENTATION,
CONF_NAME_FORMAT,
DATA_API_OBJECTS,
DATA_ENTITIES,
Expand All @@ -72,7 +69,6 @@
FORMAT_VAR_ACCOUNT_CODE,
FORMAT_VAR_ACCOUNT_ID,
FORMAT_VAR_CODE,
FORMAT_VAR_ID,
FORMAT_VAR_PROVIDER_CODE,
FORMAT_VAR_PROVIDER_NAME,
SUPPORTED_PLATFORMS,
Expand Down Expand Up @@ -150,9 +146,6 @@ async def async_register_update_delegator(
await async_refresh_api_data(hass, config_entry)


DEV_CLASSES_PROCESSED = set()


async def async_refresh_api_data(hass: HomeAssistantType, config_entry: ConfigEntry):
entry_id = config_entry.entry_id
api: "BaseEnergosbytAPI" = hass.data[DATA_API_OBJECTS][entry_id]
Expand Down Expand Up @@ -204,19 +197,6 @@ async def async_refresh_api_data(hass: HomeAssistantType, config_entry: ConfigEn
entities: EntitiesDataType = hass.data[DATA_ENTITIES][entry_id]
final_config: ConfigType = dict(hass.data[DATA_FINAL_CONFIG][entry_id])

dev_presentation = final_config.get(CONF_DEV_PRESENTATION)
dev_log_prefix = log_prefix_base + "[dev] "

if dev_presentation:
from pprint import pformat

_LOGGER.debug(
dev_log_prefix
+ ("Конечная конфигурация:" if IS_IN_RUSSIA else "Final configuration:")
+ "\n"
+ pformat(final_config)
)

platform_tasks = {}

accounts_config = final_config.get(CONF_ACCOUNTS) or {}
Expand Down Expand Up @@ -249,24 +229,6 @@ async def async_refresh_api_data(hass: HomeAssistantType, config_entry: ConfigEn
)
continue

if dev_presentation:
dev_key = (entity_cls, account.provider_type)
if dev_key in DEV_CLASSES_PROCESSED:
_LOGGER.debug(
cls_log_prefix_base
+ "[dev] "
+ (
f"Пропущен лицевой счёт ({mask_username(account.code)}) "
f"по уникальности типа"
if IS_IN_RUSSIA
else f"Account skipped ({mask_username(account.code)}) "
f"due to type uniqueness"
)
)
continue

DEV_CLASSES_PROCESSED.add(dev_key)

current_entities = entities.setdefault(entity_cls, {})

_LOGGER.debug(
Expand Down Expand Up @@ -396,39 +358,6 @@ def device_info(self) -> Dict[str, Any]:

return device_info

def _handle_dev_presentation(
self,
mapping: MutableMapping[str, Any],
filter_vars: Iterable[str],
blackout_vars: Optional[Iterable[str]] = None,
) -> None:
if self._account_config[CONF_DEV_PRESENTATION]:
filter_vars = set(filter_vars)
if blackout_vars is not None:
blackout_vars = set(blackout_vars)
filter_vars.difference_update(blackout_vars)

for attr in blackout_vars:
value = mapping.get(attr)
if value is not None:
if isinstance(value, float):
value = "#####.###"
elif isinstance(value, int):
value = "#####"
elif isinstance(value, str):
value = "XXXXX"
else:
value = "*****"
mapping[attr] = value

for attr in filter_vars:
value = mapping.get(attr)
if value is not None:
value = re.sub(r"[A-Za-z]", "X", str(value))
value = re.sub(r"[0-9]", "#", value)
value = re.sub(r"\w+", "*", value)
mapping[attr] = value

#################################################################################
# Config getter helpers
#################################################################################
Expand Down Expand Up @@ -477,11 +406,6 @@ def extra_state_attributes(self):
if ATTR_ACCOUNT_CODE not in attributes:
attributes[ATTR_ACCOUNT_CODE] = self._account.code

self._handle_dev_presentation(
attributes,
(ATTR_ACCOUNT_CODE, ATTR_ACCOUNT_ID),
)

return attributes

@property
Expand All @@ -506,12 +430,6 @@ def name(self) -> Optional[str]:
if FORMAT_VAR_PROVIDER_NAME not in name_format_values:
name_format_values[FORMAT_VAR_PROVIDER_NAME] = self._account.provider_name

self._handle_dev_presentation(
name_format_values,
(FORMAT_VAR_CODE, FORMAT_VAR_ACCOUNT_CODE),
(FORMAT_VAR_ACCOUNT_ID, FORMAT_VAR_ID),
)

return self.name_format.format_map(NameFormatDict(name_format_values))

#################################################################################
Expand Down Expand Up @@ -611,19 +529,8 @@ async def async_update_internal(self) -> None:
raise NotImplementedError

@property
@abstractmethod
def code(self) -> str:
raise NotImplementedError

@property
@abstractmethod
def state(self) -> StateType:
raise NotImplementedError

@property
@abstractmethod
def icon(self) -> str:
raise NotImplementedError
return self._account.code

@property
@abstractmethod
Expand All @@ -640,11 +547,6 @@ def name_format_values(self) -> Mapping[str, Any]:
def unique_id(self) -> str:
raise NotImplementedError

@property
@abstractmethod
def device_class(self) -> Optional[str]:
raise NotImplementedError

def register_supported_services(self, for_object: Optional[Any] = None) -> None:
for type_feature, services in self._supported_services.items():
result, features = (
Expand Down
3 changes: 0 additions & 3 deletions custom_components/lkcomu_interrao/_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
API_TYPE_DEFAULT,
API_TYPE_NAMES,
CONF_ACCOUNTS,
CONF_DEV_PRESENTATION,
CONF_LAST_INVOICE,
CONF_LAST_PAYMENT,
CONF_LOGOS,
Expand Down Expand Up @@ -96,7 +95,6 @@ def _validator_name_format_schema(schema):
vol.Optional(CONF_METERS, default=True): cv.boolean,
vol.Optional(CONF_LAST_PAYMENT, default=True): cv.boolean,
vol.Optional(CONF_LOGOS, default=True): cv.boolean,
vol.Optional(CONF_DEV_PRESENTATION, default=False): cv.boolean,
vol.Optional(CONF_NAME_FORMAT, default=lambda: NAME_FORMAT_SCHEMA({})): vol.Any(
vol.All(cv.string, lambda x: {CONF_ACCOUNTS: x}, NAME_FORMAT_SCHEMA),
NAME_FORMAT_SCHEMA,
Expand Down Expand Up @@ -161,7 +159,6 @@ def _make_provider_schema(
vol.Required(CONF_TYPE): PROFILE_TYPE_VALIDATOR,
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_DEV_PRESENTATION, default=False): cv.boolean,
# Additional API configuration
vol.Optional(CONF_USER_AGENT): vol.All(
cv.string, lambda x: " ".join(map(str.strip, x.split("\n")))
Expand Down
55 changes: 9 additions & 46 deletions custom_components/lkcomu_interrao/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@

from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
STATE_OFF,
STATE_ON,
STATE_UNKNOWN,
)
from homeassistant.helpers.typing import ConfigType, StateType
from homeassistant.helpers.typing import ConfigType
from homeassistant.util import slugify

from custom_components.lkcomu_interrao._base import (
Expand All @@ -16,13 +11,7 @@
)
from custom_components.lkcomu_interrao._encoders import payment_to_attrs
from custom_components.lkcomu_interrao.const import (
ATTR_AGENT,
ATTR_AMOUNT,
ATTR_GROUP,
ATTR_PAID_AT,
ATTR_PERIOD,
CONF_LAST_PAYMENT,
DOMAIN,
FORMAT_VAR_ID,
FORMAT_VAR_TYPE_EN,
FORMAT_VAR_TYPE_RU,
Expand All @@ -35,6 +24,8 @@
class LkcomuInterRAOLastPayment(
LkcomuInterRAOEntity[AbstractAccountWithPayments], BinarySensorEntity
):
_attr_icon = "mdi:cash-multiple"

config_key: ClassVar[str] = CONF_LAST_PAYMENT

def __init__(self, *args, last_payment: Optional[AbstractPayment] = None, **kwargs) -> None:
Expand All @@ -46,9 +37,11 @@ def __init__(self, *args, last_payment: Optional[AbstractPayment] = None, **kwar
)

@property
def is_on(self) -> bool:
def is_on(self) -> Optional[bool]:
payment = self._last_payment
return payment is not None and payment.is_accepted
if payment is None:
return None
return payment.is_accepted

@property
def entity_id(self) -> Optional[str]:
Expand Down Expand Up @@ -92,37 +85,11 @@ async def async_update_internal(self) -> None:
# Data-oriented implementation of inherent class
#################################################################################

@property
def code(self) -> str:
return self._account.code

@property
def state(self) -> StateType:
data = self._last_payment

if data is None:
return STATE_UNKNOWN

return STATE_ON if self.is_on else STATE_OFF

@property
def icon(self) -> str:
return "mdi:cash-multiple"

@property
def sensor_related_attributes(self) -> Optional[Mapping[str, Any]]:
payment = self._last_payment

if payment is None:
attributes = {}
else:

attributes = payment_to_attrs(payment)
self._handle_dev_presentation(
attributes, (ATTR_PAID_AT, ATTR_PERIOD), (ATTR_AMOUNT, ATTR_AGENT, ATTR_GROUP)
)

return attributes
if payment:
return payment_to_attrs(payment)

@property
def name_format_values(self) -> Mapping[str, Any]:
Expand All @@ -139,9 +106,5 @@ def unique_id(self) -> str:
acc = self._account
return f"{acc.api.__class__.__name__}_lastpayment_{acc.id}"

@property
def device_class(self) -> Optional[str]:
return DOMAIN + "_payment"


async_setup_entry = make_common_async_setup_entry(LkcomuInterRAOLastPayment)
Loading

0 comments on commit e9978cd

Please sign in to comment.