From d6416ddec43c7d711cd760c837cb030e9c960917 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Wed, 10 Sep 2025 08:30:38 +0200 Subject: [PATCH 01/42] Add NODE_RESET_ACK NodeResponseType --- plugwise_usb/messages/responses.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugwise_usb/messages/responses.py b/plugwise_usb/messages/responses.py index 1f4f1923d..ec2ad40f4 100644 --- a/plugwise_usb/messages/responses.py +++ b/plugwise_usb/messages/responses.py @@ -59,13 +59,15 @@ class NodeResponseType(bytes, Enum): CIRCLE_PLUS = b"00DD" # ack for CirclePlusAllowJoiningRequest with state false CLOCK_ACCEPTED = b"00D7" JOIN_ACCEPTED = b"00D9" # ack for CirclePlusAllowJoiningRequest with state true + NODE_RESET_ACK = b"00F2" + # NODE_RESET_NACK = b"????" POWER_LOG_INTERVAL_ACCEPTED = b"00F8" # ack for CircleMeasureIntervalRequest + REAL_TIME_CLOCK_ACCEPTED = b"00DF" + REAL_TIME_CLOCK_FAILED = b"00E7" RELAY_SWITCHED_OFF = b"00DE" RELAY_SWITCHED_ON = b"00D8" RELAY_SWITCH_FAILED = b"00E2" SED_CONFIG_ACCEPTED = b"00F6" - REAL_TIME_CLOCK_ACCEPTED = b"00DF" - REAL_TIME_CLOCK_FAILED = b"00E7" # TODO: Validate these response types SED_CONFIG_FAILED = b"00F7" From d41b2ecb3afba1a9ba22324f51d00ce43543e1d3 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Wed, 10 Sep 2025 20:22:17 +0200 Subject: [PATCH 02/42] Update NodeResetResponse info --- plugwise_usb/messages/requests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise_usb/messages/requests.py b/plugwise_usb/messages/requests.py index 6068e3e62..6b44eab63 100644 --- a/plugwise_usb/messages/requests.py +++ b/plugwise_usb/messages/requests.py @@ -485,7 +485,7 @@ class NodeResetRequest(PlugwiseRequest): """ _identifier = b"0009" - _reply_identifier = b"0003" + # _reply_identifier is b"0000'with NODE_RESET_ACK, not b"0003" @dirixmjm & @bouwew 20250910 def __init__( self, From 803a09eb024370602bd00c52c8fc5f6b9cc325eb Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Wed, 10 Sep 2025 20:38:55 +0200 Subject: [PATCH 03/42] Add reset_node() function --- plugwise_usb/nodes/node.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/plugwise_usb/nodes/node.py b/plugwise_usb/nodes/node.py index a41611e1f..420a53d3d 100644 --- a/plugwise_usb/nodes/node.py +++ b/plugwise_usb/nodes/node.py @@ -32,7 +32,7 @@ from ..constants import SUPPRESS_INITIALIZATION_WARNINGS, TYPE_MODEL, UTF8 from ..exceptions import FeatureError, NodeError from ..helpers.util import version_to_model -from ..messages.requests import NodeInfoRequest, NodePingRequest +from ..messages.requests import NodeInfoRequest, NodePingRequest, NodeResetRequest from ..messages.responses import NodeInfoResponse, NodePingResponse from .helpers import raise_not_loaded from .helpers.cache import NodeCache @@ -641,6 +641,20 @@ async def get_state(self, features: tuple[NodeFeature]) -> dict[NodeFeature, Any return states + async def reset_node(self) -> None: + """Reset node present in the current Plugwise network.""" + timeout = 4 + request = NodeResetRequest( + self._send, self._mac_in_str, self.node_type, timeout + ) + response = await request.send() + if response is None or response.ack_id != NodeType.NODE_RESET_ACK: + _LOGGER.warning( + "Node %s reset response is None or wrong ack_id %s received", + self._mac_in_str, + response.ack_id, + ) + async def unload(self) -> None: """Deactivate and unload node features.""" if not self._cache_enabled: From 960df6f516d772d460a1a4c711e814524576d6e5 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Thu, 11 Sep 2025 08:17:41 +0200 Subject: [PATCH 04/42] Add reset_node() function description to PlugwiseNode protocol --- plugwise_usb/api.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/plugwise_usb/api.py b/plugwise_usb/api.py index 46ae63af0..eec1fd9f3 100644 --- a/plugwise_usb/api.py +++ b/plugwise_usb/api.py @@ -495,6 +495,20 @@ async def get_state(self, features: tuple[NodeFeature]) -> dict[NodeFeature, Any # endregion # region Actions to execute + async def reset_node(self) -> None: + """Reset a node. + + Description: + Resets the mode before unregistering it from the Plugwise network. + + Returns: + None + + Raised: + A warning logger message. + + """ + async def set_relay(self, state: bool) -> bool: """Change the state of the relay. From 328c52f0ca6b5e12d34dbdf4791c925d41346c48 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Thu, 11 Sep 2025 08:27:09 +0200 Subject: [PATCH 05/42] Update unregister_node functions --- plugwise_usb/network/__init__.py | 6 +++++- plugwise_usb/network/registry.py | 21 ++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 8272747b7..69fdd896a 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -166,8 +166,12 @@ async def clear_cache(self) -> None: async def unregister_node(self, mac: str) -> None: """Unregister node from current Plugwise network.""" + if not validate_mac(mac): + raise NodeError(f"MAC {mac} invalid") + + node_to_remove = self._nodes[mac] try: - await self._register.unregister_node(mac) + await self._register.unregister_node(node_to_remove) except (KeyError, NodeError) as exc: raise MessageError("Mac not registered, already deleted?") from exc diff --git a/plugwise_usb/network/registry.py b/plugwise_usb/network/registry.py index 1945be1dc..02c77ac45 100644 --- a/plugwise_usb/network/registry.py +++ b/plugwise_usb/network/registry.py @@ -8,7 +8,7 @@ import logging from typing import Final -from ..api import NodeType +from ..api import NodeType, PlugwiseNode from ..constants import UTF8 from ..exceptions import CacheError, NodeError, StickError from ..helpers.util import validate_mac @@ -266,27 +266,26 @@ async def register_node(self, mac: str) -> None: if self.update_network_registration(mac): await self._exec_node_discover_callback(mac, None, False) - async def unregister_node(self, mac: str) -> None: + async def unregister_node(self, node: PlugwiseNode) -> None: """Unregister node from current Plugwise network.""" - if not validate_mac(mac): - raise NodeError(f"MAC {mac} invalid") - - if mac not in self._registry: - raise NodeError(f"No existing Node ({mac}) found to unregister") + if node.mac not in self._registry: + raise NodeError(f"No existing Node ({node.mac}) found to unregister") - request = NodeRemoveRequest(self._send_to_controller, self._mac_nc, mac) + # First reset the node, then remove it from the network. + node.reset_node() + request = NodeRemoveRequest(self._send_to_controller, self._mac_nc, node.mac) if (response := await request.send()) is None: raise NodeError( f"The Zigbee network coordinator '{self._mac_nc!r}'" - + f" did not respond to unregister node '{mac}'" + + f" did not respond to unregister node '{node.mac}'" ) if response.status.value != 1: raise NodeError( f"The Zigbee network coordinator '{self._mac_nc!r}'" - + f" failed to unregister node '{mac}'" + + f" failed to unregister node '{node.mac}'" ) - await self.remove_network_registration(mac) + await self.remove_network_registration(node.mac) async def clear_register_cache(self) -> None: """Clear current cache.""" From d98d104a6242b4ba0d62b55d1299fd8c68139525 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Thu, 11 Sep 2025 09:13:08 +0200 Subject: [PATCH 06/42] Add missing await --- plugwise_usb/network/registry.py | 2 +- scripts/tests_and_coverage.sh | 3 ++- tests/test_usb.py | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugwise_usb/network/registry.py b/plugwise_usb/network/registry.py index 02c77ac45..80c9de9ab 100644 --- a/plugwise_usb/network/registry.py +++ b/plugwise_usb/network/registry.py @@ -272,7 +272,7 @@ async def unregister_node(self, node: PlugwiseNode) -> None: raise NodeError(f"No existing Node ({node.mac}) found to unregister") # First reset the node, then remove it from the network. - node.reset_node() + await node.reset_node() request = NodeRemoveRequest(self._send_to_controller, self._mac_nc, node.mac) if (response := await request.send()) is None: raise NodeError( diff --git a/scripts/tests_and_coverage.sh b/scripts/tests_and_coverage.sh index 749dec0f5..4900304eb 100755 --- a/scripts/tests_and_coverage.sh +++ b/scripts/tests_and_coverage.sh @@ -57,7 +57,8 @@ set +u if [ -z "${GITHUB_ACTIONS}" ] || [ "$1" == "test_and_coverage" ] ; then # Python tests (rerun with debug if failures) - PYTHONPATH=$(pwd) pytest -qx tests/ --cov='.' --no-cov-on-fail --cov-report term-missing || PYTHONPATH=$(pwd) pytest -xrpP --log-level debug tests/ + # PYTHONPATH=$(pwd) pytest -qx tests/ --cov='.' --no-cov-on-fail --cov-report term-missing || + PYTHONPATH=$(pwd) pytest -xrpP --log-level debug tests/ fi if [ -z "${GITHUB_ACTIONS}" ] || [ "$1" == "linting" ] ; then diff --git a/tests/test_usb.py b/tests/test_usb.py index af5cbdffe..462f260fb 100644 --- a/tests/test_usb.py +++ b/tests/test_usb.py @@ -719,6 +719,10 @@ async def test_node_discovery(self, monkeypatch: pytest.MonkeyPatch) -> None: assert stick.joined_nodes == 9 assert stick.nodes.get("0098765432101234") is not None assert len(stick.nodes) == 7 # Discovered nodes + + # Test unregistering of node + await unregister_node("1111111111111111") + await stick.disconnect() async def node_relay_state( From 5ffcfda6c27c2811dbf050722cb339baef70a263 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Thu, 11 Sep 2025 19:57:11 +0200 Subject: [PATCH 07/42] Try --- tests/test_usb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_usb.py b/tests/test_usb.py index 462f260fb..01fbbe1de 100644 --- a/tests/test_usb.py +++ b/tests/test_usb.py @@ -721,7 +721,7 @@ async def test_node_discovery(self, monkeypatch: pytest.MonkeyPatch) -> None: assert len(stick.nodes) == 7 # Discovered nodes # Test unregistering of node - await unregister_node("1111111111111111") + await pw_stick.unregister_node("1111111111111111") await stick.disconnect() From 30f67021016203de665404b7a83fc14393defca5 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Thu, 11 Sep 2025 20:03:16 +0200 Subject: [PATCH 08/42] Add unregister_node() to api --- plugwise_usb/api.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugwise_usb/api.py b/plugwise_usb/api.py index eec1fd9f3..343aa5b61 100644 --- a/plugwise_usb/api.py +++ b/plugwise_usb/api.py @@ -495,17 +495,20 @@ async def get_state(self, features: tuple[NodeFeature]) -> dict[NodeFeature, Any # endregion # region Actions to execute - async def reset_node(self) -> None: - """Reset a node. + async def unregister_node(self, mac: str) -> None: + """Remove a node from the Plugwise network. Description: Resets the mode before unregistering it from the Plugwise network. + Args: + mac: MAC of the node to unregister. + Returns: None Raised: - A warning logger message. + NodeError: when the node isn't removed. """ From 44757c4e98d499acb7d928912a6f49e6deeab58e Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Thu, 11 Sep 2025 20:03:47 +0200 Subject: [PATCH 09/42] Try 2 --- tests/test_usb.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_usb.py b/tests/test_usb.py index 01fbbe1de..9310e2f7a 100644 --- a/tests/test_usb.py +++ b/tests/test_usb.py @@ -721,8 +721,10 @@ async def test_node_discovery(self, monkeypatch: pytest.MonkeyPatch) -> None: assert len(stick.nodes) == 7 # Discovered nodes # Test unregistering of node - await pw_stick.unregister_node("1111111111111111") - + _LOGGER.debug("HOI unregister node") + await pw_api.PlugwiseNode.unregister_node(self, "1111111111111111") + assert stick.nodes.get("1111111111111111") is None + assert len(stick.nodes) == 6 await stick.disconnect() async def node_relay_state( From e1fa38624b541597f3bf60252b034a0de7cabf05 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 08:58:21 +0200 Subject: [PATCH 10/42] Add reset_node request plus response --- tests/stick_test_data.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/stick_test_data.py b/tests/stick_test_data.py index 897f56f89..c9162ea58 100644 --- a/tests/stick_test_data.py +++ b/tests/stick_test_data.py @@ -1344,6 +1344,12 @@ + b"00000444" + b"00044020", ), + b"\x05\x05\x03\x03000933333333333333330204\r\n": ( + "Reset node request for 333333333333333333", + b"000000C1", # Success ack + b"000000F2" + + b"3333333333333333", + ), } From ca0fc3940d409e6fdbf1e0aee2c3b5d35eadbbe0 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 09:03:16 +0200 Subject: [PATCH 11/42] Try 3 --- tests/test_usb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_usb.py b/tests/test_usb.py index 9310e2f7a..cd7bffb5f 100644 --- a/tests/test_usb.py +++ b/tests/test_usb.py @@ -722,7 +722,7 @@ async def test_node_discovery(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test unregistering of node _LOGGER.debug("HOI unregister node") - await pw_api.PlugwiseNode.unregister_node(self, "1111111111111111") + await stick.unregister_node("1111111111111111") assert stick.nodes.get("1111111111111111") is None assert len(stick.nodes) == 6 await stick.disconnect() From 65988645d3f305b56abd8c55465e06f073340ddd Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 09:13:02 +0200 Subject: [PATCH 12/42] Correct message --- tests/stick_test_data.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/stick_test_data.py b/tests/stick_test_data.py index c9162ea58..10ae78620 100644 --- a/tests/stick_test_data.py +++ b/tests/stick_test_data.py @@ -1347,7 +1347,8 @@ b"\x05\x05\x03\x03000933333333333333330204\r\n": ( "Reset node request for 333333333333333333", b"000000C1", # Success ack - b"000000F2" + b"0000" # msg_id + + b"00F2" # NODE_RESET_ACK + b"3333333333333333", ), } From 77af8e91744090451af59184b017c0f7216d5e2b Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 09:20:14 +0200 Subject: [PATCH 13/42] Try 4 --- plugwise_usb/network/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 69fdd896a..d82bbbe24 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -166,6 +166,7 @@ async def clear_cache(self) -> None: async def unregister_node(self, mac: str) -> None: """Unregister node from current Plugwise network.""" + _LOGGER.debug("HOI network-unregister_node with %s", mac) if not validate_mac(mac): raise NodeError(f"MAC {mac} invalid") From a33aaf4318b6a2445e66d6c125bd8a12c12e5330 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 09:22:26 +0200 Subject: [PATCH 14/42] Line up mac --- tests/test_usb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_usb.py b/tests/test_usb.py index cd7bffb5f..4438918c4 100644 --- a/tests/test_usb.py +++ b/tests/test_usb.py @@ -722,8 +722,8 @@ async def test_node_discovery(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test unregistering of node _LOGGER.debug("HOI unregister node") - await stick.unregister_node("1111111111111111") - assert stick.nodes.get("1111111111111111") is None + await stick.unregister_node("3333333333333333") + assert stick.nodes.get("3333333333333333") is None assert len(stick.nodes) == 6 await stick.disconnect() From 52109b8df970c69afda9df9699a12d35fcd74e25 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 09:58:09 +0200 Subject: [PATCH 15/42] Update/correct NodeResetRequest --- plugwise_usb/messages/requests.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugwise_usb/messages/requests.py b/plugwise_usb/messages/requests.py index 6b44eab63..0d844697f 100644 --- a/plugwise_usb/messages/requests.py +++ b/plugwise_usb/messages/requests.py @@ -481,7 +481,7 @@ class NodeResetRequest(PlugwiseRequest): """TODO:Some kind of reset request. Supported protocols : 1.0, 2.0, 2.1 - Response message : + Response message : NodeResponse with NODE_RESET_ACK/NACK """ _identifier = b"0009" @@ -501,15 +501,15 @@ def __init__( Int(timeout, length=2), ] - async def send(self) -> NodeSpecificResponse | None: + async def send(self) -> NodeResponse | None: """Send request.""" result = await self._send_request() - if isinstance(result, NodeSpecificResponse): + if isinstance(result, NodeResponse): return result if result is None: return None raise MessageError( - f"Invalid response message. Received {result.__class__.__name__}, expected NodeSpecificResponse" + f"Invalid response message. Received {result.__class__.__name__}, expected NodeResponse" ) From 18fe4ad35fdc9c3b4ed4c9802afed0c9373f3954 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 10:13:58 +0200 Subject: [PATCH 16/42] NodeReset requires _mac_in_bytes --- plugwise_usb/nodes/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise_usb/nodes/node.py b/plugwise_usb/nodes/node.py index 420a53d3d..ef57c5e3a 100644 --- a/plugwise_usb/nodes/node.py +++ b/plugwise_usb/nodes/node.py @@ -645,7 +645,7 @@ async def reset_node(self) -> None: """Reset node present in the current Plugwise network.""" timeout = 4 request = NodeResetRequest( - self._send, self._mac_in_str, self.node_type, timeout + self._send, self._mac_in_bytes, self.node_type, timeout ) response = await request.send() if response is None or response.ack_id != NodeType.NODE_RESET_ACK: From 3a0887a01b130fbb39874b180f9d5cdc3185a287 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 10:21:29 +0200 Subject: [PATCH 17/42] Add node-remove messages --- tests/stick_test_data.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/stick_test_data.py b/tests/stick_test_data.py index 10ae78620..014bf6354 100644 --- a/tests/stick_test_data.py +++ b/tests/stick_test_data.py @@ -1351,6 +1351,14 @@ + b"00F2" # NODE_RESET_ACK + b"3333333333333333", ), + b"\x05\x05\x03\x03001C0098765432101234333333333333333333\r\n": ( + "Remove node request for 333333333333333333", + b"000000C1", # Success ack + b"001D" # msg_id + + b"0098765432101234" # Circle + mac + + b"3333333333333333" + + b"01", # status + ), } From 5fe0822c25711f006e597f0d014fb32d9b29bc70 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 10:55:02 +0200 Subject: [PATCH 18/42] Implement CR-suggestions --- plugwise_usb/network/__init__.py | 7 +++++-- plugwise_usb/nodes/node.py | 13 ++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index d82bbbe24..21610b8b1 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -173,8 +173,11 @@ async def unregister_node(self, mac: str) -> None: node_to_remove = self._nodes[mac] try: await self._register.unregister_node(node_to_remove) - except (KeyError, NodeError) as exc: - raise MessageError("Mac not registered, already deleted?") from exc + except NodeError as exc: + # Preserve precise failure cause from registry/reset/remove. + raise MessageError(str(exc)) from exc + except KeyError as exc: + raise MessageError(f"Mac {mac} not registered, already deleted?") from exc await self._nodes[mac].unload() self._nodes.pop(mac) diff --git a/plugwise_usb/nodes/node.py b/plugwise_usb/nodes/node.py index ef57c5e3a..43e7b3e7a 100644 --- a/plugwise_usb/nodes/node.py +++ b/plugwise_usb/nodes/node.py @@ -33,7 +33,7 @@ from ..exceptions import FeatureError, NodeError from ..helpers.util import version_to_model from ..messages.requests import NodeInfoRequest, NodePingRequest, NodeResetRequest -from ..messages.responses import NodeInfoResponse, NodePingResponse +from ..messages.responses import NodeInfoResponse, NodePingResponse, NodeResponseType from .helpers import raise_not_loaded from .helpers.cache import NodeCache from .helpers.firmware import FEATURE_SUPPORTED_AT_FIRMWARE, SupportedVersions @@ -645,14 +645,17 @@ async def reset_node(self) -> None: """Reset node present in the current Plugwise network.""" timeout = 4 request = NodeResetRequest( - self._send, self._mac_in_bytes, self.node_type, timeout + self._send, self._mac_in_bytes, int(self.node_type), timeout ) response = await request.send() - if response is None or response.ack_id != NodeType.NODE_RESET_ACK: + if response is None or getattr(response, "response_type", None) != NodeResponseType.NODE_RESET_ACK: + ack = getattr(response, "ack_id", None) + rtype = getattr(response, "response_type", None) _LOGGER.warning( - "Node %s reset response is None or wrong ack_id %s received", + "Node %s reset not acknowledged (ack_id=%s, response_type=%s)", self._mac_in_str, - response.ack_id, + ack, + rtype, ) async def unload(self) -> None: From b47b3cefaf75a1958e5eb25c01348f7b0d30f4fc Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 10:55:25 +0200 Subject: [PATCH 19/42] Change NodeType to IntEnum --- plugwise_usb/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise_usb/api.py b/plugwise_usb/api.py index 343aa5b61..611a3e6bd 100644 --- a/plugwise_usb/api.py +++ b/plugwise_usb/api.py @@ -59,7 +59,7 @@ class NodeFeature(str, Enum): TEMPERATURE = "temperature" -class NodeType(Enum): +class NodeType(IntEnum): """USB Node types.""" STICK = 0 From 2bda229ef08acbcc2d2a91cc2898fea2040fba35 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 11:12:26 +0200 Subject: [PATCH 20/42] Write node_reset_response in one line --- tests/stick_test_data.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/stick_test_data.py b/tests/stick_test_data.py index 014bf6354..9d15feca9 100644 --- a/tests/stick_test_data.py +++ b/tests/stick_test_data.py @@ -1347,9 +1347,7 @@ b"\x05\x05\x03\x03000933333333333333330204\r\n": ( "Reset node request for 333333333333333333", b"000000C1", # Success ack - b"0000" # msg_id - + b"00F2" # NODE_RESET_ACK - + b"3333333333333333", + b"0000" + b"00F2" + b"3333333333333333", # msg_id, reset_ack, mac ), b"\x05\x05\x03\x03001C0098765432101234333333333333333333\r\n": ( "Remove node request for 333333333333333333", From de15fb116ba9e19e85446d469977c8e2fed64c7e Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 11:21:16 +0200 Subject: [PATCH 21/42] Update node_reset message with CRC --- tests/stick_test_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/stick_test_data.py b/tests/stick_test_data.py index 9d15feca9..1f3dc08c8 100644 --- a/tests/stick_test_data.py +++ b/tests/stick_test_data.py @@ -1344,7 +1344,7 @@ + b"00000444" + b"00044020", ), - b"\x05\x05\x03\x03000933333333333333330204\r\n": ( + b"\x05\x05\x03\x030009333333333333333302047290\r\n": ( "Reset node request for 333333333333333333", b"000000C1", # Success ack b"0000" + b"00F2" + b"3333333333333333", # msg_id, reset_ack, mac From a4d0a12236daea722d9d56b342fdd004286602c0 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 11:22:28 +0200 Subject: [PATCH 22/42] Update node_remove message with CRC --- tests/stick_test_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/stick_test_data.py b/tests/stick_test_data.py index 1f3dc08c8..7e780ff3a 100644 --- a/tests/stick_test_data.py +++ b/tests/stick_test_data.py @@ -1349,7 +1349,7 @@ b"000000C1", # Success ack b"0000" + b"00F2" + b"3333333333333333", # msg_id, reset_ack, mac ), - b"\x05\x05\x03\x03001C0098765432101234333333333333333333\r\n": ( + b"\x05\x05\x03\x03001C009876543210123433333333333333331E2D\r\n": ( "Remove node request for 333333333333333333", b"000000C1", # Success ack b"001D" # msg_id From d326a1ad5546a304de3cf69ca627e833306a8d16 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 11:44:45 +0200 Subject: [PATCH 23/42] Use self.node_type.value to get to int-type --- plugwise_usb/nodes/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise_usb/nodes/node.py b/plugwise_usb/nodes/node.py index 43e7b3e7a..12a6826d4 100644 --- a/plugwise_usb/nodes/node.py +++ b/plugwise_usb/nodes/node.py @@ -645,7 +645,7 @@ async def reset_node(self) -> None: """Reset node present in the current Plugwise network.""" timeout = 4 request = NodeResetRequest( - self._send, self._mac_in_bytes, int(self.node_type), timeout + self._send, self._mac_in_bytes, self.node_type.value, timeout ) response = await request.send() if response is None or getattr(response, "response_type", None) != NodeResponseType.NODE_RESET_ACK: From 6b25651b426e2bdfe323cf1a420d58a3f35ec4cc Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 11:56:56 +0200 Subject: [PATCH 24/42] Ruffed --- plugwise_usb/nodes/node.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugwise_usb/nodes/node.py b/plugwise_usb/nodes/node.py index 12a6826d4..6bdd4586e 100644 --- a/plugwise_usb/nodes/node.py +++ b/plugwise_usb/nodes/node.py @@ -648,7 +648,11 @@ async def reset_node(self) -> None: self._send, self._mac_in_bytes, self.node_type.value, timeout ) response = await request.send() - if response is None or getattr(response, "response_type", None) != NodeResponseType.NODE_RESET_ACK: + if ( + response is None + or getattr(response, "response_type", None) + != NodeResponseType.NODE_RESET_ACK + ): ack = getattr(response, "ack_id", None) rtype = getattr(response, "response_type", None) _LOGGER.warning( From 96c3f89d007d4286d2ac2d78265a0610fed5ed98 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 12:42:45 +0200 Subject: [PATCH 25/42] Delete the node-cache of the deleted Node --- plugwise_usb/network/registry.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugwise_usb/network/registry.py b/plugwise_usb/network/registry.py index 80c9de9ab..4628460d5 100644 --- a/plugwise_usb/network/registry.py +++ b/plugwise_usb/network/registry.py @@ -286,6 +286,7 @@ async def unregister_node(self, node: PlugwiseNode) -> None: ) await self.remove_network_registration(node.mac) + await node.clear_cache() async def clear_register_cache(self) -> None: """Clear current cache.""" From 3b67cd11cf11b88a7a3551e9a6e67eff8a72ddc4 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 13:17:41 +0200 Subject: [PATCH 26/42] Revert test-script change --- scripts/tests_and_coverage.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/tests_and_coverage.sh b/scripts/tests_and_coverage.sh index 4900304eb..749dec0f5 100755 --- a/scripts/tests_and_coverage.sh +++ b/scripts/tests_and_coverage.sh @@ -57,8 +57,7 @@ set +u if [ -z "${GITHUB_ACTIONS}" ] || [ "$1" == "test_and_coverage" ] ; then # Python tests (rerun with debug if failures) - # PYTHONPATH=$(pwd) pytest -qx tests/ --cov='.' --no-cov-on-fail --cov-report term-missing || - PYTHONPATH=$(pwd) pytest -xrpP --log-level debug tests/ + PYTHONPATH=$(pwd) pytest -qx tests/ --cov='.' --no-cov-on-fail --cov-report term-missing || PYTHONPATH=$(pwd) pytest -xrpP --log-level debug tests/ fi if [ -z "${GITHUB_ACTIONS}" ] || [ "$1" == "linting" ] ; then From 99ffc8b355ef2249b76b1111bbdf230b180790e2 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 13:20:25 +0200 Subject: [PATCH 27/42] Revert adding unregister_node() to api --- plugwise_usb/api.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/plugwise_usb/api.py b/plugwise_usb/api.py index 611a3e6bd..590d41a6c 100644 --- a/plugwise_usb/api.py +++ b/plugwise_usb/api.py @@ -495,23 +495,6 @@ async def get_state(self, features: tuple[NodeFeature]) -> dict[NodeFeature, Any # endregion # region Actions to execute - async def unregister_node(self, mac: str) -> None: - """Remove a node from the Plugwise network. - - Description: - Resets the mode before unregistering it from the Plugwise network. - - Args: - mac: MAC of the node to unregister. - - Returns: - None - - Raised: - NodeError: when the node isn't removed. - - """ - async def set_relay(self, state: bool) -> bool: """Change the state of the relay. From 0f0ac9f230b3fff3221dc85ceb1b634314fac438 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 13:21:59 +0200 Subject: [PATCH 28/42] Remove test-debug-messages --- plugwise_usb/network/__init__.py | 1 - tests/test_usb.py | 1 - 2 files changed, 2 deletions(-) diff --git a/plugwise_usb/network/__init__.py b/plugwise_usb/network/__init__.py index 21610b8b1..985cd7581 100644 --- a/plugwise_usb/network/__init__.py +++ b/plugwise_usb/network/__init__.py @@ -166,7 +166,6 @@ async def clear_cache(self) -> None: async def unregister_node(self, mac: str) -> None: """Unregister node from current Plugwise network.""" - _LOGGER.debug("HOI network-unregister_node with %s", mac) if not validate_mac(mac): raise NodeError(f"MAC {mac} invalid") diff --git a/tests/test_usb.py b/tests/test_usb.py index 4438918c4..fae43238c 100644 --- a/tests/test_usb.py +++ b/tests/test_usb.py @@ -721,7 +721,6 @@ async def test_node_discovery(self, monkeypatch: pytest.MonkeyPatch) -> None: assert len(stick.nodes) == 7 # Discovered nodes # Test unregistering of node - _LOGGER.debug("HOI unregister node") await stick.unregister_node("3333333333333333") assert stick.nodes.get("3333333333333333") is None assert len(stick.nodes) == 6 From e74a7cd37503967a2c939220cc7a4a8c5afb9560 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 13:39:32 +0200 Subject: [PATCH 29/42] Revert to original response.ack_id --- plugwise_usb/nodes/node.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/plugwise_usb/nodes/node.py b/plugwise_usb/nodes/node.py index 6bdd4586e..bf9002e5c 100644 --- a/plugwise_usb/nodes/node.py +++ b/plugwise_usb/nodes/node.py @@ -648,18 +648,11 @@ async def reset_node(self) -> None: self._send, self._mac_in_bytes, self.node_type.value, timeout ) response = await request.send() - if ( - response is None - or getattr(response, "response_type", None) - != NodeResponseType.NODE_RESET_ACK - ): - ack = getattr(response, "ack_id", None) - rtype = getattr(response, "response_type", None) + if response is None or response.ack_id != NodeResponseType.NODE_RESET_ACK: _LOGGER.warning( - "Node %s reset not acknowledged (ack_id=%s, response_type=%s)", + "Node %s reset not acknowledged (response=%s)", self._mac_in_str, - ack, - rtype, + getattr(response, "ack_id", None), ) async def unload(self) -> None: From 29f77011fe03929fa2a84889d3b59da3c861cb5b Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 13:41:08 +0200 Subject: [PATCH 30/42] Remove commented NODE_RESET_NACK --- plugwise_usb/messages/responses.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugwise_usb/messages/responses.py b/plugwise_usb/messages/responses.py index ec2ad40f4..74da5ead8 100644 --- a/plugwise_usb/messages/responses.py +++ b/plugwise_usb/messages/responses.py @@ -60,7 +60,6 @@ class NodeResponseType(bytes, Enum): CLOCK_ACCEPTED = b"00D7" JOIN_ACCEPTED = b"00D9" # ack for CirclePlusAllowJoiningRequest with state true NODE_RESET_ACK = b"00F2" - # NODE_RESET_NACK = b"????" POWER_LOG_INTERVAL_ACCEPTED = b"00F8" # ack for CircleMeasureIntervalRequest REAL_TIME_CLOCK_ACCEPTED = b"00DF" REAL_TIME_CLOCK_FAILED = b"00E7" From 403a9121d9d4a2234db5d9c488ab8ba03aa546ae Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 13:49:26 +0200 Subject: [PATCH 31/42] Implements CR suggestions --- plugwise_usb/messages/requests.py | 6 ++---- tests/stick_test_data.py | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/plugwise_usb/messages/requests.py b/plugwise_usb/messages/requests.py index 0d844697f..780a1ac07 100644 --- a/plugwise_usb/messages/requests.py +++ b/plugwise_usb/messages/requests.py @@ -496,10 +496,8 @@ def __init__( ) -> None: """Initialize NodeResetRequest message object.""" super().__init__(send_fn, mac) - self._args += [ - Int(moduletype, length=2), - Int(timeout, length=2), - ] + module_id = getattr(moduletype, "value", moduletype) + self._args += [Int(module_id, length=2), Int(timeout, length=2)] async def send(self) -> NodeResponse | None: """Send request.""" diff --git a/tests/stick_test_data.py b/tests/stick_test_data.py index 7e780ff3a..4d22e5c64 100644 --- a/tests/stick_test_data.py +++ b/tests/stick_test_data.py @@ -1345,12 +1345,12 @@ + b"00044020", ), b"\x05\x05\x03\x030009333333333333333302047290\r\n": ( - "Reset node request for 333333333333333333", + "Reset node request for 3333333333333333", b"000000C1", # Success ack b"0000" + b"00F2" + b"3333333333333333", # msg_id, reset_ack, mac ), b"\x05\x05\x03\x03001C009876543210123433333333333333331E2D\r\n": ( - "Remove node request for 333333333333333333", + "Remove node request for 3333333333333333", b"000000C1", # Success ack b"001D" # msg_id + b"0098765432101234" # Circle + mac From 04f1a4174b5bc672453159dd2b054dafeb60bbb9 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 13:53:06 +0200 Subject: [PATCH 32/42] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e714cd0f1..410838ab2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Ongoing - PR [342](https://github.com/plugwise/python-plugwise-usb/pull/342): Improve node_type chaching. +- Improve node removal: reset the node before removing and remove the cache-file too. ## 0.46.0 - 2025-09-12 From 824f60ac29042eacad5256e662e09707743a95f4 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 13:53:33 +0200 Subject: [PATCH 33/42] Bump to v0.46.1a0 for testing --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4661415b8..5358ff510 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise_usb" -version = "0.46.0" +version = "0.46.1a0" license = "MIT" keywords = ["home", "automation", "plugwise", "module", "usb"] classifiers = [ From 104521ad888c983b760edf2e41f3fb76c191ee01 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 14:24:48 +0200 Subject: [PATCH 34/42] Correct varname --- plugwise_usb/messages/requests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugwise_usb/messages/requests.py b/plugwise_usb/messages/requests.py index 780a1ac07..20690e3f6 100644 --- a/plugwise_usb/messages/requests.py +++ b/plugwise_usb/messages/requests.py @@ -861,11 +861,11 @@ def __init__( self, send_fn: Callable[[PlugwiseRequest, bool], Awaitable[PlugwiseResponse | None]], mac_circle_plus: bytes, - mac_to_unjoined: str, + mac_to_unjoin: str, ) -> None: """Initialize NodeRemoveRequest message object.""" super().__init__(send_fn, mac_circle_plus) - self._args.append(String(mac_to_unjoined, length=16)) + self._args.append(String(mac_to_unjoin, length=16)) async def send(self) -> NodeRemoveResponse | None: """Send request.""" From e851ff9cc8dfc33dc50892e0940e41c46d9b9418 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 16:44:49 +0200 Subject: [PATCH 35/42] First remove, then reset --- plugwise_usb/network/registry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugwise_usb/network/registry.py b/plugwise_usb/network/registry.py index 4628460d5..ca18a1cb3 100644 --- a/plugwise_usb/network/registry.py +++ b/plugwise_usb/network/registry.py @@ -271,8 +271,7 @@ async def unregister_node(self, node: PlugwiseNode) -> None: if node.mac not in self._registry: raise NodeError(f"No existing Node ({node.mac}) found to unregister") - # First reset the node, then remove it from the network. - await node.reset_node() + # First remove the node, when succesful then reset it. request = NodeRemoveRequest(self._send_to_controller, self._mac_nc, node.mac) if (response := await request.send()) is None: raise NodeError( @@ -285,6 +284,7 @@ async def unregister_node(self, node: PlugwiseNode) -> None: + f" failed to unregister node '{node.mac}'" ) + await node.reset_node() await self.remove_network_registration(node.mac) await node.clear_cache() From d71a3fe447f1c37a8eada11eacfe8f4262a60d6e Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 13 Sep 2025 16:47:46 +0200 Subject: [PATCH 36/42] Bump to a1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5358ff510..524d50398 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise_usb" -version = "0.46.1a0" +version = "0.46.1a1" license = "MIT" keywords = ["home", "automation", "plugwise", "module", "usb"] classifiers = [ From 4a95fe8a79872d4eadba1a4998a90964fe85d523 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 14 Sep 2025 09:35:26 +0200 Subject: [PATCH 37/42] Add debug-logger for node-clear_cache --- plugwise_usb/nodes/node.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugwise_usb/nodes/node.py b/plugwise_usb/nodes/node.py index bf9002e5c..0e98d8380 100644 --- a/plugwise_usb/nodes/node.py +++ b/plugwise_usb/nodes/node.py @@ -391,6 +391,7 @@ async def _load_cache_file(self) -> bool: async def clear_cache(self) -> None: """Clear current cache.""" if self._node_cache is not None: + _LOGGER.debug("Removing node % cache", self._mac_in_str) await self._node_cache.clear_cache() async def _load_from_cache(self) -> bool: From a9238b34e9d463cf1f1992ae73f75cf81059711a Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 14 Sep 2025 10:13:41 +0200 Subject: [PATCH 38/42] Revert NodeType back to --- plugwise_usb/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise_usb/api.py b/plugwise_usb/api.py index 590d41a6c..46ae63af0 100644 --- a/plugwise_usb/api.py +++ b/plugwise_usb/api.py @@ -59,7 +59,7 @@ class NodeFeature(str, Enum): TEMPERATURE = "temperature" -class NodeType(IntEnum): +class NodeType(Enum): """USB Node types.""" STICK = 0 From dec9242485d7d2c87b178119f0cfb13c90154c72 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 14 Sep 2025 16:07:23 +0200 Subject: [PATCH 39/42] Update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 410838ab2..71ca653bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ ## Ongoing +- Improve node removal: remove and reset the node as executed by Source, and remove the cache-file. - PR [342](https://github.com/plugwise/python-plugwise-usb/pull/342): Improve node_type chaching. -- Improve node removal: reset the node before removing and remove the cache-file too. ## 0.46.0 - 2025-09-12 From c9ffe52c2d36320702fecf21ce8c857c6ca0d8cf Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 15 Sep 2025 17:59:47 +0200 Subject: [PATCH 40/42] Update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71ca653bc..2bb006c29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Ongoing -- Improve node removal: remove and reset the node as executed by Source, and remove the cache-file. +- PR [337](https://github.com/plugwise/python-plugwise-usb/pull/337)Improve node removal: remove and reset the node as executed by Source, and remove the cache-file. - PR [342](https://github.com/plugwise/python-plugwise-usb/pull/342): Improve node_type chaching. ## 0.46.0 - 2025-09-12 From e55e1e8b75e1b7d73aeea21ac2164f78d73a1af7 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 16 Sep 2025 11:58:52 +0200 Subject: [PATCH 41/42] Improve CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bb006c29..73db66ed6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Ongoing -- PR [337](https://github.com/plugwise/python-plugwise-usb/pull/337)Improve node removal: remove and reset the node as executed by Source, and remove the cache-file. +- PR [337](https://github.com/plugwise/python-plugwise-usb/pull/337): Improve node removal, remove and reset the node as executed by Source, and remove the cache-file. - PR [342](https://github.com/plugwise/python-plugwise-usb/pull/342): Improve node_type chaching. ## 0.46.0 - 2025-09-12 From f06b67b80ade034062309ab41919e0fc348a0189 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 16 Sep 2025 12:00:48 +0200 Subject: [PATCH 42/42] Clean up --- plugwise_usb/messages/requests.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugwise_usb/messages/requests.py b/plugwise_usb/messages/requests.py index 20690e3f6..3184b875b 100644 --- a/plugwise_usb/messages/requests.py +++ b/plugwise_usb/messages/requests.py @@ -481,11 +481,10 @@ class NodeResetRequest(PlugwiseRequest): """TODO:Some kind of reset request. Supported protocols : 1.0, 2.0, 2.1 - Response message : NodeResponse with NODE_RESET_ACK/NACK + Response message : NodeResponse with NODE_RESET_ACK/NACK (@dirixmjm & @bouwew 20250910) """ _identifier = b"0009" - # _reply_identifier is b"0000'with NODE_RESET_ACK, not b"0003" @dirixmjm & @bouwew 20250910 def __init__( self,