mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Bluesound bugfix status 595 and await (#13727)
* 595 fix * Await fixes and last 595 fix * Lint * Made internal exception class * Fix lint issue
This commit is contained in:
parent
58f3690ef6
commit
b0fd2342db
@ -37,30 +37,30 @@ REQUIREMENTS = ['xmltodict==0.11.0']
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
STATE_GROUPED = 'grouped'
|
|
||||||
|
|
||||||
ATTR_MASTER = 'master'
|
ATTR_MASTER = 'master'
|
||||||
|
|
||||||
SERVICE_JOIN = 'bluesound_join'
|
|
||||||
SERVICE_UNJOIN = 'bluesound_unjoin'
|
|
||||||
SERVICE_SET_TIMER = 'bluesound_set_sleep_timer'
|
|
||||||
SERVICE_CLEAR_TIMER = 'bluesound_clear_sleep_timer'
|
|
||||||
|
|
||||||
DATA_BLUESOUND = 'bluesound'
|
DATA_BLUESOUND = 'bluesound'
|
||||||
DEFAULT_PORT = 11000
|
DEFAULT_PORT = 11000
|
||||||
|
|
||||||
SYNC_STATUS_INTERVAL = timedelta(minutes=5)
|
|
||||||
UPDATE_CAPTURE_INTERVAL = timedelta(minutes=30)
|
|
||||||
UPDATE_SERVICES_INTERVAL = timedelta(minutes=30)
|
|
||||||
UPDATE_PRESETS_INTERVAL = timedelta(minutes=30)
|
|
||||||
NODE_OFFLINE_CHECK_TIMEOUT = 180
|
NODE_OFFLINE_CHECK_TIMEOUT = 180
|
||||||
NODE_RETRY_INITIATION = timedelta(minutes=3)
|
NODE_RETRY_INITIATION = timedelta(minutes=3)
|
||||||
|
|
||||||
|
SERVICE_CLEAR_TIMER = 'bluesound_clear_sleep_timer'
|
||||||
|
SERVICE_JOIN = 'bluesound_join'
|
||||||
|
SERVICE_SET_TIMER = 'bluesound_set_sleep_timer'
|
||||||
|
SERVICE_UNJOIN = 'bluesound_unjoin'
|
||||||
|
STATE_GROUPED = 'grouped'
|
||||||
|
SYNC_STATUS_INTERVAL = timedelta(minutes=5)
|
||||||
|
|
||||||
|
UPDATE_CAPTURE_INTERVAL = timedelta(minutes=30)
|
||||||
|
UPDATE_PRESETS_INTERVAL = timedelta(minutes=30)
|
||||||
|
UPDATE_SERVICES_INTERVAL = timedelta(minutes=30)
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Optional(CONF_HOSTS): vol.All(cv.ensure_list, [{
|
vol.Optional(CONF_HOSTS): vol.All(cv.ensure_list, [{
|
||||||
vol.Required(CONF_HOST): cv.string,
|
vol.Required(CONF_HOST): cv.string,
|
||||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
|
||||||
vol.Optional(CONF_NAME): cv.string,
|
vol.Optional(CONF_NAME): cv.string,
|
||||||
|
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
||||||
}])
|
}])
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -131,8 +131,8 @@ def _add_player(hass, async_add_devices, host, port=None, name=None):
|
|||||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, _init_player)
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, _init_player)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(hass, config, async_add_devices,
|
async def async_setup_platform(
|
||||||
discovery_info=None):
|
hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Set up the Bluesound platforms."""
|
"""Set up the Bluesound platforms."""
|
||||||
if DATA_BLUESOUND not in hass.data:
|
if DATA_BLUESOUND not in hass.data:
|
||||||
hass.data[DATA_BLUESOUND] = []
|
hass.data[DATA_BLUESOUND] = []
|
||||||
@ -202,6 +202,9 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
if self.port is None:
|
if self.port is None:
|
||||||
self.port = DEFAULT_PORT
|
self.port = DEFAULT_PORT
|
||||||
|
|
||||||
|
class _TimeoutException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _try_get_index(string, search_string):
|
def _try_get_index(string, search_string):
|
||||||
"""Get the index."""
|
"""Get the index."""
|
||||||
@ -258,7 +261,8 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
while True:
|
while True:
|
||||||
await self.async_update_status()
|
await self.async_update_status()
|
||||||
|
|
||||||
except (asyncio.TimeoutError, ClientError):
|
except (asyncio.TimeoutError, ClientError,
|
||||||
|
BluesoundPlayer._TimeoutException):
|
||||||
_LOGGER.info("Node %s is offline, retrying later", self._name)
|
_LOGGER.info("Node %s is offline, retrying later", self._name)
|
||||||
await asyncio.sleep(
|
await asyncio.sleep(
|
||||||
NODE_OFFLINE_CHECK_TIMEOUT, loop=self._hass.loop)
|
NODE_OFFLINE_CHECK_TIMEOUT, loop=self._hass.loop)
|
||||||
@ -293,8 +297,8 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
self._retry_remove = async_track_time_interval(
|
self._retry_remove = async_track_time_interval(
|
||||||
self._hass, self.async_init, NODE_RETRY_INITIATION)
|
self._hass, self.async_init, NODE_RETRY_INITIATION)
|
||||||
except Exception:
|
except Exception:
|
||||||
_LOGGER.exception("Unexpected when initiating error in %s",
|
_LOGGER.exception(
|
||||||
self.host)
|
"Unexpected when initiating error in %s", self.host)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
@ -307,8 +311,8 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
await self.async_update_captures()
|
await self.async_update_captures()
|
||||||
await self.async_update_services()
|
await self.async_update_services()
|
||||||
|
|
||||||
async def send_bluesound_command(self, method, raise_timeout=False,
|
async def send_bluesound_command(
|
||||||
allow_offline=False):
|
self, method, raise_timeout=False, allow_offline=False):
|
||||||
"""Send command to the player."""
|
"""Send command to the player."""
|
||||||
import xmltodict
|
import xmltodict
|
||||||
|
|
||||||
@ -321,6 +325,7 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
|
|
||||||
_LOGGER.debug("Calling URL: %s", url)
|
_LOGGER.debug("Calling URL: %s", url)
|
||||||
response = None
|
response = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
websession = async_get_clientsession(self._hass)
|
websession = async_get_clientsession(self._hass)
|
||||||
with async_timeout.timeout(10, loop=self._hass.loop):
|
with async_timeout.timeout(10, loop=self._hass.loop):
|
||||||
@ -332,6 +337,9 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
data = None
|
data = None
|
||||||
else:
|
else:
|
||||||
data = xmltodict.parse(result)
|
data = xmltodict.parse(result)
|
||||||
|
elif response.status == 595:
|
||||||
|
_LOGGER.info("Status 595 returned, treating as timeout")
|
||||||
|
raise BluesoundPlayer._TimeoutException()
|
||||||
else:
|
else:
|
||||||
_LOGGER.error("Error %s on %s", response.status, url)
|
_LOGGER.error("Error %s on %s", response.status, url)
|
||||||
return None
|
return None
|
||||||
@ -366,13 +374,9 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
|
|
||||||
with async_timeout.timeout(125, loop=self._hass.loop):
|
with async_timeout.timeout(125, loop=self._hass.loop):
|
||||||
response = await self._polling_session.get(
|
response = await self._polling_session.get(
|
||||||
url,
|
url, headers={CONNECTION: KEEP_ALIVE})
|
||||||
headers={CONNECTION: KEEP_ALIVE})
|
|
||||||
|
|
||||||
if response.status != 200:
|
if response.status == 200:
|
||||||
_LOGGER.error("Error %s on %s. Trying one more time.",
|
|
||||||
response.status, url)
|
|
||||||
else:
|
|
||||||
result = await response.text()
|
result = await response.text()
|
||||||
self._is_online = True
|
self._is_online = True
|
||||||
self._last_status_update = dt_util.utcnow()
|
self._last_status_update = dt_util.utcnow()
|
||||||
@ -380,8 +384,8 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
|
|
||||||
group_name = self._status.get('groupName', None)
|
group_name = self._status.get('groupName', None)
|
||||||
if group_name != self._group_name:
|
if group_name != self._group_name:
|
||||||
_LOGGER.debug('Group name change detected on device: %s',
|
_LOGGER.debug(
|
||||||
self.host)
|
"Group name change detected on device: %s", self.host)
|
||||||
self._group_name = group_name
|
self._group_name = group_name
|
||||||
# the sleep is needed to make sure that the
|
# the sleep is needed to make sure that the
|
||||||
# devices is synced
|
# devices is synced
|
||||||
@ -398,14 +402,20 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
await self.force_update_sync_status()
|
await self.force_update_sync_status()
|
||||||
|
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
elif response.status == 595:
|
||||||
|
_LOGGER.info("Status 595 returned, treating as timeout")
|
||||||
|
raise BluesoundPlayer._TimeoutException()
|
||||||
|
else:
|
||||||
|
_LOGGER.error("Error %s on %s. Trying one more time",
|
||||||
|
response.status, url)
|
||||||
|
|
||||||
except (asyncio.TimeoutError, ClientError):
|
except (asyncio.TimeoutError, ClientError):
|
||||||
self._is_online = False
|
self._is_online = False
|
||||||
self._last_status_update = None
|
self._last_status_update = None
|
||||||
self._status = None
|
self._status = None
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
_LOGGER.info("Client connection error, marking %s as offline",
|
_LOGGER.info(
|
||||||
self._name)
|
"Client connection error, marking %s as offline", self._name)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
async def async_trigger_sync_on_all(self):
|
async def async_trigger_sync_on_all(self):
|
||||||
@ -416,8 +426,8 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
await player.force_update_sync_status()
|
await player.force_update_sync_status()
|
||||||
|
|
||||||
@Throttle(SYNC_STATUS_INTERVAL)
|
@Throttle(SYNC_STATUS_INTERVAL)
|
||||||
async def async_update_sync_status(self, on_updated_cb=None,
|
async def async_update_sync_status(
|
||||||
raise_timeout=False):
|
self, on_updated_cb=None, raise_timeout=False):
|
||||||
"""Update sync status."""
|
"""Update sync status."""
|
||||||
await self.force_update_sync_status(
|
await self.force_update_sync_status(
|
||||||
on_updated_cb, raise_timeout=False)
|
on_updated_cb, raise_timeout=False)
|
||||||
@ -465,7 +475,7 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
'image': item.get('@image', ''),
|
'image': item.get('@image', ''),
|
||||||
'is_raw_url': True,
|
'is_raw_url': True,
|
||||||
'url2': item.get('@url', ''),
|
'url2': item.get('@url', ''),
|
||||||
'url': 'Preset?id=' + item.get('@id', '')
|
'url': 'Preset?id={}'.format(item.get('@id', ''))
|
||||||
})
|
})
|
||||||
|
|
||||||
if 'presets' in resp and 'preset' in resp['presets']:
|
if 'presets' in resp and 'preset' in resp['presets']:
|
||||||
@ -503,11 +513,6 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
|
|
||||||
return self._services_items
|
return self._services_items
|
||||||
|
|
||||||
@property
|
|
||||||
def should_poll(self):
|
|
||||||
"""No need to poll information."""
|
|
||||||
return True
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_content_type(self):
|
def media_content_type(self):
|
||||||
"""Content type of current playing media."""
|
"""Content type of current playing media."""
|
||||||
@ -803,22 +808,22 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
|
|
||||||
async def async_add_slave(self, slave_device):
|
async def async_add_slave(self, slave_device):
|
||||||
"""Add slave to master."""
|
"""Add slave to master."""
|
||||||
return self.send_bluesound_command('/AddSlave?slave={}&port={}'
|
return await self.send_bluesound_command(
|
||||||
.format(slave_device.host,
|
'/AddSlave?slave={}&port={}'.format(
|
||||||
slave_device.port))
|
slave_device.host, slave_device.port))
|
||||||
|
|
||||||
async def async_remove_slave(self, slave_device):
|
async def async_remove_slave(self, slave_device):
|
||||||
"""Remove slave to master."""
|
"""Remove slave to master."""
|
||||||
return self.send_bluesound_command('/RemoveSlave?slave={}&port={}'
|
return await self.send_bluesound_command(
|
||||||
.format(slave_device.host,
|
'/RemoveSlave?slave={}&port={}'.format(
|
||||||
slave_device.port))
|
slave_device.host, slave_device.port))
|
||||||
|
|
||||||
async def async_increase_timer(self):
|
async def async_increase_timer(self):
|
||||||
"""Increase sleep time on player."""
|
"""Increase sleep time on player."""
|
||||||
sleep_time = await self.send_bluesound_command('/Sleep')
|
sleep_time = await self.send_bluesound_command('/Sleep')
|
||||||
if sleep_time is None:
|
if sleep_time is None:
|
||||||
_LOGGER.error('Error while increasing sleep time on player: %s',
|
_LOGGER.error(
|
||||||
self.host)
|
"Error while increasing sleep time on player: %s", self.host)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
return int(sleep_time.get('sleep', '0'))
|
return int(sleep_time.get('sleep', '0'))
|
||||||
@ -831,8 +836,9 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
|
|
||||||
async def async_set_shuffle(self, shuffle):
|
async def async_set_shuffle(self, shuffle):
|
||||||
"""Enable or disable shuffle mode."""
|
"""Enable or disable shuffle mode."""
|
||||||
return self.send_bluesound_command('/Shuffle?state={}'
|
value = '1' if shuffle else '0'
|
||||||
.format('1' if shuffle else '0'))
|
return await self.send_bluesound_command(
|
||||||
|
'/Shuffle?state={}'.format(value))
|
||||||
|
|
||||||
async def async_select_source(self, source):
|
async def async_select_source(self, source):
|
||||||
"""Select input source."""
|
"""Select input source."""
|
||||||
@ -856,14 +862,14 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
if 'is_raw_url' in selected_source and selected_source['is_raw_url']:
|
if 'is_raw_url' in selected_source and selected_source['is_raw_url']:
|
||||||
url = selected_source['url']
|
url = selected_source['url']
|
||||||
|
|
||||||
return self.send_bluesound_command(url)
|
return await self.send_bluesound_command(url)
|
||||||
|
|
||||||
async def async_clear_playlist(self):
|
async def async_clear_playlist(self):
|
||||||
"""Clear players playlist."""
|
"""Clear players playlist."""
|
||||||
if self.is_grouped and not self.is_master:
|
if self.is_grouped and not self.is_master:
|
||||||
return
|
return
|
||||||
|
|
||||||
return self.send_bluesound_command('Clear')
|
return await self.send_bluesound_command('Clear')
|
||||||
|
|
||||||
async def async_media_next_track(self):
|
async def async_media_next_track(self):
|
||||||
"""Send media_next command to media player."""
|
"""Send media_next command to media player."""
|
||||||
@ -877,7 +883,7 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
action['@name'] == 'skip'):
|
action['@name'] == 'skip'):
|
||||||
cmd = action['@url']
|
cmd = action['@url']
|
||||||
|
|
||||||
return self.send_bluesound_command(cmd)
|
return await self.send_bluesound_command(cmd)
|
||||||
|
|
||||||
async def async_media_previous_track(self):
|
async def async_media_previous_track(self):
|
||||||
"""Send media_previous command to media player."""
|
"""Send media_previous command to media player."""
|
||||||
@ -891,35 +897,36 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
action['@name'] == 'back'):
|
action['@name'] == 'back'):
|
||||||
cmd = action['@url']
|
cmd = action['@url']
|
||||||
|
|
||||||
return self.send_bluesound_command(cmd)
|
return await self.send_bluesound_command(cmd)
|
||||||
|
|
||||||
async def async_media_play(self):
|
async def async_media_play(self):
|
||||||
"""Send media_play command to media player."""
|
"""Send media_play command to media player."""
|
||||||
if self.is_grouped and not self.is_master:
|
if self.is_grouped and not self.is_master:
|
||||||
return
|
return
|
||||||
|
|
||||||
return self.send_bluesound_command('Play')
|
return await self.send_bluesound_command('Play')
|
||||||
|
|
||||||
async def async_media_pause(self):
|
async def async_media_pause(self):
|
||||||
"""Send media_pause command to media player."""
|
"""Send media_pause command to media player."""
|
||||||
if self.is_grouped and not self.is_master:
|
if self.is_grouped and not self.is_master:
|
||||||
return
|
return
|
||||||
|
|
||||||
return self.send_bluesound_command('Pause')
|
return await self.send_bluesound_command('Pause')
|
||||||
|
|
||||||
async def async_media_stop(self):
|
async def async_media_stop(self):
|
||||||
"""Send stop command."""
|
"""Send stop command."""
|
||||||
if self.is_grouped and not self.is_master:
|
if self.is_grouped and not self.is_master:
|
||||||
return
|
return
|
||||||
|
|
||||||
return self.send_bluesound_command('Pause')
|
return await self.send_bluesound_command('Pause')
|
||||||
|
|
||||||
async def async_media_seek(self, position):
|
async def async_media_seek(self, position):
|
||||||
"""Send media_seek command to media player."""
|
"""Send media_seek command to media player."""
|
||||||
if self.is_grouped and not self.is_master:
|
if self.is_grouped and not self.is_master:
|
||||||
return
|
return
|
||||||
|
|
||||||
return self.send_bluesound_command('Play?seek=' + str(float(position)))
|
return await self.send_bluesound_command(
|
||||||
|
'Play?seek={}'.format(float(position)))
|
||||||
|
|
||||||
async def async_play_media(self, media_type, media_id, **kwargs):
|
async def async_play_media(self, media_type, media_id, **kwargs):
|
||||||
"""
|
"""
|
||||||
@ -933,9 +940,9 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
url = 'Play?url={}'.format(media_id)
|
url = 'Play?url={}'.format(media_id)
|
||||||
|
|
||||||
if kwargs.get(ATTR_MEDIA_ENQUEUE):
|
if kwargs.get(ATTR_MEDIA_ENQUEUE):
|
||||||
return self.send_bluesound_command(url)
|
return await self.send_bluesound_command(url)
|
||||||
|
|
||||||
return self.send_bluesound_command(url)
|
return await self.send_bluesound_command(url)
|
||||||
|
|
||||||
async def async_volume_up(self):
|
async def async_volume_up(self):
|
||||||
"""Volume up the media player."""
|
"""Volume up the media player."""
|
||||||
@ -957,7 +964,7 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
volume = 0
|
volume = 0
|
||||||
elif volume > 1:
|
elif volume > 1:
|
||||||
volume = 1
|
volume = 1
|
||||||
return self.send_bluesound_command(
|
return await self.send_bluesound_command(
|
||||||
'Volume?level=' + str(float(volume) * 100))
|
'Volume?level=' + str(float(volume) * 100))
|
||||||
|
|
||||||
async def async_mute_volume(self, mute):
|
async def async_mute_volume(self, mute):
|
||||||
@ -966,7 +973,7 @@ class BluesoundPlayer(MediaPlayerDevice):
|
|||||||
volume = self.volume_level
|
volume = self.volume_level
|
||||||
if volume > 0:
|
if volume > 0:
|
||||||
self._lastvol = volume
|
self._lastvol = volume
|
||||||
return self.send_bluesound_command('Volume?level=0')
|
return await self.send_bluesound_command('Volume?level=0')
|
||||||
else:
|
else:
|
||||||
return self.send_bluesound_command(
|
return await self.send_bluesound_command(
|
||||||
'Volume?level=' + str(float(self._lastvol) * 100))
|
'Volume?level=' + str(float(self._lastvol) * 100))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user