Adjust power_off for TheFrame in SamsungTV (#67841)

Co-authored-by: epenet <epenet@users.noreply.github.com>
This commit is contained in:
epenet 2022-03-08 08:20:58 +01:00 committed by GitHub
parent 5b23b9a617
commit 6f38eda114
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 11 deletions

View File

@ -133,6 +133,10 @@ class SamsungTVBridge(ABC):
async def async_send_keys(self, keys: list[str]) -> None: async def async_send_keys(self, keys: list[str]) -> None:
"""Send a list of keys to the tv.""" """Send a list of keys to the tv."""
@abstractmethod
async def async_power_off(self) -> None:
"""Send power off command to remote."""
@abstractmethod @abstractmethod
async def async_close_remote(self) -> None: async def async_close_remote(self) -> None:
"""Close remote object.""" """Close remote object."""
@ -269,6 +273,12 @@ class SamsungTVLegacyBridge(SamsungTVBridge):
# Different reasons, e.g. hostname not resolveable # Different reasons, e.g. hostname not resolveable
pass pass
async def async_power_off(self) -> None:
"""Send power off command to remote."""
await self.async_send_keys(["KEY_POWEROFF"])
# Force closing of remote session to provide instant UI feedback
await self.async_close_remote()
async def async_close_remote(self) -> None: async def async_close_remote(self) -> None:
"""Close remote object.""" """Close remote object."""
await self.hass.async_add_executor_job(self._close_remote) await self.hass.async_add_executor_job(self._close_remote)
@ -402,12 +412,7 @@ class SamsungTVWSBridge(SamsungTVBridge):
async def async_send_keys(self, keys: list[str]) -> None: async def async_send_keys(self, keys: list[str]) -> None:
"""Send a list of keys using websocket protocol.""" """Send a list of keys using websocket protocol."""
commands: list[SamsungTVCommand] = [] await self._async_send_commands([SendRemoteKey.click(key) for key in keys])
for key in keys:
if key == "KEY_POWEROFF":
key = "KEY_POWER"
commands.append(SendRemoteKey.click(key))
await self._async_send_commands(commands)
async def _async_send_commands(self, commands: list[SamsungTVCommand]) -> None: async def _async_send_commands(self, commands: list[SamsungTVCommand]) -> None:
"""Send the commands using websocket protocol.""" """Send the commands using websocket protocol."""
@ -485,6 +490,15 @@ class SamsungTVWSBridge(SamsungTVBridge):
self._notify_new_token_callback() self._notify_new_token_callback()
return self._remote return self._remote
async def async_power_off(self) -> None:
"""Send power off command to remote."""
if self._get_device_spec("FrameTVSupport") == "true":
await self._async_send_commands(SendRemoteKey.hold("KEY_POWER", 3))
else:
await self._async_send_commands([SendRemoteKey.click("KEY_POWER")])
# Force closing of remote session to provide instant UI feedback
await self.async_close_remote()
async def async_close_remote(self) -> None: async def async_close_remote(self) -> None:
"""Close remote object.""" """Close remote object."""
try: try:

View File

@ -208,10 +208,7 @@ class SamsungTVDevice(MediaPlayerEntity):
async def async_turn_off(self) -> None: async def async_turn_off(self) -> None:
"""Turn off media player.""" """Turn off media player."""
self._end_of_power_off = dt_util.utcnow() + SCAN_INTERVAL_PLUS_OFF_TIME self._end_of_power_off = dt_util.utcnow() + SCAN_INTERVAL_PLUS_OFF_TIME
await self._bridge.async_power_off()
await self._async_send_keys(["KEY_POWEROFF"])
# Force closing of remote session to provide instant UI feedback
await self._bridge.async_close_remote()
async def async_volume_up(self) -> None: async def async_volume_up(self) -> None:
"""Volume up the media player.""" """Volume up the media player."""

View File

@ -7,6 +7,7 @@ from unittest.mock import DEFAULT as DEFAULT_MOCK, AsyncMock, Mock, call, patch
import pytest import pytest
from samsungctl import exceptions from samsungctl import exceptions
from samsungtvws.async_remote import SamsungTVWSAsyncRemote from samsungtvws.async_remote import SamsungTVWSAsyncRemote
from samsungtvws.command import SamsungTVSleepCommand
from samsungtvws.exceptions import ConnectionFailure, HttpApiError from samsungtvws.exceptions import ConnectionFailure, HttpApiError
from samsungtvws.remote import ChannelEmitCommand, SendRemoteKey from samsungtvws.remote import ChannelEmitCommand, SendRemoteKey
from websockets.exceptions import WebSocketException from websockets.exceptions import WebSocketException
@ -63,7 +64,7 @@ from homeassistant.helpers.typing import ConfigType
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from .const import SAMPLE_APP_LIST from .const import SAMPLE_APP_LIST, SAMPLE_DEVICE_INFO_FRAME
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
@ -660,6 +661,37 @@ async def test_turn_off_websocket(
remotews.send_command.assert_not_called() remotews.send_command.assert_not_called()
async def test_turn_off_websocket_frame(
hass: HomeAssistant, remotews: Mock, rest_api: Mock
) -> None:
"""Test for turn_off."""
rest_api.rest_device_info.return_value = SAMPLE_DEVICE_INFO_FRAME
with patch(
"homeassistant.components.samsungtv.bridge.Remote",
side_effect=[OSError("Boom"), DEFAULT_MOCK],
):
await setup_samsungtv(hass, MOCK_CONFIGWS)
remotews.send_command.reset_mock()
assert await hass.services.async_call(
DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: ENTITY_ID}, True
)
# key called
assert remotews.send_command.call_count == 3
command = remotews.send_command.call_args_list[0].args[0]
assert isinstance(command, SendRemoteKey)
assert command.params["Cmd"] == "Press"
assert command.params["DataOfCmd"] == "KEY_POWER"
command = remotews.send_command.call_args_list[1].args[0]
assert isinstance(command, SamsungTVSleepCommand)
assert command.delay == 3
command = remotews.send_command.call_args_list[2].args[0]
assert isinstance(command, SendRemoteKey)
assert command.params["Cmd"] == "Release"
assert command.params["DataOfCmd"] == "KEY_POWER"
async def test_turn_off_legacy(hass: HomeAssistant, remote: Mock) -> None: async def test_turn_off_legacy(hass: HomeAssistant, remote: Mock) -> None:
"""Test for turn_off.""" """Test for turn_off."""
await setup_samsungtv(hass, MOCK_CONFIG_NOTURNON) await setup_samsungtv(hass, MOCK_CONFIG_NOTURNON)