From beba8afbbadd5a4a2a40a45f1b2ec287cb03d2c6 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 9 Aug 2025 09:33:19 +0200 Subject: [PATCH 01/15] Add new energy_log_record at the front of the cache this fits better to the reverse sorting of the data in the cache --- plugwise_usb/nodes/circle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index ea0150259..b4ae3089d 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -718,7 +718,7 @@ async def _energy_log_record_update_state( self._mac_in_str, ) self._set_cache( - CACHE_ENERGY_COLLECTION, cached_logs + "|" + log_cache_record + CACHE_ENERGY_COLLECTION, log_cache_record + "|" + cached_logs ) return True From 4fcad5c759163bb56ccf006ffef6c491228532e5 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 9 Aug 2025 09:51:01 +0200 Subject: [PATCH 02/15] Remove double reverse sorting --- plugwise_usb/nodes/circle.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index b4ae3089d..eea7d08b0 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -677,9 +677,10 @@ async def _energy_log_records_save_to_cache(self) -> None: self._energy_counters.get_pulse_logs() ) cached_logs = "" - for address in sorted(logs.keys(), reverse=True): - for slot in sorted(logs[address].keys(), reverse=True): - log = logs[address][slot] + # logs is already sorted in reverse + for address, record in logs.items(): + for slot in record: + log = record[slot] if cached_logs != "": cached_logs += "|" cached_logs += f"{address}:{slot}:{log.timestamp.year}" From eb07f216d8a29636cf78b7c348fb41ad345842df Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 9 Aug 2025 16:05:28 +0200 Subject: [PATCH 03/15] energy_log_update(): check if the timestamp of the log is recent --- plugwise_usb/nodes/circle.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index eea7d08b0..2b3a66076 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -24,6 +24,7 @@ ) from ..connection import StickController from ..constants import ( + DAY_IN_HOURS, DEFAULT_CONS_INTERVAL, MAX_TIME_DRIFT, MINIMAL_POWER_UPDATE, @@ -581,7 +582,14 @@ async def energy_log_update(self, address: int | None) -> tuple[bool, bool]: if log_timestamp is None or log_pulses is None: self._energy_counters.add_empty_log(response.log_address, _slot) empty_log = True - elif await self._energy_log_record_update_state( + continue + elif not self._check_timestamp_is_recent(address, _slot, log_timestamp): + # Don't store an old log-record, store am empty record instead + self._energy_counters.add_empty_log(response.log_address, _slot) + empty_log = True + continue + + if await self._energy_log_record_update_state( response.log_address, _slot, log_timestamp.replace(tzinfo=UTC), @@ -610,6 +618,25 @@ async def energy_log_update(self, address: int | None) -> tuple[bool, bool]: return result, empty_log + def _check_timestamp_is_recent(self, address, slot, timestamp) -> bool: + """Check if the timestamp of the received log-record is recent. + + A timestamp from within the last 24 hours is considered recent. + """ + if ( + (datetime.now(tz=UTC) - timestamp.replace(tzinfo=UTC)).total_seconds() + // 3600 + ) > DAY_IN_HOURS: + _LOGGER.warning( + "EnergyLog from Node %s | address %s | slot %s | timestamp %s is outdated, ignoring...", + self._mac_in_str, + address, + slot, + timestamp, + ) + return False + return True + async def _energy_log_records_load_from_cache(self) -> bool: """Load energy_log_record from cache.""" if (cache_data := self._get_cache(CACHE_ENERGY_COLLECTION)) is None: From 6ce576dd1664609c7824439d16faf3f07d3bcb93 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 9 Aug 2025 16:57:35 +0200 Subject: [PATCH 04/15] Remove replaced timestamp checking code --- plugwise_usb/nodes/circle.py | 38 ------------------------------------ 1 file changed, 38 deletions(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index 2b3a66076..e757057d0 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -463,7 +463,6 @@ async def _get_initial_energy_logs(self) -> None: ) total_addresses = 11 log_address = self._current_log_address - prev_address_timestamp: datetime | None = None while total_addresses > 0: result, empty_log = await self.energy_log_update(log_address) if result and empty_log: @@ -474,43 +473,6 @@ async def _get_initial_energy_logs(self) -> None: ) break - # Check if the most recent timestamp of an earlier address is recent - # (within 2/4 * log_interval plus 5 mins margin) - log_interval = self.energy_consumption_interval - factor = 2 if self.energy_production_interval is not None else 4 - - if log_interval is not None: - max_gap_minutes = (factor * log_interval) + 5 - if log_address == self._current_log_address: - if ( - self._last_collected_energy_timestamp is not None - and ( - datetime.now(tz=UTC) - self._last_collected_energy_timestamp - ).total_seconds() - // 60 - > max_gap_minutes - ): - _LOGGER.debug( - "Energy data collected from the current log address is outdated, stopping collection" - ) - break - elif ( - prev_address_timestamp is not None - and self._last_collected_energy_timestamp is not None - and ( - prev_address_timestamp - self._last_collected_energy_timestamp - ).total_seconds() - // 60 - > max_gap_minutes - ): - _LOGGER.debug( - "Collected energy data is outdated, stopping collection" - ) - break - - if self._last_collected_energy_timestamp is not None: - prev_address_timestamp = self._last_collected_energy_timestamp - log_address, _ = calc_log_address(log_address, 1, -4) total_addresses -= 1 From bd80b95459b926e470965979d9087c33afe623b3 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 9 Aug 2025 17:33:42 +0200 Subject: [PATCH 05/15] Simplify energy_log_update() improve docstrings --- plugwise_usb/nodes/circle.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index e757057d0..19117e689 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -365,7 +365,7 @@ async def energy_update(self) -> EnergyStatistics | None: # noqa: PLR0911 PLR09 # Always request last energy log records at initial startup if not self._last_energy_log_requested: - self._last_energy_log_requested, _ = await self.energy_log_update( + self._last_energy_log_requested = await self.energy_log_update( self._current_log_address ) @@ -379,7 +379,7 @@ async def energy_update(self) -> EnergyStatistics | None: # noqa: PLR0911 PLR09 return None # Try collecting energy-stats for _current_log_address - result, _ = await self.energy_log_update(self._current_log_address) + result = await self.energy_log_update(self._current_log_address) if not result: _LOGGER.debug( "async_energy_update | %s | Log rollover | energy_log_update failed", @@ -393,7 +393,7 @@ async def energy_update(self) -> EnergyStatistics | None: # noqa: PLR0911 PLR09 _prev_log_address, _ = calc_log_address( self._current_log_address, 1, -4 ) - result, _ = await self.energy_log_update(_prev_log_address) + result = await self.energy_log_update(_prev_log_address) if not result: _LOGGER.debug( "async_energy_update | %s | Log rollover | energy_log_update %s failed", @@ -414,7 +414,7 @@ async def energy_update(self) -> EnergyStatistics | None: # noqa: PLR0911 PLR09 return self._energy_counters.energy_statistics if len(missing_addresses) == 1: - result, _ = await self.energy_log_update(missing_addresses[0]) + result = await self.energy_log_update(missing_addresses[0]) if result: await self.power_update() _LOGGER.debug( @@ -464,11 +464,11 @@ async def _get_initial_energy_logs(self) -> None: total_addresses = 11 log_address = self._current_log_address while total_addresses > 0: - result, empty_log = await self.energy_log_update(log_address) - if result and empty_log: + result = await self.energy_log_update(log_address) + if not result: # Handle case with None-data in all address slots _LOGGER.debug( - "Energy None-data collected from log address %s, stopping collection", + "Energy None-data of outdated data collected from log address %s, stopping collection", log_address, ) break @@ -507,28 +507,28 @@ async def get_missing_energy_logs(self) -> None: if self._cache_enabled: await self._energy_log_records_save_to_cache() - async def energy_log_update(self, address: int | None) -> tuple[bool, bool]: + async def energy_log_update(self, address: int | None) -> bool: """Request energy log statistics from node. Returns true if successful.""" - empty_log = False result = False if address is None: - return result, empty_log + return result _LOGGER.debug( - "Request of energy log at address %s for node %s", + "Requesting EnergyLogs from node %s address %s", str(address), self.name, ) request = CircleEnergyLogsRequest(self._send, self._mac_in_bytes, address) if (response := await request.send()) is None: _LOGGER.debug( - "Retrieving of energy log at address %s for node %s failed", - str(address), + "Retrieving EnergyLogs data from node %s failed", self._mac_in_str, ) - return result, empty_log + return result - _LOGGER.debug("EnergyLogs data from %s, address=%s", self._mac_in_str, address) + _LOGGER.debug( + "EnergyLogs data from node %s, address=%s", self._mac_in_str, address + ) await self._available_update_state(True, response.timestamp) energy_record_update = False @@ -543,12 +543,10 @@ async def energy_log_update(self, address: int | None) -> tuple[bool, bool]: ) if log_timestamp is None or log_pulses is None: self._energy_counters.add_empty_log(response.log_address, _slot) - empty_log = True continue elif not self._check_timestamp_is_recent(address, _slot, log_timestamp): # Don't store an old log-record, store am empty record instead self._energy_counters.add_empty_log(response.log_address, _slot) - empty_log = True continue if await self._energy_log_record_update_state( @@ -578,7 +576,7 @@ async def energy_log_update(self, address: int | None) -> tuple[bool, bool]: ) await self.save_cache() - return result, empty_log + return result def _check_timestamp_is_recent(self, address, slot, timestamp) -> bool: """Check if the timestamp of the received log-record is recent. From 6776f832ab4d64ebc0efc1e59d7947f05faa7751 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 9 Aug 2025 18:01:21 +0200 Subject: [PATCH 06/15] Implement suggestions --- plugwise_usb/nodes/circle.py | 47 ++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index 19117e689..6846090b8 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -468,7 +468,7 @@ async def _get_initial_energy_logs(self) -> None: if not result: # Handle case with None-data in all address slots _LOGGER.debug( - "Energy None-data of outdated data collected from log address %s, stopping collection", + "All slots at log address %s are empty or outdated – stopping initial collection", log_address, ) break @@ -508,15 +508,15 @@ async def get_missing_energy_logs(self) -> None: await self._energy_log_records_save_to_cache() async def energy_log_update(self, address: int | None) -> bool: - """Request energy log statistics from node. Returns true if successful.""" - result = False + """Request energy logs and return True only when at least one recent, non-empty record was stored; otherwise return False.""" + any_record_stored = False if address is None: - return result + return False _LOGGER.debug( "Requesting EnergyLogs from node %s address %s", - str(address), - self.name, + self._mac_in_str, + address, ) request = CircleEnergyLogsRequest(self._send, self._mac_in_bytes, address) if (response := await request.send()) is None: @@ -524,13 +524,10 @@ async def energy_log_update(self, address: int | None) -> bool: "Retrieving EnergyLogs data from node %s failed", self._mac_in_str, ) - return result + return False - _LOGGER.debug( - "EnergyLogs data from node %s, address=%s", self._mac_in_str, address - ) + _LOGGER.debug("EnergyLogs from node %s, address=%s:", self._mac_in_str, address) await self._available_update_state(True, response.timestamp) - energy_record_update = False # Forward historical energy log information to energy counters # Each response message contains 4 log counters (slots) of the @@ -541,11 +538,12 @@ async def energy_log_update(self, address: int | None) -> bool: _LOGGER.debug( "In slot=%s: pulses=%s, timestamp=%s", _slot, log_pulses, log_timestamp ) - if log_timestamp is None or log_pulses is None: - self._energy_counters.add_empty_log(response.log_address, _slot) - continue - elif not self._check_timestamp_is_recent(address, _slot, log_timestamp): + if ( + log_timestamp is None + or log_pulses is None # Don't store an old log-record, store am empty record instead + or not self._check_timestamp_is_recent(address, _slot, log_timestamp) + ): self._energy_counters.add_empty_log(response.log_address, _slot) continue @@ -556,7 +554,7 @@ async def energy_log_update(self, address: int | None) -> bool: log_pulses, import_only=True, ): - energy_record_update = True + any_record_stored = True if not last_energy_timestamp_collected: # Collect the timestamp of the most recent response self._last_collected_energy_timestamp = log_timestamp.replace( @@ -568,25 +566,26 @@ async def energy_log_update(self, address: int | None) -> bool: ) last_energy_timestamp_collected = True - result = True self._energy_counters.update() - if energy_record_update: + if any_record_stored: _LOGGER.debug( "Saving energy record update to cache for %s", self._mac_in_str ) await self.save_cache() - return result + return any_record_stored - def _check_timestamp_is_recent(self, address, slot, timestamp) -> bool: + def _check_timestamp_is_recent( + self, address: int, slot: int, timestamp: datetime + ) -> bool: """Check if the timestamp of the received log-record is recent. A timestamp from within the last 24 hours is considered recent. """ - if ( - (datetime.now(tz=UTC) - timestamp.replace(tzinfo=UTC)).total_seconds() - // 3600 - ) > DAY_IN_HOURS: + age_seconds = ( + datetime.now(tz=UTC) - timestamp.replace(tzinfo=UTC) + ).total_seconds() + if age_seconds > DAY_IN_HOURS * 3600: _LOGGER.warning( "EnergyLog from Node %s | address %s | slot %s | timestamp %s is outdated, ignoring...", self._mac_in_str, From c652c7cca4c54de00f15758e57dc833405009367 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 12 Aug 2025 08:35:24 +0200 Subject: [PATCH 07/15] Sort and prune the records loaded from cache --- plugwise_usb/nodes/circle.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index 6846090b8..73b4307f5 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -26,6 +26,7 @@ from ..constants import ( DAY_IN_HOURS, DEFAULT_CONS_INTERVAL, + MAX_LOG_HOURS, MAX_TIME_DRIFT, MINIMAL_POWER_UPDATE, NO_PRODUCTION_INTERVAL, @@ -635,6 +636,20 @@ async def _energy_log_records_load_from_cache(self) -> bool: restored_logs[address] = [] restored_logs[address].append(slot) + # Sort and prune the records loaded from cache + sorted_logs: dict[int, dict[int, PulseLogRecord]] = {} + skip_before = datetime.now(tz=UTC) - timedelta(hours=MAX_LOG_HOURS) + sorted_address = sorted(restored_logs.keys(), reverse=True) + for address in sorted_address: + sorted_slots = sorted(restored_logs[address].keys(), reverse=True) + for slot in sorted_slots: + if restored_logs[address][slot].timestamp > skip_before: + if sorted_log.get(address) is None: + sorted_log[address] = {} + sorted_log[address][slot] = restored_logs[address][slot] + + restored_logs = sorted_logs + self._energy_counters.update() # Create task to retrieve remaining (missing) logs From 164bad6fce420e8e0644c86faf9db6a24f715b7c Mon Sep 17 00:00:00 2001 From: autoruff Date: Tue, 12 Aug 2025 06:39:25 +0000 Subject: [PATCH 08/15] fixup: ener-logs-cache-3 Python code reformatted using Ruff --- plugwise_usb/nodes/circle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index 73b4307f5..ecf66e558 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -647,7 +647,7 @@ async def _energy_log_records_load_from_cache(self) -> bool: if sorted_log.get(address) is None: sorted_log[address] = {} sorted_log[address][slot] = restored_logs[address][slot] - + restored_logs = sorted_logs self._energy_counters.update() From c89456eec1571d7a10a447c94a4d4e4caf5d4762 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 12 Aug 2025 10:44:54 +0200 Subject: [PATCH 09/15] Add_pulse_logs from sorted and pruned restored cache data --- plugwise_usb/nodes/circle.py | 61 +++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index ecf66e558..1c27cef69 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -5,7 +5,7 @@ from asyncio import Task, create_task from collections.abc import Awaitable, Callable from dataclasses import replace -from datetime import UTC, datetime +from datetime import UTC, datetime, timedelta from functools import wraps import logging from typing import Any, Final, TypeVar, cast @@ -26,7 +26,6 @@ from ..constants import ( DAY_IN_HOURS, DEFAULT_CONS_INTERVAL, - MAX_LOG_HOURS, MAX_TIME_DRIFT, MINIMAL_POWER_UPDATE, NO_PRODUCTION_INTERVAL, @@ -604,7 +603,7 @@ async def _energy_log_records_load_from_cache(self) -> bool: "Failed to restore energy log records from cache for node %s", self.name ) return False - restored_logs: dict[int, list[int]] = {} + restored_logs: dict[int, dict[int, tuple[int, datetime]]] = {} if cache_data == "": _LOGGER.debug("Cache-record is empty") return False @@ -617,38 +616,42 @@ async def _energy_log_records_load_from_cache(self) -> bool: if len(timestamp_energy_log) == 6: address = int(log_fields[0]) slot = int(log_fields[1]) - self._energy_counters.add_pulse_log( - address=address, - slot=slot, - timestamp=datetime( - year=int(timestamp_energy_log[0]), - month=int(timestamp_energy_log[1]), - day=int(timestamp_energy_log[2]), - hour=int(timestamp_energy_log[3]), - minute=int(timestamp_energy_log[4]), - second=int(timestamp_energy_log[5]), - tzinfo=UTC, - ), - pulses=int(log_fields[3]), - import_only=True, + pulses=int(log_fields[3]) + timestamp=datetime( + year=int(timestamp_energy_log[0]), + month=int(timestamp_energy_log[1]), + day=int(timestamp_energy_log[2]), + hour=int(timestamp_energy_log[3]), + minute=int(timestamp_energy_log[4]), + second=int(timestamp_energy_log[5]), + tzinfo=UTC, ) if restored_logs.get(address) is None: - restored_logs[address] = [] - restored_logs[address].append(slot) + restored_logs[address] = {} + restored_logs[address][slot] = (pulses, timestamp) + _LOGGER.debug("HOI restored_logs=%s", restored_logs) # Sort and prune the records loaded from cache - sorted_logs: dict[int, dict[int, PulseLogRecord]] = {} - skip_before = datetime.now(tz=UTC) - timedelta(hours=MAX_LOG_HOURS) - sorted_address = sorted(restored_logs.keys(), reverse=True) - for address in sorted_address: + sorted_logs: dict[int, dict[int, tuple[int, datetime]]] = {} + skip_before = datetime.now(tz=UTC) - timedelta(hours=DAY_IN_HOURS) + sorted_addresses = sorted(restored_logs.keys(), reverse=True) + for address in sorted_addresses: sorted_slots = sorted(restored_logs[address].keys(), reverse=True) for slot in sorted_slots: - if restored_logs[address][slot].timestamp > skip_before: - if sorted_log.get(address) is None: - sorted_log[address] = {} - sorted_log[address][slot] = restored_logs[address][slot] - - restored_logs = sorted_logs + if restored_logs[address][slot][1] > skip_before: + if sorted_logs.get(address) is None: + sorted_logs[address] = {} + sorted_logs[address][slot] = restored_logs[address][slot] + + for address, data in sorted_logs.items(): + for slot, pulse_data in data.items(): + self._energy_counters.add_pulse_log( + address=address, + slot=slot, + pulses=pulse_data[0], + timestamp=pulse_data[1], + import_only=True, + ) self._energy_counters.update() From 14aba45af6581440fe9fd3a937655af9ffd2f5e4 Mon Sep 17 00:00:00 2001 From: autoruff Date: Tue, 12 Aug 2025 08:55:35 +0000 Subject: [PATCH 10/15] fixup: ener-logs-cache-3 Python code reformatted using Ruff --- plugwise_usb/nodes/circle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index 1c27cef69..5c070a679 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -616,8 +616,8 @@ async def _energy_log_records_load_from_cache(self) -> bool: if len(timestamp_energy_log) == 6: address = int(log_fields[0]) slot = int(log_fields[1]) - pulses=int(log_fields[3]) - timestamp=datetime( + pulses = int(log_fields[3]) + timestamp = datetime( year=int(timestamp_energy_log[0]), month=int(timestamp_energy_log[1]), day=int(timestamp_energy_log[2]), From 526b2bad1a50707262a6eace4ffe549d1b87084d Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 12 Aug 2025 10:58:20 +0200 Subject: [PATCH 11/15] Allow complexity for now --- plugwise_usb/nodes/circle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index 5c070a679..90b12fe6e 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -596,7 +596,7 @@ def _check_timestamp_is_recent( return False return True - async def _energy_log_records_load_from_cache(self) -> bool: + async def _energy_log_records_load_from_cache(self) -> bool: # noqa: PLR0912 """Load energy_log_record from cache.""" if (cache_data := self._get_cache(CACHE_ENERGY_COLLECTION)) is None: _LOGGER.warning( From ada08b132ffea03ef4153dcd0b4f1dd9bee9e180 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 12 Aug 2025 16:20:07 +0200 Subject: [PATCH 12/15] Switch pulses and timestamp positions --- plugwise_usb/nodes/circle.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index 90b12fe6e..d4ba79a22 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -603,7 +603,7 @@ async def _energy_log_records_load_from_cache(self) -> bool: # noqa: PLR0912 "Failed to restore energy log records from cache for node %s", self.name ) return False - restored_logs: dict[int, dict[int, tuple[int, datetime]]] = {} + restored_logs: dict[int, dict[int, tuple[datetime, int]]] = {} if cache_data == "": _LOGGER.debug("Cache-record is empty") return False @@ -628,17 +628,17 @@ async def _energy_log_records_load_from_cache(self) -> bool: # noqa: PLR0912 ) if restored_logs.get(address) is None: restored_logs[address] = {} - restored_logs[address][slot] = (pulses, timestamp) + restored_logs[address][slot] = (timestamp, pulses) _LOGGER.debug("HOI restored_logs=%s", restored_logs) # Sort and prune the records loaded from cache - sorted_logs: dict[int, dict[int, tuple[int, datetime]]] = {} + sorted_logs: dict[int, dict[int, tuple[datetime, int]]] = {} skip_before = datetime.now(tz=UTC) - timedelta(hours=DAY_IN_HOURS) sorted_addresses = sorted(restored_logs.keys(), reverse=True) for address in sorted_addresses: sorted_slots = sorted(restored_logs[address].keys(), reverse=True) for slot in sorted_slots: - if restored_logs[address][slot][1] > skip_before: + if restored_logs[address][slot][0] > skip_before: if sorted_logs.get(address) is None: sorted_logs[address] = {} sorted_logs[address][slot] = restored_logs[address][slot] @@ -648,8 +648,8 @@ async def _energy_log_records_load_from_cache(self) -> bool: # noqa: PLR0912 self._energy_counters.add_pulse_log( address=address, slot=slot, - pulses=pulse_data[0], - timestamp=pulse_data[1], + pulses=pulse_data[1], + timestamp=pulse_data[0], import_only=True, ) From 523d1890f250953d85a6c1aa0c5345f22b9b601a Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 12 Aug 2025 17:03:55 +0200 Subject: [PATCH 13/15] Bump to v0.44.11a0 for testing --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index cb97c1a36..d66d79e19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise_usb" -version = "0.44.10" +version = "0.44.11a0" license = "MIT" keywords = ["home", "automation", "plugwise", "module", "usb"] classifiers = [ From 9285048fd704bf22cf702b80b1a78a5624f1f386 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 12 Aug 2025 17:24:20 +0200 Subject: [PATCH 14/15] Remove HOI logger --- plugwise_usb/nodes/circle.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugwise_usb/nodes/circle.py b/plugwise_usb/nodes/circle.py index d4ba79a22..bdf555688 100644 --- a/plugwise_usb/nodes/circle.py +++ b/plugwise_usb/nodes/circle.py @@ -629,7 +629,6 @@ async def _energy_log_records_load_from_cache(self) -> bool: # noqa: PLR0912 if restored_logs.get(address) is None: restored_logs[address] = {} restored_logs[address][slot] = (timestamp, pulses) - _LOGGER.debug("HOI restored_logs=%s", restored_logs) # Sort and prune the records loaded from cache sorted_logs: dict[int, dict[int, tuple[datetime, int]]] = {} From 45626252a632f508a7305c5784ded4d8ad718639 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 12 Aug 2025 17:25:55 +0200 Subject: [PATCH 15/15] Bump to a1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d66d79e19..3779f53df 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise_usb" -version = "0.44.11a0" +version = "0.44.11a1" license = "MIT" keywords = ["home", "automation", "plugwise", "module", "usb"] classifiers = [