Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Ongoing

- PR [319](https://github.com/plugwise/python-plugwise-usb/pull/319): Replace unclear warning message when a node is not online, also various small improvements suggested by CRAI.

## v0.44.11 - 2025-08-14

- Improve reading from energy-logs cache via PR [314](https://github.com/plugwise/python-plugwise-usb/pull/314)
Expand Down
20 changes: 12 additions & 8 deletions plugwise_usb/connection/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,14 @@ async def submit(self, request: PlugwiseRequest) -> PlugwiseResponse | None:
f"Cannot send message {request} which is currently waiting for response."
)

while request.resend:
while True:
if not request.resend:
break
_LOGGER.debug("submit | start (%s) %s", request.retries_left, request)
if not self._running or self._stick is None:
raise StickError(
f"Cannot send message {request.__class__.__name__} for"
+ f"{request.mac_decoded} because queue manager is stopped"
f"Cannot send message {request.__class__.__name__} for "
f"{request.mac_decoded} because queue manager is stopped"
)

await self._add_request_to_queue(request)
Expand All @@ -107,20 +109,22 @@ async def submit(self, request: PlugwiseRequest) -> PlugwiseResponse | None:
"%s, cancel because timeout is expected for NodePingRequests",
exc,
)
elif request.resend:
continue
if request.resend:
_LOGGER.debug("%s, retrying", exc)
else:
_LOGGER.warning("%s, cancel request", exc) # type: ignore[unreachable]
continue
_LOGGER.debug("%s, cancel request", exc)
break
except StickError as exc:
_LOGGER.error(exc)
raise StickError(
f"No response received for {request.__class__.__name__} "
+ f"to {request.mac_decoded}"
f"to {request.mac_decoded}"
) from exc
except BaseException as exc:
raise StickError(
f"No response received for {request.__class__.__name__} "
+ f"to {request.mac_decoded}"
f"to {request.mac_decoded}"
) from exc

return None
Expand Down
1 change: 0 additions & 1 deletion plugwise_usb/connection/sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ async def write_request_to_port(self, request: PlugwiseRequest) -> None:
async def _process_stick_response(self, response: StickResponse) -> None:
"""Process stick response."""
if self._stick_response is None or self._stick_response.done():
_LOGGER.warning("No open request for %s", str(response))
return
_LOGGER.debug("Received %s as reply to %s", response, self._current_request)
self._stick_response.set_result(response)
Expand Down
33 changes: 12 additions & 21 deletions plugwise_usb/messages/requests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""All known request messages to be send to plugwise devices."""
"""All known request messages to be sent to plugwise devices."""

from __future__ import annotations

Expand Down Expand Up @@ -58,7 +58,7 @@


class PlugwiseRequest(PlugwiseMessage):
"""Base class for request messages to be send from by USB-Stick."""
"""Base class for request messages to be sent from by USB-Stick."""

_reply_identifier: bytes = b"0000"

Expand Down Expand Up @@ -215,7 +215,7 @@ def _response_timeout_expired(self, stick_timeout: bool = False) -> None:
if self._response_future.done():
return
if stick_timeout:
_LOGGER.info("USB-stick responded with time out to %s", self)
_LOGGER.info("USB-stick response timeout for %s", self)
else:
_LOGGER.info(
"No response received for %s within %s seconds", self, NODE_TIME_OUT
Expand All @@ -225,12 +225,12 @@ def _response_timeout_expired(self, stick_timeout: bool = False) -> None:
self._unsubscribe_from_node()
if stick_timeout:
self._response_future.set_exception(
StickTimeout(f"USB-stick responded with time out to {self}")
StickTimeout(f"USB-stick response timeout for {self}")
)
else:
self._response_future.set_exception(
NodeTimeout(
f"No device response to {self} within {NODE_TIME_OUT} seconds"
f"No device response for {self} within {NODE_TIME_OUT} seconds"
)
)

Expand All @@ -249,16 +249,17 @@ async def process_node_response(self, response: PlugwiseResponse) -> bool:
if self._seq_id is None:
_LOGGER.warning(
"Received %s as reply to %s without a seq_id assigned",
self._response,
response,
self,
)
return False
if self._seq_id != response.seq_id:
_LOGGER.warning(
"Received %s as reply to %s which is not correct (expected seq_id=%s)",
self._response,
"Received %s as reply to %s with mismatched seq_id (expected=%r, got=%r)",
response,
self,
str(self.seq_id),
self.seq_id,
response.seq_id,
)
return False
if self._response_future.done():
Expand Down Expand Up @@ -297,19 +298,9 @@ async def _process_stick_response(self, stick_response: StickResponse) -> None:
return

if stick_response.ack_id == StickResponseType.FAILED:
self._unsubscribe_from_node()
prev_seq_id = self._seq_id
self._seq_id = None
self._response_future.set_exception(
NodeError(f"Stick failed request {self._seq_id}")
)
return

_LOGGER.debug(
"Unknown StickResponseType %s at %s for request %s",
str(stick_response.ack_id),
stick_response,
self,
)
self.assign_error(NodeError(f"Stick failed request {prev_seq_id!r}"))

async def _send_request(
self, suppress_node_errors=False
Expand Down
17 changes: 12 additions & 5 deletions plugwise_usb/network/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,12 @@ def _unsubscribe_to_protocol_events(self) -> None:
if self._unsubscribe_node_awake is not None:
self._unsubscribe_node_awake()
self._unsubscribe_node_awake = None
if self._unsubscribe_node_join is not None:
self._unsubscribe_node_join()
self._unsubscribe_node_join = None
if self._unsubscribe_node_rejoin is not None:
self._unsubscribe_node_rejoin()
self._unsubscribe_node_rejoin = None
if self._unsubscribe_stick_event is not None:
self._unsubscribe_stick_event()
self._unsubscribe_stick_event = None
Expand All @@ -322,10 +328,9 @@ async def discover_network_coordinator(self, load: bool = False) -> bool:
ping_response = await ping_request.send()
except StickTimeout as err:
raise StickError(
"The zigbee network coordinator (Circle+/Stealth+) with mac "
+ "'%s' did not respond to ping request. Make "
+ "sure the Circle+/Stealth+ is within reach of the USB-stick !",
self._controller.mac_coordinator,
f"The zigbee network coordinator (Circle+/Stealth+) with mac "
f"'{self._controller.mac_coordinator}' did not respond to the ping request. "
"Make sure the Circle+/Stealth+ is within reach of the USB-stick!"
) from err
if ping_response is None:
return False
Expand Down Expand Up @@ -418,7 +423,9 @@ async def _discover_node(
_LOGGER.debug("Starting the discovery of node %s with unknown NodeType", mac)
node_info, node_ping = await self._controller.get_node_details(mac, ping_first)
if node_info is None:
_LOGGER.debug("Node %s with unknown NodeType not responding", mac)
_LOGGER.warning(
"Node %s with unknown NodeType not responding, is it offline?", mac
)
self._registry_stragglers.append(mac)
return False
await self._create_node_object(mac, node_info.node_type)
Expand Down
2 changes: 1 addition & 1 deletion plugwise_usb/nodes/circle.py
Original file line number Diff line number Diff line change
Expand Up @@ -973,7 +973,7 @@ async def _load_from_cache(self) -> bool:

# Energy collection
if not await self._energy_log_records_load_from_cache():
_LOGGER.warning(
_LOGGER.debug(
"Node %s failed to load energy_log_records from cache",
self._mac_in_str,
)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "plugwise_usb"
version = "0.44.11"
version = "0.44.12a1"
license = "MIT"
keywords = ["home", "automation", "plugwise", "module", "usb"]
classifiers = [
Expand Down