aioWiserHeatAPI 1.5.4__tar.gz → 1.5.5__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 (51) hide show
  1. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/PKG-INFO +6 -2
  2. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/README.md +5 -1
  3. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/__init__.py +1 -1
  4. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/heating_actuator.py +65 -6
  5. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/capabilities.py +8 -6
  6. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/device.py +28 -6
  7. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/light.py +36 -11
  8. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/room.py +115 -24
  9. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/shutter.py +93 -27
  10. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/smartplug.py +3 -1
  11. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/system.py +109 -14
  12. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI.egg-info/PKG-INFO +6 -2
  13. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/LICENSE +0 -0
  14. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/cli.py +0 -0
  15. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/const.py +0 -0
  16. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/devices.py +0 -0
  17. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/discovery.py +0 -0
  18. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/exceptions.py +0 -0
  19. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/heating.py +0 -0
  20. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/__init__.py +0 -0
  21. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/automations.py +0 -0
  22. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/battery.py +0 -0
  23. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/cloud.py +0 -0
  24. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/equipment.py +0 -0
  25. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/extra_config.py +0 -0
  26. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/firmware.py +0 -0
  27. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/gps.py +0 -0
  28. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/misc.py +0 -0
  29. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/network.py +0 -0
  30. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/opentherm.py +0 -0
  31. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/signal.py +0 -0
  32. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/special_times.py +0 -0
  33. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/status.py +0 -0
  34. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/temp.py +0 -0
  35. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/helpers/zigbee.py +0 -0
  36. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/hot_water.py +0 -0
  37. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/moments.py +0 -0
  38. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/pte.py +0 -0
  39. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/rest_controller.py +0 -0
  40. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/roomstat.py +0 -0
  41. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/schedule.py +0 -0
  42. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/smartvalve.py +0 -0
  43. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/ufh.py +0 -0
  44. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI/wiserhub.py +0 -0
  45. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI.egg-info/SOURCES.txt +0 -0
  46. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI.egg-info/dependency_links.txt +0 -0
  47. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI.egg-info/entry_points.txt +0 -0
  48. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI.egg-info/requires.txt +0 -0
  49. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/aioWiserHeatAPI.egg-info/top_level.txt +0 -0
  50. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/setup.cfg +0 -0
  51. {aioWiserHeatAPI-1.5.4 → aioWiserHeatAPI-1.5.5}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: aioWiserHeatAPI
3
- Version: 1.5.4
3
+ Version: 1.5.5
4
4
  Summary: An AsyncIO API for controlling the Drayton Wiser Heating system
5
5
  Home-page: https://github.com/msp1974/aioWiserHeatAPI
6
6
  Author: Mark Parker
@@ -18,7 +18,7 @@ Requires-Dist: aiohttp>=3.9.1
18
18
  Requires-Dist: aiofiles>=23.2.1
19
19
  Requires-Dist: pyyaml>=6.0.1
20
20
 
21
- # Drayton Wiser Hub API Async v1.5.4
21
+ # Drayton Wiser Hub API Async v1.5.5
22
22
 
23
23
  This repository contains a simple API which queries the Drayton Wiser Heating sysystem used in the UK.
24
24
 
@@ -72,6 +72,10 @@ Documentation available in [info.md](https://github.com/msp1974/wiserHeatAPIv2/b
72
72
 
73
73
  ## Changelog
74
74
 
75
+ ### v1.5.5
76
+
77
+ * Added addtional v2 hub attributes and switches
78
+
75
79
  ### v1.5.4
76
80
 
77
81
  * Fixed issue whereby json conversion errors due to control characters in string
@@ -1,4 +1,4 @@
1
- # Drayton Wiser Hub API Async v1.5.4
1
+ # Drayton Wiser Hub API Async v1.5.5
2
2
 
3
3
  This repository contains a simple API which queries the Drayton Wiser Heating sysystem used in the UK.
4
4
 
@@ -52,6 +52,10 @@ Documentation available in [info.md](https://github.com/msp1974/wiserHeatAPIv2/b
52
52
 
53
53
  ## Changelog
54
54
 
55
+ ### v1.5.5
56
+
57
+ * Added addtional v2 hub attributes and switches
58
+
55
59
  ### v1.5.4
56
60
 
57
61
  * Fixed issue whereby json conversion errors due to control characters in string
@@ -3,6 +3,6 @@ import logging
3
3
  name = "aioWiserHeatAPI"
4
4
  __all__ = ["wiserAPI", "wiserDiscovery"]
5
5
 
6
- __VERSION__ = "1.5.4"
6
+ __VERSION__ = "1.5.5"
7
7
 
8
8
  _LOGGER = logging.getLogger(__name__)
@@ -1,4 +1,9 @@
1
- from .const import TEMP_OFF, TEXT_UNKNOWN, WISERHEATINGACTUATOR, WiserTempLimitsEnum
1
+ from .const import (
2
+ TEMP_OFF,
3
+ TEXT_UNKNOWN,
4
+ WISERHEATINGACTUATOR,
5
+ WiserTempLimitsEnum,
6
+ )
2
7
  from .helpers.device import _WiserDevice
3
8
  from .helpers.equipment import _WiserEquipment
4
9
  from .helpers.temp import _WiserTemperatureFunctions as tf
@@ -8,7 +13,9 @@ from .rest_controller import _WiserRestController
8
13
  class _WiserTemperatureSensor:
9
14
  """Data structure for plug in temp sensor"""
10
15
 
11
- def __init__(self, data: dict, wiser_rest_controller: _WiserRestController, id):
16
+ def __init__(
17
+ self, data: dict, wiser_rest_controller: _WiserRestController, id
18
+ ):
12
19
  self._data = data
13
20
  self._id = id
14
21
  self._wiser_rest_controller = wiser_rest_controller
@@ -45,7 +52,9 @@ class _WiserTemperatureSensor:
45
52
  return await self._send_command(
46
53
  {
47
54
  "FloorTemperatureSensor": {
48
- "MaximumTemperature": tf._to_wiser_temp(temp, "floorHeatingMax")
55
+ "MaximumTemperature": tf._to_wiser_temp(
56
+ temp, "floorHeatingMax"
57
+ )
49
58
  }
50
59
  }
51
60
  )
@@ -66,7 +75,9 @@ class _WiserTemperatureSensor:
66
75
  return await self._send_command(
67
76
  {
68
77
  "FloorTemperatureSensor": {
69
- "MinimumTemperature": tf._to_wiser_temp(temp, "floorHeatingMin")
78
+ "MinimumTemperature": tf._to_wiser_temp(
79
+ temp, "floorHeatingMin"
80
+ )
70
81
  }
71
82
  }
72
83
  )
@@ -85,7 +96,9 @@ class _WiserTemperatureSensor:
85
96
  @property
86
97
  def temperature_offset(self) -> float:
87
98
  """Get the temperature offset"""
88
- return tf._from_wiser_temp(self._data.get("Offset", None), "floorHeatingOffset")
99
+ return tf._from_wiser_temp(
100
+ self._data.get("Offset", None), "floorHeatingOffset"
101
+ )
89
102
 
90
103
  async def set_temperature_offset(self, temp: float):
91
104
  """Set the temperature offset"""
@@ -116,7 +129,8 @@ class _WiserHeatingActuator(_WiserDevice):
116
129
  def current_temperature(self) -> float:
117
130
  """Get the current measured temperature"""
118
131
  return tf._from_wiser_temp(
119
- self._device_type_data.get("MeasuredTemperature", TEMP_OFF), "current"
132
+ self._device_type_data.get("MeasuredTemperature", TEMP_OFF),
133
+ "current",
120
134
  )
121
135
 
122
136
  @property
@@ -158,6 +172,51 @@ class _WiserHeatingActuator(_WiserDevice):
158
172
  """Get output type"""
159
173
  return self._device_type_data.get("OutputType", TEXT_UNKNOWN)
160
174
 
175
+ # added by LGO
176
+ @property
177
+ def active_power(self) -> int:
178
+ """Get active power"""
179
+ return self._device_type_data.get("ActivePower", 0)
180
+
181
+ @property
182
+ def total_active_power(self) -> int:
183
+ """Get total active power"""
184
+ return self._device_type_data.get("TotalActivePower", 0)
185
+
186
+ @property
187
+ def operation_status(self) -> str:
188
+ """Get Operation status"""
189
+ return self._device_type_data.get("OperationStatus", TEXT_UNKNOWN)
190
+
191
+ @property
192
+ def fault_status(self) -> str:
193
+ """Get Fault status"""
194
+ return self._device_type_data.get("FaultStatus", TEXT_UNKNOWN)
195
+
196
+ # equipment for energy management
197
+ @property
198
+ def equipment_type(self) -> str:
199
+ """Get Equipment type"""
200
+ return self._device_type_data.get("EquipmentType", TEXT_UNKNOWN)
201
+
202
+ @property
203
+ def equipment_family(self) -> str:
204
+ """Get Equipment family"""
205
+ return self._device_type_data.get("EquipmentFamily", TEXT_UNKNOWN)
206
+
207
+ @property
208
+ def installation_type(self) -> str:
209
+ """Get Installation type"""
210
+ return self._device_type_data.get("InstallationType", TEXT_UNKNOWN)
211
+
212
+ @property
213
+ def number_of_phases(self) -> int:
214
+ """Get Installation type"""
215
+ return self._device_type_data.get("NumberOfPhases", 0)
216
+
217
+
218
+ # End added by LGO
219
+
161
220
 
162
221
  class _WiserHeatingActuatorCollection(object):
163
222
  """Class holding all wiser heating actuators"""
@@ -177,7 +177,9 @@ class _WiserHubFeatureCapabilitiesInfo:
177
177
  @property
178
178
  def automations(self) -> _WiserHubAutomationCapabilities:
179
179
  """Get automation capabilities"""
180
- return _WiserHubAutomationCapabilities(self._data.get("Automation", {}))
180
+ return _WiserHubAutomationCapabilities(
181
+ self._data.get("Automation", {})
182
+ )
181
183
 
182
184
  @property
183
185
  def pte(self) -> _WiserHubPTECapabilities:
@@ -195,12 +197,12 @@ class _WiserClimateCapabilities(object):
195
197
  @property
196
198
  def heating_supported(self) -> bool:
197
199
  """Get heating supported value"""
198
- return self._data.get("HeatingSupported")
200
+ return self._data.get("HeatingSupported", False)
199
201
 
200
202
  @property
201
203
  def cooling_supported(self) -> bool:
202
204
  """Get cooling supported value"""
203
- return self._data.get("CoolingSupported")
205
+ return self._data.get("CoolingSupported", False)
204
206
 
205
207
  @property
206
208
  def minimum_heat_set_point(self) -> int:
@@ -240,18 +242,18 @@ class _WiserClimateCapabilities(object):
240
242
  @property
241
243
  def open_window_detection(self) -> bool:
242
244
  """Get open window detection value"""
243
- return self._data.get("OpenWindowDetection")
245
+ return self._data.get("OpenWindowDetection", False)
244
246
 
245
247
  @property
246
248
  def hydronic_channel_selection(self) -> bool:
247
249
  """Get hydronic channel selection value"""
248
250
  if self._data:
249
- return self._data.get("HydronicChannelSelection")
251
+ return self._data.get("HydronicChannelSelection", False)
250
252
  return None
251
253
 
252
254
  @property
253
255
  def on_off_supported(self) -> bool:
254
256
  """Get on off supported value"""
255
257
  if self._data:
256
- return self._data.get("OnOffSupported")
258
+ return self._data.get("OnOffSupported", False)
257
259
  return None
@@ -25,6 +25,7 @@ class _WiserDevice(object):
25
25
  device_type_data: dict,
26
26
  schedule: dict = None,
27
27
  ):
28
+ self._away_action = None
28
29
  self._data = data
29
30
  self._device_type_data = device_type_data
30
31
  self._wiser_rest_controller = wiser_rest_controller
@@ -169,6 +170,26 @@ class _WiserDevice(object):
169
170
  """Get zwave network information"""
170
171
  return _WiserSignalStrength(self._data)
171
172
 
173
+ # Added by LGO
174
+ @property
175
+ def endpoint(self) -> int:
176
+ """Get endpoint"""
177
+ return self._device_type_data.get("Endpoint", 0)
178
+
179
+ # Device type Zigbee
180
+ @property
181
+ def type_comm(self) -> str:
182
+ """Get type of zigbee device"""
183
+ return self._data.get("Type", TEXT_UNKNOWN)
184
+
185
+ # UUID Zigbee
186
+ @property
187
+ def uuid(self) -> str:
188
+ """Get UUID zigbee"""
189
+ return self._device_type_data.get("UUID", TEXT_UNKNOWN)
190
+
191
+ # END Added by LGO
192
+
172
193
 
173
194
  class _WiserElectricalDevice(_WiserDevice):
174
195
  """Class representing a wiser electrical device"""
@@ -209,11 +230,11 @@ class _WiserElectricalDevice(_WiserDevice):
209
230
  return self._device_type_data.get("AwayAction", TEXT_UNKNOWN)
210
231
 
211
232
  async def set_away_mode_action(
212
- self, action: Union[WiserAwayActionEnum, WiserShutterAwayActionEnum, str]
233
+ self,
234
+ action: Union[WiserAwayActionEnum, WiserShutterAwayActionEnum, str],
213
235
  ) -> bool:
214
- if (
215
- type(action) == WiserAwayActionEnum
216
- or type(action) == WiserShutterAwayActionEnum
236
+ if isinstance(action, WiserAwayActionEnum) or isinstance(
237
+ action, WiserShutterAwayActionEnum
217
238
  ):
218
239
  action = action.value
219
240
 
@@ -223,7 +244,8 @@ class _WiserElectricalDevice(_WiserDevice):
223
244
  return True
224
245
  else:
225
246
  raise ValueError(
226
- f"{action} is not a valid away mode action. Valid modes are {self.available_away_mode_actions}"
247
+ f"{action} is not a valid away mode action. "
248
+ f"Valid modes are {self.available_away_mode_actions}"
227
249
  )
228
250
 
229
251
  @property
@@ -237,7 +259,7 @@ class _WiserElectricalDevice(_WiserDevice):
237
259
  return self._device_type_data.get("Mode", TEXT_UNKNOWN)
238
260
 
239
261
  async def set_mode(self, mode: Union[WiserDeviceModeEnum, str]) -> bool:
240
- if type(mode) == WiserDeviceModeEnum:
262
+ if isinstance(mode, WiserDeviceModeEnum):
241
263
  mode = mode.value
242
264
  if is_value_in_list(mode, self.available_modes):
243
265
  return await self._send_command({"Mode": mode.title()})
@@ -1,7 +1,13 @@
1
1
  import inspect
2
- from . import _LOGGER
3
2
 
4
- from .const import TEXT_ON, TEXT_OFF, TEXT_UNKNOWN, WISERDEVICE, WiserDeviceModeEnum
3
+ from . import _LOGGER
4
+ from .const import (
5
+ TEXT_OFF,
6
+ TEXT_ON,
7
+ TEXT_UNKNOWN,
8
+ WISERDEVICE,
9
+ WiserDeviceModeEnum,
10
+ )
5
11
  from .helpers.device import _WiserElectricalDevice
6
12
 
7
13
 
@@ -49,7 +55,7 @@ class _WiserLight(_WiserElectricalDevice):
49
55
  self._device_type_data = result
50
56
  if result:
51
57
  _LOGGER.debug(
52
- "Wiser smart plug - {} command successful".format(
58
+ "Wiser light - {} command successful".format(
53
59
  inspect.stack()[1].function
54
60
  )
55
61
  )
@@ -69,7 +75,9 @@ class _WiserLight(_WiserElectricalDevice):
69
75
  @property
70
76
  def is_dimmable(self) -> bool:
71
77
  """Get if the light is dimmable"""
72
- return True if self._device_type_data.get("IsDimmable", False) else False
78
+ return (
79
+ True if self._device_type_data.get("IsDimmable", False) else False
80
+ )
73
81
 
74
82
  @property
75
83
  def is_on(self) -> bool:
@@ -91,14 +99,18 @@ class _WiserLight(_WiserElectricalDevice):
91
99
  Turn on the light at current brightness level
92
100
  return: boolean
93
101
  """
94
- return await self._send_command({"RequestOverride": {"State": TEXT_ON}})
102
+ return await self._send_command(
103
+ {"RequestOverride": {"State": TEXT_ON}}
104
+ )
95
105
 
96
106
  async def turn_off(self) -> bool:
97
107
  """
98
108
  Turn off the light
99
109
  return: boolean
100
110
  """
101
- return await self._send_command({"RequestOverride": {"State": TEXT_OFF}})
111
+ return await self._send_command(
112
+ {"RequestOverride": {"State": TEXT_OFF}}
113
+ )
102
114
 
103
115
 
104
116
  class _WiserDimmableLight(_WiserLight):
@@ -118,10 +130,17 @@ class _WiserDimmableLight(_WiserLight):
118
130
  """Set current brightness percentage"""
119
131
  if percentage >= 0 and percentage <= 100:
120
132
  return await self._send_command(
121
- {"RequestOverride": {"State": TEXT_ON, "Percentage": percentage}}
133
+ {
134
+ "RequestOverride": {
135
+ "State": TEXT_ON,
136
+ "Percentage": percentage,
137
+ }
138
+ }
122
139
  )
123
140
  else:
124
- raise ValueError(f"Brightness level percentage must be between 0 and 100")
141
+ raise ValueError(
142
+ f"Brightness level percentage must be between 0 and 100"
143
+ )
125
144
 
126
145
  @property
127
146
  def manual_level(self) -> int:
@@ -137,7 +156,9 @@ class _WiserDimmableLight(_WiserLight):
137
156
  def output_range(self) -> _WiserOutputRange:
138
157
  """Get output range min/max."""
139
158
  # TODO: Add setter for min max values
140
- return _WiserOutputRange(self._device_type_data.get("OutputRange", None))
159
+ return _WiserOutputRange(
160
+ self._device_type_data.get("OutputRange", None)
161
+ )
141
162
 
142
163
  @property
143
164
  def scheduled_percentage(self) -> int:
@@ -179,7 +200,9 @@ class _WiserLightCollection(object):
179
200
  @property
180
201
  def onoff_lights(self) -> list:
181
202
  return list(
182
- onoff_lights for onoff_lights in self.all if not onoff_lights.is_dimmable
203
+ onoff_lights
204
+ for onoff_lights in self.all
205
+ if not onoff_lights.is_dimmable
183
206
  )
184
207
 
185
208
  def get_by_id(self, id: int) -> _WiserLight:
@@ -200,7 +223,9 @@ class _WiserLightCollection(object):
200
223
  return: _WiserLight object
201
224
  """
202
225
  try:
203
- return [light for light in self.all if light.light_id == light_id][0]
226
+ return [light for light in self.all if light.light_id == light_id][
227
+ 0
228
+ ]
204
229
  except IndexError:
205
230
  return None
206
231
 
@@ -44,7 +44,9 @@ class _WiserRoom(object):
44
44
  self._devices = devices
45
45
  self._enable_automations = enable_automations
46
46
  self._extra_config = (
47
- self._wiser_rest_controller._extra_config.config("Rooms", str(self.id))
47
+ self._wiser_rest_controller._extra_config.config(
48
+ "Rooms", str(self.id)
49
+ )
48
50
  if self._wiser_rest_controller._extra_config
49
51
  else None
50
52
  )
@@ -53,7 +55,12 @@ class _WiserRoom(object):
53
55
  )
54
56
 
55
57
  self._name = room.get("Name")
56
- self._window_detection_active = room.get("WindowDetectionActive", TEXT_UNKNOWN)
58
+ self._include_in_summer_comfort = room.get(
59
+ "IncludeInSummerComfort", False
60
+ )
61
+ self._window_detection_active = room.get(
62
+ "WindowDetectionActive", TEXT_UNKNOWN
63
+ )
57
64
 
58
65
  self._default_extra_config = {
59
66
  "passive_mode": False,
@@ -66,7 +73,9 @@ class _WiserRoom(object):
66
73
 
67
74
  # Add device id to schedule
68
75
  if self._schedule:
69
- self.schedule._assignments.append({"id": self.id, "name": self.name})
76
+ self.schedule._assignments.append(
77
+ {"id": self.id, "name": self.name}
78
+ )
70
79
 
71
80
  def _effective_heating_mode(self, mode: str, temp: float) -> str:
72
81
  if mode.casefold() == TEXT_MANUAL.casefold() and temp == TEMP_OFF:
@@ -76,7 +85,9 @@ class _WiserRoom(object):
76
85
  return WiserHeatingModeEnum.auto.value
77
86
 
78
87
  async def _send_command(
79
- self, cmd: dict, method: WiserRestActionEnum = WiserRestActionEnum.PATCH
88
+ self,
89
+ cmd: dict,
90
+ method: WiserRestActionEnum = WiserRestActionEnum.PATCH,
80
91
  ):
81
92
  """
82
93
  Send control command to the room
@@ -135,7 +146,9 @@ class _WiserRoom(object):
135
146
  def passive_mode_lower_temp(self) -> float:
136
147
  if self._extra_config and "min" in self._extra_config:
137
148
  return min(self._extra_config["min"], self.passive_mode_upper_temp)
138
- return min(self._default_extra_config["min"], self.passive_mode_upper_temp)
149
+ return min(
150
+ self._default_extra_config["min"], self.passive_mode_upper_temp
151
+ )
139
152
 
140
153
  @property
141
154
  def passive_mode_upper_temp(self) -> float:
@@ -155,10 +168,14 @@ class _WiserRoom(object):
155
168
  if not self.is_away_mode:
156
169
  # Set to min of temp range when initialised
157
170
  if enable and self.mode != WiserHeatingModeEnum.off.value:
158
- await self.set_target_temperature(self.passive_mode_lower_temp)
171
+ await self.set_target_temperature(
172
+ self.passive_mode_lower_temp
173
+ )
159
174
 
160
175
  # Set target temp back to last manual temp if in manual mode
161
- if (not enable) and self.mode == WiserHeatingModeEnum.manual.value:
176
+ if (
177
+ not enable
178
+ ) and self.mode == WiserHeatingModeEnum.manual.value:
162
179
  await self.set_target_temperature(
163
180
  self.stored_manual_target_temperature
164
181
  )
@@ -206,7 +223,9 @@ class _WiserRoom(object):
206
223
  """Get boost end timestamp"""
207
224
  if self._data.get("OverrideTimeoutUnixTime", 0) == 0:
208
225
  return None
209
- return datetime.fromtimestamp(self._data.get("OverrideTimeoutUnixTime", 0))
226
+ return datetime.fromtimestamp(
227
+ self._data.get("OverrideTimeoutUnixTime", 0)
228
+ )
210
229
 
211
230
  @property
212
231
  def boost_time_remaining(self) -> datetime:
@@ -242,7 +261,9 @@ class _WiserRoom(object):
242
261
  @property
243
262
  def current_target_temperature(self) -> float:
244
263
  """Get current target temperature for the room"""
245
- return tf._from_wiser_temp(self._data.get("DisplayedSetPoint", TEMP_MINIMUM))
264
+ return tf._from_wiser_temp(
265
+ self._data.get("DisplayedSetPoint", TEMP_MINIMUM)
266
+ )
246
267
 
247
268
  @property
248
269
  def current_temperature(self) -> float:
@@ -309,7 +330,8 @@ class _WiserRoom(object):
309
330
  True
310
331
  if "Away"
311
332
  in self._data.get(
312
- "SetpointOrigin", self._data.get("SetPointOrigin", TEXT_UNKNOWN)
333
+ "SetpointOrigin",
334
+ self._data.get("SetPointOrigin", TEXT_UNKNOWN),
313
335
  )
314
336
  else False
315
337
  )
@@ -321,7 +343,8 @@ class _WiserRoom(object):
321
343
  True
322
344
  if "Boost"
323
345
  in self._data.get(
324
- "SetpointOrigin", self._data.get("SetPointOrigin", TEXT_UNKNOWN)
346
+ "SetpointOrigin",
347
+ self._data.get("SetPointOrigin", TEXT_UNKNOWN),
325
348
  )
326
349
  else False
327
350
  )
@@ -340,13 +363,17 @@ class _WiserRoom(object):
340
363
  def is_heating(self) -> bool:
341
364
  """Get if the room is currently heating"""
342
365
  return (
343
- True if self._data.get("ControlOutputState", TEXT_OFF) == TEXT_ON else False
366
+ True
367
+ if self._data.get("ControlOutputState", TEXT_OFF) == TEXT_ON
368
+ else False
344
369
  )
345
370
 
346
371
  @property
347
372
  def manual_target_temperature(self) -> float:
348
373
  """Get current target temperature for manual mode"""
349
- return tf._from_wiser_temp(self._data.get("ManualSetPoint", TEMP_MINIMUM))
374
+ return tf._from_wiser_temp(
375
+ self._data.get("ManualSetPoint", TEMP_MINIMUM)
376
+ )
350
377
 
351
378
  @property
352
379
  def mode(self) -> str:
@@ -373,7 +400,9 @@ class _WiserRoom(object):
373
400
  self.stored_manual_target_temperature
374
401
  )
375
402
  elif mode == WiserHeatingModeEnum.auto.value:
376
- await self._send_command({"Mode": WiserHeatingModeEnum.auto.value})
403
+ await self._send_command(
404
+ {"Mode": WiserHeatingModeEnum.auto.value}
405
+ )
377
406
 
378
407
  self._mode = mode
379
408
  return True
@@ -439,8 +468,8 @@ class _WiserRoom(object):
439
468
  elif preset.lower().startswith(TEXT_BOOST.lower()):
440
469
  # Lookup boost duration
441
470
  duration = WISER_BOOST_DURATION[preset]
442
- _LOGGER.info(
443
- f"Boosting by {self._boost_temperature_delta} for {duration}"
471
+ _LOGGER.debug(
472
+ f"Boosting by {self._boost_temperature_delta}C for {duration} mins"
444
473
  )
445
474
  await self.boost(self._boost_temperature_delta, duration)
446
475
  else:
@@ -466,7 +495,9 @@ class _WiserRoom(object):
466
495
  @property
467
496
  def scheduled_target_temperature(self) -> float:
468
497
  """Get the scheduled target temperature for the room"""
469
- return tf._from_wiser_temp(self._data.get("ScheduledSetPoint", TEMP_MINIMUM))
498
+ return tf._from_wiser_temp(
499
+ self._data.get("ScheduledSetPoint", TEMP_MINIMUM)
500
+ )
470
501
 
471
502
  @property
472
503
  def smartvalve_ids(self) -> list:
@@ -507,6 +538,55 @@ class _WiserRoom(object):
507
538
  """Get the id of the underfloor heating controller relay ids"""
508
539
  return sorted(self._data.get("UfhRelayIds", []))
509
540
 
541
+ # Added by LGO
542
+ @property
543
+ def include_in_summer_comfort(self) -> bool:
544
+ """Get the status of participate to the summer comfort"""
545
+ return self._data.get("IncludeInSummerComfort")
546
+
547
+ async def set_include_in_summer_comfort(self, enabled: bool):
548
+ """Set the status of participate to the summer comfort"""
549
+ if await self._send_command({"IncludeInSummerComfort": enabled}):
550
+ self._include_in_summer_comfort = enabled
551
+ return True
552
+
553
+ @property
554
+ def hvac_mode(self) -> str:
555
+ """Get the HVAC mode of the room"""
556
+ return self._data.get("HVACMode", TEXT_UNKNOWN)
557
+
558
+ @property
559
+ def floor_sensor_state(self) -> str:
560
+ """Get the state of the floor sensor"""
561
+ return self._data.get("FloorSensorState", TEXT_UNKNOWN)
562
+
563
+ @property
564
+ def occupancy(self) -> str:
565
+ """Get the occupancy of the room"""
566
+ return self._data.get("Occupancy", TEXT_UNKNOWN)
567
+
568
+ @property
569
+ def occupancy_capable(self) -> bool:
570
+ """Get the occupancy of the room"""
571
+ return self._data.get("OccupancyCapable", False)
572
+
573
+ @property
574
+ def occupied_heating_set_point(self) -> int:
575
+ """Get the setpoint when the room is occupied"""
576
+ return self._data.get("OccupiedHeatingSetPoint", 85)
577
+
578
+ @property
579
+ def unoccupied_heating_set_point(self) -> int:
580
+ """Get the setpoint when the room is unoccupied"""
581
+ return self._data.get("UnoccupiedHeatingSetPoint", 65)
582
+
583
+ @property
584
+ def climate_demand_for_ui(self) -> int:
585
+ """Get the climate demand for UI"""
586
+ return self._data.get("ClimateDemandForUI", 0)
587
+
588
+ # End Added by LGO
589
+
510
590
  @property
511
591
  def window_detection_active(self) -> bool:
512
592
  """Get or set if window detection is active"""
@@ -545,7 +625,9 @@ class _WiserRoom(object):
545
625
  "RequestOverride": {
546
626
  "Type": "Boost",
547
627
  "DurationMinutes": duration,
548
- "IncreaseSetPointBy": tf._to_wiser_temp(inc_temp, "boostDelta"),
628
+ "IncreaseSetPointBy": tf._to_wiser_temp(
629
+ inc_temp, "boostDelta"
630
+ ),
549
631
  }
550
632
  }
551
633
  )
@@ -592,7 +674,10 @@ class _WiserRoom(object):
592
674
  return: boolean
593
675
  """
594
676
  # Set manual temp in stored config
595
- if self.mode == WiserHeatingModeEnum.manual.value and not self.is_passive_mode:
677
+ if (
678
+ self.mode == WiserHeatingModeEnum.manual.value
679
+ and not self.is_passive_mode
680
+ ):
596
681
  await self._update_extra_config("manual_temp", temp)
597
682
 
598
683
  return await self._send_command(
@@ -621,7 +706,9 @@ class _WiserRoom(object):
621
706
  return: boolean
622
707
  """
623
708
  if await self.cancel_boost():
624
- return await self.set_target_temperature(self.schedule.next.setting)
709
+ return await self.set_target_temperature(
710
+ self.schedule.next.setting
711
+ )
625
712
 
626
713
  async def cancel_overrides(self) -> bool:
627
714
  """
@@ -707,9 +794,11 @@ class _WiserRoomCollection:
707
794
  return: _WiserRoom object
708
795
  """
709
796
  try:
710
- return [room for room in self._rooms if room.name.lower() == name.lower()][
711
- 0
712
- ]
797
+ return [
798
+ room
799
+ for room in self._rooms
800
+ if room.name.lower() == name.lower()
801
+ ][0]
713
802
  except IndexError:
714
803
  return None
715
804
 
@@ -719,7 +808,9 @@ class _WiserRoomCollection:
719
808
  param schedule_id: the id of the schedule
720
809
  return: _WiserRoom object
721
810
  """
722
- return [room for room in self._rooms if room.schedule_id == schedule_id][0]
811
+ return [
812
+ room for room in self._rooms if room.schedule_id == schedule_id
813
+ ][0]
723
814
 
724
815
  def get_by_device_id(self, device_id: int) -> _WiserRoom:
725
816
  """
@@ -38,6 +38,12 @@ class _WiserLiftMovementRange(object):
38
38
  return self._data.get("LiftCloseTime")
39
39
  return None
40
40
 
41
+ async def set_close_time(self, time: int):
42
+ """Set close time"""
43
+ return await self._shutter_instance._send_command(
44
+ {"LiftOpenTime": self.open_time, "LiftCloseTime": time}
45
+ )
46
+
41
47
  @property
42
48
  def tilt_time(self) -> int:
43
49
  """Get tilt time value"""
@@ -58,7 +64,9 @@ class _WiserLiftMovementRange(object):
58
64
 
59
65
  async def set_tilt_angle_closed(self, angle: int):
60
66
  """Set tilt angle closed"""
61
- return await self._shutter_instance._send_command({"TiltAngleClosed": angle})
67
+ return await self._shutter_instance._send_command(
68
+ {"TiltAngleClosed": angle}
69
+ )
62
70
 
63
71
  @property
64
72
  def tilt_angle_open(self) -> int:
@@ -69,7 +77,9 @@ class _WiserLiftMovementRange(object):
69
77
 
70
78
  async def set_tilt_angle_open(self, angle: int):
71
79
  """Set tilt angle open"""
72
- return await self._shutter_instance._send_command({"TiltAngleOpen": angle})
80
+ return await self._shutter_instance._send_command(
81
+ {"TiltAngleOpen": angle}
82
+ )
73
83
 
74
84
  @property
75
85
  def tilt_enabled(self) -> bool:
@@ -82,12 +92,6 @@ class _WiserLiftMovementRange(object):
82
92
  """Set tilt enable"""
83
93
  return await self._shutter_instance._send_command({"TiltEnabled": en})
84
94
 
85
- async def set_close_time(self, time: int):
86
- """Set close time"""
87
- return await self._shutter_instance._send_command(
88
- {"LiftOpenTime": self.open_time, "LiftCloseTime": time}
89
- )
90
-
91
95
 
92
96
  class _WiserShutter(_WiserElectricalDevice):
93
97
  """Class representing a Wiser Shutter device"""
@@ -112,7 +116,7 @@ class _WiserShutter(_WiserElectricalDevice):
112
116
  self._device_type_data = result
113
117
  if result:
114
118
  _LOGGER.debug(
115
- "Wiser smart plug - {} command successful".format(
119
+ "Wiser shutter - {} command successful".format(
116
120
  inspect.stack()[1].function
117
121
  )
118
122
  )
@@ -141,7 +145,9 @@ class _WiserShutter(_WiserElectricalDevice):
141
145
  @property
142
146
  def drive_config(self) -> _WiserLiftMovementRange:
143
147
  """Get open and close time drive config"""
144
- return _WiserLiftMovementRange(self, self._device_type_data.get("DriveConfig"))
148
+ return _WiserLiftMovementRange(
149
+ self, self._device_type_data.get("DriveConfig")
150
+ )
145
151
 
146
152
  @property
147
153
  def is_lift_position_supported(self) -> bool:
@@ -156,19 +162,28 @@ class _WiserShutter(_WiserElectricalDevice):
156
162
  @property
157
163
  def is_open(self) -> bool:
158
164
  """Get if the shutter is open"""
159
- return True if self._device_type_data.get("CurrentLift", 0) == 100 else False
165
+ return (
166
+ True
167
+ if self._device_type_data.get("CurrentLift", 0) == 100
168
+ else False
169
+ )
160
170
 
161
171
  @property
162
172
  def is_closed(self) -> bool:
163
173
  """Get if the shutter is closed"""
164
- return True if self._device_type_data.get("CurrentLift", 0) == 0 else False
174
+ return (
175
+ True
176
+ if self._device_type_data.get("CurrentLift", 0) == 0
177
+ else False
178
+ )
165
179
 
166
180
  @property
167
181
  def is_closing(self) -> bool:
168
182
  """Get if shutter is moving-opening"""
169
183
  return (
170
184
  True
171
- if self._device_type_data.get("LiftMovement", TEXT_UNKNOWN) == "Closing"
185
+ if self._device_type_data.get("LiftMovement", TEXT_UNKNOWN)
186
+ == "Closing"
172
187
  else False
173
188
  )
174
189
 
@@ -177,7 +192,8 @@ class _WiserShutter(_WiserElectricalDevice):
177
192
  """Get if shutter is moving-opening"""
178
193
  return (
179
194
  True
180
- if self._device_type_data.get("LiftMovement", TEXT_UNKNOWN) == "Opening"
195
+ if self._device_type_data.get("LiftMovement", TEXT_UNKNOWN)
196
+ == "Opening"
181
197
  else False
182
198
  )
183
199
 
@@ -186,7 +202,8 @@ class _WiserShutter(_WiserElectricalDevice):
186
202
  """Get if shutter is not moving"""
187
203
  return (
188
204
  True
189
- if self._device_type_data.get("LiftMovement", TEXT_UNKNOWN) == "Stopped"
205
+ if self._device_type_data.get("LiftMovement", TEXT_UNKNOWN)
206
+ == "Stopped"
190
207
  else False
191
208
  )
192
209
 
@@ -195,7 +212,8 @@ class _WiserShutter(_WiserElectricalDevice):
195
212
  """Get if shutter is moving"""
196
213
  return (
197
214
  True
198
- if self._device_type_data.get("LiftMovement", TEXT_UNKNOWN) != "Stopped"
215
+ if self._device_type_data.get("LiftMovement", TEXT_UNKNOWN)
216
+ != "Stopped"
199
217
  else False
200
218
  )
201
219
 
@@ -239,14 +257,51 @@ class _WiserShutter(_WiserElectricalDevice):
239
257
  """Get target tilt of shutter"""
240
258
  return self._device_type_data.get("TargetTilt", 0)
241
259
 
260
+ @property
261
+ def respect_summer_comfort(self) -> bool:
262
+ """Get if the shutter respect summer comfort"""
263
+ return self._device_type_data.get("RespectSummerComfort", False)
264
+
265
+ async def set_respect_summer_comfort(self, en: bool):
266
+ """Set respect summer comfort"""
267
+ if await self._send_command({"RespectSummerComfort": en}):
268
+ return True
269
+
270
+ @property
271
+ def summer_comfort_lift(self) -> int:
272
+ """Get the shutter summer comfort lift"""
273
+ return self._device_type_data.get("SummerComfortLift")
274
+
275
+ async def set_summer_comfort_lift(self, lift: int):
276
+ if await self._send_command({"SummerComfortLift": lift}):
277
+ self._summer_comfort_lift = lift
278
+ return True
279
+
280
+ @property
281
+ def summer_comfort_tilt(self) -> int:
282
+ """Get the shutter summer comfort tilt"""
283
+ return self._device_type_data.get("SummerComfortTilt")
284
+
285
+ async def set_summer_comfort_tilt(self, tilt: int):
286
+ if await self._send_command({"SummerComfortTilt": tilt}):
287
+ self._summer_comfort_tilt = tilt
288
+ return True
289
+
242
290
  async def open(self, percentage: int = 100):
243
291
  """Fully open shutter"""
244
292
  if percentage >= 0 and percentage <= 100:
245
293
  return await self._send_command(
246
- {"RequestAction": {"Action": "LiftTo", "Percentage": percentage}}
294
+ {
295
+ "RequestAction": {
296
+ "Action": "LiftTo",
297
+ "Percentage": percentage,
298
+ }
299
+ }
247
300
  )
248
301
  else:
249
- raise ValueError("Shutter open percentage must be between 0 and 100")
302
+ raise ValueError(
303
+ "Shutter open percentage must be between 0 and 100"
304
+ )
250
305
 
251
306
  async def close(self):
252
307
  """Fully close shutter"""
@@ -258,24 +313,33 @@ class _WiserShutter(_WiserElectricalDevice):
258
313
  """Stop shutter during movement"""
259
314
  return await self._send_command({"RequestAction": {"Action": "Stop"}})
260
315
 
261
- async def open_tilt(self, percentage: int = 90):
262
- """Open shutter tilt to percentage"""
263
- if percentage >= 0 and percentage <= 90:
316
+ async def open_tilt(self, percentage: int = 100):
317
+ """Open tilt shutter to percentage"""
318
+ if percentage >= 0 and percentage <= 100:
264
319
  return await self._send_command(
265
- {"RequestAction": {"Action": "TiltTo", "Percentage": percentage}}
320
+ {
321
+ "RequestAction": {
322
+ "Action": "TiltTo",
323
+ "Percentage": percentage,
324
+ }
325
+ }
266
326
  )
267
327
  else:
268
- raise ValueError("Shutter tilt percentage must be between 0 and 100")
328
+ raise ValueError(
329
+ "Shutter tilt percentage must be between 0 and 100"
330
+ )
269
331
 
270
332
  async def close_tilt(self):
271
- """Fully close shutter tilt"""
333
+ """Fully close tilt shutter"""
272
334
  return await self._send_command(
273
335
  {"RequestAction": {"Action": "TiltTo", "Percentage": 0}}
274
336
  )
275
337
 
276
338
  async def stop_tilt(self):
277
- """Stop shutter tilt during movement"""
278
- return await self._send_command({"RequestAction": {"Action": "StopTilt"}})
339
+ """Stop tilt shutter during movement"""
340
+ return await self._send_command(
341
+ {"RequestAction": {"Action": "StopTilt"}}
342
+ )
279
343
 
280
344
 
281
345
  class _WiserShutterCollection(object):
@@ -315,7 +379,9 @@ class _WiserShutterCollection(object):
315
379
  """
316
380
  try:
317
381
  return [
318
- shutter for shutter in self.all if shutter.shutter_id == shutter_id
382
+ shutter
383
+ for shutter in self.all
384
+ if shutter.shutter_id == shutter_id
319
385
  ][0]
320
386
  except IndexError:
321
387
  return None
@@ -105,6 +105,8 @@ class _WiserSmartPlugCollection(object):
105
105
  return: _WiserSmartPlug object
106
106
  """
107
107
  try:
108
- return [smartplug for smartplug in self.all if smartplug.id == id][0]
108
+ return [smartplug for smartplug in self.all if smartplug.id == id][
109
+ 0
110
+ ]
109
111
  except IndexError:
110
112
  return None
@@ -49,7 +49,8 @@ class _WiserSystem(object):
49
49
  self._data.get("FeatureCapability", {})
50
50
  )
51
51
  self._cloud_data = _WiserCloud(
52
- self._system_data.get("CloudConnectionStatus"), self._data.get("Cloud", {})
52
+ self._system_data.get("CloudConnectionStatus"),
53
+ self._data.get("Cloud", {}),
53
54
  )
54
55
  self._device_data = self._get_system_device(device_data)
55
56
  self._network_data = _WiserNetwork(
@@ -61,7 +62,9 @@ class _WiserSystem(object):
61
62
  self._system_data.get("OpenThermConnectionStatus", TEXT_UNKNOWN),
62
63
  )
63
64
  self._signal = _WiserSignalStrength(self._device_data)
64
- self._upgrade_data = _WiserFirmareUpgradeInfo(self._data.get("UpgradeInfo", {}))
65
+ self._upgrade_data = _WiserFirmareUpgradeInfo(
66
+ self._data.get("UpgradeInfo", {})
67
+ )
65
68
  self._zigbee_data = _WiserZigbee(self._data.get("Zigbee", {}))
66
69
 
67
70
  # Variables to hold values for settabel values
@@ -74,15 +77,41 @@ class _WiserSystem(object):
74
77
  self._away_mode_target_temperature = self._system_data.get(
75
78
  "AwayModeSetPointLimit"
76
79
  )
77
- self._comfort_mode_enabled = self._system_data.get("ComfortModeEnabled")
80
+ self._comfort_mode_enabled = self._system_data.get(
81
+ "ComfortModeEnabled"
82
+ )
78
83
  self._degraded_mode_target_temperature = self._system_data.get(
79
84
  "DegradedModeSetpointThreshold"
80
85
  )
81
86
  self._eco_mode_enabled = self._system_data.get("EcoModeEnabled")
82
- self._hub_time = datetime.fromtimestamp(self._system_data.get("UnixTime"))
87
+ self._hub_time = datetime.fromtimestamp(
88
+ self._system_data.get("UnixTime")
89
+ )
83
90
  self._override_type = self._system_data.get("OverrideType", "")
84
91
  self._timezone_offset = self._system_data.get("TimeZoneOffset")
85
- self._valve_protection_enabled = self._system_data.get("ValveProtectionEnabled")
92
+ self._valve_protection_enabled = self._system_data.get(
93
+ "ValveProtectionEnabled"
94
+ )
95
+
96
+ # Added by LGO
97
+ # Summer comfort
98
+ self._summer_comfort_enabled = self._system_data.get(
99
+ "SummerComfortEnabled"
100
+ )
101
+ self._indoor_discomfort_temperature = self._system_data.get(
102
+ "IndoorDiscomfortTemperature"
103
+ )
104
+ self._outdoor_discomfort_temperature = self._system_data.get(
105
+ "OutdoorDiscomfortTemperature"
106
+ )
107
+ self._summer_comfort_available = self._system_data.get(
108
+ "SummerComfortAvailable"
109
+ )
110
+ self._summer_discomfort_prevention = self._system_data.get(
111
+ "SummerDiscomfortPrevention"
112
+ )
113
+
114
+ # End Added by LGO
86
115
 
87
116
  def _get_system_device(self, device_data: dict):
88
117
  for device in device_data:
@@ -101,10 +130,14 @@ class _WiserSystem(object):
101
130
  f"{WISERSYSTEM}/{path}", cmd
102
131
  )
103
132
  else:
104
- result = await self._wiser_rest_controller._send_command(WISERSYSTEM, cmd)
133
+ result = await self._wiser_rest_controller._send_command(
134
+ WISERSYSTEM, cmd
135
+ )
105
136
  if result:
106
137
  _LOGGER.debug(
107
- "Wiser hub - {} command successful".format(inspect.stack()[1].function)
138
+ "Wiser hub - {} command successful".format(
139
+ inspect.stack()[1].function
140
+ )
108
141
  )
109
142
  return True
110
143
  return False
@@ -120,7 +153,9 @@ class _WiserSystem(object):
120
153
  return self._automatic_daylight_saving
121
154
 
122
155
  async def set_automatic_daylight_saving_enabled(self, enabled: bool):
123
- if await self._send_command({"AutomaticDaylightSaving": str(enabled).lower()}):
156
+ if await self._send_command(
157
+ {"AutomaticDaylightSaving": str(enabled).lower()}
158
+ ):
124
159
  self._automatic_daylight_saving = enabled
125
160
  return True
126
161
 
@@ -130,7 +165,9 @@ class _WiserSystem(object):
130
165
  return True if self._override_type == "Away" else False
131
166
 
132
167
  async def set_away_mode_enabled(self, enabled: bool):
133
- if await self._send_command({"RequestOverride": {"Type": 2 if enabled else 0}}):
168
+ if await self._send_command(
169
+ {"RequestOverride": {"Type": 2 if enabled else 0}}
170
+ ):
134
171
  self._override_type = "Away" if enabled else ""
135
172
  return True
136
173
 
@@ -140,7 +177,9 @@ class _WiserSystem(object):
140
177
  return self._away_mode_affects_hotwater
141
178
 
142
179
  async def set_away_mode_affects_hotwater(self, enabled: bool = False):
143
- if await self._send_command({"AwayModeAffectsHotWater": str(enabled).lower()}):
180
+ if await self._send_command(
181
+ {"AwayModeAffectsHotWater": str(enabled).lower()}
182
+ ):
144
183
  self._away_mode_affects_hotwater = enabled
145
184
  return True
146
185
 
@@ -159,9 +198,9 @@ class _WiserSystem(object):
159
198
  def boiler_fuel_type(self) -> str:
160
199
  """Get boiler fuel type setting"""
161
200
  # TODO: Add ability to set to 1 of 3 types
162
- return self._system_data.get("BoilerSettings", {"FuelType": TEXT_UNKNOWN}).get(
163
- "FuelType"
164
- )
201
+ return self._system_data.get(
202
+ "BoilerSettings", {"FuelType": TEXT_UNKNOWN}
203
+ ).get("FuelType")
165
204
 
166
205
  @property
167
206
  def brand_name(self) -> str:
@@ -312,6 +351,60 @@ class _WiserSystem(object):
312
351
  """Get zwave network information"""
313
352
  return self._signal
314
353
 
354
+ # Added LGO
355
+ @property
356
+ def summer_comfort_enabled(self) -> bool:
357
+ """Get whether summer comfort mode is enabled"""
358
+ return self._summer_comfort_enabled
359
+
360
+ async def set_summer_comfort_enabled(self, enabled: bool):
361
+ """Set whether summer comfort mode is enabled"""
362
+ if await self._send_command({"SummerComfortEnabled": enabled}):
363
+ self._summer_comfort_enabled = enabled
364
+ return True
365
+
366
+ @property
367
+ def indoor_discomfort_temperature(self) -> float:
368
+ """Get indoor discomfort temperature for summer comfort"""
369
+ return tf._from_wiser_temp(self._indoor_discomfort_temperature)
370
+
371
+ async def set_indoor_discomfort_temperature(self, temp: float):
372
+ """Set indoor discomfort temperature for summer comfort"""
373
+ temp = tf._to_wiser_temp(temp)
374
+ if await self._send_command({"IndoorDiscomfortTemperature": temp}):
375
+ self._away_mode_target_temperature = tf._to_wiser_temp(temp)
376
+ return True
377
+
378
+ @property
379
+ def outdoor_discomfort_temperature(self) -> float:
380
+ """Get outdoor discomfort temperature for summer comfort"""
381
+ return tf._from_wiser_temp(self._outdoor_discomfort_temperature)
382
+
383
+ async def set_outdoor_discomfort_temperature(self, temp: float):
384
+ """Set outdoor discomfort temperature for summer comfort"""
385
+ temp = tf._to_wiser_temp(temp)
386
+ if await self._send_command({"OutdoorDiscomfortTemperature": temp}):
387
+ self._away_mode_target_temperature = tf._to_wiser_temp(temp)
388
+ return True
389
+
390
+ @property
391
+ def summer_comfort_available(self) -> bool:
392
+ """Get whether summer comfort mode is available"""
393
+ return self._summer_comfort_available
394
+
395
+ @property
396
+ def summer_discomfort_prevention(self) -> bool:
397
+ """Get summer discomfort prevention"""
398
+ return self._summer_discomfort_prevention
399
+
400
+ async def set_summer_discomfort_prevention(self, enabled: bool):
401
+ """Set summer discomfort prevention"""
402
+ if await self._send_command({"SummerDiscomfortPrevention": enabled}):
403
+ self._summer_discomfort_prevention = enabled
404
+ return True
405
+
406
+ # End Added LGO
407
+
315
408
  @property
316
409
  def sunrise_times(self) -> list:
317
410
  """Get sunrise times"""
@@ -377,7 +470,9 @@ class _WiserSystem(object):
377
470
  "RequestOverride": {
378
471
  "Type": "Boost",
379
472
  "DurationMinutes": duration,
380
- "IncreaseSetPointBy": tf._to_wiser_temp(inc_temp, "boostDelta"),
473
+ "IncreaseSetPointBy": tf._to_wiser_temp(
474
+ inc_temp, "boostDelta"
475
+ ),
381
476
  }
382
477
  }
383
478
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: aioWiserHeatAPI
3
- Version: 1.5.4
3
+ Version: 1.5.5
4
4
  Summary: An AsyncIO API for controlling the Drayton Wiser Heating system
5
5
  Home-page: https://github.com/msp1974/aioWiserHeatAPI
6
6
  Author: Mark Parker
@@ -18,7 +18,7 @@ Requires-Dist: aiohttp>=3.9.1
18
18
  Requires-Dist: aiofiles>=23.2.1
19
19
  Requires-Dist: pyyaml>=6.0.1
20
20
 
21
- # Drayton Wiser Hub API Async v1.5.4
21
+ # Drayton Wiser Hub API Async v1.5.5
22
22
 
23
23
  This repository contains a simple API which queries the Drayton Wiser Heating sysystem used in the UK.
24
24
 
@@ -72,6 +72,10 @@ Documentation available in [info.md](https://github.com/msp1974/wiserHeatAPIv2/b
72
72
 
73
73
  ## Changelog
74
74
 
75
+ ### v1.5.5
76
+
77
+ * Added addtional v2 hub attributes and switches
78
+
75
79
  ### v1.5.4
76
80
 
77
81
  * Fixed issue whereby json conversion errors due to control characters in string
File without changes