pyvesync 3.0.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyvesync/__init__.py +11 -0
- pyvesync/base_devices/__init__.py +35 -0
- pyvesync/base_devices/bulb_base.py +348 -0
- pyvesync/base_devices/fan_base.py +398 -0
- pyvesync/base_devices/fryer_base.py +69 -0
- pyvesync/base_devices/humidifier_base.py +460 -0
- pyvesync/base_devices/outlet_base.py +315 -0
- pyvesync/base_devices/purifier_base.py +518 -0
- pyvesync/base_devices/switch_base.py +270 -0
- pyvesync/base_devices/thermostat_base.py +277 -0
- pyvesync/base_devices/vesyncbasedevice.py +580 -0
- pyvesync/const.py +749 -0
- pyvesync/device_container.py +360 -0
- pyvesync/device_map.py +1090 -0
- pyvesync/devices/__init__.py +1 -0
- pyvesync/devices/vesyncbulb.py +1254 -0
- pyvesync/devices/vesyncfan.py +238 -0
- pyvesync/devices/vesynchumidifier.py +785 -0
- pyvesync/devices/vesynckitchen.py +664 -0
- pyvesync/devices/vesyncoutlet.py +962 -0
- pyvesync/devices/vesyncpurifier.py +951 -0
- pyvesync/devices/vesyncswitch.py +449 -0
- pyvesync/devices/vesyncthermostat.py +175 -0
- pyvesync/models/__init__.py +11 -0
- pyvesync/models/base_models.py +117 -0
- pyvesync/models/bulb_models.py +173 -0
- pyvesync/models/bypass_models.py +264 -0
- pyvesync/models/fan_models.py +46 -0
- pyvesync/models/fryer_models.py +28 -0
- pyvesync/models/home_models.py +158 -0
- pyvesync/models/humidifier_models.py +187 -0
- pyvesync/models/outlet_models.py +194 -0
- pyvesync/models/purifier_models.py +204 -0
- pyvesync/models/switch_models.py +89 -0
- pyvesync/models/thermostat_models.py +122 -0
- pyvesync/models/vesync_models.py +252 -0
- pyvesync/utils/__init__.py +1 -0
- pyvesync/utils/colors.py +248 -0
- pyvesync/utils/device_mixins.py +366 -0
- pyvesync/utils/enum_utils.py +25 -0
- pyvesync/utils/errors.py +859 -0
- pyvesync/utils/helpers.py +696 -0
- pyvesync/utils/logs.py +500 -0
- pyvesync/vesync.py +445 -0
- pyvesync-3.0.0b0.dist-info/METADATA +527 -0
- pyvesync-3.0.0b0.dist-info/RECORD +49 -0
- pyvesync-3.0.0b0.dist-info/WHEEL +5 -0
- pyvesync-3.0.0b0.dist-info/licenses/LICENSE +21 -0
- pyvesync-3.0.0b0.dist-info/top_level.txt +1 -0
pyvesync/__init__.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Base devices and state classes for VeSync devices.
|
|
2
|
+
|
|
3
|
+
This module contains the base classes for VeSync devices, as well as the state classes
|
|
4
|
+
for each device type. The base classes are used to create the device objects, while the
|
|
5
|
+
state classes are used to store the current state of the device.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .vesyncbasedevice import VeSyncBaseDevice, VeSyncBaseToggleDevice, DeviceState
|
|
9
|
+
from .bulb_base import VeSyncBulb, BulbState
|
|
10
|
+
from .switch_base import VeSyncSwitch, SwitchState
|
|
11
|
+
from .outlet_base import VeSyncOutlet, OutletState
|
|
12
|
+
from .fan_base import VeSyncFanBase, FanState
|
|
13
|
+
from .purifier_base import VeSyncPurifier, PurifierState
|
|
14
|
+
from .humidifier_base import VeSyncHumidifier, HumidifierState
|
|
15
|
+
from .fryer_base import VeSyncFryer, FryerState
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"BulbState",
|
|
19
|
+
"DeviceState",
|
|
20
|
+
"FanState",
|
|
21
|
+
"FryerState",
|
|
22
|
+
"HumidifierState",
|
|
23
|
+
"OutletState",
|
|
24
|
+
"PurifierState",
|
|
25
|
+
"SwitchState",
|
|
26
|
+
"VeSyncBaseDevice",
|
|
27
|
+
"VeSyncBaseToggleDevice",
|
|
28
|
+
"VeSyncBulb",
|
|
29
|
+
"VeSyncFanBase",
|
|
30
|
+
"VeSyncFryer",
|
|
31
|
+
"VeSyncHumidifier",
|
|
32
|
+
"VeSyncOutlet",
|
|
33
|
+
"VeSyncPurifier",
|
|
34
|
+
"VeSyncSwitch",
|
|
35
|
+
]
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"""Base classes for all VeSync bulbs."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import logging
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
from typing_extensions import deprecated
|
|
6
|
+
|
|
7
|
+
from pyvesync.base_devices.vesyncbasedevice import VeSyncBaseToggleDevice, DeviceState
|
|
8
|
+
from pyvesync.utils.colors import HSV, RGB, Color
|
|
9
|
+
from pyvesync.utils.helpers import Converters, Validators, NUMERIC_STRICT
|
|
10
|
+
from pyvesync.const import BulbFeatures
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from pyvesync import VeSync
|
|
14
|
+
from pyvesync.models.vesync_models import ResponseDeviceDetailsModel
|
|
15
|
+
from pyvesync.device_map import BulbMap
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class BulbState(DeviceState):
|
|
22
|
+
"""VeSync Bulb State Base.
|
|
23
|
+
|
|
24
|
+
Base class to hold all state attributes for bulb devices. Inherits from
|
|
25
|
+
[`DeviceState`][pyvesync.base_devices.vesyncbasedevice.DeviceState]. This
|
|
26
|
+
class should not be used directly for devices, but rather subclassed for each
|
|
27
|
+
bulb type.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
device (VeSyncBulb): VeSync Bulb device.
|
|
31
|
+
details (ResponseDeviceDetailsModel): Device details from API.
|
|
32
|
+
feature_map (BulbMap): Feature map for bulb.
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
_exclude_serialization (list[str]): List of attributes to exclude from
|
|
36
|
+
serialization.
|
|
37
|
+
active_time (int): Active time of device, defaults to None.
|
|
38
|
+
connection_status (str): Connection status of device.
|
|
39
|
+
device (VeSyncBaseDevice): Device object.
|
|
40
|
+
device_status (str): Device status.
|
|
41
|
+
features (dict): Features of device.
|
|
42
|
+
last_update_ts (int): Last update timestamp of device, defaults to None.
|
|
43
|
+
brightness (int): Brightness of bulb (0-100).
|
|
44
|
+
color_temp (int): White color temperature of bulb in percent (0-100).
|
|
45
|
+
color_temp_kelvin (int): White color temperature of bulb in Kelvin.
|
|
46
|
+
color (Color): Color of bulb in the form of a dataclass with two namedtuple
|
|
47
|
+
attributes - `hsv` & `rgb`. See
|
|
48
|
+
[utils.colors.Colors][pyvesync.utils.colors.Color].
|
|
49
|
+
color_mode (str): Color mode of bulb.
|
|
50
|
+
color_modes (list[str]): List of color modes supported by bulb.
|
|
51
|
+
|
|
52
|
+
Methods:
|
|
53
|
+
update_ts: Update last update timestamp.
|
|
54
|
+
to_dict: Dump state to JSON.
|
|
55
|
+
to_json: Dump state to JSON string.
|
|
56
|
+
to_jsonb: Dump state to JSON bytes.
|
|
57
|
+
as_tuple: Convert state to tuple of (name, value) tuples.
|
|
58
|
+
|
|
59
|
+
See Also:
|
|
60
|
+
- [`VeSyncBulb`][pyvesync.base_devices.bulb_base.VeSyncBulb]
|
|
61
|
+
- [`ResponseDeviceDetailsModel`][
|
|
62
|
+
pyvesync.models.device_list_models.ResponseDeviceDetailsModel]
|
|
63
|
+
- [`BulbMap`][pyvesync.device_map.BulbMap]
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
__slots__ = (
|
|
67
|
+
'_brightness',
|
|
68
|
+
'_color',
|
|
69
|
+
'_color_temp',
|
|
70
|
+
'color_mode',
|
|
71
|
+
'color_modes'
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def __init__(self,
|
|
75
|
+
device: VeSyncBulb,
|
|
76
|
+
details: ResponseDeviceDetailsModel,
|
|
77
|
+
feature_map: BulbMap) -> None:
|
|
78
|
+
"""Initialize VeSync Bulb State Base."""
|
|
79
|
+
super().__init__(device, details, feature_map)
|
|
80
|
+
self._exclude_serialization: list[str] = ['rgb', 'hsv']
|
|
81
|
+
self.features: list[str] = feature_map.features
|
|
82
|
+
self.color_modes: list[str] = feature_map.color_modes
|
|
83
|
+
self.device: VeSyncBulb = device
|
|
84
|
+
self.color_mode: str | None = None
|
|
85
|
+
self._brightness: int | None = None
|
|
86
|
+
self._color_temp: int | None = None
|
|
87
|
+
self._color: Color | None = None
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def color(self) -> Color | None:
|
|
91
|
+
"""Return color of bulb."""
|
|
92
|
+
return self._color
|
|
93
|
+
|
|
94
|
+
@color.setter
|
|
95
|
+
def color(self, color: Color | None) -> None:
|
|
96
|
+
"""Set color of bulb."""
|
|
97
|
+
self._color = color
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def hsv(self) -> HSV | None:
|
|
101
|
+
"""Return color of bulb as HSV."""
|
|
102
|
+
if self._color is not None:
|
|
103
|
+
return self._color.hsv
|
|
104
|
+
return None
|
|
105
|
+
|
|
106
|
+
@hsv.setter
|
|
107
|
+
def hsv(
|
|
108
|
+
self, hue: NUMERIC_STRICT, saturation: NUMERIC_STRICT, value: NUMERIC_STRICT
|
|
109
|
+
) -> None:
|
|
110
|
+
"""Set color property with HSV values."""
|
|
111
|
+
self._color = Color.from_hsv(hue, saturation, value)
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def rgb(self) -> RGB | None:
|
|
115
|
+
"""Return color of bulb as RGB."""
|
|
116
|
+
if self._color is not None:
|
|
117
|
+
return self._color.rgb
|
|
118
|
+
return None
|
|
119
|
+
|
|
120
|
+
@rgb.setter
|
|
121
|
+
def rgb(self, red: float, green: float, blue: float) -> None:
|
|
122
|
+
"""Set color property with RGB values."""
|
|
123
|
+
self._color = Color.from_rgb(red, green, blue)
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def brightness(self) -> int | None:
|
|
127
|
+
"""Brightness of vesync bulb 0-100."""
|
|
128
|
+
if not self.device.supports_brightness:
|
|
129
|
+
logger.warning("Brightness not supported by this bulb")
|
|
130
|
+
return None
|
|
131
|
+
return self._brightness
|
|
132
|
+
|
|
133
|
+
@brightness.setter
|
|
134
|
+
def brightness(self, value: int | None) -> None:
|
|
135
|
+
if not self.device.supports_brightness:
|
|
136
|
+
logger.warning("Brightness not supported by this bulb")
|
|
137
|
+
return
|
|
138
|
+
if Validators.validate_zero_to_hundred(value):
|
|
139
|
+
self._brightness = value
|
|
140
|
+
else:
|
|
141
|
+
self._brightness = None
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def color_temp(self) -> int | None:
|
|
145
|
+
"""White color temperature of bulb in percent (0-100)."""
|
|
146
|
+
if not self.device.supports_color_temp:
|
|
147
|
+
logger.warning("Color temperature not supported by this bulb")
|
|
148
|
+
return None
|
|
149
|
+
return self._color_temp
|
|
150
|
+
|
|
151
|
+
@color_temp.setter
|
|
152
|
+
def color_temp(self, value: int) -> None:
|
|
153
|
+
if not self.device.supports_color_temp:
|
|
154
|
+
logger.warning("Color temperature not supported by this bulb")
|
|
155
|
+
return
|
|
156
|
+
if Validators.validate_zero_to_hundred(value):
|
|
157
|
+
self._color_temp = value
|
|
158
|
+
else:
|
|
159
|
+
logger.warning("Color temperature must be between 0 and 100")
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def color_temp_kelvin(self) -> int | None:
|
|
163
|
+
"""Return white color temperature of bulb in Kelvin."""
|
|
164
|
+
if not self.device.supports_color_temp:
|
|
165
|
+
logger.warning("Color temperature not supported by this bulb")
|
|
166
|
+
return None
|
|
167
|
+
if self._color_temp is not None:
|
|
168
|
+
return Converters.color_temp_pct_to_kelvin(self._color_temp)
|
|
169
|
+
return None
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class VeSyncBulb(VeSyncBaseToggleDevice[BulbState]):
|
|
173
|
+
"""Base class for VeSync Bulbs.
|
|
174
|
+
|
|
175
|
+
Abstract base class to provide methods for controlling and
|
|
176
|
+
getting details of VeSync bulbs. Inherits from
|
|
177
|
+
[`VeSyncBaseDevice`][pyvesync.base_devices.vesyncbasedevice.VeSyncBaseDevice]. This
|
|
178
|
+
class should not be used directly for devices, but rather subclassed for each bulb.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
details (ResponseDeviceDetailsModel): Device details from API.
|
|
182
|
+
manager (VeSync): VeSync API manager.
|
|
183
|
+
feature_map (BulbMap): Feature map for bulb.
|
|
184
|
+
|
|
185
|
+
Attributes:
|
|
186
|
+
state (BulbState): Device state object
|
|
187
|
+
Each device has a separate state base class in the base_devices module.
|
|
188
|
+
last_response (ResponseInfo): Last response from API call.
|
|
189
|
+
manager (VeSync): Manager object for API calls.
|
|
190
|
+
device_name (str): Name of device.
|
|
191
|
+
device_image (str): URL for device image.
|
|
192
|
+
cid (str): Device ID.
|
|
193
|
+
connection_type (str): Connection type of device.
|
|
194
|
+
device_type (str): Type of device.
|
|
195
|
+
type (str): Type of device.
|
|
196
|
+
uuid (str): UUID of device, not always present.
|
|
197
|
+
config_module (str): Configuration module of device.
|
|
198
|
+
mac_id (str): MAC ID of device.
|
|
199
|
+
current_firm_version (str): Current firmware version of device.
|
|
200
|
+
device_region (str): Region of device. (US, EU, etc.)
|
|
201
|
+
pid (str): Product ID of device, pulled by some devices on update.
|
|
202
|
+
sub_device_no (int): Sub-device number of device.
|
|
203
|
+
product_type (str): Product type of device.
|
|
204
|
+
features (dict): Features of device.
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
__slots__ = ()
|
|
208
|
+
|
|
209
|
+
# __metaclass__ = ABCMeta
|
|
210
|
+
|
|
211
|
+
def __init__(self, details: ResponseDeviceDetailsModel,
|
|
212
|
+
manager: VeSync, feature_map: BulbMap) -> None:
|
|
213
|
+
"""Initialize VeSync smart bulb base class."""
|
|
214
|
+
super().__init__(details, manager, feature_map)
|
|
215
|
+
self.state: BulbState = BulbState(self, details, feature_map)
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def supports_brightness(self) -> bool:
|
|
219
|
+
"""Return True if bulb supports brightness."""
|
|
220
|
+
return BulbFeatures.DIMMABLE in self.features
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def supports_color_temp(self) -> bool:
|
|
224
|
+
"""Return True if bulb supports color temperature."""
|
|
225
|
+
return BulbFeatures.COLOR_TEMP in self.features
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def supports_multicolor(self) -> bool:
|
|
229
|
+
"""Return True if bulb supports backlight."""
|
|
230
|
+
return BulbFeatures.MULTICOLOR in self.features
|
|
231
|
+
|
|
232
|
+
async def set_hsv(self, hue: float, saturation: float, value: float) -> bool:
|
|
233
|
+
"""Set HSV if supported by bulb.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
hue (float): Hue 0-360
|
|
237
|
+
saturation (float): Saturation 0-100
|
|
238
|
+
value (float): Value 0-100
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
bool: True if successful, False otherwise.
|
|
242
|
+
"""
|
|
243
|
+
if not self.supports_multicolor:
|
|
244
|
+
logger.debug("Color mode is not supported on this bulb.")
|
|
245
|
+
return False
|
|
246
|
+
new_color = Color.from_hsv(hue, saturation, value)
|
|
247
|
+
if new_color is None:
|
|
248
|
+
logger.warning("Invalid color value")
|
|
249
|
+
return False
|
|
250
|
+
return await self.set_hsv(*new_color.rgb.to_tuple())
|
|
251
|
+
|
|
252
|
+
async def set_rgb(self, red: float, green: float, blue: float) -> bool:
|
|
253
|
+
"""Set RGB if supported by bulb.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
red (float): Red 0-255
|
|
257
|
+
green (float): green 0-255
|
|
258
|
+
blue (float): blue 0-255
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
bool: True if successful, False otherwise.
|
|
262
|
+
"""
|
|
263
|
+
if not self.supports_multicolor:
|
|
264
|
+
logger.debug("Color mode is not supported on this bulb.")
|
|
265
|
+
return False
|
|
266
|
+
new_color = Color.from_rgb(red, green, blue)
|
|
267
|
+
if new_color is None:
|
|
268
|
+
logger.warning("Invalid color value")
|
|
269
|
+
return False
|
|
270
|
+
return await self.set_hsv(*new_color.hsv.to_tuple())
|
|
271
|
+
|
|
272
|
+
async def set_brightness(self, brightness: int) -> bool:
|
|
273
|
+
"""Set brightness if supported by bulb.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
brightness (NUMERIC_T): Brightness 0-100
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
bool: True if successful, False otherwise.
|
|
280
|
+
"""
|
|
281
|
+
del brightness
|
|
282
|
+
logger.warning("Brightness not supported/configured by this bulb")
|
|
283
|
+
return False
|
|
284
|
+
|
|
285
|
+
@property
|
|
286
|
+
@deprecated("Access state in `self.state` attribute, use `self.state.rgb`")
|
|
287
|
+
def color_value_rgb(self) -> RGB | None:
|
|
288
|
+
"""DEPRECATED....use `self.state.rgb`."""
|
|
289
|
+
if self.state.color is not None:
|
|
290
|
+
return self.state.color.rgb
|
|
291
|
+
return None
|
|
292
|
+
|
|
293
|
+
@property
|
|
294
|
+
@deprecated("Access state in `self.state` attribute, use `self.state.hsv`")
|
|
295
|
+
def color_value_hsv(self) -> HSV | None:
|
|
296
|
+
"""DEPRECATED....use `self.state.hsv`."""
|
|
297
|
+
if self.state.color is not None:
|
|
298
|
+
return self.state.color.hsv
|
|
299
|
+
return None
|
|
300
|
+
|
|
301
|
+
async def set_color_temp(self, color_temp: int) -> bool:
|
|
302
|
+
"""Set color temperature if supported by bulb.
|
|
303
|
+
|
|
304
|
+
Args:
|
|
305
|
+
color_temp (int): Color temperature 0-100
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
bool: True if successful, False otherwise.
|
|
309
|
+
"""
|
|
310
|
+
del color_temp
|
|
311
|
+
if self.supports_color_temp:
|
|
312
|
+
logger.debug("Color temperature is not configured on this bulb.")
|
|
313
|
+
else:
|
|
314
|
+
logger.debug("Color temperature not supported by this bulb")
|
|
315
|
+
return False
|
|
316
|
+
|
|
317
|
+
async def set_white_mode(self) -> bool:
|
|
318
|
+
"""Set white mode if supported by bulb.
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
bool: True if successful, False otherwise.
|
|
322
|
+
"""
|
|
323
|
+
if self.supports_multicolor:
|
|
324
|
+
logger.debug("White mode is not configured on this bulb.")
|
|
325
|
+
else:
|
|
326
|
+
logger.warning("White mode not supported by this bulb")
|
|
327
|
+
return False
|
|
328
|
+
|
|
329
|
+
async def set_color_mode(self, color_mode: str) -> bool:
|
|
330
|
+
"""Set color mode if supported by bulb.
|
|
331
|
+
|
|
332
|
+
Args:
|
|
333
|
+
color_mode (str): Color mode to set.
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
bool: True if successful, False otherwise.
|
|
337
|
+
"""
|
|
338
|
+
del color_mode
|
|
339
|
+
if self.supports_multicolor:
|
|
340
|
+
logger.debug("Color mode is not configured on this bulb.")
|
|
341
|
+
else:
|
|
342
|
+
logger.warning("Color mode not supported by this bulb")
|
|
343
|
+
return False
|
|
344
|
+
|
|
345
|
+
@deprecated("Use `set_white_mode` instead.")
|
|
346
|
+
async def enable_white_mode(self) -> bool:
|
|
347
|
+
"""Enable white mode if supported by bulb."""
|
|
348
|
+
return await self.set_white_mode()
|