mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 02:37:08 +00:00
Revert cast platform polling mode (#14027)
This commit is contained in:
parent
5d3471269a
commit
7f634c6ed0
@ -288,8 +288,7 @@ class CastDevice(MediaPlayerDevice):
|
|||||||
self._chromecast = None # type: Optional[pychromecast.Chromecast]
|
self._chromecast = None # type: Optional[pychromecast.Chromecast]
|
||||||
self.cast_status = None
|
self.cast_status = None
|
||||||
self.media_status = None
|
self.media_status = None
|
||||||
self.media_status_position = None
|
self.media_status_received = None
|
||||||
self.media_status_position_received = None
|
|
||||||
self._available = False # type: bool
|
self._available = False # type: bool
|
||||||
self._status_listener = None # type: Optional[CastStatusListener]
|
self._status_listener = None # type: Optional[CastStatusListener]
|
||||||
|
|
||||||
@ -362,26 +361,10 @@ class CastDevice(MediaPlayerDevice):
|
|||||||
self._chromecast = None
|
self._chromecast = None
|
||||||
self.cast_status = None
|
self.cast_status = None
|
||||||
self.media_status = None
|
self.media_status = None
|
||||||
self.media_status_position = None
|
self.media_status_received = None
|
||||||
self.media_status_position_received = None
|
|
||||||
self._status_listener.invalidate()
|
self._status_listener.invalidate()
|
||||||
self._status_listener = None
|
self._status_listener = None
|
||||||
|
|
||||||
def update(self):
|
|
||||||
"""Periodically update the properties.
|
|
||||||
|
|
||||||
Even though we receive callbacks for most state changes, some 3rd party
|
|
||||||
apps don't always send them. Better poll every now and then if the
|
|
||||||
chromecast is active (i.e. an app is running).
|
|
||||||
"""
|
|
||||||
if not self._available:
|
|
||||||
# Not connected or not available.
|
|
||||||
return
|
|
||||||
|
|
||||||
if self._chromecast.media_controller.is_active:
|
|
||||||
# We can only update status if the media namespace is active
|
|
||||||
self._chromecast.media_controller.update_status()
|
|
||||||
|
|
||||||
# ========== Callbacks ==========
|
# ========== Callbacks ==========
|
||||||
def new_cast_status(self, cast_status):
|
def new_cast_status(self, cast_status):
|
||||||
"""Handle updates of the cast status."""
|
"""Handle updates of the cast status."""
|
||||||
@ -390,36 +373,8 @@ class CastDevice(MediaPlayerDevice):
|
|||||||
|
|
||||||
def new_media_status(self, media_status):
|
def new_media_status(self, media_status):
|
||||||
"""Handle updates of the media status."""
|
"""Handle updates of the media status."""
|
||||||
# Only use media position for playing/paused,
|
|
||||||
# and for normal playback rate
|
|
||||||
if (media_status is None or
|
|
||||||
abs(media_status.playback_rate - 1) > 0.01 or
|
|
||||||
not (media_status.player_is_playing or
|
|
||||||
media_status.player_is_paused)):
|
|
||||||
self.media_status_position = None
|
|
||||||
self.media_status_position_received = None
|
|
||||||
else:
|
|
||||||
# Avoid unnecessary state attribute updates if player_state and
|
|
||||||
# calculated position stay the same
|
|
||||||
now = dt_util.utcnow()
|
|
||||||
do_update = \
|
|
||||||
(self.media_status is None or
|
|
||||||
self.media_status_position is None or
|
|
||||||
self.media_status.player_state != media_status.player_state)
|
|
||||||
if not do_update:
|
|
||||||
if media_status.player_is_playing:
|
|
||||||
elapsed = now - self.media_status_position_received
|
|
||||||
do_update = abs(media_status.current_time -
|
|
||||||
(self.media_status_position +
|
|
||||||
elapsed.total_seconds())) > 1
|
|
||||||
else:
|
|
||||||
do_update = \
|
|
||||||
self.media_status_position != media_status.current_time
|
|
||||||
if do_update:
|
|
||||||
self.media_status_position = media_status.current_time
|
|
||||||
self.media_status_position_received = now
|
|
||||||
|
|
||||||
self.media_status = media_status
|
self.media_status = media_status
|
||||||
|
self.media_status_received = dt_util.utcnow()
|
||||||
self.schedule_update_ha_state()
|
self.schedule_update_ha_state()
|
||||||
|
|
||||||
def new_connection_status(self, connection_status):
|
def new_connection_status(self, connection_status):
|
||||||
@ -496,8 +451,8 @@ class CastDevice(MediaPlayerDevice):
|
|||||||
# ========== Properties ==========
|
# ========== Properties ==========
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
"""Polling needed for cast integration, see async_update."""
|
"""No polling needed."""
|
||||||
return True
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@ -625,7 +580,12 @@ class CastDevice(MediaPlayerDevice):
|
|||||||
@property
|
@property
|
||||||
def media_position(self):
|
def media_position(self):
|
||||||
"""Position of current playing media in seconds."""
|
"""Position of current playing media in seconds."""
|
||||||
return self.media_status_position
|
if self.media_status is None or \
|
||||||
|
not (self.media_status.player_is_playing or
|
||||||
|
self.media_status.player_is_paused or
|
||||||
|
self.media_status.player_is_idle):
|
||||||
|
return None
|
||||||
|
return self.media_status.current_time
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_position_updated_at(self):
|
def media_position_updated_at(self):
|
||||||
@ -633,7 +593,7 @@ class CastDevice(MediaPlayerDevice):
|
|||||||
|
|
||||||
Returns value from homeassistant.util.dt.utcnow().
|
Returns value from homeassistant.util.dt.utcnow().
|
||||||
"""
|
"""
|
||||||
return self.media_status_position_received
|
return self.media_status_received
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unique_id(self) -> Optional[str]:
|
def unique_id(self) -> Optional[str]:
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""The tests for the Cast Media player platform."""
|
"""The tests for the Cast Media player platform."""
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
import asyncio
|
import asyncio
|
||||||
import datetime as dt
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from unittest.mock import patch, MagicMock, Mock
|
from unittest.mock import patch, MagicMock, Mock
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
@ -15,8 +14,7 @@ from homeassistant.components.media_player.cast import ChromecastInfo
|
|||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect, \
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect, \
|
||||||
async_dispatcher_send
|
async_dispatcher_send
|
||||||
from homeassistant.components.media_player import cast, \
|
from homeassistant.components.media_player import cast
|
||||||
ATTR_MEDIA_POSITION, ATTR_MEDIA_POSITION_UPDATED_AT
|
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
|
|
||||||
@ -288,8 +286,6 @@ async def test_entity_media_states(hass: HomeAssistantType):
|
|||||||
assert entity.unique_id == full_info.uuid
|
assert entity.unique_id == full_info.uuid
|
||||||
|
|
||||||
media_status = MagicMock(images=None)
|
media_status = MagicMock(images=None)
|
||||||
media_status.current_time = 0
|
|
||||||
media_status.playback_rate = 1
|
|
||||||
media_status.player_is_playing = True
|
media_status.player_is_playing = True
|
||||||
entity.new_media_status(media_status)
|
entity.new_media_status(media_status)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@ -324,85 +320,6 @@ async def test_entity_media_states(hass: HomeAssistantType):
|
|||||||
assert state.state == 'unknown'
|
assert state.state == 'unknown'
|
||||||
|
|
||||||
|
|
||||||
async def test_entity_media_position(hass: HomeAssistantType):
|
|
||||||
"""Test various entity media states."""
|
|
||||||
info = get_fake_chromecast_info()
|
|
||||||
full_info = attr.evolve(info, model_name='google home',
|
|
||||||
friendly_name='Speaker', uuid=FakeUUID)
|
|
||||||
|
|
||||||
with patch('pychromecast.dial.get_device_status',
|
|
||||||
return_value=full_info):
|
|
||||||
chromecast, entity = await async_setup_media_player_cast(hass, info)
|
|
||||||
|
|
||||||
media_status = MagicMock(images=None)
|
|
||||||
media_status.current_time = 10
|
|
||||||
media_status.playback_rate = 1
|
|
||||||
media_status.player_is_playing = True
|
|
||||||
media_status.player_is_paused = False
|
|
||||||
media_status.player_is_idle = False
|
|
||||||
now = dt.datetime.now(dt.timezone.utc)
|
|
||||||
with patch('homeassistant.util.dt.utcnow', return_value=now):
|
|
||||||
entity.new_media_status(media_status)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
state = hass.states.get('media_player.speaker')
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION] == 10
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION_UPDATED_AT] == now
|
|
||||||
|
|
||||||
media_status.current_time = 15
|
|
||||||
now_plus_5 = now + dt.timedelta(seconds=5)
|
|
||||||
with patch('homeassistant.util.dt.utcnow', return_value=now_plus_5):
|
|
||||||
entity.new_media_status(media_status)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
state = hass.states.get('media_player.speaker')
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION] == 10
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION_UPDATED_AT] == now
|
|
||||||
|
|
||||||
media_status.current_time = 20
|
|
||||||
with patch('homeassistant.util.dt.utcnow', return_value=now_plus_5):
|
|
||||||
entity.new_media_status(media_status)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
state = hass.states.get('media_player.speaker')
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION] == 20
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION_UPDATED_AT] == now_plus_5
|
|
||||||
|
|
||||||
media_status.current_time = 25
|
|
||||||
now_plus_10 = now + dt.timedelta(seconds=10)
|
|
||||||
media_status.player_is_playing = False
|
|
||||||
media_status.player_is_paused = True
|
|
||||||
with patch('homeassistant.util.dt.utcnow', return_value=now_plus_10):
|
|
||||||
entity.new_media_status(media_status)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
state = hass.states.get('media_player.speaker')
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION] == 25
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION_UPDATED_AT] == now_plus_10
|
|
||||||
|
|
||||||
now_plus_15 = now + dt.timedelta(seconds=15)
|
|
||||||
with patch('homeassistant.util.dt.utcnow', return_value=now_plus_15):
|
|
||||||
entity.new_media_status(media_status)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
state = hass.states.get('media_player.speaker')
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION] == 25
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION_UPDATED_AT] == now_plus_10
|
|
||||||
|
|
||||||
media_status.current_time = 30
|
|
||||||
now_plus_20 = now + dt.timedelta(seconds=20)
|
|
||||||
with patch('homeassistant.util.dt.utcnow', return_value=now_plus_20):
|
|
||||||
entity.new_media_status(media_status)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
state = hass.states.get('media_player.speaker')
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION] == 30
|
|
||||||
assert state.attributes[ATTR_MEDIA_POSITION_UPDATED_AT] == now_plus_20
|
|
||||||
|
|
||||||
media_status.player_is_paused = False
|
|
||||||
media_status.player_is_idle = True
|
|
||||||
with patch('homeassistant.util.dt.utcnow', return_value=now_plus_20):
|
|
||||||
entity.new_media_status(media_status)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
state = hass.states.get('media_player.speaker')
|
|
||||||
assert ATTR_MEDIA_POSITION not in state.attributes
|
|
||||||
assert ATTR_MEDIA_POSITION_UPDATED_AT not in state.attributes
|
|
||||||
|
|
||||||
|
|
||||||
async def test_switched_host(hass: HomeAssistantType):
|
async def test_switched_host(hass: HomeAssistantType):
|
||||||
"""Test cast device listens for changed hosts and disconnects old cast."""
|
"""Test cast device listens for changed hosts and disconnects old cast."""
|
||||||
info = get_fake_chromecast_info()
|
info = get_fake_chromecast_info()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user