mirror of
https://github.com/home-assistant/core.git
synced 2025-07-09 22:37:11 +00:00
Squeezebox dispatch helper (#37030)
This commit is contained in:
parent
a798b508bc
commit
f7325a7d35
@ -1,55 +1,18 @@
|
||||
"""The Logitech Squeezebox integration."""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from pysqueezebox import async_discover
|
||||
|
||||
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_DISCOVERY, ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_START
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import DOMAIN, ENTRY_PLAYERS, KNOWN_PLAYERS, PLAYER_DISCOVERY_UNSUB
|
||||
from .const import DISCOVERY_TASK, DOMAIN, PLAYER_DISCOVERY_UNSUB
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DISCOVERY_TASK = "discovery_task"
|
||||
|
||||
|
||||
async def start_server_discovery(hass):
|
||||
"""Start a server discovery task."""
|
||||
|
||||
def _discovered_server(server):
|
||||
asyncio.create_task(
|
||||
hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_DISCOVERY},
|
||||
data={
|
||||
CONF_HOST: server.host,
|
||||
CONF_PORT: int(server.port),
|
||||
"uuid": server.uuid,
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
if DISCOVERY_TASK not in hass.data[DOMAIN]:
|
||||
_LOGGER.debug("Adding server discovery task for squeezebox")
|
||||
hass.data[DOMAIN][DISCOVERY_TASK] = hass.async_create_task(
|
||||
async_discover(_discovered_server)
|
||||
)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict):
|
||||
"""Set up the Logitech Squeezebox component."""
|
||||
if hass.is_running:
|
||||
asyncio.create_task(start_server_discovery(hass))
|
||||
else:
|
||||
hass.bus.async_listen_once(
|
||||
EVENT_HOMEASSISTANT_START, start_server_discovery(hass)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@ -66,13 +29,6 @@ async def async_unload_entry(hass, entry):
|
||||
# Stop player discovery task for this config entry.
|
||||
hass.data[DOMAIN][entry.entry_id][PLAYER_DISCOVERY_UNSUB]()
|
||||
|
||||
# Remove config entry's players from list of known players
|
||||
entry_players = hass.data[DOMAIN][entry.entry_id][ENTRY_PLAYERS]
|
||||
if entry_players:
|
||||
for player in entry_players:
|
||||
_LOGGER.debug("Remove entry player %s from list of known players.", player)
|
||||
hass.data[DOMAIN][KNOWN_PLAYERS].remove(player)
|
||||
|
||||
# Remove stored data for this config entry
|
||||
hass.data[DOMAIN].pop(entry.entry_id)
|
||||
|
||||
|
@ -150,12 +150,11 @@ class SqueezeboxConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
errors = {}
|
||||
if user_input:
|
||||
error = await self._validate_input(user_input)
|
||||
if error:
|
||||
errors["base"] = error
|
||||
else:
|
||||
if not error:
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_HOST], data=user_input
|
||||
)
|
||||
errors["base"] = error
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="edit", data_schema=self.data_schema, errors=errors
|
||||
|
@ -3,4 +3,5 @@ DOMAIN = "squeezebox"
|
||||
ENTRY_PLAYERS = "entry_players"
|
||||
KNOWN_PLAYERS = "known_players"
|
||||
PLAYER_DISCOVERY_UNSUB = "player_discovery_unsub"
|
||||
DISCOVERY_TASK = "discovery_task"
|
||||
DEFAULT_PORT = 9000
|
||||
|
@ -2,7 +2,7 @@
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from pysqueezebox import Server
|
||||
from pysqueezebox import Server, async_discover
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
@ -23,6 +23,7 @@ from homeassistant.components.media_player.const import (
|
||||
SUPPORT_VOLUME_MUTE,
|
||||
SUPPORT_VOLUME_SET,
|
||||
)
|
||||
from homeassistant.config_entries import SOURCE_DISCOVERY
|
||||
from homeassistant.const import (
|
||||
ATTR_COMMAND,
|
||||
CONF_HOST,
|
||||
@ -34,17 +35,20 @@ from homeassistant.const import (
|
||||
STATE_OFF,
|
||||
STATE_PAUSED,
|
||||
STATE_PLAYING,
|
||||
STATE_UNAVAILABLE,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.dispatcher import (
|
||||
async_dispatcher_connect,
|
||||
async_dispatcher_send,
|
||||
)
|
||||
from homeassistant.util.dt import utcnow
|
||||
|
||||
from .__init__ import start_server_discovery
|
||||
from .const import (
|
||||
DEFAULT_PORT,
|
||||
DISCOVERY_TASK,
|
||||
DOMAIN,
|
||||
ENTRY_PLAYERS,
|
||||
KNOWN_PLAYERS,
|
||||
PLAYER_DISCOVERY_UNSUB,
|
||||
)
|
||||
@ -57,6 +61,8 @@ SERVICE_UNSYNC = "unsync"
|
||||
ATTR_QUERY_RESULT = "query_result"
|
||||
ATTR_SYNC_GROUP = "sync_group"
|
||||
|
||||
SIGNAL_PLAYER_REDISCOVERED = "squeezebox_player_rediscovered"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DISCOVERY_INTERVAL = 60
|
||||
@ -107,6 +113,30 @@ SQUEEZEBOX_MODE = {
|
||||
}
|
||||
|
||||
|
||||
async def start_server_discovery(hass):
|
||||
"""Start a server discovery task."""
|
||||
|
||||
def _discovered_server(server):
|
||||
asyncio.create_task(
|
||||
hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_DISCOVERY},
|
||||
data={
|
||||
CONF_HOST: server.host,
|
||||
CONF_PORT: int(server.port),
|
||||
"uuid": server.uuid,
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
if DISCOVERY_TASK not in hass.data[DOMAIN]:
|
||||
_LOGGER.debug("Adding server discovery task for squeezebox")
|
||||
hass.data[DOMAIN][DISCOVERY_TASK] = hass.async_create_task(
|
||||
async_discover(_discovered_server)
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||
"""Set up squeezebox platform from platform entry in configuration.yaml (deprecated)."""
|
||||
|
||||
@ -129,13 +159,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
hass.data[DOMAIN].setdefault(config_entry.entry_id, {})
|
||||
|
||||
known_players = hass.data[DOMAIN].get(KNOWN_PLAYERS)
|
||||
if known_players is None:
|
||||
hass.data[DOMAIN][KNOWN_PLAYERS] = known_players = []
|
||||
|
||||
entry_players = hass.data[DOMAIN][config_entry.entry_id].setdefault(
|
||||
ENTRY_PLAYERS, []
|
||||
)
|
||||
known_players = hass.data[DOMAIN].setdefault(KNOWN_PLAYERS, [])
|
||||
|
||||
_LOGGER.debug("Creating LMS object for %s", host)
|
||||
lms = Server(async_get_clientsession(hass), host, port, username, password)
|
||||
@ -153,15 +177,16 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
),
|
||||
None,
|
||||
)
|
||||
if entity and not entity.available:
|
||||
# check if previously unavailable player has connected
|
||||
if entity:
|
||||
await player.async_update()
|
||||
entity.available = player.connected
|
||||
async_dispatcher_send(
|
||||
hass, SIGNAL_PLAYER_REDISCOVERED, player.player_id, player.connected
|
||||
)
|
||||
|
||||
if not entity:
|
||||
_LOGGER.debug("Adding new entity: %s", player)
|
||||
entity = SqueezeBoxEntity(player)
|
||||
known_players.append(entity)
|
||||
entry_players.append(entity)
|
||||
async_add_entities([entity])
|
||||
|
||||
players = await lms.async_get_players()
|
||||
@ -227,6 +252,7 @@ class SqueezeBoxEntity(MediaPlayerEntity):
|
||||
self._last_update = None
|
||||
self._query_result = {}
|
||||
self._available = True
|
||||
self._remove_dispatcher = None
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
@ -254,16 +280,17 @@ class SqueezeBoxEntity(MediaPlayerEntity):
|
||||
"""Return True if device connected to LMS server."""
|
||||
return self._available
|
||||
|
||||
@available.setter
|
||||
def available(self, val):
|
||||
"""Set available to True or False."""
|
||||
self._available = bool(val)
|
||||
@callback
|
||||
def rediscovered(self, unique_id, connected):
|
||||
"""Make a player available again."""
|
||||
if unique_id == self.unique_id and connected:
|
||||
self._available = True
|
||||
_LOGGER.info("Player %s is available again", self.name)
|
||||
self._remove_dispatcher()
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the device."""
|
||||
if not self.available:
|
||||
return STATE_UNAVAILABLE
|
||||
if not self._player.power:
|
||||
return STATE_OFF
|
||||
if self._player.mode:
|
||||
@ -282,6 +309,15 @@ class SqueezeBoxEntity(MediaPlayerEntity):
|
||||
_LOGGER.info("Player %s is not available", self.name)
|
||||
self._available = False
|
||||
|
||||
# start listening for restored players
|
||||
self._remove_dispatcher = async_dispatcher_connect(
|
||||
self.hass, SIGNAL_PLAYER_REDISCOVERED, self.rediscovered
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self):
|
||||
"""Remove from list of known players when removed from hass."""
|
||||
self.hass.data[DOMAIN][KNOWN_PLAYERS].remove(self)
|
||||
|
||||
@property
|
||||
def volume_level(self):
|
||||
"""Volume level of the media player (0..1)."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user