From 0848e5a28a7c02e09e6a8c85468a3fe4c370419c Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Jun 2025 10:25:38 +0200 Subject: [PATCH 01/23] Implement energy-reset functions --- plugwise_usb/__init__.py | 18 ++++++++++++++++-- plugwise_usb/network/__init__.py | 22 ++++++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/plugwise_usb/__init__.py b/plugwise_usb/__init__.py index 06222ab89..ea2bc9e4f 100644 --- a/plugwise_usb/__init__.py +++ b/plugwise_usb/__init__.py @@ -10,7 +10,7 @@ from collections.abc import Callable, Coroutine from functools import wraps import logging -from typing import Any, TypeVar, cast, Final +from typing import Any, Final, TypeVar, cast from .api import NodeEvent, PlugwiseNode, StickEvent from .connection import StickController @@ -210,6 +210,20 @@ async def set_accept_join_request(self, state: bool) -> bool: raise NodeError(f"Failed setting accept joining: {exc}") from exc return True + async def energy_reset_request(self, mac: str) -> bool: + """Send an energy-reset request to a Node.""" + try: + await self._network.energy_reset_request(mac) + except (MessageError, NodeError) as exc: + raise NodeError(f"{exc}") from exc + + # Follow up by an energy-intervals (re)set + result = await self.set_energy_intervals(mac, 60, 0) + if result: + return True + + return False + async def set_energy_intervals( self, mac: str, cons_interval: int, prod_interval: int ) -> bool: @@ -295,7 +309,7 @@ async def connect(self, port: str | None = None) -> None: "Unable to connect. " + "Path to USB-Stick is not defined, set port property first" ) - + await self._controller.connect_to_stick( self._port, ) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index cce2cea65..edaf633a5 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -12,11 +12,12 @@ from ..api import NodeEvent, NodeType, PlugwiseNode, StickEvent from ..connection import StickController -from ..constants import UTF8 +from ..constants import UTC, UTF8 from ..exceptions import CacheError, MessageError, NodeError, StickError, StickTimeout from ..messages.requests import ( - CirclePlusAllowJoiningRequest, + CircleClockSetRequest, CircleMeasureIntervalRequest, + CirclePlusAllowJoiningRequest, NodePingRequest, ) from ..messages.responses import ( @@ -541,6 +542,23 @@ async def allow_join_requests(self, state: bool) -> None: _LOGGER.debug("Sent AllowJoiningRequest to Circle+ with state=%s", state) self.accept_join_request = state + async def energy_reset_request(self, mac: str) -> None: + """Send an energy-reset to a Node.""" + request = CircleClockSetRequest( + self._send, + self._mac_in_bytes, + datetime.now(tz=UTC), + self._node_protocols.max, + True, + ) + if (response := await request.send()) is None: + raise NodeError(f"Energy-reset for {mac} failed") + + if response.ack_id != NodeResponseType.CLOCK_ACCEPTED: + raise MessageError( + f"Unknown NodeResponseType '{response.response_type.name}' received" + ) + async def set_energy_intervals( self, mac: str, consumption: int, production: int ) -> None: From d1a5c3a6705123e15ca0db5b2c1e09f9271b1908 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Jun 2025 10:37:36 +0200 Subject: [PATCH 02/23] Improve --- plugwise_usb/__init__.py | 3 +-- plugwise_usb/network/__init__.py | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/plugwise_usb/__init__.py b/plugwise_usb/__init__.py index ea2bc9e4f..7e4e63f8e 100644 --- a/plugwise_usb/__init__.py +++ b/plugwise_usb/__init__.py @@ -218,8 +218,7 @@ async def energy_reset_request(self, mac: str) -> bool: raise NodeError(f"{exc}") from exc # Follow up by an energy-intervals (re)set - result = await self.set_energy_intervals(mac, 60, 0) - if result: + if (result := await self.set_energy_intervals(mac, 60, 0)): return True return False diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index edaf633a5..d42c4c2bd 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -6,13 +6,13 @@ from asyncio import Task, create_task, gather, sleep from collections.abc import Callable, Coroutine -from datetime import datetime, timedelta +from datetime import UTC, datetime, timedelta import logging from typing import Any from ..api import NodeEvent, NodeType, PlugwiseNode, StickEvent from ..connection import StickController -from ..constants import UTC, UTF8 +from ..constants import UTF8 from ..exceptions import CacheError, MessageError, NodeError, StickError, StickTimeout from ..messages.requests import ( CircleClockSetRequest, @@ -545,7 +545,7 @@ async def allow_join_requests(self, state: bool) -> None: async def energy_reset_request(self, mac: str) -> None: """Send an energy-reset to a Node.""" request = CircleClockSetRequest( - self._send, + self._controller.send, self._mac_in_bytes, datetime.now(tz=UTC), self._node_protocols.max, From 95dc6203975d26ec8f104c94e1d71bb81f7efbb4 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Jun 2025 11:30:21 +0200 Subject: [PATCH 03/23] Fixes --- plugwise_usb/__init__.py | 2 +- plugwise_usb/network/__init__.py | 5 +++-- plugwise_usb/nodes/node.py | 8 ++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/plugwise_usb/__init__.py b/plugwise_usb/__init__.py index 7e4e63f8e..691016b49 100644 --- a/plugwise_usb/__init__.py +++ b/plugwise_usb/__init__.py @@ -219,7 +219,7 @@ async def energy_reset_request(self, mac: str) -> bool: # Follow up by an energy-intervals (re)set if (result := await self.set_energy_intervals(mac, 60, 0)): - return True + return result return False diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index d42c4c2bd..8a84d3965 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -544,11 +544,12 @@ async def allow_join_requests(self, state: bool) -> None: async def energy_reset_request(self, mac: str) -> None: """Send an energy-reset to a Node.""" + node_protocols = self._nodes[mac].node_protocols request = CircleClockSetRequest( self._controller.send, - self._mac_in_bytes, + bytes(mac, UTF8), datetime.now(tz=UTC), - self._node_protocols.max, + node_protocols.max, True, ) if (response := await request.send()) is None: diff --git a/plugwise_usb/nodes/node.py b/plugwise_usb/nodes/node.py index d73d5933e..d5d78d402 100644 --- a/plugwise_usb/nodes/node.py +++ b/plugwise_usb/nodes/node.py @@ -100,6 +100,14 @@ def available_state(self) -> AvailableState: self._last_seen, ) + @property + def node_protocols(self) -> SupportedVersions | None: + """Return the node_protocols for the Node.""" + if self._node_protocols is None: + return None + + return self._node_protocols + @property @raise_not_loaded def battery_config(self) -> BatteryConfig: From 82dc77e4e1fea3cbc1c42aad8617c4a3dd44a889 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Jun 2025 12:33:33 +0200 Subject: [PATCH 04/23] Don't try resetting node_types that don't support it --- plugwise_usb/network/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 8a84d3965..40327fcaf 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -544,6 +544,11 @@ async def allow_join_requests(self, state: bool) -> None: async def energy_reset_request(self, mac: str) -> None: """Send an energy-reset to a Node.""" + if self._nodes[mac].node_info.node_type.value not in (1, 2, 9): + raise NodeError( + "Energy-resetting not supported for {self._nodes[mac].node_info.node_type.name}" + ) + node_protocols = self._nodes[mac].node_protocols request = CircleClockSetRequest( self._controller.send, From 0fd4d21ddc3a9d09e0b93ed69bed8f5cff4e5621 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Jun 2025 13:00:45 +0200 Subject: [PATCH 05/23] Bump to v0.42.0a0 test-version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 374f9c5cc..be24d0e7e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise_usb" -version = "v0.41.0" +version = "v0.42.0a0" license = "MIT" keywords = ["home", "automation", "plugwise", "module", "usb"] classifiers = [ From d82ed88230fcb9b253e02fa99bfda821f830a585 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Jun 2025 13:02:00 +0200 Subject: [PATCH 06/23] Update CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e5f7d1ab..4dcb2b733 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.42.0 + +- Implement resetting of energylogs + ## v0.41.0 - Implement setting of energy logging intervals [#247](https://github.com/plugwise/python-plugwise-usb/pull/247) From c9f25bfc35225866bf97c83bd3595edf3f46ec14 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Jun 2025 14:03:34 +0200 Subject: [PATCH 07/23] Hardcode reset-logaddress --- plugwise_usb/messages/requests.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugwise_usb/messages/requests.py b/plugwise_usb/messages/requests.py index 3f9e49c26..548a49348 100644 --- a/plugwise_usb/messages/requests.py +++ b/plugwise_usb/messages/requests.py @@ -12,7 +12,7 @@ from ..constants import ( DAY_IN_MINUTES, HOUR_IN_MINUTES, - LOGADDR_OFFSET, +# LOGADDR_OFFSET, MAX_RETRIES, MESSAGE_FOOTER, MESSAGE_HEADER, @@ -764,8 +764,9 @@ def __init__( day_of_week = Int(dt.weekday(), 2) if reset: self._args += [ - this_date, - LogAddr(LOGADDR_OFFSET, 8, False), + this_date, + #LogAddr(LOGADDR_OFFSET, 8, False), + String("00044000", 8), this_time, day_of_week, ] From 38e629e15405565876eff9271b4824b45f303f00 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Jun 2025 14:12:37 +0200 Subject: [PATCH 08/23] Bump to a1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index be24d0e7e..40c483631 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise_usb" -version = "v0.42.0a0" +version = "v0.42.0a1" license = "MIT" keywords = ["home", "automation", "plugwise", "module", "usb"] classifiers = [ From b47b7b6ce979c6fbbe802d14afabaac5e611eafa Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 08:01:52 +0200 Subject: [PATCH 09/23] Block setting energy intervals on devices that don't support it --- plugwise_usb/network/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 40327fcaf..15bd0d3c5 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -573,6 +573,11 @@ async def set_energy_intervals( Default: consumption = 60, production = 0. For logging energy in both directions set both to 60. """ + if self._nodes[mac].node_info.node_type.value not in (1, 2, 9): + raise NodeError( + "Setting energy-intervals not supported for {self._nodes[mac].node_info.node_type.name}" + ) + # Validate input parameters if consumption <= 0: raise ValueError("Consumption interval must be positive") From cf93af192bae5d0ebb3a75b3c9a398380526e75c Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 08:40:17 +0200 Subject: [PATCH 10/23] Fix wrong LogAddr input value --- plugwise_usb/messages/requests.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugwise_usb/messages/requests.py b/plugwise_usb/messages/requests.py index 548a49348..d4e61a68f 100644 --- a/plugwise_usb/messages/requests.py +++ b/plugwise_usb/messages/requests.py @@ -12,7 +12,7 @@ from ..constants import ( DAY_IN_MINUTES, HOUR_IN_MINUTES, -# LOGADDR_OFFSET, + LOGADDR_OFFSET, MAX_RETRIES, MESSAGE_FOOTER, MESSAGE_HEADER, @@ -765,8 +765,7 @@ def __init__( if reset: self._args += [ this_date, - #LogAddr(LOGADDR_OFFSET, 8, False), - String("00044000", 8), + LogAddr(0, 8, False), this_time, day_of_week, ] From b366b6e00b71291371a7ca77d0d71c4768eee719 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 08:41:09 +0200 Subject: [PATCH 11/23] Fix CHANGELOG spelling --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dcb2b733..2cae2b68f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## v0.42.0 -- Implement resetting of energylogs +- Implement resetting of energy logs ## v0.41.0 From 4fb487254e226b9d1364734d0314569ad1721b03 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 08:44:59 +0200 Subject: [PATCH 12/23] Implement review suggestions & corrections --- plugwise_usb/network/__init__.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 15bd0d3c5..5b747cab8 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -33,6 +33,8 @@ from ..nodes import get_plugwise_node from .registry import StickNetworkRegister +ENERGY_NODE_TYPES: tuple[int] = (1, 2, 9) + _LOGGER = logging.getLogger(__name__) # endregion @@ -544,9 +546,9 @@ async def allow_join_requests(self, state: bool) -> None: async def energy_reset_request(self, mac: str) -> None: """Send an energy-reset to a Node.""" - if self._nodes[mac].node_info.node_type.value not in (1, 2, 9): + if self._nodes[mac].node_info.node_type.value not in ENERGY_NODE_TYPES: raise NodeError( - "Energy-resetting not supported for {self._nodes[mac].node_info.node_type.name}" + f"Energy-resetting not supported for {self._nodes[mac].node_info.node_type.name}" ) node_protocols = self._nodes[mac].node_protocols @@ -573,9 +575,9 @@ async def set_energy_intervals( Default: consumption = 60, production = 0. For logging energy in both directions set both to 60. """ - if self._nodes[mac].node_info.node_type.value not in (1, 2, 9): + if self._nodes[mac].node_info.node_type.value not in ENERGY_NODE_TYPES: raise NodeError( - "Setting energy-intervals not supported for {self._nodes[mac].node_info.node_type.name}" + f"Setting energy-intervals not supported for {self._nodes[mac].node_info.node_type.name}" ) # Validate input parameters From 06a544a847c36cf2a4f68bac9e72a8f58432dfe8 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 10:15:19 +0200 Subject: [PATCH 13/23] More fixes and improvements --- plugwise_usb/__init__.py | 1 + plugwise_usb/messages/requests.py | 2 +- plugwise_usb/network/__init__.py | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/plugwise_usb/__init__.py b/plugwise_usb/__init__.py index 691016b49..3f14f7d61 100644 --- a/plugwise_usb/__init__.py +++ b/plugwise_usb/__init__.py @@ -212,6 +212,7 @@ async def set_accept_join_request(self, state: bool) -> bool: async def energy_reset_request(self, mac: str) -> bool: """Send an energy-reset request to a Node.""" + _LOGGER.debug("Resetting energy logs for %s", mac) try: await self._network.energy_reset_request(mac) except (MessageError, NodeError) as exc: diff --git a/plugwise_usb/messages/requests.py b/plugwise_usb/messages/requests.py index d4e61a68f..69f89dabf 100644 --- a/plugwise_usb/messages/requests.py +++ b/plugwise_usb/messages/requests.py @@ -764,7 +764,7 @@ def __init__( day_of_week = Int(dt.weekday(), 2) if reset: self._args += [ - this_date, + this_date, LogAddr(0, 8, False), this_time, day_of_week, diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 5b747cab8..0a879a929 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -13,6 +13,7 @@ from ..api import NodeEvent, NodeType, PlugwiseNode, StickEvent from ..connection import StickController from ..constants import UTF8 +from ..helpers.util import validate_mac from ..exceptions import CacheError, MessageError, NodeError, StickError, StickTimeout from ..messages.requests import ( CircleClockSetRequest, @@ -546,6 +547,12 @@ async def allow_join_requests(self, state: bool) -> None: async def energy_reset_request(self, mac: str) -> None: """Send an energy-reset to a Node.""" + if not validate_mac(mac): + raise NodeError(f"MAC '{mac}' invalid") + + if mac not in self._nodes: + raise NodeError(f"Node {mac} not present in network") + if self._nodes[mac].node_info.node_type.value not in ENERGY_NODE_TYPES: raise NodeError( f"Energy-resetting not supported for {self._nodes[mac].node_info.node_type.name}" @@ -575,6 +582,12 @@ async def set_energy_intervals( Default: consumption = 60, production = 0. For logging energy in both directions set both to 60. """ + if not validate_mac(mac): + raise NodeError(f"MAC '{mac}' invalid") + + if mac not in self._nodes: + raise NodeError(f"Node {mac} not present in network") + if self._nodes[mac].node_info.node_type.value not in ENERGY_NODE_TYPES: raise NodeError( f"Setting energy-intervals not supported for {self._nodes[mac].node_info.node_type.name}" From 34b6e516cd6377e23131eaa91cadc5e4e9174c09 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 11:28:41 +0200 Subject: [PATCH 14/23] Remove unused import --- plugwise_usb/messages/requests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugwise_usb/messages/requests.py b/plugwise_usb/messages/requests.py index 69f89dabf..d01bd6b08 100644 --- a/plugwise_usb/messages/requests.py +++ b/plugwise_usb/messages/requests.py @@ -12,7 +12,6 @@ from ..constants import ( DAY_IN_MINUTES, HOUR_IN_MINUTES, - LOGADDR_OFFSET, MAX_RETRIES, MESSAGE_FOOTER, MESSAGE_HEADER, From 69226648333cbee468c31d3a7e54a800d1de26e5 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 11:31:17 +0200 Subject: [PATCH 15/23] Remove blank spaces --- plugwise_usb/network/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 0a879a929..dd33f6917 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -552,7 +552,7 @@ async def energy_reset_request(self, mac: str) -> None: if mac not in self._nodes: raise NodeError(f"Node {mac} not present in network") - + if self._nodes[mac].node_info.node_type.value not in ENERGY_NODE_TYPES: raise NodeError( f"Energy-resetting not supported for {self._nodes[mac].node_info.node_type.name}" From bb4544426ecbfcc18696a1c9f0205c6a4bc8cdc5 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 11:38:49 +0200 Subject: [PATCH 16/23] Improve NodeError message, as suggested --- plugwise_usb/network/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index dd33f6917..8a58eb2fe 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -571,7 +571,8 @@ async def energy_reset_request(self, mac: str) -> None: if response.ack_id != NodeResponseType.CLOCK_ACCEPTED: raise MessageError( - f"Unknown NodeResponseType '{response.response_type.name}' received" + f"Unexpected NodeResponseType {response.ack_id!r} " + +"received in response to CircleClockSetRequest " ) async def set_energy_intervals( From 17739d3ad3077d1f781bb7dadbf44bb690dcb2fb Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 11:57:06 +0200 Subject: [PATCH 17/23] Use single line with f-string --- plugwise_usb/network/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 8a58eb2fe..dd0448e25 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -571,8 +571,7 @@ async def energy_reset_request(self, mac: str) -> None: if response.ack_id != NodeResponseType.CLOCK_ACCEPTED: raise MessageError( - f"Unexpected NodeResponseType {response.ack_id!r} " - +"received in response to CircleClockSetRequest " + f"Unexpected NodeResponseType {response.ack_id!r} received as response to CircleClockSetRequest" ) async def set_energy_intervals( From f4f42b6f14846bc6c11e74cb42cca687f6104171 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 12:00:05 +0200 Subject: [PATCH 18/23] Bump to a2 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 40c483631..be50e62fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise_usb" -version = "v0.42.0a1" +version = "0.42.0a2" license = "MIT" keywords = ["home", "automation", "plugwise", "module", "usb"] classifiers = [ From b0c75182255999bae67fcafac0d6ffc9436acf88 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 12:23:07 +0200 Subject: [PATCH 19/23] Break out _validate_energy_node() function as suggested --- plugwise_usb/network/__init__.py | 37 +++++++++++++------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index dd0448e25..4137ae7ab 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -547,17 +547,7 @@ async def allow_join_requests(self, state: bool) -> None: async def energy_reset_request(self, mac: str) -> None: """Send an energy-reset to a Node.""" - if not validate_mac(mac): - raise NodeError(f"MAC '{mac}' invalid") - - if mac not in self._nodes: - raise NodeError(f"Node {mac} not present in network") - - if self._nodes[mac].node_info.node_type.value not in ENERGY_NODE_TYPES: - raise NodeError( - f"Energy-resetting not supported for {self._nodes[mac].node_info.node_type.name}" - ) - + self._validate_energy_node(mac) node_protocols = self._nodes[mac].node_protocols request = CircleClockSetRequest( self._controller.send, @@ -582,17 +572,7 @@ async def set_energy_intervals( Default: consumption = 60, production = 0. For logging energy in both directions set both to 60. """ - if not validate_mac(mac): - raise NodeError(f"MAC '{mac}' invalid") - - if mac not in self._nodes: - raise NodeError(f"Node {mac} not present in network") - - if self._nodes[mac].node_info.node_type.value not in ENERGY_NODE_TYPES: - raise NodeError( - f"Setting energy-intervals not supported for {self._nodes[mac].node_info.node_type.name}" - ) - + self._validate_energy_node(mac) # Validate input parameters if consumption <= 0: raise ValueError("Consumption interval must be positive") @@ -613,6 +593,19 @@ async def set_energy_intervals( f"Unknown NodeResponseType '{response.response_type.name}' received" ) + def _validate_energy_node(self, mac: str) -> None: + """Validate node for energy operations.""" + if not validate_mac(mac): + raise NodeError(f"MAC '{mac}' invalid") + + if mac not in self._nodes: + raise NodeError(f"Node {mac} not present in network") + + if self._nodes[mac].node_info.node_type.value not in ENERGY_NODE_TYPES: + raise NodeError( + f"Energy operations not supported for {self._nodes[mac].node_info.node_type.name}" + ) + def subscribe_to_node_events( self, node_event_callback: Callable[[NodeEvent, str], Coroutine[Any, Any, None]], From 71a85932aee3997d131b6ba6800accf1fd4761d7 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 18:47:41 +0200 Subject: [PATCH 20/23] Remove comment --- plugwise_usb/network/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 4137ae7ab..63f2b5314 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -573,7 +573,6 @@ async def set_energy_intervals( For logging energy in both directions set both to 60. """ self._validate_energy_node(mac) - # Validate input parameters if consumption <= 0: raise ValueError("Consumption interval must be positive") if production < 0: From 7ae404a44c8ebdd11c462a8f81041de2f5ba1910 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 19:02:48 +0200 Subject: [PATCH 21/23] Add constants and use --- plugwise_usb/__init__.py | 7 ++++++- plugwise_usb/constants.py | 9 ++++++++- plugwise_usb/network/__init__.py | 10 ++++------ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/plugwise_usb/__init__.py b/plugwise_usb/__init__.py index 3f14f7d61..812249840 100644 --- a/plugwise_usb/__init__.py +++ b/plugwise_usb/__init__.py @@ -14,6 +14,7 @@ from .api import NodeEvent, PlugwiseNode, StickEvent from .connection import StickController +from .const import DEFAULT_CONS_INTERVAL, NO_PRODUCTION_INTERVAL from .exceptions import MessageError, NodeError, StickError, SubscriptionError from .network import StickNetwork @@ -219,7 +220,11 @@ async def energy_reset_request(self, mac: str) -> bool: raise NodeError(f"{exc}") from exc # Follow up by an energy-intervals (re)set - if (result := await self.set_energy_intervals(mac, 60, 0)): + if ( + result := await self.set_energy_intervals( + mac, DEFAULT_CONS_INTERVAL, NO_PRODUCTION_INTERVAL + ) + ): return result return False diff --git a/plugwise_usb/constants.py b/plugwise_usb/constants.py index 2e4f4441c..42539e97f 100644 --- a/plugwise_usb/constants.py +++ b/plugwise_usb/constants.py @@ -31,7 +31,7 @@ # Max timeout in seconds # Stick responds with timeout messages within 10s. -STICK_TIME_OUT: Final = 11 +STICK_TIME_OUT: Final = 11 # In bigger networks a response from a Node could take up a while, so lets use 15 seconds. NODE_TIME_OUT: Final = 15 @@ -99,3 +99,10 @@ 8: ("Celsius",), 9: ("Stealth",), } + +# Energy logging intervals +DEFAULT_CONS_INTERVAL: Final[int] = 60 +NO_PRODUCTION_INTERVAL: Final[int] = 0 + +# Energy Node types +ENERGY_NODE_TYPES: tuple[int] = (1, 2, 9) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 63f2b5314..948089326 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -12,9 +12,9 @@ from ..api import NodeEvent, NodeType, PlugwiseNode, StickEvent from ..connection import StickController -from ..constants import UTF8 -from ..helpers.util import validate_mac +from ..constants import ENERGY_NODE_TYPES, UTF8 from ..exceptions import CacheError, MessageError, NodeError, StickError, StickTimeout +from ..helpers.util import validate_mac from ..messages.requests import ( CircleClockSetRequest, CircleMeasureIntervalRequest, @@ -34,8 +34,6 @@ from ..nodes import get_plugwise_node from .registry import StickNetworkRegister -ENERGY_NODE_TYPES: tuple[int] = (1, 2, 9) - _LOGGER = logging.getLogger(__name__) # endregion @@ -596,10 +594,10 @@ def _validate_energy_node(self, mac: str) -> None: """Validate node for energy operations.""" if not validate_mac(mac): raise NodeError(f"MAC '{mac}' invalid") - + if mac not in self._nodes: raise NodeError(f"Node {mac} not present in network") - + if self._nodes[mac].node_info.node_type.value not in ENERGY_NODE_TYPES: raise NodeError( f"Energy operations not supported for {self._nodes[mac].node_info.node_type.name}" From ede19eb61816aa400683315e0f07fcbdcc3a50ce Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Jun 2025 19:09:48 +0200 Subject: [PATCH 22/23] Fix wrong spelling --- plugwise_usb/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise_usb/__init__.py b/plugwise_usb/__init__.py index 812249840..ebbf8e587 100644 --- a/plugwise_usb/__init__.py +++ b/plugwise_usb/__init__.py @@ -14,7 +14,7 @@ from .api import NodeEvent, PlugwiseNode, StickEvent from .connection import StickController -from .const import DEFAULT_CONS_INTERVAL, NO_PRODUCTION_INTERVAL +from .constants import DEFAULT_CONS_INTERVAL, NO_PRODUCTION_INTERVAL from .exceptions import MessageError, NodeError, StickError, SubscriptionError from .network import StickNetwork From 02027974c664a3d77f23234783815f4627d284b8 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Wed, 4 Jun 2025 11:03:23 +0200 Subject: [PATCH 23/23] Set to v0.42.0 release-version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index be50e62fa..2e3af094f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise_usb" -version = "0.42.0a2" +version = "0.42.0" license = "MIT" keywords = ["home", "automation", "plugwise", "module", "usb"] classifiers = [