diff --git a/CHANGELOG.md b/CHANGELOG.md index 279ae4ddc..6bf45d22c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v1.14.6 + +- Bugfixes: fix domestic hot water comfort switching, dhw modes selection issues reported in Core issue [#178699](https://github.com/home-assistant/core/issues/178699) via PR [#914](https://github.com/plugwise/python-plugwise/pull/914) + ## v1.14.5 - Rename dict-keys: `max_dhw_temperature` to `dhw_temperature`, `maximum_boiler_temperature` to `boiler_temperature` via PR [#908](https://github.com/plugwise/python-plugwise/pull/908) diff --git a/plugwise/helper.py b/plugwise/helper.py index 793aabdb1..820deafab 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -271,10 +271,12 @@ def _collect_dhw_modes(self, appliance: etree.Element) -> None: appliance, "domestic_hot_water_mode_control_functionality" ) # Determine the dhw modes from the domestic_hot_water_comfort_mode toggle - if not self._dhw_allowed_modes: - self._get_toggle_state( - appliance, "domestic_hot_water_comfort_mode", "dhw_cm_switch", {} - ) + if self._dhw_allowed_modes: + return + + self._get_toggle_state( + appliance, "domestic_hot_water_comfort_mode", "dhw_cm_switch", {} + ) def _appl_gateway_info(self, appl: Munch, appliance: etree.Element) -> Munch: """Helper-function for _appliance_info_finder().""" @@ -508,7 +510,10 @@ def _get_toggle_state( if "switches" in data: data["switches"][name] = state.text == "on" self._count += 1 - if toggle == "domestic_hot_water_comfort_mode": + if ( + not self._dhw_allowed_modes + and toggle == "domestic_hot_water_comfort_mode" + ): self._dhw_allowed_modes = ["comfort", "eco"] def _get_plugwise_notifications(self) -> None: diff --git a/plugwise/legacy/smile.py b/plugwise/legacy/smile.py index 4c5fbf7b7..9118ff02b 100644 --- a/plugwise/legacy/smile.py +++ b/plugwise/legacy/smile.py @@ -157,15 +157,15 @@ async def set_offset(self, dev_id: str, offset: float) -> None: async def set_preset(self, _: str, preset: str) -> None: """Set the given Preset on the relevant Thermostat - from DOMAIN_OBJECTS.""" if not (presets := self._presets()): - raise PlugwiseError("Plugwise: no presets available.") # pragma: no cover + raise PlugwiseError("Plugwise: no presets available") # pragma: no cover if preset not in list(presets): - raise PlugwiseError("Plugwise: invalid preset.") + raise PlugwiseError(f"Plugwise: invalid preset {preset}") locator = f'rule/directives/when/then[@icon="{preset}"].../.../...' if (rule := self._domain_objects.find(locator)) is None: - raise PlugwiseError("Plugwise: no preset rule found.") # pragma: no cover + raise PlugwiseError("Plugwise: no preset rule found") # pragma: no cover if (rule_id := rule.get("id")) is None: - raise PlugwiseError("Plugwise: no preset id found.") # pragma: no cover + raise PlugwiseError("Plugwise: no preset id found") # pragma: no cover data = f"true" await self.call_request(RULES, method="put", data=data) @@ -196,7 +196,7 @@ async def set_schedule_state( Used in HA Core to set the hvac_mode: in practice switch between schedule on - off. """ if state not in (STATE_OFF, STATE_ON): - raise PlugwiseError("Plugwise: invalid schedule state.") + raise PlugwiseError(f"Plugwise: invalid schedule state {state}") # Handle no schedule-name / Off-schedule provided if name is None or name == OFF: @@ -210,7 +210,7 @@ async def set_schedule_state( if schedule_rule_id is None: raise PlugwiseError( - "Plugwise: no schedule with this name available." + f"Plugwise: no schedule with name {name} available" ) # pragma: no cover new_state = "false" diff --git a/plugwise/smile.py b/plugwise/smile.py index 8f4627fe1..0aea89a58 100644 --- a/plugwise/smile.py +++ b/plugwise/smile.py @@ -43,7 +43,7 @@ def model_to_switch_items(model: str, state: str, switch: Munch) -> tuple[str, M Helper function for set_switch_state(). """ match model: - case "select_dhw_mode" | "dhw_mode": + case "select_dhw_mode" | "dhw_mode" | "dhw_cm_switch": switch.device = switch.func_type = "toggle" switch.act_type = "domestic_hot_water_comfort_mode" case "cooling_ena_switch": @@ -189,7 +189,7 @@ async def set_number( thermostat_id = th_func.get("id") if thermostat_id is None: - raise PlugwiseError(f"Plugwise: cannot change setpoint, {key} not found.") + raise PlugwiseError(f"Plugwise: cannot change setpoint, {key} not found") data = ( "" @@ -203,7 +203,7 @@ async def set_offset(self, dev_id: str, offset: float) -> None: """Set the Temperature offset for thermostats that support this feature.""" if dev_id not in self.therms_with_offset_func: raise PlugwiseError( - "Plugwise: this device does not have temperature-offset capability." + "Plugwise: this device does not have temperature-offset capability" ) value = str(offset) @@ -214,9 +214,9 @@ async def set_offset(self, dev_id: str, offset: float) -> None: async def set_preset(self, loc_id: str, preset: str) -> None: """Set the given Preset on the relevant Thermostat - from LOCATIONS.""" if (presets := self._presets(loc_id)) is None: - raise PlugwiseError("Plugwise: no presets available.") # pragma: no cover + raise PlugwiseError("Plugwise: no presets available") # pragma: no cover if preset not in list(presets): - raise PlugwiseError("Plugwise: invalid preset.") + raise PlugwiseError(f"Plugwise: invalid preset {preset}") current_location = self._domain_objects.find(f'location[@id="{loc_id}"]') location_name = current_location.find("name").text @@ -268,12 +268,13 @@ async def set_dhw_mode( - and the 5 modes available on the Loria. """ if ( - self._dhw_allowed_modes - and mode not in self._dhw_allowed_modes + mode not in self.gw_entities.get(appl_id, {}).get("dhw_modes", []) or length is None or not isinstance(length, int) ): - raise PlugwiseError("Plugwise: invalid dhw mode or invalid dhw modes list.") + raise PlugwiseError( + f"Plugwise: invalid dhw mode {mode} or invalid length {length}" + ) match length: case 2: @@ -291,8 +292,10 @@ async def set_dhw_mode( async def set_gateway_mode(self, mode: str) -> None: """Set the gateway mode.""" - if mode not in self._gw_allowed_modes: - raise PlugwiseError("Plugwise: invalid gateway mode.") + if mode not in self.gw_entities.get(self.gateway_id, {}).get( + "gateway_modes", [] + ): + raise PlugwiseError(f"Plugwise: invalid gateway mode {mode}") end_time = "2037-04-21T08:00:53.000Z" valid = "" @@ -323,8 +326,10 @@ async def set_gateway_mode(self, mode: str) -> None: async def set_regulation_mode(self, mode: str) -> None: """Set the heating regulation mode.""" - if mode not in self._reg_allowed_modes: - raise PlugwiseError("Plugwise: invalid regulation mode.") + if mode not in self.gw_entities.get(self.gateway_id, {}).get( + "regulation_modes", [] + ): + raise PlugwiseError(f"Plugwise: invalid regulation mode {mode}") duration = "" if "bleeding" in mode: @@ -342,7 +347,7 @@ async def set_regulation_mode(self, mode: str) -> None: async def set_zone_profile(self, loc_id: str, profile: str) -> None: """Set the Adam thermoszone heating profile.""" if profile not in ALLOWED_ZONE_PROFILES: - raise PlugwiseError("Plugwise: invalid zone profile.") + raise PlugwiseError(f"Plugwise: invalid zone profile {profile}") data = ( "" @@ -364,7 +369,7 @@ async def set_schedule_state( if state is None: state = STATE_ON elif state not in (STATE_OFF, STATE_ON): - raise PlugwiseError("Plugwise: invalid schedule state.") + raise PlugwiseError(f"Plugwise: invalid schedule state {state}") # Translate selection of Off-schedule-option to disabling the active schedule if name == OFF: @@ -379,7 +384,7 @@ async def set_schedule_state( schedule_rule = self._rule_ids_by_name(name, loc_id) # Raise an error when the schedule name does not exist if not schedule_rule or schedule_rule is None: - raise PlugwiseError("Plugwise: no schedule with this name available.") + raise PlugwiseError(f"Plugwise: no schedule with name {name} available") # If no state change is requested, do nothing if state == self._schedule_old_states[loc_id][name]: @@ -526,7 +531,7 @@ async def set_temperature(self, loc_id: str, items: dict[str, float]) -> None: if setpoint is None: raise PlugwiseError( - "Plugwise: failed setting temperature: no valid input provided" + f"Plugwise: failed setting temperature: setpoint {setpoint} provided" ) # pragma: no cover" temperature = str(setpoint) diff --git a/pyproject.toml b/pyproject.toml index ff158f2fc..cc56b0b0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise" -version = "1.14.5" +version = "1.14.6" license = "MIT" description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3." readme = "README.md"