pyvesync is a library to manage VeSync compatible smart home devices
- Installation
- Supported Devices
- Usage
- Configuration
- Example Usage
- API Details
- Manager API
- Standard Device API
- Outlet API Methods & Properties
- Standard Air Purifier Properties & Methods
- Lights API Methods & Properties
- Levoit Humidifier Methods and Properties
- Cosori Devices
- JSON Output API
- JSON Output for All Devices
- JSON Output for Outlets
- JSON Output for Dimmable Switch
- JSON Output for Dimmable Bulb
- JSON Output for Tunable Bulb
- JSON Output for Multicolor Bulb
- JSON Output for Air Purifier
- JSON Output for 300S Humidifier
- JSON Output for Core200S Purifier
- JSON Output for 400S Purifier
- JSON Output for 600S Purifier
- Notes
- Debug mode
- Feature Requests
Install the latest version from pip:
pip install pyvesync
- Voltson Smart WiFi Outlet- Round (7A model ESW01-USA)
- Voltson Smart WiFi Outlet - Round (10A model ESW01-EU)
- Voltson Smart Wifi Outlet - Round (10A model ESW03-USA)
- Voltson Smart WiFi Outlet - Rectangle (15A model ESW15-USA)
- Two Plug Outdoor Outlet (ESO15-TB) (Each plug is a separate
VeSyncOutlet
object, energy readings are for both plugs combined)
- Etekcity Smart WiFi Light Switch (model ESWL01)
- Etekcity Wifi Dimmer Switch (ESD16)
- LV-PUR131S
- Core 200S
- Core 300S
- Core 400S
- Core 600S
- Soft White Dimmable Smart Bulb (ESL100)
- Cool to Soft White Tunable Dimmable Bulb (ESL100CW)
- Multicolor Bulb (XYD0001)
- Dual 200S
- Classic 300S
- LUH-D301S-WEU Dual (200S)
- LV600S
- OasisMist LUS-O415S-WUS
Cosori Air Fryer
- Cosori 3.7 and 5.8 Quart Air Fryer
To start with the module:
from pyvesync import VeSync
manager = VeSync("EMAIL", "PASSWORD", "TIME_ZONE", debug=False)
manager.login()
# Get/Update Devices from server - populate device lists
manager.update()
my_switch = manager.outlets[0]
# Turn on the first switch
my_switch.turn_on()
# Turn off the first switch
my_switch.turn_off()
# Get energy usage data for outlets
manager.update_energy()
# Set bulb brightness to 75% of first bulb in the list
my_bulb = manager.bulbs[0]
my_bulb.set_brightness(75)
# get its details in JSON and print
print(my_bulb.displayJSON())
Devices are stored in the respective lists in the instantiated VeSync
class:
manager.login()
manager.update()
manager.outlets = [VeSyncOutletObjects]
manager.switches = [VeSyncSwitchObjects]
manager.fans = [VeSyncFanObjects]
manager.bulbs = [VeSyncBulbObjects]
# Get device (outlet, etc.) by device name
dev_name = "My Device"
for device in manager.outlets:
if device.device_name == dev_name:
my_device = device
device.display()
# Turn on switch by switch name
switch_name = "My Switch"
for switch in manager.switches:
if switch.device_name == switch_name:
switch.turn_on()
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:
tz database.
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
If outlets are going to be continuously polled, a custom energy update interval can be set - The default is 6 hours (21600 seconds)
manager.energy_update_interval = 360 # time in seconds
Bypass the interval check to trigger outlet energy update.
for s in manager.outlets:
s.update_energy(check_bypass=False) # Get energy history for each device
VeSync.get_devices()
- Returns a list of devices
VeSync.login()
- Uses class username and password to login to VeSync
VeSync.update()
- Fetch updated information about devices
VeSync.update_all_devices()
- Fetch details for all devices (run VeSyncDevice.update()
)
VeSync.update_energy(bypass_check=False)
- Get energy history for all outlets - Builds week, month and year nested energy dictionary. Set bypass_check=True
to disable the library from checking the update interval
These properties and methods are available for all devices.
VeSyncDevice.device_name
- Name given when registering device
VeSyncDevice.device_type
- Model of device, used to determine proper device class.
VeSyncDevice.connection_status
- Device online/offline
VeSyncDevice.config_module
- Special configuration identifier for device. Currently, not used in this API.
VeSyncDevice.sub_device_no
- Sub-device number for certain devices. Used for the outdoor outlet.
VeSyncDevice.device_status
- Device on/off
VeSyncDevice.is_on
- Returns boolean True/False if device is on.
VeSyncDevice.firmware_update
- Returns True is new firmware is available
VeSyncDevice.turn_on()
- Turn on the device
VeSyncDevice.turn_off()
- Turn off the device
VeSyncDevice.update()
- Fetch updated information about device
VeSyncDevice.active_time
- Return active time of the device in minutes
VeSyncDevice.get_config()
- Retrieve Configuration data such as firmware version for device and store in the VeSyncDevice.config
dictionary
VeSyncOutlet.update_energy(bypass_check=False)
- Get outlet energy history - Builds week, month and year nested energy dictionary. Set bypass_check=True
to disable the library from checking the update interval
VeSyncOutlet.energy_today
- Return current energy usage in kWh
VeSyncOutlet.power
- Return current power in watts of the device
VeSyncOutlet.voltage
- Return current voltage reading
VesyncOutlet.weekly_energy_total
- Return total energy reading for the past week in kWh, starts 12:01AM Sunday morning
VesyncOutlet.monthly_energy_total
- Return total energy reading for the past month in kWh
VesyncOutlet.yearly_energy_total
- Return total energy reading for the past year in kWh
The rectangular smart switch model supports some additional functionality on top of the regular api call
VeSyncOutlet.nightlight_status
- Get the status of the nightlight
VeSyncOutlet.nightlight_brightness
- Get the brightness of the nightlight
VeSyncOutlet.turn_on_nightlight()
- Turn on the nightlight
VeSyncOutlet.turn_off_nightlight()
- Turn off the nightlight
VeSyncFan.details
- Dictionary of device details
VeSyncFan.update()
VeSyncFan.details = {
'active_time': 30004, # minutes
'filter_life': 45, # percent of filter life remaining
'screen_status': 'on', # display on/off
'level': 3, # fan level
'air_quality': 2, # air quality level
}
NOTE: LV-PUR131S outputs air_quality
as a string, such as Excellent
VeSyncFan.features
- Unique features to air purifier model. Currently, the only feature is air_quality, which is not supported on Core 200S.
VeSyncFan.modes
- Modes of operation supported by model - [sleep, off, auto]
VeSyncFan.fan_level
- Return the level of the fan
VeSyncFan.filter_life
- Return the percentage of filter life remaining
VeSyncFan.air_quality
- Return air quality level as integer, 1 being the best - Not available on Core 200S
VeSyncFan.air_quality_value
- PM2.5 air quality reading
VeSyncFan.screen_status
- Get Status of screen on/off
VeSyncFan.auto_mode()
- Change mode to auto
VeSyncFan.manual_mode()
- Change fan mode to manual with fan level 1
VeSyncFan.sleep_mode()
- Change fan mode to sleep
VeSyncFan.change_fan_speed(speed=None)
- Change fan speed. Call without speed to toggle to next speed
Compatible levels for each model:
- Core 200S [1, 2, 3]
- Core 300S/400S [1, 2, 3, 4]
- PUR131S [1, 2, 3]
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)
VeSyncFan.child_lock_on()
Enable child lock
VeSyncFan.child_lock_off()
Disable child lock
VeSyncFan.turn_on_display()
Turn display on
VeSyncFan.turn_off_display()
Turn display off
VeSyncFan.set_night_light('on'|'dim'|'off')
- Set night light brightness
Compatible with all bulbs
VeSyncBulb.brightness
- Return brightness in percentage (1 - 100)
VeSyncBulb.set_brightness(brightness)
- Set bulb brightness values from 1 - 100
NOTE: only compatible with ESL100CW and Valceno Bulbs, NOT compatible with ESL100MC Bulbs
VeSyncBulb.color_temp_pct
- Return color temperature in percentage (0 - 100)
VeSyncBulb.color_temp_kelvin
- Return brightness in Kelvin
VeSyncBulb.set_color_temp(color_temp)
- Set white temperature in percentage (0 - 100)
Compatible with ESL100MC & Valceno Bulbs
Properties
VeSyncBulb.color
- Returns a dataclass with HSV and RGB attributes that are named tuples
VeSyncBulb.color.rbg = namedtuple('RGB', ['red', 'green', 'blue'])
VeSyncBulb.color.hsv = namedtuple('HSV', ['hue', 'saturation', 'value'])
VeSyncBulb.color_hsv
- Returns a named tuple with HSV values
VeSyncBulb.color_rgb
- Returns a named tuple with RGB values
VeSyncBulb.color_mode
- Return bulb color mode (string values: 'white', 'color', 'hsv')
VeSyncBulb.color_hue
- Return color hue (float values from 0.0 - 360.0)
VeSyncBulb.color_saturation
- Return color saturation (float values from 0.0 - 100.0)
VeSyncBulb.color_value
- Return color value (int values from 0 - 100)
The following properties are also still available for backwards compatibility
VeSyncBulb.color_value_hsv
- Return color value in HSV named tuple format (hue: float 0.0-360.0, saturation: float 0.0-100.0, value: float 0-100 )
VeSyncBulb.color_value_rgb
- Return color value in RGB named tuple format (red: float, green: float, blue: float 0-255.0)
Methods
VeSyncBulb.set_hsv(hue, saturation, value)
- Set bulb color in HSV format
- Arguments: hue (numeric) 0 - 360, saturation (numeric) 0-100, value (numeric) 0-100
- Returns bool
VeSyncBulb.set_rgb(red, green, blue)
- Set bulb color in RGB format
- Arguments: red (numeric) 0-255, green (numeric) 0-255, blue (numeric) 0-255
- Returns bool
VeSyncBulb.enable_white_mode()
- Turn bulb to white mode - returns bool
VeSyncBulb.set_color_temp(color_temp)
- Set bulb white temperature (int values from 0 - 100)
- Setting this will automatically force the bulb into White mode
VeSyncBulb.set_status(brightness, color_temp, color_saturation, color_hue, color_mode color_value)
- Set every property, in a single call
- All parameters are optional
NOTE: Due to the varying API between bulbs, avoid setting the color_mode
argument directly, instead set colors values with set_hsv
or set_rgb
to turn on color and use enable_white_mode()
to turn off color.
VeSyncSwitch.brightness
- Return brightness of switch in percentage (1 - 100)
VeSyncSwitch.indicator_light_status
- return status of indicator light on switch
VeSyncSwitch.rgb_light_status
- return status of rgb light on faceplate
VeSyncSwitch.rgb_light_value
- return dictionary of rgb light color (0 - 255)
VeSyncSwitch.set_brightness(brightness)
- Set brightness of switch (1 - 100)
VeSyncSwitch.indicator_light_on()
- Turn indicator light on
VeSyncSwitch.indicator_light_off()
- Turn indicator light off
VeSyncSwitch.rgb_color_on()
- Turn rgb light on
VeSyncSwitch.rgb_color_off()
- Turn rgb light off
VeSyncSwitch.rgb_color_set(red, green, blue)
- Set color of rgb light (0 - 255)
The details dictionary contains all device status details
VeSyncHumid.details = {
'humidity': 80, # percent humidity in room
'mist_virtual_level': 0, # Level of mist output 1 - 9
'mist_level': 0,
'mode': 'manual', # auto, manual, sleep
'water_lacks': False,
'humidity_high': False,
'water_tank_lifted': False,
'display': False,
'automatic_stop_reach_target': False,
'night_light_brightness': 0
}
The configuration dictionary shows current settings
VeSyncHumid.config = {
'auto_target_humidity': 80, # percent humidity in room
'display': True, # Display on/off
'automatic_stop': False
}
The LV600S has warm mist settings that show in the details dictionary in addition to the key/values above.
VeSyncLV600S.details = {
'warm_mist_enabled': True,
'warm_mist_level': 2
}
VeSyncHumid.humidity
- current humidity level in room
VeSyncHumid.mist_level
- current mist level
VeSyncHumid.mode
- Mode of operation - sleep, off, auto/humidity
VeSyncHumid.water_lacks
- Returns True if water is low
VeSyncHumid.auto_humidity
- Target humidity for auto mode
VeSyncHumid.auto_enabled
- Returns true if auto stop enabled at target humidity
VeSyncHumid.automatic_stop_on()
Set humidifier to stop at set humidity
VeSyncHumid.automatic_stop_off
Set humidifier to run continuously
VeSyncHumid.turn_on_display()
Turn display on
VeSyncHumid.turn_off_display()
Turn display off
VeSyncHumid.set_humidity(30)
Set humidity between 30 and 80 percent
VeSyncHumid.set_night_light_brightness(50)
Set nightlight brightness between 1 and 100
VeSyncHumid.set_humidity_mode('sleep')
Set humidity mode - sleep/auto
VeSyncHumid.set_mist_level(4)
Set mist output 1 - 9
VeSync600S.warm_mist_enabled
- Returns true if warm mist feature is enabled
VeSync600S.set_warm_level(2)
- Sets warm mist level
Cosori devices are found under the manager.kitchen
VeSync class attribute.
The Cosori 3.7 and 5.8 Quart Air Fryer has several methods and properties that can be used to monitor and control the device.
This library splits the functionality and status into two classes that are both accessible from the device instance.
To maintain consistency of state, the update() method is called after each of the methods that change the state of the device.
There is also an instance attribute that can be set VeSyncAirFryer158.refresh_interval
that will set the interval in seconds that the state of the air fryer should be updated before a method that changes state is called. This is an additional API call but is necessary to maintain state, especially when trying to pause
or resume
the device. Defaults to 60 seconds but can be set via:
# Change to 120 seconds before status is updated between calls
VeSyncAirFryer158.refresh_interval = 120
# Set status update before every call
VeSyncAirFryer158.refresh_interval = 0
# Disable status update before every call
VeSyncAirFryer158.refresh_interval = -1
All properties cannot be directly set, they must be set from the get_details()
or methods that set the status.
They can be set through the VeSyncAirFryer158.fryer_status
dataclass but should be avoided. This separation of functionality and status is purposeful to avoid inconsistent states.
VeSyncAirFryer158.temp_unit
- Temperature units of the device (fahrenheit
or celsius
)
VeSyncAirFryer158.current_temp
- Current temperature in the defined temperature units. If device is not running, this defaults to None
VeSyncAirFryer158.cook_set_temp
- Set temperature or target temperature for preheat
VeSyncAirFryer158.cook_last_time
- The last minutes remaining returned from API for cook mode
VeSyncAirFryer158.preheat_last_time
- The last minutes remaining returned from API for preheat mode
VeSyncAirFryer158.cook_status
- Status of air fryer. This can be the following states:
standby
- Air fryer is off and no cook or preheat is in progresscooking
- Air fryer is actively cookingcookStop
- Cooking is paused and can be resumedcookEnd
- Cooking is ended and can be resumedheating
- Air fryer is preheatingpreheatStop
- Preheat is paused and can be resumedheatEnd
- Preheat is ended and cooking mode can be started withcook_from_preheat()
method
VeSyncAirFryer158.is_heating
- Returns true if air fryer is preheating
VeSyncAirFryer158.is_cooking
- Returns true if air fryer is cooking
VeSyncAirFryer158.is_paused
- Returns true if air fryer is paused and can be resumed
VeSyncAirFryer158.remaining_time
- Returns minutes remaining based on timestamp of last API return when air fryer is running. Returns None
if not running
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.
VeSyncAirFryer158.update()
- Retrieve current status
VeSyncAirFryer158.cook(set_temp: int, set_time: int)
- Set air fryer cook mode based on time and temp in defined units
VeSyncAirFryer158.set_preheat(target_temp: int, cook_time: int)
- Set air fryer preheat mode based on time and temp in defined units
VeSyncAirFryer158.cook_from_preheat()
- Start cook mode when air fryer is in preheatEnd
state
VeSyncAirFryer158.pause()
- Pause air fryer when in cooking
or heating
state
VeSyncAirFryer158.resume()
- Resume air fryer when in cookStop
or preheatStop
state
VeSyncAirFryer158.end()
- End cooking or preheating and return air fryer to standby
state
The device.displayJSON()
method outputs properties and status of the device
device.displayJSON()
#Returns:
{
"Device Name": "Device 1",
"Model": "Device Model",
"Subdevice No": "1",
"Status": "on",
"Online": "online",
"Type": "Device Type",
"CID": "DEVICE-CID"
}
{
"Active Time": "1", # in minutes
"Energy": "2.4", # today's energy in kWh
"Power": "12", # current power in W
"Voltage": "120", # current voltage
"Energy Week": "12", # totaly energy of week in kWh
"Energy Month": "50", # total energy of month in kWh
"Energy Year": "89", # total energy of year in kWh
}
This output only applies to dimmable switch. The standard switch has the default device JSON output shown above
{
"Indicator Light": "on", # status of indicator light
"Brightness": "50", # percent brightness
"RGB Light": "on" # status of RGB Light on faceplate
}
# output for dimmable bulb
{
# all default outputs plus...
"Brightness": "50" # brightness in percent
}
# output for tunable bulb
{
# all default outputs plus...
"Brightness": "50" # brightness in percent
"Kelvin": "5400" # white temperature in Kelvin
}
# output for valceno multicolor bulb
{
# all default outputs plus...
"Brightness": "100", # brightness in percent (also used for color value in hsv mode)
"WhiteTemperaturePct": "0", # white temperature in percent
"WhiteTemperatureKelvin": "2700", # white temperature in Kelvin
"ColorHSV": "hsv(hue=79.99, saturation=90.0, value=100)", # color definition in HSV model
"ColorRGB": "rgb(red=178.5, green=255.0, blue=25.5)", # color definition in RGB model
"ColorMode": "hsv" # color mode ( white / hsv )
}
{
"Active Time": "50", # minutes
"Fan Level": "2", # fan level 1-3
"Air Quality": "95", # air quality in percent
"Mode": "auto",
"Screen Status": "on",
"Filter Life": "99" # remaining filter life in percent
}
{
"Mode": "manual", # auto, manual, sleep
"Humidity": 20, # percent
"Mist Virtual Level": 6, # Mist level 1 - 9
"Water Lacks": true, # True/False
"Water Tank Lifted": true, # True/False
"Display": true, # True/False
"Automatic Stop Reach Target": true,
"Night Light Brightness": 10, # 1 - 100
"Auto Target Humidity": true, # True/False
"Automatic Stop": true # True/False
}
{
"Device Name": "MyPurifier",
"Model": "Core200S",
"Subdevice No": "None",
"Status": "on",
"Online": "online",
"Type": "wifi-air",
"CID": "asd_sdfKIHG7IJHGwJGJ7GJ_ag5h3G55",
"Mode": "manual",
"Filter Life": "99",
"Fan Level": "1",
"Display": true,
"Child Lock": false,
"Night Light": "off",
"Display Config": true,
"Display_Forever Config": false
}
{
"Device Name": "MyPurifier",
"Model": "Core200S",
"Subdevice No": "None",
"Status": "on",
"Online": "online",
"Type": "wifi-air",
"CID": "<CID>",
"Mode": "manual",
"Filter Life": "100",
"Air Quality Level": "5",
"Air Quality Value": "1",
"Fan Level": "1",
"Display": true,
"Child Lock": false,
"Night Light": "off",
"Display Config": true,
"Display_Forever Config": false
}
{
"Device Name": "My 600s",
"Model": "LAP-C601S-WUS",
"Subdevice No": "None",
"Status": "on",
"Online": "online",
"Type": "wifi-air",
"CID": "<CID>",
"Mode": "manual",
"Filter Life": "98",
"Air Quality Level": "5",
"Air Quality Value": "1",
"Fan Level": "3",
"Display": true,
"Child Lock": false,
"Night Light": "off",
"Display Config": true,
"Display_Forever Config": false
}
More detailed data is available within the VesyncOutlet
by inspecting the VesyncOutlet.energy
dictionary.
The VesyncOutlet.energy
object includes 3 nested dictionaries week
, month
, and year
that contain detailed weekly, monthly and yearly data
VesyncOutlet.energy['week']['energy_consumption_of_today']
VesyncOutlet.energy['week']['cost_per_kwh']
VesyncOutlet.energy['week']['max_energy']
VesyncOutlet.energy['week']['total_energy']
VesyncOutlet.energy['week']['data'] # which itself is a list of values
To make it easier to debug, there is a debug
argument in the VeSync
method. This prints out your device list and any other debug log messages.
import pyvesync.vesync as vs
manager = vs.VeSync('user', 'pass', debug=True)
manager.login()
manager.update()
# Prints device list returned from Vesync
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. 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.
SSL pinning makes capturing packets with android not feasible anymore. 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.
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.
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.
For example:
Before:
{
'tk': 'abc123abc123==3rf',
'accountId': '123456789',
'cid': 'abcdef12-3gh-ij'
}
After:
{
'tk': 'AAA111AAA111==1AA',
'accountId': '111111111',
'cid': 'AAAAAA11-1AA-AA'
}
All contributions are welcome, please run tox
before submitting a PR to ensure code is valid.
Ensure new devices are integrated in tests, please review the testing documentation for more information.
This project is licensed under MIT.