plugwise 0.37.8__tar.gz → 0.38.0__tar.gz
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-0.37.8 → plugwise-0.38.0}/PKG-INFO +9 -8
- {plugwise-0.37.8 → plugwise-0.38.0}/README.md +8 -7
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/__init__.py +54 -34
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/constants.py +2 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/data.py +1 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/exceptions.py +4 -8
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/helper.py +29 -3
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/legacy/smile.py +7 -5
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/smile.py +29 -14
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise.egg-info/PKG-INFO +9 -8
- {plugwise-0.37.8 → plugwise-0.38.0}/pyproject.toml +2 -2
- {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_adam.py +22 -2
- {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_init.py +37 -28
- {plugwise-0.37.8 → plugwise-0.38.0}/LICENSE +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/common.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/legacy/data.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/legacy/helper.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/py.typed +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/util.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise.egg-info/SOURCES.txt +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise.egg-info/dependency_links.txt +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise.egg-info/requires.txt +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/plugwise.egg-info/top_level.txt +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/setup.cfg +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/setup.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_anna.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_generic.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_legacy_anna.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_legacy_generic.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_legacy_p1.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_legacy_stretch.py +0 -0
- {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_p1.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: plugwise
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.38.0
|
4
4
|
Summary: Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3.
|
5
5
|
Home-page: https://github.com/plugwise/python-plugwise
|
6
6
|
Author: Plugwise device owners
|
@@ -54,12 +54,13 @@ This module supports `Smile`s (and `Stretch`), i.e. the networked plugwise devic
|
|
54
54
|
Our main usage for this module is supporting [Home Assistant](https://www.home-assistant.io) / [home-assistant](http://github.com/home-assistant/core/)
|
55
55
|
|
56
56
|
[](https://github.com/plugwise)
|
57
|
-
[](https://coderabbit.ai)
|
58
|
+
[](https://github.com/plugwise/python-plugwise/issues/291)
|
58
59
|
|
60
|
+
[](https://pypi.python.org/pypi/plugwise/)
|
59
61
|
[](https://github.com/plugwise/python-plugwise/actions)
|
60
62
|
[](https://github.com/plugwise/python-plugwise/actions)
|
61
63
|
[](https://results.pre-commit.ci/latest/github/plugwise/python-plugwise/main)
|
62
|
-
[](https://github.com/plugwise/python-plugwise/issues/291)
|
63
64
|
|
64
65
|
[](https://www.codefactor.io/repository/github/plugwise/python-plugwise)
|
65
66
|
[](https://codecov.io/gh/plugwise/python-plugwise)
|
@@ -94,9 +95,9 @@ See the [`plugwise-beta`](https://github.com/plugwise/plugwise-beta) repository
|
|
94
95
|
|
95
96
|
## Development/patches
|
96
97
|
|
97
|
-
Like Home Assistant Core we use `pre-commit` and additionally run [pre-commit.ci](http://pre-commit.ci) to automatically validate your commits and PRs.
|
98
|
+
Like Home Assistant Core, we use `pre-commit` and additionally run [pre-commit.ci](http://pre-commit.ci) to automatically validate your commits and PRs.
|
98
99
|
|
99
|
-
If you want to create a PR please
|
100
|
+
If you want to create a PR, please ensure you at least run `scripts/setup.sh`. This will ensure your environment is set up correctly before attempting to `git commit`. We sincerely and highly recommended also setting up local testing, see [`tests/README.md`](https://github.com/plugwise/python-plugwise/blob/main/tests/README.md) for more information and run `scripts/setup_test.sh` to prepare your environment.
|
100
101
|
|
101
102
|
## Project support status
|
102
103
|
|
@@ -125,13 +126,13 @@ Module providing interfacing with the Plugwise devices:
|
|
125
126
|
|
126
127
|
## License, origins and contributors
|
127
128
|
|
128
|
-
As per the origins we have retained the appropriate licensing and including the MIT-license for this project.
|
129
|
+
As per the origins, we have retained the appropriate licensing and including the MIT-license for this project.
|
129
130
|
|
130
131
|
Origins (from newest to oldest):
|
131
132
|
|
132
133
|
- Networked (Smile/Stretch) Plugwise support by @bouwew (Bouwe) and @CoMPaTech (Tom). We both support and help out @brefra (Frank) where possible, he's supporting the USB module and integration.
|
133
134
|
- 'All' available Plugwise support by @bouwew (Bouwe), @brefra (Frank) and @CoMPaTech (Tom)
|
134
|
-
- Upstreamed haanna/HA-core Anna, including all later products - 'Plugwise-Smile/Plugwise-HA/plugwise-beta
|
135
|
+
- Upstreamed haanna/HA-core Anna, including all later products - 'Plugwise-Smile/Plugwise-HA/plugwise-beta' by @bouwew (Bouwe) & @CoMPaTech (Tom)
|
135
136
|
- Networked Plugwise Anna module with custom_module - `haanna/anna-ha` via <https://github.com/laetificat> (Kevin)
|
136
137
|
- USB-based stick module with custom_module - `plugwise-stick/plugwise` by @brefra (Frank)
|
137
138
|
- USB-plugwise module - `plugwise` by <https://github.com/cyberjunky/python-plugwise> (Ron) originally by <https://github.com/aequitas/python-plugwise> (Johan) (with reference only in license to Sven)
|
@@ -139,4 +140,4 @@ Origins (from newest to oldest):
|
|
139
140
|
|
140
141
|
## Thanks
|
141
142
|
|
142
|
-
On behalf all of us, big thanks to Plugwise and community members @riemers and @tane from [HAshop](https://hashop.nl) for their support and obviously all our users and testers who dealt with our typos and challenges. Disclaimer, while we are communicating with Plugwise and they expressed their gratitude through their newsletter, we are not part of Plugwise as a company. We are just a bunch of guys anxious to get our (and your) Plugwise products working with Home Assistant.
|
143
|
+
On behalf of all of us, big thanks to Plugwise and community members @riemers and @tane from [HAshop](https://hashop.nl) for their support and obviously all our users and testers who dealt with our typos and challenges. Disclaimer, while we are communicating with Plugwise and they expressed their gratitude through their newsletter, we are not part of Plugwise as a company. We are just a bunch of guys anxious to get our (and your) Plugwise products working with Home Assistant.
|
@@ -7,12 +7,13 @@ This module supports `Smile`s (and `Stretch`), i.e. the networked plugwise devic
|
|
7
7
|
Our main usage for this module is supporting [Home Assistant](https://www.home-assistant.io) / [home-assistant](http://github.com/home-assistant/core/)
|
8
8
|
|
9
9
|
[](https://github.com/plugwise)
|
10
|
-
[](https://coderabbit.ai)
|
11
|
+
[](https://github.com/plugwise/python-plugwise/issues/291)
|
11
12
|
|
13
|
+
[](https://pypi.python.org/pypi/plugwise/)
|
12
14
|
[](https://github.com/plugwise/python-plugwise/actions)
|
13
15
|
[](https://github.com/plugwise/python-plugwise/actions)
|
14
16
|
[](https://results.pre-commit.ci/latest/github/plugwise/python-plugwise/main)
|
15
|
-
[](https://github.com/plugwise/python-plugwise/issues/291)
|
16
17
|
|
17
18
|
[](https://www.codefactor.io/repository/github/plugwise/python-plugwise)
|
18
19
|
[](https://codecov.io/gh/plugwise/python-plugwise)
|
@@ -47,9 +48,9 @@ See the [`plugwise-beta`](https://github.com/plugwise/plugwise-beta) repository
|
|
47
48
|
|
48
49
|
## Development/patches
|
49
50
|
|
50
|
-
Like Home Assistant Core we use `pre-commit` and additionally run [pre-commit.ci](http://pre-commit.ci) to automatically validate your commits and PRs.
|
51
|
+
Like Home Assistant Core, we use `pre-commit` and additionally run [pre-commit.ci](http://pre-commit.ci) to automatically validate your commits and PRs.
|
51
52
|
|
52
|
-
If you want to create a PR please
|
53
|
+
If you want to create a PR, please ensure you at least run `scripts/setup.sh`. This will ensure your environment is set up correctly before attempting to `git commit`. We sincerely and highly recommended also setting up local testing, see [`tests/README.md`](https://github.com/plugwise/python-plugwise/blob/main/tests/README.md) for more information and run `scripts/setup_test.sh` to prepare your environment.
|
53
54
|
|
54
55
|
## Project support status
|
55
56
|
|
@@ -78,13 +79,13 @@ Module providing interfacing with the Plugwise devices:
|
|
78
79
|
|
79
80
|
## License, origins and contributors
|
80
81
|
|
81
|
-
As per the origins we have retained the appropriate licensing and including the MIT-license for this project.
|
82
|
+
As per the origins, we have retained the appropriate licensing and including the MIT-license for this project.
|
82
83
|
|
83
84
|
Origins (from newest to oldest):
|
84
85
|
|
85
86
|
- Networked (Smile/Stretch) Plugwise support by @bouwew (Bouwe) and @CoMPaTech (Tom). We both support and help out @brefra (Frank) where possible, he's supporting the USB module and integration.
|
86
87
|
- 'All' available Plugwise support by @bouwew (Bouwe), @brefra (Frank) and @CoMPaTech (Tom)
|
87
|
-
- Upstreamed haanna/HA-core Anna, including all later products - 'Plugwise-Smile/Plugwise-HA/plugwise-beta
|
88
|
+
- Upstreamed haanna/HA-core Anna, including all later products - 'Plugwise-Smile/Plugwise-HA/plugwise-beta' by @bouwew (Bouwe) & @CoMPaTech (Tom)
|
88
89
|
- Networked Plugwise Anna module with custom_module - `haanna/anna-ha` via <https://github.com/laetificat> (Kevin)
|
89
90
|
- USB-based stick module with custom_module - `plugwise-stick/plugwise` by @brefra (Frank)
|
90
91
|
- USB-plugwise module - `plugwise` by <https://github.com/cyberjunky/python-plugwise> (Ron) originally by <https://github.com/aequitas/python-plugwise> (Johan) (with reference only in license to Sven)
|
@@ -92,4 +93,4 @@ Origins (from newest to oldest):
|
|
92
93
|
|
93
94
|
## Thanks
|
94
95
|
|
95
|
-
On behalf all of us, big thanks to Plugwise and community members @riemers and @tane from [HAshop](https://hashop.nl) for their support and obviously all our users and testers who dealt with our typos and challenges. Disclaimer, while we are communicating with Plugwise and they expressed their gratitude through their newsletter, we are not part of Plugwise as a company. We are just a bunch of guys anxious to get our (and your) Plugwise products working with Home Assistant.
|
96
|
+
On behalf of all of us, big thanks to Plugwise and community members @riemers and @tane from [HAshop](https://hashop.nl) for their support and obviously all our users and testers who dealt with our typos and challenges. Disclaimer, while we are communicating with Plugwise and they expressed their gratitude through their newsletter, we are not part of Plugwise as a company. We are just a bunch of guys anxious to get our (and your) Plugwise products working with Home Assistant.
|
@@ -18,7 +18,14 @@ from plugwise.constants import (
|
|
18
18
|
PlugwiseData,
|
19
19
|
ThermoLoc,
|
20
20
|
)
|
21
|
-
from plugwise.exceptions import
|
21
|
+
from plugwise.exceptions import (
|
22
|
+
ConnectionFailedError,
|
23
|
+
DataMissingError,
|
24
|
+
InvalidSetupError,
|
25
|
+
PlugwiseError,
|
26
|
+
ResponseError,
|
27
|
+
UnsupportedDeviceError,
|
28
|
+
)
|
22
29
|
from plugwise.helper import SmileComm
|
23
30
|
from plugwise.legacy.smile import SmileLegacyAPI
|
24
31
|
from plugwise.smile import SmileAPI
|
@@ -141,30 +148,28 @@ class Smile(SmileComm):
|
|
141
148
|
self._user,
|
142
149
|
self._port,
|
143
150
|
self._timeout,
|
144
|
-
)
|
145
|
-
|
146
|
-
self.
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
self._timeout,
|
167
|
-
)
|
151
|
+
) if not self.smile_legacy else SmileLegacyAPI(
|
152
|
+
self._host,
|
153
|
+
self._passwd,
|
154
|
+
self._websession,
|
155
|
+
self._is_thermostat,
|
156
|
+
self._on_off_device,
|
157
|
+
self._opentherm_device,
|
158
|
+
self._stretch_v2,
|
159
|
+
self._target_smile,
|
160
|
+
self.loc_data,
|
161
|
+
self.smile_fw_version,
|
162
|
+
self.smile_hostname,
|
163
|
+
self.smile_hw_version,
|
164
|
+
self.smile_mac_address,
|
165
|
+
self.smile_model,
|
166
|
+
self.smile_name,
|
167
|
+
self.smile_type,
|
168
|
+
self.smile_zigbee_mac_address,
|
169
|
+
self._user,
|
170
|
+
self._port,
|
171
|
+
self._timeout,
|
172
|
+
)
|
168
173
|
|
169
174
|
# Update all endpoints on first connect
|
170
175
|
await self._smile_api.full_update_device()
|
@@ -289,17 +294,22 @@ class Smile(SmileComm):
|
|
289
294
|
return return_model
|
290
295
|
|
291
296
|
async def full_update_device(self) -> None:
|
292
|
-
"""
|
297
|
+
"""Helper-function used for testing."""
|
293
298
|
await self._smile_api.full_update_device()
|
294
299
|
|
295
300
|
def get_all_devices(self) -> None:
|
296
|
-
"""
|
301
|
+
"""Helper-function used for testing."""
|
297
302
|
self._smile_api.get_all_devices()
|
298
303
|
|
299
304
|
async def async_update(self) -> PlugwiseData:
|
300
305
|
"""Perform an incremental update for updating the various device states."""
|
301
|
-
data
|
302
|
-
|
306
|
+
data = PlugwiseData({}, {})
|
307
|
+
try:
|
308
|
+
data = await self._smile_api.async_update()
|
309
|
+
self.gateway_id = data.gateway["gateway_id"]
|
310
|
+
except (DataMissingError, KeyError) as err:
|
311
|
+
raise PlugwiseError("No Plugwise data received") from err
|
312
|
+
|
303
313
|
return data
|
304
314
|
|
305
315
|
########################################################################################################
|
@@ -311,19 +321,19 @@ class Smile(SmileComm):
|
|
311
321
|
key: str,
|
312
322
|
loc_id: str,
|
313
323
|
option: str,
|
314
|
-
|
324
|
+
state: str | None = None,
|
315
325
|
) -> None:
|
316
326
|
"""Set the selected option for the applicable Select."""
|
317
|
-
await self._smile_api.set_select(key, loc_id, option,
|
327
|
+
await self._smile_api.set_select(key, loc_id, option, state)
|
318
328
|
|
319
329
|
async def set_schedule_state(
|
320
330
|
self,
|
321
331
|
loc_id: str,
|
322
|
-
|
332
|
+
state: str | None,
|
323
333
|
name: str | None = None,
|
324
334
|
) -> None:
|
325
335
|
"""Activate/deactivate the Schedule, with the given name, on the relevant Thermostat."""
|
326
|
-
await self._smile_api.set_schedule_state(loc_id,
|
336
|
+
await self._smile_api.set_schedule_state(loc_id, state, name)
|
327
337
|
|
328
338
|
async def set_preset(self, loc_id: str, preset: str) -> None:
|
329
339
|
"""Set the given Preset on the relevant Thermostat."""
|
@@ -366,4 +376,14 @@ class Smile(SmileComm):
|
|
366
376
|
|
367
377
|
async def delete_notification(self) -> None:
|
368
378
|
"""Delete the active Plugwise Notification."""
|
369
|
-
|
379
|
+
try:
|
380
|
+
await self._smile_api.delete_notification()
|
381
|
+
except ConnectionFailedError as exc:
|
382
|
+
raise PlugwiseError(f"Failed to delete notification: {str(exc)}") from exc
|
383
|
+
|
384
|
+
async def reboot_gateway(self) -> None:
|
385
|
+
"""Reboot the Plugwise Gateway."""
|
386
|
+
try:
|
387
|
+
await self._smile_api.reboot_gateway()
|
388
|
+
except ConnectionFailedError as exc:
|
389
|
+
raise PlugwiseError(f"Failed to reboot gateway: {str(exc)}") from exc
|
@@ -17,6 +17,7 @@ DEGREE: Final = "°"
|
|
17
17
|
ELECTRIC_POTENTIAL_VOLT: Final = "V"
|
18
18
|
ENERGY_KILO_WATT_HOUR: Final = "kWh"
|
19
19
|
ENERGY_WATT_HOUR: Final = "Wh"
|
20
|
+
GATEWAY_REBOOT: Final = "/core/gateways;@reboot"
|
20
21
|
PERCENTAGE: Final = "%"
|
21
22
|
POWER_WATT: Final = "W"
|
22
23
|
PRESET_AWAY: Final = "away"
|
@@ -388,6 +389,7 @@ class GatewayData(TypedDict, total=False):
|
|
388
389
|
heater_id: str
|
389
390
|
item_count: int
|
390
391
|
notifications: dict[str, dict[str, str]]
|
392
|
+
reboot: bool
|
391
393
|
smile_name: str
|
392
394
|
|
393
395
|
|
@@ -9,6 +9,10 @@ class ConnectionFailedError(PlugwiseException):
|
|
9
9
|
"""Raised when unable to connect."""
|
10
10
|
|
11
11
|
|
12
|
+
class DataMissingError(PlugwiseException):
|
13
|
+
"""Raised when expected data is missing."""
|
14
|
+
|
15
|
+
|
12
16
|
class InvalidAuthentication(PlugwiseException):
|
13
17
|
"""Raised when unable to authenticate."""
|
14
18
|
|
@@ -29,14 +33,6 @@ class DeviceSetupError(PlugwiseException):
|
|
29
33
|
"""Raised when device is missing critical setup data."""
|
30
34
|
|
31
35
|
|
32
|
-
class DeviceTimeoutError(PlugwiseException):
|
33
|
-
"""Raised when device is not supported."""
|
34
|
-
|
35
|
-
|
36
|
-
class ErrorSendingCommandError(PlugwiseException):
|
37
|
-
"""Raised when device is not accepting the command."""
|
38
|
-
|
39
|
-
|
40
36
|
class ResponseError(PlugwiseException):
|
41
37
|
"""Raised when empty or error in response returned."""
|
42
38
|
|
@@ -123,6 +123,14 @@ class SmileComm:
|
|
123
123
|
resp = await self._websession.get(
|
124
124
|
url, headers=use_headers, auth=self._auth
|
125
125
|
)
|
126
|
+
if method == "post":
|
127
|
+
use_headers = {"Content-type": "text/xml"}
|
128
|
+
resp = await self._websession.post(
|
129
|
+
url,
|
130
|
+
headers=use_headers,
|
131
|
+
data=data,
|
132
|
+
auth=self._auth,
|
133
|
+
)
|
126
134
|
if method == "put":
|
127
135
|
use_headers = {"Content-type": "text/xml"}
|
128
136
|
resp = await self._websession.put(
|
@@ -144,6 +152,17 @@ class SmileComm:
|
|
144
152
|
raise ConnectionFailedError from exc
|
145
153
|
return await self._request(command, retry - 1)
|
146
154
|
|
155
|
+
if resp.status == 504:
|
156
|
+
if retry < 1:
|
157
|
+
LOGGER.warning(
|
158
|
+
"Failed sending %s %s to Plugwise Smile, error: %s",
|
159
|
+
method,
|
160
|
+
command,
|
161
|
+
"504 Gateway Timeout",
|
162
|
+
)
|
163
|
+
raise ConnectionFailedError
|
164
|
+
return await self._request(command, retry - 1)
|
165
|
+
|
147
166
|
return await self._request_validate(resp, method)
|
148
167
|
|
149
168
|
async def _request_validate(self, resp: ClientResponse, method: str) -> etree:
|
@@ -152,8 +171,8 @@ class SmileComm:
|
|
152
171
|
if resp.status == 202:
|
153
172
|
return
|
154
173
|
|
155
|
-
# Cornercase for
|
156
|
-
if method
|
174
|
+
# Cornercase for server not responding with 202
|
175
|
+
if method in ("post", "put") and resp.status == 200:
|
157
176
|
return
|
158
177
|
|
159
178
|
if resp.status == 401:
|
@@ -161,7 +180,14 @@ class SmileComm:
|
|
161
180
|
LOGGER.error("%s", msg)
|
162
181
|
raise InvalidAuthentication
|
163
182
|
|
164
|
-
if
|
183
|
+
if resp.status == 405:
|
184
|
+
msg = "405 Method not allowed."
|
185
|
+
LOGGER.error("%s", msg)
|
186
|
+
raise ConnectionFailedError
|
187
|
+
|
188
|
+
if not (result := await resp.text()) or (
|
189
|
+
"<error>" in result and "Not started" not in result
|
190
|
+
):
|
165
191
|
LOGGER.warning("Smile response empty or error in %s", result)
|
166
192
|
raise ResponseError
|
167
193
|
|
@@ -149,6 +149,9 @@ class SmileLegacyAPI(SmileComm, SmileLegacyData):
|
|
149
149
|
async def delete_notification(self) -> None:
|
150
150
|
"""Set-function placeholder for legacy devices."""
|
151
151
|
|
152
|
+
async def reboot_gateway(self) -> None:
|
153
|
+
"""Set-function placeholder for legacy devices."""
|
154
|
+
|
152
155
|
async def set_dhw_mode(self, mode: str) -> None:
|
153
156
|
"""Set-function placeholder for legacy devices."""
|
154
157
|
|
@@ -182,13 +185,12 @@ class SmileLegacyAPI(SmileComm, SmileLegacyData):
|
|
182
185
|
async def set_regulation_mode(self, mode: str) -> None:
|
183
186
|
"""Set-function placeholder for legacy devices."""
|
184
187
|
|
185
|
-
async def set_select(self, key: str, loc_id: str, option: str,
|
188
|
+
async def set_select(self, key: str, loc_id: str, option: str, state: str | None) -> None:
|
186
189
|
"""Set the thermostat schedule option."""
|
187
|
-
# schedule
|
188
|
-
|
189
|
-
await self.set_schedule_state("dummy", option, name)
|
190
|
+
# schedule name corresponds to select option
|
191
|
+
await self.set_schedule_state("dummy", state, option)
|
190
192
|
|
191
|
-
async def set_schedule_state(self, _: str, state: str, name: str | None) -> None:
|
193
|
+
async def set_schedule_state(self, _: str, state: str | None, name: str | None) -> None:
|
192
194
|
"""Activate/deactivate the Schedule.
|
193
195
|
|
194
196
|
Determined from - DOMAIN_OBJECTS.
|
@@ -5,6 +5,7 @@ Plugwise backend module for Home Assistant Core.
|
|
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
|
ADAM,
|
@@ -14,6 +15,7 @@ from plugwise.constants import (
|
|
14
15
|
DEFAULT_TIMEOUT,
|
15
16
|
DEFAULT_USERNAME,
|
16
17
|
DOMAIN_OBJECTS,
|
18
|
+
GATEWAY_REBOOT,
|
17
19
|
LOCATIONS,
|
18
20
|
MAX_SETPOINT,
|
19
21
|
MIN_SETPOINT,
|
@@ -26,7 +28,7 @@ from plugwise.constants import (
|
|
26
28
|
ThermoLoc,
|
27
29
|
)
|
28
30
|
from plugwise.data import SmileData
|
29
|
-
from plugwise.exceptions import PlugwiseError
|
31
|
+
from plugwise.exceptions import ConnectionFailedError, DataMissingError, PlugwiseError
|
30
32
|
from plugwise.helper import SmileComm
|
31
33
|
|
32
34
|
import aiohttp
|
@@ -131,13 +133,15 @@ class SmileAPI(SmileComm, SmileData):
|
|
131
133
|
# Perform a full update at day-change
|
132
134
|
self.gw_data: GatewayData = {}
|
133
135
|
self.gw_devices: dict[str, DeviceData] = {}
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
136
|
+
try:
|
137
|
+
await self.full_update_device()
|
138
|
+
self.get_all_devices()
|
139
|
+
if "heater_id" in self.gw_data:
|
140
|
+
self._heater_id = self.gw_data["heater_id"]
|
141
|
+
if "cooling_enabled" in self.gw_devices[self._heater_id]["binary_sensors"]:
|
142
|
+
self._cooling_enabled = self.gw_devices[self._heater_id]["binary_sensors"]["cooling_enabled"]
|
143
|
+
except KeyError as err:
|
144
|
+
raise DataMissingError("No Plugwise data received") from err
|
141
145
|
|
142
146
|
return PlugwiseData(self.gw_data, self.gw_devices)
|
143
147
|
|
@@ -145,9 +149,21 @@ class SmileAPI(SmileComm, SmileData):
|
|
145
149
|
### API Set and HA Service-related Functions ###
|
146
150
|
########################################################################################################
|
147
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
|
+
|
148
160
|
async def delete_notification(self) -> None:
|
149
161
|
"""Delete the active Plugwise Notification."""
|
150
|
-
await self.
|
162
|
+
await self.call_request(NOTIFICATIONS, method="delete")
|
163
|
+
|
164
|
+
async def reboot_gateway(self) -> None:
|
165
|
+
"""Reboot the Gateway."""
|
166
|
+
await self.call_request(GATEWAY_REBOOT, method="post")
|
151
167
|
|
152
168
|
async def set_number(
|
153
169
|
self,
|
@@ -208,7 +224,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
208
224
|
|
209
225
|
await self._request(uri, method="put", data=data)
|
210
226
|
|
211
|
-
async def set_select(self, key: str, loc_id: str, option: str,
|
227
|
+
async def set_select(self, key: str, loc_id: str, option: str, state: str | None) -> None:
|
212
228
|
"""Set a dhw/gateway/regulation mode or the thermostat schedule option."""
|
213
229
|
match key:
|
214
230
|
case "select_dhw_mode":
|
@@ -218,9 +234,8 @@ class SmileAPI(SmileComm, SmileData):
|
|
218
234
|
case "select_regulation_mode":
|
219
235
|
await self.set_regulation_mode(option)
|
220
236
|
case "select_schedule":
|
221
|
-
# schedule
|
222
|
-
|
223
|
-
await self.set_schedule_state(loc_id, option, name)
|
237
|
+
# schedule name corresponds to select option
|
238
|
+
await self.set_schedule_state(loc_id, state, option)
|
224
239
|
|
225
240
|
async def set_dhw_mode(self, mode: str) -> None:
|
226
241
|
"""Set the domestic hot water heating regulation mode."""
|
@@ -271,7 +286,7 @@ class SmileAPI(SmileComm, SmileData):
|
|
271
286
|
async def set_schedule_state(
|
272
287
|
self,
|
273
288
|
loc_id: str,
|
274
|
-
new_state: str,
|
289
|
+
new_state: str | None,
|
275
290
|
name: str | None,
|
276
291
|
) -> None:
|
277
292
|
"""Activate/deactivate the Schedule, with the given name, on the relevant Thermostat.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: plugwise
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.38.0
|
4
4
|
Summary: Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3.
|
5
5
|
Home-page: https://github.com/plugwise/python-plugwise
|
6
6
|
Author: Plugwise device owners
|
@@ -54,12 +54,13 @@ This module supports `Smile`s (and `Stretch`), i.e. the networked plugwise devic
|
|
54
54
|
Our main usage for this module is supporting [Home Assistant](https://www.home-assistant.io) / [home-assistant](http://github.com/home-assistant/core/)
|
55
55
|
|
56
56
|
[](https://github.com/plugwise)
|
57
|
-
[](https://coderabbit.ai)
|
58
|
+
[](https://github.com/plugwise/python-plugwise/issues/291)
|
58
59
|
|
60
|
+
[](https://pypi.python.org/pypi/plugwise/)
|
59
61
|
[](https://github.com/plugwise/python-plugwise/actions)
|
60
62
|
[](https://github.com/plugwise/python-plugwise/actions)
|
61
63
|
[](https://results.pre-commit.ci/latest/github/plugwise/python-plugwise/main)
|
62
|
-
[](https://github.com/plugwise/python-plugwise/issues/291)
|
63
64
|
|
64
65
|
[](https://www.codefactor.io/repository/github/plugwise/python-plugwise)
|
65
66
|
[](https://codecov.io/gh/plugwise/python-plugwise)
|
@@ -94,9 +95,9 @@ See the [`plugwise-beta`](https://github.com/plugwise/plugwise-beta) repository
|
|
94
95
|
|
95
96
|
## Development/patches
|
96
97
|
|
97
|
-
Like Home Assistant Core we use `pre-commit` and additionally run [pre-commit.ci](http://pre-commit.ci) to automatically validate your commits and PRs.
|
98
|
+
Like Home Assistant Core, we use `pre-commit` and additionally run [pre-commit.ci](http://pre-commit.ci) to automatically validate your commits and PRs.
|
98
99
|
|
99
|
-
If you want to create a PR please
|
100
|
+
If you want to create a PR, please ensure you at least run `scripts/setup.sh`. This will ensure your environment is set up correctly before attempting to `git commit`. We sincerely and highly recommended also setting up local testing, see [`tests/README.md`](https://github.com/plugwise/python-plugwise/blob/main/tests/README.md) for more information and run `scripts/setup_test.sh` to prepare your environment.
|
100
101
|
|
101
102
|
## Project support status
|
102
103
|
|
@@ -125,13 +126,13 @@ Module providing interfacing with the Plugwise devices:
|
|
125
126
|
|
126
127
|
## License, origins and contributors
|
127
128
|
|
128
|
-
As per the origins we have retained the appropriate licensing and including the MIT-license for this project.
|
129
|
+
As per the origins, we have retained the appropriate licensing and including the MIT-license for this project.
|
129
130
|
|
130
131
|
Origins (from newest to oldest):
|
131
132
|
|
132
133
|
- Networked (Smile/Stretch) Plugwise support by @bouwew (Bouwe) and @CoMPaTech (Tom). We both support and help out @brefra (Frank) where possible, he's supporting the USB module and integration.
|
133
134
|
- 'All' available Plugwise support by @bouwew (Bouwe), @brefra (Frank) and @CoMPaTech (Tom)
|
134
|
-
- Upstreamed haanna/HA-core Anna, including all later products - 'Plugwise-Smile/Plugwise-HA/plugwise-beta
|
135
|
+
- Upstreamed haanna/HA-core Anna, including all later products - 'Plugwise-Smile/Plugwise-HA/plugwise-beta' by @bouwew (Bouwe) & @CoMPaTech (Tom)
|
135
136
|
- Networked Plugwise Anna module with custom_module - `haanna/anna-ha` via <https://github.com/laetificat> (Kevin)
|
136
137
|
- USB-based stick module with custom_module - `plugwise-stick/plugwise` by @brefra (Frank)
|
137
138
|
- USB-plugwise module - `plugwise` by <https://github.com/cyberjunky/python-plugwise> (Ron) originally by <https://github.com/aequitas/python-plugwise> (Johan) (with reference only in license to Sven)
|
@@ -139,4 +140,4 @@ Origins (from newest to oldest):
|
|
139
140
|
|
140
141
|
## Thanks
|
141
142
|
|
142
|
-
On behalf all of us, big thanks to Plugwise and community members @riemers and @tane from [HAshop](https://hashop.nl) for their support and obviously all our users and testers who dealt with our typos and challenges. Disclaimer, while we are communicating with Plugwise and they expressed their gratitude through their newsletter, we are not part of Plugwise as a company. We are just a bunch of guys anxious to get our (and your) Plugwise products working with Home Assistant.
|
143
|
+
On behalf of all of us, big thanks to Plugwise and community members @riemers and @tane from [HAshop](https://hashop.nl) for their support and obviously all our users and testers who dealt with our typos and challenges. Disclaimer, while we are communicating with Plugwise and they expressed their gratitude through their newsletter, we are not part of Plugwise as a company. We are just a bunch of guys anxious to get our (and your) Plugwise products working with Home Assistant.
|
@@ -1,10 +1,10 @@
|
|
1
1
|
[build-system]
|
2
|
-
requires = ["setuptools~=
|
2
|
+
requires = ["setuptools~=70.0", "wheel~=0.43.0"]
|
3
3
|
build-backend = "setuptools.build_meta"
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "plugwise"
|
7
|
-
version = "0.
|
7
|
+
version = "0.38.0"
|
8
8
|
license = {file = "LICENSE"}
|
9
9
|
description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3."
|
10
10
|
readme = "README.md"
|
@@ -55,6 +55,10 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
|
|
55
55
|
smile, "675416a629f343c495449970e2ca37b5"
|
56
56
|
)
|
57
57
|
assert not switch_change
|
58
|
+
|
59
|
+
reboot = await self.tinker_reboot(smile)
|
60
|
+
assert reboot
|
61
|
+
|
58
62
|
await smile.close_connection()
|
59
63
|
await self.disconnect(server, client)
|
60
64
|
|
@@ -78,11 +82,13 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
|
|
78
82
|
try:
|
79
83
|
await smile.delete_notification()
|
80
84
|
notification_deletion = False # pragma: no cover
|
81
|
-
except pw_exceptions.
|
85
|
+
except pw_exceptions.PlugwiseError:
|
82
86
|
notification_deletion = True
|
83
|
-
|
84
87
|
assert notification_deletion
|
85
88
|
|
89
|
+
reboot = await self.tinker_reboot(smile, unhappy=True)
|
90
|
+
assert not reboot
|
91
|
+
|
86
92
|
await smile.close_connection()
|
87
93
|
await self.disconnect(server, client)
|
88
94
|
|
@@ -330,6 +336,20 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
|
|
330
336
|
smile, "2022-01-16 00:00:01", testdata_updated, initialize=False
|
331
337
|
)
|
332
338
|
|
339
|
+
# Simulate receiving no xml-data after a requesting a reboot of the gateway
|
340
|
+
self.smile_setup = "reboot/adam_plus_anna_new"
|
341
|
+
try:
|
342
|
+
await self.device_test(smile, initialize=False)
|
343
|
+
except pw_exceptions.PlugwiseError:
|
344
|
+
_LOGGER.debug("Receiving no data after a reboot is properly handled")
|
345
|
+
|
346
|
+
# Simulate receiving xml-data with <error>
|
347
|
+
self.smile_setup = "error/adam_plus_anna_new"
|
348
|
+
try:
|
349
|
+
await self.device_test(smile, initialize=False)
|
350
|
+
except pw_exceptions.ResponseError:
|
351
|
+
_LOGGER.debug("Receiving error-data from the Gateway")
|
352
|
+
|
333
353
|
await smile.close_connection()
|
334
354
|
await self.disconnect(server, client)
|
335
355
|
|
@@ -31,6 +31,7 @@ CORE_DOMAIN_OBJECTS_TAIL = "/core/domain_objects{tail:.*}"
|
|
31
31
|
CORE_LOCATIONS = "/core/locations"
|
32
32
|
CORE_LOCATIONS_TAIL = "/core/locations{tail:.*}"
|
33
33
|
CORE_APPLIANCES_TAIL = "/core/appliances{tail:.*}"
|
34
|
+
CORE_GATEWAYS_TAIL = "/core/gateways{tail:.*}"
|
34
35
|
CORE_NOTIFICATIONS_TAIL = "/core/notifications{tail:.*}"
|
35
36
|
CORE_RULES_TAIL = "/core/rules{tail:.*}"
|
36
37
|
EMPTY_XML = "<xml />"
|
@@ -93,6 +94,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
93
94
|
|
94
95
|
if fail_auth:
|
95
96
|
app.router.add_get("/{tail:.*}", self.smile_fail_auth)
|
97
|
+
app.router.add_route("POST", "/{tail:.*}", self.smile_fail_auth)
|
96
98
|
app.router.add_route("PUT", "/{tail:.*}", self.smile_fail_auth)
|
97
99
|
return app
|
98
100
|
|
@@ -106,6 +108,9 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
106
108
|
# Introducte timeout with 2 seconds, test by setting response to 10ms
|
107
109
|
# Don't actually wait 2 seconds as this will prolongue testing
|
108
110
|
if not raise_timeout:
|
111
|
+
app.router.add_route(
|
112
|
+
"POST", CORE_GATEWAYS_TAIL, self.smile_http_accept
|
113
|
+
)
|
109
114
|
app.router.add_route("PUT", CORE_LOCATIONS_TAIL, self.smile_http_accept)
|
110
115
|
app.router.add_route(
|
111
116
|
"DELETE", CORE_NOTIFICATIONS_TAIL, self.smile_http_accept
|
@@ -115,11 +120,14 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
115
120
|
"PUT", CORE_APPLIANCES_TAIL, self.smile_http_accept
|
116
121
|
)
|
117
122
|
else:
|
123
|
+
app.router.add_route(
|
124
|
+
"POST", CORE_GATEWAYS_TAIL, self.smile_timeout
|
125
|
+
)
|
118
126
|
app.router.add_route("PUT", CORE_LOCATIONS_TAIL, self.smile_timeout)
|
119
127
|
app.router.add_route("PUT", CORE_RULES_TAIL, self.smile_timeout)
|
120
128
|
app.router.add_route("PUT", CORE_APPLIANCES_TAIL, self.smile_timeout)
|
121
129
|
app.router.add_route(
|
122
|
-
"DELETE",
|
130
|
+
"DELETE", CORE_NOTIFICATIONS_TAIL, self.smile_timeout
|
123
131
|
)
|
124
132
|
|
125
133
|
return app
|
@@ -241,7 +249,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
241
249
|
@classmethod
|
242
250
|
async def smile_timeout(cls, request):
|
243
251
|
"""Render timeout endpoint."""
|
244
|
-
raise
|
252
|
+
raise aiohttp.web.HTTPGatewayTimeout()
|
245
253
|
|
246
254
|
@classmethod
|
247
255
|
async def smile_broken(cls, request):
|
@@ -339,7 +347,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
339
347
|
assert connection_state
|
340
348
|
return server, smile, client
|
341
349
|
except (
|
342
|
-
pw_exceptions.
|
350
|
+
pw_exceptions.ConnectionFailedError,
|
343
351
|
pw_exceptions.InvalidXMLError,
|
344
352
|
pw_exceptions.InvalidAuthentication,
|
345
353
|
) as exception:
|
@@ -420,7 +428,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
420
428
|
assert connection_state
|
421
429
|
return server, smile, client
|
422
430
|
except (
|
423
|
-
pw_exceptions.
|
431
|
+
pw_exceptions.ConnectionFailedError,
|
424
432
|
pw_exceptions.InvalidXMLError,
|
425
433
|
pw_exceptions.InvalidAuthentication,
|
426
434
|
) as exception:
|
@@ -451,7 +459,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
451
459
|
await self.connect(timeout=True)
|
452
460
|
_LOGGER.error(" - timeout not handled") # pragma: no cover
|
453
461
|
raise self.ConnectError # pragma: no cover
|
454
|
-
except
|
462
|
+
except pw_exceptions.ConnectionFailedError:
|
455
463
|
_LOGGER.info(" + successfully passed timeout handling.")
|
456
464
|
|
457
465
|
try:
|
@@ -478,7 +486,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
478
486
|
await self.connect_legacy(timeout=True)
|
479
487
|
_LOGGER.error(" - timeout not handled") # pragma: no cover
|
480
488
|
raise self.ConnectError # pragma: no cover
|
481
|
-
except
|
489
|
+
except pw_exceptions.ConnectionFailedError:
|
482
490
|
_LOGGER.info(" + successfully passed timeout handling.")
|
483
491
|
|
484
492
|
try:
|
@@ -628,6 +636,22 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
628
636
|
|
629
637
|
# pragma warning restore S3776
|
630
638
|
|
639
|
+
@pytest.mark.asyncio
|
640
|
+
async def tinker_reboot(self, smile, unhappy=False):
|
641
|
+
"""Test rebooting a gateway."""
|
642
|
+
_LOGGER.info("- Rebooting the gateway")
|
643
|
+
try:
|
644
|
+
await smile.reboot_gateway()
|
645
|
+
_LOGGER.info(" + worked as intended")
|
646
|
+
return True
|
647
|
+
except pw_exceptions.PlugwiseError:
|
648
|
+
if unhappy:
|
649
|
+
_LOGGER.info(" + failed as expected")
|
650
|
+
return False
|
651
|
+
else: # pragma: no cover
|
652
|
+
_LOGGER.info(" - failed unexpectedly")
|
653
|
+
return False
|
654
|
+
|
631
655
|
@pytest.mark.asyncio
|
632
656
|
async def tinker_switch(
|
633
657
|
self, smile, dev_id=None, members=None, model="relay", unhappy=False
|
@@ -645,10 +669,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
645
669
|
except pw_exceptions.PlugwiseError:
|
646
670
|
_LOGGER.info(" + locked, not switched as expected")
|
647
671
|
return False
|
648
|
-
except
|
649
|
-
pw_exceptions.ErrorSendingCommandError,
|
650
|
-
pw_exceptions.ResponseError,
|
651
|
-
):
|
672
|
+
except pw_exceptions.ConnectionFailedError:
|
652
673
|
if unhappy:
|
653
674
|
tinker_switch_passed = True # test is pass!
|
654
675
|
_LOGGER.info(" + failed as expected")
|
@@ -673,10 +694,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
673
694
|
await smile.set_temperature(loc_id, test_temp)
|
674
695
|
_LOGGER.info(" + tinker_thermostat_temp worked as intended")
|
675
696
|
tinker_temp_passed = True
|
676
|
-
except
|
677
|
-
pw_exceptions.ErrorSendingCommandError,
|
678
|
-
pw_exceptions.ResponseError,
|
679
|
-
):
|
697
|
+
except pw_exceptions.ConnectionFailedError:
|
680
698
|
if unhappy:
|
681
699
|
_LOGGER.info(" + tinker_thermostat_temp failed as expected")
|
682
700
|
tinker_temp_passed = True
|
@@ -703,10 +721,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
703
721
|
except pw_exceptions.PlugwiseError:
|
704
722
|
_LOGGER.info(" + found invalid preset, as expected")
|
705
723
|
tinker_preset_passed = True
|
706
|
-
except
|
707
|
-
pw_exceptions.ErrorSendingCommandError,
|
708
|
-
pw_exceptions.ResponseError,
|
709
|
-
):
|
724
|
+
except pw_exceptions.ConnectionFailedError:
|
710
725
|
if unhappy:
|
711
726
|
tinker_preset_passed = True
|
712
727
|
_LOGGER.info(" + tinker_thermostat_preset failed as expected")
|
@@ -733,16 +748,13 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
733
748
|
new_schedule = new_schedule[1:]
|
734
749
|
_LOGGER.info("- Adjusting schedule to %s", f"{new_schedule}{warning}")
|
735
750
|
try:
|
736
|
-
await smile.set_select("select_schedule", loc_id,
|
751
|
+
await smile.set_select("select_schedule", loc_id, new_schedule, state)
|
737
752
|
tinker_schedule_passed = True
|
738
753
|
_LOGGER.info(" + working as intended")
|
739
754
|
except pw_exceptions.PlugwiseError:
|
740
755
|
_LOGGER.info(" + failed as expected")
|
741
756
|
tinker_schedule_passed = True
|
742
|
-
except
|
743
|
-
pw_exceptions.ErrorSendingCommandError,
|
744
|
-
pw_exceptions.ResponseError,
|
745
|
-
):
|
757
|
+
except pw_exceptions.ConnectionFailedError:
|
746
758
|
tinker_schedule_passed = False
|
747
759
|
if unhappy:
|
748
760
|
_LOGGER.info(" + failed as expected before intended failure")
|
@@ -763,16 +775,13 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
763
775
|
for state in states:
|
764
776
|
_LOGGER.info("- Adjusting schedule to state %s", state)
|
765
777
|
try:
|
766
|
-
await smile.set_select("select_schedule", "dummy", state)
|
778
|
+
await smile.set_select("select_schedule", "dummy", None, state)
|
767
779
|
tinker_schedule_passed = True
|
768
780
|
_LOGGER.info(" + working as intended")
|
769
781
|
except pw_exceptions.PlugwiseError:
|
770
782
|
_LOGGER.info(" + failed as expected")
|
771
783
|
tinker_schedule_passed = True
|
772
|
-
except
|
773
|
-
pw_exceptions.ErrorSendingCommandError,
|
774
|
-
pw_exceptions.ResponseError,
|
775
|
-
):
|
784
|
+
except pw_exceptions.ConnectionFailedError:
|
776
785
|
tinker_schedule_passed = False
|
777
786
|
if unhappy:
|
778
787
|
_LOGGER.info(" + failed as expected before intended failure")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|