Skip to content

Conversation

@dirixmjm
Copy link
Contributor

@dirixmjm dirixmjm commented Jun 12, 2025

Add NodeFeature.CIRCLEPLUS
Add enable_auto_join function which exposes CirclePlusAllowJoingingRequest

Summary by CodeRabbit

  • New Features
    • Added support for the "Circle Plus" feature with auto join enablement for compatible devices.
  • Enhancements
    • Updated device feature compatibility to include Circle Plus on firmware version 2.0 or higher.
  • Bug Fixes
    • Removed deprecated join request acceptance controls from network and stick interfaces to simplify device joining.

@dirixmjm dirixmjm requested a review from a team as a code owner June 12, 2025 13:08
@coderabbitai
Copy link

coderabbitai bot commented Jun 12, 2025

Walkthrough

The changes introduce support for a new "circleplus" feature in the Plugwise USB integration. This includes updating feature enumerations, adding feature-to-firmware mapping, and implementing an asynchronous method to enable auto-join functionality for Circle Plus nodes. Additionally, join request handling was removed from the Stick and StickNetwork classes, and related tests were adjusted.

Changes

File(s) Change Summary
plugwise_usb/api.py Added CIRCLEPLUS to NodeFeature enum and included it in the PUSHING_FEATURES tuple.
plugwise_usb/nodes/circle_plus.py Added support for NodeFeature.CIRCLEPLUS; introduced enable_auto_join async method.
plugwise_usb/nodes/helpers/firmware.py Mapped NodeFeature.CIRCLEPLUS to firmware version 2.0 in the feature support dictionary.
plugwise_usb/init.py Removed accept_join_request property and set_accept_join_request async method from Stick.
plugwise_usb/network/init.py Removed accept_join_request attribute and allow_join_requests async method from StickNetwork class; removed join acceptance checks.
tests/test_usb.py Removed assertions and tests related to accept_join_request; updated expected features to include NodeFeature.CIRCLEPLUS.
CHANGELOG.md Added changelog entry for version 0.44.3 documenting the new CirclePlus "Allow Joining Request".
pyproject.toml Bumped project version from 0.44.2 to 0.44.3.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant PlugwiseCirclePlus
    participant CirclePlusAllowJoiningRequest

    User->>PlugwiseCirclePlus: enable_auto_join()
    PlugwiseCirclePlus->>PlugwiseCirclePlus: Check if node is loaded
    PlugwiseCirclePlus->>CirclePlusAllowJoiningRequest: Create request (allow_joining=True)
    PlugwiseCirclePlus->>PlugwiseCirclePlus: Send request asynchronously
    PlugwiseCirclePlus-->>User: Return result (bool)
Loading

Suggested reviewers

  • dirixmjm
  • brefra
  • ArnoutD

Poem

In the warren of code, a new feature appears,
Circleplus hops in, met with bunny cheers!
Auto-join enabled, with firmware in tow,
Now Circle Plus nodes have a new trick to show.
With each little update, our network grows bright—
Hopping ahead, everything's working just right!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a767c06 and cbf217b.

📒 Files selected for processing (1)
  • CHANGELOG.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Check commit
✨ Finishing Touches
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Commit Unit Tests in branch cpaj
  • Post Copyable Unit Tests in Comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@codecov
Copy link

codecov bot commented Jun 12, 2025

Codecov Report

Attention: Patch coverage is 44.44444% with 5 lines in your changes missing coverage. Please review.

Project coverage is 81.13%. Comparing base (b29517b) to head (cbf217b).
Report is 15 commits behind head on main.

Files with missing lines Patch % Lines
plugwise_usb/nodes/circle_plus.py 37.50% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #260      +/-   ##
==========================================
- Coverage   81.22%   81.13%   -0.09%     
==========================================
  Files          36       36              
  Lines        7537     7502      -35     
==========================================
- Hits         6122     6087      -35     
  Misses       1415     1415              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
plugwise_usb/api.py (1)

57-58: Enum entry looks fine, but consider keeping alphabetical order

CIRCLEPLUS is correctly added and follows the existing lowercase-string convention.
For long-term readability, you may want to keep the enum list alphabetically sorted – a convention already adopted in several other enums in this file.

plugwise_usb/nodes/circle_plus.py (1)

13-14: Imports OK – minor style nit

Imports follow the local relative-package style, but ordering is now interleaved between stdlib / third-party / local sections. Consider grouping the two local-package imports (CirclePlusAllowJoiningRequest, raise_not_loaded) together for clarity.

Also applies to: 18-19

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b29517b and 1e1f7d6.

📒 Files selected for processing (3)
  • plugwise_usb/api.py (2 hunks)
  • plugwise_usb/nodes/circle_plus.py (3 hunks)
  • plugwise_usb/nodes/helpers/firmware.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
plugwise_usb/nodes/helpers/firmware.py (1)
plugwise_usb/api.py (1)
  • NodeFeature (39-57)
🪛 GitHub Check: codecov/patch
plugwise_usb/nodes/circle_plus.py

[warning] 130-132: plugwise_usb/nodes/circle_plus.py#L130-L132
Added lines #L130 - L132 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Check commit
🔇 Additional comments (2)
plugwise_usb/api.py (1)

78-88: Addition to PUSHING_FEATURES OK

NodeFeature.CIRCLEPLUS is correctly appended to the push-capable features.

plugwise_usb/nodes/helpers/firmware.py (1)

156-172: Firmware mapping updated correctly

NodeFeature.CIRCLEPLUS is mapped to 2.0, in line with the other first-generation features.

coderabbitai recommendations
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
plugwise_usb/nodes/circle_plus.py (2)

128-134: Docstring violates PEP 257 / Ruff D413

Add a blank line after the “Returns:” header.

-        Returns:
-           bool: True if the request was acknowledged, False otherwise.
+        Returns:
+
+            bool: True if the request was acknowledged, False otherwise.
🧰 Tools
🪛 Ruff (0.11.9)

132-132: Missing blank line after last section ("Returns")

Add blank line after "Returns"

(D413)


135-135: Log message lacks node context

Stick to the existing pattern and include the MAC address for easier debugging.

-        _LOGGER.info("Enabling auto-join for CirclePlus")
+        _LOGGER.info("Enabling auto-join for CirclePlus %s", self.mac)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e1f7d6 and c5e516d.

📒 Files selected for processing (2)
  • plugwise_usb/api.py (2 hunks)
  • plugwise_usb/nodes/circle_plus.py (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugwise_usb/api.py
🧰 Additional context used
🪛 Ruff (0.11.9)
plugwise_usb/nodes/circle_plus.py

132-132: Missing blank line after last section ("Returns")

Add blank line after "Returns"

(D413)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Check commit
🔇 Additional comments (3)
plugwise_usb/nodes/circle_plus.py (3)

34-42: Feature-set parity fixed – looks good

NodeFeature.CIRCLEPLUS is now present in both cache-restore and fresh-load paths, removing the earlier discrepancy.

Also applies to: 71-79


136-138:

Details

✅ Verification successful

Confirm CirclePlusAllowJoiningRequest constructor

Most request classes take (send_fn, mac_in_bytes, enable); only passing True may produce an invalid frame. Please verify.


🏁 Script executed:

#!/bin/bash
# Inspect the constructor signature
ast-grep --pattern $'class CirclePlusAllowJoiningRequest {
  $$$
  def __init__($$$) {
    $$$
  }
  $$$
}'

Length of output: 108


I’ll locate and inspect the actual constructor signature for CirclePlusAllowJoiningRequest.


🏁 Script executed:

#!/bin/bash
# Find where the class is defined
rg -n "class CirclePlusAllowJoiningRequest" -n .

# Show its __init__ signature
rg -n "def __init__" "$(rg -l "CirclePlusAllowJoiningRequest")"

Length of output: 606


I’ll inspect the CirclePlusAllowJoiningRequest class and its base PlugwiseRequest to confirm the required constructor parameters.


🏁 Script executed:

#!/bin/bash
# Show CirclePlusAllowJoiningRequest definition and its __init__ (if any)
rg -n -A10 "class CirclePlusAllowJoiningRequest" plugwise_usb/messages/requests.py

# Show base class PlugwiseRequest signature for inherited __init__
rg -n -A20 "class PlugwiseRequest" plugwise_usb/messages/requests.py

Length of output: 1288


I’ll inspect how requests are instantiated in circle_plus.py around this call to confirm the intended parameters.


🏁 Script executed:

#!/bin/bash
# Show context around the allow-joining call
rg -n -C5 "CirclePlusAllowJoiningRequest" plugwise_usb/nodes/circle_plus.py

# List other request instantiations for comparison
rg -n -C3 "CirclePlus.*Request" plugwise_usb/nodes/circle_plus.py

Length of output: 2322


I’ll retrieve the full CirclePlusAllowJoiningRequest implementation to confirm its constructor:


🏁 Script executed:

#!/bin/bash
# Show the full class including any __init__ override
rg -n -A30 "class CirclePlusAllowJoiningRequest" plugwise_usb/messages/requests.py

Length of output: 1246


No changes required for CirclePlusAllowJoiningRequest constructor
The constructor is defined as __init__(self, send_fn, enable) and calls super().__init__(send_fn, None), so passing only self._send and True is correct.


141-142:

Details

❌ Incorrect review comment

Potential enum mismatch & unnecessary cast

  1. Ensure the ACK constant really is JOIN_ACCEPTED—older code uses ALLOW_JOINING_ACCEPTED.
  2. If response.ack_id is already a NodeResponseType, the explicit cast is redundant and may raise ValueError when the id is unknown.
-        return NodeResponseType(response.ack_id) == NodeResponseType.JOIN_ACCEPTED
+        return response.ack_id == NodeResponseType.ALLOW_JOINING_ACCEPTED

Adjust the constant name to the actual one defined in NodeResponseType.


🏁 Script executed:

#!/bin/bash
set -e

echo "1. Locating NodeResponseType definition..."
rg --max-count 1 "class NodeResponseType" -n .

echo
echo "2. Searching for ALLOW_JOINING_ACCEPTED references..."
rg "ALLOW_JOINING_ACCEPTED" -n .

echo
echo "3. Searching for JOIN_ACCEPTED references..."
rg "JOIN_ACCEPTED" -n .

Length of output: 387


🏁 Script executed:

#!/bin/bash
set -e

echo "Displaying NodeResponseType enum members (lines 50–120):"
sed -n '50,120p' plugwise_usb/messages/responses.py

Length of output: 2564


🏁 Script executed:

#!/bin/bash
set -e

echo "1. Searching for ack_id property or usage..."
rg "ack_id" -n plugwise_usb/messages/responses.py

echo
echo "2. Displaying context around NodeResponse class..."
start_line=$(grep -n "class NodeResponse" -n plugwise_usb/messages/responses.py | cut -d: -f1)
sed -n "$((start_line - 5)),$((start_line + 30))p" plugwise_usb/messages/responses.py

Length of output: 1143


No change needed for JOIN_ACCEPTED & enum cast

  • NodeResponseType defines JOIN_ACCEPTED (b"00D9")—there is no ALLOW_JOINING_ACCEPTED constant.
  • response.ack_id is a raw bytes value; wrapping it in NodeResponseType(...) is required to map it to the enum before comparison.

The existing code is correct as-is.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
tests/test_usb.py (1)

297-300: Avoid asyncio.sleep() for timestamp separation to keep the test deterministic

Using await asyncio.sleep(0.001) to ensure different timestamps works most of the time but relies on wall-clock granularity and the event-loop scheduler.
A busy CI runner may occasionally schedule both coroutine wake-ups within the same millisecond, making the ordering assertions flaky.

A safer pattern is to bypass the real clock completely and stub the timestamp that the PlugwiseRequest uses for ordering (e.g. via freezegun, a parametrised now= argument, or monkey-patching the attribute after construction).

-await asyncio.sleep(0.001)  # Ensure timestamp is different
-circle_plus_allow_joining_request = pw_requests.CirclePlusAllowJoiningRequest(
-    self.dummy_fn, True
-)
+# Force a monotonic timestamp delta instead of relying on sleep
+with freeze_time(dt.utcnow() + td(milliseconds=2)):
+    circle_plus_allow_joining_request = pw_requests.CirclePlusAllowJoiningRequest(
+        self.dummy_fn, True
+    )

This keeps the tests both fast and fully deterministic.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 375cf00 and bee0bad.

📒 Files selected for processing (1)
  • tests/test_usb.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/test_usb.py (1)
plugwise_usb/api.py (1)
  • NodeFeature (39-57)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Check commit
  • GitHub Check: Check commit
🔇 Additional comments (1)
tests/test_usb.py (1)

2498-2503: Feature list update looks correct

NodeFeature.CIRCLEPLUS is now included in the expected feature set for the Circle + node, matching the library change. No further issues spotted here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
CHANGELOG.md (1)

5-6: Fix Markdown link syntax and naming consistency
There’s an extra space before the parentheses in the PR link (resulting in a bare URL), and “circle plus interface” should match the CirclePlus casing.

- - PR [#260] (https://github.com/plugwise/python-plugwise-usb/pull/260)
+ - PR [#260](https://github.com/plugwise/python-plugwise-usb/pull/260)
-   - CirclePlus: Expose Allow Joining Request to circle plus interface
+   - CirclePlus: Expose Allow Joining Request to CirclePlus interface
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Bare URL used
null

(MD034, no-bare-urls)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bee0bad and b6fd41f.

📒 Files selected for processing (2)
  • CHANGELOG.md (1 hunks)
  • pyproject.toml (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • pyproject.toml
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
CHANGELOG.md

5-5: Bare URL used
null

(MD034, no-bare-urls)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Check commit
  • GitHub Check: Check commit
🔇 Additional comments (1)
CHANGELOG.md (1)

3-4: New version entry looks good
The header ## v0.44.3 - 2025-06-12 follows the established format and is correctly positioned above v0.44.2.

@sonarqubecloud
Copy link

Copy link
Contributor

@bouwew bouwew left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

W.r.t. the changes by @dirixmjm : LGTM!

@dirixmjm dirixmjm merged commit d53077d into main Jun 13, 2025
27 of 29 checks passed
@dirixmjm dirixmjm deleted the cpaj branch June 13, 2025 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants