Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
1f05641
Propagate NodeType to node on init
dirixmjm Jul 14, 2025
6a34d17
remove remaing node_info_default and double name definition
dirixmjm Jul 15, 2025
4a32628
Remove double load_defaults calls.
dirixmjm Jul 19, 2025
11a7187
Extend default values loading to Sense and Switch
dirixmjm Jul 19, 2025
7c53420
Let SED->load() return None
dirixmjm Jul 19, 2025
80db654
Fix return value
dirixmjm Jul 19, 2025
010a379
await _load_defaults
dirixmjm Jul 19, 2025
47589eb
Change load() to return None in all cases
dirixmjm Jul 19, 2025
3546bca
fix return value
dirixmjm Jul 19, 2025
ca903cd
chore(deps): update pre-commit hook biomejs/pre-commit to v2.1.1 (#283)
renovate[bot] Jul 10, 2025
9588bb2
chore(deps): update pre-commit hook astral-sh/ruff-pre-commit to v0.1…
renovate[bot] Jul 12, 2025
372500d
Migrate to Trusted Publishing (pypi)
CoMPaTech Jul 14, 2025
51951e6
Skip check for tool-merging as well
CoMPaTech Jul 14, 2025
a73f1c8
CRAI suggestions
CoMPaTech Jul 14, 2025
823fa26
Fully match version
CoMPaTech Jul 16, 2025
77c3784
chore(deps): update pre-commit hook astral-sh/ruff-pre-commit to v0.1…
renovate[bot] Jul 18, 2025
3fb6ef4
chore(deps): update pre-commit hook biomejs/pre-commit to v2.1.2 (#292)
renovate[bot] Jul 19, 2025
fccad5d
Revert Improve energy_log_update() output logic
bouwew Jul 20, 2025
6f9ce04
Retain the added functionality
bouwew Jul 20, 2025
afb0563
Update CHANGELOG
bouwew Jul 20, 2025
eaf5f26
Improve comment
bouwew Jul 20, 2025
c272b50
Use qsize() to obtain queue depth
bouwew Jul 18, 2025
b04d84a
Remove use of queue_depth
bouwew Jul 18, 2025
3ef8977
Remove all request/response counter related
bouwew Jul 18, 2025
e3bb5c2
Add comment about queue rate limiting
bouwew Jul 18, 2025
47f1196
Bump to v0.44.8a8 test-version
bouwew Jul 18, 2025
191ef77
Update CHANGELOG
bouwew Jul 18, 2025
9d610e8
Define constant REPORT_QUEUE_FILLING_UP and set it to 8
bouwew Jul 20, 2025
abb9212
fixup: alt_prio_queue Python code reformatted using Ruff
Jul 20, 2025
52aa9b3
Import added constant from constants.py
bouwew Jul 20, 2025
000ff94
Update CHANGELOG
bouwew Jul 21, 2025
49b9c1d
Set to v0.44.8 release-version
bouwew Jul 21, 2025
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
7 changes: 3 additions & 4 deletions plugwise_usb/network/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,10 +481,9 @@ async def _load_node(self, mac: str) -> bool:
return False
if self._nodes[mac].is_loaded:
return True
if await self._nodes[mac].load():
await self._notify_node_event_subscribers(NodeEvent.LOADED, mac)
return True
return False
await self._nodes[mac].load()
await self._notify_node_event_subscribers(NodeEvent.LOADED, mac)
return True

async def _load_stragglers(self) -> None:
"""Retry failed load operation."""
Expand Down
6 changes: 6 additions & 0 deletions plugwise_usb/nodes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,41 +26,47 @@ def get_plugwise_node( # noqa: PLR0911
return PlugwiseCirclePlus(
mac,
address,
node_type,
controller,
loaded_callback,
)
if node_type == NodeType.CIRCLE:
return PlugwiseCircle(
mac,
address,
node_type,
controller,
loaded_callback,
)
if node_type == NodeType.SWITCH:
return PlugwiseSwitch(
mac,
address,
node_type,
controller,
loaded_callback,
)
if node_type == NodeType.SENSE:
return PlugwiseSense(
mac,
address,
node_type,
controller,
loaded_callback,
)
if node_type == NodeType.SCAN:
return PlugwiseScan(
mac,
address,
node_type,
controller,
loaded_callback,
)
if node_type == NodeType.STEALTH:
return PlugwiseStealth(
mac,
address,
node_type,
controller,
loaded_callback,
)
Expand Down
62 changes: 35 additions & 27 deletions plugwise_usb/nodes/circle.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
from datetime import UTC, datetime
from functools import wraps
import logging
from typing import Any, TypeVar, cast
from typing import Any, Final, TypeVar, cast

from ..api import (
EnergyStatistics,
NodeEvent,
NodeFeature,
NodeInfo,
NodeInfoMessage,
NodeType,
PowerStatistics,
RelayConfig,
RelayLock,
Expand Down Expand Up @@ -58,6 +59,19 @@
CACHE_RELAY_INIT = "relay_init"
CACHE_RELAY_LOCK = "relay_lock"

CIRCLE_FEATURES: Final = (
NodeFeature.CIRCLE,
NodeFeature.RELAY,
NodeFeature.RELAY_INIT,
NodeFeature.RELAY_LOCK,
NodeFeature.ENERGY,
NodeFeature.POWER,
)


# Default firmware if not known
DEFAULT_FIRMWARE: Final = datetime(2008, 8, 26, 15, 46, tzinfo=UTC)

FuncT = TypeVar("FuncT", bound=Callable[..., Any])
_LOGGER = logging.getLogger(__name__)

Expand All @@ -81,11 +95,12 @@ def __init__(
self,
mac: str,
address: int,
node_type: NodeType,
controller: StickController,
loaded_callback: Callable[[NodeEvent, str], Awaitable[None]],
):
"""Initialize base class for Sleeping End Device."""
super().__init__(mac, address, controller, loaded_callback)
super().__init__(mac, address, node_type, controller, loaded_callback)

# Relay
self._relay_lock: RelayLock = RelayLock()
Expand Down Expand Up @@ -875,10 +890,10 @@ async def clock_synchronize(self) -> bool:
return True
return False

async def load(self) -> bool:
async def load(self) -> None:
"""Load and activate Circle node features."""
if self._loaded:
return True
return

if self._cache_enabled:
_LOGGER.debug("Loading Circle node %s from cache", self._mac_in_str)
Expand All @@ -888,34 +903,18 @@ async def load(self) -> bool:
_LOGGER.debug("Retrieving Info For Circle node %s", self._mac_in_str)

# Check if node is online
if not self._available and not await self.is_online():
_LOGGER.debug(
"Failed to load Circle node %s because it is not online",
self._mac_in_str,
)
return False

# Get node info
if await self.node_info_update() is None:
if (
not self._available and not await self.is_online()
) or await self.node_info_update() is None:
_LOGGER.debug(
"Failed to load Circle node %s because it is not responding to information request",
"Failed to retrieve NodeInfo for %s, loading defaults",
self._mac_in_str,
)
return False
await self._load_defaults()

self._loaded = True
self._loaded = True

self._setup_protocol(
CIRCLE_FIRMWARE_SUPPORT,
(
NodeFeature.CIRCLE,
NodeFeature.RELAY,
NodeFeature.RELAY_INIT,
NodeFeature.RELAY_LOCK,
NodeFeature.ENERGY,
NodeFeature.POWER,
),
)
self._setup_protocol(CIRCLE_FIRMWARE_SUPPORT, CIRCLE_FEATURES)
await self._loaded_callback(NodeEvent.LOADED, self.mac)
await self.initialize()
return True
Expand Down Expand Up @@ -965,6 +964,15 @@ async def _load_from_cache(self) -> bool:

return result

async def _load_defaults(self) -> None:
"""Load default configuration settings."""
if self._node_info.model is None:
self._node_info.model = "Circle"
if self._node_info.name is None:
self._node_info.name = f"Circle {self._node_info.mac[-5:]}"
if self._node_info.firmware is None:
self._node_info.firmware = DEFAULT_FIRMWARE

@raise_not_loaded
async def initialize(self) -> bool:
"""Initialize node."""
Expand Down
18 changes: 8 additions & 10 deletions plugwise_usb/nodes/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
)

CACHE_FIRMWARE = "firmware"
CACHE_NODE_TYPE = "node_type"
CACHE_HARDWARE = "hardware"
CACHE_NODE_INFO_TIMESTAMP = "node_info_timestamp"
CACHE_RELAY = "relay"
Expand All @@ -61,16 +60,22 @@ def __init__(
self,
mac: str,
address: int,
node_type: NodeType,
controller: StickController,
loaded_callback: Callable[[NodeEvent, str], Awaitable[None]],
):
"""Initialize Plugwise base node class."""
super().__init__()
self.node_type = node_type
self._loaded_callback = loaded_callback
self._message_subscribe = controller.subscribe_to_messages
self._features: tuple[NodeFeature, ...] = NODE_FEATURES
self._last_seen = datetime.now(tz=UTC)
self._node_info = NodeInfo(mac, address)
self._node_info = NodeInfo(
mac=mac,
zigbee_address=address,
node_type=self.node_type,
)
self._ping = NetworkStatistics()
self._mac_in_bytes = bytes(mac, encoding=UTF8)
self._mac_in_str = mac
Expand Down Expand Up @@ -462,7 +467,6 @@ async def node_info_update(
_LOGGER.debug("No response for node_info_update() for %s", self.mac)
await self._available_update_state(False)
return self._node_info

await self._available_update_state(True, node_info.timestamp)
await self.update_node_details(node_info)
return self._node_info
Expand All @@ -475,16 +479,13 @@ async def _node_info_load_from_cache(self) -> bool:

firmware = self._get_cache_as_datetime(CACHE_FIRMWARE)
hardware = self._get_cache(CACHE_HARDWARE)
node_type: NodeType | None = None
if (node_type_str := self._get_cache(CACHE_NODE_TYPE)) is not None:
node_type = NodeType(int(node_type_str))
relay_state = self._get_cache(CACHE_RELAY) == "True"
timestamp = self._get_cache_as_datetime(CACHE_NODE_INFO_TIMESTAMP)
node_info = NodeInfoMessage(
current_logaddress_pointer=None,
firmware=firmware,
hardware=hardware,
node_type=node_type,
node_type=self.node_type,
relay_state=relay_state,
timestamp=timestamp,
)
Expand All @@ -509,9 +510,6 @@ async def update_node_details(
complete = True
if node_info.node_type is None:
complete = False
else:
self._node_info.node_type = NodeType(node_info.node_type)
self._set_cache(CACHE_NODE_TYPE, self._node_info.node_type.value)

if node_info.firmware is None:
complete = False
Expand Down
Loading
Loading