From 0432c6a2fc94bd02e8a277013258b833adef7c58 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 8 Jun 2026 15:31:07 +0200 Subject: [PATCH 1/9] Change dhw_cm_switch to _dhw_allowed_modes/select_dhw_mode --- plugwise/helper.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugwise/helper.py b/plugwise/helper.py index 075f5b17d..d8ecadfca 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -482,8 +482,13 @@ def _get_toggle_state( if xml.find("type").text == "heater_central": locator = f"./actuator_functionalities/toggle_functionality[type='{toggle}']/state" if (state := xml.find(locator)) is not None: - data["switches"][name] = state.text == "on" - self._count += 1 + match toggle: + case "cooling_ena_switch": + data["switches"][name] = state.text == "on" + self._count += 1 + case "dhw_cm_switch": + self._dhw_allowed_modes = ["comfort", "off"] + self.select_dhw_mode = "comfort" if state.text == "on" else "off" def _get_plugwise_notifications(self) -> None: """Collect the Plugwise notifications.""" From 6977433cbb5786dd1c5ada9aa04854f23f7c0ad6 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 9 Jun 2026 08:13:22 +0200 Subject: [PATCH 2/9] Adapt comment to widened scope --- plugwise/helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise/helper.py b/plugwise/helper.py index d8ecadfca..b72a384fb 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -351,7 +351,7 @@ def _get_measurement_data(self, entity_id: str, entity: GwEntityData) -> None: measurements = DEVICE_MEASUREMENTS if self._is_thermostat and entity_id == self.heater_id: measurements = HEATER_CENTRAL_MEASUREMENTS - # Show the allowed dhw_modes (Loria only) + # Show the available dhw_modes if self._dhw_allowed_modes: data["dhw_modes"] = self._dhw_allowed_modes # Counting of this item is done in _appliance_measurements() From 3058843e3d397773986adee7e9c2c65483844085 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 9 Jun 2026 08:14:43 +0200 Subject: [PATCH 3/9] Move toggles collection up --- plugwise/helper.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugwise/helper.py b/plugwise/helper.py index b72a384fb..869a3aef9 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -407,12 +407,12 @@ def _collect_appliance_data( if ( appliance := self._domain_objects.find(f'./appliance[@id="{entity_id}"]') ) is not None: - self._appliance_measurements(appliance, data, measurements) - self._get_lock_state(appliance, data) - for toggle, name in TOGGLES.items(): self._get_toggle_state(appliance, toggle, name, data) + self._appliance_measurements(appliance, data, measurements) + self._get_lock_state(appliance, data) + if appliance.find("type").text in ACTUATOR_CLASSES: self._get_actuator_functionalities(appliance, entity, data) From 84817da10c1e6d3fde7d103af1de703ea149912e Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 9 Jun 2026 08:21:29 +0200 Subject: [PATCH 4/9] Improve --- plugwise/helper.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/plugwise/helper.py b/plugwise/helper.py index 869a3aef9..c7be3f7fd 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -242,9 +242,8 @@ def _appliance_info_finder(self, appl: Munch, appliance: etree.Element) -> Munch appl := self._appl_heater_central_info(appl, appliance, False) ): # False means non-legacy entity return Munch() - self._dhw_allowed_modes = self._get_appl_actuator_modes( - appliance, "domestic_hot_water_mode_control_functionality" - ) + self._collect_dhw_modes(appliance) + return appl case _ as s if s.endswith("_plug"): # Collect info from plug-types (Plug, Aqara Smart Plug) @@ -265,6 +264,18 @@ def _appliance_info_finder(self, appl: Munch, appliance: etree.Element) -> Munch case _: # pragma: no cover return Munch() + def _collect_dhw_modes(self, appliance: etree.Element) -> None: + """Collect the DHW modes.""" + # Collect the Loria dhw_modes + self._dhw_allowed_modes = self._get_appl_actuator_modes( + appliance, "domestic_hot_water_mode_control_functionality" + ) + # Collect the default dhw modes: comfort and off + if not self._dhw_allowed_modes: + self._get_toggle_state( + appliance, "domestic_hot_water_comfort_mode", "dhw_cm_switch", None + ) + def _appl_gateway_info(self, appl: Munch, appliance: etree.Element) -> Munch: """Helper-function for _appliance_info_finder().""" self._gateway_id = appl.entity_id @@ -407,8 +418,8 @@ def _collect_appliance_data( if ( appliance := self._domain_objects.find(f'./appliance[@id="{entity_id}"]') ) is not None: - for toggle, name in TOGGLES.items(): - self._get_toggle_state(appliance, toggle, name, data) + # Collect the cooling enabled toggle state + self._get_toggle_state(appliance, "cooling_enabled", "cooling_ena_switch", data) self._appliance_measurements(appliance, data, measurements) self._get_lock_state(appliance, data) @@ -483,12 +494,12 @@ def _get_toggle_state( locator = f"./actuator_functionalities/toggle_functionality[type='{toggle}']/state" if (state := xml.find(locator)) is not None: match toggle: - case "cooling_ena_switch": + case "cooling_enabled": data["switches"][name] = state.text == "on" self._count += 1 - case "dhw_cm_switch": + case "domestic_hot_water_comfort_mode": self._dhw_allowed_modes = ["comfort", "off"] - self.select_dhw_mode = "comfort" if state.text == "on" else "off" + # data["select_dhw_mode"] = "comfort" if state.text == "on" else "off" def _get_plugwise_notifications(self) -> None: """Collect the Plugwise notifications.""" From 6aa174ab958c5b022d7d7a77e970b21d57c29961 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 9 Jun 2026 20:06:12 +0200 Subject: [PATCH 5/9] Constants: add 2nd options for select_dhw_mode --- plugwise/constants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugwise/constants.py b/plugwise/constants.py index 267f2cbdb..4673b6dd7 100644 --- a/plugwise/constants.py +++ b/plugwise/constants.py @@ -181,6 +181,7 @@ ), # Available with the Loria and Elga (newer Anna firmware) heatpumps "cooling_state": UOM(NONE), "domestic_hot_water_mode": DATA("select_dhw_mode", NONE), + "domestic_hot_water_comfort_mode": DATA("select_dhw_mode", NONE), "domestic_hot_water_setpoint": UOM(TEMP_CELSIUS), "domestic_hot_water_state": DATA("dhw_state", NONE), "domestic_hot_water_temperature": DATA("dhw_temperature", TEMP_CELSIUS), From bcbfdc3fa7cfb5c370e2d9a9323c5c56405430a2 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 9 Jun 2026 20:09:23 +0200 Subject: [PATCH 6/9] Improve 2 --- plugwise/helper.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugwise/helper.py b/plugwise/helper.py index c7be3f7fd..797277b0d 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -463,6 +463,7 @@ def _appliance_measurements( continue if new_name := getattr(attrs, ATTR_NAME, None): + old_measurement = measurement measurement = new_name match measurement: @@ -471,6 +472,8 @@ def _appliance_measurements( 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" common_match_cases(measurement, attrs, appl_p_loc, data) @@ -499,7 +502,6 @@ def _get_toggle_state( self._count += 1 case "domestic_hot_water_comfort_mode": self._dhw_allowed_modes = ["comfort", "off"] - # data["select_dhw_mode"] = "comfort" if state.text == "on" else "off" def _get_plugwise_notifications(self) -> None: """Collect the Plugwise notifications.""" From 279713409c65eb28f870c79859377c76bf337beb Mon Sep 17 00:00:00 2001 From: autoruff Date: Tue, 9 Jun 2026 18:20:22 +0000 Subject: [PATCH 7/9] fixup: dhw_update Python code fixed using ruff --- plugwise/helper.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugwise/helper.py b/plugwise/helper.py index 797277b0d..b6f7645c8 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -419,7 +419,9 @@ def _collect_appliance_data( appliance := self._domain_objects.find(f'./appliance[@id="{entity_id}"]') ) is not None: # Collect the cooling enabled toggle state - self._get_toggle_state(appliance, "cooling_enabled", "cooling_ena_switch", data) + self._get_toggle_state( + appliance, "cooling_enabled", "cooling_ena_switch", data + ) self._appliance_measurements(appliance, data, measurements) self._get_lock_state(appliance, data) @@ -473,7 +475,9 @@ def _appliance_measurements( 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" + data["select_dhw_mode"] = ( + "comfort" if appl_p_loc.text == "on" else "off" + ) common_match_cases(measurement, attrs, appl_p_loc, data) From 910244f96d494e9bb4b20a69bbf48d7f490bea08 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Wed, 10 Jun 2026 07:57:02 +0200 Subject: [PATCH 8/9] Update testdata json --- tests/data/adam/adam_bad_thermostat.json | 8 +++++--- tests/data/adam/adam_heatpump_cooling.json | 8 +++++--- tests/data/adam/adam_jip.json | 8 +++++--- tests/data/adam/adam_onoff_cooling_fake_firmware.json | 8 +++++--- tests/data/adam/adam_plus_anna.json | 8 +++++--- tests/data/adam/adam_plus_anna_new.json | 8 +++++--- tests/data/adam/adam_plus_anna_new_regulation_off.json | 8 +++++--- 7 files changed, 35 insertions(+), 21 deletions(-) diff --git a/tests/data/adam/adam_bad_thermostat.json b/tests/data/adam/adam_bad_thermostat.json index 5554c02e1..16978a60c 100644 --- a/tests/data/adam/adam_bad_thermostat.json +++ b/tests/data/adam/adam_bad_thermostat.json @@ -7,6 +7,10 @@ "heating_state": false }, "dev_class": "heater_central", + "dhw_modes": [ + "comfort", + "off" + ], "location": "856285a783f24bf4b2573c8bc510eabf", "max_dhw_temperature": { "lower_bound": 0.0, @@ -23,6 +27,7 @@ "model": "Generic heater", "model_id": "1.1", "name": "OpenTherm", + "select_dhw_mode": "off", "sensors": { "dhw_temperature": 49.9, "intended_boiler_temperature": 0.0, @@ -31,9 +36,6 @@ "return_temperature": 33.0, "water_temperature": 20.9 }, - "switches": { - "dhw_cm_switch": false - }, "vendor": "WeHeat" }, "3ee6b9486cb04c258a3130fff2b144a4": { diff --git a/tests/data/adam/adam_heatpump_cooling.json b/tests/data/adam/adam_heatpump_cooling.json index 71bfad7e2..6c9f1fabe 100644 --- a/tests/data/adam/adam_heatpump_cooling.json +++ b/tests/data/adam/adam_heatpump_cooling.json @@ -44,6 +44,10 @@ }, "dev_class": "heater_central", "location": "eedadcb297564f1483faa509179aebed", + "dhw_modes": [ + "comfort", + "off" + ], "max_dhw_temperature": { "lower_bound": 40.0, "resolution": 0.01, @@ -59,6 +63,7 @@ "model": "Generic heater/cooler", "model_id": "17.1", "name": "OpenTherm", + "select_dhw_mode": "off", "sensors": { "dhw_temperature": 63.5, "intended_boiler_temperature": 0.0, @@ -68,9 +73,6 @@ "water_pressure": 2.0, "water_temperature": 24.5 }, - "switches": { - "dhw_cm_switch": true - }, "vendor": "Remeha B.V." }, "1053c8bbf8be43c6921742b146a625f1": { diff --git a/tests/data/adam/adam_jip.json b/tests/data/adam/adam_jip.json index a1136e3c9..3c10a4ca7 100644 --- a/tests/data/adam/adam_jip.json +++ b/tests/data/adam/adam_jip.json @@ -330,6 +330,10 @@ }, "dev_class": "heater_central", "location": "9e4433a9d69f40b3aefd15e74395eaec", + "dhw_modes": [ + "comfort", + "off" + ], "max_dhw_temperature": { "lower_bound": 40.0, "resolution": 0.01, @@ -345,6 +349,7 @@ "model": "Generic heater", "model_id": "10.20", "name": "OpenTherm", + "select_dhw_mode": "off", "sensors": { "intended_boiler_temperature": 0.0, "modulation_level": 0.0, @@ -352,9 +357,6 @@ "water_pressure": 1.4, "water_temperature": 37.3 }, - "switches": { - "dhw_cm_switch": false - }, "vendor": "Remeha B.V." }, "f61f1a2535f54f52ad006a3d18e459ca": { diff --git a/tests/data/adam/adam_onoff_cooling_fake_firmware.json b/tests/data/adam/adam_onoff_cooling_fake_firmware.json index f822e33d8..27d994a0e 100644 --- a/tests/data/adam/adam_onoff_cooling_fake_firmware.json +++ b/tests/data/adam/adam_onoff_cooling_fake_firmware.json @@ -9,6 +9,10 @@ }, "dev_class": "heater_central", "location": "eedadcb297564f1483faa509179aebed", + "dhw_modes": [ + "comfort", + "off" + ], "max_dhw_temperature": { "lower_bound": 40.0, "resolution": 0.01, @@ -23,6 +27,7 @@ }, "model": "Unknown", "name": "OnOff", + "select_dhw_mode": "comfort", "sensors": { "dhw_temperature": 63.5, "intended_boiler_temperature": 0.0, @@ -31,9 +36,6 @@ "return_temperature": 24.9, "water_pressure": 2.0, "water_temperature": 24.5 - }, - "switches": { - "dhw_cm_switch": true } }, "7d97fc3117784cfdafe347bcedcbbbcb": { diff --git a/tests/data/adam/adam_plus_anna.json b/tests/data/adam/adam_plus_anna.json index 8533e7468..d86a53176 100644 --- a/tests/data/adam/adam_plus_anna.json +++ b/tests/data/adam/adam_plus_anna.json @@ -35,6 +35,10 @@ }, "dev_class": "heater_central", "location": "07d618f0bb80412687f065b8698ce3e7", + "dhw_modes": [ + "comfort", + "off" + ], "maximum_boiler_temperature": { "lower_bound": 0.0, "resolution": 1.0, @@ -43,12 +47,10 @@ }, "model": "Generic heater", "name": "OpenTherm", + "select_dhw_mode": "off", "sensors": { "intended_boiler_temperature": 0.0, "water_temperature": 48.0 - }, - "switches": { - "dhw_cm_switch": false } }, "aa6b0002df0a46e1b1eb94beb61eddfe": { diff --git a/tests/data/adam/adam_plus_anna_new.json b/tests/data/adam/adam_plus_anna_new.json index 0c1057afc..d794d51cd 100644 --- a/tests/data/adam/adam_plus_anna_new.json +++ b/tests/data/adam/adam_plus_anna_new.json @@ -8,6 +8,10 @@ }, "dev_class": "heater_central", "location": "bc93488efab249e5bc54fd7e175a6f91", + "dhw_modes": [ + "comfort", + "off" + ], "maximum_boiler_temperature": { "lower_bound": 25.0, "resolution": 0.01, @@ -16,12 +20,10 @@ }, "model": "Generic heater", "name": "OpenTherm", + "select_dhw_mode": "off", "sensors": { "intended_boiler_temperature": 22.5, "water_temperature": 43.0 - }, - "switches": { - "dhw_cm_switch": false } }, "10016900610d4c7481df78c89606ef22": { diff --git a/tests/data/adam/adam_plus_anna_new_regulation_off.json b/tests/data/adam/adam_plus_anna_new_regulation_off.json index 4a0576d90..4f3130c05 100644 --- a/tests/data/adam/adam_plus_anna_new_regulation_off.json +++ b/tests/data/adam/adam_plus_anna_new_regulation_off.json @@ -8,6 +8,10 @@ }, "dev_class": "heater_central", "location": "bc93488efab249e5bc54fd7e175a6f91", + "dhw_modes": [ + "comfort", + "off" + ], "maximum_boiler_temperature": { "lower_bound": 25.0, "resolution": 0.01, @@ -16,12 +20,10 @@ }, "model": "Generic heater", "name": "OpenTherm", + "select_dhw_mode": "off", "sensors": { "intended_boiler_temperature": 0.0, "water_temperature": 30.0 - }, - "switches": { - "dhw_cm_switch": false } }, "10016900610d4c7481df78c89606ef22": { From 8209bef27ad031019c585a59c924610901132af2 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Wed, 10 Jun 2026 08:13:15 +0200 Subject: [PATCH 9/9] Save entity_items updates --- tests/test_adam.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_adam.py b/tests/test_adam.py index b818713f1..98266c7cc 100644 --- a/tests/test_adam.py +++ b/tests/test_adam.py @@ -47,7 +47,7 @@ async def test_connect_adam_plus_anna_new(self): test_items = await self.device_test(api, "2025-10-12 00:00:01", testdata) assert api.gateway_id == "da224107914542988a88561b4452b0f6" - assert self.entity_items == 231 + assert self.entity_items == 232 assert test_items == self.entity_items assert self.entity_list == [ "da224107914542988a88561b4452b0f6",