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.
Files changed (49) hide show
  1. pyvesync/__init__.py +11 -0
  2. pyvesync/base_devices/__init__.py +35 -0
  3. pyvesync/base_devices/bulb_base.py +348 -0
  4. pyvesync/base_devices/fan_base.py +398 -0
  5. pyvesync/base_devices/fryer_base.py +69 -0
  6. pyvesync/base_devices/humidifier_base.py +460 -0
  7. pyvesync/base_devices/outlet_base.py +315 -0
  8. pyvesync/base_devices/purifier_base.py +518 -0
  9. pyvesync/base_devices/switch_base.py +270 -0
  10. pyvesync/base_devices/thermostat_base.py +277 -0
  11. pyvesync/base_devices/vesyncbasedevice.py +580 -0
  12. pyvesync/const.py +749 -0
  13. pyvesync/device_container.py +360 -0
  14. pyvesync/device_map.py +1090 -0
  15. pyvesync/devices/__init__.py +1 -0
  16. pyvesync/devices/vesyncbulb.py +1254 -0
  17. pyvesync/devices/vesyncfan.py +238 -0
  18. pyvesync/devices/vesynchumidifier.py +785 -0
  19. pyvesync/devices/vesynckitchen.py +664 -0
  20. pyvesync/devices/vesyncoutlet.py +962 -0
  21. pyvesync/devices/vesyncpurifier.py +951 -0
  22. pyvesync/devices/vesyncswitch.py +449 -0
  23. pyvesync/devices/vesyncthermostat.py +175 -0
  24. pyvesync/models/__init__.py +11 -0
  25. pyvesync/models/base_models.py +117 -0
  26. pyvesync/models/bulb_models.py +173 -0
  27. pyvesync/models/bypass_models.py +264 -0
  28. pyvesync/models/fan_models.py +46 -0
  29. pyvesync/models/fryer_models.py +28 -0
  30. pyvesync/models/home_models.py +158 -0
  31. pyvesync/models/humidifier_models.py +187 -0
  32. pyvesync/models/outlet_models.py +194 -0
  33. pyvesync/models/purifier_models.py +204 -0
  34. pyvesync/models/switch_models.py +89 -0
  35. pyvesync/models/thermostat_models.py +122 -0
  36. pyvesync/models/vesync_models.py +252 -0
  37. pyvesync/utils/__init__.py +1 -0
  38. pyvesync/utils/colors.py +248 -0
  39. pyvesync/utils/device_mixins.py +366 -0
  40. pyvesync/utils/enum_utils.py +25 -0
  41. pyvesync/utils/errors.py +859 -0
  42. pyvesync/utils/helpers.py +696 -0
  43. pyvesync/utils/logs.py +500 -0
  44. pyvesync/vesync.py +445 -0
  45. pyvesync-3.0.0b0.dist-info/METADATA +527 -0
  46. pyvesync-3.0.0b0.dist-info/RECORD +49 -0
  47. pyvesync-3.0.0b0.dist-info/WHEEL +5 -0
  48. pyvesync-3.0.0b0.dist-info/licenses/LICENSE +21 -0
  49. pyvesync-3.0.0b0.dist-info/top_level.txt +1 -0
pyvesync/__init__.py ADDED
@@ -0,0 +1,11 @@
1
+ """VeSync API Library."""
2
+
3
+ # pylint: skip-file
4
+ # flake8: noqa
5
+ from .vesync import VeSync
6
+ import logging
7
+
8
+
9
+ logging.basicConfig(
10
+ level=logging.INFO, format='%(asctime)s - %(levelname)5s - %(message)s'
11
+ )
@@ -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()