pyvesync 2.1.9__tar.gz → 2.1.11__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.
Files changed (23) hide show
  1. {pyvesync-2.1.9 → pyvesync-2.1.11}/MANIFEST.in +2 -0
  2. {pyvesync-2.1.9 → pyvesync-2.1.11}/PKG-INFO +36 -10
  3. pyvesync-2.1.9/src/pyvesync.egg-info/PKG-INFO → pyvesync-2.1.11/README.md +29 -27
  4. {pyvesync-2.1.9 → pyvesync-2.1.11}/setup.py +38 -39
  5. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync/helpers.py +38 -62
  6. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync/vesync.py +55 -4
  7. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync/vesyncfan.py +931 -67
  8. pyvesync-2.1.9/README.md → pyvesync-2.1.11/src/pyvesync.egg-info/PKG-INFO +53 -8
  9. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync.egg-info/SOURCES.txt +1 -3
  10. pyvesync-2.1.9/src/pyvesync.egg-info/not-zip-safe +0 -1
  11. pyvesync-2.1.9/test/test.py +0 -82
  12. {pyvesync-2.1.9 → pyvesync-2.1.11}/LICENSE +0 -0
  13. {pyvesync-2.1.9 → pyvesync-2.1.11}/requirements.txt +0 -0
  14. {pyvesync-2.1.9 → pyvesync-2.1.11}/setup.cfg +0 -0
  15. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync/__init__.py +0 -0
  16. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync/vesyncbasedevice.py +0 -0
  17. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync/vesyncbulb.py +0 -0
  18. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync/vesynckitchen.py +0 -0
  19. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync/vesyncoutlet.py +0 -0
  20. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync/vesyncswitch.py +0 -0
  21. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync.egg-info/dependency_links.txt +0 -0
  22. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync.egg-info/requires.txt +0 -0
  23. {pyvesync-2.1.9 → pyvesync-2.1.11}/src/pyvesync.egg-info/top_level.txt +0 -0
@@ -1 +1,3 @@
1
1
  include README.md LICENSE requirements.txt
2
+ exclude test
3
+ prune test
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyvesync
3
- Version: 2.1.9
3
+ Version: 2.1.11
4
4
  Summary: pyvesync is a library to manage Etekcity Devices, Cosori Air Fryers and Levoit Air Purifiers run on the VeSync app.
5
5
  Home-page: https://github.com/webdjoe/pyvesync
6
6
  Author: Mark Perdue, Joe Trabulsy
@@ -14,8 +14,13 @@ Classifier: Natural Language :: English
14
14
  Classifier: Programming Language :: Python :: 3.8
15
15
  Requires-Python: >=3.8
16
16
  Description-Content-Type: text/markdown
17
- Provides-Extra: dev
18
17
  License-File: LICENSE
18
+ Requires-Dist: requests>=2.20.0
19
+ Provides-Extra: dev
20
+ Requires-Dist: pytest; extra == "dev"
21
+ Requires-Dist: pytest-cov; extra == "dev"
22
+ Requires-Dist: yaml; extra == "dev"
23
+ Requires-Dist: tox; extra == "dev"
19
24
 
20
25
  # pyvesync [![build status](https://img.shields.io/pypi/v/pyvesync.svg)](https://pypi.python.org/pypi/pyvesync) [![Build Status](https://dev.azure.com/webdjoe/pyvesync/_apis/build/status/webdjoe.pyvesync?branchName=master)](https://dev.azure.com/webdjoe/pyvesync/_build/latest?definitionId=4&branchName=master) [![Open Source? Yes!](https://badgen.net/badge/Open%20Source%20%3F/Yes%21/blue?icon=github)](https://github.com/Naereen/badges/) [![PyPI license](https://img.shields.io/pypi/l/ansicolortags.svg)](https://pypi.python.org/pypi/ansicolortags/) <!-- omit in toc -->
21
26
 
@@ -48,9 +53,9 @@ pyvesync is a library to manage VeSync compatible [smart home devices](#supporte
48
53
  - [Standard Air Purifier Properties \& Methods](#standard-air-purifier-properties--methods)
49
54
  - [Air Purifier Properties](#air-purifier-properties)
50
55
  - [Air Purifier Methods](#air-purifier-methods)
51
- - [Levoit Purifier Core200S/300S/400S and Vital 100S/200S Properties](#levoit-purifier-core200s300s400s-and-vital-100s200s-properties)
52
- - [Levoit Purifier Core200S/300S/400S and Vital 100S/200S Methods](#levoit-purifier-core200s300s400s-and-vital-100s200s-methods)
53
- - [Levoit Vital 100S/200S Properties and Methods](#levoit-vital-100s200s-properties-and-methods)
56
+ - [Levoit Purifier Core200S/300S/400S and Vital 100S/200S Properties](#levoit-purifier-core200s300s400s-vital-100s200s--everest-air-properties)
57
+ - [Levoit Purifier Core200S/300S/400S, Vital 100S/200S & Everest Air Methods](#levoit-purifier-core200s300s400s-vital-100s200s--everest-air-methods)
58
+ - [Levoit Vital 100S/200S Properties and Methods](#levoit-vital-100s200s--everest-air-properties-and-methods)
54
59
  - [Lights API Methods \& Properties](#lights-api-methods--properties)
55
60
  - [Brightness Light Bulb Method and Properties](#brightness-light-bulb-method-and-properties)
56
61
  - [Light Bulb Color Temperature Methods and Properties](#light-bulb-color-temperature-methods-and-properties)
@@ -113,6 +118,7 @@ pip install pyvesync
113
118
  5. Core 600S
114
119
  6. Vital 100S
115
120
  7. Vital 200S
121
+ 8. Everest Air
116
122
 
117
123
  ### Etekcity Bulbs
118
124
 
@@ -130,6 +136,7 @@ pip install pyvesync
130
136
  3. LUH-D301S-WEU Dual (200S)
131
137
  4. LV600S
132
138
  5. OasisMist LUS-O415S-WUS
139
+ 6. OasisMist LUH-M101S-WUS
133
140
 
134
141
  Cosori Air Fryer
135
142
 
@@ -348,13 +355,13 @@ Compatible levels for each model:
348
355
  - PUR131S [1, 2, 3]
349
356
  - Vital 100S/200S [1, 2, 3, 4]
350
357
 
351
- #### Levoit Purifier Core200S/300S/400S and Vital 100S/200S Properties
358
+ #### Levoit Purifier Core200S/300S/400S, Vital 100S/200S & Everest Air Properties
352
359
 
353
360
  `VeSyncFan.child_lock` - Return the state of the child lock (True=On/False=off)
354
361
 
355
362
  `VeSyncAir.night_light` - Return the state of the night light (on/dim/off) **Not available on Vital 100S/200S**
356
363
 
357
- #### Levoit Purifier Core200S/300S/400S and Vital 100S/200S Methods
364
+ #### Levoit Purifier Core200S/300S/400S, Vital 100S/200S & Everest Air Methods
358
365
 
359
366
  `VeSyncFan.child_lock_on()` Enable child lock
360
367
 
@@ -366,13 +373,15 @@ Compatible levels for each model:
366
373
 
367
374
  `VeSyncFan.set_night_light('on'|'dim'|'off')` - Set night light brightness
368
375
 
369
- `VeSyncFan.get_timer()` - Get any running timers, stores Timer DataClass in `VeSyncFan.timer`
376
+ `VeSyncFan.get_timer()` - Get any running timers, stores Timer DataClass in `VeSyncFan.timer`. See [Timer Dataclass](#timer-dataclass)
370
377
 
371
378
  `VeSyncFan.set_timer(timer_duration=3000)` - Set a timer for the device, only turns device off. Timer DataClass stored in `VeSyncFan.timer`
372
379
 
373
380
  `VeSyncFan.clear_timer()` - Cancel any running timer
374
381
 
375
- #### Levoit Vital 100S/200S Properties and Methods
382
+ `VeSyncFan.reset_filter()` - Reset filter to 100% **NOTE: Only available on Core200S**
383
+
384
+ #### Levoit Vital 100S/200S & Everest Air Properties and Methods
376
385
 
377
386
  The Levoit Vital 100S/200S has additional features not available on other models.
378
387
 
@@ -392,6 +401,23 @@ The Levoit Vital 100S/200S has additional features not available on other models
392
401
 
393
402
  `VeSyncFan.set_light_detection_off()` - Turn off light detection mode
394
403
 
404
+ #### Levoit Everest Air Properties & Methods
405
+
406
+ `VeSyncFan.turbo_mode()` - Set turbo mode
407
+
408
+ Additional properties in the `VeSyncFan['details']` dictionary:
409
+
410
+ ```python
411
+ VeSyncFan['Details'] = {
412
+ 'pm1': 0, # air quality reading of particulates 1.0 microns
413
+ 'pm10': 10, # air quality reading of particulates 10 microns
414
+ 'fan_rotate_angle': 45, # angle of fan vents
415
+ 'aq_percent': 45, # Air Quality percentage reading
416
+ 'filter_open_state': False # returns bool of filter open
417
+ }
418
+
419
+ ```
420
+
395
421
  ### Lights API Methods & Properties
396
422
 
397
423
  #### Brightness Light Bulb Method and Properties
@@ -1045,7 +1071,7 @@ After:
1045
1071
  }
1046
1072
  ```
1047
1073
 
1048
- # Contributing
1074
+ ## Contributing
1049
1075
 
1050
1076
  All [contributions](CONTRIBUTING.md) are welcome.
1051
1077
 
@@ -1,22 +1,3 @@
1
- Metadata-Version: 2.1
2
- Name: pyvesync
3
- Version: 2.1.9
4
- Summary: pyvesync is a library to manage Etekcity Devices, Cosori Air Fryers and Levoit Air Purifiers run on the VeSync app.
5
- Home-page: https://github.com/webdjoe/pyvesync
6
- Author: Mark Perdue, Joe Trabulsy
7
- Author-email: webdjoe@gmail.com
8
- License: MIT
9
- Keywords: iot,vesync,levoit,etekcity,cosori,valceno
10
- Classifier: License :: OSI Approved :: MIT License
11
- Classifier: Intended Audience :: Developers
12
- Classifier: Intended Audience :: End Users/Desktop
13
- Classifier: Natural Language :: English
14
- Classifier: Programming Language :: Python :: 3.8
15
- Requires-Python: >=3.8
16
- Description-Content-Type: text/markdown
17
- Provides-Extra: dev
18
- License-File: LICENSE
19
-
20
1
  # pyvesync [![build status](https://img.shields.io/pypi/v/pyvesync.svg)](https://pypi.python.org/pypi/pyvesync) [![Build Status](https://dev.azure.com/webdjoe/pyvesync/_apis/build/status/webdjoe.pyvesync?branchName=master)](https://dev.azure.com/webdjoe/pyvesync/_build/latest?definitionId=4&branchName=master) [![Open Source? Yes!](https://badgen.net/badge/Open%20Source%20%3F/Yes%21/blue?icon=github)](https://github.com/Naereen/badges/) [![PyPI license](https://img.shields.io/pypi/l/ansicolortags.svg)](https://pypi.python.org/pypi/ansicolortags/) <!-- omit in toc -->
21
2
 
22
3
  pyvesync is a library to manage VeSync compatible [smart home devices](#supported-devices)
@@ -48,9 +29,9 @@ pyvesync is a library to manage VeSync compatible [smart home devices](#supporte
48
29
  - [Standard Air Purifier Properties \& Methods](#standard-air-purifier-properties--methods)
49
30
  - [Air Purifier Properties](#air-purifier-properties)
50
31
  - [Air Purifier Methods](#air-purifier-methods)
51
- - [Levoit Purifier Core200S/300S/400S and Vital 100S/200S Properties](#levoit-purifier-core200s300s400s-and-vital-100s200s-properties)
52
- - [Levoit Purifier Core200S/300S/400S and Vital 100S/200S Methods](#levoit-purifier-core200s300s400s-and-vital-100s200s-methods)
53
- - [Levoit Vital 100S/200S Properties and Methods](#levoit-vital-100s200s-properties-and-methods)
32
+ - [Levoit Purifier Core200S/300S/400S and Vital 100S/200S Properties](#levoit-purifier-core200s300s400s-vital-100s200s--everest-air-properties)
33
+ - [Levoit Purifier Core200S/300S/400S, Vital 100S/200S & Everest Air Methods](#levoit-purifier-core200s300s400s-vital-100s200s--everest-air-methods)
34
+ - [Levoit Vital 100S/200S Properties and Methods](#levoit-vital-100s200s--everest-air-properties-and-methods)
54
35
  - [Lights API Methods \& Properties](#lights-api-methods--properties)
55
36
  - [Brightness Light Bulb Method and Properties](#brightness-light-bulb-method-and-properties)
56
37
  - [Light Bulb Color Temperature Methods and Properties](#light-bulb-color-temperature-methods-and-properties)
@@ -113,6 +94,7 @@ pip install pyvesync
113
94
  5. Core 600S
114
95
  6. Vital 100S
115
96
  7. Vital 200S
97
+ 8. Everest Air
116
98
 
117
99
  ### Etekcity Bulbs
118
100
 
@@ -130,6 +112,7 @@ pip install pyvesync
130
112
  3. LUH-D301S-WEU Dual (200S)
131
113
  4. LV600S
132
114
  5. OasisMist LUS-O415S-WUS
115
+ 6. OasisMist LUH-M101S-WUS
133
116
 
134
117
  Cosori Air Fryer
135
118
 
@@ -348,13 +331,13 @@ Compatible levels for each model:
348
331
  - PUR131S [1, 2, 3]
349
332
  - Vital 100S/200S [1, 2, 3, 4]
350
333
 
351
- #### Levoit Purifier Core200S/300S/400S and Vital 100S/200S Properties
334
+ #### Levoit Purifier Core200S/300S/400S, Vital 100S/200S & Everest Air Properties
352
335
 
353
336
  `VeSyncFan.child_lock` - Return the state of the child lock (True=On/False=off)
354
337
 
355
338
  `VeSyncAir.night_light` - Return the state of the night light (on/dim/off) **Not available on Vital 100S/200S**
356
339
 
357
- #### Levoit Purifier Core200S/300S/400S and Vital 100S/200S Methods
340
+ #### Levoit Purifier Core200S/300S/400S, Vital 100S/200S & Everest Air Methods
358
341
 
359
342
  `VeSyncFan.child_lock_on()` Enable child lock
360
343
 
@@ -366,13 +349,15 @@ Compatible levels for each model:
366
349
 
367
350
  `VeSyncFan.set_night_light('on'|'dim'|'off')` - Set night light brightness
368
351
 
369
- `VeSyncFan.get_timer()` - Get any running timers, stores Timer DataClass in `VeSyncFan.timer`
352
+ `VeSyncFan.get_timer()` - Get any running timers, stores Timer DataClass in `VeSyncFan.timer`. See [Timer Dataclass](#timer-dataclass)
370
353
 
371
354
  `VeSyncFan.set_timer(timer_duration=3000)` - Set a timer for the device, only turns device off. Timer DataClass stored in `VeSyncFan.timer`
372
355
 
373
356
  `VeSyncFan.clear_timer()` - Cancel any running timer
374
357
 
375
- #### Levoit Vital 100S/200S Properties and Methods
358
+ `VeSyncFan.reset_filter()` - Reset filter to 100% **NOTE: Only available on Core200S**
359
+
360
+ #### Levoit Vital 100S/200S & Everest Air Properties and Methods
376
361
 
377
362
  The Levoit Vital 100S/200S has additional features not available on other models.
378
363
 
@@ -392,6 +377,23 @@ The Levoit Vital 100S/200S has additional features not available on other models
392
377
 
393
378
  `VeSyncFan.set_light_detection_off()` - Turn off light detection mode
394
379
 
380
+ #### Levoit Everest Air Properties & Methods
381
+
382
+ `VeSyncFan.turbo_mode()` - Set turbo mode
383
+
384
+ Additional properties in the `VeSyncFan['details']` dictionary:
385
+
386
+ ```python
387
+ VeSyncFan['Details'] = {
388
+ 'pm1': 0, # air quality reading of particulates 1.0 microns
389
+ 'pm10': 10, # air quality reading of particulates 10 microns
390
+ 'fan_rotate_angle': 45, # angle of fan vents
391
+ 'aq_percent': 45, # Air Quality percentage reading
392
+ 'filter_open_state': False # returns bool of filter open
393
+ }
394
+
395
+ ```
396
+
395
397
  ### Lights API Methods & Properties
396
398
 
397
399
  #### Brightness Light Bulb Method and Properties
@@ -1045,7 +1047,7 @@ After:
1045
1047
  }
1046
1048
  ```
1047
1049
 
1048
- # Contributing
1050
+ ## Contributing
1049
1051
 
1050
1052
  All [contributions](CONTRIBUTING.md) are welcome.
1051
1053
 
@@ -1,39 +1,38 @@
1
- """pyvesync setup script."""
2
-
3
- from os import path
4
- from setuptools import setup, find_packages
5
-
6
-
7
- this_directory = path.abspath(path.dirname(__file__))
8
- with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
9
- long_description = f.read()
10
-
11
- setup(
12
- name='pyvesync',
13
- version='2.1.9',
14
- description='pyvesync is a library to manage Etekcity\
15
- Devices, Cosori Air Fryers and Levoit Air \
16
- Purifiers run on the VeSync app.',
17
- long_description=long_description,
18
- long_description_content_type='text/markdown',
19
- url='https://github.com/webdjoe/pyvesync',
20
- author='Mark Perdue, Joe Trabulsy',
21
- author_email='webdjoe@gmail.com',
22
- license='MIT',
23
- classifiers=[
24
- 'License :: OSI Approved :: MIT License',
25
- 'Intended Audience :: Developers',
26
- 'Intended Audience :: End Users/Desktop',
27
- 'Natural Language :: English',
28
- 'Programming Language :: Python :: 3.8',
29
- ],
30
- keywords=['iot', 'vesync', 'levoit', 'etekcity', 'cosori', 'valceno'],
31
- packages=find_packages('src', exclude=['tests', 'tests.*']),
32
- package_dir={'': 'src'},
33
- zip_safe=False,
34
- install_requires=['requests>=2.20.0'],
35
- extras_require={
36
- 'dev': ['pytest', 'pytest-cov', 'yaml', 'tox']
37
- },
38
- python_requires='>=3.8',
39
- )
1
+ """pyvesync setup script."""
2
+
3
+ from os import path
4
+ from setuptools import setup, find_packages
5
+
6
+
7
+ this_directory = path.abspath(path.dirname(__file__))
8
+ with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
9
+ long_description = f.read()
10
+
11
+ setup(
12
+ name='pyvesync',
13
+ version='2.1.11',
14
+ description='pyvesync is a library to manage Etekcity\
15
+ Devices, Cosori Air Fryers and Levoit Air \
16
+ Purifiers run on the VeSync app.',
17
+ long_description=long_description,
18
+ long_description_content_type='text/markdown',
19
+ url='https://github.com/webdjoe/pyvesync',
20
+ author='Mark Perdue, Joe Trabulsy',
21
+ author_email='webdjoe@gmail.com',
22
+ license='MIT',
23
+ classifiers=[
24
+ 'License :: OSI Approved :: MIT License',
25
+ 'Intended Audience :: Developers',
26
+ 'Intended Audience :: End Users/Desktop',
27
+ 'Natural Language :: English',
28
+ 'Programming Language :: Python :: 3.8',
29
+ ],
30
+ keywords=['iot', 'vesync', 'levoit', 'etekcity', 'cosori', 'valceno'],
31
+ packages=find_packages('src', exclude=['tests', 'test*']),
32
+ package_dir={'': 'src'},
33
+ install_requires=['requests>=2.20.0'],
34
+ extras_require={
35
+ 'dev': ['pytest', 'pytest-cov', 'yaml', 'tox']
36
+ },
37
+ python_requires='>=3.8',
38
+ )
@@ -6,7 +6,7 @@ import time
6
6
  import json
7
7
  import colorsys
8
8
  from dataclasses import dataclass, field, InitVar
9
- from typing import NamedTuple, Optional, Union
9
+ from typing import Any, Dict, NamedTuple, Optional, Union
10
10
  import re
11
11
  import requests
12
12
 
@@ -38,7 +38,7 @@ class Helpers:
38
38
  """VeSync Helper Functions."""
39
39
 
40
40
  @staticmethod
41
- def req_headers(manager) -> dict:
41
+ def req_headers(manager) -> Dict[str, str]:
42
42
  """Build header for api requests."""
43
43
  headers = {
44
44
  'accept-language': 'en',
@@ -51,7 +51,7 @@ class Helpers:
51
51
  return headers
52
52
 
53
53
  @staticmethod
54
- def req_header_bypass() -> dict:
54
+ def req_header_bypass() -> Dict[str, str]:
55
55
  """Build header for api requests on 'bypass' endpoint."""
56
56
  return {
57
57
  'Content-Type': 'application/json; charset=UTF-8',
@@ -59,17 +59,17 @@ class Helpers:
59
59
  }
60
60
 
61
61
  @staticmethod
62
- def req_body_base(manager) -> dict:
62
+ def req_body_base(manager) -> Dict[str, str]:
63
63
  """Return universal keys for body of api requests."""
64
64
  return {'timeZone': manager.time_zone, 'acceptLanguage': 'en'}
65
65
 
66
66
  @staticmethod
67
- def req_body_auth(manager) -> dict:
67
+ def req_body_auth(manager) -> Dict[str, str]:
68
68
  """Keys for authenticating api requests."""
69
69
  return {'accountID': manager.account_id, 'token': manager.token}
70
70
 
71
71
  @staticmethod
72
- def req_body_details() -> dict:
72
+ def req_body_details() -> Dict[str, str]:
73
73
  """Detail keys for api requests."""
74
74
  return {
75
75
  'appVersion': APP_VERSION,
@@ -79,83 +79,57 @@ class Helpers:
79
79
  }
80
80
 
81
81
  @classmethod
82
- def req_body(cls, manager, type_) -> dict:
82
+ def req_body(cls, manager, type_) -> Dict[str, Any]:
83
83
  """Builder for body of api requests."""
84
- body = {}
84
+ body = cls.req_body_base(manager)
85
85
 
86
86
  if type_ == 'login':
87
- body = {**cls.req_body_base(manager),
88
- **cls.req_body_details()}
89
- body['email'] = manager.username
90
- body['password'] = cls.hash_password(manager.password)
91
- body['devToken'] = ''
92
- body['userType'] = USER_TYPE
93
- body['method'] = 'login'
94
- elif type_ == 'devicedetail':
95
- body = {
96
- **cls.req_body_base(manager),
97
- **cls.req_body_auth(manager),
98
- **cls.req_body_details(),
99
- }
100
- body['method'] = 'devicedetail'
101
- body['mobileId'] = MOBILE_ID
102
- elif type_ == 'devicelist':
103
- body = {
104
- **cls.req_body_base(manager),
105
- **cls.req_body_auth(manager),
106
- **cls.req_body_details(),
107
- }
87
+ body |= cls.req_body_details() # type: ignore
88
+ body |= {
89
+ 'email': manager.username,
90
+ 'password': cls.hash_password(manager.password),
91
+ 'devToken': '',
92
+ 'userType': USER_TYPE,
93
+ 'method': 'login'
94
+ } # type: ignore
95
+ return body
96
+
97
+ body |= cls.req_body_auth(manager) # type: ignore
98
+
99
+ if type_ == 'devicestatus':
100
+ return body
101
+
102
+ body |= cls.req_body_details() # type: ignore
103
+
104
+ if type_ == 'devicelist':
108
105
  body['method'] = 'devices'
109
106
  body['pageNo'] = '1'
110
107
  body['pageSize'] = '100'
111
- elif type_ == 'devicestatus':
112
- body = {**cls.req_body_base(manager),
113
- **cls.req_body_auth(manager)}
108
+
109
+ elif type_ == 'devicedetail':
110
+ body['method'] = 'devicedetail'
111
+ body['mobileId'] = MOBILE_ID
112
+
114
113
  elif type_ == 'energy_week':
115
- body = {
116
- **cls.req_body_base(manager),
117
- **cls.req_body_auth(manager),
118
- **cls.req_body_details(),
119
- }
120
114
  body['method'] = 'energyweek'
121
115
  body['mobileId'] = MOBILE_ID
116
+
122
117
  elif type_ == 'energy_month':
123
- body = {
124
- **cls.req_body_base(manager),
125
- **cls.req_body_auth(manager),
126
- **cls.req_body_details(),
127
- }
128
118
  body['method'] = 'energymonth'
129
119
  body['mobileId'] = MOBILE_ID
120
+
130
121
  elif type_ == 'energy_year':
131
- body = {
132
- **cls.req_body_base(manager),
133
- **cls.req_body_auth(manager),
134
- **cls.req_body_details(),
135
- }
136
122
  body['method'] = 'energyyear'
137
123
  body['mobileId'] = MOBILE_ID
124
+
138
125
  elif type_ == 'bypass':
139
- body = {
140
- **cls.req_body_base(manager),
141
- **cls.req_body_auth(manager),
142
- **cls.req_body_details(),
143
- }
144
126
  body['method'] = 'bypass'
127
+
145
128
  elif type_ == 'bypassV2':
146
- body = {
147
- **cls.req_body_base(manager),
148
- **cls.req_body_auth(manager),
149
- **cls.req_body_details(),
150
- }
151
129
  body['deviceRegion'] = DEFAULT_REGION
152
130
  body['method'] = 'bypassV2'
131
+
153
132
  elif type_ == 'bypass_config':
154
- body = {
155
- **cls.req_body_base(manager),
156
- **cls.req_body_auth(manager),
157
- **cls.req_body_details(),
158
- }
159
133
  body['method'] = 'firmwareUpdateInfo'
160
134
 
161
135
  return body
@@ -237,6 +211,8 @@ class Helpers:
237
211
  API_BASE_URL + api, json=json_object, headers=headers,
238
212
  timeout=API_TIMEOUT
239
213
  )
214
+ else:
215
+ raise NameError(f'Invalid method {method}')
240
216
  except requests.exceptions.RequestException as e:
241
217
  logger.debug(e)
242
218
  except Exception as e: # pylint: disable=broad-except
@@ -74,11 +74,45 @@ def object_factory(dev_type, config, manager) -> Tuple[str, VeSyncBaseDevice]:
74
74
 
75
75
 
76
76
  class VeSync: # pylint: disable=function-redefined
77
- """VeSync API functions."""
77
+ """VeSync Manager Class."""
78
78
 
79
79
  def __init__(self, username, password, time_zone=DEFAULT_TZ,
80
80
  debug=False, redact=True):
81
- """Initialize VeSync class with username, password and time zone."""
81
+ """Initialize VeSync Manager.
82
+
83
+ This class is used as the manager for all VeSync objects, all methods and
84
+ API calls are performed from this class. Time zone, debug and redact are
85
+ optional. Time zone must be a string of an IANA time zone format. Once
86
+ class is instantiated, call `manager.login()` to log in to VeSync servers,
87
+ which returns `True` if successful. Once logged in, call `manager.update()`
88
+ to retrieve devices and update device details.
89
+
90
+ Parameters:
91
+ -----------
92
+ username : str
93
+ VeSync account username (usually email address)
94
+ password : str
95
+ VeSync account password
96
+ time_zone : str, optional
97
+ Time zone for device from IANA database, by default DEFAULT_TZ
98
+ debug : bool, optional
99
+ Enable debug logging, by default False
100
+ redact : bool, optional
101
+ Redact sensitive information in logs, by default True
102
+
103
+ Attributes
104
+ ----------
105
+ fans : list
106
+ List of VeSyncFan objects for humidifiers and air purifiers
107
+ outlets : list
108
+ List of VeSyncOutlet objects for smart plugs
109
+ switches : list
110
+ List of VeSyncSwitch objects for wall switches
111
+ bulbs : list
112
+ List of VeSyncBulb objects for smart bulbs
113
+ kitchen : list
114
+ List of VeSyncKitchen objects for smart kitchen appliances
115
+ """
82
116
  self.debug = debug
83
117
  if debug: # pragma: no cover
84
118
  logger.setLevel(logging.DEBUG)
@@ -308,7 +342,15 @@ class VeSync: # pylint: disable=function-redefined
308
342
  return proc_return
309
343
 
310
344
  def login(self) -> bool:
311
- """Return True if log in request succeeds."""
345
+ """Log into VeSync server.
346
+
347
+ Username and password are provided when class is instantiated.
348
+
349
+ Returns
350
+ -------
351
+ bool
352
+ True if login successful, False if not
353
+ """
312
354
  user_check = isinstance(self.username, str) and len(self.username) > 0
313
355
  pass_check = isinstance(self.password, str) and len(self.password) > 0
314
356
  if user_check is False:
@@ -346,7 +388,16 @@ class VeSync: # pylint: disable=function-redefined
346
388
  return False
347
389
 
348
390
  def update(self) -> None:
349
- """Fetch updated information about devices."""
391
+ """Fetch updated information about devices.
392
+
393
+ Pulls devices list from VeSync and instantiates any new devices. Devices
394
+ are stored in the instance attributes `outlets`, `switches`, `fans`, and
395
+ `bulbs`. The `_device_list` attribute is a dictionary of these attributes.
396
+
397
+ Returns
398
+ -------
399
+ None
400
+ """
350
401
  if self.device_time_check():
351
402
 
352
403
  if not self.enabled: