diff --git a/CHANGELOG.md b/CHANGELOG.md
index 51ead928c..b582165fa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog
+## v0.36.3
+
+- Bugfixes for [#558](https://github.com/plugwise/plugwise-beta/issues/558) and [#559](https://github.com/plugwise/plugwise-beta/issues/559).
+
## v0.36.2
- Improve support for Anna+Elga systems that do not support cooling (fix for [#547](https://github.com/plugwise/plugwise-beta/issues/547)).
diff --git a/plugwise/__init__.py b/plugwise/__init__.py
index 2b292fb30..e1d96e0de 100644
--- a/plugwise/__init__.py
+++ b/plugwise/__init__.py
@@ -871,20 +871,20 @@ async def set_gateway_mode(self, mode: str) -> None:
if mode not in self._gw_allowed_modes:
raise PlugwiseError("Plugwise: invalid gateway mode.")
- time_1 = dt.datetime.now(dt.UTC)
- away_time = time_1.isoformat(timespec="milliseconds") + "Z"
- time_2 = str(dt.date.today() - dt.timedelta(1))
- vacation_time = time_2 + "T23:00:00.000Z"
end_time = "2037-04-21T08:00:53.000Z"
valid = ""
if mode == "away":
+ time_1 = self._domain_objects.find("./gateway/time").text
+ away_time = dt.datetime.fromisoformat(time_1).astimezone(dt.UTC).isoformat(timespec="milliseconds").replace("+00:00", "Z")
valid = (
f"{away_time}{end_time}"
)
if mode == "vacation":
+ time_2 = str(dt.date.today() - dt.timedelta(1))
+ vacation_time = time_2 + "T23:00:00.000Z"
valid = f"{vacation_time}{end_time}"
- uri = f"{APPLIANCES};type=gateway/gateway_mode_control"
+ uri = f"{APPLIANCES};id={self.gateway_id}/gateway_mode_control"
data = f"{mode}{valid}"
await self._request(uri, method="put", data=data)
diff --git a/plugwise/helper.py b/plugwise/helper.py
index 0f773bf2b..6e8a6bf8b 100644
--- a/plugwise/helper.py
+++ b/plugwise/helper.py
@@ -751,6 +751,7 @@ def _presets(self, loc_id: str) -> dict[str, list[float]]:
return self._presets_legacy()
if not (rule_ids := self._rule_ids_by_tag(tag_1, loc_id)):
+ rule_ids = None
if not (rule_ids := self._rule_ids_by_name(tag_2, loc_id)):
return presets # pragma: no cover
@@ -767,35 +768,38 @@ def _presets(self, loc_id: str) -> dict[str, list[float]]:
return presets
- def _rule_ids_by_name(self, name: str, loc_id: str) -> dict[str, str]:
+ def _rule_ids_by_name(self, name: str, loc_id: str) -> dict[str, dict[str, str]]:
"""Helper-function for _presets().
Obtain the rule_id from the given name and and provide the location_id, when present.
"""
- schedule_ids: dict[str, str] = {}
+ schedule_ids: dict[str, dict[str, str]] = {}
locator = f'./contexts/context/zone/location[@id="{loc_id}"]'
for rule in self._domain_objects.findall(f'./rule[name="{name}"]'):
+ active = rule.find("active").text
if rule.find(locator) is not None:
- schedule_ids[rule.attrib["id"]] = loc_id
+ schedule_ids[rule.attrib["id"]] = {"location": loc_id, "name": name, "active": active}
else:
- schedule_ids[rule.attrib["id"]] = NONE
+ schedule_ids[rule.attrib["id"]] = {"location": NONE, "name": name, "active": active}
return schedule_ids
- def _rule_ids_by_tag(self, tag: str, loc_id: str) -> dict[str, str]:
+ def _rule_ids_by_tag(self, tag: str, loc_id: str) -> dict[str, dict[str, str]]:
"""Helper-function for _presets(), _schedules() and _last_active_schedule().
Obtain the rule_id from the given template_tag and provide the location_id, when present.
"""
- schedule_ids: dict[str, str] = {}
+ schedule_ids: dict[str, dict[str, str]] = {}
locator1 = f'./template[@tag="{tag}"]'
locator2 = f'./contexts/context/zone/location[@id="{loc_id}"]'
for rule in self._domain_objects.findall("./rule"):
if rule.find(locator1) is not None:
+ name = rule.find("name").text
+ active = rule.find("active").text
if rule.find(locator2) is not None:
- schedule_ids[rule.attrib["id"]] = loc_id
+ schedule_ids[rule.attrib["id"]] = {"location": loc_id, "name": name, "active": active}
else:
- schedule_ids[rule.attrib["id"]] = NONE
+ schedule_ids[rule.attrib["id"]] = {"location": NONE, "name": name, "active": active}
return schedule_ids
@@ -1478,7 +1482,7 @@ def _schedules(self, location: str) -> tuple[list[str], str]:
NEW: when a location_id is present then the schedule is active. Valid for both Adam and non-legacy Anna.
"""
available: list[str] = [NONE]
- rule_ids: dict[str, str] = {}
+ rule_ids: dict[str, dict[str, str]] = {}
selected = NONE
# Legacy Anna schedule, only one schedule allowed
@@ -1495,15 +1499,16 @@ def _schedules(self, location: str) -> tuple[list[str], str]:
return available, selected
schedules: list[str] = []
- for rule_id, loc_id in rule_ids.items():
- name = self._domain_objects.find(f'./rule[@id="{rule_id}"]/name').text
+ for rule_id, data in rule_ids.items():
+ active = data["active"] == "true"
+ name = data["name"]
locator = f'./rule[@id="{rule_id}"]/directives'
# Show an empty schedule as no schedule found
if self._domain_objects.find(locator) is None:
continue # pragma: no cover
available.append(name)
- if location == loc_id:
+ if location == data["location"] and active:
selected = name
self._last_active[location] = selected
schedules.append(name)
diff --git a/pyproject.toml b/pyproject.toml
index 483206e0e..e4e245d86 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "plugwise"
-version = "0.36.2"
+version = "0.36.3"
license = {file = "LICENSE"}
description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3."
readme = "README.md"