pyvesync 3.0.0__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 (50) hide show
  1. pyvesync/__init__.py +5 -0
  2. pyvesync/base_devices/__init__.py +35 -0
  3. pyvesync/base_devices/bulb_base.py +330 -0
  4. pyvesync/base_devices/fan_base.py +392 -0
  5. pyvesync/base_devices/fryer_base.py +68 -0
  6. pyvesync/base_devices/humidifier_base.py +462 -0
  7. pyvesync/base_devices/outlet_base.py +327 -0
  8. pyvesync/base_devices/purifier_base.py +525 -0
  9. pyvesync/base_devices/switch_base.py +271 -0
  10. pyvesync/base_devices/thermostat_base.py +283 -0
  11. pyvesync/base_devices/vesyncbasedevice.py +572 -0
  12. pyvesync/const.py +825 -0
  13. pyvesync/device_container.py +373 -0
  14. pyvesync/device_map.py +1172 -0
  15. pyvesync/devices/__init__.py +1 -0
  16. pyvesync/devices/vesyncbulb.py +1126 -0
  17. pyvesync/devices/vesyncfan.py +233 -0
  18. pyvesync/devices/vesynchumidifier.py +808 -0
  19. pyvesync/devices/vesynckitchen.py +651 -0
  20. pyvesync/devices/vesyncoutlet.py +954 -0
  21. pyvesync/devices/vesyncpurifier.py +990 -0
  22. pyvesync/devices/vesyncswitch.py +415 -0
  23. pyvesync/devices/vesyncthermostat.py +171 -0
  24. pyvesync/models/__init__.py +11 -0
  25. pyvesync/models/base_models.py +129 -0
  26. pyvesync/models/bulb_models.py +197 -0
  27. pyvesync/models/bypass_models.py +289 -0
  28. pyvesync/models/fan_models.py +47 -0
  29. pyvesync/models/fryer_models.py +34 -0
  30. pyvesync/models/home_models.py +169 -0
  31. pyvesync/models/humidifier_models.py +202 -0
  32. pyvesync/models/outlet_models.py +220 -0
  33. pyvesync/models/purifier_models.py +261 -0
  34. pyvesync/models/switch_models.py +101 -0
  35. pyvesync/models/thermostat_models.py +134 -0
  36. pyvesync/models/vesync_models.py +439 -0
  37. pyvesync/utils/__init__.py +1 -0
  38. pyvesync/utils/colors.py +250 -0
  39. pyvesync/utils/device_mixins.py +362 -0
  40. pyvesync/utils/enum_utils.py +26 -0
  41. pyvesync/utils/errors.py +867 -0
  42. pyvesync/utils/helpers.py +700 -0
  43. pyvesync/utils/logs.py +525 -0
  44. pyvesync/vesync.py +638 -0
  45. pyvesync/vesynchome.py +152 -0
  46. pyvesync-3.0.0.dist-info/METADATA +567 -0
  47. pyvesync-3.0.0.dist-info/RECORD +50 -0
  48. pyvesync-3.0.0.dist-info/WHEEL +5 -0
  49. pyvesync-3.0.0.dist-info/licenses/LICENSE +21 -0
  50. pyvesync-3.0.0.dist-info/top_level.txt +1 -0
pyvesync/const.py ADDED
@@ -0,0 +1,825 @@
1
+ """pyvesync library constants.
2
+
3
+ All device states and information are defined by Enums in this module.
4
+
5
+ Attributes:
6
+ DEFAULT_LANGUAGE (str): Default language for the VeSync app.
7
+ API_BASE_URL (str): Base URL for the VeSync API. If not specified,
8
+ a region-specific API URL is automatically selected.
9
+ API_TIMEOUT (int): Timeout for API requests.
10
+ USER_AGENT (str): User agent for API requests.
11
+ DEFAULT_TZ (str): Default timezone for VeSync devices, updated by API after
12
+ login.
13
+ DEFAULT_REGION (str): Default region for VeSync devices,
14
+ updated by API when retrieving devices.
15
+ APP_VERSION (str): Version of the VeSync app.
16
+ APP_ID (str): ID of the app. VeSync uses a random 8-letter string, but any non-empty
17
+ string works.
18
+ PHONE_BRAND (str): Brand of the phone used to login to the VeSync app.
19
+ PHONE_OS (str): Operating system of the phone used to login to the VeSync app.
20
+ MOBILE_ID (str): Unique identifier for the phone used to login to the VeSync app.
21
+ USER_TYPE (str): User type for the VeSync app - internal app usage.
22
+ BYPASS_APP_V (str): Bypass app version
23
+ BYPASS_HEADER_UA (str): Bypass header user agent
24
+ TERMINAL_ID (str): Unique identifier for new API calls
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import string
30
+ from enum import Enum, IntEnum, StrEnum
31
+ from random import choices, randint
32
+ from types import MappingProxyType
33
+ from uuid import uuid4
34
+
35
+ from pyvesync.utils.enum_utils import IntEnumMixin
36
+
37
+ DEFAULT_LANGUAGE = 'en'
38
+ API_BASE_URL = None # Global URL (non-EU regions): "https://smartapi.vesync.com"
39
+ # If device is out of reach, the cloud api sends a timeout response after 7 seconds,
40
+ # using 8 here so there is time enough to catch that message
41
+ API_BASE_URL_US = 'https://smartapi.vesync.com'
42
+ API_BASE_URL_EU = 'https://smartapi.vesync.eu'
43
+ NON_EU_REGIONS = ['US', 'CA', 'MX', 'JP']
44
+ API_TIMEOUT = 8
45
+ USER_AGENT = (
46
+ 'VeSync/3.2.39 (com.etekcity.vesyncPlatform; build:5; iOS 15.5.0) Alamofire/5.2.1'
47
+ )
48
+ DEFAULT_TZ = 'America/New_York'
49
+ DEFAULT_REGION = 'US'
50
+ APP_VERSION = '5.6.60'
51
+ APP_ID = ''.join(choices(string.ascii_lowercase + string.digits, k=8)) # noqa: S311
52
+ PHONE_BRAND = 'pyvesync'
53
+ PHONE_OS = 'Android'
54
+ MOBILE_ID = str(randint(1000000000000000, 9999999999999999)) # noqa: S311
55
+ USER_TYPE = '1'
56
+ BYPASS_APP_V = f'VeSync {APP_VERSION}'
57
+ BYPASS_HEADER_UA = 'okhttp/3.12.1'
58
+ TERMINAL_ID = '2' + str(uuid4()).replace('-', '')
59
+ CLIENT_TYPE = 'vesyncApp'
60
+
61
+ STATUS_OK = 200
62
+
63
+
64
+ # Generic Constants
65
+
66
+ KELVIN_MIN = 2700
67
+ KELVIN_MAX = 6500
68
+
69
+
70
+ class ProductLines(StrEnum):
71
+ """High level product line."""
72
+
73
+ WIFI_LIGHT = 'wifi-light'
74
+ WIFI_AIR = 'wifi-air'
75
+ WIFI_KITCHEN = 'wifi-kitchen'
76
+ SWITCHES = 'Switches'
77
+ WIFI_SWITCH = 'wifi-switch'
78
+ THERMOSTAT = 'thermostat'
79
+
80
+
81
+ class ProductTypes(StrEnum):
82
+ """General device types enum."""
83
+
84
+ OUTLET = 'outlet'
85
+ BULB = 'bulb'
86
+ SWITCH = 'switch'
87
+ PURIFIER = 'purifier'
88
+ FAN = 'fan'
89
+ HUMIDIFIER = 'humidifier'
90
+ AIR_FRYER = 'air fryer'
91
+ KITCHEN_THERMOMETER = 'kitchen thermometer'
92
+ THERMOSTAT = 'thermostat'
93
+
94
+
95
+ class IntFlag(IntEnum):
96
+ """DEPRECATED. Integer flag to indicate if a device is not supported.
97
+
98
+ This is used by data models as a default value for feature attributes
99
+ that are not supported by all devices.
100
+
101
+ The default value is -999.
102
+
103
+ Attributes:
104
+ NOT_SUPPORTED: Device is not supported, -999
105
+ """
106
+
107
+ NOT_SUPPORTED = -999
108
+
109
+ def __str__(self) -> str:
110
+ """Return string representation of IntFlag."""
111
+ return str(self.name)
112
+
113
+
114
+ class StrFlag(StrEnum):
115
+ """DEPRECATED. String flag to indicate if a device is not supported.
116
+
117
+ This is used by data models as a default value for feature attributes
118
+ that are not supported by all devices.
119
+
120
+ The default value is "not_supported".
121
+
122
+ Attributes:
123
+ NOT_SUPPORTED: Device is not supported, "not_supported"
124
+ """
125
+
126
+ NOT_SUPPORTED = 'not_supported'
127
+
128
+
129
+ class NightlightStatus(StrEnum):
130
+ """Nightlight status for VeSync devices.
131
+
132
+ Values can be converted to int and bool.
133
+
134
+ Attributes:
135
+ ON: Nightlight is on.
136
+ OFF: Nightlight is off.
137
+ AUTO: Nightlight is in auto mode.
138
+ UNKNOWN: Nightlight status is unknown.
139
+
140
+ Usage:
141
+ ```python
142
+ NightlightStatus.ON
143
+ # <NightlightStatus.ON: 'on'>
144
+ int(NightlightStatus.ON)
145
+ # 1
146
+ bool(NightlightStatus.ON)
147
+ # True
148
+ ```
149
+ """
150
+
151
+ ON = 'on'
152
+ OFF = 'off'
153
+ AUTO = 'auto'
154
+ UNKNOWN = 'unknown'
155
+
156
+ def __bool__(self) -> bool:
157
+ """Return True if nightlight is on or auto."""
158
+ return self in [NightlightStatus.ON, NightlightStatus.AUTO]
159
+
160
+ def __int__(self) -> int:
161
+ """Return integer representation of the enum."""
162
+ if self not in [NightlightStatus.ON, NightlightStatus.OFF]:
163
+ raise ValueError('Only ON and OFF are valid values for int conversion')
164
+ return int(self == NightlightStatus.ON)
165
+
166
+
167
+ class DeviceStatus(StrEnum):
168
+ """VeSync device status enum.
169
+
170
+ In addition to converting to int and bool values,
171
+ this enum can be used to convert from bool and int values
172
+ to corresponding string values.
173
+
174
+ Attributes:
175
+ ON: Device is on.
176
+ OFF: Device is off.
177
+ PAUSED: Device is paused.
178
+ STANDBY: Device is in standby mode.
179
+ IDLE: Device is idle.
180
+ RUNNING: Device is running.
181
+ UNKNOWN: Device status is unknown.
182
+
183
+ Usage:
184
+ ```python
185
+ DeviceStatus.ON
186
+ # <DeviceStatus.ON: 'on'>
187
+ bool(DeviceStatus.ON)
188
+ # True
189
+ int(DeviceStatus.ON)
190
+ # 1
191
+ DeviceStatus.from_int(1)
192
+ # 'on'
193
+ DeviceStatus.from_bool(True)
194
+ # 'on'
195
+ ```
196
+ """
197
+
198
+ ON = 'on'
199
+ OFF = 'off'
200
+ PAUSED = 'paused'
201
+ STANDBY = 'standby'
202
+ IDLE = 'idle'
203
+ RUNNING = 'running'
204
+ UNKNOWN = 'unknown'
205
+
206
+ def __bool__(self) -> bool:
207
+ """Return True if device is on or running."""
208
+ return self in [DeviceStatus.ON, DeviceStatus.RUNNING]
209
+
210
+ def __int__(self) -> int:
211
+ """Return integer representation of the enum.
212
+
213
+ 1 is ON and RUNNING, 0 is OFF, PAUSED, STANDBY, IDLE.
214
+ -1 is UNKNOWN.
215
+ """
216
+ match self:
217
+ case DeviceStatus.ON | DeviceStatus.RUNNING:
218
+ return 1
219
+ case (
220
+ DeviceStatus.OFF
221
+ | DeviceStatus.PAUSED
222
+ | DeviceStatus.STANDBY
223
+ | DeviceStatus.IDLE
224
+ ):
225
+ return 0
226
+ return -1
227
+
228
+ @classmethod
229
+ def from_int(cls, value: int | None) -> str:
230
+ """Convert integer value to corresponding string.
231
+
232
+ If value is 1, return ON and if 0, return OFF.
233
+ If value is -999, return NOT_SUPPORTED.
234
+ """
235
+ if value == 1:
236
+ return cls.ON
237
+ if value == 0:
238
+ return cls.OFF
239
+ if value == IntFlag.NOT_SUPPORTED:
240
+ return StrFlag.NOT_SUPPORTED
241
+ return cls.UNKNOWN
242
+
243
+ @classmethod
244
+ def from_bool(cls, value: bool) -> DeviceStatus:
245
+ """Convert boolean value to corresponding string."""
246
+ return cls.ON if value is True else cls.OFF
247
+
248
+
249
+ class ConnectionStatus(StrEnum):
250
+ """VeSync device connection status enum.
251
+
252
+ Corresponding boolean value is True if device is online.
253
+
254
+ Attributes:
255
+ ONLINE: Device is online.
256
+ OFFLINE: Device is offline.
257
+ UNKNOWN: Device connection status is unknown.
258
+
259
+ Methods:
260
+ from_bool(value: bool | None) -> ConnectionStatus:
261
+ Convert boolean value to corresponding string.
262
+
263
+ Usage:
264
+ ```python
265
+ ConnectionStatus.ONLINE
266
+ # <ConnectionStatus.ONLINE: 'online'>
267
+ bool(ConnectionStatus.ONLINE)
268
+ # True
269
+ ConnectionStatus.ONLINE == ConnectionStatus.ONLINE
270
+ # True
271
+ ```
272
+ """
273
+
274
+ ONLINE = 'online'
275
+ OFFLINE = 'offline'
276
+ UNKNOWN = 'unknown'
277
+
278
+ def __bool__(self) -> bool:
279
+ """Return True if device is online."""
280
+ return self == ConnectionStatus.ONLINE
281
+
282
+ @classmethod
283
+ def from_bool(cls, value: bool | None) -> ConnectionStatus:
284
+ """Convert boolean value to corresponding string.
285
+
286
+ Returns ConnectionStatus.ONLINE if True, else ConnectionStatus.OFFLINE.
287
+ """
288
+ return cls.ONLINE if value else cls.OFFLINE
289
+
290
+
291
+ class NightlightModes(StrEnum):
292
+ """Nightlight modes.
293
+
294
+ Attributes:
295
+ ON: Nightlight is on.
296
+ OFF: Nightlight is off.
297
+ DIM: Nightlight is dimmed.
298
+ AUTO: Nightlight is in auto mode.
299
+ UNKNOWN: Nightlight status is unknown.
300
+ """
301
+
302
+ ON = 'on'
303
+ OFF = 'off'
304
+ DIM = 'dim'
305
+ AUTO = 'auto'
306
+ UNKNOWN = 'unknown'
307
+
308
+ def __bool__(self) -> bool:
309
+ """Return True if nightlight is on or auto.
310
+
311
+ Off and unknown are False, all other True.
312
+ """
313
+ return self in [NightlightModes.ON, NightlightModes.AUTO, NightlightModes.DIM]
314
+
315
+
316
+ class ColorMode(StrEnum):
317
+ """VeSync bulb color modes.
318
+
319
+ Attributes:
320
+ RGB: RGB color mode.
321
+ HSV: HSV color mode.
322
+ WHITE: White color mode.
323
+ COLOR: Color mode.
324
+ """
325
+
326
+ RGB = 'rgb'
327
+ HSV = 'hsv'
328
+ WHITE = 'white'
329
+ COLOR = 'color'
330
+
331
+
332
+ # Purifier Constants
333
+
334
+
335
+ class AirQualityLevel(Enum):
336
+ """Representation of air quality levels as string and integers.
337
+
338
+ Attributes:
339
+ EXCELLENT: Air quality is excellent.
340
+ GOOD: Air quality is good.
341
+ MODERATE: Air quality is moderate.
342
+ POOR: Air quality is poor.
343
+ UNKNOWN: Air quality is unknown.
344
+
345
+ Methods:
346
+ from_string(value: str | None) -> AirQualityLevel:
347
+ Convert string value to corresponding integer.
348
+ from_int(value: int | None) -> AirQualityLevel:
349
+ Convert integer value to corresponding string.
350
+
351
+ Note:
352
+ Alias for "very good" is "excellent".
353
+ Alias for "bad" is "poor".
354
+
355
+ Usage:
356
+ ```python
357
+ AirQualityLevels.EXCELLENT
358
+ # <AirQualityLevels.EXCELLENT: 1>
359
+ AirQualityLevels.from_string("excellent")
360
+ # 1
361
+ AirQualityLevels.from_int(1)
362
+ # "excellent"
363
+ int(AirQualityLevels.EXCELLENT)
364
+ # 1
365
+ str(AirQualityLevels.EXCELLENT)
366
+ # "excellent"
367
+ from_string("good")
368
+ # <AirQualityLevels.GOOD: 2>
369
+ from_int(2)
370
+ # "good"
371
+ ```
372
+ """
373
+
374
+ EXCELLENT = 1
375
+ GOOD = 2
376
+ MODERATE = 3
377
+ POOR = 4
378
+ UNKNOWN = -1
379
+
380
+ def __int__(self) -> int:
381
+ """Return integer representation of the enum."""
382
+ return self.value
383
+
384
+ def __str__(self) -> str:
385
+ """Return string representation of the enum."""
386
+ return self.name.lower()
387
+
388
+ @classmethod
389
+ def from_string(cls, value: str | None) -> AirQualityLevel:
390
+ """Convert string value to corresponding integer.
391
+
392
+ Get enum from string value to normalize different values of the same
393
+ format.
394
+
395
+ Note:
396
+ Values are excellent, good, moderate and poor. Aliases are:
397
+ very good for excellent and bad for poor. Unknown is returned
398
+ if value is None or not in the list.
399
+ """
400
+ _string_to_enum = MappingProxyType(
401
+ {
402
+ 'excellent': cls.EXCELLENT,
403
+ 'very good': cls.EXCELLENT, # Alias
404
+ 'good': cls.GOOD,
405
+ 'moderate': cls.MODERATE,
406
+ 'poor': cls.POOR,
407
+ 'bad': cls.POOR, # Alias
408
+ 'unknown': cls.UNKNOWN,
409
+ }
410
+ )
411
+ if isinstance(value, str) and value.lower() in _string_to_enum:
412
+ return AirQualityLevel(_string_to_enum[value.lower()])
413
+ return cls.UNKNOWN
414
+
415
+ @classmethod
416
+ def from_int(cls, value: int | None) -> AirQualityLevel:
417
+ """Convert integer value to corresponding string."""
418
+ if value in [itm.value for itm in cls]:
419
+ return cls(value)
420
+ return cls.UNKNOWN
421
+
422
+
423
+ class PurifierAutoPreference(StrEnum):
424
+ """Preference Levels for Purifier Auto Mode.
425
+
426
+ Attributes:
427
+ DEFAULT: Default preference level.
428
+ EFFICIENT: Efficient preference level.
429
+ QUIET: Quiet preference level.
430
+ UNKNOWN: Unknown preference level.
431
+ """
432
+
433
+ DEFAULT = 'default'
434
+ EFFICIENT = 'efficient'
435
+ QUIET = 'quiet'
436
+ UNKNOWN = 'unknown'
437
+
438
+
439
+ # Fan Constants
440
+
441
+
442
+ class FanSleepPreference(StrEnum):
443
+ """Sleep mode preferences for VeSync fans.
444
+
445
+ Attributes:
446
+ DEFAULT: Default sleep mode.
447
+ ADVANCED: Advanced sleep mode.
448
+ TURBO: Turbo sleep mode.
449
+ EFFICIENT: Efficient sleep mode.
450
+ QUIET: Quiet sleep mode.
451
+ UNKNOWN: Unknown sleep mode.
452
+ """
453
+
454
+ DEFAULT = 'default'
455
+ ADVANCED = 'advanced'
456
+ TURBO = 'turbo'
457
+ EFFICIENT = 'efficient'
458
+ QUIET = 'quiet'
459
+ TEMP_SENSE = 'tempSense'
460
+ KIDS = 'kids'
461
+ UNKNOWN = 'unknown'
462
+
463
+
464
+ # Device Features
465
+
466
+
467
+ class Features(StrEnum):
468
+ """Base Class for Features Enum to appease typing."""
469
+
470
+
471
+ # Device Features
472
+
473
+
474
+ class HumidifierFeatures(Features):
475
+ """VeSync humidifier features.
476
+
477
+ Attributes:
478
+ ONOFF: Device on/off status.
479
+ CHILD_LOCK: Child lock status.
480
+ NIGHTLIGHT: Nightlight status.
481
+ WATER_LEVEL: Water level status.
482
+ WARM_MIST: Warm mist status.
483
+ AUTO_STOP: Auto stop when target humidity is reached.
484
+ Different from auto, which adjusts fan level to maintain humidity.
485
+ """
486
+
487
+ ONOFF = 'onoff'
488
+ CHILD_LOCK = 'child_lock'
489
+ NIGHTLIGHT = 'night_light'
490
+ WATER_LEVEL = 'water_level'
491
+ WARM_MIST = 'warm_mist'
492
+ AUTO_STOP = 'auto_stop'
493
+ NIGHTLIGHT_BRIGHTNESS = 'nightlight_brightness'
494
+ DRYING_MODE = 'drying_mode'
495
+
496
+
497
+ class PurifierFeatures(Features):
498
+ """VeSync air purifier features.
499
+
500
+ Attributes:
501
+ CHILD_LOCK: Child lock status.
502
+ NIGHTLIGHT: Nightlight status.
503
+ AIR_QUALITY: Air quality status.
504
+ VENT_ANGLE: Vent angle status.
505
+ LIGHT_DETECT: Light detection status.
506
+ PM25: PM2.5 level status.
507
+ PM10: PM10 level status.
508
+ PM1: PM1 level status.
509
+ AQPERCENT: Air quality percentage status.
510
+ RESET_FILTER: Reset filter status.
511
+ """
512
+
513
+ RESET_FILTER = 'reset_filter'
514
+ CHILD_LOCK = 'child_lock'
515
+ NIGHTLIGHT = 'night_light'
516
+ AIR_QUALITY = 'air_quality'
517
+ VENT_ANGLE = 'fan_rotate'
518
+ LIGHT_DETECT = 'light_detect'
519
+ PM25 = 'pm25'
520
+ PM10 = 'pm10'
521
+ PM1 = 'pm1'
522
+ AQPERCENT = 'aq_percent'
523
+
524
+
525
+ class PurifierStringLevels(Features):
526
+ """String levels for Air Purifier fan speed.
527
+
528
+ Attributes:
529
+ LOW: Low fan speed.
530
+ MEDIUM: Medium fan speed.
531
+ HIGH: High fan speed.
532
+ """
533
+
534
+ LOW = 'low'
535
+ MEDIUM = 'medium'
536
+ HIGH = 'high'
537
+
538
+
539
+ class BulbFeatures(Features):
540
+ """VeSync bulb features.
541
+
542
+ Attributes:
543
+ ONOFF: Device on/off status.
544
+ DIMMABLE: Dimmable status.
545
+ COLOR_TEMP: Color temperature status.
546
+ MULTICOLOR: Multicolor status.
547
+ """
548
+
549
+ ONOFF = 'onoff'
550
+ DIMMABLE = 'dimmable'
551
+ COLOR_TEMP = 'color_temp'
552
+ MULTICOLOR = 'multicolor'
553
+
554
+
555
+ class OutletFeatures(Features):
556
+ """VeSync outlet features.
557
+
558
+ Attributes:
559
+ ONOFF: Device on/off status.
560
+ ENERGY_MONITOR: Energy monitor status.
561
+ NIGHTLIGHT: Nightlight status.
562
+ """
563
+
564
+ ONOFF = 'onoff'
565
+ ENERGY_MONITOR = 'energy_monitor'
566
+ NIGHTLIGHT = 'nightlight'
567
+
568
+
569
+ class SwitchFeatures(Features):
570
+ """VeSync switch features.
571
+
572
+ Attributes:
573
+ ONOFF: Device on/off status.
574
+ DIMMABLE: Dimmable status.
575
+ INDICATOR_LIGHT: Indicator light status.
576
+ BACKLIGHT: Backlight status.
577
+ BACKLIGHT_RGB: RGB backlight status.
578
+ """
579
+
580
+ ONOFF = 'onoff'
581
+ DIMMABLE = 'dimmable'
582
+ INDICATOR_LIGHT = 'indicator_light'
583
+ BACKLIGHT = 'backlight'
584
+ BACKLIGHT_RGB = 'backlight_rgb'
585
+
586
+
587
+ class FanFeatures(Features):
588
+ """VeSync fan features."""
589
+
590
+ OSCILLATION = 'oscillation'
591
+ SOUND = 'sound'
592
+ DISPLAYING_TYPE = 'displaying_type' # Unknown functionality
593
+
594
+
595
+ # Modes
596
+
597
+
598
+ class PurifierModes(Features):
599
+ """VeSync air purifier modes.
600
+
601
+ Attributes:
602
+ AUTO: Auto mode.
603
+ MANUAL: Manual mode.
604
+ SLEEP: Sleep mode.
605
+ TURBO: Turbo mode.
606
+ PET: Pet mode.
607
+ UNKNOWN: Unknown mode.
608
+ """
609
+
610
+ AUTO = 'auto'
611
+ MANUAL = 'manual'
612
+ SLEEP = 'sleep'
613
+ TURBO = 'turbo'
614
+ PET = 'pet'
615
+ UNKNOWN = 'unknown'
616
+
617
+
618
+ class HumidifierModes(Features):
619
+ """VeSync humidifier modes.
620
+
621
+ Attributes:
622
+ AUTO: Auto mode.
623
+ MANUAL: Manual mode.
624
+ HUMIDITY: Humidity mode.
625
+ SLEEP: Sleep mode.
626
+ TURBO: Turbo mode.
627
+ PET: Pet mode.
628
+ UNKNOWN: Unknown mode.
629
+ AUTOPRO: AutoPro mode.
630
+ """
631
+
632
+ AUTO = 'auto'
633
+ MANUAL = 'manual'
634
+ HUMIDITY = 'humidity'
635
+ SLEEP = 'sleep'
636
+ TURBO = 'turbo'
637
+ PET = 'pet'
638
+ UNKNOWN = 'unknown'
639
+ AUTOPRO = 'autopro'
640
+
641
+
642
+ class FanModes(StrEnum):
643
+ """VeSync fan modes.
644
+
645
+ Attributes:
646
+ AUTO: Auto mode.
647
+ NORMAL: Normal mode.
648
+ MANUAL: Manual mode.
649
+ SLEEP: Sleep mode.
650
+ TURBO: Turbo mode.
651
+ PET: Pet mode.
652
+ UNKNOWN: Unknown mode.
653
+ ADVANCED_SLEEP: Advanced sleep mode.
654
+ """
655
+
656
+ AUTO = 'auto'
657
+ NORMAL = 'normal'
658
+ MANUAL = 'normal'
659
+ SLEEP = 'advancedSleep'
660
+ TURBO = 'turbo'
661
+ PET = 'pet'
662
+ UNKNOWN = 'unknown'
663
+ ADVANCED_SLEEP = 'advancedSleep'
664
+
665
+
666
+ # Air Fryer Constants
667
+
668
+ AIRFRYER_PID_MAP = {
669
+ 'WiFi_SKA_AirFryer137_US': 'wnxwqs76gknqyzjn',
670
+ 'WiFi_SKA_AirFryer158_US': '2cl8hmafsthl65bd',
671
+ 'WiFi_AirFryer_CS158-AF_EU': '8t8op7pcvzlsbosm',
672
+ }
673
+ """PID's for VeSync Air Fryers based on ConfigModule."""
674
+
675
+
676
+ # Thermostat Constants
677
+
678
+
679
+ class ThermostatWorkModes(IntEnum):
680
+ """Working modes for VeSync Aura thermostats.
681
+
682
+ Based on the VeSync app and API values.
683
+
684
+ Attributes:
685
+ OFF: Thermostat is off (0).
686
+ HEAT: Thermostat is in heating mode (1).
687
+ COOL: Thermostat is in cooling mode (2).
688
+ AUTO: Thermostat is in auto mode (3).
689
+ EM_HEAT: Thermostat is in emergency heating mode (4).
690
+ SMART_AUTO: Thermostat is in smart auto mode (5).
691
+ """
692
+
693
+ OFF = 0
694
+ HEAT = 1
695
+ COOL = 2
696
+ AUTO = 3
697
+ EM_HEAT = 4
698
+ SMART_AUTO = 5
699
+
700
+
701
+ class ThermostatFanModes(IntEnum):
702
+ """Fan modes for VeSync Aura thermostats.
703
+
704
+ Based on the VeSync app and API values.
705
+
706
+ Attributes:
707
+ AUTO: Fan is in auto mode (1).
708
+ ON: Fan is on (2).
709
+ CIRCULATE: Fan is in circulate mode (3).
710
+ """
711
+
712
+ AUTO = 1
713
+ ON = 2
714
+ CIRCULATE = 3
715
+
716
+
717
+ class ThermostatHoldOptions(IntEnumMixin):
718
+ """Hold options for VeSync Aura thermostats.
719
+
720
+ Attributes:
721
+ UNTIL_NEXT_SCHEDULED_ITEM: Hold until next scheduled item (2).
722
+ TWO_HOURS: Hold for two hours (3).
723
+ FOUR_HOURS: Hold for four hours (4).
724
+ PERMANENTLY: Hold permanently (5).
725
+ """
726
+
727
+ UNTIL_NEXT_SCHEDULED_ITEM = 2
728
+ TWO_HOURS = 3
729
+ FOUR_HOURS = 4
730
+ PERMANENTLY = 5
731
+
732
+
733
+ class ThermostatHoldStatus(IntEnumMixin):
734
+ """Set the hold status of the thermostat.
735
+
736
+ Attributes:
737
+ SET: Set the hold status (1).
738
+ CANCEL: Cancel the hold status (0).
739
+ """
740
+
741
+ SET = 1
742
+ CANCEL = 0
743
+
744
+
745
+ class ThermostatScheduleOrHoldOptions(IntEnumMixin):
746
+ """Schedule or hold options for VeSync Aura thermostats."""
747
+
748
+ NOT_SCHEDULE_NOT_HOLD = 0
749
+ ON_SCHEDULE = 1
750
+ ON_HOLD = 2
751
+ VACATION = 3
752
+
753
+
754
+ class ThermostatEcoTypes(IntEnumMixin):
755
+ """Eco types for VeSync Aura thermostats."""
756
+
757
+ COMFORT_SECOND = 1
758
+ COMFORT_FIRST = 2
759
+ BALANCE = 3
760
+ ECO_FIRST = 4
761
+ ECO_SECOND = 5
762
+
763
+
764
+ class ThermostatRoutineTypes(IntEnumMixin):
765
+ """Routine types for VeSync Aura thermostats."""
766
+
767
+ HOME = 2
768
+ AWAY = 1
769
+ SLEEP = 3
770
+ CUSTOM = 4
771
+
772
+
773
+ class ThermostatAlarmCodes(IntEnumMixin):
774
+ """Alarm codes for VeSync Aura thermostats."""
775
+
776
+ HEAT_COOL = 100
777
+ ABOVE_SAFE_TEMP = 102
778
+ HEAT_RUNNING_TIME_TOO_LONG = 104
779
+
780
+
781
+ class ThermostatReminderCodes(IntEnumMixin):
782
+ """Reminder codes for VeSync Aura thermostats."""
783
+
784
+ FILTER = 150
785
+ HVAC = 151
786
+
787
+
788
+ class ThermostatWorkStatusCodes(IntEnumMixin):
789
+ """Work status codes for VeSync Aura thermostats."""
790
+
791
+ OFF = 0
792
+ HEATING = 1
793
+ COOLING = 2
794
+ EM_HEATING = 3
795
+
796
+
797
+ class ThermostatFanStatus(IntEnumMixin):
798
+ """Fan Status Enum for Aura Thermostats."""
799
+
800
+ OFF = 0
801
+ ON = 1
802
+
803
+
804
+ class ThermostatConst:
805
+ """Constants for VeSync Aura thermostats."""
806
+
807
+ ReminderCode = ThermostatReminderCodes
808
+ AlarmCode = ThermostatAlarmCodes
809
+ WorkMode = ThermostatWorkModes
810
+ FanStatus = ThermostatFanStatus
811
+ FanMode = ThermostatFanModes
812
+ HoldOption = ThermostatHoldOptions
813
+ EcoType = ThermostatEcoTypes
814
+ RoutineType = ThermostatRoutineTypes
815
+ ScheduleOrHoldOption = ThermostatScheduleOrHoldOptions
816
+ WorkStatus = ThermostatWorkStatusCodes
817
+
818
+
819
+ # ------------------- AIR FRYER CONST ------------------ #
820
+
821
+
822
+ CUSTOM_RECIPE_ID = 1
823
+ CUSTOM_RECIPE_TYPE = 3
824
+ CUSTOM_RECIPE_NAME = 'Manual Cook'
825
+ CUSTOM_COOK_MODE = 'custom'