Home Assistant Unofficial Reference 2024.12.1
media_player.py
Go to the documentation of this file.
1 """Support for interface with a Ziggo Mediabox XL."""
2 
3 from __future__ import annotations
4 
5 import logging
6 import socket
7 
8 import voluptuous as vol
9 from ziggo_mediabox_xl import ZiggoMediaboxXL
10 
12  PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
13  MediaPlayerEntity,
14  MediaPlayerEntityFeature,
15  MediaPlayerState,
16 )
17 from homeassistant.const import CONF_HOST, CONF_NAME
18 from homeassistant.core import HomeAssistant
20 from homeassistant.helpers.entity_platform import AddEntitiesCallback
21 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
22 
23 _LOGGER = logging.getLogger(__name__)
24 
25 DATA_KNOWN_DEVICES = "ziggo_mediabox_xl_known_devices"
26 
27 PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
28  {vol.Required(CONF_HOST): cv.string, vol.Optional(CONF_NAME): cv.string}
29 )
30 
31 
33  hass: HomeAssistant,
34  config: ConfigType,
35  add_entities: AddEntitiesCallback,
36  discovery_info: DiscoveryInfoType | None = None,
37 ) -> None:
38  """Set up the Ziggo Mediabox XL platform."""
39 
40  hass.data[DATA_KNOWN_DEVICES] = known_devices = set()
41 
42  # Is this a manual configuration?
43  if (host := config.get(CONF_HOST)) is not None:
44  name = config.get(CONF_NAME)
45  manual_config = True
46  elif discovery_info is not None:
47  host = discovery_info["host"]
48  name = discovery_info.get("name")
49  manual_config = False
50  else:
51  _LOGGER.error("Cannot determine device")
52  return
53 
54  # Only add a device once, so discovered devices do not override manual
55  # config.
56  hosts = []
57  connection_successful = False
58  ip_addr = socket.gethostbyname(host)
59  if ip_addr not in known_devices:
60  try:
61  # Mediabox instance with a timeout of 3 seconds.
62  mediabox = ZiggoMediaboxXL(ip_addr, 3)
63  # Check if a connection can be established to the device.
64  if mediabox.test_connection():
65  connection_successful = True
66  elif manual_config:
67  _LOGGER.error("Can't connect to %s", host)
68  else:
69  _LOGGER.error("Can't connect to %s", host)
70  # When the device is in eco mode it's not connected to the network
71  # so it needs to be added anyway if it's configured manually.
72  if manual_config or connection_successful:
73  hosts.append(
74  ZiggoMediaboxXLDevice(mediabox, host, name, connection_successful)
75  )
76  known_devices.add(ip_addr)
77  except OSError as error:
78  _LOGGER.error("Can't connect to %s: %s", host, error)
79  else:
80  _LOGGER.warning("Ignoring duplicate Ziggo Mediabox XL %s", host)
81  add_entities(hosts, True)
82 
83 
85  """Representation of a Ziggo Mediabox XL Device."""
86 
87  _attr_supported_features = (
88  MediaPlayerEntityFeature.TURN_ON
89  | MediaPlayerEntityFeature.TURN_OFF
90  | MediaPlayerEntityFeature.NEXT_TRACK
91  | MediaPlayerEntityFeature.PAUSE
92  | MediaPlayerEntityFeature.PREVIOUS_TRACK
93  | MediaPlayerEntityFeature.SELECT_SOURCE
94  | MediaPlayerEntityFeature.PLAY
95  )
96 
97  def __init__(self, mediabox, host, name, available):
98  """Initialize the device."""
99  self._mediabox_mediabox = mediabox
100  self._host_host = host
101  self._attr_name_attr_name = name
102  self._attr_available_attr_available = available
103 
104  def update(self) -> None:
105  """Retrieve the state of the device."""
106  try:
107  if self._mediabox_mediabox.test_connection():
108  if self._mediabox_mediabox.turned_on():
109  if self.statestatestatestatestate != MediaPlayerState.PAUSED:
110  self._attr_state_attr_state = MediaPlayerState.PLAYING
111  else:
112  self._attr_state_attr_state = MediaPlayerState.OFF
113  self._attr_available_attr_available = True
114  else:
115  self._attr_available_attr_available = False
116  except OSError:
117  _LOGGER.error("Couldn't fetch state from %s", self._host_host)
118  self._attr_available_attr_available = False
119 
120  def send_keys(self, keys):
121  """Send keys to the device and handle exceptions."""
122  try:
123  self._mediabox_mediabox.send_keys(keys)
124  except OSError:
125  _LOGGER.error("Couldn't send keys to %s", self._host_host)
126 
127  @property
128  def source_list(self) -> list[str]:
129  """List of available sources (channels)."""
130  return [
131  self._mediabox_mediabox.channels()[c]
132  for c in sorted(self._mediabox_mediabox.channels().keys())
133  ]
134 
135  def turn_on(self) -> None:
136  """Turn the media player on."""
137  self.send_keyssend_keys(["POWER"])
138 
139  def turn_off(self) -> None:
140  """Turn off media player."""
141  self.send_keyssend_keys(["POWER"])
142 
143  def media_play(self) -> None:
144  """Send play command."""
145  self.send_keyssend_keys(["PLAY"])
146  self._attr_state_attr_state = MediaPlayerState.PLAYING
147 
148  def media_pause(self) -> None:
149  """Send pause command."""
150  self.send_keyssend_keys(["PAUSE"])
151  self._attr_state_attr_state = MediaPlayerState.PAUSED
152 
153  def media_play_pause(self) -> None:
154  """Simulate play pause media player."""
155  self.send_keyssend_keys(["PAUSE"])
156  if self.statestatestatestatestate == MediaPlayerState.PAUSED:
157  self._attr_state_attr_state = MediaPlayerState.PLAYING
158  else:
159  self._attr_state_attr_state = MediaPlayerState.PAUSED
160 
161  def media_next_track(self) -> None:
162  """Channel up."""
163  self.send_keyssend_keys(["CHAN_UP"])
164  self._attr_state_attr_state = MediaPlayerState.PLAYING
165 
166  def media_previous_track(self) -> None:
167  """Channel down."""
168  self.send_keyssend_keys(["CHAN_DOWN"])
169  self._attr_state_attr_state = MediaPlayerState.PLAYING
170 
171  def select_source(self, source):
172  """Select the channel."""
173  if str(source).isdigit():
174  digits = str(source)
175  else:
176  digits = next(
177  (
178  key
179  for key, value in self._mediabox_mediabox.channels().items()
180  if value == source
181  ),
182  None,
183  )
184  if digits is None:
185  return
186 
187  self.send_keyssend_keys([f"NUM_{digit}" for digit in str(digits)])
188  self._attr_state_attr_state = MediaPlayerState.PLAYING
None add_entities(AsusWrtRouter router, AddEntitiesCallback async_add_entities, set[str] tracked)
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: media_player.py:37