Skip to content

Commit fac605a

Browse files
committed
Fix display & enabled/disabled bug
1 parent 85fe110 commit fac605a

File tree

4 files changed

+63
-35
lines changed

4 files changed

+63
-35
lines changed

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
include README.md LICENSE requirements.txt
2+
exclude test
3+
prune test

setup.py

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

1111
setup(
1212
name='pyvesync',
13-
version='2.1.8',
13+
version='2.1.9',
1414
description='pyvesync is a library to manage Etekcity\
1515
Devices, Cosori Air Fryers and Levoit Air \
1616
Purifiers run on the VeSync app.',
@@ -28,9 +28,8 @@
2828
'Programming Language :: Python :: 3.8',
2929
],
3030
keywords=['iot', 'vesync', 'levoit', 'etekcity', 'cosori', 'valceno'],
31-
packages=find_packages('src', exclude=['tests', 'tests.*']),
31+
packages=find_packages('src', exclude=['tests', 'test*']),
3232
package_dir={'': 'src'},
33-
zip_safe=False,
3433
install_requires=['requests>=2.20.0'],
3534
extras_require={
3635
'dev': ['pytest', 'pytest-cov', 'yaml', 'tox']

src/pyvesync/helpers.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,19 @@ def redactor(cls, stringvalue: str) -> str:
194194
'##_REDACTED_##', stringvalue)
195195
return stringvalue
196196

197+
@staticmethod
198+
def nested_code_check(response: dict) -> bool:
199+
"""Return true if all code values are 0."""
200+
if isinstance(response, dict):
201+
for key, value in response.items():
202+
if key == 'code':
203+
if value != 0:
204+
return False
205+
elif isinstance(value, dict):
206+
if not Helpers.nested_code_check(value):
207+
return False
208+
return True
209+
197210
@staticmethod
198211
def call_api(api: str, method: str, json_object: Optional[dict] = None,
199212
headers: Optional[dict] = None) -> tuple:

src/pyvesync/vesyncfan.py

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
'module': 'VeSyncVital',
100100
'models': ['LAP-V102S-AASR', 'LAP-V102S-WUS', 'LAP-V102S-WEU',
101101
'LAP-V102S-AUSR', 'LAP-V102S-WJP'],
102-
'modes': ['manual', 'auto', 'sleep', 'off'],
102+
'modes': ['manual', 'auto', 'sleep', 'off', 'pet'],
103103
'features': ['air_quality'],
104104
'levels': list(range(1, 5))
105105
},
@@ -768,29 +768,20 @@ def get_details(self) -> None:
768768
headers=head,
769769
json_object=body,
770770
)
771-
if not isinstance(r, dict):
772-
logger.debug('Error in purifier response')
771+
if Helpers.nested_code_check(r) is False or not isinstance(r, dict):
772+
logger.debug('Error getting purifier details')
773+
self.connection_status = 'offline'
773774
return
774-
if not isinstance(r.get('result'), dict):
775-
logger.debug('Error in purifier response')
776-
return
777-
outer_result = r.get('result', {})
778-
inner_result = None
779775

780-
if outer_result:
781-
inner_result = r.get('result', {}).get('result')
782-
if inner_result is not None and Helpers.code_check(r):
783-
if outer_result.get('code') == 0:
784-
self.build_purifier_dict(inner_result)
785-
else:
786-
self.online = False
787-
logger.debug('error in inner result dict from purifier')
788-
if inner_result.get('configuration', {}):
789-
self.build_config_dict(inner_result.get('configuration', {}))
790-
else:
791-
logger.debug('No configuration found in purifier status')
776+
inner_result = r.get('result', {}).get('result')
777+
778+
if inner_result is not None:
779+
self.build_purifier_dict(inner_result)
792780
else:
793-
logger.debug('Error in purifier response')
781+
self.connection_status = 'offline'
782+
logger.debug('error in inner result dict from purifier')
783+
if inner_result.get('configuration', {}):
784+
self.build_config_dict(inner_result.get('configuration', {}))
794785

795786
def build_api_dict(self, method: str) -> Tuple[Dict, Dict]:
796787
"""Return default body for Levoit Vital 100S/200S API."""
@@ -809,7 +800,7 @@ def build_api_dict(self, method: str) -> Tuple[Dict, Dict]:
809800

810801
def build_purifier_dict(self, dev_dict: dict) -> None:
811802
"""Build Bypass purifier status dictionary."""
812-
self.online = True
803+
self.connection_status = 'online'
813804
power_switch = bool(dev_dict.get('powerSwitch', 0))
814805
self.enabled = power_switch
815806
self.device_status = 'on' if power_switch is True else 'off'
@@ -846,10 +837,7 @@ def pet_mode(self) -> bool:
846837

847838
def set_light_detection(self, toggle: bool) -> bool:
848839
"""Enable/Disable Light Detection Feature."""
849-
if toggle is True:
850-
toggle_id = 1
851-
else:
852-
toggle_id = 0
840+
toggle_id = int(toggle)
853841
if self.details['light_detection_switch'] == toggle_id:
854842
logger.debug("Light Detection is already set to %s", toggle_id)
855843
return True
@@ -863,7 +851,7 @@ def set_light_detection(self, toggle: bool) -> bool:
863851
json_object=body,
864852
)
865853

866-
if r is not None and Helpers.code_check(r):
854+
if r is not None and Helpers.nested_code_check(r):
867855
self.details['light_detection'] = toggle
868856
return True
869857
logger.debug("Error toggling purifier - %s",
@@ -901,7 +889,7 @@ def toggle_switch(self, toggle: bool) -> bool:
901889
json_object=body,
902890
)
903891

904-
if r is not None and Helpers.code_check(r):
892+
if r is not None and Helpers.nested_code_check(r):
905893
if toggle:
906894
self.device_status = 'on'
907895
else:
@@ -929,7 +917,7 @@ def set_child_lock(self, mode: bool) -> bool:
929917
json_object=body,
930918
)
931919

932-
if r is not None and Helpers.code_check(r):
920+
if r is not None and Helpers.nested_code_check(r):
933921
self.details['child_lock'] = mode
934922
return True
935923

@@ -954,7 +942,7 @@ def set_display(self, mode: bool) -> bool:
954942
json_object=body,
955943
)
956944

957-
if r is not None and Helpers.code_check(r):
945+
if r is not None and Helpers.nested_code_check(r):
958946
self.details['screen_switch'] = mode
959947
return True
960948

@@ -1004,7 +992,7 @@ def set_timer(self, timer_duration: int, action: str = 'off',
1004992
json_object=body,
1005993
)
1006994

1007-
if r is not None and Helpers.code_check(r):
995+
if r is not None and Helpers.nested_code_check(r):
1008996
self.timer = Timer(timer_duration, action)
1009997
return True
1010998

@@ -1024,7 +1012,7 @@ def clear_timer(self) -> bool:
10241012
json_object=body,
10251013
)
10261014

1027-
if r is not None and Helpers.code_check(r):
1015+
if r is not None and Helpers.nested_code_check(r):
10281016
self.timer = None
10291017
return True
10301018

@@ -1164,6 +1152,32 @@ def mode_toggle(self, mode: str) -> bool:
11641152
logger.debug('Error setting purifier mode')
11651153
return False
11661154

1155+
def displayJSON(self) -> str:
1156+
"""Return air purifier status and properties in JSON output."""
1157+
sup = super().displayJSON()
1158+
sup_val = json.loads(sup)
1159+
sup_val.update(
1160+
{
1161+
'Mode': self.mode,
1162+
'Filter Life': str(self.details['filter_life']),
1163+
'Fan Level': str(self.speed),
1164+
'Display On': self.details['display'],
1165+
'Child Lock': self.details['child_lock'],
1166+
'Night Light': str(self.details['night_light']),
1167+
'Display Set On': self.details['screen_switch'],
1168+
'Light Detection Enabled': self.details['light_detection_switch'],
1169+
'Environment Light State': self.details['environment_light_state']
1170+
}
1171+
)
1172+
if self.air_quality_feature is True:
1173+
sup_val.update(
1174+
{'Air Quality Level': str(self.details.get('air_quality', ''))}
1175+
)
1176+
sup_val.update(
1177+
{'Air Quality Value': str(self.details.get('air_quality_value', ''))}
1178+
)
1179+
return json.dumps(sup_val, indent=4)
1180+
11671181

11681182
class VeSyncAir131(VeSyncBaseDevice):
11691183
"""Levoit Air Purifier Class."""

0 commit comments

Comments
 (0)