Skip to content

Commit 71fdf8a

Browse files
authored
Merge pull request #806 from plugwise/clean_last_active_schedule
Remove storing of last active schedules
2 parents 93233e3 + a4def9f commit 71fdf8a

File tree

7 files changed

+16
-90
lines changed

7 files changed

+16
-90
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## v1.8.3
4+
5+
- Remove storing the last active schedule(s) via PR [#806](https://github.com/plugwise/python-plugwise/pull/806), to be handled by the HA Integration
6+
37
## v1.8.2
48

59
- Add support for Emma Pro wired, rename wireless Emma to Emma Pro via PR [#804](https://github.com/plugwise/python-plugwise/pull/804)

plugwise/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ def __init__(
6767
self._cooling_present = False
6868
self._elga = False
6969
self._is_thermostat = False
70-
self._last_active: dict[str, str | None] = {}
7170
self._loc_data: dict[str, ThermoLoc] = {}
7271
self._on_off_device = False
7372
self._opentherm_device = False
@@ -156,7 +155,6 @@ async def connect(self) -> Version:
156155
self._cooling_present,
157156
self._elga,
158157
self._is_thermostat,
159-
self._last_active,
160158
self._loc_data,
161159
self._on_off_device,
162160
self._opentherm_device,

plugwise/helper.py

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from __future__ import annotations
77

8-
import datetime as dt
98
from typing import cast
109

1110
from plugwise.common import SmileCommon
@@ -50,9 +49,6 @@
5049
skip_obsolete_measurements,
5150
)
5251

53-
# Time related
54-
from dateutil import tz
55-
from dateutil.parser import parse
5652
from defusedxml import ElementTree as etree
5753
from munch import Munch
5854
from packaging import version
@@ -78,7 +74,6 @@ def __init__(self) -> None:
7874
self._endpoint: str
7975
self._elga: bool
8076
self._is_thermostat: bool
81-
self._last_active: dict[str, str | None]
8277
self._loc_data: dict[str, ThermoLoc]
8378
self._schedule_old_states: dict[str, dict[str, str]]
8479
self._gateway_id: str = NONE
@@ -871,7 +866,7 @@ def _rule_ids_by_name(self, name: str, loc_id: str) -> dict[str, dict[str, str]]
871866
return schedule_ids
872867

873868
def _rule_ids_by_tag(self, tag: str, loc_id: str) -> dict[str, dict[str, str]]:
874-
"""Helper-function for _presets(), _schedules() and _last_active_schedule().
869+
"""Helper-function for _presets() and _schedules().
875870
876871
Obtain the rule_id from the given template_tag and provide the location_id, when present.
877872
"""
@@ -906,11 +901,6 @@ def _schedules(self, location: str) -> tuple[list[str], str]:
906901
available: list[str] = [NONE]
907902
rule_ids: dict[str, dict[str, str]] = {}
908903
selected = NONE
909-
# Adam schedules, one schedule can be linked to various locations
910-
# self._last_active contains the locations and the active schedule name per location, or None
911-
if location not in self._last_active:
912-
self._last_active[location] = None
913-
914904
tag = "zone_preset_based_on_time_and_presence_with_override"
915905
if not (rule_ids := self._rule_ids_by_tag(tag, location)):
916906
return available, selected
@@ -927,34 +917,16 @@ def _schedules(self, location: str) -> tuple[list[str], str]:
927917
available.append(name)
928918
if location == data["location"] and active:
929919
selected = name
930-
self._last_active[location] = selected
931920
schedules.append(name)
932921

933922
if schedules:
934923
available.remove(NONE)
935924
available.append(OFF)
936925
if selected == NONE:
937926
selected = OFF
938-
if self._last_active.get(location) is None:
939-
self._last_active[location] = self._last_used_schedule(schedules)
940-
941-
return available, selected
942927

943-
def _last_used_schedule(self, schedules: list[str]) -> str:
944-
"""Helper-function for _schedules().
945928

946-
Determine the last-used schedule based on the modified date.
947-
"""
948-
epoch = dt.datetime(1970, 1, 1, tzinfo=tz.tzutc())
949-
schedules_dates: dict[str, float] = {}
950-
951-
for name in schedules:
952-
result = self._domain_objects.find(f'./rule[name="{name}"]')
953-
schedule_date = result.find("modified_date").text
954-
schedule_time = parse(schedule_date)
955-
schedules_dates[name] = (schedule_time - epoch).total_seconds()
956-
957-
return sorted(schedules_dates.items(), key=lambda kv: kv[1])[-1][0]
929+
return available, selected
958930

959931
def _thermostat_uri(self, loc_id: str) -> str:
960932
"""Helper-function for smile.py: set_temperature().

plugwise/smile.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ def __init__(
6868
_cooling_present: bool,
6969
_elga: bool,
7070
_is_thermostat: bool,
71-
_last_active: dict[str, str | None],
7271
_loc_data: dict[str, ThermoLoc],
7372
_on_off_device: bool,
7473
_opentherm_device: bool,
@@ -81,7 +80,6 @@ def __init__(
8180
self._cooling_present = _cooling_present
8281
self._elga = _elga
8382
self._is_thermostat = _is_thermostat
84-
self._last_active = _last_active
8583
self._loc_data = _loc_data
8684
self._on_off_device = _on_off_device
8785
self._opentherm_device = _opentherm_device
@@ -325,14 +323,12 @@ async def set_schedule_state(
325323
if name == OFF:
326324
new_state = STATE_OFF
327325

328-
# Handle no schedule-name / Off-schedule provided
326+
# Handle no schedule-name / schedule-off requested: find the active schedule
329327
if name is None or name == OFF:
330-
if schedule_name := self._last_active[loc_id]:
331-
name = schedule_name
332-
else:
328+
_, name = self._schedules(loc_id)
329+
if name == OFF: # no active schedule found, nothing to do
333330
return
334331

335-
assert isinstance(name, str)
336332
schedule_rule = self._rule_ids_by_name(name, loc_id)
337333
# Raise an error when the schedule name does not exist
338334
if not schedule_rule or schedule_rule is None:
@@ -351,7 +347,7 @@ async def set_schedule_state(
351347
template_id = self._domain_objects.find(locator).attrib["id"]
352348
template = f'<template id="{template_id}" />'
353349

354-
contexts = self.determine_contexts(loc_id, name, new_state, schedule_rule_id)
350+
contexts = self.determine_contexts(loc_id, new_state, schedule_rule_id)
355351
data = (
356352
"<rules>"
357353
f"<rule id='{schedule_rule_id}'>"
@@ -366,7 +362,7 @@ async def set_schedule_state(
366362
self._schedule_old_states[loc_id][name] = new_state
367363

368364
def determine_contexts(
369-
self, loc_id: str, name: str, state: str, sched_id: str
365+
self, loc_id: str, state: str, sched_id: str
370366
) -> str:
371367
"""Helper-function for set_schedule_state()."""
372368
locator = f'.//*[@id="{sched_id}"]/contexts'
@@ -377,7 +373,6 @@ def determine_contexts(
377373
subject = etree.fromstring(subject)
378374

379375
if state == STATE_OFF:
380-
self._last_active[loc_id] = name
381376
contexts.remove(subject)
382377
if state == STATE_ON:
383378
contexts.append(subject)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "plugwise"
7-
version = "1.8.2"
7+
version = "1.8.3"
88
license = "MIT"
99
description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3."
1010
readme = "README.md"

tests/test_adam.py

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ async def test_connect_adam_plus_anna_new(self):
3434

3535
await self.device_test(api, "2025-10-12 00:00:01", testdata)
3636
assert api.gateway_id == "da224107914542988a88561b4452b0f6"
37-
assert api._last_active["f2bf9048bef64cc5b6d5110154e33c81"] == "Weekschema"
38-
assert (
39-
api._last_active["f871b8c4d63549319221e294e4f88074"] == "Weekschema"
40-
) # Badkamer
4137
assert self.entity_items == 216
4238
assert self.entity_list == [
4339
"da224107914542988a88561b4452b0f6",
@@ -216,11 +212,6 @@ async def test_connect_adam_zone_per_device(self):
216212

217213
await self.device_test(api, "2022-05-16 00:00:01", testdata)
218214
assert api.gateway_id == "fe799307f1624099878210aa0b9f1475"
219-
assert api._last_active["12493538af164a409c6a1c79e38afe1c"] == BADKAMER_SCHEMA
220-
assert api._last_active["c50f167537524366a5af7aa3942feb1e"] == GF7_WOONKAMER
221-
assert api._last_active["82fa13f017d240daa0d0ea1775420f24"] == CV_JESSIE
222-
assert api._last_active["08963fec7c53423ca5680aa4cb502c63"] == BADKAMER_SCHEMA
223-
assert api._last_active["446ac08dd04d4eff8ac57489757b7314"] == BADKAMER_SCHEMA
224215
assert self.entity_items == 379
225216

226217
assert "af82e4ccf9c548528166d38e560662a4" in self.notifications
@@ -294,11 +285,6 @@ async def test_connect_adam_multiple_devices_per_zone(self):
294285
)
295286

296287
await self.device_test(api, "2022-05-16 00:00:01", testdata)
297-
assert api._last_active["12493538af164a409c6a1c79e38afe1c"] == BADKAMER_SCHEMA
298-
assert api._last_active["c50f167537524366a5af7aa3942feb1e"] == GF7_WOONKAMER
299-
assert api._last_active["82fa13f017d240daa0d0ea1775420f24"] == CV_JESSIE
300-
assert api._last_active["08963fec7c53423ca5680aa4cb502c63"] == BADKAMER_SCHEMA
301-
assert api._last_active["446ac08dd04d4eff8ac57489757b7314"] == BADKAMER_SCHEMA
302288
assert self.entity_items == 385
303289

304290
assert "af82e4ccf9c548528166d38e560662a4" in self.notifications
@@ -335,16 +321,6 @@ async def test_adam_heatpump_cooling(self):
335321
server, api, client = await self.connect_wrapper()
336322

337323
await self.device_test(api, "2022-01-02 00:00:01", testdata)
338-
assert api._last_active["b52908550469425b812c87f766fe5303"] == WERKDAG_SCHEMA
339-
assert api._last_active["20e735858f8146cead98b873177a4f99"] == WERKDAG_SCHEMA
340-
assert api._last_active["e39529c79ab54fda9bed26cfc0447546"] == WERKDAG_SCHEMA
341-
assert api._last_active["9a27714b970547ee9a6bdadc2b815ad5"] == WERKDAG_SCHEMA
342-
assert api._last_active["93ac3f7bf25342f58cbb77c4a99ac0b3"] == WERKDAG_SCHEMA
343-
assert api._last_active["fa5fa6b34f6b40a0972988b20e888ed4"] == WERKDAG_SCHEMA
344-
assert api._last_active["04b15f6e884448288f811d29fb7b1b30"] == WERKDAG_SCHEMA
345-
assert api._last_active["a562019b0b1f47a4bde8ebe3dbe3e8a9"] == WERKDAG_SCHEMA
346-
assert api._last_active["8cf650a4c10c44819e426bed406aec34"] == WERKDAG_SCHEMA
347-
assert api._last_active["5cc21042f87f4b4c94ccb5537c47a53f"] == WERKDAG_SCHEMA
348324
assert self.entity_items == 518
349325
assert self.cooling_present
350326
assert self._cooling_enabled
@@ -392,7 +368,6 @@ async def test_connect_adam_plus_anna(self):
392368

393369
await self.device_test(api, "2020-03-22 00:00:01", testdata)
394370
assert api.gateway_id == "b128b4bbbd1f47e9bf4d756e8fb5ee94"
395-
assert api._last_active["009490cc2f674ce6b576863fbb64f867"] == "Weekschema"
396371
assert self.entity_items == 82
397372
assert "6fb89e35caeb4b1cb275184895202d84" in self.notifications
398373

@@ -433,10 +408,6 @@ async def test_adam_plus_jip(self):
433408

434409
await self.device_test(api, "2021-06-20 00:00:01", testdata)
435410
assert api.gateway_id == "b5c2386c6f6342669e50fe49dd05b188"
436-
assert api._last_active["d58fec52899f4f1c92e4f8fad6d8c48c"] is None
437-
assert api._last_active["06aecb3d00354375924f50c47af36bd2"] is None
438-
assert api._last_active["d27aede973b54be484f6842d1b2802ad"] is None
439-
assert api._last_active["13228dab8ce04617af318a2888b3c548"] is None
440411
assert self.entity_items == 261
441412

442413
# Negative test

tests/test_anna.py

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ async def test_connect_anna_v4(self):
2929

3030
await self.device_test(api, "2020-04-05 00:00:01", testdata)
3131
assert api.gateway_id == "0466eae8520144c78afb29628384edeb"
32-
assert api._last_active["eb5309212bf5407bb143e5bfa3b18aee"] == "Standaard"
3332
assert self.entity_items == 60
3433
assert not self.notifications
3534

@@ -102,7 +101,6 @@ async def test_connect_anna_v4_dhw(self):
102101
)
103102

104103
await self.device_test(api, "2020-04-05 00:00:01", testdata)
105-
assert api._last_active["eb5309212bf5407bb143e5bfa3b18aee"] == "Standaard"
106104
assert self.entity_items == 60
107105
assert not self.notifications
108106

@@ -160,7 +158,6 @@ async def test_connect_anna_without_boiler_fw441(self):
160158
)
161159

162160
await self.device_test(api, "2022-05-16 00:00:01", testdata)
163-
assert api._last_active["c34c6864216446528e95d88985e714cc"] == "Normaal"
164161
assert self.entity_items == 41
165162
assert not self.notifications
166163

@@ -189,7 +186,6 @@ async def test_connect_anna_heatpump_heating(self):
189186

190187
await self.device_test(api, "2020-04-12 00:00:01", testdata)
191188
assert api.gateway_id == "015ae9ea3f964e668e490fa39da3870b"
192-
assert api._last_active["c784ee9fdab44e1395b8dee7d7a497d5"] == "standaard"
193189
assert self.entity_items == 69
194190
assert not self.notifications
195191
assert self.cooling_present
@@ -245,7 +241,6 @@ async def test_connect_anna_heatpump_cooling(self):
245241
)
246242

247243
await self.device_test(api, "2020-04-19 00:00:01", testdata)
248-
assert api._last_active["c784ee9fdab44e1395b8dee7d7a497d5"] == "standaard"
249244
assert self.entity_items == 66
250245
assert self.cooling_present
251246
assert not self.notifications
@@ -318,7 +313,6 @@ async def test_connect_anna_elga_no_cooling(self):
318313

319314
await self.device_test(api, "2020-04-12 00:00:01", testdata)
320315
assert api.gateway_id == "015ae9ea3f964e668e490fa39da3870b"
321-
assert api._last_active["c784ee9fdab44e1395b8dee7d7a497d5"] == "standaard"
322316
assert self.entity_items == 65
323317
assert not self.notifications
324318
assert not self.cooling_present
@@ -342,9 +336,6 @@ async def test_connect_anna_elga_2(self):
342336
)
343337

344338
await self.device_test(api, "2022-03-13 00:00:01", testdata)
345-
assert (
346-
api._last_active["d3ce834534114348be628b61b26d9220"] == THERMOSTAT_SCHEDULE
347-
)
348339
assert self.entity_items == 61
349340
assert api.gateway_id == "fb49af122f6e4b0f91267e1cf7666d6f"
350341
assert self.cooling_present
@@ -364,13 +355,13 @@ async def test_connect_anna_elga_2_schedule_off(self):
364355
assert api.smile.hostname == "smile000000"
365356

366357
await self.device_test(api, "2022-03-13 00:00:01", testdata)
367-
assert (
368-
api._last_active["d3ce834534114348be628b61b26d9220"] == THERMOSTAT_SCHEDULE
369-
)
370-
assert self.cooling_present
371358
assert not self._cooling_enabled
372359
assert self.entity_items == 65
373360

361+
result = await self.tinker_thermostat(
362+
api, "d3ce834534114348be628b61b26d9220", good_schedules=["Thermostat schedule", "off"]
363+
)
364+
assert result
374365
await api.close_connection()
375366
await self.disconnect(server, client)
376367

@@ -394,9 +385,6 @@ async def test_connect_anna_elga_2_cooling(self):
394385
)
395386

396387
await self.device_test(api, "2022-03-10 00:00:01", testdata)
397-
assert (
398-
api._last_active["d3ce834534114348be628b61b26d9220"] == THERMOSTAT_SCHEDULE
399-
)
400388
assert self.entity_items == 65
401389
assert not self.notifications
402390

@@ -450,7 +438,6 @@ async def test_connect_anna_loria_heating_idle(self):
450438
)
451439

452440
await self.device_test(api, "2022-05-16 00:00:01", testdata)
453-
assert api._last_active["15da035090b847e7a21f93e08c015ebc"] == "Winter"
454441
assert self.entity_items == 68
455442
assert self.cooling_present
456443
assert not self._cooling_enabled
@@ -516,7 +503,6 @@ async def test_connect_anna_loria_cooling_active(self):
516503
)
517504

518505
await self.device_test(api, "2022-05-16 00:00:01", testdata)
519-
assert api._last_active["15da035090b847e7a21f93e08c015ebc"] == "Winter"
520506
assert self.entity_items == 68
521507
assert self.cooling_present
522508
assert self._cooling_enabled

0 commit comments

Comments
 (0)