Skip to content

Commit

Permalink
Merge pull request #96 from bhamiltoncx/Core200S
Browse files Browse the repository at this point in the history
Add support for Dual 200S humidifier device
  • Loading branch information
webdjoe authored Nov 21, 2021
2 parents a157537 + c80bfbc commit 5607a97
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 32 deletions.
4 changes: 3 additions & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pr:

jobs:
- job: 'Validation'
pool:
vmImage: 'ubuntu-20.04'
steps:
- task: UsePythonVersion@0
inputs:
Expand All @@ -39,7 +41,7 @@ jobs:
- job: 'pytest'
pool:
vmImage: 'ubuntu-latest'
vmImage: 'ubuntu-20.04'
strategy:
matrix:
Python36:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

setup(
name='pyvesync',
version='1.4.1',
version='1.4.2',
description='pyvesync is a library to manage Etekcity\
Devices and Levoit Air Purifier',
long_description=long_description,
Expand Down
13 changes: 8 additions & 5 deletions src/pyvesync/vesync.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
import time
from itertools import chain
from collections import defaultdict
from typing import List, Dict, DefaultDict, Union, Any
from typing import List, Dict, DefaultDict, Union, Any, Type

from pyvesync.helpers import Helpers
from pyvesync.vesyncbasedevice import VeSyncBaseDevice
from pyvesync.vesyncbulb import VeSyncBulbESL100, VeSyncBulbESL100CW
from pyvesync.vesyncfan import (
VeSyncAir131,
VeSyncHumid300S,
VeSyncHumid200300S,
VeSyncAir200S,
VeSyncAir300S400S,
)
Expand All @@ -32,7 +33,7 @@

# Class dictionary based on device type

_DEVICE_CLASS: Dict[str, Any] = {
_DEVICE_CLASS: Dict[str, Type[VeSyncBaseDevice]] = {
'wifi-switch-1.3': VeSyncOutlet7A,
'ESW03-USA': VeSyncOutlet10A,
'ESW01-EU': VeSyncOutlet10A,
Expand All @@ -44,7 +45,8 @@
'ESL100': VeSyncBulbESL100,
'ESL100CW': VeSyncBulbESL100CW,
'ESWD16': VeSyncDimmerSwitch,
'Classic300S': VeSyncHumid300S,
'Classic300S': VeSyncHumid200300S,
'Dual200S': VeSyncHumid200300S,
'Core200S': VeSyncAir200S,
'Core300S': VeSyncAir300S400S,
'Core400S': VeSyncAir300S400S,
Expand All @@ -54,7 +56,8 @@
outlets=['wifi-switch-1.3', 'ESW03-USA',
'ESW01-EU', 'ESW15-USA', 'ESO15-TB'],
switches=['ESWL01', 'ESWL03', 'ESWD16'],
fans=['LV-PUR131S', 'Classic300S', 'Core200S', 'Core300S', 'Core400S'],
fans=['LV-PUR131S', 'Classic300S', 'Core200S',
'Core300S', 'Core400S', 'Dual200S'],
bulbs=['ESL100', 'ESL100CW'],
)

Expand Down
6 changes: 4 additions & 2 deletions src/pyvesync/vesyncbasedevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ def __hash__(self):

def __str__(self):
"""Use device info for string represtation of class."""
return f'Device Name: {self.device_name}, Device Type: {self.device_type},\
SubDevice No.: {self.sub_device_no} Status: {self.device_status}'
return f'Device Name: {self.device_name}, \
Device Type: {self.device_type},\
SubDevice No.: {self.sub_device_no},\
Status: {self.device_status}'

def __repr__(self):
"""Representation of device details."""
Expand Down
62 changes: 39 additions & 23 deletions src/pyvesync/vesyncfan.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
from pyvesync.vesyncbasedevice import VeSyncBaseDevice
from pyvesync.helpers import Helpers

air_features = {
'Dual200S': [],
'Classic300S': ['nightlight']
}

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -1059,13 +1063,17 @@ def displayJSON(self) -> str:
return sup_val


class VeSyncHumid300S(VeSyncBaseDevice):
"""300S Humidifier Class."""
class VeSyncHumid200300S(VeSyncBaseDevice):
"""200S/300S Humidifier Class."""

def __init__(self, details, manager):
"""Initilize 300S Humidifier class."""
"""Initialize 200S/300S Humidifier class."""
super().__init__(details, manager)
self.enabled = True
if 'nightlight' in air_features.get(details['deviceType']):
self.night_light = True
else:
self.night_light = False
self.details: Dict[str, Union[str, int, float]] = {
'humidity': 0,
'mist_virtual_level': 0,
Expand All @@ -1076,16 +1084,17 @@ def __init__(self, details, manager):
'water_tank_lifted': False,
'display': False,
'automatic_stop_reach_target': False,
'night_light_brightness': 0
}
if self.night_light:
self.details['night_light_brightness'] = 0
self.config: Dict[str, Union[str, int, float]] = {
'auto_target_humidity': 0,
'display': False,
'automatic_stop': True
}

def __build_api_dict(self, method: str) -> Tuple[Dict, Dict]:
"""Build 300S api call header and body.
"""Build 200S/300S api call header and body.
Available methods are: 'getHumidifierStatus', 'setAutomaticStop',
'setSwitch', 'setNightLightBrightness', 'setVirtualLevel',
Expand All @@ -1108,7 +1117,7 @@ def __build_api_dict(self, method: str) -> Tuple[Dict, Dict]:
return head, body

def build_humid_dict(self, dev_dict: Dict):
"""Build 300S humidifier status dictionary."""
"""Build 200S/300S humidifier status dictionary."""
self.enabled = dev_dict.get('enabled')
self.details['humidity'] = dev_dict.get('humidity', 0)
self.details['mist_virtual_level'] = dev_dict.get(
Expand All @@ -1123,8 +1132,9 @@ def build_humid_dict(self, dev_dict: Dict):
self.details['automatic_stop_reach_target'] = dev_dict.get(
'automatic_stop_reach_target', True
)
self.details['night_light_brightness'] = dev_dict.get(
'night_light_brightness', 0)
if self.night_light:
self.details['night_light_brightness'] = dev_dict.get(
'night_light_brightness', 0)

def build_config_dict(self, conf_dict):
"""Build configuration dict for 300s humidifier."""
Expand All @@ -1134,7 +1144,7 @@ def build_config_dict(self, conf_dict):
self.config['automatic_stop'] = conf_dict.get('automatic_stop', True)

def get_details(self) -> None:
"""Build 300S Humidifier details dictionary."""
"""Build 200S/300S Humidifier details dictionary."""
head = Helpers.bypass_header()
body = Helpers.bypass_body_v2(self.manager)
body['cid'] = self.cid
Expand Down Expand Up @@ -1169,7 +1179,7 @@ def get_details(self) -> None:
logger.debug('Error in humidifier response')

def update(self):
"""Update 300S Humidifier details."""
"""Update 200S/300S Humidifier details."""
self.get_details()

def toggle_switch(self, toggle: bool) -> bool:
Expand Down Expand Up @@ -1204,23 +1214,23 @@ def toggle_switch(self, toggle: bool) -> bool:
return False

def turn_on(self) -> bool:
"""Turn 300S Humidifier on."""
"""Turn 200S/300S Humidifier on."""
return self.toggle_switch(True)

def turn_off(self):
"""Turn 300S Humidifier off."""
"""Turn 200S/300S Humidifier off."""
return self.toggle_switch(False)

def automatic_stop_on(self) -> bool:
"""Turn 300S Humidifier automatic stop on."""
"""Turn 200S/300S Humidifier automatic stop on."""
return self.set_automatic_stop(True)

def automatic_stop_off(self) -> bool:
"""Turn 300S Humidifier automatic stop on."""
"""Turn 200S/300S Humidifier automatic stop on."""
return self.set_automatic_stop(False)

def set_automatic_stop(self, mode: bool) -> bool:
"""Set 300S Humidifier to automatic stop."""
"""Set 200S/300S Humidifier to automatic stop."""
if mode not in (True, False):
logger.debug(
'Invalid mode passed to set_automatic_stop - %s', mode)
Expand Down Expand Up @@ -1274,15 +1284,15 @@ def set_display(self, mode: bool) -> bool:
return False

def turn_on_display(self) -> bool:
"""Turn 300S Humidifier on."""
"""Turn 200S/300S Humidifier on."""
return self.set_display(True)

def turn_off_display(self):
"""Turn 300S Humidifier off."""
"""Turn 200S/300S Humidifier off."""
return self.set_display(False)

def set_humidity(self, humidity: int) -> bool:
"""Set target 300S Humidifier humidity."""
"""Set target 200S/300S Humidifier humidity."""
if humidity < 30 or humidity > 80:
logger.debug("Humidity value must be set between 30 and 80")
return False
Expand All @@ -1308,7 +1318,11 @@ def set_humidity(self, humidity: int) -> bool:
return False

def set_night_light_brightness(self, brightness: int) -> bool:
"""Set target 300S Humidifier night light brightness."""
"""Set target 200S/300S Humidifier night light brightness."""
if not self.night_light:
logger.debug('%s is a %s does not have a nightlight',
self.device_name, self.device_type)
return False
if brightness < 0 or brightness > 100:
logger.debug("Brightness value must be set between 0 and 100")
return False
Expand Down Expand Up @@ -1400,12 +1414,13 @@ def display(self) -> None:
('Display: ', self.details['display'], ''),
('Automatic Stop Reach Target: ',
self.details['automatic_stop_reach_target'], ''),
('Night Light Brightness: ',
self.details['night_light_brightness'], 'percent'),
('Auto Target Humidity: ',
self.config['auto_target_humidity'], 'percent'),
('Automatic Stop: ', self.config['automatic_stop'], ''),
]
if self.night_light:
disp1.append(('Night Light Brightness: ',
self.details['night_light_brightness'], 'percent'))
for line in disp1:
print(f'{line[0]:.<29} {line[1]} {line[2]}')

Expand All @@ -1426,11 +1441,12 @@ def displayJSON(self) -> str:
'Display': self.details['display'],
'Automatic Stop Reach Target': self.details[
'automatic_stop_reach_target'],
'Night Light Brightness': self.details[
'night_light_brightness'],
'Auto Target Humidity': str(self.config[
'auto_target_humidity']),
'Automatic Stop': self.config['automatic_stop'],
}
)
if self.night_light:
sup_val['Night Light Brightness'] = self.details[
'night_light_brightness']
return json.dumps(sup_val)

0 comments on commit 5607a97

Please sign in to comment.