Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions switchbot/devices/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def name(self) -> str:
@property
def rssi(self) -> int:
"""Return RSSI of device."""
return self._get_adv_value("rssi")
return self._get_adv_value("rssi") or self._device.rssi

async def _ensure_connected(self):
"""Ensure connection to device is established."""
Expand Down Expand Up @@ -249,8 +249,7 @@ def _resolve_characteristics(self, services: BleakGATTServiceCollection) -> bool

def _reset_disconnect_timer(self):
"""Reset disconnect timer."""
if self._disconnect_timer:
self._disconnect_timer.cancel()
self._cancel_disconnect_timer()
self._expected_disconnect = False
self._disconnect_timer = self.loop.call_later(
DISCONNECT_DELAY, self._disconnect
Expand All @@ -271,28 +270,47 @@ def _disconnected(self, client: BleakClientWithServiceCache) -> None:

def _disconnect(self):
"""Disconnect from device."""
self._disconnect_timer = None
self._cancel_disconnect_timer()
asyncio.create_task(self._execute_timed_disconnect())

async def _execute_timed_disconnect(self):
def _cancel_disconnect_timer(self):
"""Cancel disconnect timer."""
if self._disconnect_timer:
self._disconnect_timer.cancel()
self._disconnect_timer = None

async def _execute_forced_disconnect(self) -> None:
"""Execute forced disconnection."""
self._cancel_disconnect_timer()
_LOGGER.debug(
"%s: Executing forced disconnect",
self.name,
)
await self._execute_disconnect()

async def _execute_timed_disconnect(self) -> None:
"""Execute timed disconnection."""
_LOGGER.debug(
"%s: Disconnecting after timeout of %s",
"%s: Executing timed disconnect after timeout of %s",
self.name,
DISCONNECT_DELAY,
)
await self._execute_disconnect()

async def _execute_disconnect(self):
async def _execute_disconnect(self) -> None:
"""Execute disconnection."""
async with self._connect_lock:
if self._disconnect_timer: # If the timer was reset, don't disconnect
return
client = self._client
self._expected_disconnect = True
self._client = None
self._read_char = None
self._write_char = None
if client and client.is_connected:
_LOGGER.debug("%s: Disconnecting", self.name)
await client.disconnect()
_LOGGER.debug("%s: Disconnect completed", self.name)

async def _send_command_locked(self, key: str, command: bytes) -> bytes:
"""Send command to device and read response."""
Expand All @@ -309,14 +327,14 @@ async def _send_command_locked(self, key: str, command: bytes) -> bytes:
0.25,
ex,
)
await self._execute_disconnect()
await self._execute_forced_disconnect()
raise
except BleakError as ex:
# Disconnect so we can reset state and try again
_LOGGER.debug(
"%s: RSSI: %s; Disconnecting due to error: %s", self.name, self.rssi, ex
)
await self._execute_disconnect()
await self._execute_forced_disconnect()
raise

async def _execute_command_locked(self, key: str, command: bytes) -> bytes:
Expand Down