Revert cast platform polling mode (#14027)

This commit is contained in:
Otto Winter 2018-04-22 22:32:15 +02:00 committed by Paulus Schoutsen
parent 5d3471269a
commit 7f634c6ed0
2 changed files with 13 additions and 136 deletions

View File

@ -288,8 +288,7 @@ class CastDevice(MediaPlayerDevice):
self._chromecast = None # type: Optional[pychromecast.Chromecast]
self.cast_status = None
self.media_status = None
self.media_status_position = None
self.media_status_position_received = None
self.media_status_received = None
self._available = False # type: bool
self._status_listener = None # type: Optional[CastStatusListener]
@ -362,26 +361,10 @@ class CastDevice(MediaPlayerDevice):
self._chromecast = None
self.cast_status = None
self.media_status = None
self.media_status_position = None
self.media_status_position_received = None
self.media_status_received = None
self._status_listener.invalidate()
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 ==========
def new_cast_status(self, cast_status):
"""Handle updates of the cast status."""
@ -390,36 +373,8 @@ class CastDevice(MediaPlayerDevice):
def new_media_status(self, 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_received = dt_util.utcnow()
self.schedule_update_ha_state()
def new_connection_status(self, connection_status):
@ -496,8 +451,8 @@ class CastDevice(MediaPlayerDevice):
# ========== Properties ==========
@property
def should_poll(self):
"""Polling needed for cast integration, see async_update."""
return True
"""No polling needed."""
return False
@property
def name(self):
@ -625,7 +580,12 @@ class CastDevice(MediaPlayerDevice):
@property
def media_position(self):
"""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
def media_position_updated_at(self):
@ -633,7 +593,7 @@ class CastDevice(MediaPlayerDevice):
Returns value from homeassistant.util.dt.utcnow().
"""
return self.media_status_position_received
return self.media_status_received
@property
def unique_id(self) -> Optional[str]:

View File

@ -1,7 +1,6 @@
"""The tests for the Cast Media player platform."""
# pylint: disable=protected-access
import asyncio
import datetime as dt
from typing import Optional
from unittest.mock import patch, MagicMock, Mock
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.helpers.dispatcher import async_dispatcher_connect, \
async_dispatcher_send
from homeassistant.components.media_player import cast, \
ATTR_MEDIA_POSITION, ATTR_MEDIA_POSITION_UPDATED_AT
from homeassistant.components.media_player import cast
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
media_status = MagicMock(images=None)
media_status.current_time = 0
media_status.playback_rate = 1
media_status.player_is_playing = True
entity.new_media_status(media_status)
await hass.async_block_till_done()
@ -324,85 +320,6 @@ async def test_entity_media_states(hass: HomeAssistantType):
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):
"""Test cast device listens for changed hosts and disconnects old cast."""
info = get_fake_chromecast_info()