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.
Files changed (32) hide show
  1. {plugwise-0.37.8 → plugwise-0.38.0}/PKG-INFO +9 -8
  2. {plugwise-0.37.8 → plugwise-0.38.0}/README.md +8 -7
  3. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/__init__.py +54 -34
  4. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/constants.py +2 -0
  5. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/data.py +1 -0
  6. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/exceptions.py +4 -8
  7. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/helper.py +29 -3
  8. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/legacy/smile.py +7 -5
  9. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/smile.py +29 -14
  10. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise.egg-info/PKG-INFO +9 -8
  11. {plugwise-0.37.8 → plugwise-0.38.0}/pyproject.toml +2 -2
  12. {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_adam.py +22 -2
  13. {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_init.py +37 -28
  14. {plugwise-0.37.8 → plugwise-0.38.0}/LICENSE +0 -0
  15. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/common.py +0 -0
  16. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/legacy/data.py +0 -0
  17. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/legacy/helper.py +0 -0
  18. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/py.typed +0 -0
  19. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise/util.py +0 -0
  20. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise.egg-info/SOURCES.txt +0 -0
  21. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise.egg-info/dependency_links.txt +0 -0
  22. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise.egg-info/requires.txt +0 -0
  23. {plugwise-0.37.8 → plugwise-0.38.0}/plugwise.egg-info/top_level.txt +0 -0
  24. {plugwise-0.37.8 → plugwise-0.38.0}/setup.cfg +0 -0
  25. {plugwise-0.37.8 → plugwise-0.38.0}/setup.py +0 -0
  26. {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_anna.py +0 -0
  27. {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_generic.py +0 -0
  28. {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_legacy_anna.py +0 -0
  29. {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_legacy_generic.py +0 -0
  30. {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_legacy_p1.py +0 -0
  31. {plugwise-0.37.8 → plugwise-0.38.0}/tests/test_legacy_stretch.py +0 -0
  32. {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.37.8
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
  [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/plugwise)
57
- [![PyPI version fury.io](https://badge.fury.io/py/plugwise.svg)](https://pypi.python.org/pypi/plugwise/)
57
+ [![CodeRabbit.ai is Awesome](https://img.shields.io/badge/AI-orange?label=CodeRabbit&color=orange&link=https%3A%2F%2Fcoderabbit.ai)](https://coderabbit.ai)
58
+ [![renovate maintained](https://img.shields.io/badge/maintained%20with-renovate-blue?logo=renovatebot)](https://github.com/plugwise/python-plugwise/issues/291)
58
59
 
60
+ [![PyPI version fury.io](https://badge.fury.io/py/plugwise.svg)](https://pypi.python.org/pypi/plugwise/)
59
61
  [![Latest release](https://github.com/plugwise/python-plugwise/workflows/Latest%20release/badge.svg)](https://github.com/plugwise/python-plugwise/actions)
60
62
  [![Newest commit](https://github.com/plugwise/python-plugwise/workflows/Latest%20commit/badge.svg)](https://github.com/plugwise/python-plugwise/actions)
61
63
  [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/plugwise/python-plugwise/main.svg)](https://results.pre-commit.ci/latest/github/plugwise/python-plugwise/main)
62
- [![renovate maintained](https://img.shields.io/badge/maintained%20with-renovate-blue?logo=renovatebot)](https://github.com/plugwise/python-plugwise/issues/291)
63
64
 
64
65
  [![CodeFactor](https://www.codefactor.io/repository/github/plugwise/python-plugwise/badge)](https://www.codefactor.io/repository/github/plugwise/python-plugwise)
65
66
  [![codecov](https://codecov.io/gh/plugwise/python-plugwise/branch/main/graph/badge.svg)](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 make sure 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
+ 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` by @bouwew (Bouwe) & @CoMPaTech (Tom)
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
  [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/plugwise)
10
- [![PyPI version fury.io](https://badge.fury.io/py/plugwise.svg)](https://pypi.python.org/pypi/plugwise/)
10
+ [![CodeRabbit.ai is Awesome](https://img.shields.io/badge/AI-orange?label=CodeRabbit&color=orange&link=https%3A%2F%2Fcoderabbit.ai)](https://coderabbit.ai)
11
+ [![renovate maintained](https://img.shields.io/badge/maintained%20with-renovate-blue?logo=renovatebot)](https://github.com/plugwise/python-plugwise/issues/291)
11
12
 
13
+ [![PyPI version fury.io](https://badge.fury.io/py/plugwise.svg)](https://pypi.python.org/pypi/plugwise/)
12
14
  [![Latest release](https://github.com/plugwise/python-plugwise/workflows/Latest%20release/badge.svg)](https://github.com/plugwise/python-plugwise/actions)
13
15
  [![Newest commit](https://github.com/plugwise/python-plugwise/workflows/Latest%20commit/badge.svg)](https://github.com/plugwise/python-plugwise/actions)
14
16
  [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/plugwise/python-plugwise/main.svg)](https://results.pre-commit.ci/latest/github/plugwise/python-plugwise/main)
15
- [![renovate maintained](https://img.shields.io/badge/maintained%20with-renovate-blue?logo=renovatebot)](https://github.com/plugwise/python-plugwise/issues/291)
16
17
 
17
18
  [![CodeFactor](https://www.codefactor.io/repository/github/plugwise/python-plugwise/badge)](https://www.codefactor.io/repository/github/plugwise/python-plugwise)
18
19
  [![codecov](https://codecov.io/gh/plugwise/python-plugwise/branch/main/graph/badge.svg)](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 make sure 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
+ 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` by @bouwew (Bouwe) & @CoMPaTech (Tom)
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 InvalidSetupError, ResponseError, UnsupportedDeviceError
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
- if self.smile_legacy:
146
- self._smile_api = SmileLegacyAPI(
147
- self._host,
148
- self._passwd,
149
- self._websession,
150
- self._is_thermostat,
151
- self._on_off_device,
152
- self._opentherm_device,
153
- self._stretch_v2,
154
- self._target_smile,
155
- self.loc_data,
156
- self.smile_fw_version,
157
- self.smile_hostname,
158
- self.smile_hw_version,
159
- self.smile_mac_address,
160
- self.smile_model,
161
- self.smile_name,
162
- self.smile_type,
163
- self.smile_zigbee_mac_address,
164
- self._user,
165
- self._port,
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
- """Perform a first fetch of all XML data, needed for initialization."""
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
- """Determine the devices present from the obtained XML-data."""
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: PlugwiseData = await self._smile_api.async_update()
302
- self.gateway_id = data.gateway["gateway_id"]
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
- name: str | None = None,
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, name)
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
- new_state: str,
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, new_state, name)
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
- await self._smile_api.delete_notification()
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
 
@@ -38,6 +38,7 @@ class SmileData(SmileHelper):
38
38
  "gateway_id": self.gateway_id,
39
39
  "item_count": self._count,
40
40
  "notifications": self._notifications,
41
+ "reboot": True,
41
42
  "smile_name": self.smile_name,
42
43
  }
43
44
  )
@@ -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 stretch not responding with 202
156
- if method == "put" and resp.status == 200:
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 not (result := await resp.text()) or "<error>" in result:
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, name: str | None) -> None:
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 state corresponds to select option
188
- # schedule name corresponds to select name
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
- await self.full_update_device()
135
- self.get_all_devices()
136
-
137
- if "heater_id" in self.gw_data:
138
- self._heater_id = self.gw_data["heater_id"]
139
- if "cooling_enabled" in self.gw_devices[self._heater_id]["binary_sensors"]:
140
- self._cooling_enabled = self.gw_devices[self._heater_id]["binary_sensors"]["cooling_enabled"]
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._request(NOTIFICATIONS, method="delete")
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, name: str | None) -> None:
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 state corresponds to select option
222
- # schedule name corresponds to select name
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.37.8
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
  [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/plugwise)
57
- [![PyPI version fury.io](https://badge.fury.io/py/plugwise.svg)](https://pypi.python.org/pypi/plugwise/)
57
+ [![CodeRabbit.ai is Awesome](https://img.shields.io/badge/AI-orange?label=CodeRabbit&color=orange&link=https%3A%2F%2Fcoderabbit.ai)](https://coderabbit.ai)
58
+ [![renovate maintained](https://img.shields.io/badge/maintained%20with-renovate-blue?logo=renovatebot)](https://github.com/plugwise/python-plugwise/issues/291)
58
59
 
60
+ [![PyPI version fury.io](https://badge.fury.io/py/plugwise.svg)](https://pypi.python.org/pypi/plugwise/)
59
61
  [![Latest release](https://github.com/plugwise/python-plugwise/workflows/Latest%20release/badge.svg)](https://github.com/plugwise/python-plugwise/actions)
60
62
  [![Newest commit](https://github.com/plugwise/python-plugwise/workflows/Latest%20commit/badge.svg)](https://github.com/plugwise/python-plugwise/actions)
61
63
  [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/plugwise/python-plugwise/main.svg)](https://results.pre-commit.ci/latest/github/plugwise/python-plugwise/main)
62
- [![renovate maintained](https://img.shields.io/badge/maintained%20with-renovate-blue?logo=renovatebot)](https://github.com/plugwise/python-plugwise/issues/291)
63
64
 
64
65
  [![CodeFactor](https://www.codefactor.io/repository/github/plugwise/python-plugwise/badge)](https://www.codefactor.io/repository/github/plugwise/python-plugwise)
65
66
  [![codecov](https://codecov.io/gh/plugwise/python-plugwise/branch/main/graph/badge.svg)](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 make sure 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
+ 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` by @bouwew (Bouwe) & @CoMPaTech (Tom)
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~=69.0", "wheel~=0.43.0"]
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.37.8"
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.ResponseError:
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", "/core/notifications{tail:.*}", self.smile_timeout
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 TimeoutError
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.DeviceTimeoutError,
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.DeviceTimeoutError,
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 (pw_exceptions.DeviceTimeoutError, pw_exceptions.ResponseError):
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 (pw_exceptions.DeviceTimeoutError, pw_exceptions.ResponseError):
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, state, new_schedule)
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