Home Assistant Unofficial Reference 2024.12.1
server.py
Go to the documentation of this file.
1 """Snapcast Integration."""
2 
3 from __future__ import annotations
4 
5 import logging
6 
7 import snapcast.control
8 from snapcast.control.client import Snapclient
9 
10 from homeassistant.components.media_player import MediaPlayerEntity
11 from homeassistant.core import HomeAssistant
12 from homeassistant.helpers import entity_registry as er
13 from homeassistant.helpers.entity_platform import AddEntitiesCallback
14 
15 from .media_player import SnapcastClientDevice, SnapcastGroupDevice
16 
17 _LOGGER = logging.getLogger(__name__)
18 
19 
21  """Snapcast server and data stored in the Home Assistant data object."""
22 
23  hass: HomeAssistant
24 
25  def __init__(
26  self,
27  hass: HomeAssistant,
28  server: snapcast.control.Snapserver,
29  hpid: str,
30  entry_id: str,
31  ) -> None:
32  """Initialize the HomeAssistantSnapcast object.
33 
34  Parameters
35  ----------
36  hass: HomeAssistant
37  hass object
38  server : snapcast.control.Snapserver
39  Snapcast server
40  hpid : str
41  host and port
42  entry_id: str
43  ConfigEntry entry_id
44 
45  Returns
46  -------
47  None
48 
49  """
50  self.hass: HomeAssistant = hass
51  self.server: snapcast.control.Snapserver = server
52  self.hpid: str = hpid
53  self._entry_id_entry_id = entry_id
54  self.clients: list[SnapcastClientDevice] = []
55  self.groups: list[SnapcastGroupDevice] = []
56  self.hass_async_add_entities: AddEntitiesCallback
57  # connect callbacks
58  self.server.set_on_update_callback(self.on_updateon_update)
59  self.server.set_on_connect_callback(self.on_connecton_connect)
60  self.server.set_on_disconnect_callback(self.on_disconnecton_disconnect)
61  self.server.set_new_client_callback(self.on_add_clienton_add_client)
62 
63  async def disconnect(self) -> None:
64  """Disconnect from server."""
65  self.server.set_on_update_callback(None)
66  self.server.set_on_connect_callback(None)
67  self.server.set_on_disconnect_callback(None)
68  self.server.set_new_client_callback(None)
69  self.server.stop()
70 
71  def on_update(self) -> None:
72  """Update all entities.
73 
74  Retrieve all groups/clients from server and add/update/delete entities.
75  """
76  if not self.hass_async_add_entities:
77  return
78  new_groups: list[MediaPlayerEntity] = []
79  groups: list[MediaPlayerEntity] = []
80  hass_groups = {g.identifier: g for g in self.groups}
81  for group in self.server.groups:
82  if group.identifier in hass_groups:
83  groups.append(hass_groups[group.identifier])
84  hass_groups[group.identifier].async_schedule_update_ha_state()
85  else:
86  new_groups.append(SnapcastGroupDevice(group, self.hpid, self._entry_id_entry_id))
87  new_clients: list[MediaPlayerEntity] = []
88  clients: list[MediaPlayerEntity] = []
89  hass_clients = {c.identifier: c for c in self.clients}
90  for client in self.server.clients:
91  if client.identifier in hass_clients:
92  clients.append(hass_clients[client.identifier])
93  hass_clients[client.identifier].async_schedule_update_ha_state()
94  else:
95  new_clients.append(
96  SnapcastClientDevice(client, self.hpid, self._entry_id_entry_id)
97  )
98  del_entities: list[MediaPlayerEntity] = [
99  x for x in self.groups if x not in groups
100  ]
101  del_entities.extend([x for x in self.clients if x not in clients])
102 
103  _LOGGER.debug("New clients: %s", str([c.name for c in new_clients]))
104  _LOGGER.debug("New groups: %s", str([g.name for g in new_groups]))
105  _LOGGER.debug("Delete: %s", str(del_entities))
106 
107  ent_reg = er.async_get(self.hass)
108  for entity in del_entities:
109  ent_reg.async_remove(entity.entity_id)
110  self.hass_async_add_entities(new_clients + new_groups)
111 
112  def on_connect(self) -> None:
113  """Activate all entities and update."""
114  for client in self.clients:
115  client.set_availability(True)
116  for group in self.groups:
117  group.set_availability(True)
118  _LOGGER.debug("Server connected: %s", self.hpid)
119  self.on_updateon_update()
120 
121  def on_disconnect(self, ex: Exception | None) -> None:
122  """Deactivate all entities."""
123  for client in self.clients:
124  client.set_availability(False)
125  for group in self.groups:
126  group.set_availability(False)
127  _LOGGER.warning(
128  "Server disconnected: %s. Trying to reconnect. %s", self.hpid, str(ex or "")
129  )
130 
131  def on_add_client(self, client: Snapclient) -> None:
132  """Add a Snapcast client.
133 
134  Parameters
135  ----------
136  client : Snapclient
137  Snapcast client to be added to HA.
138 
139  """
140  if not self.hass_async_add_entities:
141  return
142  clients = [SnapcastClientDevice(client, self.hpid, self._entry_id_entry_id)]
143  self.hass_async_add_entities(clients)
None __init__(self, HomeAssistant hass, snapcast.control.Snapserver server, str hpid, str entry_id)
Definition: server.py:31