Home Assistant Unofficial Reference 2024.12.1
media_player.py
Go to the documentation of this file.
1 """Support for Epson projector."""
2 
3 from __future__ import annotations
4 
5 import logging
6 
7 from epson_projector import Projector, ProjectorUnavailableError
8 from epson_projector.const import (
9  BACK,
10  BUSY_CODES,
11  CMODE,
12  CMODE_LIST,
13  CMODE_LIST_SET,
14  DEFAULT_SOURCES,
15  EPSON_CODES,
16  FAST,
17  INV_SOURCES,
18  MUTE,
19  PAUSE,
20  PLAY,
21  POWER,
22  SOURCE,
23  SOURCE_LIST,
24  TURN_OFF,
25  TURN_ON,
26  VOL_DOWN,
27  VOL_UP,
28  VOLUME,
29 )
30 import voluptuous as vol
31 
33  MediaPlayerEntity,
34  MediaPlayerEntityFeature,
35  MediaPlayerState,
36 )
37 from homeassistant.config_entries import ConfigEntry
38 from homeassistant.core import HomeAssistant
39 from homeassistant.helpers import (
40  config_validation as cv,
41  device_registry as dr,
42  entity_platform,
43  entity_registry as er,
44 )
45 from homeassistant.helpers.device_registry import DeviceInfo
46 from homeassistant.helpers.entity_platform import AddEntitiesCallback
47 
48 from .const import ATTR_CMODE, DOMAIN, SERVICE_SELECT_CMODE
49 
50 _LOGGER = logging.getLogger(__name__)
51 
52 
54  hass: HomeAssistant,
55  config_entry: ConfigEntry,
56  async_add_entities: AddEntitiesCallback,
57 ) -> None:
58  """Set up the Epson projector from a config entry."""
59  projector: Projector = hass.data[DOMAIN][config_entry.entry_id]
60  projector_entity = EpsonProjectorMediaPlayer(
61  projector=projector,
62  unique_id=config_entry.unique_id or config_entry.entry_id,
63  entry=config_entry,
64  )
65  async_add_entities([projector_entity], True)
66  platform = entity_platform.async_get_current_platform()
67  platform.async_register_entity_service(
68  SERVICE_SELECT_CMODE,
69  {vol.Required(ATTR_CMODE): vol.All(cv.string, vol.Any(*CMODE_LIST_SET))},
70  SERVICE_SELECT_CMODE,
71  )
72 
73 
75  """Representation of Epson Projector Device."""
76 
77  _attr_has_entity_name = True
78  _attr_name = None
79 
80  _attr_supported_features = (
81  MediaPlayerEntityFeature.TURN_ON
82  | MediaPlayerEntityFeature.TURN_OFF
83  | MediaPlayerEntityFeature.SELECT_SOURCE
84  | MediaPlayerEntityFeature.VOLUME_MUTE
85  | MediaPlayerEntityFeature.VOLUME_STEP
86  | MediaPlayerEntityFeature.NEXT_TRACK
87  | MediaPlayerEntityFeature.PREVIOUS_TRACK
88  )
89 
90  def __init__(
91  self, projector: Projector, unique_id: str, entry: ConfigEntry
92  ) -> None:
93  """Initialize entity to control Epson projector."""
94  self._projector_projector = projector
95  self._entry_entry = entry
96  self._attr_available_attr_available = False
97  self._cmode_cmode = None
98  self._attr_source_list_attr_source_list = list(DEFAULT_SOURCES.values())
99  self._attr_unique_id_attr_unique_id = unique_id
100  self._attr_device_info_attr_device_info = DeviceInfo(
101  identifiers={(DOMAIN, unique_id)},
102  manufacturer="Epson",
103  model="Epson",
104  )
105 
106  async def set_unique_id(self) -> bool:
107  """Set unique id for projector config entry."""
108  _LOGGER.debug("Setting unique_id for projector")
109  if self._entry_entry.unique_id:
110  return False
111  if uid := await self._projector_projector.get_serial_number():
112  self.hasshass.config_entries.async_update_entry(self._entry_entry, unique_id=uid)
113  ent_reg = er.async_get(self.hasshass)
114  old_entity_id = ent_reg.async_get_entity_id(
115  "media_player", DOMAIN, self._entry_entry.entry_id
116  )
117  if old_entity_id is not None:
118  ent_reg.async_update_entity(old_entity_id, new_unique_id=uid)
119  dev_reg = dr.async_get(self.hasshass)
120  device = dev_reg.async_get_device({(DOMAIN, self._entry_entry.entry_id)})
121  if device is not None:
122  dev_reg.async_update_device(device.id, new_identifiers={(DOMAIN, uid)})
123  self.hasshass.async_create_task(
124  self.hasshass.config_entries.async_reload(self._entry_entry.entry_id)
125  )
126  return True
127  return False
128 
129  async def async_update(self) -> None:
130  """Update state of device."""
131  try:
132  power_state = await self._projector_projector.get_power()
133  except ProjectorUnavailableError as ex:
134  _LOGGER.debug("Projector is unavailable: %s", ex)
135  self._attr_available_attr_available = False
136  return
137  if not power_state:
138  self._attr_available_attr_available = False
139  return
140  _LOGGER.debug("Projector status: %s", power_state)
141  self._attr_available_attr_available = True
142  if power_state == EPSON_CODES[POWER]:
143  self._attr_state_attr_state = MediaPlayerState.ON
144  if await self.set_unique_idset_unique_id():
145  return
146  self._attr_source_list_attr_source_list = list(DEFAULT_SOURCES.values())
147  cmode = await self._projector_projector.get_property(CMODE)
148  self._cmode_cmode = CMODE_LIST.get(cmode, self._cmode_cmode)
149  source = await self._projector_projector.get_property(SOURCE)
150  self._attr_source_attr_source = SOURCE_LIST.get(source, self._attr_source_attr_source)
151  if volume := await self._projector_projector.get_property(VOLUME):
152  try:
153  self._attr_volume_level_attr_volume_level = float(volume)
154  except ValueError:
155  self._attr_volume_level_attr_volume_level = None
156  elif power_state in BUSY_CODES:
157  self._attr_state_attr_state = MediaPlayerState.ON
158  else:
159  self._attr_state_attr_state = MediaPlayerState.OFF
160 
161  async def async_turn_on(self) -> None:
162  """Turn on epson."""
163  if self.statestatestatestatestate == MediaPlayerState.OFF:
164  await self._projector_projector.send_command(TURN_ON)
165  self._attr_state_attr_state = MediaPlayerState.ON
166 
167  async def async_turn_off(self) -> None:
168  """Turn off epson."""
169  if self.statestatestatestatestate == MediaPlayerState.ON:
170  await self._projector_projector.send_command(TURN_OFF)
171  self._attr_state_attr_state = MediaPlayerState.OFF
172 
173  async def select_cmode(self, cmode: str) -> None:
174  """Set color mode in Epson."""
175  await self._projector_projector.send_command(CMODE_LIST_SET[cmode])
176 
177  async def async_select_source(self, source: str) -> None:
178  """Select input source."""
179  selected_source = INV_SOURCES[source]
180  await self._projector_projector.send_command(selected_source)
181 
182  async def async_mute_volume(self, mute: bool) -> None:
183  """Mute (true) or unmute (false) sound."""
184  await self._projector_projector.send_command(MUTE)
185 
186  async def async_volume_up(self) -> None:
187  """Increase volume."""
188  await self._projector_projector.send_command(VOL_UP)
189 
190  async def async_volume_down(self) -> None:
191  """Decrease volume."""
192  await self._projector_projector.send_command(VOL_DOWN)
193 
194  async def async_media_play(self) -> None:
195  """Play media via Epson."""
196  await self._projector_projector.send_command(PLAY)
197 
198  async def async_media_pause(self) -> None:
199  """Pause media via Epson."""
200  await self._projector_projector.send_command(PAUSE)
201 
202  async def async_media_next_track(self) -> None:
203  """Skip to next."""
204  await self._projector_projector.send_command(FAST)
205 
206  async def async_media_previous_track(self) -> None:
207  """Skip to previous."""
208  await self._projector_projector.send_command(BACK)
209 
210  @property
211  def extra_state_attributes(self) -> dict[str, str]:
212  """Return device specific state attributes."""
213  if self._cmode_cmode is None:
214  return {}
215  return {ATTR_CMODE: self._cmode_cmode}
None __init__(self, Projector projector, str unique_id, ConfigEntry entry)
Definition: media_player.py:92
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: media_player.py:57