Skip to content

Change DHW comfort switch to select#883

Draft
bouwew wants to merge 9 commits into
mainfrom
dhw_update
Draft

Change DHW comfort switch to select#883
bouwew wants to merge 9 commits into
mainfrom
dhw_update

Conversation

@bouwew

@bouwew bouwew commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

New Features

  • Added domestic hot water comfort mode selection capability for heater devices, enabling users to choose between "comfort" and "off" modes for more granular climate control

Tests

  • Updated test data fixtures and assertions across multiple device configurations to validate the new DHW mode selection feature and associated entity structure changes

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR extends the Plugwise integration to support DHW (Domestic Hot Water) comfort mode selection for heater_central entities. A new constant maps the DHW comfort measurement to a select_dhw_mode field; collection logic gathers allowed DHW modes; the appliance data pipeline is reordered to capture cooling_enabled state and derive select_dhw_mode from DHW measurements; and test fixtures are updated to reflect the new structure.

Changes

DHW Mode Selection for Heater Central

Layer / File(s) Summary
Constants and DHW mode collection infrastructure
plugwise/constants.py, plugwise/helper.py
HEATER_CENTRAL_MEASUREMENTS adds domestic_hot_water_comfort_modeselect_dhw_mode mapping; new _collect_dhw_modes() method populates _dhw_allowed_modes from DHW actuator; _appliance_info_finder() invokes DHW mode collection after non-legacy heater_central info is gathered.
Appliance data and measurement handling
plugwise/helper.py
_collect_appliance_data() explicitly collects cooling_enabled toggle before measurements; _appliance_measurements() tracks prior measurement to derive select_dhw_mode (on→comfort, else→off); _get_toggle_state() dispatches cooling_enabled to boolean switch and initializes _dhw_allowed_modes for domestic_hot_water_comfort_mode.
Test fixture alignment with DHW data structure
tests/data/adam/adam_bad_thermostat.json, adam_heatpump_cooling.json, adam_jip.json, adam_onoff_cooling_fake_firmware.json, adam_plus_anna.json, adam_plus_anna_new.json, adam_plus_anna_new_regulation_off.json, tests/test_adam.py
Seven test fixtures updated to include dhw_modes arrays and select_dhw_mode fields for heater devices, removing legacy dhw_cm_switch switches. Entity count assertion incremented from 231 to 232.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • plugwise/python-plugwise#802: Both PRs modify the heater_central data collection path in _appliance_info_finder(), with #802 adding an orphan device guard and this PR adding DHW mode collection invocation.

Suggested labels

enhancement

Suggested reviewers

  • CoMPaTech
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: converting a DHW (domestic hot water) comfort switch entity to a select entity, which is reflected throughout all code and test data modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dhw_update

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.

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
B Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@coderabbitai coderabbitai Bot requested a review from CoMPaTech June 10, 2026 06:24
@coderabbitai coderabbitai Bot added the enhancement New feature or request label Jun 10, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
plugwise/helper.py (1)

35-35: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove unused import.

The TOGGLES constant is imported but never used in this file.

🧹 Proposed fix
-    TOGGLES,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugwise/helper.py` at line 35, Remove the unused import TOGGLES from the
import list in this module: locate the import statement that includes TOGGLES in
plugwise/helper.py and delete TOGGLES (or the whole import if it becomes empty)
so the file no longer imports an unused symbol.

Source: Pipeline failures

tests/test_adam.py (1)

120-123: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Test will fail: dhw_cm_switch removed from fixture.

According to the layer description, the adam_plus_anna_new fixture (loaded at line 35) has had dhw_cm_switch entries removed from switches objects. This test attempts to tinker with dhw_cm_switch on the heater_central device and expects success (line 123 assert switch_change), but the switch no longer exists in the fixture data.

🔧 Suggested fix options

Option 1: Remove the obsolete switch test

-        switch_change = await self.tinker_switch(
-            api,
-            "056ee145a816487eaa69243c3280f8bf",
-            model="dhw_cm_switch",
-        )
-        assert switch_change

Option 2: Update test to verify the new select entity

Replace the switch test with a test for the new select_dhw_mode functionality, if a corresponding test helper exists.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_adam.py` around lines 120 - 123, The test fails because the
adam_plus_anna_new fixture no longer includes the dhw_cm_switch entity; update
tests/test_adam.py by removing the obsolete switch assertion or replacing it
with a check for the new select entity (e.g., change the call that targets
model="dhw_cm_switch" on device "056ee145a816487eaa69243c3280f8bf" to instead
target the new select entity name such as "select_dhw_mode" and assert its
behavior), ensuring you update the invoked test helper call and the final
assertion (currently "assert switch_change") to match the new entity and
expected return value.
🧹 Nitpick comments (1)
plugwise/helper.py (1)

467-480: ⚡ Quick win

Clarify old_measurement initialization and scope.

The variable old_measurement is assigned on line 468 only when new_name exists, but it's referenced unconditionally on line 477. While this appears safe in practice (both domestic_hot_water_mode and domestic_hot_water_comfort_mode have DATA mappings with names), the logic is fragile and not immediately obvious.

♻️ Proposed refactor for clarity
 def _appliance_measurements(
     self,
     appliance: etree.Element,
     data: GwEntityData,
     measurements: dict[str, DATA | UOM],
 ) -> None:
     """Helper-function for _get_measurement_data() - collect appliance measurement data."""
     for measurement, attrs in measurements.items():
         p_locator = f'.//logs/point_log[type="{measurement}"]/period/measurement'
         if (appl_p_loc := appliance.find(p_locator)) is not None:
             if skip_obsolete_measurements(appliance, measurement):
                 continue
 
+            old_measurement = measurement
             if new_name := getattr(attrs, ATTR_NAME, None):
-                old_measurement = measurement
                 measurement = new_name
 
             match measurement:
                 case "elga_status_code":
                     data["elga_status_code"] = int(appl_p_loc.text)
                 case "select_dhw_mode":
                     if self._dhw_allowed_modes:
                         data["select_dhw_mode"] = appl_p_loc.text
                         if old_measurement == "domestic_hot_water_comfort_mode":
                             data["select_dhw_mode"] = (
                                 "comfort" if appl_p_loc.text == "on" else "off"
                             )

This ensures old_measurement is always defined before the match statement.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugwise/helper.py` around lines 467 - 480, old_measurement is only set when
new_name exists but is referenced later unconditionally in the match branch for
"select_dhw_mode"; initialize old_measurement to the current measurement before
the conditional that may rename it so it always has a value (ensure the block
using ATTR_NAME still updates measurement when new_name is present and preserves
old_measurement for later checks), referencing the existing symbols measurement,
old_measurement, ATTR_NAME, appl_p_loc, and self._dhw_allowed_modes to locate
and adjust the logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugwise/helper.py`:
- Around line 267-278: _collect_dhw_modes calls _get_toggle_state with None for
the data parameter which violates the declared GwEntityData (non-Optional) type;
either make _get_toggle_state accept Optional[GwEntityData] (update its
signature and handle None inside the function) or change the call in
_collect_dhw_modes to pass an empty dict/appropriate GwEntityData-shaped empty
value instead of None for the "domestic_hot_water_comfort_mode" /
"dhw_cm_switch" call so the types remain consistent.

---

Outside diff comments:
In `@plugwise/helper.py`:
- Line 35: Remove the unused import TOGGLES from the import list in this module:
locate the import statement that includes TOGGLES in plugwise/helper.py and
delete TOGGLES (or the whole import if it becomes empty) so the file no longer
imports an unused symbol.

In `@tests/test_adam.py`:
- Around line 120-123: The test fails because the adam_plus_anna_new fixture no
longer includes the dhw_cm_switch entity; update tests/test_adam.py by removing
the obsolete switch assertion or replacing it with a check for the new select
entity (e.g., change the call that targets model="dhw_cm_switch" on device
"056ee145a816487eaa69243c3280f8bf" to instead target the new select entity name
such as "select_dhw_mode" and assert its behavior), ensuring you update the
invoked test helper call and the final assertion (currently "assert
switch_change") to match the new entity and expected return value.

---

Nitpick comments:
In `@plugwise/helper.py`:
- Around line 467-480: old_measurement is only set when new_name exists but is
referenced later unconditionally in the match branch for "select_dhw_mode";
initialize old_measurement to the current measurement before the conditional
that may rename it so it always has a value (ensure the block using ATTR_NAME
still updates measurement when new_name is present and preserves old_measurement
for later checks), referencing the existing symbols measurement,
old_measurement, ATTR_NAME, appl_p_loc, and self._dhw_allowed_modes to locate
and adjust the logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c3649d18-c70a-480a-8b38-f2124773ded9

📥 Commits

Reviewing files that changed from the base of the PR and between d06304e and 8209bef.

📒 Files selected for processing (10)
  • plugwise/constants.py
  • plugwise/helper.py
  • tests/data/adam/adam_bad_thermostat.json
  • tests/data/adam/adam_heatpump_cooling.json
  • tests/data/adam/adam_jip.json
  • tests/data/adam/adam_onoff_cooling_fake_firmware.json
  • tests/data/adam/adam_plus_anna.json
  • tests/data/adam/adam_plus_anna_new.json
  • tests/data/adam/adam_plus_anna_new_regulation_off.json
  • tests/test_adam.py

Comment thread plugwise/helper.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant