plugwise 0.38.0__py3-none-any.whl → 0.38.1__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 +43 -12
- plugwise/helper.py +41 -41
- plugwise/legacy/smile.py +16 -6
- plugwise/smile.py +19 -18
- {plugwise-0.38.0.dist-info → plugwise-0.38.1.dist-info}/METADATA +1 -1
- {plugwise-0.38.0.dist-info → plugwise-0.38.1.dist-info}/RECORD +9 -9
- {plugwise-0.38.0.dist-info → plugwise-0.38.1.dist-info}/LICENSE +0 -0
- {plugwise-0.38.0.dist-info → plugwise-0.38.1.dist-info}/WHEEL +0 -0
- {plugwise-0.38.0.dist-info → plugwise-0.38.1.dist-info}/top_level.txt +0 -0
plugwise/__init__.py
CHANGED
@@ -324,7 +324,10 @@ class Smile(SmileComm):
|
|
324
324
|
state: str | None = None,
|
325
325
|
) -> None:
|
326
326
|
"""Set the selected option for the applicable Select."""
|
327
|
-
|
327
|
+
try:
|
328
|
+
await self._smile_api.set_select(key, loc_id, option, state)
|
329
|
+
except ConnectionFailedError as exc:
|
330
|
+
raise ConnectionFailedError(f"Failed to set select option '{option}': {str(exc)}") from exc
|
328
331
|
|
329
332
|
async def set_schedule_state(
|
330
333
|
self,
|
@@ -333,15 +336,25 @@ class Smile(SmileComm):
|
|
333
336
|
name: str | None = None,
|
334
337
|
) -> None:
|
335
338
|
"""Activate/deactivate the Schedule, with the given name, on the relevant Thermostat."""
|
336
|
-
|
339
|
+
try:
|
340
|
+
await self._smile_api.set_schedule_state(loc_id, state, name)
|
341
|
+
except ConnectionFailedError as exc: # pragma no cover
|
342
|
+
raise ConnectionFailedError(f"Failed to set schedule state: {str(exc)}") from exc # pragma no cover
|
343
|
+
|
337
344
|
|
338
345
|
async def set_preset(self, loc_id: str, preset: str) -> None:
|
339
346
|
"""Set the given Preset on the relevant Thermostat."""
|
340
|
-
|
347
|
+
try:
|
348
|
+
await self._smile_api.set_preset(loc_id, preset)
|
349
|
+
except ConnectionFailedError as exc:
|
350
|
+
raise ConnectionFailedError(f"Failed to set preset: {str(exc)}") from exc
|
341
351
|
|
342
352
|
async def set_temperature(self, loc_id: str, items: dict[str, float]) -> None:
|
343
353
|
"""Set the given Temperature on the relevant Thermostat."""
|
344
|
-
|
354
|
+
try:
|
355
|
+
await self._smile_api.set_temperature(loc_id, items)
|
356
|
+
except ConnectionFailedError as exc:
|
357
|
+
raise ConnectionFailedError(f"Failed to set temperature: {str(exc)}") from exc
|
345
358
|
|
346
359
|
async def set_number(
|
347
360
|
self,
|
@@ -350,40 +363,58 @@ class Smile(SmileComm):
|
|
350
363
|
temperature: float,
|
351
364
|
) -> None:
|
352
365
|
"""Set the maximum boiler- or DHW-setpoint on the Central Heating boiler or the temperature-offset on a Thermostat."""
|
353
|
-
|
366
|
+
try:
|
367
|
+
await self._smile_api.set_number(dev_id, key, temperature)
|
368
|
+
except ConnectionFailedError as exc:
|
369
|
+
raise ConnectionFailedError(f"Failed to set number '{key}': {str(exc)}") from exc
|
354
370
|
|
355
371
|
async def set_temperature_offset(self, dev_id: str, offset: float) -> None:
|
356
372
|
"""Set the Temperature offset for thermostats that support this feature."""
|
357
|
-
|
373
|
+
try: # pragma no cover
|
374
|
+
await self._smile_api.set_offset(dev_id, offset) # pragma: no cover
|
375
|
+
except ConnectionFailedError as exc: # pragma no cover
|
376
|
+
raise ConnectionFailedError(f"Failed to set temperature offset: {str(exc)}") from exc # pragma no cover
|
358
377
|
|
359
378
|
async def set_switch_state(
|
360
379
|
self, appl_id: str, members: list[str] | None, model: str, state: str
|
361
380
|
) -> None:
|
362
381
|
"""Set the given State of the relevant Switch."""
|
363
|
-
|
382
|
+
try:
|
383
|
+
await self._smile_api.set_switch_state(appl_id, members, model, state)
|
384
|
+
except ConnectionFailedError as exc:
|
385
|
+
raise ConnectionFailedError(f"Failed to set switch state: {str(exc)}") from exc
|
364
386
|
|
365
387
|
async def set_gateway_mode(self, mode: str) -> None:
|
366
388
|
"""Set the gateway mode."""
|
367
|
-
|
389
|
+
try: # pragma no cover
|
390
|
+
await self._smile_api.set_gateway_mode(mode) # pragma: no cover
|
391
|
+
except ConnectionFailedError as exc: # pragma no cover
|
392
|
+
raise ConnectionFailedError(f"Failed to set gateway mode: {str(exc)}") from exc # pragma no cover
|
368
393
|
|
369
394
|
async def set_regulation_mode(self, mode: str) -> None:
|
370
395
|
"""Set the heating regulation mode."""
|
371
|
-
|
396
|
+
try: # pragma no cover
|
397
|
+
await self._smile_api.set_regulation_mode(mode) # pragma: no cover
|
398
|
+
except ConnectionFailedError as exc: # pragma no cover
|
399
|
+
raise ConnectionFailedError(f"Failed to set regulation mode: {str(exc)}") from exc # pragma no cover
|
372
400
|
|
373
401
|
async def set_dhw_mode(self, mode: str) -> None:
|
374
402
|
"""Set the domestic hot water heating regulation mode."""
|
375
|
-
|
403
|
+
try: # pragma no cover
|
404
|
+
await self._smile_api.set_dhw_mode(mode) # pragma: no cover
|
405
|
+
except ConnectionFailedError as exc: # pragma no cover
|
406
|
+
raise ConnectionFailedError(f"Failed to set dhw mode: {str(exc)}") from exc # pragma no cover
|
376
407
|
|
377
408
|
async def delete_notification(self) -> None:
|
378
409
|
"""Delete the active Plugwise Notification."""
|
379
410
|
try:
|
380
411
|
await self._smile_api.delete_notification()
|
381
412
|
except ConnectionFailedError as exc:
|
382
|
-
raise
|
413
|
+
raise ConnectionFailedError(f"Failed to delete notification: {str(exc)}") from exc
|
383
414
|
|
384
415
|
async def reboot_gateway(self) -> None:
|
385
416
|
"""Reboot the Plugwise Gateway."""
|
386
417
|
try:
|
387
418
|
await self._smile_api.reboot_gateway()
|
388
419
|
except ConnectionFailedError as exc:
|
389
|
-
raise
|
420
|
+
raise ConnectionFailedError(f"Failed to reboot gateway: {str(exc)}") from exc
|
plugwise/helper.py
CHANGED
@@ -115,30 +115,31 @@ class SmileComm:
|
|
115
115
|
use_headers = headers
|
116
116
|
|
117
117
|
try:
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
118
|
+
match method:
|
119
|
+
case "delete":
|
120
|
+
resp = await self._websession.delete(url, auth=self._auth)
|
121
|
+
case "get":
|
122
|
+
# Work-around for Stretchv2, should not hurt the other smiles
|
123
|
+
use_headers = {"Accept-Encoding": "gzip"}
|
124
|
+
resp = await self._websession.get(
|
125
|
+
url, headers=use_headers, auth=self._auth
|
126
|
+
)
|
127
|
+
case "post":
|
128
|
+
use_headers = {"Content-type": "text/xml"}
|
129
|
+
resp = await self._websession.post(
|
130
|
+
url,
|
131
|
+
headers=use_headers,
|
132
|
+
data=data,
|
133
|
+
auth=self._auth,
|
134
|
+
)
|
135
|
+
case "put":
|
136
|
+
use_headers = {"Content-type": "text/xml"}
|
137
|
+
resp = await self._websession.put(
|
138
|
+
url,
|
139
|
+
headers=use_headers,
|
140
|
+
data=data,
|
141
|
+
auth=self._auth,
|
142
|
+
)
|
142
143
|
except (
|
143
144
|
ClientError
|
144
145
|
) as exc: # ClientError is an ancestor class of ServerTimeoutError
|
@@ -167,23 +168,22 @@ class SmileComm:
|
|
167
168
|
|
168
169
|
async def _request_validate(self, resp: ClientResponse, method: str) -> etree:
|
169
170
|
"""Helper-function for _request(): validate the returned data."""
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
raise ConnectionFailedError
|
171
|
+
match resp.status:
|
172
|
+
case 200:
|
173
|
+
# Cornercases for server not responding with 202
|
174
|
+
if method in ("post", "put"):
|
175
|
+
return
|
176
|
+
case 202:
|
177
|
+
# Command accepted gives empty body with status 202
|
178
|
+
return
|
179
|
+
case 401:
|
180
|
+
msg = "Invalid Plugwise login, please retry with the correct credentials."
|
181
|
+
LOGGER.error("%s", msg)
|
182
|
+
raise InvalidAuthentication
|
183
|
+
case 405:
|
184
|
+
msg = "405 Method not allowed."
|
185
|
+
LOGGER.error("%s", msg)
|
186
|
+
raise ConnectionFailedError
|
187
187
|
|
188
188
|
if not (result := await resp.text()) or (
|
189
189
|
"<error>" in result and "Not started" not in result
|
plugwise/legacy/smile.py
CHANGED
@@ -5,6 +5,7 @@ Plugwise backend module for Home Assistant Core - covering the legacy P1, Anna,
|
|
5
5
|
from __future__ import annotations
|
6
6
|
|
7
7
|
import datetime as dt
|
8
|
+
from typing import Any
|
8
9
|
|
9
10
|
from plugwise.constants import (
|
10
11
|
APPLIANCES,
|
@@ -23,7 +24,7 @@ from plugwise.constants import (
|
|
23
24
|
PlugwiseData,
|
24
25
|
ThermoLoc,
|
25
26
|
)
|
26
|
-
from plugwise.exceptions import PlugwiseError
|
27
|
+
from plugwise.exceptions import ConnectionFailedError, PlugwiseError
|
27
28
|
from plugwise.helper import SmileComm
|
28
29
|
from plugwise.legacy.data import SmileLegacyData
|
29
30
|
|
@@ -180,7 +181,7 @@ class SmileLegacyAPI(SmileComm, SmileLegacyData):
|
|
180
181
|
rule = self._domain_objects.find(locator)
|
181
182
|
data = f'<rules><rule id="{rule.attrib["id"]}"><active>true</active></rule></rules>'
|
182
183
|
|
183
|
-
await self.
|
184
|
+
await self.call_request(RULES, method="put", data=data)
|
184
185
|
|
185
186
|
async def set_regulation_mode(self, mode: str) -> None:
|
186
187
|
"""Set-function placeholder for legacy devices."""
|
@@ -226,7 +227,7 @@ class SmileLegacyAPI(SmileComm, SmileLegacyData):
|
|
226
227
|
f' id="{template_id}" /><active>{new_state}</active></rule></rules>'
|
227
228
|
)
|
228
229
|
|
229
|
-
await self.
|
230
|
+
await self.call_request(uri, method="put", data=data)
|
230
231
|
|
231
232
|
async def set_switch_state(
|
232
233
|
self, appl_id: str, members: list[str] | None, model: str, state: str
|
@@ -254,7 +255,7 @@ class SmileLegacyAPI(SmileComm, SmileLegacyData):
|
|
254
255
|
if self._appliances.find(locator).text == "true":
|
255
256
|
raise PlugwiseError("Plugwise: the locked Relay was not switched.")
|
256
257
|
|
257
|
-
await self.
|
258
|
+
await self.call_request(uri, method="put", data=data)
|
258
259
|
|
259
260
|
async def _set_groupswitch_member_state(
|
260
261
|
self, members: list[str], state: str, switch: Munch
|
@@ -267,7 +268,7 @@ class SmileLegacyAPI(SmileComm, SmileLegacyData):
|
|
267
268
|
uri = f"{APPLIANCES};id={member}/{switch.func_type}"
|
268
269
|
data = f"<{switch.func_type}><{switch.func}>{state}</{switch.func}></{switch.func_type}>"
|
269
270
|
|
270
|
-
await self.
|
271
|
+
await self.call_request(uri, method="put", data=data)
|
271
272
|
|
272
273
|
async def set_temperature(self, _: str, items: dict[str, float]) -> None:
|
273
274
|
"""Set the given Temperature on the relevant Thermostat."""
|
@@ -287,4 +288,13 @@ class SmileLegacyAPI(SmileComm, SmileLegacyData):
|
|
287
288
|
f"{temperature}</setpoint></thermostat_functionality>"
|
288
289
|
)
|
289
290
|
|
290
|
-
await self.
|
291
|
+
await self.call_request(uri, method="put", data=data)
|
292
|
+
|
293
|
+
async def call_request(self, uri: str, **kwargs: Any) -> None:
|
294
|
+
"""ConnectionFailedError wrapper for calling _request()."""
|
295
|
+
method: str = kwargs["method"]
|
296
|
+
data: str | None = kwargs.get("data")
|
297
|
+
try:
|
298
|
+
await self._request(uri, method=method, data=data)
|
299
|
+
except ConnectionFailedError as exc:
|
300
|
+
raise ConnectionFailedError from exc
|
plugwise/smile.py
CHANGED
@@ -149,14 +149,6 @@ class SmileAPI(SmileComm, SmileData):
|
|
149
149
|
### API Set and HA Service-related Functions ###
|
150
150
|
########################################################################################################
|
151
151
|
|
152
|
-
async def call_request(self, uri: str, **kwargs: Any) -> None:
|
153
|
-
"""ConnectionFailedError wrapper for calling _request()."""
|
154
|
-
method: str = kwargs["method"]
|
155
|
-
try:
|
156
|
-
await self._request(uri, method=method)
|
157
|
-
except ConnectionFailedError as exc:
|
158
|
-
raise ConnectionFailedError from exc
|
159
|
-
|
160
152
|
async def delete_notification(self) -> None:
|
161
153
|
"""Delete the active Plugwise Notification."""
|
162
154
|
await self.call_request(NOTIFICATIONS, method="delete")
|
@@ -189,7 +181,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
189
181
|
|
190
182
|
uri = f"{APPLIANCES};id={self._heater_id}/thermostat;id={thermostat_id}"
|
191
183
|
data = f"<thermostat_functionality><setpoint>{temp}</setpoint></thermostat_functionality>"
|
192
|
-
await self.
|
184
|
+
await self.call_request(uri, method="put", data=data)
|
193
185
|
|
194
186
|
async def set_offset(self, dev_id: str, offset: float) -> None:
|
195
187
|
"""Set the Temperature offset for thermostats that support this feature."""
|
@@ -202,7 +194,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
202
194
|
uri = f"{APPLIANCES};id={dev_id}/offset;type=temperature_offset"
|
203
195
|
data = f"<offset_functionality><offset>{value}</offset></offset_functionality>"
|
204
196
|
|
205
|
-
await self.
|
197
|
+
await self.call_request(uri, method="put", data=data)
|
206
198
|
|
207
199
|
async def set_preset(self, loc_id: str, preset: str) -> None:
|
208
200
|
"""Set the given Preset on the relevant Thermostat - from LOCATIONS."""
|
@@ -222,7 +214,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
222
214
|
f"</type><preset>{preset}</preset></location></locations>"
|
223
215
|
)
|
224
216
|
|
225
|
-
await self.
|
217
|
+
await self.call_request(uri, method="put", data=data)
|
226
218
|
|
227
219
|
async def set_select(self, key: str, loc_id: str, option: str, state: str | None) -> None:
|
228
220
|
"""Set a dhw/gateway/regulation mode or the thermostat schedule option."""
|
@@ -245,7 +237,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
245
237
|
uri = f"{APPLIANCES};type=heater_central/domestic_hot_water_mode_control"
|
246
238
|
data = f"<domestic_hot_water_mode_control_functionality><mode>{mode}</mode></domestic_hot_water_mode_control_functionality>"
|
247
239
|
|
248
|
-
await self.
|
240
|
+
await self.call_request(uri, method="put", data=data)
|
249
241
|
|
250
242
|
async def set_gateway_mode(self, mode: str) -> None:
|
251
243
|
"""Set the gateway mode."""
|
@@ -268,7 +260,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
268
260
|
uri = f"{APPLIANCES};id={self.gateway_id}/gateway_mode_control"
|
269
261
|
data = f"<gateway_mode_control_functionality><mode>{mode}</mode>{valid}</gateway_mode_control_functionality>"
|
270
262
|
|
271
|
-
await self.
|
263
|
+
await self.call_request(uri, method="put", data=data)
|
272
264
|
|
273
265
|
async def set_regulation_mode(self, mode: str) -> None:
|
274
266
|
"""Set the heating regulation mode."""
|
@@ -281,7 +273,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
281
273
|
duration = "<duration>300</duration>"
|
282
274
|
data = f"<regulation_mode_control_functionality>{duration}<mode>{mode}</mode></regulation_mode_control_functionality>"
|
283
275
|
|
284
|
-
await self.
|
276
|
+
await self.call_request(uri, method="put", data=data)
|
285
277
|
|
286
278
|
async def set_schedule_state(
|
287
279
|
self,
|
@@ -335,7 +327,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
335
327
|
f"{template}{contexts}</rule></rules>"
|
336
328
|
)
|
337
329
|
|
338
|
-
await self.
|
330
|
+
await self.call_request(uri, method="put", data=data)
|
339
331
|
self._schedule_old_states[loc_id][name] = new_state
|
340
332
|
|
341
333
|
def determine_contexts(
|
@@ -404,7 +396,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
404
396
|
if self._domain_objects.find(locator).text == "true":
|
405
397
|
raise PlugwiseError("Plugwise: the locked Relay was not switched.")
|
406
398
|
|
407
|
-
await self.
|
399
|
+
await self.call_request(uri, method="put", data=data)
|
408
400
|
|
409
401
|
async def _set_groupswitch_member_state(
|
410
402
|
self, members: list[str], state: str, switch: Munch
|
@@ -419,7 +411,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
419
411
|
uri = f"{APPLIANCES};id={member}/{switch.device};id={switch_id}"
|
420
412
|
data = f"<{switch.func_type}><{switch.func}>{state}</{switch.func}></{switch.func_type}>"
|
421
413
|
|
422
|
-
await self.
|
414
|
+
await self.call_request(uri, method="put", data=data)
|
423
415
|
|
424
416
|
async def set_temperature(self, loc_id: str, items: dict[str, float]) -> None:
|
425
417
|
"""Set the given Temperature on the relevant Thermostat."""
|
@@ -460,4 +452,13 @@ class SmileAPI(SmileComm, SmileData):
|
|
460
452
|
f"{temperature}</setpoint></thermostat_functionality>"
|
461
453
|
)
|
462
454
|
|
463
|
-
await self.
|
455
|
+
await self.call_request(uri, method="put", data=data)
|
456
|
+
|
457
|
+
async def call_request(self, uri: str, **kwargs: Any) -> None:
|
458
|
+
"""ConnectionFailedError wrapper for calling _request()."""
|
459
|
+
method: str = kwargs["method"]
|
460
|
+
data: str | None = kwargs.get("data")
|
461
|
+
try:
|
462
|
+
await self._request(uri, method=method, data=data)
|
463
|
+
except ConnectionFailedError as exc:
|
464
|
+
raise ConnectionFailedError from exc
|
@@ -1,17 +1,17 @@
|
|
1
|
-
plugwise/__init__.py,sha256=
|
1
|
+
plugwise/__init__.py,sha256=zo6whZ4QeZxymEWO_nQ2A4d_XpaXExjKJWZjJzaAxwk,16773
|
2
2
|
plugwise/common.py,sha256=P4sUYzgVcFsIR2DmQxeVeOiZvFZWpZXgwHA3XRc1Sx0,12538
|
3
3
|
plugwise/constants.py,sha256=aP2ifDFIRuzYzuhJk1cOdqN84yR135eqCzAATrhxMo4,16646
|
4
4
|
plugwise/data.py,sha256=HA3OoLrTad4ytns6_rfygwu8eGfopHJBNADGs-hvaQk,9054
|
5
5
|
plugwise/exceptions.py,sha256=Ce-tO9uNsMB-8FP6VAxBvsHNJ-NIM9F0onUZOdZI4Ys,1110
|
6
|
-
plugwise/helper.py,sha256=
|
6
|
+
plugwise/helper.py,sha256=NFcxVtY9qdM2TtBbGs-_eh7xKO6G_M3Q4W9bXUCpH84,43861
|
7
7
|
plugwise/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
-
plugwise/smile.py,sha256=
|
8
|
+
plugwise/smile.py,sha256=mPQsq4qjxZ9cpUmGi_FvYrguj7GGoeqfSQjQNmq5ybU,18617
|
9
9
|
plugwise/util.py,sha256=9ld46KJHWFze2eUrVSgUYn0g3zNerlpboM0iUa0H3ak,7830
|
10
10
|
plugwise/legacy/data.py,sha256=DsHR9xgiFDg_Vh_6ZpOskw8ZhNQ3CmwjstI3yiH6MEk,3048
|
11
11
|
plugwise/legacy/helper.py,sha256=6-tYQMEXepE5rec-hn6lt2EeknADI3J8UFuBSLgu8dk,17878
|
12
|
-
plugwise/legacy/smile.py,sha256=
|
13
|
-
plugwise-0.38.
|
14
|
-
plugwise-0.38.
|
15
|
-
plugwise-0.38.
|
16
|
-
plugwise-0.38.
|
17
|
-
plugwise-0.38.
|
12
|
+
plugwise/legacy/smile.py,sha256=E5Ub5TtQcfcbB7AUVf1zwxonpkGuMHELITf5td5HEXw,11321
|
13
|
+
plugwise-0.38.1.dist-info/LICENSE,sha256=mL22BjmXtg_wnoDnnaqps5_Bg_VGj_yHueX5lsKwbCc,1144
|
14
|
+
plugwise-0.38.1.dist-info/METADATA,sha256=moQq3lGIMmw36rfewCiQB_GCyolvSkUu4WZs-QJUNMs,9098
|
15
|
+
plugwise-0.38.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
16
|
+
plugwise-0.38.1.dist-info/top_level.txt,sha256=MYOmktMFf8ZmX6_OE1y9MoCZFfY-L8DA0F2tA2IvE4s,9
|
17
|
+
plugwise-0.38.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|