Skip to content

Conversation

@bouwew
Copy link
Contributor

@bouwew bouwew commented Dec 21, 2025

Changes:

  • Rename _all_... to _get_...
  • Reorganize _get_appliances()
  • Rework optimize _scan_thermostat() and related functions
  • For the home-location, check for type == building, this is a better method for finding the home-location

Summary by CodeRabbit

  • Refactor
    • Improved device discovery and location assignment; thermostat detection, matching and ranking rebuilt for more reliable zone mappings and consistent thermostat scanning.
  • Chores
    • Added thermostat priority mappings and expanded plug classification to better identify and label plug and thermostat devices; additional appliance/location metadata captured.
  • Docs
    • Changelog updated to reference the additional PR.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 21, 2025

Walkthrough

Adds a THERMO_MATCHING constant and refactors appliance/location helpers: renames methods, extends appliance data and plug-class logic, changes thermostat-ranking signatures and matching to mutate internal _loc_data, and makes thermostat scanning run in the thermostat path (removed ADAM-only guard).

Changes

Cohort / File(s) Summary
Constants enrichment
plugwise/constants.py
Added public constant THERMO_MATCHING: Final[dict[str, int]] mapping device classes to priorities ("thermostat": 2, "zone_thermometer": 2, "zone_thermostat": 2, "thermostatic_radiator_valve": 1).
Helper refactor
plugwise/helper.py
Renamed _all_appliances_get_appliances and _all_locations_get_locations; added extend_plug_device_class; expanded appliance fields (available, entity_id, location, zigbee_mac, vendor_name, etc.); replaced _match_locations with _match_and_rank_thermostats that mutates _loc_data; changed _rank_thermostat signature to (entity_id, entity, location_id, location, thermo_matching) and adjusted thermostat scanning to use the new ranking flow.
Integration update
plugwise/smile.py
Replaced _all_appliances() with _get_appliances(); removed ADAM-only guard so _scan_thermostats() runs when _is_thermostat is true; removed ADAM from imports.
Legacy locations
plugwise/legacy/helper.py
loc._type read from XML and used to set self._home_loc_id when loc._type == "building"; assignment ordering adjusted.
Changelog
CHANGELOG.md
Text update: added PR #838 alongside #837 in the Ongoing section.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify all call sites updated for _get_appliances / _get_locations.
  • Confirm _rank_thermostat signature changes align with callers and type hints.
  • Review initialization and types for new appliance fields (zigbee_mac, vendor_name, etc.).
  • Check _match_and_rank_thermostats correctly populates _loc_data and downstream consumers.
  • Validate behavioral change removing ADAM guard in plugwise/smile.py.

Possibly related PRs

Suggested labels

quality

Poem

🐰 I hopped through constants, neat and new,
I nudged the helpers, gave fields their due,
Thermostats ranked, locations known,
Scans run freer — no ADAM throne,
A tiny rabbit cheers this code anew!

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Further code optimizations' is overly vague and generic. It uses non-descriptive language that doesn't convey what specific changes were made, making it unclear for developers scanning history. Consider a more specific title that highlights a key change, such as 'Refactor appliance and location retrieval methods' or 'Optimize thermostat matching and ranking logic.'
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch correct-group-related

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0c4271c and e4efbbe.

📒 Files selected for processing (1)
  • plugwise/helper.py (5 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 797
File: fixtures/adam_anna_new_2/data.json:1-304
Timestamp: 2025-10-11T14:05:29.022Z
Learning: In Plugwise fixture data (data.json files), location IDs referenced in device entries don't always need corresponding top-level location objects. Only climate zones (ThermoZone entries with dev_class "climate") require full top-level definitions with thermostats, schedules, and presets. Simple organizational locations that just group devices (like single plugs) can be referenced without top-level entries.
📚 Learning: 2024-12-22T09:37:24.648Z
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 678
File: plugwise/legacy/helper.py:69-69
Timestamp: 2024-12-22T09:37:24.648Z
Learning: The code in plugwise/legacy/helper.py is fully separated from plugwise/helper.py. The user indicates that the problem signaled about the mismatch of the variable name (_home_location vs _home_loc_id) does not actually apply.

Applied to files:

  • plugwise/helper.py
📚 Learning: 2025-12-21T10:56:14.461Z
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 838
File: plugwise/helper.py:210-211
Timestamp: 2025-12-21T10:56:14.461Z
Learning: In plugwise/helper.py, when parsing location XML elements, the `type` element is always present for a location, so null checks are not required when accessing `location.find("type").text`.

Applied to files:

  • plugwise/helper.py
📚 Learning: 2025-10-11T14:05:29.022Z
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 797
File: fixtures/adam_anna_new_2/data.json:1-304
Timestamp: 2025-10-11T14:05:29.022Z
Learning: In Plugwise fixture data (data.json files), location IDs referenced in device entries don't always need corresponding top-level location objects. Only climate zones (ThermoZone entries with dev_class "climate") require full top-level definitions with thermostats, schedules, and presets. Simple organizational locations that just group devices (like single plugs) can be referenced without top-level entries.

Applied to files:

  • plugwise/helper.py
🔇 Additional comments (5)
plugwise/helper.py (5)

60-69: LGTM! Proper None-checking addresses previous AttributeError concern.

The implementation correctly guards against missing description elements by checking for None before accessing .text. This resolves the critical issue flagged in previous reviews.


108-163: LGTM! Proper initialization order prevents AttributeError.

Calling _get_locations() on line 115 before processing appliances ensures that self._home_loc_id and self._home_location are set (or KeyError is raised) before they're used on line 146. The addition of extend_plug_device_class() on line 152 properly handles plug-type classification before appliance info collection.


203-230: LGTM! Clear error handling prevents uninitialized attributes.

The KeyError on lines 226-229 ensures that if no building-type location exists, the method fails fast with a clear message rather than leaving self._home_loc_id and self._home_location uninitialized. This addresses the AttributeError concern from previous reviews.


757-780: LGTM! Proper guard clause and zone construction.

The early return on lines 763-764 correctly restricts thermostat scanning to ADAM devices. The zone construction logic properly uses the enriched location data structure to build climate zones only for locations with ranked thermostats.


781-824: LGTM! Thermostat ranking logic is correct.

The refactored thermostat matching and ranking implementation properly handles:

  • Early return on line 810 when entity doesn't match the location or isn't a thermostat device
  • Primary thermostat election when rank matches or exceeds current priority (lines 813-822)
  • Proper demotion of previous primary thermostats to secondary list (lines 818-820)

The walrus operator on line 818 correctly checks for a non-empty primary list before demoting.


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.

@codecov
Copy link

codecov bot commented Dec 21, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (20b7108) to head (e4efbbe).
⚠️ Report is 17 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #838   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           21        21           
  Lines         3442      3435    -7     
=========================================
- Hits          3442      3435    -7     

☔ 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
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: 0

🧹 Nitpick comments (1)
plugwise/constants.py (1)

95-100: Consider using Final type annotation for immutability.

The THERMO_MATCHING constant should be annotated with Final[dict[str, int]] to match the pattern of other module-level constants and to clearly indicate this mapping should not be modified at runtime.

🔎 Proposed fix
-THERMO_MATCHING: dict[str, int] = {
+THERMO_MATCHING: Final[dict[str, int]] = {
     "thermostat": 2,
     "zone_thermometer": 2,
     "zone_thermostat": 2,
     "thermostatic_radiator_valve": 1,
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20b7108 and 5311198.

📒 Files selected for processing (3)
  • plugwise/constants.py (1 hunks)
  • plugwise/helper.py (4 hunks)
  • plugwise/smile.py (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-12-22T09:37:24.648Z
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 678
File: plugwise/legacy/helper.py:69-69
Timestamp: 2024-12-22T09:37:24.648Z
Learning: The code in plugwise/legacy/helper.py is fully separated from plugwise/helper.py. The user indicates that the problem signaled about the mismatch of the variable name (_home_location vs _home_loc_id) does not actually apply.

Applied to files:

  • plugwise/helper.py
🧬 Code graph analysis (2)
plugwise/smile.py (1)
plugwise/helper.py (3)
  • _get_appliances (97-159)
  • _get_appliances_with_offset_functionality (300-309)
  • _scan_thermostats (742-764)
plugwise/helper.py (2)
plugwise/common.py (1)
  • _create_gw_entities (147-166)
plugwise/constants.py (2)
  • GwEntityData (533-595)
  • ThermoLoc (511-517)
🔇 Additional comments (11)
plugwise/smile.py (2)

109-109: LGTM - Method rename aligns with helper module.

The rename from _all_appliances() to _get_appliances() is consistent with the refactored method name in plugwise/helper.py.


110-114: LGTM - Simplified conditional logic with internal gating.

The thermostat scanning is now called unconditionally when _is_thermostat is true, which simplifies this call site. The ADAM-specific gating has been moved inside _scan_thermostats() itself (lines 748-749 in plugwise/helper.py), which is a cleaner separation of concerns.

plugwise/helper.py (9)

97-104: LGTM - Method rename improves clarity.

The rename from _all_appliances to _get_appliances better reflects that this method both collects and processes appliances, rather than just returning all of them. The updated docstring accurately describes the method's behavior.


108-120: LGTM - Explicit initialization improves code clarity.

Explicitly initializing all appliance attributes to None or appropriate default values makes the data structure more predictable and easier to understand. This is a good practice for avoiding potential AttributeError exceptions.


122-128: LGTM - Clearer comments and consistent filtering logic.

The updated comment better explains the filtering logic for OpenThermGateway appliances and orphaned thermostats. The multi-line condition format improves readability.


130-146: LGTM - Location assignment logic is more explicit.

The refactored location assignment logic with clearer comments makes the handling of appliances without locations more understandable. The plug description handling remains functionally equivalent.


154-159: LGTM - Improved code organization.

Moving the P1 smartmeter collection after appliance processing and explicitly calling _reorder_devices() makes the workflow more obvious and maintainable.


742-764: LGTM - Adam-specific logic properly guarded.

The updated _scan_thermostats() method correctly includes an early return for non-ADAM devices, and the refactored iteration over _loc_data is cleaner. The docstring accurately reflects that this is Adam-only functionality.


766-775: LGTM - Method rename reflects updated behavior.

The rename from _match_locations to _match_and_rank_thermostats better describes the method's purpose. The refactored implementation that directly populates internal structures rather than returning a dictionary is a cleaner design.


777-810: Parameter order change is correct and consistent throughout codebase.

The caller at line 773-775 passes arguments in the correct order matching the new signature: entity_id, entity, location_id, location, thermo_matching. Only one call to this method exists, and it has been updated correctly.


197-214: Code structure is correct — _loc_data initialization matches the ThermoLoc TypedDict.

The initialization in _get_locations() (lines 204-210) creates dictionaries with all required keys (name, primary, primary_prio, secondary) matching the ThermoLoc structure defined in plugwise/constants.py:511-517. All usages of _loc_data in the codebase access compatible keys. The _home_location (XML element) and _home_loc_id (string ID) serve distinct purposes and are used appropriately.

@bouwew bouwew changed the title Further optimizations Further code optimizations Dec 21, 2025
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: 1

🧹 Nitpick comments (2)
plugwise/helper.py (2)

106-164: LGTM - Clean refactoring of appliance collection.

The rename from _all_appliances() to _get_appliances() aligns with the PR objectives. The reorganization improves clarity by:

  • Initializing all appliance fields upfront (lines 117-129)
  • Extracting plug device class logic to extend_plug_device_class() (line 150)
  • Maintaining the skip logic and flow control
Optional: Consider consolidating field initialization

Lines 117-129 could be more concise using a dict:

appl = Munch({
    "available": None,
    "entity_id": appliance.attrib["id"],
    "location": None,
    "name": appliance.find("name").text,
    "model": None,
    "model_id": None,
    "module_id": None,
    "firmware": None,
    "hardware": None,
    "mac": None,
    "pwclass": appliance.find("type").text,
    "zigbee_mac": None,
    "vendor_name": None,
})

This is purely stylistic and the current approach is equally valid.


770-779: Consider the efficiency of nested location × entity loops.

Lines 775-779 iterate over all locations and all entities (O(n×m) complexity). If the number of locations and entities is large, this could be inefficient.

Consider building a location-to-entities map once:

def _match_and_rank_thermostats(self) -> None:
    """Match thermostat-appliances with locations, rank them for locations with multiple thermostats."""
    # Build location index
    entities_by_location: dict[str, list[tuple[str, GwEntityData]]] = {}
    for entity_id, entity in self.gw_entities.items():
        if "location" in entity:
            loc = entity["location"]
            entities_by_location.setdefault(loc, []).append((entity_id, entity))
    
    # Rank thermostats per location
    for location_id, location in self._loc_data.items():
        for entity_id, entity in entities_by_location.get(location_id, []):
            self._rank_thermostat(entity_id, entity, location_id, location, THERMO_MATCHING)

This would reduce complexity to O(n+m). However, if the dataset sizes are small (typical for home automation), the current approach is acceptable.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 034d948 and 57876ad.

📒 Files selected for processing (1)
  • plugwise/helper.py (5 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-12-22T09:37:24.648Z
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 678
File: plugwise/legacy/helper.py:69-69
Timestamp: 2024-12-22T09:37:24.648Z
Learning: The code in plugwise/legacy/helper.py is fully separated from plugwise/helper.py. The user indicates that the problem signaled about the mismatch of the variable name (_home_location vs _home_loc_id) does not actually apply.

Applied to files:

  • plugwise/helper.py
📚 Learning: 2025-10-11T14:05:29.022Z
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 797
File: fixtures/adam_anna_new_2/data.json:1-304
Timestamp: 2025-10-11T14:05:29.022Z
Learning: In Plugwise fixture data (data.json files), location IDs referenced in device entries don't always need corresponding top-level location objects. Only climate zones (ThermoZone entries with dev_class "climate") require full top-level definitions with thermostats, schedules, and presets. Simple organizational locations that just group devices (like single plugs) can be referenced without top-level entries.

Applied to files:

  • plugwise/helper.py
🧬 Code graph analysis (1)
plugwise/helper.py (3)
plugwise/legacy/helper.py (1)
  • _appliance_info_finder (192-205)
plugwise/common.py (2)
  • _create_gw_entities (147-166)
  • check_name (67-72)
plugwise/constants.py (2)
  • GwEntityData (533-595)
  • ThermoLoc (511-517)
🔇 Additional comments (5)
plugwise/helper.py (5)

201-218: LGTM - Well-structured location data initialization.

The rename and refactoring of _get_locations() cleanly initializes the _loc_data structure that supports the new thermostat ranking logic. The dict structure with "name", "primary", "primary_prio", and "secondary" keys aligns with the ThermoLoc TypedDict.


746-768: LGTM - Thermostat scanning refactored correctly.

The refactored _scan_thermostats() maintains the Adam-only guard and now uses _match_and_rank_thermostats() to populate _loc_data with thermostat rankings. The iteration over _loc_data (lines 756-768) correctly builds zone entities from the ranking results.


781-815: LGTM - Thermostat ranking logic is sound.

The updated _rank_thermostat() signature and implementation correctly:

  • Matches thermostats to locations by comparing entity["location"] with location_id
  • Ranks based on thermo_matching priority values
  • Handles demotion of former primary thermostats to secondary (lines 808-810)
  • Supports multiple primary thermostats with the same priority (line 801-802)

The logic flow is clear and handles the edge cases appropriately.


33-33: THERMO_MATCHING constant is properly defined.

The imported THERMO_MATCHING constant is correctly defined in plugwise/constants.py (line 95) as a Final[dict[str, int]] mapping device class strings to priority integers:

  • "thermostat": 2
  • "zone_thermometer": 2
  • "zone_thermostat": 2
  • "thermostatic_radiator_valve": 1

The import at line 33 and usage at line 778 are both correct.


781-815: No action required. The dev_class key is always initialized in _create_gw_entities() (line 149 in common.py: self.gw_entities[appl.entity_id] = {"dev_class": appl.pwclass}), and all entities passed to _rank_thermostat() come from self.gw_entities.items() after creation. There are no code paths that add entries to gw_entities without this key.

@bouwew bouwew force-pushed the correct-group-related branch from 57876ad to 6a41486 Compare December 21, 2025 10:09
@bouwew bouwew marked this pull request as ready for review December 21, 2025 10:13
@bouwew bouwew requested a review from a team as a code owner December 21, 2025 10:13
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: 1

🧹 Nitpick comments (1)
plugwise/helper.py (1)

805-809: Optional: Remove redundant location check.

The condition location_id == entity["location"] at line 807 is redundant because we're already iterating over entities_by_location.get(location_id, []), which only contains entities where entity["location"] matches location_id. While this defensive check doesn't hurt, it could be simplified for clarity.

🔎 Proposed simplification
-        if (
-            "location" in entity
-            and location_id == entity["location"]
-            and appl_class in thermo_matching
-        ):
+        if "location" in entity and appl_class in thermo_matching:
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57876ad and 6a41486.

📒 Files selected for processing (1)
  • plugwise/helper.py (5 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 797
File: fixtures/adam_anna_new_2/data.json:1-304
Timestamp: 2025-10-11T14:05:29.022Z
Learning: In Plugwise fixture data (data.json files), location IDs referenced in device entries don't always need corresponding top-level location objects. Only climate zones (ThermoZone entries with dev_class "climate") require full top-level definitions with thermostats, schedules, and presets. Simple organizational locations that just group devices (like single plugs) can be referenced without top-level entries.
📚 Learning: 2024-12-22T09:37:24.648Z
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 678
File: plugwise/legacy/helper.py:69-69
Timestamp: 2024-12-22T09:37:24.648Z
Learning: The code in plugwise/legacy/helper.py is fully separated from plugwise/helper.py. The user indicates that the problem signaled about the mismatch of the variable name (_home_location vs _home_loc_id) does not actually apply.

Applied to files:

  • plugwise/helper.py
📚 Learning: 2025-10-11T14:05:29.022Z
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 797
File: fixtures/adam_anna_new_2/data.json:1-304
Timestamp: 2025-10-11T14:05:29.022Z
Learning: In Plugwise fixture data (data.json files), location IDs referenced in device entries don't always need corresponding top-level location objects. Only climate zones (ThermoZone entries with dev_class "climate") require full top-level definitions with thermostats, schedules, and presets. Simple organizational locations that just group devices (like single plugs) can be referenced without top-level entries.

Applied to files:

  • plugwise/helper.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Process test coverage
🔇 Additional comments (4)
plugwise/helper.py (4)

60-69: Past review concern properly addressed.

The AttributeError risk flagged in the previous review has been correctly resolved. The code now properly guards against missing description elements using walrus operators before accessing .text.


108-166: LGTM!

The renaming to _get_appliances() follows a clearer naming convention, and the additional field initializations (zigbee_mac, vendor_name) along with the call to extend_plug_device_class() properly extend the appliance data structure.


748-771: LGTM!

The Adam-only guard at the start is a good defensive check, and the updated code properly uses the new location data structure (location["primary_prio"], location["primary"], location["secondary"]).


772-789: The refactoring to build an entities_by_location index and mutate _loc_data directly is sound. The THERMO_MATCHING constant is properly defined in plugwise.constants with the expected thermostat priority mappings.

Comment on lines 777 to 789
# Build location index
entities_by_location: dict[str, list[tuple[str, GwEntityData]]] = {}
for entity_id, entity in self.gw_entities.items():
if "location" in entity:
loc = entity["location"]
entities_by_location.setdefault(loc, []).append((entity_id, entity))

# Rank thermostats per location
for location_id, location in self._loc_data.items():
for entity_id, entity in entities_by_location.get(location_id, []):
self._rank_thermostat(
entity_id, entity, location_id, location, THERMO_MATCHING
)
Copy link
Member

Choose a reason for hiding this comment

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

Wondered if we couldn't do this in a single loop

Suggested change
# Build location index
entities_by_location: dict[str, list[tuple[str, GwEntityData]]] = {}
for entity_id, entity in self.gw_entities.items():
if "location" in entity:
loc = entity["location"]
entities_by_location.setdefault(loc, []).append((entity_id, entity))
# Rank thermostats per location
for location_id, location in self._loc_data.items():
for entity_id, entity in entities_by_location.get(location_id, []):
self._rank_thermostat(
entity_id, entity, location_id, location, THERMO_MATCHING
)
# Rank thermostats by walking locations
for location_id, location in self._loc_data.items():
for entity_id, entity in self.gw_entities.items():
if entity.get("location") == location_id:
self._rank_thermostat(
entity_id, entity, location_id, location, THERMO_MATCHING
)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I had that. See the nitpick above, the code-change comes from the suggestion in the nitpick.
And it has more benefits, it simplifies the _rank_thermostat() function.

Comment on lines 804 to 809
appl_class = entity["dev_class"]
if (
"location" in entity
and location_id == entity["location"]
and appl_class in thermo_matching
):
Copy link
Member

Choose a reason for hiding this comment

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

Suggest turning this negative and return None

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This line has been simplified, see the latest commits.

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

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a41486 and 0c4271c.

📒 Files selected for processing (2)
  • plugwise/helper.py (5 hunks)
  • plugwise/legacy/helper.py (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 678
File: plugwise/legacy/helper.py:69-69
Timestamp: 2024-12-22T09:37:24.648Z
Learning: The code in plugwise/legacy/helper.py is fully separated from plugwise/helper.py. The user indicates that the problem signaled about the mismatch of the variable name (_home_location vs _home_loc_id) does not actually apply.
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 797
File: fixtures/adam_anna_new_2/data.json:1-304
Timestamp: 2025-10-11T14:05:29.022Z
Learning: In Plugwise fixture data (data.json files), location IDs referenced in device entries don't always need corresponding top-level location objects. Only climate zones (ThermoZone entries with dev_class "climate") require full top-level definitions with thermostats, schedules, and presets. Simple organizational locations that just group devices (like single plugs) can be referenced without top-level entries.
📚 Learning: 2024-12-22T09:37:24.648Z
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 678
File: plugwise/legacy/helper.py:69-69
Timestamp: 2024-12-22T09:37:24.648Z
Learning: The code in plugwise/legacy/helper.py is fully separated from plugwise/helper.py. The user indicates that the problem signaled about the mismatch of the variable name (_home_location vs _home_loc_id) does not actually apply.

Applied to files:

  • plugwise/helper.py
  • plugwise/legacy/helper.py
📚 Learning: 2025-10-11T14:05:29.022Z
Learnt from: bouwew
Repo: plugwise/python-plugwise PR: 797
File: fixtures/adam_anna_new_2/data.json:1-304
Timestamp: 2025-10-11T14:05:29.022Z
Learning: In Plugwise fixture data (data.json files), location IDs referenced in device entries don't always need corresponding top-level location objects. Only climate zones (ThermoZone entries with dev_class "climate") require full top-level definitions with thermostats, schedules, and presets. Simple organizational locations that just group devices (like single plugs) can be referenced without top-level entries.

Applied to files:

  • plugwise/helper.py
  • plugwise/legacy/helper.py
🧬 Code graph analysis (1)
plugwise/helper.py (3)
plugwise/legacy/helper.py (1)
  • _appliance_info_finder (189-202)
plugwise/common.py (2)
  • _create_gw_entities (147-166)
  • check_name (67-72)
plugwise/constants.py (2)
  • GwEntityData (533-595)
  • ThermoLoc (511-517)
🔇 Additional comments (5)
plugwise/helper.py (5)

60-68: LGTM!

The defensive null checks properly guard against AttributeError when the description element or its text is missing. This addresses the past review concern.


108-166: LGTM!

The refactoring improves clarity with the _get_ prefix, explicit field initialization, and extracted helper function. The logic flow remains intact.


226-229: Verify intentional removal of fallback for missing home location.

The code now raises KeyError when no building location is found, whereas a past review noted that the legacy implementation creates a fake "Home" location as a fallback. This represents a breaking behavioral change that could cause initialization failures in edge cases.

Confirm this fail-fast approach is intentional and that all supported configurations guarantee a building-type location exists.

Based on past review comments indicating fallback handling was needed for missing "Home" location.


757-779: LGTM!

The refactoring cleanly integrates the new thermostat ranking results from _match_and_rank_thermostats() into the zone creation logic. The Adam-only guard remains in place as appropriate.


781-828: LGTM!

The refactored thermostat matching and ranking logic is well-structured. Building the entity-by-location index improves clarity, and the in-place mutation of location data aligns with the new _loc_data structure. The ranking algorithm correctly handles primary election and demotion to secondary.

if loc_id == appl_d_loc and appl_class in thermo_matching:
if thermo_matching[appl_class] == thermo_loc["primary_prio"]:
thermo_loc["primary"].append(appliance_id)
if (appl_class := entity["dev_class"]) in thermo_matching:
Copy link
Member

Choose a reason for hiding this comment

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

Same still applies, negate and return as there is no 'else'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok implemented.

@sonarqubecloud
Copy link

@bouwew bouwew merged commit c005c19 into main Dec 21, 2025
18 checks passed
@bouwew bouwew deleted the correct-group-related branch December 21, 2025 12:07
This was referenced Dec 22, 2025
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