Skip to content

Commit c699120

Browse files
authored
Merge pull request #188 from webdjoe/Levoit200S
Add Levoit Vital 100S/200S
2 parents 308a988 + 3263f07 commit c699120

18 files changed

+1131
-73
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ test.py
2929
tools/__init__.py
3030
tools/vesyncdevice.py
3131
pyvesync.und
32+
.venv

CONTRIBUTING.md

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,28 @@
22

33
1. Git clone the repository
44

5-
```
6-
git clone https://github.com/webdjoe/pyvesync
5+
```bash
6+
git clone https://github.com/webdjoe/pyvesync && cd pyvesync
77
```
88

99
2. Create and activate a separate python virtual environment for pyvesync
1010

11-
```
11+
```bash
12+
# Check Python version is 3.8 or higher
13+
python3 --version # or python --version or python3.8 --version
1214
# Create a new venv
1315
python3 -m venv pyvesync-venv
1416
# Activate the venv
1517
source pyvesync-venv/bin/activate
16-
```
17-
18-
3. Install pyvesync in the venv
18+
# or ....
19+
pyvesync-venv\Scripts\activate.ps1 # on powershell
20+
pyvesync-venv\Scripts\activate.bat # on command prompt
1921

22+
# Install development tools
23+
pip install -e .[dev]
2024
```
21-
pip3 install -e pyvesync/
22-
```
25+
26+
3. Make changes and test in virtual environment
2327

2428
If the above steps were executed successfully, you should now have:
2529

@@ -33,12 +37,52 @@ run `deactivate`.
3337

3438
Install tox, navigate to the pyvesync repository which contains the tox.ini file, and run tox as follows:
3539

36-
```
37-
pip install tox
38-
cd pyvesync
40+
```bash
41+
# Run all tests and linters
3942
tox
43+
44+
# Run tests, linters separately
45+
tox -e testenv # pytest
46+
tox -e pylint # linting
47+
tox -e lint # flake8 & pydocstrings
48+
tox -e mypy # type checkings
4049
```
4150

51+
Tests are run based off of the API calls recorded in the [api](src/tests/api) directory. Please read the [Test Readme](src/tests/README.md) for further details on the structure of the tests.
52+
53+
4254
# Ensure new devices are Integrated in Tests
4355

44-
If you integrate a new device, please read the [testing README](tests/README.md) to ensure that your device is tested.
56+
If you integrate a new device, please read the [testing README](tests/README.md) to ensure that your device is tested.
57+
58+
## Testing with pytest and Writing API to YAML
59+
60+
Part of the pytest test are against a library of API calls written to YAML files in the `tests` directory. If you are developing a new device, be aware that these tests will fail at first until you are ready to write the final API.
61+
62+
There are two pytest command line arguments built into the tests to specify when to write the api data to YAML files or when to overwrite the existing API calls in the YAML files.
63+
64+
To run a tests for development on existing devices or if you are not ready to write the api calls yet:
65+
66+
```bash
67+
# Through pytest
68+
pytest
69+
70+
# or through tox
71+
tox -e testenv # you can also use the environments lint, pylint, mypy
72+
```
73+
74+
If developing a new device and it is completed and thoroughly tested, pass the `--write_api` to pytest. Be sure to include the `--` before the argument in the tox command.
75+
76+
```bash
77+
pytest --write_api
78+
79+
tox -e testenv -- --write_api
80+
```
81+
82+
If fixing an existing device where the API call was incorrect or the api has changed, pass `--write_api` and `overwrite` to pytest. Both arguments need to be provided to overwrite existing API data already in the YAML files.
83+
84+
```bash
85+
pytest --write_api --overwrite
86+
87+
tox -e testenv -- --write_api --overwrite
88+
```

README.md

Lines changed: 101 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ pyvesync is a library to manage VeSync compatible [smart home devices](#supporte
2929
- [Standard Air Purifier Properties \& Methods](#standard-air-purifier-properties--methods)
3030
- [Air Purifier Properties](#air-purifier-properties)
3131
- [Air Purifier Methods](#air-purifier-methods)
32-
- [Levoit Purifier Core200S/300S/400S Properties](#levoit-purifier-core200s300s400s-properties)
33-
- [Levoit Purifier Core200S/300S/400S Methods](#levoit-purifier-core200s300s400s-methods)
32+
- [Levoit Purifier Core200S/300S/400S and Vital 100S/200S Properties](#levoit-purifier-core200s300s400s-and-vital-100s200s-properties)
33+
- [Levoit Purifier Core200S/300S/400S and Vital 100S/200S Methods](#levoit-purifier-core200s300s400s-and-vital-100s200s-methods)
34+
- [Levoit Vital 100S/200S Properties and Methods](#levoit-vital-100s200s-properties-and-methods)
3435
- [Lights API Methods \& Properties](#lights-api-methods--properties)
3536
- [Brightness Light Bulb Method and Properties](#brightness-light-bulb-method-and-properties)
3637
- [Light Bulb Color Temperature Methods and Properties](#light-bulb-color-temperature-methods-and-properties)
@@ -91,6 +92,8 @@ pip install pyvesync
9192
3. Core 300S
9293
4. Core 400S
9394
5. Core 600S
95+
6. Vital 100S
96+
7. Vital 200S
9497

9598
### Etekcity Bulbs
9699

@@ -324,14 +327,15 @@ Compatible levels for each model:
324327
- Core 200S [1, 2, 3]
325328
- Core 300S/400S [1, 2, 3, 4]
326329
- PUR131S [1, 2, 3]
330+
- Vital 100S/200S [1, 2, 3, 4]
327331

328-
#### Levoit Purifier Core200S/300S/400S Properties
332+
#### Levoit Purifier Core200S/300S/400S and Vital 100S/200S Properties
329333

330334
`VeSyncFan.child_lock` - Return the state of the child lock (True=On/False=off)
331335

332-
`VeSyncAir.night_light` - Return the state of the night light (on/dim/off)
336+
`VeSyncAir.night_light` - Return the state of the night light (on/dim/off) **Not available on Vital 100S/200S**
333337

334-
#### Levoit Purifier Core200S/300S/400S Methods
338+
#### Levoit Purifier Core200S/300S/400S and Vital 100S/200S Methods
335339

336340
`VeSyncFan.child_lock_on()` Enable child lock
337341

@@ -349,6 +353,26 @@ Compatible levels for each model:
349353

350354
`VeSyncFan.clear_timer()` - Cancel any running timer
351355

356+
#### Levoit Vital 100S/200S Properties and Methods
357+
358+
The Levoit Vital 100S/200S has additional features not available on other models.
359+
360+
`VeSyncFan.set_fan_speed` - The manual fan speed that is currently set (remains constant when in auto/sleep mode)
361+
362+
`VeSyncFan.fan_level` - Returns the fan level purifier is currently operating on whether in auto/manual/sleep mode
363+
364+
`VeSyncFan.light_detection` - Returns the state of the light detection mode (True=On/False=off)
365+
366+
`VeSyncFan.light_detection_state` - Returns whether light is detected (True/False)
367+
368+
`VeSyncFan.pet_mode()` - Set pet mode **NOTE: Only available on Vital 200S**
369+
370+
`VeSyncFan.set_auto_preference(preference='default', room_size=600)` - Set the auto mode preference. Preference can be 'default', 'efficient' or quiet. Room size defaults to 600
371+
372+
`VeSyncFan.set_light_detection_on()` - Turn on light detection mode
373+
374+
`VeSyncFan.set_light_detection_off()` - Turn off light detection mode
375+
352376
### Lights API Methods & Properties
353377

354378
#### Brightness Light Bulb Method and Properties
@@ -865,15 +889,80 @@ manager.update()
865889

866890
## Feature Requests
867891

868-
~~If you would like new devices to be added, you will need to capture the packets from the app. The easiest way to do this is by using [Packet Capture for Android](https://play.google.com/store/apps/details?id=app.greyshirts.sslcapture&hl=en_US&gl=US). This works without rooting the device. If you do not have an android or are concerned with adding an app that uses a custom certificate to read the traffic, you can use an Android emulator such as [Nox](https://www.bignox.com/).~~
892+
Before filing an issue to request a new feature or device, please ensure that you will take the time to test the feature throuroughly. New features cannot be simply tested on Home Assistant. A separate integration must be created which is not part of this library. In order to test a new feature, clone the branch and install into a new virtual environment.
869893

870-
SSL pinning makes capturing packets with Android ~~not feasible anymore~~ harder than before. A system-wide proxy [ProxyDroid](https://play.google.com/store/apps/details?id=org.proxydroid&hl=en) can be used if ssl pinning is disabled [TrustMeAlready](https://github.com/ViRb3/TrustMeAlready).
894+
```bash
895+
mkdir python_test && cd python_test
896+
897+
# Check Python version is 3.8 or higher
898+
python3 --version # or python --version or python3.8 --version
899+
# Create a new venv
900+
python3 -m venv pyvesync-venv
901+
# Activate the venv on linux
902+
source pyvesync-venv/bin/activate
903+
# or ....
904+
pyvesync-venv\Scripts\activate.ps1 # on powershell
905+
pyvesync-venv\Scripts\activate.bat # on command prompt
906+
907+
# Install branch to be tested into new virtual environment
908+
pip install git+https://github.com/webdjoe/pyvesync@BRANCHNAME
909+
```
910+
911+
Test functionality with a script
912+
913+
`test.py`
914+
915+
```python
916+
import sys
917+
import logging
918+
import json
919+
from pyvesync import VeSync
920+
921+
logger = logging.getLogger(__name__)
922+
logger.setLevel(logging.DEBUG)
923+
924+
def test_device():
925+
# Instantiate VeSync class and login
926+
manager = VeSync(user, password, debug=True)
927+
if manager.login() == False
928+
logger("Unable to login")
929+
return
930+
931+
# Test specific device
932+
# If this were a humidifier and there is only one humidifier/purifier
933+
# You can access it with the device index
934+
fan = manager.fans[0]
935+
# or loop through the fan devices and test for device with "My Device" name
936+
# Use lower() to avoid capitalization issues
937+
my_device_name = "My Device"
938+
fan = None
939+
for dev in manager.fans:
940+
if dev.name.lower() == my_device_name.lower()
941+
fan = dev
942+
if fan == None:
943+
logger.debug("Device not found")
944+
logger.debug("Devices found - \n" + json.dumps(manager._dev_list))
945+
return
946+
947+
# Test all device methods and functionality
948+
# Be aware some devices lose internet connectivity if turned off
949+
fan.turn_on()
950+
fan.turn_off()
951+
fan.sleep_mode()
952+
953+
# Make script runnable from command line
954+
if __name__ == "__main__":
955+
logger.debug("Testing device")
956+
test_device()
957+
...
958+
959+
```
871960

872-
Charles Proxy is a proxy that allows you to perform MITM SSL captures on an iOS device. This is the only way to capture packets that I am aware of that is currently possible.
961+
## Device Requests
873962

874-
When capturing packets make sure all packets are captured from the device list, along with all functions that the app contains. The captured packets are stored in text files, please do not capture with pcap format.
963+
SSL pinning makes capturing packets much harder. In order to be able to capture packets, SSL pinning needs to be disabled before running an SSL proxy. Use an Android emulator such as Android Studio, which is available for Windows and Linux for free. Download the APK from APKPure or a similiar site and use [Objection](https://github.com/sensepost/objection) or [Frida](https://frida.re/docs/gadget/). Followed by capturing the packets with Charles Proxy or another SSL proxy application.
875964

876-
After you capture the packets, please redact the `accountid` and `token`. If you feel you must redact other keys, please do not delete them entirely. Replace letters with "A" and numbers with "1", leave all punctuation intact and maintain length.
965+
Be sure to capture all packets from the device list and each of the possible device menus and actions. Please redact the `accountid` and `token` from the captured packets. If you feel you must redact other keys, please do not delete them entirely. Replace letters with "A" and numbers with "1", leave all punctuation intact and maintain length.
877966

878967
For example:
879968

@@ -897,8 +986,8 @@ After:
897986
}
898987
```
899988

900-
All [contributions](CONTRIBUTING.md) are welcome, please run `tox` before submitting a PR to ensure code is valid.
989+
# Contributing
901990

902-
Ensure new devices are integrated in tests, please review the [testing](tests/README.md) documentation for more information.
991+
All [contributions](CONTRIBUTING.md) are welcome.
903992

904993
This project is licensed under [MIT](LICENSE).

setup.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
setup(
1212
name='pyvesync',
13-
version='2.1.7',
13+
version='2.1.8',
1414
description='pyvesync is a library to manage Etekcity\
1515
Devices, Cosori Air Fryers and Levoit Air \
1616
Purifiers run on the VeSync app.',
@@ -32,5 +32,8 @@
3232
package_dir={'': 'src'},
3333
zip_safe=False,
3434
install_requires=['requests>=2.20.0'],
35+
extras_require={
36+
'dev': ['pytest', 'pytest-cov', 'yaml', 'tox']
37+
},
3538
python_requires='>=3.8',
3639
)

0 commit comments

Comments
 (0)