Some Sonos fixes (#35115)

This commit is contained in:
Anders Melchiorsen 2020-05-04 20:22:47 +02:00 committed by GitHub
parent ee07fac9bc
commit b3e637ca7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 18 deletions

View File

@ -3,7 +3,7 @@
"name": "Sonos", "name": "Sonos",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/sonos", "documentation": "https://www.home-assistant.io/integrations/sonos",
"requirements": ["pysonos==0.0.25"], "requirements": ["pysonos==0.0.28"],
"ssdp": [ "ssdp": [
{ {
"st": "urn:schemas-upnp-org:device:ZonePlayer:1" "st": "urn:schemas-upnp-org:device:ZonePlayer:1"

View File

@ -31,7 +31,13 @@ from homeassistant.components.media_player.const import (
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_MUTE,
SUPPORT_VOLUME_SET, SUPPORT_VOLUME_SET,
) )
from homeassistant.const import ATTR_TIME, STATE_IDLE, STATE_PAUSED, STATE_PLAYING from homeassistant.const import (
ATTR_TIME,
EVENT_HOMEASSISTANT_STOP,
STATE_IDLE,
STATE_PAUSED,
STATE_PLAYING,
)
from homeassistant.core import ServiceCall, callback from homeassistant.core import ServiceCall, callback
from homeassistant.helpers import config_validation as cv, entity_platform, service from homeassistant.helpers import config_validation as cv, entity_platform, service
from homeassistant.util.dt import utcnow from homeassistant.util.dt import utcnow
@ -99,11 +105,13 @@ UNAVAILABLE_VALUES = {"", "NOT_IMPLEMENTED", None}
class SonosData: class SonosData:
"""Storage class for platform global data.""" """Storage class for platform global data."""
def __init__(self, hass): def __init__(self):
"""Initialize the data.""" """Initialize the data."""
self.entities = [] self.entities = []
self.discovered = [] self.discovered = []
self.topology_condition = asyncio.Condition() self.topology_condition = asyncio.Condition()
self.discovery_thread = None
self.hosts_heartbeat = None
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
@ -116,7 +124,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities): async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up Sonos from a config entry.""" """Set up Sonos from a config entry."""
if DATA_SONOS not in hass.data: if DATA_SONOS not in hass.data:
hass.data[DATA_SONOS] = SonosData(hass) hass.data[DATA_SONOS] = SonosData()
config = hass.data[SONOS_DOMAIN].get("media_player", {}) config = hass.data[SONOS_DOMAIN].get("media_player", {})
_LOGGER.debug("Reached async_setup_entry, config=%s", config) _LOGGER.debug("Reached async_setup_entry, config=%s", config)
@ -125,6 +133,15 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
if advertise_addr: if advertise_addr:
pysonos.config.EVENT_ADVERTISE_IP = advertise_addr pysonos.config.EVENT_ADVERTISE_IP = advertise_addr
def _stop_discovery(event):
data = hass.data[DATA_SONOS]
if data.discovery_thread:
data.discovery_thread.stop()
data.discovery_thread = None
if data.hosts_heartbeat:
data.hosts_heartbeat()
data.hosts_heartbeat = None
def _discovery(now=None): def _discovery(now=None):
"""Discover players from network or configuration.""" """Discover players from network or configuration."""
hosts = config.get(CONF_HOSTS) hosts = config.get(CONF_HOSTS)
@ -162,10 +179,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
_LOGGER.warning("Failed to initialize '%s'", host) _LOGGER.warning("Failed to initialize '%s'", host)
_LOGGER.debug("Tested all hosts") _LOGGER.debug("Tested all hosts")
hass.helpers.event.call_later(DISCOVERY_INTERVAL, _discovery) hass.data[DATA_SONOS].hosts_heartbeat = hass.helpers.event.call_later(
DISCOVERY_INTERVAL, _discovery
)
else: else:
_LOGGER.debug("Starting discovery thread") _LOGGER.debug("Starting discovery thread")
pysonos.discover_thread( hass.data[DATA_SONOS].discovery_thread = pysonos.discover_thread(
_discovered_player, _discovered_player,
interval=DISCOVERY_INTERVAL, interval=DISCOVERY_INTERVAL,
interface_addr=config.get(CONF_INTERFACE_ADDR), interface_addr=config.get(CONF_INTERFACE_ADDR),
@ -173,6 +192,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
_LOGGER.debug("Adding discovery job") _LOGGER.debug("Adding discovery job")
hass.async_add_executor_job(_discovery) hass.async_add_executor_job(_discovery)
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _stop_discovery)
platform = entity_platform.current_platform.get() platform = entity_platform.current_platform.get()
@ -639,17 +659,14 @@ class SonosEntity(MediaPlayerEntity):
def update_media_music(self, update_media_position, track_info): def update_media_music(self, update_media_position, track_info):
"""Update state when playing music tracks.""" """Update state when playing music tracks."""
self._media_duration = _timespan_secs(track_info.get("duration")) self._media_duration = _timespan_secs(track_info.get("duration"))
current_position = _timespan_secs(track_info.get("position"))
position_info = self.soco.avTransport.GetPositionInfo(
[("InstanceID", 0), ("Channel", "Master")]
)
rel_time = _timespan_secs(position_info.get("RelTime"))
# player started reporting position? # player started reporting position?
update_media_position |= rel_time is not None and self._media_position is None if current_position is not None and self._media_position is None:
update_media_position = True
# position jumped? # position jumped?
if rel_time is not None and self._media_position is not None: if current_position is not None and self._media_position is not None:
if self.state == STATE_PLAYING: if self.state == STATE_PLAYING:
time_diff = utcnow() - self._media_position_updated_at time_diff = utcnow() - self._media_position_updated_at
time_diff = time_diff.total_seconds() time_diff = time_diff.total_seconds()
@ -658,12 +675,13 @@ class SonosEntity(MediaPlayerEntity):
calculated_position = self._media_position + time_diff calculated_position = self._media_position + time_diff
update_media_position |= abs(calculated_position - rel_time) > 1.5 if abs(calculated_position - current_position) > 1.5:
update_media_position = True
if rel_time is None: if current_position is None:
self._clear_media_position() self._clear_media_position()
elif update_media_position: elif update_media_position:
self._media_position = rel_time self._media_position = current_position
self._media_position_updated_at = utcnow() self._media_position_updated_at = utcnow()
self._media_image_url = track_info.get("album_art") self._media_image_url = track_info.get("album_art")

View File

@ -1584,7 +1584,7 @@ pysnmp==4.4.12
pysoma==0.0.10 pysoma==0.0.10
# homeassistant.components.sonos # homeassistant.components.sonos
pysonos==0.0.25 pysonos==0.0.28
# homeassistant.components.spc # homeassistant.components.spc
pyspcwebgw==0.4.0 pyspcwebgw==0.4.0

View File

@ -644,7 +644,7 @@ pysmartthings==0.7.1
pysoma==0.0.10 pysoma==0.0.10
# homeassistant.components.sonos # homeassistant.components.sonos
pysonos==0.0.25 pysonos==0.0.28
# homeassistant.components.spc # homeassistant.components.spc
pyspcwebgw==0.4.0 pyspcwebgw==0.4.0