Skip to content

Commit

Permalink
fix: Wrong Today/Yesterday calculation (#199)
Browse files Browse the repository at this point in the history
  • Loading branch information
GuyKh authored Nov 4, 2024
1 parent ee2b764 commit 14bd37f
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 59 deletions.
10 changes: 3 additions & 7 deletions custom_components/iec/commons.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytz

from datetime import datetime
from datetime import date
from enum import Enum

from homeassistant.helpers.device_registry import DeviceInfo
Expand All @@ -13,7 +13,7 @@
TIMEZONE = pytz.timezone("Asia/Jerusalem")


def find_reading_by_date(daily_reading: RemoteReading, desired_date: datetime) -> bool:
def find_reading_by_date(daily_reading: RemoteReading, desired_date: date) -> bool:
"""Search for a daily reading matching a specific date.
Args:
Expand All @@ -29,11 +29,7 @@ def find_reading_by_date(daily_reading: RemoteReading, desired_date: datetime) -
TypeError: If the `daily_reading.date` attribute is not of type `datetime`.
"""
return (
daily_reading.date.year == desired_date.year
and daily_reading.date.month == desired_date.month
and daily_reading.date.day == desired_date.day
) # Checks if the dates match
return daily_reading.date.date() == desired_date # Checks if the dates match


class IecEntityType(Enum):
Expand Down
71 changes: 23 additions & 48 deletions custom_components/iec/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,31 +306,33 @@ async def _verify_daily_readings_exist(
_LOGGER.debug(
f'Daily reading for date: {desired_date.strftime("%Y-%m-%d")} is missing, calculating manually'
)
hourly_readings = prefetched_reading
if not hourly_readings:
hourly_readings = await self._get_readings(
daily_readings = prefetched_reading
if not daily_readings:
daily_readings = await self._get_readings(
contract_id,
device.device_number,
device.device_code,
desired_date,
ReadingResolution.DAILY,
ReadingResolution.MONTHLY,
)
else:
_LOGGER.debug(
f'Daily reading for date: {desired_date.strftime("%Y-%m-%d")} - using existing prefetched readings'
)

daily_sum = 0
if hourly_readings is None or hourly_readings.data is None:
_LOGGER.info(
f'No readings found for date: {desired_date.strftime("%Y-%m-%d")}'
daily_sum = next(
filter(
lambda reading: reading.date.date() == desired_date.date(),
daily_readings,
),
0,
)
if daily_sum <= 0:
_LOGGER.debug(
f'Couldn\'t find daily reading for: {desired_date.strftime("%Y-%m-%d")}'
)
return

for reading in hourly_readings.data:
daily_sum += reading.value

daily_readings.append(RemoteReading(0, desired_date, daily_sum))
else:
daily_readings.append(RemoteReading(0, desired_date, daily_sum))
else:
_LOGGER.debug(
f'Daily reading for date: {daily_reading.date.strftime("%Y-%m-%d")}'
Expand Down Expand Up @@ -380,7 +382,7 @@ async def _async_update_data(
for c in all_contracts
if c.status == 1 and int(c.contract_id) in self._contract_ids
}
localized_today = TIMEZONE.localize(datetime.today())
localized_today = TIMEZONE.localize(datetime.now())
kwh_tariff = await self._get_kwh_tariff()
kva_tariff = await self._get_kva_tariff()

Expand Down Expand Up @@ -446,10 +448,6 @@ async def _async_update_data(
# For some reason, there are differences between sending 2024-03-01 and sending 2024-03-07 (Today)
# So instead of sending the 1st day of the month, just sending today date

monthly_report_req_date: datetime = localized_today.replace(
hour=1, minute=0, second=0, microsecond=0
) + timedelta(days=1)

devices = await self._get_devices_by_contract_id(contract_id)

for device in devices:
Expand All @@ -459,7 +457,7 @@ async def _async_update_data(
contract_id,
device.device_number,
device.device_code,
monthly_report_req_date,
localized_today,
ReadingResolution.MONTHLY,
)
if (
Expand All @@ -469,27 +467,12 @@ async def _async_update_data(
remote_reading.future_consumption_info
)

if monthly_report_req_date.date() == localized_today.date():
daily_readings[device.device_number] = remote_reading.data
else:
this_month_reading = await self._get_readings(
contract_id,
device.device_number,
device.device_code,
localized_today,
ReadingResolution.MONTHLY,
)
if this_month_reading:
daily_readings[device.device_number] = (
this_month_reading.data
)
daily_readings[device.device_number] = remote_reading.data

weekly_future_consumption = None
if localized_today.day == 1:
# if today's the 1st of the month, "yesterday" is on a different month
yesterday: datetime = monthly_report_req_date - timedelta(
days=1
)
yesterday: datetime = localized_today - timedelta(days=1)
remote_reading = await self._get_readings(
contract_id,
device.device_number,
Expand Down Expand Up @@ -535,14 +518,6 @@ async def _async_update_data(
)
self._today_readings[today_reading_key] = today_reading

await self._verify_daily_readings_exist(
daily_readings[device.device_number],
localized_today,
device,
contract_id,
today_reading,
)

# fallbacks for future consumption since IEC api is broken :/
if (
not future_consumption[device.device_number]
Expand Down Expand Up @@ -658,7 +633,7 @@ async def _insert_statistics(self, contract_id: int, is_smart_meter: bool) -> No
_LOGGER.debug(f"Updating statistics for IEC Contract {contract_id}")
devices = await self._get_devices_by_contract_id(contract_id)
kwh_price = await self._get_kwh_tariff()
localized_today = TIMEZONE.localize(datetime.today())
localized_today = TIMEZONE.localize(datetime.now())

if not devices:
_LOGGER.error(f"Failed fetching devices for IEC Contract {contract_id}")
Expand Down Expand Up @@ -913,7 +888,7 @@ async def _estimate_bill(
"Couldn't get Last Meter Read, WILL NOT calculate the usage part in estimated bill."
)
last_meter_read = None
last_meter_read_date = TIMEZONE.localize(datetime.today()).date()
last_meter_read_date = TIMEZONE.localize(datetime.now()).date()
last_invoice = EMPTY_INVOICE
else:
last_meter_read = last_meter_reading.reading
Expand Down Expand Up @@ -992,7 +967,7 @@ def _calculate_estimated_bill(
consumption_price = round(future_consumption * kwh_tariff, 2)
total_days = 0

today = TIMEZONE.localize(datetime.today())
today = TIMEZONE.localize(datetime.now())

if last_invoice != EMPTY_INVOICE:
current_date = last_meter_read_date + timedelta(days=1)
Expand Down
10 changes: 6 additions & 4 deletions custom_components/iec/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,12 @@ def _get_iec_type_by_class(description: IecEntityDescription) -> IecEntityType:


def _get_reading_by_date(
readings: list[RemoteReading] | None, desired_date: datetime
readings: list[RemoteReading] | None, desired_datetime: datetime
) -> RemoteReading:
if not readings:
return EMPTY_REMOTE_READING

desired_date = desired_datetime.date()
try:
reading = next(
reading
Expand Down Expand Up @@ -176,7 +178,7 @@ def _get_reading_by_date(
data[DAILY_READINGS_DICT_NAME][
data[ATTRIBUTES_DICT_NAME][METER_ID_ATTR_NAME]
],
TIMEZONE.localize(datetime.today()),
TIMEZONE.localize(datetime.now()),
).value
if (
data[DAILY_READINGS_DICT_NAME]
Expand All @@ -195,7 +197,7 @@ def _get_reading_by_date(
data[DAILY_READINGS_DICT_NAME][
data[ATTRIBUTES_DICT_NAME][METER_ID_ATTR_NAME]
],
TIMEZONE.localize(datetime.today()) - timedelta(days=1),
TIMEZONE.localize(datetime.now()) - timedelta(days=1),
).value
)
if (data[DAILY_READINGS_DICT_NAME])
Expand All @@ -214,7 +216,7 @@ def _get_reading_by_date(
for reading in data[DAILY_READINGS_DICT_NAME][
data[ATTRIBUTES_DICT_NAME][METER_ID_ATTR_NAME]
]
if reading.date.month == TIMEZONE.localize(datetime.today()).month
if reading.date.month == TIMEZONE.localize(datetime.now()).month
]
)
)
Expand Down

0 comments on commit 14bd37f

Please sign in to comment.