Skip to content

Commit

Permalink
Merge pull request #188 from webdjoe/Levoit200S
Browse files Browse the repository at this point in the history
Add Levoit Vital 100S/200S
  • Loading branch information
webdjoe committed Jul 17, 2023
2 parents 308a988 + 3263f07 commit c699120
Show file tree
Hide file tree
Showing 18 changed files with 1,131 additions and 73 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ test.py
tools/__init__.py
tools/vesyncdevice.py
pyvesync.und
.venv
68 changes: 56 additions & 12 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@

1. Git clone the repository

```
git clone https://github.com/webdjoe/pyvesync
```bash
git clone https://github.com/webdjoe/pyvesync && cd pyvesync
```

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

```
```bash
# Check Python version is 3.8 or higher
python3 --version # or python --version or python3.8 --version
# Create a new venv
python3 -m venv pyvesync-venv
# Activate the venv
source pyvesync-venv/bin/activate
```

3. Install pyvesync in the venv
# or ....
pyvesync-venv\Scripts\activate.ps1 # on powershell
pyvesync-venv\Scripts\activate.bat # on command prompt

# Install development tools
pip install -e .[dev]
```
pip3 install -e pyvesync/
```

3. Make changes and test in virtual environment

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

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

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

```
pip install tox
cd pyvesync
```bash
# Run all tests and linters
tox

# Run tests, linters separately
tox -e testenv # pytest
tox -e pylint # linting
tox -e lint # flake8 & pydocstrings
tox -e mypy # type checkings
```

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.


# Ensure new devices are Integrated in Tests

If you integrate a new device, please read the [testing README](tests/README.md) to ensure that your device is tested.
If you integrate a new device, please read the [testing README](tests/README.md) to ensure that your device is tested.

## Testing with pytest and Writing API to YAML

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.

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.

To run a tests for development on existing devices or if you are not ready to write the api calls yet:

```bash
# Through pytest
pytest

# or through tox
tox -e testenv # you can also use the environments lint, pylint, mypy
```

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.

```bash
pytest --write_api

tox -e testenv -- --write_api
```

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.

```bash
pytest --write_api --overwrite

tox -e testenv -- --write_api --overwrite
```
113 changes: 101 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ pyvesync is a library to manage VeSync compatible [smart home devices](#supporte
- [Standard Air Purifier Properties \& Methods](#standard-air-purifier-properties--methods)
- [Air Purifier Properties](#air-purifier-properties)
- [Air Purifier Methods](#air-purifier-methods)
- [Levoit Purifier Core200S/300S/400S Properties](#levoit-purifier-core200s300s400s-properties)
- [Levoit Purifier Core200S/300S/400S Methods](#levoit-purifier-core200s300s400s-methods)
- [Levoit Purifier Core200S/300S/400S and Vital 100S/200S Properties](#levoit-purifier-core200s300s400s-and-vital-100s200s-properties)
- [Levoit Purifier Core200S/300S/400S and Vital 100S/200S Methods](#levoit-purifier-core200s300s400s-and-vital-100s200s-methods)
- [Levoit Vital 100S/200S Properties and Methods](#levoit-vital-100s200s-properties-and-methods)
- [Lights API Methods \& Properties](#lights-api-methods--properties)
- [Brightness Light Bulb Method and Properties](#brightness-light-bulb-method-and-properties)
- [Light Bulb Color Temperature Methods and Properties](#light-bulb-color-temperature-methods-and-properties)
Expand Down Expand Up @@ -91,6 +92,8 @@ pip install pyvesync
3. Core 300S
4. Core 400S
5. Core 600S
6. Vital 100S
7. Vital 200S

### Etekcity Bulbs

Expand Down Expand Up @@ -324,14 +327,15 @@ Compatible levels for each model:
- Core 200S [1, 2, 3]
- Core 300S/400S [1, 2, 3, 4]
- PUR131S [1, 2, 3]
- Vital 100S/200S [1, 2, 3, 4]

#### Levoit Purifier Core200S/300S/400S Properties
#### Levoit Purifier Core200S/300S/400S and Vital 100S/200S Properties

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

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

#### Levoit Purifier Core200S/300S/400S Methods
#### Levoit Purifier Core200S/300S/400S and Vital 100S/200S Methods

`VeSyncFan.child_lock_on()` Enable child lock

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

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

#### Levoit Vital 100S/200S Properties and Methods

The Levoit Vital 100S/200S has additional features not available on other models.

`VeSyncFan.set_fan_speed` - The manual fan speed that is currently set (remains constant when in auto/sleep mode)

`VeSyncFan.fan_level` - Returns the fan level purifier is currently operating on whether in auto/manual/sleep mode

`VeSyncFan.light_detection` - Returns the state of the light detection mode (True=On/False=off)

`VeSyncFan.light_detection_state` - Returns whether light is detected (True/False)

`VeSyncFan.pet_mode()` - Set pet mode **NOTE: Only available on Vital 200S**

`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

`VeSyncFan.set_light_detection_on()` - Turn on light detection mode

`VeSyncFan.set_light_detection_off()` - Turn off light detection mode

### Lights API Methods & Properties

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

## Feature Requests

~~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/).~~
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.

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).
```bash
mkdir python_test && cd python_test

# Check Python version is 3.8 or higher
python3 --version # or python --version or python3.8 --version
# Create a new venv
python3 -m venv pyvesync-venv
# Activate the venv on linux
source pyvesync-venv/bin/activate
# or ....
pyvesync-venv\Scripts\activate.ps1 # on powershell
pyvesync-venv\Scripts\activate.bat # on command prompt

# Install branch to be tested into new virtual environment
pip install git+https://github.com/webdjoe/pyvesync@BRANCHNAME
```

Test functionality with a script

`test.py`

```python
import sys
import logging
import json
from pyvesync import VeSync

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

def test_device():
# Instantiate VeSync class and login
manager = VeSync(user, password, debug=True)
if manager.login() == False
logger("Unable to login")
return

# Test specific device
# If this were a humidifier and there is only one humidifier/purifier
# You can access it with the device index
fan = manager.fans[0]
# or loop through the fan devices and test for device with "My Device" name
# Use lower() to avoid capitalization issues
my_device_name = "My Device"
fan = None
for dev in manager.fans:
if dev.name.lower() == my_device_name.lower()
fan = dev
if fan == None:
logger.debug("Device not found")
logger.debug("Devices found - \n" + json.dumps(manager._dev_list))
return

# Test all device methods and functionality
# Be aware some devices lose internet connectivity if turned off
fan.turn_on()
fan.turn_off()
fan.sleep_mode()

# Make script runnable from command line
if __name__ == "__main__":
logger.debug("Testing device")
test_device()
...

```

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.
## Device Requests

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.
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.

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.
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.

For example:

Expand All @@ -897,8 +986,8 @@ After:
}
```

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

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

This project is licensed under [MIT](LICENSE).
5 changes: 4 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

setup(
name='pyvesync',
version='2.1.7',
version='2.1.8',
description='pyvesync is a library to manage Etekcity\
Devices, Cosori Air Fryers and Levoit Air \
Purifiers run on the VeSync app.',
Expand All @@ -32,5 +32,8 @@
package_dir={'': 'src'},
zip_safe=False,
install_requires=['requests>=2.20.0'],
extras_require={
'dev': ['pytest', 'pytest-cov', 'yaml', 'tox']
},
python_requires='>=3.8',
)
Loading

0 comments on commit c699120

Please sign in to comment.