Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle Long entity names #115

Merged
merged 9 commits into from
May 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions custom_components/iec/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .commons import get_device_info
from .commons import get_device_info, IecEntityType
from .const import DOMAIN, STATICS_DICT_NAME, INVOICE_DICT_NAME, \
EMPTY_INVOICE, ATTRIBUTES_DICT_NAME, METER_ID_ATTR_NAME
from .coordinator import IecApiCoordinator
Expand Down Expand Up @@ -84,7 +84,8 @@ def __init__(
):
"""Initialize the sensor."""
super().__init__(coordinator, str(int(contract_id)),
attributes_to_add.get(METER_ID_ATTR_NAME) if attributes_to_add else None)
attributes_to_add.get(METER_ID_ATTR_NAME) if attributes_to_add else None,
IecEntityType.CONTRACT)
self.entity_description = entity_description
self._attr_unique_id = f"{str(contract_id)}_{entity_description.key}"

Expand All @@ -111,4 +112,4 @@ def is_on(self) -> bool | None:
@property
def device_info(self) -> DeviceInfo:
"""Return the device info."""
return get_device_info(self.contract_id, self.meter_id)
return get_device_info(self.contract_id, None, IecEntityType.CONTRACT)
37 changes: 27 additions & 10 deletions custom_components/iec/commons.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""IEC common functions."""
from datetime import datetime
from enum import Enum

from homeassistant.helpers.device_registry import DeviceInfo
from iec_api.models.remote_reading import RemoteReading

from custom_components.iec import DOMAIN
from custom_components.iec.const import STATICS_DICT_NAME


def find_reading_by_date(daily_reading: RemoteReading, desired_date: datetime) -> bool:
Expand All @@ -29,32 +29,49 @@ def find_reading_by_date(daily_reading: RemoteReading, desired_date: datetime) -
daily_reading.date.day == desired_date.day) # Checks if the dates match


def get_device_info(contract_id: str, meter_id: str | None) -> DeviceInfo:
class IecEntityType(Enum):
"""Entity type."""

GENERIC = 1
CONTRACT = 2
METER = 3


def get_device_info(contract_id: str, meter_id: str | None, iec_entity_type: IecEntityType = IecEntityType.GENERIC) \
-> DeviceInfo:
"""Get device information based on contract ID and optional meter ID.

Args:
contract_id (str): The contract ID.
meter_id (str, optional): The meter ID, if available.
iec_entity_type (IecEntityType): The Entity Type

Returns:
DeviceInfo: An object containing device information.

"""

if contract_id == STATICS_DICT_NAME:
name = "IEC Static Data"
else:
contract_id = str(int(contract_id))
name = f"IEC Contract {contract_id}{((' - Meter ' + meter_id) if meter_id else '')}"
name = "IEC"
model = None
serial_number = None
match iec_entity_type:
case IecEntityType.CONTRACT:
contract_id = str(int(contract_id))
name = f"IEC Contract [{contract_id}]"
model = "Contract: " + contract_id
case IecEntityType.METER:
name = f"IEC Meter [{meter_id}]"
model = "Contract: " + contract_id
serial_number = ("Meter ID: " + meter_id) if meter_id else ""

identifier: str = contract_id + (("_" + meter_id) if meter_id else "")
identifier: str = contract_id + (("_" + meter_id) if (iec_entity_type == IecEntityType.METER and meter_id) else "")
return DeviceInfo(
identifiers={
# Serial numbers are unique identifiers within a specific domain
(DOMAIN, identifier)
},
name=name,
manufacturer="Israel Electric Company",
model="Contract: " + contract_id,
serial_number=("Meter ID: " + meter_id) if meter_id else "",
model=model,
serial_number=serial_number,
)
8 changes: 5 additions & 3 deletions custom_components/iec/iec_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from custom_components.iec import IecApiCoordinator
from custom_components.iec.commons import get_device_info
from custom_components.iec.commons import get_device_info, IecEntityType


class IecEntity(CoordinatorEntity[IecApiCoordinator]):
"""Class describing IEC base-class entities."""

_attr_has_entity_name = True

def __init__(self, coordinator: IecApiCoordinator, contract_id: str, meter_id: str | None) -> None:
def __init__(self, coordinator: IecApiCoordinator, contract_id: str, meter_id: str | None,
iec_entity_type: IecEntityType):
"""Set up a IEC entity."""
super().__init__(coordinator)
self.contract_id = contract_id
self.meter_id = meter_id
self._attr_device_info = get_device_info(self.contract_id, self.meter_id)
self.iec_entity_type = iec_entity_type
self._attr_device_info = get_device_info(self.contract_id, self.meter_id, self.iec_entity_type)
51 changes: 36 additions & 15 deletions custom_components/iec/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from iec_api.models.invoice import Invoice
from iec_api.models.remote_reading import RemoteReading

from .commons import find_reading_by_date
from .commons import find_reading_by_date, IecEntityType
from .const import DOMAIN, ILS, STATICS_DICT_NAME, STATIC_KWH_TARIFF, FUTURE_CONSUMPTIONS_DICT_NAME, INVOICE_DICT_NAME, \
ILS_PER_KWH, DAILY_READINGS_DICT_NAME, EMPTY_REMOTE_READING, CONTRACT_DICT_NAME, EMPTY_INVOICE, \
ATTRIBUTES_DICT_NAME, METER_ID_ATTR_NAME
Expand All @@ -42,6 +42,16 @@ class IecEntityDescription(SensorEntityDescription, IecEntityDescriptionMixin):
"""Class describing IEC sensors entities."""


@dataclass(frozen=True, kw_only=True)
class IecMeterEntityDescription(IecEntityDescription):
"""Class describing IEC sensors entities related to specific meter."""


@dataclass(frozen=True, kw_only=True)
class IecContractEntityDescription(IecEntityDescription):
"""Class describing IEC sensors entities related to specific contract."""


def get_previous_bill_kwh_price(invoice: Invoice) -> float:
"""Calculate the previous bill's kilowatt-hour price by dividing the consumption by the original amount.

Expand All @@ -54,6 +64,16 @@ def get_previous_bill_kwh_price(invoice: Invoice) -> float:
return invoice.consumption / invoice.amount_origin


def _get_iec_type_by_class(description: IecEntityDescription) -> IecEntityType:
"""Get IEC type by class."""

if isinstance(description, IecContractEntityDescription):
return IecEntityType.CONTRACT
if isinstance(description, IecMeterEntityDescription):
return IecEntityType.METER
return IecEntityType.GENERIC


def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: datetime) -> RemoteReading:
if not readings:
return EMPTY_REMOTE_READING
Expand All @@ -67,7 +87,7 @@ def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: dat


SMART_ELEC_SENSORS: tuple[IecEntityDescription, ...] = (
IecEntityDescription(
IecMeterEntityDescription(
key="elec_forecasted_usage",
device_class=SensorDeviceClass.ENERGY,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
Expand All @@ -78,7 +98,7 @@ def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: dat
if (data[FUTURE_CONSUMPTIONS_DICT_NAME]
and data[FUTURE_CONSUMPTIONS_DICT_NAME][data[ATTRIBUTES_DICT_NAME][METER_ID_ATTR_NAME]]) else None
),
IecEntityDescription(
IecMeterEntityDescription(
key="elec_forecasted_cost",
device_class=SensorDeviceClass.MONETARY,
native_unit_of_measurement=ILS,
Expand All @@ -90,7 +110,7 @@ def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: dat
* data[STATICS_DICT_NAME][STATIC_KWH_TARIFF]) if (data[FUTURE_CONSUMPTIONS_DICT_NAME]
and data[ATTRIBUTES_DICT_NAME][METER_ID_ATTR_NAME]) else None
),
IecEntityDescription(
IecMeterEntityDescription(
key="elec_today_consumption",
device_class=SensorDeviceClass.ENERGY,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
Expand All @@ -101,7 +121,7 @@ def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: dat
datetime.now()).value if (data[DAILY_READINGS_DICT_NAME] and
[data[ATTRIBUTES_DICT_NAME][METER_ID_ATTR_NAME]]) else None
),
IecEntityDescription(
IecMeterEntityDescription(
key="elec_yesterday_consumption",
device_class=SensorDeviceClass.ENERGY,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
Expand All @@ -112,7 +132,7 @@ def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: dat
datetime.now() - timedelta(days=1)).value) if (
data[DAILY_READINGS_DICT_NAME]) else None,
),
IecEntityDescription(
IecMeterEntityDescription(
key="elec_this_month_consumption",
device_class=SensorDeviceClass.ENERGY,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
Expand All @@ -123,7 +143,7 @@ def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: dat
if reading.date.month == datetime.now().month])) if (
data[DAILY_READINGS_DICT_NAME]) else None,
),
IecEntityDescription(
IecMeterEntityDescription(
key="elec_latest_meter_reading",
device_class=SensorDeviceClass.ENERGY,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
Expand All @@ -135,7 +155,7 @@ def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: dat
)

ELEC_SENSORS: tuple[IecEntityDescription, ...] = (
IecEntityDescription(
IecContractEntityDescription(
key="iec_last_elec_usage",
device_class=SensorDeviceClass.ENERGY,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
Expand All @@ -144,7 +164,7 @@ def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: dat
value_fn=lambda data: data[INVOICE_DICT_NAME].consumption if (
data[INVOICE_DICT_NAME] != EMPTY_INVOICE) else None,
),
IecEntityDescription(
IecContractEntityDescription(
key="iec_last_cost",
device_class=SensorDeviceClass.MONETARY,
native_unit_of_measurement=ILS,
Expand All @@ -153,15 +173,15 @@ def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: dat
value_fn=lambda data: data[INVOICE_DICT_NAME].amount_origin if (
data[INVOICE_DICT_NAME] != EMPTY_INVOICE) else None,
),
IecEntityDescription(
IecContractEntityDescription(
key="iec_last_bill_remain_to_pay",
device_class=SensorDeviceClass.MONETARY,
native_unit_of_measurement=ILS,
suggested_display_precision=2,
value_fn=lambda data: data[INVOICE_DICT_NAME].amount_to_pay if (
data[INVOICE_DICT_NAME] != EMPTY_INVOICE) else None,
),
IecEntityDescription(
IecContractEntityDescription(
key="iec_last_number_of_days",
device_class=SensorDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.DAYS,
Expand All @@ -170,19 +190,19 @@ def _get_reading_by_date(readings: list[RemoteReading] | None, desired_date: dat
value_fn=lambda data: data[INVOICE_DICT_NAME].days_period if (
data[INVOICE_DICT_NAME] != EMPTY_INVOICE) else None,
),
IecEntityDescription(
IecContractEntityDescription(
key="iec_bill_date",
device_class=SensorDeviceClass.DATE,
value_fn=lambda data: data[INVOICE_DICT_NAME].to_date.date() if (
data[INVOICE_DICT_NAME] != EMPTY_INVOICE) else None,
),
IecEntityDescription(
IecContractEntityDescription(
key="iec_bill_last_payment_date",
device_class=SensorDeviceClass.DATE,
value_fn=lambda data: data[INVOICE_DICT_NAME].last_date if (
data[INVOICE_DICT_NAME] != EMPTY_INVOICE) else None,
),
IecEntityDescription(
IecContractEntityDescription(
key="iec_last_meter_reading",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
Expand Down Expand Up @@ -262,7 +282,8 @@ def __init__(
) -> None:
"""Initialize the sensor."""
super().__init__(coordinator, contract_id,
attributes_to_add.get(METER_ID_ATTR_NAME) if attributes_to_add else None)
attributes_to_add.get(METER_ID_ATTR_NAME) if attributes_to_add else None,
_get_iec_type_by_class(description))
self.entity_description = description
self._attr_unique_id = f"{str(contract_id)}_{description.key}"
self._attr_translation_key = f"{description.key}"
Expand Down
30 changes: 15 additions & 15 deletions custom_components/iec/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"entity": {
"binary_sensor": {
"last_iec_invoice_paid": {
"name": "Is last IEC invoice {multi_contract} paid"
"name": "Is last invoice {multi_contract} paid"
}
},
"sensor": {
Expand All @@ -13,48 +13,48 @@
"name": "Next bill electric forecasted cost {multi_contract}"
},
"elec_today_consumption": {
"name": "IEC today electric consumption {multi_contract}"
"name": "Today electric consumption {multi_contract}"
},
"elec_yesterday_consumption": {
"name": "IEC yesterday electric consumption {multi_contract}"
"name": "Yesterday electric consumption {multi_contract}"
},
"elec_this_month_consumption": {
"name": "IEC this month electric consumption {multi_contract}"
"name": "This month electric consumption {multi_contract}"
},
"elec_latest_meter_reading": {
"name": "IEC latest meter reading {multi_contract}"
"name": "Latest meter reading {multi_contract}"
},
"iec_last_elec_usage": {
"name": "Last IEC bill electric usage to date {multi_contract}"
"name": "Last bill electric usage to date {multi_contract}"
},
"iec_last_cost": {
"name": "Last IEC bill electric cost {multi_contract}"
"name": "Last bill electric cost {multi_contract}"
},
"iec_last_bill_remain_to_pay": {
"name": "Last IEC bill amount to pay {multi_contract}"
"name": "Last bill amount to pay {multi_contract}"
},
"iec_last_number_of_days": {
"name": "Last IEC bill length in days {multi_contract}"
"name": "Last bill length in days {multi_contract}"
},
"iec_bill_date": {
"name": "Last IEC bill date {multi_contract}"
"name": "Last bill date {multi_contract}"
},
"iec_bill_last_payment_date": {
"name": "Last IEC bill payment date {multi_contract}"
"name": "Last bill payment date {multi_contract}"
},
"iec_last_meter_reading": {
"name": "Last IEC bill meter reading {multi_contract}"
"name": "Last bill meter reading {multi_contract}"
},
"iec_kwh_tariff": {
"name": "IEC kWh tariff"
"name": "kWh tariff"
}
}
},
"config": {
"step": {
"user": {
"title": "IEC Account ID",
"description": "Enter your IEC User ID (תעודת זהות)",
"title": "Account ID",
"description": "Enter your User ID (תעודת זהות)",
"data": {
"user_id": "User ID"
}
Expand Down