mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 19:27:45 +00:00
Refactor run app in SamsungTV (#67616)
Co-authored-by: epenet <epenet@users.noreply.github.com>
This commit is contained in:
parent
acd906dfab
commit
c5f7e7d1b0
@ -11,6 +11,7 @@ from samsungctl import Remote
|
|||||||
from samsungctl.exceptions import AccessDenied, ConnectionClosed, UnhandledResponse
|
from samsungctl.exceptions import AccessDenied, ConnectionClosed, UnhandledResponse
|
||||||
from samsungtvws.async_remote import SamsungTVWSAsyncRemote
|
from samsungtvws.async_remote import SamsungTVWSAsyncRemote
|
||||||
from samsungtvws.async_rest import SamsungTVAsyncRest
|
from samsungtvws.async_rest import SamsungTVAsyncRest
|
||||||
|
from samsungtvws.command import SamsungTVCommand
|
||||||
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
|
||||||
@ -128,7 +129,7 @@ class SamsungTVBridge(ABC):
|
|||||||
"""Tells if the TV is on."""
|
"""Tells if the TV is on."""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def async_send_key(self, key: str, key_type: str | None = None) -> None:
|
async def async_send_key(self, key: str) -> None:
|
||||||
"""Send a key to the tv and handles exceptions."""
|
"""Send a key to the tv and handles exceptions."""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@ -237,7 +238,7 @@ class SamsungTVLegacyBridge(SamsungTVBridge):
|
|||||||
pass
|
pass
|
||||||
return self._remote
|
return self._remote
|
||||||
|
|
||||||
async def async_send_key(self, key: str, key_type: str | None = None) -> None:
|
async def async_send_key(self, key: str) -> None:
|
||||||
"""Send the key using legacy protocol."""
|
"""Send the key using legacy protocol."""
|
||||||
await self.hass.async_add_executor_job(self._send_key, key)
|
await self.hass.async_add_executor_job(self._send_key, key)
|
||||||
|
|
||||||
@ -388,22 +389,25 @@ class SamsungTVWSBridge(SamsungTVBridge):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def async_send_key(self, key: str, key_type: str | None = None) -> None:
|
async def async_launch_app(self, app_id: str) -> None:
|
||||||
|
"""Send the launch_app command using websocket protocol."""
|
||||||
|
await self._async_send_command(ChannelEmitCommand.launch_app(app_id))
|
||||||
|
|
||||||
|
async def async_send_key(self, key: str) -> None:
|
||||||
"""Send the key using websocket protocol."""
|
"""Send the key using websocket protocol."""
|
||||||
if key == "KEY_POWEROFF":
|
if key == "KEY_POWEROFF":
|
||||||
key = "KEY_POWER"
|
key = "KEY_POWER"
|
||||||
|
await self._async_send_command(SendRemoteKey.click(key))
|
||||||
|
|
||||||
|
async def _async_send_command(self, command: SamsungTVCommand) -> None:
|
||||||
|
"""Send the commands using websocket protocol."""
|
||||||
try:
|
try:
|
||||||
# recreate connection if connection was dead
|
# recreate connection if connection was dead
|
||||||
retry_count = 1
|
retry_count = 1
|
||||||
for _ in range(retry_count + 1):
|
for _ in range(retry_count + 1):
|
||||||
try:
|
try:
|
||||||
if remote := await self._async_get_remote():
|
if remote := await self._async_get_remote():
|
||||||
if key_type == "run_app":
|
await remote.send_command(command)
|
||||||
await remote.send_command(
|
|
||||||
ChannelEmitCommand.launch_app(key)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await remote.send_command(SendRemoteKey.click(key))
|
|
||||||
break
|
break
|
||||||
except (
|
except (
|
||||||
BrokenPipeError,
|
BrokenPipeError,
|
||||||
|
@ -173,12 +173,20 @@ class SamsungTVDevice(MediaPlayerEntity):
|
|||||||
if self._app_list is not None:
|
if self._app_list is not None:
|
||||||
self._attr_source_list.extend(self._app_list)
|
self._attr_source_list.extend(self._app_list)
|
||||||
|
|
||||||
async def _async_send_key(self, key: str, key_type: str | None = None) -> None:
|
async def _async_launch_app(self, app_id: str) -> None:
|
||||||
|
"""Send launch_app to the tv."""
|
||||||
|
if self._power_off_in_progress():
|
||||||
|
LOGGER.info("TV is powering off, not sending launch_app command")
|
||||||
|
return
|
||||||
|
assert isinstance(self._bridge, SamsungTVWSBridge)
|
||||||
|
await self._bridge.async_launch_app(app_id)
|
||||||
|
|
||||||
|
async def _async_send_key(self, key: str) -> None:
|
||||||
"""Send a key to the tv and handles exceptions."""
|
"""Send a key to the tv and handles exceptions."""
|
||||||
if self._power_off_in_progress() and key != "KEY_POWEROFF":
|
if self._power_off_in_progress() and key != "KEY_POWEROFF":
|
||||||
LOGGER.info("TV is powering off, not sending command: %s", key)
|
LOGGER.info("TV is powering off, not sending key: %s", key)
|
||||||
return
|
return
|
||||||
await self._bridge.async_send_key(key, key_type)
|
await self._bridge.async_send_key(key)
|
||||||
|
|
||||||
def _power_off_in_progress(self) -> bool:
|
def _power_off_in_progress(self) -> bool:
|
||||||
return (
|
return (
|
||||||
@ -248,7 +256,7 @@ class SamsungTVDevice(MediaPlayerEntity):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Support changing a channel."""
|
"""Support changing a channel."""
|
||||||
if media_type == MEDIA_TYPE_APP:
|
if media_type == MEDIA_TYPE_APP:
|
||||||
await self._async_send_key(media_id, "run_app")
|
await self._async_launch_app(media_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
if media_type != MEDIA_TYPE_CHANNEL:
|
if media_type != MEDIA_TYPE_CHANNEL:
|
||||||
@ -284,7 +292,7 @@ class SamsungTVDevice(MediaPlayerEntity):
|
|||||||
async def async_select_source(self, source: str) -> None:
|
async def async_select_source(self, source: str) -> None:
|
||||||
"""Select input source."""
|
"""Select input source."""
|
||||||
if self._app_list and source in self._app_list:
|
if self._app_list and source in self._app_list:
|
||||||
await self._async_send_key(self._app_list[source], "run_app")
|
await self._async_launch_app(self._app_list[source])
|
||||||
return
|
return
|
||||||
|
|
||||||
if source in SOURCES:
|
if source in SOURCES:
|
||||||
|
@ -624,13 +624,16 @@ async def test_device_class(hass: HomeAssistant) -> None:
|
|||||||
assert state.attributes[ATTR_DEVICE_CLASS] is MediaPlayerDeviceClass.TV.value
|
assert state.attributes[ATTR_DEVICE_CLASS] is MediaPlayerDeviceClass.TV.value
|
||||||
|
|
||||||
|
|
||||||
async def test_turn_off_websocket(hass: HomeAssistant, remotews: Mock) -> None:
|
async def test_turn_off_websocket(
|
||||||
|
hass: HomeAssistant, remotews: Mock, caplog: pytest.LogCaptureFixture
|
||||||
|
) -> None:
|
||||||
"""Test for turn_off."""
|
"""Test for turn_off."""
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.samsungtv.bridge.Remote",
|
"homeassistant.components.samsungtv.bridge.Remote",
|
||||||
side_effect=[OSError("Boom"), DEFAULT_MOCK],
|
side_effect=[OSError("Boom"), DEFAULT_MOCK],
|
||||||
):
|
):
|
||||||
await setup_samsungtv(hass, MOCK_CONFIGWS)
|
await setup_samsungtv(hass, MOCK_CONFIGWS)
|
||||||
|
|
||||||
remotews.send_command.reset_mock()
|
remotews.send_command.reset_mock()
|
||||||
|
|
||||||
assert await hass.services.async_call(
|
assert await hass.services.async_call(
|
||||||
@ -642,11 +645,20 @@ async def test_turn_off_websocket(hass: HomeAssistant, remotews: Mock) -> None:
|
|||||||
assert isinstance(command, SendRemoteKey)
|
assert isinstance(command, SendRemoteKey)
|
||||||
assert command.params["DataOfCmd"] == "KEY_POWER"
|
assert command.params["DataOfCmd"] == "KEY_POWER"
|
||||||
|
|
||||||
|
# commands not sent : power off in progress
|
||||||
|
remotews.send_command.reset_mock()
|
||||||
assert await hass.services.async_call(
|
assert await hass.services.async_call(
|
||||||
DOMAIN, SERVICE_VOLUME_UP, {ATTR_ENTITY_ID: ENTITY_ID}, True
|
DOMAIN, SERVICE_VOLUME_UP, {ATTR_ENTITY_ID: ENTITY_ID}, True
|
||||||
)
|
)
|
||||||
# key not called
|
assert "TV is powering off, not sending key: KEY_VOLUP" in caplog.text
|
||||||
assert remotews.send_command.call_count == 1
|
assert await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_SELECT_SOURCE,
|
||||||
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_INPUT_SOURCE: "Deezer"},
|
||||||
|
True,
|
||||||
|
)
|
||||||
|
assert "TV is powering off, not sending launch_app command" in caplog.text
|
||||||
|
remotews.send_command.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
async def test_turn_off_legacy(hass: HomeAssistant, remote: Mock) -> None:
|
async def test_turn_off_legacy(hass: HomeAssistant, remote: Mock) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user