mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Improve Roku (#34431)
This commit is contained in:
parent
7f77e99e4d
commit
6dd836589c
@ -10,7 +10,6 @@ from roku import RokuException
|
|||||||
from homeassistant.components.media_player import MediaPlayerDevice
|
from homeassistant.components.media_player import MediaPlayerDevice
|
||||||
from homeassistant.components.media_player.const import (
|
from homeassistant.components.media_player.const import (
|
||||||
MEDIA_TYPE_CHANNEL,
|
MEDIA_TYPE_CHANNEL,
|
||||||
MEDIA_TYPE_MOVIE,
|
|
||||||
SUPPORT_NEXT_TRACK,
|
SUPPORT_NEXT_TRACK,
|
||||||
SUPPORT_PLAY,
|
SUPPORT_PLAY,
|
||||||
SUPPORT_PLAY_MEDIA,
|
SUPPORT_PLAY_MEDIA,
|
||||||
@ -66,12 +65,7 @@ class RokuDevice(MediaPlayerDevice):
|
|||||||
self._power_state = self.roku.power_state
|
self._power_state = self.roku.power_state
|
||||||
self.ip_address = self.roku.host
|
self.ip_address = self.roku.host
|
||||||
self.channels = self.get_source_list()
|
self.channels = self.get_source_list()
|
||||||
|
|
||||||
if self.roku.current_app is not None:
|
|
||||||
self.current_app = self.roku.current_app
|
self.current_app = self.roku.current_app
|
||||||
else:
|
|
||||||
self.current_app = None
|
|
||||||
|
|
||||||
self._available = True
|
self._available = True
|
||||||
except (RequestsConnectionError, RequestsReadTimeout, RokuException):
|
except (RequestsConnectionError, RequestsReadTimeout, RokuException):
|
||||||
self._available = False
|
self._available = False
|
||||||
@ -90,6 +84,7 @@ class RokuDevice(MediaPlayerDevice):
|
|||||||
"""Return the name of the device."""
|
"""Return the name of the device."""
|
||||||
if self._device_info.user_device_name:
|
if self._device_info.user_device_name:
|
||||||
return self._device_info.user_device_name
|
return self._device_info.user_device_name
|
||||||
|
|
||||||
return f"Roku {self._device_info.serial_num}"
|
return f"Roku {self._device_info.serial_num}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -103,8 +98,10 @@ class RokuDevice(MediaPlayerDevice):
|
|||||||
|
|
||||||
if self.current_app.name == "Power Saver" or self.current_app.is_screensaver:
|
if self.current_app.name == "Power Saver" or self.current_app.is_screensaver:
|
||||||
return STATE_IDLE
|
return STATE_IDLE
|
||||||
|
|
||||||
if self.current_app.name == "Roku":
|
if self.current_app.name == "Roku":
|
||||||
return STATE_HOME
|
return STATE_HOME
|
||||||
|
|
||||||
if self.current_app.name is not None:
|
if self.current_app.name is not None:
|
||||||
return STATE_PLAYING
|
return STATE_PLAYING
|
||||||
|
|
||||||
@ -139,23 +136,17 @@ class RokuDevice(MediaPlayerDevice):
|
|||||||
@property
|
@property
|
||||||
def media_content_type(self):
|
def media_content_type(self):
|
||||||
"""Content type of current playing media."""
|
"""Content type of current playing media."""
|
||||||
if self.current_app is None:
|
if self.current_app is None or self.current_app.name in ("Power Saver", "Roku"):
|
||||||
return None
|
return None
|
||||||
if self.current_app.name == "Power Saver":
|
|
||||||
return None
|
return MEDIA_TYPE_CHANNEL
|
||||||
if self.current_app.name == "Roku":
|
|
||||||
return None
|
|
||||||
return MEDIA_TYPE_MOVIE
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_image_url(self):
|
def media_image_url(self):
|
||||||
"""Image url of current playing media."""
|
"""Image url of current playing media."""
|
||||||
if self.current_app is None:
|
if self.current_app is None or self.current_app.name in ("Power Saver", "Roku"):
|
||||||
return None
|
|
||||||
if self.current_app.name == "Roku":
|
|
||||||
return None
|
|
||||||
if self.current_app.name == "Power Saver":
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if self.current_app.id is None:
|
if self.current_app.id is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -233,12 +224,15 @@ class RokuDevice(MediaPlayerDevice):
|
|||||||
MEDIA_TYPE_CHANNEL,
|
MEDIA_TYPE_CHANNEL,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.current_app is not None:
|
if self.current_app is not None:
|
||||||
self.roku.launch(self.roku["tvinput.dtv"], {"ch": media_id})
|
self.roku.launch(self.roku["tvinput.dtv"], {"ch": media_id})
|
||||||
|
|
||||||
def select_source(self, source):
|
def select_source(self, source):
|
||||||
"""Select input source."""
|
"""Select input source."""
|
||||||
if self.current_app is not None:
|
if self.current_app is None:
|
||||||
|
return
|
||||||
|
|
||||||
if source == "Home":
|
if source == "Home":
|
||||||
self.roku.home()
|
self.roku.home()
|
||||||
else:
|
else:
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
"""Tests for the Roku Media Player platform."""
|
"""Tests for the Roku Media Player platform."""
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
from asynctest import PropertyMock, patch
|
from asynctest import PropertyMock, patch
|
||||||
|
from requests.exceptions import (
|
||||||
|
ConnectionError as RequestsConnectionError,
|
||||||
|
ReadTimeout as RequestsReadTimeout,
|
||||||
|
)
|
||||||
from requests_mock import Mocker
|
from requests_mock import Mocker
|
||||||
|
from roku import RokuException
|
||||||
|
|
||||||
from homeassistant.components.media_player.const import (
|
from homeassistant.components.media_player.const import (
|
||||||
ATTR_INPUT_SOURCE,
|
ATTR_INPUT_SOURCE,
|
||||||
@ -9,7 +16,6 @@ from homeassistant.components.media_player.const import (
|
|||||||
ATTR_MEDIA_VOLUME_MUTED,
|
ATTR_MEDIA_VOLUME_MUTED,
|
||||||
DOMAIN as MP_DOMAIN,
|
DOMAIN as MP_DOMAIN,
|
||||||
MEDIA_TYPE_CHANNEL,
|
MEDIA_TYPE_CHANNEL,
|
||||||
MEDIA_TYPE_MOVIE,
|
|
||||||
SERVICE_PLAY_MEDIA,
|
SERVICE_PLAY_MEDIA,
|
||||||
SERVICE_SELECT_SOURCE,
|
SERVICE_SELECT_SOURCE,
|
||||||
SUPPORT_NEXT_TRACK,
|
SUPPORT_NEXT_TRACK,
|
||||||
@ -32,11 +38,15 @@ from homeassistant.const import (
|
|||||||
SERVICE_VOLUME_DOWN,
|
SERVICE_VOLUME_DOWN,
|
||||||
SERVICE_VOLUME_MUTE,
|
SERVICE_VOLUME_MUTE,
|
||||||
SERVICE_VOLUME_UP,
|
SERVICE_VOLUME_UP,
|
||||||
|
STATE_HOME,
|
||||||
STATE_PLAYING,
|
STATE_PLAYING,
|
||||||
STATE_STANDBY,
|
STATE_STANDBY,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
|
from tests.common import async_fire_time_changed
|
||||||
from tests.components.roku import UPNP_SERIAL, setup_integration
|
from tests.components.roku import UPNP_SERIAL, setup_integration
|
||||||
|
|
||||||
MAIN_ENTITY_ID = f"{MP_DOMAIN}.my_roku_3"
|
MAIN_ENTITY_ID = f"{MP_DOMAIN}.my_roku_3"
|
||||||
@ -87,6 +97,47 @@ async def test_tv_setup(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
|||||||
assert tv.unique_id == TV_SERIAL
|
assert tv.unique_id == TV_SERIAL
|
||||||
|
|
||||||
|
|
||||||
|
async def test_availability(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
||||||
|
"""Test entity availability."""
|
||||||
|
now = dt_util.utcnow()
|
||||||
|
future = now + timedelta(minutes=1)
|
||||||
|
|
||||||
|
with patch("homeassistant.util.dt.utcnow", return_value=now):
|
||||||
|
await setup_integration(hass, requests_mock)
|
||||||
|
|
||||||
|
with patch("roku.Roku._get", side_effect=RokuException,), patch(
|
||||||
|
"homeassistant.util.dt.utcnow", return_value=future
|
||||||
|
):
|
||||||
|
async_fire_time_changed(hass, future)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get(MAIN_ENTITY_ID).state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
future += timedelta(minutes=1)
|
||||||
|
|
||||||
|
with patch("roku.Roku._get", side_effect=RequestsConnectionError,), patch(
|
||||||
|
"homeassistant.util.dt.utcnow", return_value=future
|
||||||
|
):
|
||||||
|
async_fire_time_changed(hass, future)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get(MAIN_ENTITY_ID).state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
future += timedelta(minutes=1)
|
||||||
|
|
||||||
|
with patch("roku.Roku._get", side_effect=RequestsReadTimeout,), patch(
|
||||||
|
"homeassistant.util.dt.utcnow", return_value=future
|
||||||
|
):
|
||||||
|
async_fire_time_changed(hass, future)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get(MAIN_ENTITY_ID).state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
future += timedelta(minutes=1)
|
||||||
|
|
||||||
|
with patch("homeassistant.util.dt.utcnow", return_value=future):
|
||||||
|
async_fire_time_changed(hass, future)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get(MAIN_ENTITY_ID).state == STATE_HOME
|
||||||
|
|
||||||
|
|
||||||
async def test_supported_features(
|
async def test_supported_features(
|
||||||
hass: HomeAssistantType, requests_mock: Mocker
|
hass: HomeAssistantType, requests_mock: Mocker
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -142,7 +193,7 @@ async def test_attributes(hass: HomeAssistantType, requests_mock: Mocker) -> Non
|
|||||||
await setup_integration(hass, requests_mock)
|
await setup_integration(hass, requests_mock)
|
||||||
|
|
||||||
state = hass.states.get(MAIN_ENTITY_ID)
|
state = hass.states.get(MAIN_ENTITY_ID)
|
||||||
assert state.state == "home"
|
assert state.state == STATE_HOME
|
||||||
|
|
||||||
assert state.attributes.get(ATTR_MEDIA_CONTENT_TYPE) is None
|
assert state.attributes.get(ATTR_MEDIA_CONTENT_TYPE) is None
|
||||||
assert state.attributes.get(ATTR_INPUT_SOURCE) == "Roku"
|
assert state.attributes.get(ATTR_INPUT_SOURCE) == "Roku"
|
||||||
@ -162,7 +213,7 @@ async def test_tv_attributes(hass: HomeAssistantType, requests_mock: Mocker) ->
|
|||||||
state = hass.states.get(TV_ENTITY_ID)
|
state = hass.states.get(TV_ENTITY_ID)
|
||||||
assert state.state == STATE_PLAYING
|
assert state.state == STATE_PLAYING
|
||||||
|
|
||||||
assert state.attributes.get(ATTR_MEDIA_CONTENT_TYPE) == MEDIA_TYPE_MOVIE
|
assert state.attributes.get(ATTR_MEDIA_CONTENT_TYPE) == MEDIA_TYPE_CHANNEL
|
||||||
assert state.attributes.get(ATTR_INPUT_SOURCE) == "Antenna TV"
|
assert state.attributes.get(ATTR_INPUT_SOURCE) == "Antenna TV"
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user