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
@@ -0,0 +1,460 @@
1
+ """Base Device and State Class for VeSync Humidifiers."""
2
+ from __future__ import annotations
3
+ from abc import abstractmethod
4
+ import logging
5
+ from typing import TYPE_CHECKING
6
+ from typing_extensions import deprecated
7
+
8
+ from pyvesync.base_devices.vesyncbasedevice import VeSyncBaseToggleDevice, DeviceState
9
+ from pyvesync.const import (
10
+ HumidifierFeatures,
11
+ HumidifierModes,
12
+ DeviceStatus,
13
+ IntFlag,
14
+ StrFlag
15
+ )
16
+
17
+ if TYPE_CHECKING:
18
+ from pyvesync import VeSync
19
+ from pyvesync.models.vesync_models import ResponseDeviceDetailsModel
20
+ from pyvesync.device_map import HumidifierMap
21
+
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ class HumidifierState(DeviceState):
27
+ """State Class for VeSync Humidifiers.
28
+
29
+ This is the state class for all vesync humidifiers. If there are
30
+ new features or state attributes, they should be added directly to
31
+ this class and be set to the default `NOT_SUPPORTED` flag.
32
+
33
+ Attributes:
34
+ auto_preference (int): Auto preference level.
35
+ auto_stop_target_reached (bool): Automatic stop target reached.
36
+ auto_target_humidity (int): Target humidity level.
37
+ automatic_stop_config (bool): Automatic stop configuration.
38
+ child_lock_status (bool): Child lock status.
39
+ display_set_status (str): Display set status.
40
+ display_status (str): Display status.
41
+ drying_mode_auto_switch (str): Drying mode auto switch status.
42
+ drying_mode_level (int): Drying mode level.
43
+ drying_mode_status (str): Drying mode status.
44
+ drying_mode_time_remain (int): Drying mode time remaining.
45
+ filter_life_percent (int): Filter life percentage.
46
+ humidity (int): Current humidity level.
47
+ humidity_high (bool): High humidity status.
48
+ mist_level (int): Mist level.
49
+ mist_virtual_level (int): Mist virtual level.
50
+ mode (str): Current mode.
51
+ nightlight_brightness (int): Nightlight brightness level.
52
+ nightlight_status (str): Nightlight status.
53
+ temperature (int): Current temperature.
54
+ warm_mist_enabled (bool): Warm mist enabled status.
55
+ warm_mist_level (int): Warm mist level.
56
+ water_lacks (bool): Water lacks status.
57
+ water_tank_lifted (bool): Water tank lifted status.
58
+ """
59
+
60
+ __slots__ = (
61
+ "auto_preference",
62
+ "auto_stop_target_reached",
63
+ "auto_target_humidity",
64
+ "automatic_stop_config",
65
+ "child_lock_status",
66
+ "display_set_status",
67
+ "display_status",
68
+ "drying_mode_auto_switch",
69
+ "drying_mode_level",
70
+ "drying_mode_status",
71
+ "drying_mode_time_remain",
72
+ "filter_life_percent",
73
+ "humidity",
74
+ "humidity_high",
75
+ "mist_level",
76
+ "mist_virtual_level",
77
+ "mode",
78
+ "nightlight_brightness",
79
+ "nightlight_status",
80
+ "temperature",
81
+ "warm_mist_enabled",
82
+ "warm_mist_level",
83
+ "water_lacks",
84
+ "water_tank_lifted",
85
+ )
86
+
87
+ def __init__(self, device: VeSyncHumidifier, details: ResponseDeviceDetailsModel,
88
+ feature_map: HumidifierMap) -> None:
89
+ """Initialize VeSync Humidifier State.
90
+
91
+ This state class is used to store the current state of the humidifier.
92
+
93
+ Args:
94
+ device (VeSyncHumidifier): The device object.
95
+ details (ResponseDeviceDetailsModel): The device details.
96
+ feature_map (HumidifierMap): The feature map for the device.
97
+ """
98
+ super().__init__(device, details, feature_map)
99
+ self.auto_stop_target_reached: bool = False
100
+ self.auto_target_humidity: int = IntFlag.NOT_SUPPORTED
101
+ self.automatic_stop_config: bool = False
102
+ self.display_set_status: str = DeviceStatus.UNKNOWN
103
+ self.display_status: str = DeviceStatus.UNKNOWN
104
+ self.humidity: int = IntFlag.NOT_SUPPORTED
105
+ self.humidity_high: bool = False
106
+ self.mist_level: int | None = None
107
+ self.mist_virtual_level: int | None = None
108
+ self.mode: str = HumidifierModes.UNKNOWN
109
+ self.nightlight_brightness: int = IntFlag.NOT_SUPPORTED
110
+ self.nightlight_status: str = StrFlag.NOT_SUPPORTED
111
+ self.warm_mist_enabled: bool | None = None
112
+ self.warm_mist_level: int = IntFlag.NOT_SUPPORTED
113
+ self.water_lacks: bool = False
114
+ self.water_tank_lifted: bool = False
115
+ self.temperature: int = IntFlag.NOT_SUPPORTED
116
+ # Superior 6000S States
117
+ self.auto_preference: int = IntFlag.NOT_SUPPORTED
118
+ self.filter_life_percent: int = IntFlag.NOT_SUPPORTED
119
+ self.drying_mode_level: int = IntFlag.NOT_SUPPORTED
120
+ self.drying_mode_auto_switch: str = StrFlag.NOT_SUPPORTED
121
+ self.drying_mode_status: str = StrFlag.NOT_SUPPORTED
122
+ self.drying_mode_time_remain: int = IntFlag.NOT_SUPPORTED
123
+
124
+ @property
125
+ def automatic_stop(self) -> bool:
126
+ """Return the automatic stop status.
127
+
128
+ Returns:
129
+ bool: True if automatic stop is enabled, False otherwise.
130
+ """
131
+ return self.automatic_stop_config
132
+
133
+ @property
134
+ @deprecated("Use auto_stop_target_reached instead.")
135
+ def automatic_stop_target_reached(self) -> bool:
136
+ """Deprecated function.
137
+
138
+ Returns:
139
+ bool: True if automatic stop target is reached, False otherwise.
140
+ """
141
+ return self.auto_stop_target_reached
142
+
143
+ @property
144
+ def target_humidity(self) -> int:
145
+ """Return the target humidity level.
146
+
147
+ Returns:
148
+ int: Target humidity level.
149
+ """
150
+ return self.auto_target_humidity
151
+
152
+ @property
153
+ def auto_humidity(self) -> int:
154
+ """Return the auto humidity level.
155
+
156
+ Returns:
157
+ int: Auto humidity level.
158
+ """
159
+ return self.auto_target_humidity
160
+
161
+ @property
162
+ def auto_enabled(self) -> bool:
163
+ """Return True if auto mode is enabled."""
164
+ return self.mode in [HumidifierModes.AUTO, self.mode, HumidifierModes.HUMIDITY]
165
+
166
+ @property
167
+ @deprecated("Use humidity property instead.")
168
+ def humidity_level(self) -> int | None:
169
+ """Deprecated function.
170
+
171
+ Returns:
172
+ int | None: Humidity level.
173
+ """
174
+ return self.humidity
175
+
176
+ @property
177
+ def drying_mode_state(self) -> str:
178
+ """Return the drying mode state.
179
+
180
+ Returns:
181
+ str | None: Drying mode state.
182
+ """
183
+ return self.drying_mode_status
184
+
185
+ @property
186
+ def drying_mode_seconds_remaining(self) -> int:
187
+ """Return the drying mode seconds remaining.
188
+
189
+ Return:
190
+ int | None: Drying mode seconds remaining.
191
+ """
192
+ return self.drying_mode_time_remain
193
+
194
+ @property
195
+ def drying_mode_enabled(self) -> bool:
196
+ """Return True if drying mode is enabled.
197
+
198
+ Returns:
199
+ bool | None: True if drying mode is enabled, False otherwise.
200
+ """
201
+ return self.drying_mode_status == DeviceStatus.ON
202
+
203
+
204
+ class VeSyncHumidifier(VeSyncBaseToggleDevice):
205
+ """VeSyncHumdifier Base Class.
206
+
207
+ This is the base device to be inherited by all Humidifier devices.
208
+ This class only holds the device configuration and static attributes.
209
+ The state attribute holds the current state.
210
+
211
+ Attributes:
212
+ state (HumidifierState): The state of the humidifier.
213
+ last_response (ResponseInfo): Last response from API call.
214
+ manager (VeSync): Manager object for API calls.
215
+ device_name (str): Name of device.
216
+ device_image (str): URL for device image.
217
+ cid (str): Device ID.
218
+ connection_type (str): Connection type of device.
219
+ device_type (str): Type of device.
220
+ type (str): Type of device.
221
+ uuid (str): UUID of device, not always present.
222
+ config_module (str): Configuration module of device.
223
+ mac_id (str): MAC ID of device.
224
+ current_firm_version (str): Current firmware version of device.
225
+ device_region (str): Region of device. (US, EU, etc.)
226
+ pid (str): Product ID of device, pulled by some devices on update.
227
+ sub_device_no (int): Sub-device number of device.
228
+ product_type (str): Product type of device.
229
+ features (dict): Features of device.
230
+ mist_levels (list): List of mist levels.
231
+ mist_modes (list): List of mist modes.
232
+ target_minmax (tuple): Tuple of target min and max values.
233
+ warm_mist_levels (list): List of warm mist levels.
234
+
235
+ """
236
+
237
+ __slots__ = (
238
+ "mist_levels",
239
+ "mist_modes",
240
+ "target_minmax",
241
+ "warm_mist_levels",
242
+ )
243
+
244
+ def __init__(self, details: ResponseDeviceDetailsModel,
245
+ manager: VeSync, feature_map: HumidifierMap) -> None:
246
+ """Initialize VeSync Humidifier Class.
247
+
248
+ Args:
249
+ details (ResponseDeviceDetailsModel): The device details.
250
+ manager (VeSync): The VeSync manager.
251
+ feature_map (HumidifierMap): The feature map for the device.
252
+ """
253
+ super().__init__(details, manager, feature_map)
254
+ self.state: HumidifierState = HumidifierState(self, details, feature_map)
255
+ self.mist_modes: dict[str, str] = feature_map.mist_modes
256
+ self.mist_levels: list[str | int] = feature_map.mist_levels
257
+ self.features: list[str] = feature_map.features
258
+ self.warm_mist_levels: list[int | str] = feature_map.warm_mist_levels
259
+ self.target_minmax: tuple[int, int] = feature_map.target_minmax
260
+
261
+ @property
262
+ def supports_warm_mist(self) -> bool:
263
+ """Return True if the humidifier supports warm mist.
264
+
265
+ Returns:
266
+ bool: True if warm mist is supported, False otherwise.
267
+ """
268
+ return HumidifierFeatures.WARM_MIST in self.features
269
+
270
+ @property
271
+ def supports_nightlight(self) -> bool:
272
+ """Return True if the humidifier supports nightlight.
273
+
274
+ Returns:
275
+ bool: True if nightlight is supported, False otherwise.
276
+ """
277
+ return HumidifierFeatures.NIGHTLIGHT in self.features
278
+
279
+ @property
280
+ def supports_nightlight_brightness(self) -> bool:
281
+ """Return True if the humidifier supports nightlight brightness."""
282
+ return HumidifierFeatures.NIGHTLIGHT_BRIGHTNESS in self.features
283
+
284
+ @property
285
+ def supports_drying_mode(self) -> bool:
286
+ """Return True if the humidifier supports drying mode."""
287
+ return HumidifierFeatures.DRYING_MODE in self.features
288
+
289
+ async def toggle_automatic_stop(self, toggle: bool | None = None) -> bool:
290
+ """Toggle automatic stop.
291
+
292
+ Args:
293
+ toggle (bool | None): True to enable automatic stop, False to disable.
294
+
295
+ Returns:
296
+ bool: Success of request.
297
+ """
298
+ del toggle
299
+ logger.warning("Automatic stop is not supported or configured for this device.")
300
+ return False
301
+
302
+ async def toggle_display(self, toggle: bool) -> bool:
303
+ """Toggle the display on/off.
304
+
305
+ Args:
306
+ toggle (bool): True to turn on the display, False to turn off.
307
+
308
+ Returns:
309
+ bool: Success of request.
310
+ """
311
+ del toggle
312
+ logger.warning("Display is not supported or configured for this device.")
313
+ return False
314
+
315
+ @abstractmethod
316
+ async def set_mode(self, mode: str) -> bool:
317
+ """Set Humidifier Mode.
318
+
319
+ Args:
320
+ mode (str): Humidifier mode.
321
+
322
+ Returns:
323
+ bool: Success of request.
324
+
325
+ Note:
326
+ Modes for device are defined in `self.mist_modes`.
327
+ """
328
+
329
+ @abstractmethod
330
+ async def set_mist_level(self, level: int) -> bool:
331
+ """Set Mist Level for Humidifier.
332
+
333
+ Args:
334
+ level (int): Mist level.
335
+
336
+ Returns:
337
+ bool: Success of request.
338
+
339
+ Note:
340
+ Mist levels are defined in `self.mist_levels`.
341
+ """
342
+
343
+ async def turn_on_display(self) -> bool:
344
+ """Turn on the display.
345
+
346
+ Returns:
347
+ bool: Success of request.
348
+ """
349
+ return await self.toggle_display(True)
350
+
351
+ async def turn_off_display(self) -> bool:
352
+ """Turn off the display.
353
+
354
+ Returns:
355
+ bool: Success of request.
356
+ """
357
+ return await self.toggle_display(False)
358
+
359
+ async def turn_on_automatic_stop(self) -> bool:
360
+ """Turn on automatic stop.
361
+
362
+ Returns:
363
+ bool: Success of request.
364
+ """
365
+ return await self.toggle_automatic_stop(True)
366
+
367
+ async def turn_off_automatic_stop(self) -> bool:
368
+ """Turn off automatic stop.
369
+
370
+ Returns:
371
+ bool: Success of request.
372
+ """
373
+ return await self.toggle_automatic_stop(False)
374
+
375
+ async def set_auto_mode(self) -> bool:
376
+ """Set Humidifier to Auto Mode.
377
+
378
+ Returns:
379
+ bool: Success of request.
380
+ """
381
+ if HumidifierModes.AUTO in self.mist_modes:
382
+ return await self.set_mode(HumidifierModes.AUTO)
383
+ logger.debug("Auto mode not supported for this device.")
384
+ return await self.set_mode(HumidifierModes.AUTO)
385
+
386
+ async def set_manual_mode(self) -> bool:
387
+ """Set Humidifier to Manual Mode.
388
+
389
+ Returns:
390
+ bool: Success of request.
391
+ """
392
+ if HumidifierModes.MANUAL in self.mist_modes:
393
+ return await self.set_mode(HumidifierModes.MANUAL)
394
+ logger.debug("Manual mode not supported for this device.")
395
+ return await self.set_mode(HumidifierModes.MANUAL)
396
+
397
+ async def set_sleep_mode(self) -> bool:
398
+ """Set Humidifier to Sleep Mode.
399
+
400
+ Returns:
401
+ bool: Success of request.
402
+ """
403
+ if HumidifierModes.SLEEP in self.mist_modes:
404
+ return await self.set_mode(HumidifierModes.SLEEP)
405
+ logger.debug("Sleep mode not supported for this device.")
406
+ return await self.set_mode(HumidifierModes.SLEEP)
407
+
408
+ async def set_humidity(self, humidity: int) -> bool:
409
+ """Set Humidifier Target Humidity.
410
+
411
+ Args:
412
+ humidity (int): Target humidity level.
413
+
414
+ Returns:
415
+ bool: Success of request.
416
+ """
417
+ del humidity
418
+ logger.debug("Target humidity is not supported or configured for this device.")
419
+ return False
420
+
421
+ async def set_nightlight_brightness(self, brightness: int) -> bool:
422
+ """Set Humidifier night light brightness.
423
+
424
+ Args:
425
+ brightness (int): Target night light brightness.
426
+
427
+ Returns:
428
+ bool: Success of request.
429
+ """
430
+ del brightness
431
+ if not self.supports_nightlight_brightness:
432
+ logger.debug("Nightlight brightness is not supported for this device.")
433
+ return False
434
+ logger.debug("Nightlight brightness has not been configured.")
435
+ return False
436
+
437
+ async def set_warm_level(self, warm_level: int) -> bool:
438
+ """Set Humidifier Warm Level.
439
+
440
+ Args:
441
+ warm_level (int): Target warm level.
442
+
443
+ Returns:
444
+ bool: Success of request.
445
+ """
446
+ del warm_level
447
+ if self.supports_warm_mist:
448
+ logger.debug("Warm level has not been configured.")
449
+ return False
450
+ logger.debug("Warm level is not supported for this device.")
451
+ return False
452
+
453
+ async def toggle_drying_mode(self, toggle: bool | None = None) -> bool:
454
+ """enable/disable drying filters after turning off."""
455
+ del toggle
456
+ if self.supports_drying_mode:
457
+ logger.debug("Drying mode is not configured for this device.")
458
+ return False
459
+ logger.debug("Drying mode is not supported for this device.")
460
+ return False