aioWiserHeatAPI 1.5.19__tar.gz → 1.6.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.
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/PKG-INFO +12 -2
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/README.md +11 -1
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/__init__.py +1 -1
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/binary_sensor.py +40 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/const.py +3 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/devices.py +236 -68
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/heating_actuator.py +18 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/device.py +10 -2
- aiowiserheatapi-1.6.0/aioWiserHeatAPI/helpers/threshold.py +93 -0
- aiowiserheatapi-1.6.0/aioWiserHeatAPI/helpers/uiconfiguration.py +73 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/hot_water.py +114 -35
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/light.py +24 -3
- aiowiserheatapi-1.6.0/aioWiserHeatAPI/ptc.py +201 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI.egg-info/PKG-INFO +12 -2
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI.egg-info/SOURCES.txt +3 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/LICENSE +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/automation.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/boiler_interface.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/button_panel.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/cli.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/discovery.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/exceptions.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/heating.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/__init__.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/automations.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/battery.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/capabilities.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/cloud.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/equipment.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/extra_config.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/firmware.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/gps.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/misc.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/network.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/opentherm.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/signal.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/special_times.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/status.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/temp.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/version.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/helpers/zigbee.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/moments.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/pte.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/rest_controller.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/room.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/roomstat.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/schedule.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/shutter.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/smartplug.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/smartvalve.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/smokealarm.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/system.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/ufh.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI/wiserhub.py +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI.egg-info/dependency_links.txt +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI.egg-info/entry_points.txt +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI.egg-info/requires.txt +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/aioWiserHeatAPI.egg-info/top_level.txt +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/setup.cfg +0 -0
- {aiowiserheatapi-1.5.19 → aiowiserheatapi-1.6.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: aioWiserHeatAPI
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.0
|
|
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.3
|
|
|
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.
|
|
21
|
+
# Drayton Wiser Hub API Async v1.6.0
|
|
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,16 @@ Documentation available in [info.md](https://github.com/msp1974/wiserHeatAPIv2/b
|
|
|
72
72
|
|
|
73
73
|
## Changelog
|
|
74
74
|
|
|
75
|
+
### v1.6.0
|
|
76
|
+
* Refactored how devices are enumerated
|
|
77
|
+
* BREAKING CHANGE - threshold sensor is now a device attribute and not its own device
|
|
78
|
+
* Added: support for 2 gang light switches
|
|
79
|
+
* Added: support for threshold and UI configuration as device attributes
|
|
80
|
+
* Added: support for PTC devices
|
|
81
|
+
* Added: UUID now exists for all devices (for future use)
|
|
82
|
+
* Added: New attributes and stored extra config for Hot Water to support HW Climate automation in HA integration
|
|
83
|
+
* Added: Control of interacts with room climate for binary sensors
|
|
84
|
+
|
|
75
85
|
### v1.5.19
|
|
76
86
|
* Fixed error when BoilerInterface does not provide DeviceId field
|
|
77
87
|
* Fixed not supporting non ascii characters in schedule names
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Drayton Wiser Hub API Async v1.
|
|
1
|
+
# Drayton Wiser Hub API Async v1.6.0
|
|
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,16 @@ Documentation available in [info.md](https://github.com/msp1974/wiserHeatAPIv2/b
|
|
|
52
52
|
|
|
53
53
|
## Changelog
|
|
54
54
|
|
|
55
|
+
### v1.6.0
|
|
56
|
+
* Refactored how devices are enumerated
|
|
57
|
+
* BREAKING CHANGE - threshold sensor is now a device attribute and not its own device
|
|
58
|
+
* Added: support for 2 gang light switches
|
|
59
|
+
* Added: support for threshold and UI configuration as device attributes
|
|
60
|
+
* Added: support for PTC devices
|
|
61
|
+
* Added: UUID now exists for all devices (for future use)
|
|
62
|
+
* Added: New attributes and stored extra config for Hot Water to support HW Climate automation in HA integration
|
|
63
|
+
* Added: Control of interacts with room climate for binary sensors
|
|
64
|
+
|
|
55
65
|
### v1.5.19
|
|
56
66
|
* Fixed error when BoilerInterface does not provide DeviceId field
|
|
57
67
|
* Fixed not supporting non ascii characters in schedule names
|
|
@@ -2,13 +2,43 @@
|
|
|
2
2
|
Handles binary_sensor devices
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import inspect
|
|
6
|
+
|
|
7
|
+
from aioWiserHeatAPI import _LOGGER
|
|
8
|
+
|
|
5
9
|
from .helpers.battery import _WiserBattery
|
|
6
10
|
from .helpers.device import _WiserDevice
|
|
11
|
+
from .helpers.threshold import _WiserThresholdSensor
|
|
7
12
|
|
|
8
13
|
|
|
9
14
|
class _WiserBinarySensor(_WiserDevice):
|
|
10
15
|
"""Class representing a Wiser Binary Sensor"""
|
|
11
16
|
|
|
17
|
+
def __init__(self, *args):
|
|
18
|
+
"""Initialise."""
|
|
19
|
+
super().__init__(*args)
|
|
20
|
+
self._threshold_sensors: list[_WiserThresholdSensor] = []
|
|
21
|
+
|
|
22
|
+
async def _send_command(self, cmd: dict):
|
|
23
|
+
"""
|
|
24
|
+
Send control command to the Threshold sensor
|
|
25
|
+
param cmd: json command structure
|
|
26
|
+
return: boolen - true = success, false = failed
|
|
27
|
+
"""
|
|
28
|
+
result = await self._wiser_rest_controller._send_command(
|
|
29
|
+
self._endpoint.format(self.device_type_id), cmd
|
|
30
|
+
)
|
|
31
|
+
if result:
|
|
32
|
+
self._device_type_data = result
|
|
33
|
+
if result:
|
|
34
|
+
_LOGGER.debug(
|
|
35
|
+
"Wiser light - {} command successful".format(
|
|
36
|
+
inspect.stack()[1].function
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
return True
|
|
40
|
+
return False
|
|
41
|
+
|
|
12
42
|
@property
|
|
13
43
|
def active(self) -> bool:
|
|
14
44
|
"""Get if is active"""
|
|
@@ -19,6 +49,11 @@ class _WiserBinarySensor(_WiserDevice):
|
|
|
19
49
|
"""Get the if interacts with room climate"""
|
|
20
50
|
return self._device_type_data.get("InteractsWithRoomClimate")
|
|
21
51
|
|
|
52
|
+
async def set_interacts_with_room_climate(self, enabled: bool):
|
|
53
|
+
if await self._send_command({"InteractsWithRoomClimate": str(enabled).lower()}):
|
|
54
|
+
self._interacts_with_room_climate = enabled
|
|
55
|
+
return True
|
|
56
|
+
|
|
22
57
|
@property
|
|
23
58
|
def type(self) -> str:
|
|
24
59
|
"""Get the type of device"""
|
|
@@ -34,6 +69,11 @@ class _WiserBinarySensor(_WiserDevice):
|
|
|
34
69
|
"""Get the battery information for the smokealarm"""
|
|
35
70
|
return _WiserBattery(self._data)
|
|
36
71
|
|
|
72
|
+
@property
|
|
73
|
+
def threshold_sensors(self) -> list[_WiserThresholdSensor]:
|
|
74
|
+
"""Get threshold sensors."""
|
|
75
|
+
return self._threshold_sensors
|
|
76
|
+
|
|
37
77
|
|
|
38
78
|
class _WiserWindowDoorSensor(_WiserBinarySensor):
|
|
39
79
|
"""Class representing a Wiser WindowDoor Sensor"""
|
|
@@ -101,11 +101,14 @@ WISERHEATINGACTUATOR = "HeatingActuator/{}"
|
|
|
101
101
|
WISERUFHCONTROLLER = "UnderFloorHeating/{}"
|
|
102
102
|
WISERSHUTTER = "Shutter/{}"
|
|
103
103
|
WISERLIGHT = "Light/{}"
|
|
104
|
+
WISERPOWERTAGCONTROL = "PTC/{}"
|
|
104
105
|
WISERPOWERTAGENERGY = "PTE/{}"
|
|
105
106
|
WISERSMOKEALARM = "SmokeAlarmDevice/{}"
|
|
106
107
|
WISERBINARYSENSOR = "BinarySensor/{}"
|
|
107
108
|
WISERBOILERINTERFACE = "BoilerInterface/{}"
|
|
108
109
|
WISERBUTTONPANEL = "ButtonPanel/{}"
|
|
110
|
+
WISERTHRESHOLDSENSOR = "ThresholdSensor/{}"
|
|
111
|
+
WISERUICONFIGURATION = "UIConfiguration/{}"
|
|
109
112
|
|
|
110
113
|
|
|
111
114
|
# Enums
|
|
@@ -3,28 +3,41 @@ Module to manage all devices
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import enum
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import Any
|
|
6
8
|
|
|
7
|
-
from .binary_sensor import
|
|
9
|
+
from .binary_sensor import (
|
|
10
|
+
_WiserBinarySensor,
|
|
11
|
+
_WiserBinarySensorCollection,
|
|
12
|
+
_WiserWindowDoorSensor,
|
|
13
|
+
)
|
|
8
14
|
from .boiler_interface import _WiserBoilerInterface, _WiserBoilerInterfaceCollection
|
|
9
15
|
from .button_panel import _WiserButtonPanel, _WiserButtonPanelCollection
|
|
10
16
|
from .const import (
|
|
11
|
-
TEXT_UNKNOWN,
|
|
12
17
|
WISERBINARYSENSOR,
|
|
13
18
|
WISERBOILERINTERFACE,
|
|
14
19
|
WISERBUTTONPANEL,
|
|
15
20
|
WISERHEATINGACTUATOR,
|
|
16
21
|
WISERLIGHT,
|
|
22
|
+
WISERPOWERTAGCONTROL,
|
|
17
23
|
WISERPOWERTAGENERGY,
|
|
18
24
|
WISERROOMSTAT,
|
|
19
25
|
WISERSHUTTER,
|
|
20
26
|
WISERSMARTPLUG,
|
|
21
27
|
WISERSMARTVALVE,
|
|
22
28
|
WISERSMOKEALARM,
|
|
29
|
+
WISERTHRESHOLDSENSOR,
|
|
23
30
|
WISERUFHCONTROLLER,
|
|
31
|
+
WISERUICONFIGURATION,
|
|
24
32
|
)
|
|
25
33
|
from .heating_actuator import _WiserHeatingActuator, _WiserHeatingActuatorCollection
|
|
26
34
|
from .helpers.device import _WiserDevice
|
|
35
|
+
from .helpers.threshold import (
|
|
36
|
+
_WiserThresholdSensor,
|
|
37
|
+
)
|
|
38
|
+
from .helpers.uiconfiguration import _WiserUIConfigSensor
|
|
27
39
|
from .light import _WiserDimmableLight, _WiserLight, _WiserLightCollection
|
|
40
|
+
from .ptc import _WiserPowerTagControl, _WiserPowerTagControlCollection
|
|
28
41
|
from .pte import _WiserPowerTagEnergy, _WiserPowerTagEnergyCollection
|
|
29
42
|
from .rest_controller import _WiserRestController
|
|
30
43
|
from .roomstat import _WiserRoomStat, _WiserRoomStatCollection
|
|
@@ -36,6 +49,116 @@ from .smokealarm import _WiserSmokeAlarm, _WiserSmokeAlarmCollection
|
|
|
36
49
|
from .ufh import _WiserUFHController, _WiserUFHControllerCollection
|
|
37
50
|
|
|
38
51
|
|
|
52
|
+
@dataclass(frozen=True, kw_only=True)
|
|
53
|
+
class DeviceConfig:
|
|
54
|
+
device_class: Any
|
|
55
|
+
collection: Any
|
|
56
|
+
endpoint: str = None
|
|
57
|
+
heating: bool = False
|
|
58
|
+
schedule_type: WiserScheduleTypeEnum | None = None
|
|
59
|
+
has_v2_equipment: bool = False
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass(frozen=True, kw_only=True)
|
|
63
|
+
class AncillaryDeviceConfig:
|
|
64
|
+
device_class: Any
|
|
65
|
+
attribute: str
|
|
66
|
+
endpoint: str = None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
PRODUCT_TYPE_CONFIG = {
|
|
70
|
+
"SmartValve": DeviceConfig(
|
|
71
|
+
device_class=_WiserSmartValve,
|
|
72
|
+
collection=_WiserSmartValveCollection,
|
|
73
|
+
endpoint=WISERSMARTVALVE,
|
|
74
|
+
heating=True,
|
|
75
|
+
),
|
|
76
|
+
"RoomStat": DeviceConfig(
|
|
77
|
+
device_class=_WiserRoomStat,
|
|
78
|
+
collection=_WiserRoomStatCollection,
|
|
79
|
+
endpoint=WISERROOMSTAT,
|
|
80
|
+
heating=True,
|
|
81
|
+
),
|
|
82
|
+
"SmartPlug": DeviceConfig(
|
|
83
|
+
device_class=_WiserSmartPlug,
|
|
84
|
+
collection=_WiserSmartPlugCollection,
|
|
85
|
+
endpoint=WISERSMARTPLUG,
|
|
86
|
+
schedule_type=WiserScheduleTypeEnum.onoff,
|
|
87
|
+
has_v2_equipment=True,
|
|
88
|
+
),
|
|
89
|
+
"HeatingActuator": DeviceConfig(
|
|
90
|
+
device_class=_WiserHeatingActuator,
|
|
91
|
+
collection=_WiserHeatingActuatorCollection,
|
|
92
|
+
endpoint=WISERHEATINGACTUATOR,
|
|
93
|
+
heating=True,
|
|
94
|
+
has_v2_equipment=True,
|
|
95
|
+
),
|
|
96
|
+
"UnderFloorHeating": DeviceConfig(
|
|
97
|
+
device_class=_WiserUFHController,
|
|
98
|
+
collection=_WiserUFHControllerCollection,
|
|
99
|
+
endpoint=WISERUFHCONTROLLER,
|
|
100
|
+
heating=True,
|
|
101
|
+
),
|
|
102
|
+
"Light": DeviceConfig(
|
|
103
|
+
device_class=_WiserLight,
|
|
104
|
+
collection=_WiserLightCollection,
|
|
105
|
+
endpoint=WISERLIGHT,
|
|
106
|
+
schedule_type=WiserScheduleTypeEnum.level,
|
|
107
|
+
),
|
|
108
|
+
"Shutter": DeviceConfig(
|
|
109
|
+
device_class=_WiserShutter,
|
|
110
|
+
collection=_WiserShutterCollection,
|
|
111
|
+
endpoint=WISERSHUTTER,
|
|
112
|
+
schedule_type=WiserScheduleTypeEnum.level,
|
|
113
|
+
),
|
|
114
|
+
"PTC": DeviceConfig(
|
|
115
|
+
device_class=_WiserPowerTagControl,
|
|
116
|
+
collection=_WiserPowerTagControlCollection,
|
|
117
|
+
endpoint=WISERPOWERTAGCONTROL,
|
|
118
|
+
has_v2_equipment=True,
|
|
119
|
+
),
|
|
120
|
+
"PTE": DeviceConfig(
|
|
121
|
+
device_class=_WiserPowerTagEnergy,
|
|
122
|
+
collection=_WiserPowerTagEnergyCollection,
|
|
123
|
+
endpoint=WISERPOWERTAGENERGY,
|
|
124
|
+
has_v2_equipment=True,
|
|
125
|
+
),
|
|
126
|
+
"SmokeAlarmDevice": DeviceConfig(
|
|
127
|
+
device_class=_WiserSmokeAlarm,
|
|
128
|
+
collection=_WiserSmokeAlarmCollection,
|
|
129
|
+
endpoint=WISERSMOKEALARM,
|
|
130
|
+
),
|
|
131
|
+
"BinarySensor": DeviceConfig(
|
|
132
|
+
device_class=_WiserBinarySensor,
|
|
133
|
+
collection=_WiserBinarySensorCollection,
|
|
134
|
+
endpoint=WISERBINARYSENSOR,
|
|
135
|
+
),
|
|
136
|
+
"BoilerInterface": DeviceConfig(
|
|
137
|
+
device_class=_WiserBoilerInterface,
|
|
138
|
+
collection=_WiserBoilerInterfaceCollection,
|
|
139
|
+
endpoint=WISERBOILERINTERFACE,
|
|
140
|
+
),
|
|
141
|
+
"ButtonPanel": DeviceConfig(
|
|
142
|
+
device_class=_WiserButtonPanel,
|
|
143
|
+
collection=_WiserButtonPanelCollection,
|
|
144
|
+
endpoint=WISERBUTTONPANEL,
|
|
145
|
+
),
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
ANCILLARY_SENSOR_CONFIG = {
|
|
149
|
+
"ThresholdSensor": AncillaryDeviceConfig(
|
|
150
|
+
device_class=_WiserThresholdSensor,
|
|
151
|
+
attribute="_threshold_sensors",
|
|
152
|
+
endpoint=WISERTHRESHOLDSENSOR,
|
|
153
|
+
),
|
|
154
|
+
"UIConfiguration": AncillaryDeviceConfig(
|
|
155
|
+
device_class=_WiserUIConfigSensor,
|
|
156
|
+
attribute="_uiconfig_sensors",
|
|
157
|
+
endpoint=WISERUICONFIGURATION,
|
|
158
|
+
),
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
|
|
39
162
|
class _WiserDeviceTypeEnum(enum.Enum):
|
|
40
163
|
iTRV = "SmartValve"
|
|
41
164
|
RoomStat = "RoomStat"
|
|
@@ -53,7 +176,7 @@ class _WiserDeviceTypeEnum(enum.Enum):
|
|
|
53
176
|
ButtonPanel = "ButtonPanel"
|
|
54
177
|
|
|
55
178
|
|
|
56
|
-
|
|
179
|
+
PRODUCT_TYPE_CONFIG_OLD = {
|
|
57
180
|
"iTRV": {
|
|
58
181
|
"class": _WiserSmartValve,
|
|
59
182
|
"collection": _WiserSmartValveCollection,
|
|
@@ -167,79 +290,86 @@ class _WiserDeviceCollection:
|
|
|
167
290
|
]
|
|
168
291
|
return equipment_data[0] if equipment_data else None
|
|
169
292
|
|
|
170
|
-
def
|
|
171
|
-
"""
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
device_type.value not in self._device_collection
|
|
177
|
-
and device_type.name in PRODUCT_TYPE_CONFIG
|
|
178
|
-
):
|
|
179
|
-
self._device_collection[device_type.value] = PRODUCT_TYPE_CONFIG[
|
|
180
|
-
device_type.name
|
|
181
|
-
].get("collection")()
|
|
182
|
-
|
|
183
|
-
# Iterate device data for all known device types
|
|
184
|
-
if self._device_data:
|
|
185
|
-
for device in self._device_data:
|
|
186
|
-
device_type = device.get("ProductType", TEXT_UNKNOWN)
|
|
187
|
-
if device_type in PRODUCT_TYPE_CONFIG:
|
|
188
|
-
device_config = PRODUCT_TYPE_CONFIG[device_type]
|
|
189
|
-
device_info = [
|
|
190
|
-
device_info
|
|
191
|
-
for device_info in self._domain_data.get(
|
|
192
|
-
_WiserDeviceTypeEnum[device_type].value
|
|
193
|
-
)
|
|
194
|
-
if device_info.get("DeviceId", device_info.get("id"))
|
|
195
|
-
== device.get("id")
|
|
196
|
-
]
|
|
293
|
+
def _get_device_info_by_id(self, device_id: int) -> dict[str, Any] | None:
|
|
294
|
+
"""Get device entry by id."""
|
|
295
|
+
for device in self._domain_data.get("Device"):
|
|
296
|
+
if device.get("id") == device_id:
|
|
297
|
+
return device
|
|
298
|
+
return None
|
|
197
299
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
continue
|
|
300
|
+
def _build(self):
|
|
301
|
+
"""Updated builf collection of devices.
|
|
201
302
|
|
|
303
|
+
Starts with device type key first and then gets matching device data
|
|
304
|
+
"""
|
|
305
|
+
# TODO - limit checks based on DeviceCapabilityMatrix
|
|
306
|
+
for device_type in PRODUCT_TYPE_CONFIG:
|
|
307
|
+
# If not yet in the collection, add empty collection to device collections.
|
|
308
|
+
if device_type not in self._device_collection:
|
|
309
|
+
self._device_collection[device_type] = PRODUCT_TYPE_CONFIG[
|
|
310
|
+
device_type
|
|
311
|
+
].collection()
|
|
312
|
+
|
|
313
|
+
if device_type_data := self._domain_data.get(device_type):
|
|
314
|
+
# We have this device type in data
|
|
315
|
+
device_config = PRODUCT_TYPE_CONFIG[device_type]
|
|
316
|
+
|
|
317
|
+
# Now build collection of devices
|
|
318
|
+
for device in device_type_data:
|
|
202
319
|
# Get class to create and collection to append for device
|
|
203
|
-
device_class =
|
|
320
|
+
device_class = device_config.device_class
|
|
321
|
+
|
|
322
|
+
# TODO: Fix this so not fudged
|
|
323
|
+
if device_type == "Light" and device.get("IsDimmable"):
|
|
324
|
+
device_class = _WiserDimmableLight
|
|
325
|
+
|
|
326
|
+
# Device info id can be DeviceId or id depending on device type
|
|
327
|
+
device_info_id = device.get("DeviceId", device.get("id"))
|
|
328
|
+
|
|
329
|
+
# Get device info data
|
|
330
|
+
device_info_data = self._get_device_info_by_id(device_info_id)
|
|
204
331
|
|
|
205
332
|
# If heating device add room id
|
|
206
|
-
if device_config.
|
|
207
|
-
if not device.get("RoomId"):
|
|
208
|
-
|
|
209
|
-
self._domain_data,
|
|
333
|
+
if device_config.heating:
|
|
334
|
+
if not device.get("RoomId", device_info_data.get("RoomId")):
|
|
335
|
+
device["RoomId"] = self._get_temp_device_room_id(
|
|
336
|
+
self._domain_data, device_info_id
|
|
210
337
|
)
|
|
211
338
|
|
|
212
339
|
# If schedule device add schedule
|
|
213
|
-
if device_config.
|
|
214
|
-
device_schedule =
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
device_config.get("schedule_type")
|
|
218
|
-
)
|
|
219
|
-
if schedule.id == device_info[0].get("ScheduleId")
|
|
220
|
-
]
|
|
340
|
+
if device_config.schedule_type:
|
|
341
|
+
device_schedule = self._schedules.get_by_id(
|
|
342
|
+
device_config.schedule_type, device.get("ScheduleId")
|
|
343
|
+
)
|
|
221
344
|
else:
|
|
222
345
|
device_schedule = None
|
|
223
346
|
|
|
224
|
-
# If has equipment entry, add equipment to device info data
|
|
225
|
-
if device_config.get("has_v2_equipment"):
|
|
226
|
-
device_info[0]["EquipmentData"] = self._get_equipment_data(
|
|
227
|
-
device_info[0].get("EquipmentId")
|
|
228
|
-
)
|
|
229
|
-
|
|
230
347
|
# Add device to collection
|
|
231
|
-
self._device_collection[
|
|
232
|
-
_WiserDeviceTypeEnum[device_type].value
|
|
233
|
-
]._items.append(
|
|
348
|
+
self._device_collection[device_type]._items.append(
|
|
234
349
|
device_class(
|
|
235
350
|
self._wiser_rest_controller,
|
|
236
|
-
device_config.
|
|
351
|
+
device_config.endpoint,
|
|
352
|
+
device_info_data,
|
|
237
353
|
device,
|
|
238
|
-
|
|
239
|
-
device_schedule[0] if device_schedule else None,
|
|
354
|
+
device_schedule,
|
|
240
355
|
)
|
|
241
356
|
)
|
|
242
357
|
|
|
358
|
+
# Add ancillary sensors to device
|
|
359
|
+
for anc_device_type, anc_device_type_info in ANCILLARY_SENSOR_CONFIG.items():
|
|
360
|
+
if anc_device_type_data := self._domain_data.get(anc_device_type):
|
|
361
|
+
for anc_device in anc_device_type_data:
|
|
362
|
+
device_id = anc_device.get("DeviceId", anc_device.get("id"))
|
|
363
|
+
if device := self.get_by_id(device_id):
|
|
364
|
+
if hasattr(device, anc_device_type_info.attribute):
|
|
365
|
+
getattr(device, anc_device_type_info.attribute).append(
|
|
366
|
+
anc_device_type_info.device_class(
|
|
367
|
+
self._wiser_rest_controller,
|
|
368
|
+
anc_device_type_info.endpoint,
|
|
369
|
+
anc_device,
|
|
370
|
+
)
|
|
371
|
+
)
|
|
372
|
+
|
|
243
373
|
def _get_temp_device_room_id(self, domain_data: dict, device_id: int) -> int:
|
|
244
374
|
rooms = domain_data.get("Room")
|
|
245
375
|
for room in rooms:
|
|
@@ -268,52 +398,90 @@ class _WiserDeviceCollection:
|
|
|
268
398
|
@property
|
|
269
399
|
def heating_actuators(self) -> _WiserHeatingActuatorCollection:
|
|
270
400
|
"""Return all heating actuators"""
|
|
271
|
-
|
|
401
|
+
try:
|
|
402
|
+
return self._device_collection["HeatingActuator"]
|
|
403
|
+
except KeyError:
|
|
404
|
+
return None
|
|
272
405
|
|
|
273
406
|
@property
|
|
274
407
|
def lights(self) -> _WiserLightCollection:
|
|
275
408
|
"""Return all lights"""
|
|
276
|
-
|
|
409
|
+
try:
|
|
410
|
+
return self._device_collection["Light"]
|
|
411
|
+
except KeyError:
|
|
412
|
+
return None
|
|
413
|
+
|
|
414
|
+
@property
|
|
415
|
+
def power_tags_c(self) -> _WiserPowerTagControlCollection:
|
|
416
|
+
"""Return all power tag Cs"""
|
|
417
|
+
try:
|
|
418
|
+
return self._device_collection["PTC"]
|
|
419
|
+
except KeyError:
|
|
420
|
+
return None
|
|
277
421
|
|
|
278
422
|
@property
|
|
279
423
|
def power_tags(self) -> _WiserPowerTagEnergyCollection:
|
|
280
424
|
"""Return all power tags"""
|
|
281
|
-
|
|
425
|
+
try:
|
|
426
|
+
return self._device_collection["PTE"]
|
|
427
|
+
except KeyError:
|
|
428
|
+
return None
|
|
282
429
|
|
|
283
430
|
@property
|
|
284
431
|
def roomstats(self) -> _WiserRoomStatCollection:
|
|
285
432
|
"""Return all roomstats"""
|
|
286
|
-
|
|
433
|
+
try:
|
|
434
|
+
return self._device_collection["RoomStat"]
|
|
435
|
+
except KeyError:
|
|
436
|
+
return None
|
|
287
437
|
|
|
288
438
|
@property
|
|
289
439
|
def shutters(self) -> _WiserShutterCollection:
|
|
290
440
|
"""Return all shutters"""
|
|
291
|
-
|
|
441
|
+
try:
|
|
442
|
+
return self._device_collection["Shutter"]
|
|
443
|
+
except KeyError:
|
|
444
|
+
return None
|
|
292
445
|
|
|
293
446
|
@property
|
|
294
447
|
def smartplugs(self) -> _WiserSmartPlugCollection:
|
|
295
448
|
"""Return all smart plugs"""
|
|
296
|
-
|
|
449
|
+
try:
|
|
450
|
+
return self._device_collection["SmartPlug"]
|
|
451
|
+
except KeyError:
|
|
452
|
+
return None
|
|
297
453
|
|
|
298
454
|
@property
|
|
299
455
|
def smartvalves(self) -> _WiserSmartValveCollection:
|
|
300
456
|
"""Return all smart valves (iTRVs)"""
|
|
301
|
-
|
|
457
|
+
try:
|
|
458
|
+
return self._device_collection["SmartValve"]
|
|
459
|
+
except KeyError:
|
|
460
|
+
return None
|
|
302
461
|
|
|
303
462
|
@property
|
|
304
463
|
def smokealarms(self) -> _WiserSmokeAlarmCollection:
|
|
305
464
|
"""Return all smoke alarms"""
|
|
306
|
-
|
|
465
|
+
try:
|
|
466
|
+
return self._device_collection["SmokeAlarmDevice"]
|
|
467
|
+
except KeyError:
|
|
468
|
+
return None
|
|
307
469
|
|
|
308
470
|
@property
|
|
309
471
|
def ufh_controllers(self) -> _WiserUFHControllerCollection:
|
|
310
472
|
"""Return all UFH controllers"""
|
|
311
|
-
|
|
473
|
+
try:
|
|
474
|
+
return self._device_collection["UnderFloorHeating"]
|
|
475
|
+
except KeyError:
|
|
476
|
+
return None
|
|
312
477
|
|
|
313
478
|
@property
|
|
314
479
|
def binary_sensor(self):
|
|
315
480
|
"""Return all binary sensors"""
|
|
316
|
-
|
|
481
|
+
try:
|
|
482
|
+
return self._device_collection["BinarySensor"]
|
|
483
|
+
except KeyError:
|
|
484
|
+
return None
|
|
317
485
|
|
|
318
486
|
def get_by_id(self, device_id: int) -> _WiserDevice:
|
|
319
487
|
"""
|
|
@@ -2,6 +2,8 @@ from .const import TEMP_OFF, TEXT_UNKNOWN, WISERHEATINGACTUATOR, WiserTempLimits
|
|
|
2
2
|
from .helpers.device import _WiserDevice
|
|
3
3
|
from .helpers.equipment import _WiserEquipment
|
|
4
4
|
from .helpers.temp import _WiserTemperatureFunctions as tf
|
|
5
|
+
from .helpers.threshold import _WiserThresholdSensor
|
|
6
|
+
from .helpers.uiconfiguration import _WiserUIConfigSensor
|
|
5
7
|
from .rest_controller import _WiserRestController
|
|
6
8
|
|
|
7
9
|
|
|
@@ -107,6 +109,12 @@ class _WiserTemperatureSensor:
|
|
|
107
109
|
class _WiserHeatingActuator(_WiserDevice):
|
|
108
110
|
"""Class representing a Wiser Heating Actuator device"""
|
|
109
111
|
|
|
112
|
+
def __init__(self, *args):
|
|
113
|
+
"""Initialise."""
|
|
114
|
+
super().__init__(*args)
|
|
115
|
+
self._threshold_sensors: list[_WiserThresholdSensor] = []
|
|
116
|
+
self._uiconfig_sensors: list[_WiserUIConfigSensor] = []
|
|
117
|
+
|
|
110
118
|
@property
|
|
111
119
|
def current_target_temperature(self) -> float:
|
|
112
120
|
"""Get the current target temperature setting"""
|
|
@@ -161,6 +169,16 @@ class _WiserHeatingActuator(_WiserDevice):
|
|
|
161
169
|
"""Get output type"""
|
|
162
170
|
return self._device_type_data.get("OutputType", TEXT_UNKNOWN)
|
|
163
171
|
|
|
172
|
+
@property
|
|
173
|
+
def threshold_sensors(self) -> list[_WiserThresholdSensor]:
|
|
174
|
+
"""Get threshold sensors."""
|
|
175
|
+
return self._threshold_sensors
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def uiconfig_sensors(self) -> list[_WiserUIConfigSensor]:
|
|
179
|
+
"""Get ui configuration sensors."""
|
|
180
|
+
return self._uiconfig_sensors
|
|
181
|
+
|
|
164
182
|
|
|
165
183
|
class _WiserHeatingActuatorCollection(object):
|
|
166
184
|
"""Class holding all wiser heating actuators"""
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import hashlib
|
|
1
2
|
import inspect
|
|
2
3
|
from typing import Union
|
|
4
|
+
from uuid import UUID
|
|
3
5
|
|
|
4
6
|
from .. import _LOGGER
|
|
5
7
|
from ..const import (
|
|
@@ -76,7 +78,7 @@ class _WiserDevice(object):
|
|
|
76
78
|
@property
|
|
77
79
|
def device_type_id(self) -> int:
|
|
78
80
|
"""Get the device id for the specific device type"""
|
|
79
|
-
return self.
|
|
81
|
+
return self._device_type_data.get("id")
|
|
80
82
|
|
|
81
83
|
@property
|
|
82
84
|
def identify(self) -> bool:
|
|
@@ -188,7 +190,13 @@ class _WiserDevice(object):
|
|
|
188
190
|
@property
|
|
189
191
|
def uuid(self) -> str:
|
|
190
192
|
"""Get UUID zigbee"""
|
|
191
|
-
|
|
193
|
+
if uuid := self._device_type_data.get("UUID"):
|
|
194
|
+
return uuid
|
|
195
|
+
uname = (
|
|
196
|
+
f"{self.product_type}_{self.serial_number}_{self.id}_{self.device_type_id}"
|
|
197
|
+
)
|
|
198
|
+
hexstr = hashlib.md5(uname.encode("UTF-8")).hexdigest()
|
|
199
|
+
return UUID(hex=hexstr)
|
|
192
200
|
|
|
193
201
|
# END Added by LGO
|
|
194
202
|
|