Skip to content

Implement config_flow reconfigure#407

Merged
bouwew merged 36 commits intomainfrom
reconfigure
Mar 1, 2026
Merged

Implement config_flow reconfigure#407
bouwew merged 36 commits intomainfrom
reconfigure

Conversation

@bouwew
Copy link
Contributor

@bouwew bouwew commented Feb 26, 2026

Summary by CodeRabbit

  • New Features

    • Add ability to reconfigure the USB stick device path via the configuration flow and UI messages.
  • Bug Fixes

    • Safer cleanup on unload to avoid errors when runtime data is missing.
  • Localization

    • Added reconfigure prompts and abort messages; updated MAC address descriptions.
  • Tests

    • Expanded and added tests covering reconfiguration flows and related fixtures.
  • Chore

    • Bumped integration version to v0.59.0 and updated changelog.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

Warning

Rate limit exceeded

@bouwew has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 10 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 7a25f5a and c433f44.

📒 Files selected for processing (1)
  • custom_components/plugwise_usb/config_flow.py

Walkthrough

Adds USB stick path reconfiguration (config flow step), hardens unload/teardown to guard runtime_data, updates UI strings/translations, bumps package version to 0.59.0, and expands tests to cover reconfigure scenarios.

Changes

Cohort / File(s) Summary
Release & Metadata
CHANGELOG.md, custom_components/plugwise_usb/manifest.json, pyproject.toml
Bumped version to v0.59.0 and added changelog entry.
Config Flow: reconfiguration
custom_components/plugwise_usb/config_flow.py
Added STICK_RECONF_SCHEMA and async_step_reconfigure; validate_usb_connection can return mac_stick=None; use raise_on_progress=False for unique_id updates and handle aborts/duplicates.
Unload / runtime safety
custom_components/plugwise_usb/__init__.py
Safer unload: derive runtime_data via getattr(..., {}), guard unsubscribe/disconnect calls, unsubscribe node feature coordinators, and return async_unload_platforms result directly.
Localization & UI strings
custom_components/plugwise_usb/strings.json, custom_components/plugwise_usb/translations/en.json, custom_components/plugwise_usb/translations/nl.json
Added reconfigure UI strings and abort messages (not_the_same_stick, reconfigure_successful); removed trailing periods from MAC descriptions.
Tests: fixtures & flows
tests/conftest.py, tests/test_config_flow.py
Introduced TEST_USB_PATH, mock_usb_stick_not_setup fixture, updated mock_config_entry and setup_integration return; added extensive reconfigure flow tests (success, same-path, other-stick, error mapping).

Sequence Diagram

sequenceDiagram
    participant User as User
    participant Flow as ConfigFlow
    participant Stick as USBStick
    participant HA as HomeAssistant

    User->>Flow: start reconfigure (usb_path)
    Flow->>Flow: normalize/resolve device path
    Flow->>Stick: validate connection (device path)
    Stick-->>Flow: return mac_stick (or None) / errors
    Flow->>Flow: compare mac_stick with config_entry.unique_id
    alt same stick & valid
        Flow->>HA: update config entry data (usb_path) and reload
        HA-->>Flow: reload complete
        Flow-->>User: abort with reconfigure_successful
    else different stick
        Flow-->>User: abort with not_the_same_stick
    else validation error
        Flow-->>User: show cannot_connect / appropriate error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • ArnoutD
  • dirixmjm
  • CoMPaTech

Poem

🐰 A little stick changed where it lays,
I hopped and checked its winding ways.
Reconfigure, tidy, safe unwind,
Tests assure no bugs to find. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Implement config_flow reconfigure' accurately describes the main objective of the PR, which adds a new reconfiguration flow to the config_flow module.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch reconfigure

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@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 (1)
custom_components/plugwise_usb/config_flow.py (1)

158-158: Remove or return the abort call in the reconfigure error path.

self.async_abort(...) is called but not returned, so it has no effect. The reason string is also inconsistent with existing keys (already_configured).

🧹 Proposed cleanup
-            self.async_abort(reason="already configured")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@custom_components/plugwise_usb/config_flow.py` at line 158, The call to
self.async_abort(reason="already configured") in the reconfigure error path is
ineffective and uses an inconsistent reason key; replace it with a returned
abort using the existing key by changing it to return
self.async_abort(reason="already_configured") (locate the call in the
reconfigure flow, e.g., inside async_step_reconfigure or the reconfigure error
handling block where self.async_abort is invoked).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@custom_components/plugwise_usb/__init__.py`:
- Around line 165-170: The unload cleanup assumes all runtime_data keys exist;
change the logic in async_unload_entry to use config_entry.runtime_data.get(...)
with safe defaults and guard callables: call unsubscribe function only if
config_entry.runtime_data.get(UNSUBSCRIBE_DISCOVERY) is not None and callable,
iterate config_entry.runtime_data.get(NODES, {}) to await each
coordinator.unsubscribe_all_nodefeatures() only if present, and call await on
config_entry.runtime_data.get(STICK).disconnect() only if STICK is present and
connected; this prevents KeyError when entries were partially initialized.

In `@custom_components/plugwise_usb/config_flow.py`:
- Around line 122-127: async_step_manual_path sets the unique ID via
async_set_unique_id but doesn't call _abort_if_unique_id_configured before
creating the entry, allowing duplicate sticks via different path aliases; update
async_step_manual_path to call await self._abort_if_unique_id_configured() (same
as async_step_user) immediately after async_set_unique_id and before returning
self.async_create_entry, so duplicate MACs are rejected regardless of
device_path (keep validate_usb_connection as-is).

---

Nitpick comments:
In `@custom_components/plugwise_usb/config_flow.py`:
- Line 158: The call to self.async_abort(reason="already configured") in the
reconfigure error path is ineffective and uses an inconsistent reason key;
replace it with a returned abort using the existing key by changing it to return
self.async_abort(reason="already_configured") (locate the call in the
reconfigure flow, e.g., inside async_step_reconfigure or the reconfigure error
handling block where self.async_abort is invoked).

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e7b1eb and d3b8fc7.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • custom_components/plugwise_usb/__init__.py
  • custom_components/plugwise_usb/config_flow.py
  • custom_components/plugwise_usb/strings.json
  • custom_components/plugwise_usb/translations/en.json
  • custom_components/plugwise_usb/translations/nl.json
  • tests/conftest.py
  • tests/test_config_flow.py

@bouwew bouwew marked this pull request as ready for review March 1, 2026 13:41
@bouwew bouwew requested a review from a team as a code owner March 1, 2026 13:41
Copy link
Contributor

@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: 3

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

3-6: Consider adding a release date to v0.59.0 for consistency.

Recent entries include dates in the heading, which makes release history easier to scan.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CHANGELOG.md` around lines 3 - 6, Update the CHANGELOG entry header "##
v0.59.0" to include the release date (e.g., "## v0.59.0 - YYYY-MM-DD") so it
matches the format of recent entries; edit the heading text in the CHANGELOG.md
near the existing "## v0.59.0" line and add the appropriate publication date.
tests/test_config_flow.py (1)

18-21: Use realistic Plugwise MAC fixture values in reconfigure identity tests.

Lines 18-19 currently use short, separator-based values. Using 16-character hexadecimal values will better mirror production behavior for stick identity comparisons.

🔧 Suggested update
-TEST_MAC: Final[str] = "01:23:45:67:AB"
-TEST_MAC2: Final[str] = "02:23:45:67:AB"
+TEST_MAC: Final[str] = "0123456789ABCDEF"
+TEST_MAC2: Final[str] = "FEDCBA9876543210"

Based on learnings: Plugwise ZigBee devices use 16-character hexadecimal MAC addresses without separators (e.g., "0123456789ABCDEF") following the IEEE 802.15.4 64-bit address format.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_config_flow.py` around lines 18 - 21, The test fixtures TEST_MAC
and TEST_MAC2 use short, separator-based MAC strings—replace them with realistic
16-character hexadecimal Plugwise MACs (uppercase, no separators) to mirror
production 64-bit addresses; update the constants TEST_MAC and TEST_MAC2 in
tests/test_config_flow.py to values like "0123456789ABCDEF" and
"1123456789ABCDEF" and ensure any comparisons or assertions that reference
TEST_MAC/TEST_MAC2 still match the new format (no other logic changes required).
custom_components/plugwise_usb/config_flow.py (1)

37-37: Misleading parameter name: self should be hass.

This standalone function uses self as its first parameter name, but callers pass self.hass. The function works correctly, but self conventionally refers to a class instance, making this confusing to readers.

-async def validate_usb_connection(self, device_path=None) -> tuple[dict[str, str], str | None]:
+async def validate_usb_connection(hass, device_path=None) -> tuple[dict[str, str], str | None]:

And update line 42:

-    if device_path in plugwise_stick_entries(self):
+    if device_path in plugwise_stick_entries(hass):
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@custom_components/plugwise_usb/config_flow.py` at line 37, Rename the first
parameter of the standalone function validate_usb_connection from self to hass
to reflect that it expects a HomeAssistant object (callers pass self.hass);
update the function signature and every internal reference from self to hass
(including the usage referenced near line 42) and keep the existing type hints
(e.g., hass: HomeAssistant or appropriate typing) so callers don't need to
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@custom_components/plugwise_usb/__init__.py`:
- Line 58: The line setting config_entry.runtime_data[STICK] = api_stick assumes
runtime_data is a dict; ensure runtime_data is initialized first by checking
config_entry.runtime_data and assigning an empty dict if falsy (e.g., None)
before subscripting. Update the setup code in __init__.py (where config_entry,
runtime_data, STICK, and api_stick are used) to guard/assign runtime_data = {}
when absent, then set runtime_data[STICK] = api_stick so subscripting cannot
raise TypeError during entry setup.

In `@custom_components/plugwise_usb/config_flow.py`:
- Around line 150-151: The call to async_set_unique_id is misaligned due to one
extra space; fix the inconsistent indentation so the second line of the call
aligns with the first (use 4-space indentation like surrounding code) for the
async_set_unique_id(unique_id=mac_stick, raise_on_progress=False) invocation in
the config flow.

In `@tests/conftest.py`:
- Around line 35-41: The test fixture returns a MockConfigEntry with
minor_version=1 which conflicts with the config flow's MINOR_VERSION in
PlugwiseUSBConfigFlow (MINOR_VERSION = 0); update either the fixture or the
config flow so they match — change the fixture's minor_version to 0 or bump
PlugwiseUSBConfigFlow.MINOR_VERSION to 1 (whichever aligns with intended upgrade
behavior) and ensure MockConfigEntry, minor_version, and
PlugwiseUSBConfigFlow.MINOR_VERSION stay consistent across tests and
config_flow.py.

---

Nitpick comments:
In `@CHANGELOG.md`:
- Around line 3-6: Update the CHANGELOG entry header "## v0.59.0" to include the
release date (e.g., "## v0.59.0 - YYYY-MM-DD") so it matches the format of
recent entries; edit the heading text in the CHANGELOG.md near the existing "##
v0.59.0" line and add the appropriate publication date.

In `@custom_components/plugwise_usb/config_flow.py`:
- Line 37: Rename the first parameter of the standalone function
validate_usb_connection from self to hass to reflect that it expects a
HomeAssistant object (callers pass self.hass); update the function signature and
every internal reference from self to hass (including the usage referenced near
line 42) and keep the existing type hints (e.g., hass: HomeAssistant or
appropriate typing) so callers don't need to change.

In `@tests/test_config_flow.py`:
- Around line 18-21: The test fixtures TEST_MAC and TEST_MAC2 use short,
separator-based MAC strings—replace them with realistic 16-character hexadecimal
Plugwise MACs (uppercase, no separators) to mirror production 64-bit addresses;
update the constants TEST_MAC and TEST_MAC2 in tests/test_config_flow.py to
values like "0123456789ABCDEF" and "1123456789ABCDEF" and ensure any comparisons
or assertions that reference TEST_MAC/TEST_MAC2 still match the new format (no
other logic changes required).

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 495338c and 1af73a5.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • custom_components/plugwise_usb/__init__.py
  • custom_components/plugwise_usb/config_flow.py
  • custom_components/plugwise_usb/manifest.json
  • custom_components/plugwise_usb/strings.json
  • custom_components/plugwise_usb/translations/en.json
  • custom_components/plugwise_usb/translations/nl.json
  • pyproject.toml
  • tests/conftest.py
  • tests/test_config_flow.py

Copy link
Contributor

@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.

🧹 Nitpick comments (1)
custom_components/plugwise_usb/config_flow.py (1)

144-149: Use an explicit None check for submitted reconfigure payload.

if user_input: can skip valid-but-empty payloads; use is not None for consistent flow-step semantics.

Suggested diff
-        if user_input:
+        if user_input is not None:
             device_path = await self.hass.async_add_executor_job(
                 usb.get_serial_by_id, user_input.get(CONF_USB_PATH)
             )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@custom_components/plugwise_usb/config_flow.py` around lines 144 - 149, The
config flow currently uses a truthy check `if user_input:` which will skip
valid-but-empty payloads; change the conditional in the flow handling block to
an explicit None check (`if user_input is not None:`) so empty dicts are
processed correctly; update the block where usb.get_serial_by_id and
validate_usb_connection are called (referencing CONF_USB_PATH,
usb.get_serial_by_id, and validate_usb_connection in config_flow.py) to use the
new `is not None` check and keep the rest of the logic unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@custom_components/plugwise_usb/config_flow.py`:
- Around line 144-149: The config flow currently uses a truthy check `if
user_input:` which will skip valid-but-empty payloads; change the conditional in
the flow handling block to an explicit None check (`if user_input is not None:`)
so empty dicts are processed correctly; update the block where
usb.get_serial_by_id and validate_usb_connection are called (referencing
CONF_USB_PATH, usb.get_serial_by_id, and validate_usb_connection in
config_flow.py) to use the new `is not None` check and keep the rest of the
logic unchanged.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1af73a5 and 7a25f5a.

📒 Files selected for processing (3)
  • custom_components/plugwise_usb/__init__.py
  • custom_components/plugwise_usb/config_flow.py
  • tests/conftest.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/conftest.py

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 1, 2026

@bouwew bouwew merged commit bd2947a into main Mar 1, 2026
12 checks passed
@bouwew bouwew deleted the reconfigure branch March 1, 2026 14:11
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.

1 participant