From 5713d11f7cf9b96e04fd91c509d04fc718b88897 Mon Sep 17 00:00:00 2001 From: SapuSeven Date: Wed, 20 Aug 2025 16:53:26 +0200 Subject: [PATCH 1/4] Properly return from login methods --- src/pyvesync/vesync.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/pyvesync/vesync.py b/src/pyvesync/vesync.py index 3d26980..41e58eb 100644 --- a/src/pyvesync/vesync.py +++ b/src/pyvesync/vesync.py @@ -307,7 +307,7 @@ async def get_devices(self) -> bool: return proc_return - async def login(self) -> bool: # pylint: disable=W9006 # pylint mult docstring raises + async def login(self) -> None: # pylint: disable=W9006 # pylint mult docstring raises """Log into VeSync server. Username and password are provided when class is instantiated. @@ -364,7 +364,7 @@ async def _login_token( self, auth_code: str | None = None, region_change_token: str | None = None, - ) -> bool: # pylint: disable=W9006 # pylint mult docstring raises + ) -> None: # pylint: disable=W9006 # pylint mult docstring raises """Exchanges the authorization code for a token. This completes the login process. If the initial call fails with @@ -407,7 +407,7 @@ async def _login_token( if error_info.error_type == ErrorTypes.CROSS_REGION: # cross region error result = response_model.result self.country_code = result.countryCode - await self._login_token(region_change_token=result.bizToken) + return await self._login_token(region_change_token=result.bizToken) resp_message = resp_dict.get('msg') if resp_message is not None: error_info.message = f'{error_info.message} ({resp_message})' @@ -427,6 +427,7 @@ async def _login_token( self.country_code = result.countryCode self.enabled = True logger.debug('Login successful') + return None except (MissingField, UnserializableDataError) as exc: logger.debug('Error parsing login response: %s', exc) From 2d0a3756b0896dc62bdffcd6a261e6aa0bdea941 Mon Sep 17 00:00:00 2001 From: SapuSeven Date: Wed, 20 Aug 2025 17:50:51 +0200 Subject: [PATCH 2/4] Ensure light detection is turned off when changing display status --- src/pyvesync/devices/vesyncpurifier.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/pyvesync/devices/vesyncpurifier.py b/src/pyvesync/devices/vesyncpurifier.py index b46c160..64053b5 100644 --- a/src/pyvesync/devices/vesyncpurifier.py +++ b/src/pyvesync/devices/vesyncpurifier.py @@ -1,6 +1,7 @@ """VeSync API for controlling air purifiers.""" from __future__ import annotations import logging +import asyncio from typing import TYPE_CHECKING from typing_extensions import deprecated @@ -528,6 +529,10 @@ async def set_light_detection(self, toggle: bool) -> bool: async def toggle_light_detection(self, toggle: bool | None = None) -> bool: """Enable/Disable Light Detection Feature.""" + if bool(self.state.light_detection_status) == toggle: + _LOGGER.debug('Light detection is already %s', self.state.light_detection_status) + return True + if toggle is None: toggle = not bool(self.state.light_detection_status) payload_data = {"lightDetectionSwitch": int(toggle)} @@ -536,8 +541,7 @@ async def toggle_light_detection(self, toggle: bool | None = None) -> bool: if r is None: return False - self.state.light_detection_switch = DeviceStatus.ON if toggle \ - else DeviceStatus.OFF + self.state.light_detection_switch = DeviceStatus.from_bool(toggle) self.state.connection_status = ConnectionStatus.ONLINE return True @@ -587,6 +591,10 @@ async def toggle_child_lock(self, toggle: bool | None = None) -> bool: return True async def toggle_display(self, mode: bool) -> bool: + if bool(self.state.light_detection_status): + await self.toggle_light_detection(False) # Ensure light detection is off + await asyncio.sleep(1) # Wait for a second - the setDisplay call fails when called immediately after disabling light detection + if bool(self.state.display_set_status) == mode: _LOGGER.debug('Display is already %s', mode) return True From f346e90293eb5b47f105f85675a2eca905936383 Mon Sep 17 00:00:00 2001 From: SapuSeven Date: Sat, 23 Aug 2025 11:05:04 +0200 Subject: [PATCH 3/4] Remove explicit return --- src/pyvesync/vesync.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pyvesync/vesync.py b/src/pyvesync/vesync.py index 41e58eb..d8da4b7 100644 --- a/src/pyvesync/vesync.py +++ b/src/pyvesync/vesync.py @@ -427,7 +427,6 @@ async def _login_token( self.country_code = result.countryCode self.enabled = True logger.debug('Login successful') - return None except (MissingField, UnserializableDataError) as exc: logger.debug('Error parsing login response: %s', exc) From d962e651b51cac27bb98156d051cbb33b4698a18 Mon Sep 17 00:00:00 2001 From: SapuSeven Date: Tue, 26 Aug 2025 00:29:55 +0200 Subject: [PATCH 4/4] Return False with error log instead of modifying light detection directly --- src/pyvesync/devices/vesyncpurifier.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pyvesync/devices/vesyncpurifier.py b/src/pyvesync/devices/vesyncpurifier.py index 64053b5..3974992 100644 --- a/src/pyvesync/devices/vesyncpurifier.py +++ b/src/pyvesync/devices/vesyncpurifier.py @@ -1,7 +1,6 @@ """VeSync API for controlling air purifiers.""" from __future__ import annotations import logging -import asyncio from typing import TYPE_CHECKING from typing_extensions import deprecated @@ -592,8 +591,8 @@ async def toggle_child_lock(self, toggle: bool | None = None) -> bool: async def toggle_display(self, mode: bool) -> bool: if bool(self.state.light_detection_status): - await self.toggle_light_detection(False) # Ensure light detection is off - await asyncio.sleep(1) # Wait for a second - the setDisplay call fails when called immediately after disabling light detection + _LOGGER.error('Cannot set display when light detection is enabled') + return False if bool(self.state.display_set_status) == mode: _LOGGER.debug('Display is already %s', mode)