Home Assistant Unofficial Reference 2024.12.1
media_player.py
Go to the documentation of this file.
1 """Support for interface with an Aquos TV."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 import logging
7 from typing import Any, Concatenate
8 
9 import sharp_aquos_rc
10 import voluptuous as vol
11 
13  PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
14  MediaPlayerEntity,
15  MediaPlayerEntityFeature,
16  MediaPlayerState,
17 )
18 from homeassistant.const import (
19  CONF_HOST,
20  CONF_NAME,
21  CONF_PASSWORD,
22  CONF_PORT,
23  CONF_TIMEOUT,
24  CONF_USERNAME,
25 )
26 from homeassistant.core import HomeAssistant
28 from homeassistant.helpers.entity_platform import AddEntitiesCallback
29 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
30 
31 _LOGGER = logging.getLogger(__name__)
32 
33 DEFAULT_NAME = "Sharp Aquos TV"
34 DEFAULT_PORT = 10002
35 DEFAULT_USERNAME = "admin"
36 DEFAULT_PASSWORD = "password"
37 DEFAULT_TIMEOUT = 0.5
38 DEFAULT_RETRIES = 2
39 
40 PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
41  {
42  vol.Required(CONF_HOST): cv.string,
43  vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
44  vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
45  vol.Optional(CONF_USERNAME, default=DEFAULT_USERNAME): cv.string,
46  vol.Optional(CONF_PASSWORD, default=DEFAULT_PASSWORD): cv.string,
47  vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.string,
48  vol.Optional("retries", default=DEFAULT_RETRIES): cv.string,
49  vol.Optional("power_on_enabled", default=False): cv.boolean,
50  }
51 )
52 
53 SOURCES = {
54  0: "TV / Antenna",
55  1: "HDMI_IN_1",
56  2: "HDMI_IN_2",
57  3: "HDMI_IN_3",
58  4: "HDMI_IN_4",
59  5: "COMPONENT IN",
60  6: "VIDEO_IN_1",
61  7: "VIDEO_IN_2",
62  8: "PC_IN",
63 }
64 
65 
67  hass: HomeAssistant,
68  config: ConfigType,
69  add_entities: AddEntitiesCallback,
70  discovery_info: DiscoveryInfoType | None = None,
71 ) -> None:
72  """Set up the Sharp Aquos TV platform."""
73 
74  name = config[CONF_NAME]
75  port = config[CONF_PORT]
76  username = config[CONF_USERNAME]
77  password = config[CONF_PASSWORD]
78  power_on_enabled = config["power_on_enabled"]
79  host = config[CONF_HOST]
80  remote = sharp_aquos_rc.TV(host, port, username, password, 15, 1)
81 
82  add_entities([SharpAquosTVDevice(name, remote, power_on_enabled)])
83 
84 
85 def _retry[_SharpAquosTVDeviceT: SharpAquosTVDevice, **_P](
86  func: Callable[Concatenate[_SharpAquosTVDeviceT, _P], Any],
87 ) -> Callable[Concatenate[_SharpAquosTVDeviceT, _P], None]:
88  """Handle query retries."""
89 
90  def wrapper(obj: _SharpAquosTVDeviceT, *args: _P.args, **kwargs: _P.kwargs) -> None:
91  """Wrap all query functions."""
92  update_retries = 5
93  while update_retries > 0:
94  try:
95  func(obj, *args, **kwargs)
96  break
97  except (OSError, TypeError, ValueError):
98  update_retries -= 1
99  if update_retries == 0:
100  obj.set_state(MediaPlayerState.OFF)
101 
102  return wrapper
103 
104 
106  """Representation of a Aquos TV."""
107 
108  _attr_source_list = list(SOURCES.values())
109  _attr_supported_features = (
110  MediaPlayerEntityFeature.TURN_OFF
111  | MediaPlayerEntityFeature.NEXT_TRACK
112  | MediaPlayerEntityFeature.PAUSE
113  | MediaPlayerEntityFeature.PREVIOUS_TRACK
114  | MediaPlayerEntityFeature.SELECT_SOURCE
115  | MediaPlayerEntityFeature.VOLUME_MUTE
116  | MediaPlayerEntityFeature.VOLUME_STEP
117  | MediaPlayerEntityFeature.VOLUME_SET
118  | MediaPlayerEntityFeature.PLAY
119  )
120 
121  def __init__(
122  self, name: str, remote: sharp_aquos_rc.TV, power_on_enabled: bool = False
123  ) -> None:
124  """Initialize the aquos device."""
125  self._power_on_enabled_power_on_enabled = power_on_enabled
126  if power_on_enabled:
127  self._attr_supported_features_attr_supported_features |= MediaPlayerEntityFeature.TURN_ON
128  # Save a reference to the imported class
129  self._attr_name_attr_name = name
130  # Assume that the TV is not muted
131  self._remote_remote = remote
132 
133  def set_state(self, state: MediaPlayerState) -> None:
134  """Set TV state."""
135  self._attr_state_attr_state = state
136 
137  @_retry
138  def update(self) -> None:
139  """Retrieve the latest data."""
140  if self._remote_remote.power() == 1:
141  self._attr_state_attr_state = MediaPlayerState.ON
142  else:
143  self._attr_state_attr_state = MediaPlayerState.OFF
144  # Set TV to be able to remotely power on
145  if self._power_on_enabled_power_on_enabled:
146  self._remote_remote.power_on_command_settings(2)
147  else:
148  self._remote_remote.power_on_command_settings(0)
149  # Get mute state
150  if self._remote_remote.mute() == 2:
151  self._attr_is_volume_muted_attr_is_volume_muted = False
152  else:
153  self._attr_is_volume_muted_attr_is_volume_muted = True
154  # Get source
155  self._attr_source_attr_source = SOURCES.get(self._remote_remote.input())
156  # Get volume
157  self._attr_volume_level_attr_volume_level = self._remote_remote.volume() / 60
158 
159  @_retry
160  def turn_off(self) -> None:
161  """Turn off tvplayer."""
162  self._remote_remote.power(0)
163 
164  @_retry
165  def volume_up(self) -> None:
166  """Volume up the media player."""
167  if self.volume_levelvolume_level is None:
168  _LOGGER.debug("Unknown volume in volume_up")
169  return
170  self._remote_remote.volume(int(self.volume_levelvolume_level * 60) + 2)
171 
172  @_retry
173  def volume_down(self) -> None:
174  """Volume down media player."""
175  if self.volume_levelvolume_level is None:
176  _LOGGER.debug("Unknown volume in volume_down")
177  return
178  self._remote_remote.volume(int(self.volume_levelvolume_level * 60) - 2)
179 
180  @_retry
181  def set_volume_level(self, volume: float) -> None:
182  """Set Volume media player."""
183  self._remote_remote.volume(int(volume * 60))
184 
185  @_retry
186  def mute_volume(self, mute: bool) -> None:
187  """Send mute command."""
188  self._remote_remote.mute(0)
189 
190  @_retry
191  def turn_on(self) -> None:
192  """Turn the media player on."""
193  self._remote_remote.power(1)
194 
195  @_retry
196  def media_play_pause(self) -> None:
197  """Simulate play pause media player."""
198  self._remote_remote.remote_button(40)
199 
200  @_retry
201  def media_play(self) -> None:
202  """Send play command."""
203  self._remote_remote.remote_button(16)
204 
205  @_retry
206  def media_pause(self) -> None:
207  """Send pause command."""
208  self._remote_remote.remote_button(16)
209 
210  @_retry
211  def media_next_track(self) -> None:
212  """Send next track command."""
213  self._remote_remote.remote_button(21)
214 
215  @_retry
216  def media_previous_track(self) -> None:
217  """Send the previous track command."""
218  self._remote_remote.remote_button(19)
219 
220  def select_source(self, source: str) -> None:
221  """Set the input source."""
222  for key, value in SOURCES.items():
223  if source == value:
224  self._remote_remote.input(key)
None __init__(self, str name, sharp_aquos_rc.TV remote, bool power_on_enabled=False)
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: media_player.py:71
None add_entities(AsusWrtRouter router, AddEntitiesCallback async_add_entities, set[str] tracked)