plugwise 1.6.3__py3-none-any.whl → 1.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plugwise/__init__.py +134 -100
- plugwise/common.py +32 -123
- plugwise/constants.py +6 -16
- plugwise/data.py +60 -37
- plugwise/helper.py +198 -333
- plugwise/legacy/data.py +20 -12
- plugwise/legacy/helper.py +31 -63
- plugwise/legacy/smile.py +64 -60
- plugwise/smile.py +50 -54
- plugwise/smilecomm.py +148 -0
- plugwise/util.py +117 -28
- {plugwise-1.6.3.dist-info → plugwise-1.7.0.dist-info}/METADATA +2 -2
- plugwise-1.7.0.dist-info/RECORD +18 -0
- {plugwise-1.6.3.dist-info → plugwise-1.7.0.dist-info}/WHEEL +1 -1
- plugwise-1.6.3.dist-info/RECORD +0 -17
- {plugwise-1.6.3.dist-info → plugwise-1.7.0.dist-info}/LICENSE +0 -0
- {plugwise-1.6.3.dist-info → plugwise-1.7.0.dist-info}/top_level.txt +0 -0
plugwise/legacy/data.py
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
|
3
3
|
Plugwise Smile protocol data-collection helpers for legacy devices.
|
4
4
|
"""
|
5
|
+
|
5
6
|
from __future__ import annotations
|
6
7
|
|
7
8
|
# Dict as class
|
8
9
|
# Version detection
|
9
|
-
from plugwise.constants import NONE, OFF, GwEntityData
|
10
|
+
from plugwise.constants import NONE, OFF, GwEntityData, SmileProps
|
10
11
|
from plugwise.legacy.helper import SmileLegacyHelper
|
11
12
|
from plugwise.util import remove_empty_platform_dicts
|
12
13
|
|
@@ -16,25 +17,20 @@ class SmileLegacyData(SmileLegacyHelper):
|
|
16
17
|
|
17
18
|
def __init__(self) -> None:
|
18
19
|
"""Init."""
|
20
|
+
self._smile_props: SmileProps
|
19
21
|
SmileLegacyHelper.__init__(self)
|
20
22
|
|
21
23
|
def _all_entity_data(self) -> None:
|
22
24
|
"""Helper-function for get_all_gateway_entities().
|
23
25
|
|
24
|
-
Collect data for each entity and add to self.
|
26
|
+
Collect data for each entity and add to self._smile_props and self.gw_entities.
|
25
27
|
"""
|
26
28
|
self._update_gw_entities()
|
27
|
-
self.
|
28
|
-
|
29
|
-
|
30
|
-
"item_count": self._count,
|
31
|
-
"smile_name": self.smile_name,
|
32
|
-
}
|
33
|
-
)
|
29
|
+
self._smile_props["gateway_id"] = self.gateway_id
|
30
|
+
self._smile_props["item_count"] = self._count
|
31
|
+
self._smile_props["smile_name"] = self.smile_name
|
34
32
|
if self._is_thermostat:
|
35
|
-
self.
|
36
|
-
{"heater_id": self._heater_id, "cooling_present": False}
|
37
|
-
)
|
33
|
+
self._smile_props["heater_id"] = self._heater_id
|
38
34
|
|
39
35
|
def _update_gw_entities(self) -> None:
|
40
36
|
"""Helper-function for _all_entity_data() and async_update().
|
@@ -63,6 +59,7 @@ class SmileLegacyData(SmileLegacyHelper):
|
|
63
59
|
|
64
60
|
# Thermostat data (presets, temperatures etc)
|
65
61
|
self._climate_data(entity, data)
|
62
|
+
self._get_anna_control_state(data)
|
66
63
|
|
67
64
|
return data
|
68
65
|
|
@@ -91,3 +88,14 @@ class SmileLegacyData(SmileLegacyHelper):
|
|
91
88
|
self._count += 1
|
92
89
|
if sel_schedule in (NONE, OFF):
|
93
90
|
data["climate_mode"] = "heat"
|
91
|
+
|
92
|
+
def _get_anna_control_state(self, data: GwEntityData) -> None:
|
93
|
+
"""Set the thermostat control_state based on the opentherm/onoff device state."""
|
94
|
+
data["control_state"] = "idle"
|
95
|
+
for entity in self.gw_entities.values():
|
96
|
+
if entity["dev_class"] != "heater_central":
|
97
|
+
continue
|
98
|
+
|
99
|
+
binary_sensors = entity["binary_sensors"]
|
100
|
+
if binary_sensors["heating_state"]:
|
101
|
+
data["control_state"] = "heating"
|
plugwise/legacy/helper.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
Plugwise Smile protocol helpers.
|
4
4
|
"""
|
5
|
+
|
5
6
|
from __future__ import annotations
|
6
7
|
|
7
8
|
from typing import cast
|
@@ -29,13 +30,14 @@ from plugwise.constants import (
|
|
29
30
|
ActuatorDataType,
|
30
31
|
ActuatorType,
|
31
32
|
ApplianceType,
|
32
|
-
GatewayData,
|
33
33
|
GwEntityData,
|
34
34
|
SensorType,
|
35
35
|
ThermoLoc,
|
36
36
|
)
|
37
37
|
from plugwise.util import (
|
38
|
+
collect_power_values,
|
38
39
|
common_match_cases,
|
40
|
+
count_data_items,
|
39
41
|
format_measure,
|
40
42
|
skip_obsolete_measurements,
|
41
43
|
version_to_model,
|
@@ -62,32 +64,15 @@ class SmileLegacyHelper(SmileCommon):
|
|
62
64
|
def __init__(self) -> None:
|
63
65
|
"""Set the constructor for this class."""
|
64
66
|
self._appliances: etree
|
65
|
-
self._count: int
|
66
|
-
self._domain_objects: etree
|
67
|
-
self._heater_id: str
|
68
|
-
self._home_location: str
|
69
67
|
self._is_thermostat: bool
|
70
|
-
self._last_modified: dict[str, str] = {}
|
71
68
|
self._loc_data: dict[str, ThermoLoc]
|
72
69
|
self._locations: etree
|
73
70
|
self._modules: etree
|
74
|
-
self._notifications: dict[str, dict[str, str]] = {}
|
75
|
-
self._on_off_device: bool
|
76
|
-
self._opentherm_device: bool
|
77
|
-
self._outdoor_temp: float
|
78
|
-
self._status: etree
|
79
71
|
self._stretch_v2: bool
|
80
|
-
self._system: etree
|
81
|
-
|
82
|
-
self.gateway_id: str
|
83
|
-
self.gw_data: GatewayData = {}
|
84
72
|
self.gw_entities: dict[str, GwEntityData] = {}
|
85
|
-
self.smile_fw_version: Version | None
|
86
|
-
self.smile_hw_version: str | None
|
87
73
|
self.smile_mac_address: str | None
|
88
74
|
self.smile_model: str
|
89
|
-
self.
|
90
|
-
self.smile_type: str
|
75
|
+
self.smile_version: Version | None
|
91
76
|
self.smile_zigbee_mac_address: str | None
|
92
77
|
SmileCommon.__init__(self)
|
93
78
|
|
@@ -114,7 +99,7 @@ class SmileLegacyHelper(SmileCommon):
|
|
114
99
|
):
|
115
100
|
continue # pragma: no cover
|
116
101
|
|
117
|
-
appl.location = self.
|
102
|
+
appl.location = self._home_loc_id
|
118
103
|
appl.entity_id = appliance.attrib["id"]
|
119
104
|
appl.name = appliance.find("name").text
|
120
105
|
# Extend device_class name when a Circle/Stealth is type heater_central -- Pw-Beta Issue #739
|
@@ -160,7 +145,7 @@ class SmileLegacyHelper(SmileCommon):
|
|
160
145
|
|
161
146
|
# Legacy Anna without outdoor_temp and Stretches have no locations, create fake location-data
|
162
147
|
if not (locations := self._locations.findall("./location")):
|
163
|
-
self.
|
148
|
+
self._home_loc_id = FAKE_LOC
|
164
149
|
self._loc_data[FAKE_LOC] = {"name": "Home"}
|
165
150
|
return
|
166
151
|
|
@@ -169,18 +154,15 @@ class SmileLegacyHelper(SmileCommon):
|
|
169
154
|
loc.loc_id = location.attrib["id"]
|
170
155
|
# Filter the valid single location for P1 legacy: services not empty
|
171
156
|
locator = "./services"
|
172
|
-
if (
|
173
|
-
self.smile_type == "power"
|
174
|
-
and len(location.find(locator)) == 0
|
175
|
-
):
|
157
|
+
if self.smile_type == "power" and len(location.find(locator)) == 0:
|
176
158
|
continue
|
177
159
|
|
178
160
|
if loc.name == "Home":
|
179
|
-
self.
|
161
|
+
self._home_loc_id = loc.loc_id
|
180
162
|
# Replace location-name for P1 legacy, can contain privacy-related info
|
181
163
|
if self.smile_type == "power":
|
182
164
|
loc.name = "Home"
|
183
|
-
self.
|
165
|
+
self._home_loc_id = loc.loc_id
|
184
166
|
|
185
167
|
self._loc_data[loc.loc_id] = {"name": loc.name}
|
186
168
|
|
@@ -189,15 +171,15 @@ class SmileLegacyHelper(SmileCommon):
|
|
189
171
|
|
190
172
|
Use the home_location or FAKE_APPL as entity id.
|
191
173
|
"""
|
192
|
-
self.gateway_id = self.
|
174
|
+
self.gateway_id = self._home_loc_id
|
193
175
|
if self.smile_type == "power":
|
194
176
|
self.gateway_id = FAKE_APPL
|
195
177
|
|
196
178
|
self.gw_entities[self.gateway_id] = {"dev_class": "gateway"}
|
197
179
|
self._count += 1
|
198
180
|
for key, value in {
|
199
|
-
"firmware": str(self.
|
200
|
-
"location": self.
|
181
|
+
"firmware": str(self.smile_version),
|
182
|
+
"location": self._home_loc_id,
|
201
183
|
"mac_address": self.smile_mac_address,
|
202
184
|
"model": self.smile_model,
|
203
185
|
"name": self.smile_name,
|
@@ -212,15 +194,15 @@ class SmileLegacyHelper(SmileCommon):
|
|
212
194
|
def _appliance_info_finder(self, appliance: etree, appl: Munch) -> Munch:
|
213
195
|
"""Collect entity info (Smile/Stretch, Thermostats, OpenTherm/On-Off): firmware, model and vendor name."""
|
214
196
|
match appl.pwclass:
|
215
|
-
|
197
|
+
# Collect thermostat entity info
|
216
198
|
case _ as dev_class if dev_class in THERMOSTAT_CLASSES:
|
217
199
|
return self._appl_thermostat_info(appl, appliance, self._modules)
|
218
|
-
|
200
|
+
# Collect heater_central entity info
|
219
201
|
case "heater_central":
|
220
202
|
return self._appl_heater_central_info(
|
221
203
|
appl, appliance, True, self._appliances, self._modules
|
222
204
|
) # True means legacy device
|
223
|
-
|
205
|
+
# Collect info from Stretches
|
224
206
|
case _:
|
225
207
|
return self._energy_entity_info_finder(appliance, appl)
|
226
208
|
|
@@ -231,7 +213,9 @@ class SmileLegacyHelper(SmileCommon):
|
|
231
213
|
"""
|
232
214
|
if self.smile_type in ("power", "stretch"):
|
233
215
|
locator = "./services/electricity_point_meter"
|
234
|
-
module_data = self._get_module_data(
|
216
|
+
module_data = self._get_module_data(
|
217
|
+
appliance, locator, self._modules, legacy=True
|
218
|
+
)
|
235
219
|
appl.zigbee_mac = module_data["zigbee_mac_address"]
|
236
220
|
# Filter appliance without zigbee_mac, it's an orphaned device
|
237
221
|
if appl.zigbee_mac is None and self.smile_type != "power":
|
@@ -272,7 +256,7 @@ class SmileLegacyHelper(SmileCommon):
|
|
272
256
|
Collect the appliance-data based on entity_id.
|
273
257
|
"""
|
274
258
|
data: GwEntityData = {"binary_sensors": {}, "sensors": {}, "switches": {}}
|
275
|
-
# Get P1 smartmeter data from
|
259
|
+
# Get P1 smartmeter data from MODULES
|
276
260
|
entity = self.gw_entities[entity_id]
|
277
261
|
# !! DON'T CHANGE below two if-lines, will break stuff !!
|
278
262
|
if self.smile_type == "power":
|
@@ -294,14 +278,13 @@ class SmileLegacyHelper(SmileCommon):
|
|
294
278
|
if appliance.find("type").text in ACTUATOR_CLASSES:
|
295
279
|
self._get_actuator_functionalities(appliance, entity, data)
|
296
280
|
|
297
|
-
#
|
298
|
-
#
|
281
|
+
# Anna: the Smile outdoor_temperature is present in the Home location
|
282
|
+
# For some Anna's LOCATIONS is empty, falling back to domain_objects!
|
299
283
|
if self._is_thermostat and entity_id == self.gateway_id:
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
data.update({"sensors": {"outdoor_temperature": outdoor_temperature}})
|
284
|
+
locator = f"./location[@id='{self._home_loc_id}']/logs/point_log[type='outdoor_temperature']/period/measurement"
|
285
|
+
if (found := self._domain_objects.find(locator)) is not None:
|
286
|
+
value = format_measure(found.text, NONE)
|
287
|
+
data.update({"sensors": {"outdoor_temperature": value}})
|
305
288
|
self._count += 1
|
306
289
|
|
307
290
|
if "c_heating_state" in data:
|
@@ -326,7 +309,7 @@ class SmileLegacyHelper(SmileCommon):
|
|
326
309
|
loc.meas_list = loc.measurement.split("_")
|
327
310
|
for loc.logs in mod_logs:
|
328
311
|
for loc.log_type in mod_list:
|
329
|
-
|
312
|
+
collect_power_values(data, loc, t_string, legacy=True)
|
330
313
|
|
331
314
|
self._count += len(data["sensors"])
|
332
315
|
return data
|
@@ -359,13 +342,10 @@ class SmileLegacyHelper(SmileCommon):
|
|
359
342
|
appl_i_loc.text, ENERGY_WATT_HOUR
|
360
343
|
)
|
361
344
|
|
362
|
-
self.
|
345
|
+
self._count = count_data_items(self._count, data)
|
363
346
|
|
364
347
|
def _get_actuator_functionalities(
|
365
|
-
self,
|
366
|
-
xml: etree,
|
367
|
-
entity: GwEntityData,
|
368
|
-
data: GwEntityData
|
348
|
+
self, xml: etree, entity: GwEntityData, data: GwEntityData
|
369
349
|
) -> None:
|
370
350
|
"""Helper-function for _get_measurement_data()."""
|
371
351
|
for item in ACTIVE_ACTUATORS:
|
@@ -399,20 +379,6 @@ class SmileLegacyHelper(SmileCommon):
|
|
399
379
|
act_item = cast(ActuatorType, item)
|
400
380
|
data[act_item] = temp_dict
|
401
381
|
|
402
|
-
def _object_value(self, obj_id: str, measurement: str) -> float | int | None:
|
403
|
-
"""Helper-function for smile.py: _get_entity_data().
|
404
|
-
|
405
|
-
Obtain the value/state for the given object from a location in DOMAIN_OBJECTS
|
406
|
-
"""
|
407
|
-
val: float | int | None = None
|
408
|
-
search = self._domain_objects
|
409
|
-
locator = f'./location[@id="{obj_id}"]/logs/point_log[type="{measurement}"]/period/measurement'
|
410
|
-
if (found := search.find(locator)) is not None:
|
411
|
-
val = format_measure(found.text, NONE)
|
412
|
-
return val
|
413
|
-
|
414
|
-
return val
|
415
|
-
|
416
382
|
def _preset(self) -> str | None:
|
417
383
|
"""Helper-function for smile.py: _climate_data().
|
418
384
|
|
@@ -458,7 +424,9 @@ class SmileLegacyHelper(SmileCommon):
|
|
458
424
|
active = result.text == "on"
|
459
425
|
|
460
426
|
# Show an empty schedule as no schedule found
|
461
|
-
directives =
|
427
|
+
directives = (
|
428
|
+
search.find(f'./rule[@id="{rule_id}"]/directives/when/then') is not None
|
429
|
+
)
|
462
430
|
if directives and name is not None:
|
463
431
|
available = [name, OFF]
|
464
432
|
selected = name if active else OFF
|
plugwise/legacy/smile.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
Plugwise backend module for Home Assistant Core - covering the legacy P1, Anna, and Stretch devices.
|
4
4
|
"""
|
5
|
+
|
5
6
|
from __future__ import annotations
|
6
7
|
|
7
8
|
from collections.abc import Awaitable, Callable
|
@@ -10,8 +11,6 @@ from typing import Any
|
|
10
11
|
|
11
12
|
from plugwise.constants import (
|
12
13
|
APPLIANCES,
|
13
|
-
DEFAULT_PORT,
|
14
|
-
DEFAULT_USERNAME,
|
15
14
|
DOMAIN_OBJECTS,
|
16
15
|
LOCATIONS,
|
17
16
|
LOGGER,
|
@@ -19,46 +18,40 @@ from plugwise.constants import (
|
|
19
18
|
OFF,
|
20
19
|
REQUIRE_APPLIANCES,
|
21
20
|
RULES,
|
22
|
-
GatewayData,
|
23
21
|
GwEntityData,
|
24
|
-
|
22
|
+
SmileProps,
|
25
23
|
ThermoLoc,
|
26
24
|
)
|
27
|
-
from plugwise.exceptions import ConnectionFailedError, PlugwiseError
|
25
|
+
from plugwise.exceptions import ConnectionFailedError, DataMissingError, PlugwiseError
|
28
26
|
from plugwise.legacy.data import SmileLegacyData
|
29
27
|
|
30
|
-
import aiohttp
|
31
28
|
from munch import Munch
|
32
29
|
from packaging.version import Version
|
33
30
|
|
34
31
|
|
35
32
|
class SmileLegacyAPI(SmileLegacyData):
|
36
|
-
"""The Plugwise SmileLegacyAPI class."""
|
33
|
+
"""The Plugwise SmileLegacyAPI helper class for actual Plugwise legacy devices."""
|
37
34
|
|
38
35
|
# pylint: disable=too-many-instance-attributes, too-many-public-methods
|
39
36
|
|
40
37
|
def __init__(
|
41
38
|
self,
|
42
|
-
host: str,
|
43
|
-
password: str,
|
44
|
-
request: Callable[..., Awaitable[Any]],
|
45
|
-
websession: aiohttp.ClientSession,
|
46
39
|
_is_thermostat: bool,
|
47
40
|
_loc_data: dict[str, ThermoLoc],
|
48
41
|
_on_off_device: bool,
|
49
42
|
_opentherm_device: bool,
|
43
|
+
_request: Callable[..., Awaitable[Any]],
|
44
|
+
_smile_props: SmileProps,
|
50
45
|
_stretch_v2: bool,
|
51
46
|
_target_smile: str,
|
52
|
-
smile_fw_version: Version | None,
|
53
47
|
smile_hostname: str,
|
54
48
|
smile_hw_version: str | None,
|
55
49
|
smile_mac_address: str | None,
|
56
50
|
smile_model: str,
|
57
51
|
smile_name: str,
|
58
52
|
smile_type: str,
|
53
|
+
smile_version: Version | None,
|
59
54
|
smile_zigbee_mac_address: str | None,
|
60
|
-
port: int = DEFAULT_PORT,
|
61
|
-
username: str = DEFAULT_USERNAME,
|
62
55
|
) -> None:
|
63
56
|
"""Set the constructor for this class."""
|
64
57
|
self._cooling_present = False
|
@@ -66,81 +59,86 @@ class SmileLegacyAPI(SmileLegacyData):
|
|
66
59
|
self._loc_data = _loc_data
|
67
60
|
self._on_off_device = _on_off_device
|
68
61
|
self._opentherm_device = _opentherm_device
|
62
|
+
self._request = _request
|
63
|
+
self._smile_props = _smile_props
|
69
64
|
self._stretch_v2 = _stretch_v2
|
70
65
|
self._target_smile = _target_smile
|
71
|
-
self.request = request
|
72
|
-
self.smile_fw_version = smile_fw_version
|
73
66
|
self.smile_hostname = smile_hostname
|
74
67
|
self.smile_hw_version = smile_hw_version
|
75
68
|
self.smile_mac_address = smile_mac_address
|
76
69
|
self.smile_model = smile_model
|
77
70
|
self.smile_name = smile_name
|
78
71
|
self.smile_type = smile_type
|
72
|
+
self.smile_version = smile_version
|
79
73
|
self.smile_zigbee_mac_address = smile_zigbee_mac_address
|
80
74
|
SmileLegacyData.__init__(self)
|
81
75
|
|
76
|
+
self._first_update = True
|
82
77
|
self._previous_day_number: str = "0"
|
83
78
|
|
84
79
|
async def full_xml_update(self) -> None:
|
85
|
-
"""Perform a first fetch of
|
86
|
-
self._domain_objects = await self.
|
87
|
-
self._locations = await self.
|
88
|
-
self._modules = await self.
|
80
|
+
"""Perform a first fetch of the Plugwise server XML data."""
|
81
|
+
self._domain_objects = await self._request(DOMAIN_OBJECTS)
|
82
|
+
self._locations = await self._request(LOCATIONS)
|
83
|
+
self._modules = await self._request(MODULES)
|
89
84
|
# P1 legacy has no appliances
|
90
85
|
if self.smile_type != "power":
|
91
|
-
self._appliances = await self.
|
86
|
+
self._appliances = await self._request(APPLIANCES)
|
92
87
|
|
93
88
|
def get_all_gateway_entities(self) -> None:
|
94
|
-
"""Collect the gateway entities from the received raw XML-data.
|
89
|
+
"""Collect the Plugwise gateway entities and their data and states from the received raw XML-data.
|
95
90
|
|
96
|
-
|
97
|
-
|
91
|
+
First, collect all the connected entities and their initial data.
|
92
|
+
Collect and add switching- and/or pump-group entities.
|
93
|
+
Finally, collect the data and states for each entity.
|
98
94
|
"""
|
99
|
-
# Gather all the devices and their initial data
|
100
95
|
self._all_appliances()
|
101
|
-
|
102
|
-
# Collect and add switching- and/or pump-group devices
|
103
96
|
if group_data := self._get_group_switches():
|
104
97
|
self.gw_entities.update(group_data)
|
105
98
|
|
106
|
-
# Collect the remaining data for all entities
|
107
99
|
self._all_entity_data()
|
108
100
|
|
109
|
-
async def async_update(self) ->
|
110
|
-
"""Perform an
|
111
|
-
|
101
|
+
async def async_update(self) -> dict[str, GwEntityData]:
|
102
|
+
"""Perform an full update update at day-change: re-collect all gateway entities and their data and states.
|
103
|
+
|
104
|
+
Otherwise perform an incremental update: only collect the entities updated data and states.
|
105
|
+
"""
|
112
106
|
day_number = dt.datetime.now().strftime("%w")
|
113
|
-
if
|
114
|
-
day_number # pylint: disable=consider-using-assignment-expr
|
115
|
-
!= self._previous_day_number
|
116
|
-
):
|
107
|
+
if self._first_update or day_number != self._previous_day_number:
|
117
108
|
LOGGER.info(
|
118
109
|
"Performing daily full-update, reload the Plugwise integration when a single entity becomes unavailable."
|
119
110
|
)
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
111
|
+
try:
|
112
|
+
await self.full_xml_update()
|
113
|
+
self.get_all_gateway_entities()
|
114
|
+
# Detect failed data-retrieval
|
115
|
+
_ = self.gw_entities[self.gateway_id]["location"]
|
116
|
+
except KeyError as err: # pragma: no cover
|
117
|
+
raise DataMissingError(
|
118
|
+
"No (full) Plugwise legacy data received"
|
119
|
+
) from err
|
125
120
|
else:
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
self.
|
132
|
-
|
133
|
-
|
134
|
-
|
121
|
+
try:
|
122
|
+
self._domain_objects = await self._request(DOMAIN_OBJECTS)
|
123
|
+
match self._target_smile:
|
124
|
+
case "smile_v2":
|
125
|
+
self._modules = await self._request(MODULES)
|
126
|
+
case self._target_smile if self._target_smile in REQUIRE_APPLIANCES:
|
127
|
+
self._appliances = await self._request(APPLIANCES)
|
128
|
+
|
129
|
+
self._update_gw_entities()
|
130
|
+
# Detect failed data-retrieval
|
131
|
+
_ = self.gw_entities[self.gateway_id]["location"]
|
132
|
+
except KeyError as err: # pragma: no cover
|
133
|
+
raise DataMissingError("No legacy Plugwise data received") from err
|
134
|
+
|
135
|
+
self._first_update = False
|
135
136
|
self._previous_day_number = day_number
|
136
|
-
return
|
137
|
-
devices=self.gw_entities,
|
138
|
-
gateway=self.gw_data,
|
139
|
-
)
|
137
|
+
return self.gw_entities
|
140
138
|
|
141
|
-
########################################################################################################
|
142
|
-
### API Set and HA Service-related Functions ###
|
143
|
-
########################################################################################################
|
139
|
+
########################################################################################################
|
140
|
+
### API Set and HA Service-related Functions ###
|
141
|
+
########################################################################################################
|
144
142
|
|
145
143
|
async def delete_notification(self) -> None:
|
146
144
|
"""Set-function placeholder for legacy devices."""
|
@@ -181,12 +179,16 @@ class SmileLegacyAPI(SmileLegacyData):
|
|
181
179
|
async def set_regulation_mode(self, mode: str) -> None:
|
182
180
|
"""Set-function placeholder for legacy devices."""
|
183
181
|
|
184
|
-
async def set_select(
|
182
|
+
async def set_select(
|
183
|
+
self, key: str, loc_id: str, option: str, state: str | None
|
184
|
+
) -> None:
|
185
185
|
"""Set the thermostat schedule option."""
|
186
186
|
# schedule name corresponds to select option
|
187
187
|
await self.set_schedule_state("dummy", state, option)
|
188
188
|
|
189
|
-
async def set_schedule_state(
|
189
|
+
async def set_schedule_state(
|
190
|
+
self, _: str, state: str | None, name: str | None
|
191
|
+
) -> None:
|
190
192
|
"""Activate/deactivate the Schedule.
|
191
193
|
|
192
194
|
Determined from - DOMAIN_OBJECTS.
|
@@ -205,7 +207,9 @@ class SmileLegacyAPI(SmileLegacyData):
|
|
205
207
|
schedule_rule_id = rule.attrib["id"]
|
206
208
|
|
207
209
|
if schedule_rule_id is None:
|
208
|
-
raise PlugwiseError(
|
210
|
+
raise PlugwiseError(
|
211
|
+
"Plugwise: no schedule with this name available."
|
212
|
+
) # pragma: no cover
|
209
213
|
|
210
214
|
new_state = "false"
|
211
215
|
if state == "on":
|
@@ -290,6 +294,6 @@ class SmileLegacyAPI(SmileLegacyData):
|
|
290
294
|
method: str = kwargs["method"]
|
291
295
|
data: str | None = kwargs.get("data")
|
292
296
|
try:
|
293
|
-
await self.
|
297
|
+
await self._request(uri, method=method, data=data)
|
294
298
|
except ConnectionFailedError as exc:
|
295
299
|
raise ConnectionFailedError from exc
|