Skip to content

Commit 308a988

Browse files
authored
Merge pull request #183 from webdjoe/feature-requests
Feature requests
2 parents bb9060b + 1b4c6f0 commit 308a988

18 files changed

+787
-152
lines changed

README.md

Lines changed: 87 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pyvesync is a library to manage VeSync compatible [smart home devices](#supporte
4444
- [Cosori 3.7 and 5.8 Quart Air Fryer](#cosori-37-and-58-quart-air-fryer)
4545
- [Air Fryer Properties](#air-fryer-properties)
4646
- [Air Fryer Methods](#air-fryer-methods)
47+
- [Timer DataClass](#timer-dataclass)
4748
- [JSON Output API](#json-output-api)
4849
- [JSON Output for All Devices](#json-output-for-all-devices)
4950
- [JSON Output for Outlets](#json-output-for-outlets)
@@ -52,7 +53,6 @@ pyvesync is a library to manage VeSync compatible [smart home devices](#supporte
5253
- [JSON Output for Tunable Bulb](#json-output-for-tunable-bulb)
5354
- [JSON Output for Multicolor Bulb](#json-output-for-multicolor-bulb)
5455
- [JSON Output for Air Purifier](#json-output-for-air-purifier)
55-
- [JSON Output for 300S Humidifier](#json-output-for-300s-humidifier)
5656
- [JSON Output for Core200S Purifier](#json-output-for-core200s-purifier)
5757
- [JSON Output for 400S Purifier](#json-output-for-400s-purifier)
5858
- [JSON Output for 600S Purifier](#json-output-for-600s-purifier)
@@ -61,7 +61,6 @@ pyvesync is a library to manage VeSync compatible [smart home devices](#supporte
6161
- [Redact mode](#redact-mode)
6262
- [Feature Requests](#feature-requests)
6363

64-
6564
## Installation
6665

6766
Install the latest version from pip:
@@ -81,6 +80,7 @@ pip install pyvesync
8180
5. Two Plug Outdoor Outlet (ESO15-TB) (Each plug is a separate `VeSyncOutlet` object, energy readings are for both plugs combined)
8281

8382
### Wall Switches
83+
8484
1. Etekcity Smart WiFi Light Switch (model ESWL01)
8585
2. Etekcity Wifi Dimmer Switch (ESD16)
8686

@@ -98,16 +98,19 @@ pip install pyvesync
9898
2. Cool to Soft White Tunable Dimmable Bulb (ESL100CW)
9999

100100
### Valceno Bulbs
101+
101102
1. Multicolor Bulb (XYD0001)
102103

103104
### Levoit Humidifiers
105+
104106
1. Dual 200S
105107
2. Classic 300S
106108
3. LUH-D301S-WEU Dual (200S)
107109
4. LV600S
108110
5. OasisMist LUS-O415S-WUS
109111

110112
Cosori Air Fryer
113+
111114
1. Cosori 3.7 and 5.8 Quart Air Fryer
112115

113116
## Usage
@@ -139,6 +142,7 @@ my_bulb.set_brightness(75)
139142
# get its details in JSON and print
140143
print(my_bulb.displayJSON())
141144
```
145+
142146
Devices are stored in the respective lists in the instantiated `VeSync` class:
143147

144148
```python
@@ -163,14 +167,17 @@ for switch in manager.switches:
163167
if switch.device_name == switch_name:
164168
switch.turn_on()
165169
```
170+
166171
## Configuration
167172

168173
### Time Zones
174+
169175
The `time_zone` argument is optional but the specified time zone must match time zone in the tz database (IANNA Time Zone Database), see this link for reference:
170176
[tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
171177
The time zone determines how the energy history is generated for the smart outlets, i.e. for the week starts at 12:01AM Sunday morning at the specified time zone. If no time zone or an invalid time zone is entered the default is America/New_York
172178

173179
### Outlet energy data update interval
180+
174181
If outlets are going to be continuously polled, a custom energy update interval can be set - The default is 6 hours (21600 seconds)
175182

176183
```python
@@ -182,7 +189,9 @@ manager.energy_update_interval = 360 # time in seconds
182189
### Get electricity metrics of outlets
183190

184191
Bypass the interval check to trigger outlet energy update.
192+
185193
```python
194+
186195
for s in manager.outlets:
187196
s.update_energy(check_bypass=False) # Get energy history for each device
188197
```
@@ -311,6 +320,7 @@ NOTE: LV-PUR131S outputs `air_quality` as a string, such as `Excellent`
311320
`VeSyncFan.change_fan_speed(speed=None)` - Change fan speed. Call without speed to toggle to next speed
312321

313322
Compatible levels for each model:
323+
314324
- Core 200S [1, 2, 3]
315325
- Core 300S/400S [1, 2, 3, 4]
316326
- PUR131S [1, 2, 3]
@@ -333,6 +343,11 @@ Compatible levels for each model:
333343

334344
`VeSyncFan.set_night_light('on'|'dim'|'off')` - Set night light brightness
335345

346+
`VeSyncFan.get_timer()` - Get any running timers, stores Timer DataClass in `VeSyncFan.timer`
347+
348+
`VeSyncFan.set_timer(timer_duration=3000)` - Set a timer for the device, only turns device off. Timer DataClass stored in `VeSyncFan.timer`
349+
350+
`VeSyncFan.clear_timer()` - Cancel any running timer
336351

337352
### Lights API Methods & Properties
338353

@@ -356,9 +371,9 @@ Compatible levels for each model:
356371

357372
*Compatible with ESL100MC & Valceno Bulbs*
358373
**Properties**
359-
`VeSyncBulb.color` - Returns a dataclass with HSV and RGB attributes that are named tuples
374+
`VeSyncBulb.color` - Returns a Dataclass with HSV and RGB attributes that are named tuples
360375

361-
```
376+
```python
362377
VeSyncBulb.color.rbg = namedtuple('RGB', ['red', 'green', 'blue'])
363378
VeSyncBulb.color.hsv = namedtuple('HSV', ['hue', 'saturation', 'value'])
364379
```
@@ -549,6 +564,7 @@ They can be set through the `VeSyncAirFryer158.fryer_status` dataclass but shoul
549564
`VeSyncAirFryer158.preheat_last_time` - The last minutes remaining returned from API for preheat mode
550565

551566
`VeSyncAirFryer158.cook_status` - Status of air fryer. This can be the following states:
567+
552568
1. `standby` - Air fryer is off and no cook or preheat is in progress
553569
2. `cooking` - Air fryer is actively cooking
554570
3. `cookStop` - Cooking is paused and can be resumed
@@ -565,7 +581,7 @@ They can be set through the `VeSyncAirFryer158.fryer_status` dataclass but shoul
565581

566582
`VeSyncAirFryer158.remaining_time` - Returns minutes remaining based on timestamp of last API return when air fryer is running. Returns `None` if not running
567583

568-
`VeSyncAirFryer158.fryer_status` - Dataclass that contains the status of the air fryer. The attributes of this dataclass are directly accessible from the `VeSyncAirFryer158` properties and **should not be directly set.**
584+
`VeSyncAirFryer158.fryer_status` - Dataclass that contains the status of the air fryer. The attributes of this Dataclass are directly accessible from the `VeSyncAirFryer158` properties and **should not be directly set.**
569585

570586
##### Air Fryer Methods
571587

@@ -583,6 +599,43 @@ They can be set through the `VeSyncAirFryer158.fryer_status` dataclass but shoul
583599

584600
`VeSyncAirFryer158.end()` - End cooking or preheating and return air fryer to `standby` state
585601

602+
603+
### Timer DataClass
604+
605+
This is the a Timer DataClass that is used in the `get_timer()` or `set_timer()` methods *only implemented for Levoit Core 200S and 300S Air Purifier*, will eventually integrate with remaining devices. This object is created when the device timer methods are called. **The `pause()`, `resume()` and `stop()` methods for this DataClass only impact the timer locally and do not update the API.**
606+
607+
```python
608+
from pyvesync.helpers import Timer
609+
610+
timer = Timer(timer_duration=60, id=1)
611+
612+
# Get time remaining in seconds
613+
# Calculates based on timer elapsed each time property is called
614+
timer.remaining_time
615+
616+
# Get status
617+
timer.status
618+
619+
# Get action
620+
timer.action
621+
622+
# Set status - active or done
623+
timer.status = 'active'
624+
625+
# set time remaining in seconds, does not edit status
626+
timer.remaining_time = 120
627+
628+
# Pause timer - Does not update API - only pauses locally
629+
timer.pause()
630+
631+
# End timer -Does not update API - only ends locally
632+
timer.end()
633+
634+
# Resume timer - Does not update API - only Resumes locally
635+
timer.start()
636+
```
637+
638+
586639
### JSON Output API
587640

588641
The `device.displayJSON()` method outputs properties and status of the device
@@ -682,9 +735,9 @@ This output only applies to dimmable switch. The standard switch has the defaul
682735
"Filter Life": "99" # remaining filter life in percent
683736
}
684737
```
685-
#### JSON Output for 300S Humidifier
686738

687739
```python
740+
688741
{
689742
"Mode": "manual", # auto, manual, sleep
690743
"Humidity": 20, # percent
@@ -703,21 +756,21 @@ This output only applies to dimmable switch. The standard switch has the defaul
703756

704757
```python
705758
{
706-
"Device Name": "MyPurifier",
707-
"Model": "Core200S",
708-
"Subdevice No": "None",
709-
"Status": "on",
710-
"Online": "online",
711-
"Type": "wifi-air",
712-
"CID": "asd_sdfKIHG7IJHGwJGJ7GJ_ag5h3G55",
713-
"Mode": "manual",
714-
"Filter Life": "99",
715-
"Fan Level": "1",
716-
"Display": true,
717-
"Child Lock": false,
718-
"Night Light": "off",
719-
"Display Config": true,
720-
"Display_Forever Config": false
759+
"Device Name": "MyPurifier",
760+
"Model": "Core200S",
761+
"Subdevice No": "None",
762+
"Status": "on",
763+
"Online": "online",
764+
"Type": "wifi-air",
765+
"CID": "asd_sdfKIHG7IJHGwJGJ7GJ_ag5h3G55",
766+
"Mode": "manual",
767+
"Filter Life": "99",
768+
"Fan Level": "1",
769+
"Display": true,
770+
"Child Lock": false,
771+
"Night Light": "off",
772+
"Display Config": true,
773+
"Display_Forever Config": false
721774
}
722775
```
723776

@@ -744,6 +797,7 @@ This output only applies to dimmable switch. The standard switch has the defaul
744797
"Display_Forever Config": false
745798
}
746799
```
800+
747801
#### JSON Output for 600S Purifier
748802

749803
```python
@@ -813,7 +867,7 @@ manager.update()
813867

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

816-
SSL pinning makes capturing packets with Android ~~not feasible anymore~~ harder than before. A system-wide proxy (https://play.google.com/store/apps/details?id=org.proxydroid&hl=en) can be used if ssl pinning is disabled (https://github.com/ViRb3/TrustMeAlready).
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).
817871

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

@@ -824,19 +878,22 @@ After you capture the packets, please redact the `accountid` and `token`. If you
824878
For example:
825879

826880
Before:
827-
```
881+
882+
```json
828883
{
829-
'tk': 'abc123abc123==3rf',
830-
'accountId': '123456789',
831-
'cid': 'abcdef12-3gh-ij'
884+
"tk": "abc123abc123==3rf",
885+
"accountId": "123456789",
886+
"cid": "abcdef12-3gh-ij"
832887
}
833888
```
889+
834890
After:
835-
```
891+
892+
```json
836893
{
837-
'tk': 'AAA111AAA111==1AA',
838-
'accountId': '111111111',
839-
'cid': 'AAAAAA11-1AA-AA'
894+
"tk": "AAA111AAA111==1AA",
895+
"accountId": "111111111",
896+
"cid": "AAAAAA11-1AA-AA"
840897
}
841898
```
842899

setup.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010

1111
setup(
1212
name='pyvesync',
13-
version='2.1.6',
13+
version='2.1.7',
1414
description='pyvesync is a library to manage Etekcity\
15-
Devices and Levoit Air Purifier',
15+
Devices, Cosori Air Fryers and Levoit Air \
16+
Purifiers run on the VeSync app.',
1617
long_description=long_description,
1718
long_description_content_type='text/markdown',
1819
url='https://github.com/webdjoe/pyvesync',

0 commit comments

Comments
 (0)