Samsung TV can't turn off after idle period
When Samsung TV is idle for a period of time after issued a command, subsequent 'turn_off' command won't turn off the TV. The issue is seen in Samsung models with websocket as discussed in #12302. == Reproducible Steps 1. Turn on TV (either via HA or directly). 2. Issue some commands e.g. volume ups / downs. 3. Wait for ~1 minute. 4. Issue turn_off command via HA. TV won't turn off. 5. Issue subsequent turn off commands won't turn off TV still. 6. However, issue some other commands e.g. volume ups / downs multiple times in a row and then turn_off will turn off the TV. == Root Cause The underlying websocket connection opened by samsungctl get closed after some idle time. There was no retry mechanism so issued commands would intermittently fail but the subsequent one would succeed when `_remote` get recreated. With `turn_off()`, however, there is an additional call to `self.get_remote().close()` which indirectly caused new connection to be created and then closed immediately. This causes the component to stuck in failure mode when turn_off command is repeatly issued. == The Fix Recreate the connection and retry the command if connection is closed to avoid silent failures due to connection closed. Also set `_remote` to None after calling close() to put it in correct state. This fix eliminates intermittent command failure and failure mode in turn_off().
This commit is contained in:
parent
6af995026b
commit
58a1c38393
1 changed files with 14 additions and 4 deletions
|
@ -154,17 +154,26 @@ class SamsungTVDevice(MediaPlayerDevice):
|
|||
and not (key == 'KEY_POWER' or key == 'KEY_POWEROFF'):
|
||||
_LOGGER.info("TV is powering off, not sending command: %s", key)
|
||||
return
|
||||
try:
|
||||
# recreate connection if connection was dead
|
||||
retry_count = 1
|
||||
for _ in range(retry_count + 1):
|
||||
try:
|
||||
self.get_remote().control(key)
|
||||
break
|
||||
except (self._exceptions_class.ConnectionClosed,
|
||||
BrokenPipeError):
|
||||
# BrokenPipe can occur when the commands is sent to fast
|
||||
self._remote = None
|
||||
self._state = STATE_ON
|
||||
except (self._exceptions_class.UnhandledResponse,
|
||||
self._exceptions_class.AccessDenied, BrokenPipeError):
|
||||
self._exceptions_class.AccessDenied):
|
||||
# We got a response so it's on.
|
||||
# BrokenPipe can occur when the commands is sent to fast
|
||||
self._state = STATE_ON
|
||||
self._remote = None
|
||||
_LOGGER.debug("Failed sending command %s", key, exc_info=True)
|
||||
return
|
||||
except (self._exceptions_class.ConnectionClosed, OSError):
|
||||
except OSError:
|
||||
self._state = STATE_OFF
|
||||
self._remote = None
|
||||
if self._power_off_in_progress():
|
||||
|
@ -207,6 +216,7 @@ class SamsungTVDevice(MediaPlayerDevice):
|
|||
# Force closing of remote session to provide instant UI feedback
|
||||
try:
|
||||
self.get_remote().close()
|
||||
self._remote = None
|
||||
except OSError:
|
||||
_LOGGER.debug("Could not establish connection.")
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue