Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
15 changes: 10 additions & 5 deletions plugwise/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()."""
Expand Down Expand Up @@ -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:
Expand Down
12 changes: 6 additions & 6 deletions plugwise/legacy/smile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"<rules><rule id='{rule_id}'><active>true</active></rule></rules>"
await self.call_request(RULES, method="put", data=data)
Expand Down Expand Up @@ -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:
Expand All @@ -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"
Expand Down
37 changes: 21 additions & 16 deletions plugwise/smile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand Down Expand Up @@ -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 = (
"<thermostat_functionality>"
Expand All @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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 = ""
Expand Down Expand Up @@ -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:
Expand All @@ -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 = (
"<thermostat_functionality>"
Expand All @@ -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:
Expand All @@ -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]:
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down