|
2 | 2 |
|
3 | 3 | from asyncio import timeout |
4 | 4 | from dataclasses import dataclass |
| 5 | +from datetime import datetime |
5 | 6 | import logging |
6 | 7 |
|
7 | | -from pysqueezebox import Server |
| 8 | +from pysqueezebox import Player, Server |
8 | 9 |
|
9 | 10 | from homeassistant.config_entries import ConfigEntry |
10 | 11 | from homeassistant.const import ( |
|
23 | 24 | DeviceEntryType, |
24 | 25 | format_mac, |
25 | 26 | ) |
| 27 | +from homeassistant.helpers.dispatcher import async_dispatcher_send |
| 28 | +from homeassistant.helpers.event import async_call_later |
26 | 29 |
|
27 | 30 | from .const import ( |
28 | 31 | CONF_HTTPS, |
| 32 | + DISCOVERY_INTERVAL, |
29 | 33 | DISCOVERY_TASK, |
30 | 34 | DOMAIN, |
| 35 | + KNOWN_PLAYERS, |
| 36 | + KNOWN_SERVERS, |
31 | 37 | MANUFACTURER, |
32 | 38 | SERVER_MODEL, |
| 39 | + SIGNAL_PLAYER_DISCOVERED, |
| 40 | + SIGNAL_PLAYER_REDISCOVERED, |
33 | 41 | STATUS_API_TIMEOUT, |
34 | 42 | STATUS_QUERY_LIBRARYNAME, |
35 | 43 | STATUS_QUERY_MAC, |
36 | 44 | STATUS_QUERY_UUID, |
37 | 45 | STATUS_QUERY_VERSION, |
38 | 46 | ) |
39 | | -from .coordinator import LMSStatusDataUpdateCoordinator |
| 47 | +from .coordinator import ( |
| 48 | + LMSStatusDataUpdateCoordinator, |
| 49 | + SqueezeBoxPlayerUpdateCoordinator, |
| 50 | +) |
40 | 51 |
|
41 | 52 | _LOGGER = logging.getLogger(__name__) |
42 | 53 |
|
@@ -117,15 +128,55 @@ async def async_setup_entry(hass: HomeAssistant, entry: SqueezeboxConfigEntry) - |
117 | 128 | ) |
118 | 129 | _LOGGER.debug("LMS Device %s", device) |
119 | 130 |
|
120 | | - coordinator = LMSStatusDataUpdateCoordinator(hass, lms) |
| 131 | + server_coordinator = LMSStatusDataUpdateCoordinator(hass, lms) |
121 | 132 |
|
122 | 133 | entry.runtime_data = SqueezeboxData( |
123 | | - coordinator=coordinator, |
| 134 | + coordinator=server_coordinator, |
124 | 135 | server=lms, |
125 | 136 | ) |
126 | 137 |
|
127 | | - await coordinator.async_config_entry_first_refresh() |
| 138 | + # set up player discovery |
| 139 | + known_servers = hass.data.setdefault(DOMAIN, {}).setdefault(KNOWN_SERVERS, {}) |
| 140 | + known_players = known_servers.setdefault(lms.uuid, {}).setdefault(KNOWN_PLAYERS, []) |
| 141 | + |
| 142 | + async def _player_discovery(now: datetime | None = None) -> None: |
| 143 | + """Discover squeezebox players by polling server.""" |
| 144 | + |
| 145 | + async def _discovered_player(player: Player) -> None: |
| 146 | + """Handle a (re)discovered player.""" |
| 147 | + if player.player_id in known_players: |
| 148 | + await player.async_update() |
| 149 | + async_dispatcher_send( |
| 150 | + hass, SIGNAL_PLAYER_REDISCOVERED, player.player_id, player.connected |
| 151 | + ) |
| 152 | + else: |
| 153 | + _LOGGER.debug("Adding new entity: %s", player) |
| 154 | + player_coordinator = SqueezeBoxPlayerUpdateCoordinator( |
| 155 | + hass, player, lms.uuid |
| 156 | + ) |
| 157 | + known_players.append(player.player_id) |
| 158 | + async_dispatcher_send( |
| 159 | + hass, SIGNAL_PLAYER_DISCOVERED, player_coordinator |
| 160 | + ) |
| 161 | + |
| 162 | + if players := await lms.async_get_players(): |
| 163 | + for player in players: |
| 164 | + hass.async_create_task(_discovered_player(player)) |
| 165 | + |
| 166 | + entry.async_on_unload( |
| 167 | + async_call_later(hass, DISCOVERY_INTERVAL, _player_discovery) |
| 168 | + ) |
| 169 | + |
| 170 | + await server_coordinator.async_config_entry_first_refresh() |
128 | 171 | await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) |
| 172 | + |
| 173 | + _LOGGER.debug( |
| 174 | + "Adding player discovery job for LMS server: %s", entry.data[CONF_HOST] |
| 175 | + ) |
| 176 | + entry.async_create_background_task( |
| 177 | + hass, _player_discovery(), "squeezebox.media_player.player_discovery" |
| 178 | + ) |
| 179 | + |
129 | 180 | return True |
130 | 181 |
|
131 | 182 |
|
|
0 commit comments