Skip to content

Commit 750d93c

Browse files
committed
Move energy-log validity-check into energy_log_update()
1 parent 757787c commit 750d93c

File tree

1 file changed

+50
-64
lines changed

1 file changed

+50
-64
lines changed

plugwise_usb/nodes/circle.py

Lines changed: 50 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ async def energy_update(self) -> EnergyStatistics | None: # noqa: PLR0911 PLR09
364364

365365
# Always request last energy log records at initial startup
366366
if not self._last_energy_log_requested:
367-
self._last_energy_log_requested, _ = await self.energy_log_update(
367+
self._last_energy_log_requested = await self.energy_log_update(
368368
self._current_log_address
369369
)
370370

@@ -378,7 +378,7 @@ async def energy_update(self) -> EnergyStatistics | None: # noqa: PLR0911 PLR09
378378
return None
379379

380380
# Try collecting energy-stats for _current_log_address
381-
result, _ = await self.energy_log_update(self._current_log_address)
381+
result = await self.energy_log_update(self._current_log_address)
382382
if not result:
383383
_LOGGER.debug(
384384
"async_energy_update | %s | Log rollover | energy_log_update failed",
@@ -392,7 +392,7 @@ async def energy_update(self) -> EnergyStatistics | None: # noqa: PLR0911 PLR09
392392
_prev_log_address, _ = calc_log_address(
393393
self._current_log_address, 1, -4
394394
)
395-
result, _ = await self.energy_log_update(_prev_log_address)
395+
result = await self.energy_log_update(_prev_log_address)
396396
if not result:
397397
_LOGGER.debug(
398398
"async_energy_update | %s | Log rollover | energy_log_update %s failed",
@@ -413,7 +413,7 @@ async def energy_update(self) -> EnergyStatistics | None: # noqa: PLR0911 PLR09
413413
return self._energy_counters.energy_statistics
414414

415415
if len(missing_addresses) == 1:
416-
result, _ = await self.energy_log_update(missing_addresses[0])
416+
result = await self.energy_log_update(missing_addresses[0])
417417
if result:
418418
await self.power_update()
419419
_LOGGER.debug(
@@ -464,52 +464,15 @@ async def _get_initial_energy_logs(self) -> None:
464464
log_address = self._current_log_address
465465
prev_address_timestamp: datetime | None = None
466466
while total_addresses > 0:
467-
result, empty_log = await self.energy_log_update(log_address)
468-
if result and empty_log:
467+
result = await self.energy_log_update(log_address)
468+
if not result:
469469
# Handle case with None-data in all address slots
470470
_LOGGER.debug(
471-
"Energy None-data collected from log address %s, stopping collection",
471+
"All slots at log address %s are empty or outdated – stopping initial collection",
472472
log_address,
473473
)
474474
break
475475

476-
# Check if the most recent timestamp of an earlier address is recent
477-
# (within 2/4 * log_interval plus 5 mins margin)
478-
log_interval = self.energy_consumption_interval
479-
factor = 2 if self.energy_production_interval is not None else 4
480-
481-
if log_interval is not None:
482-
max_gap_minutes = (factor * log_interval) + 5
483-
if log_address == self._current_log_address:
484-
if (
485-
self._last_collected_energy_timestamp is not None
486-
and (
487-
datetime.now(tz=UTC) - self._last_collected_energy_timestamp
488-
).total_seconds()
489-
// 60
490-
> max_gap_minutes
491-
):
492-
_LOGGER.debug(
493-
"Energy data collected from the current log address is outdated, stopping collection"
494-
)
495-
break
496-
elif (
497-
prev_address_timestamp is not None
498-
and self._last_collected_energy_timestamp is not None
499-
and (
500-
prev_address_timestamp - self._last_collected_energy_timestamp
501-
).total_seconds()
502-
// 60
503-
> max_gap_minutes
504-
):
505-
_LOGGER.debug(
506-
"Collected energy data is outdated, stopping collection"
507-
)
508-
break
509-
510-
if self._last_collected_energy_timestamp is not None:
511-
prev_address_timestamp = self._last_collected_energy_timestamp
512-
513476
log_address, _ = calc_log_address(log_address, 1, -4)
514477
total_addresses -= 1
515478

@@ -544,30 +507,27 @@ async def get_missing_energy_logs(self) -> None:
544507
if self._cache_enabled:
545508
await self._energy_log_records_save_to_cache()
546509

547-
async def energy_log_update(self, address: int | None) -> tuple[bool, bool]:
548-
"""Request energy log statistics from node. Returns true if successful."""
549-
empty_log = False
550-
result = False
510+
async def energy_log_update(self, address: int | None) -> bool:
511+
"""Request energy logs and return True only when at least one recent, non-empty record was stored; otherwise return False."""
512+
any_record_stored = False
551513
if address is None:
552-
return result, empty_log
514+
return False
553515

554516
_LOGGER.debug(
555-
"Request of energy log at address %s for node %s",
556-
str(address),
557-
self.name,
517+
"Requesting EnergyLogs from node %s address %s",
518+
self._mac_in_str,
519+
address,
558520
)
559521
request = CircleEnergyLogsRequest(self._send, self._mac_in_bytes, address)
560522
if (response := await request.send()) is None:
561523
_LOGGER.debug(
562-
"Retrieving of energy log at address %s for node %s failed",
563-
str(address),
524+
"Retrieving EnergyLogs data from node %s failed",
564525
self._mac_in_str,
565526
)
566-
return result, empty_log
527+
return False
567528

568-
_LOGGER.debug("EnergyLogs data from %s, address=%s", self._mac_in_str, address)
529+
_LOGGER.debug("EnergyLogs from node %s, address=%s:", self._mac_in_str, address)
569530
await self._available_update_state(True, response.timestamp)
570-
energy_record_update = False
571531

572532
# Forward historical energy log information to energy counters
573533
# Each response message contains 4 log counters (slots) of the
@@ -578,17 +538,23 @@ async def energy_log_update(self, address: int | None) -> tuple[bool, bool]:
578538
_LOGGER.debug(
579539
"In slot=%s: pulses=%s, timestamp=%s", _slot, log_pulses, log_timestamp
580540
)
581-
if log_timestamp is None or log_pulses is None:
541+
if (
542+
log_timestamp is None
543+
or log_pulses is None
544+
# Don't store an old log-record, store am empty record instead
545+
or not self._check_timestamp_is_recent(address, _slot, log_timestamp)
546+
):
582547
self._energy_counters.add_empty_log(response.log_address, _slot)
583-
empty_log = True
584-
elif await self._energy_log_record_update_state(
548+
continue
549+
550+
if await self._energy_log_record_update_state(
585551
response.log_address,
586552
_slot,
587553
log_timestamp.replace(tzinfo=UTC),
588554
log_pulses,
589555
import_only=True,
590556
):
591-
energy_record_update = True
557+
any_record_stored = True
592558
if not last_energy_timestamp_collected:
593559
# Collect the timestamp of the most recent response
594560
self._last_collected_energy_timestamp = log_timestamp.replace(
@@ -600,15 +566,35 @@ async def energy_log_update(self, address: int | None) -> tuple[bool, bool]:
600566
)
601567
last_energy_timestamp_collected = True
602568

603-
result = True
604569
self._energy_counters.update()
605-
if energy_record_update:
570+
if any_record_stored:
606571
_LOGGER.debug(
607572
"Saving energy record update to cache for %s", self._mac_in_str
608573
)
609574
await self.save_cache()
610575

611-
return result, empty_log
576+
return any_record_stored
577+
578+
def _check_timestamp_is_recent(
579+
self, address: int, slot: int, timestamp: datetime
580+
) -> bool:
581+
"""Check if the timestamp of the received log-record is recent.
582+
583+
A timestamp from within the last 24 hours is considered recent.
584+
"""
585+
age_seconds = (
586+
datetime.now(tz=UTC) - timestamp.replace(tzinfo=UTC)
587+
).total_seconds()
588+
if age_seconds > DAY_IN_HOURS * 3600:
589+
_LOGGER.warning(
590+
"EnergyLog from Node %s | address %s | slot %s | timestamp %s is outdated, ignoring...",
591+
self._mac_in_str,
592+
address,
593+
slot,
594+
timestamp,
595+
)
596+
return False
597+
return True
612598

613599
async def _energy_log_records_load_from_cache(self) -> bool:
614600
"""Load energy_log_record from cache."""

0 commit comments

Comments
 (0)