1 """Vizio SmartCast Device support."""
3 from __future__
import annotations
5 from datetime
import timedelta
8 from pyvizio
import AppConfig, VizioAsync
9 from pyvizio.api.apps
import find_app_name
10 from pyvizio.const
import APP_HOME, INPUT_APPS, NO_APP_RUNNING, UNKNOWN_APP
13 MediaPlayerDeviceClass,
15 MediaPlayerEntityFeature,
32 async_dispatcher_connect,
33 async_dispatcher_send,
38 CONF_ADDITIONAL_CONFIGS,
45 SERVICE_UPDATE_SETTING,
47 UPDATE_SETTING_SCHEMA,
55 from .coordinator
import VizioAppsDataUpdateCoordinator
57 _LOGGER = logging.getLogger(__name__)
65 config_entry: ConfigEntry,
66 async_add_entities: AddEntitiesCallback,
68 """Set up a Vizio media player entry."""
69 host = config_entry.data[CONF_HOST]
70 token = config_entry.data.get(CONF_ACCESS_TOKEN)
71 name = config_entry.data[CONF_NAME]
72 device_class = config_entry.data[CONF_DEVICE_CLASS]
76 volume_step = config_entry.options.get(
77 CONF_VOLUME_STEP, config_entry.data.get(CONF_VOLUME_STEP, DEFAULT_VOLUME_STEP)
81 if not config_entry.options:
82 params[
"options"] = {CONF_VOLUME_STEP: volume_step}
84 include_or_exclude_key = next(
87 for key
in config_entry.data.get(CONF_APPS, {})
88 if key
in (CONF_INCLUDE, CONF_EXCLUDE)
92 if include_or_exclude_key:
93 params[
"options"][CONF_APPS] = {
94 include_or_exclude_key: config_entry.data[CONF_APPS][
95 include_or_exclude_key
99 if not config_entry.data.get(CONF_VOLUME_STEP):
100 new_data = config_entry.data.copy()
101 new_data.update({CONF_VOLUME_STEP: volume_step})
102 params[
"data"] = new_data
105 hass.config_entries.async_update_entry(
115 device_type=VIZIO_DEVICE_CLASSES[device_class],
117 timeout=DEFAULT_TIMEOUT,
120 apps_coordinator = hass.data[DOMAIN].
get(CONF_APPS)
122 entity =
VizioDevice(config_entry, device, name, device_class, apps_coordinator)
125 platform = entity_platform.async_get_current_platform()
126 platform.async_register_entity_service(
127 SERVICE_UPDATE_SETTING, UPDATE_SETTING_SCHEMA,
"async_update_setting"
132 """Media Player implementation which performs REST requests to device."""
134 _attr_has_entity_name =
True
136 _received_device_info =
False
140 config_entry: ConfigEntry,
143 device_class: MediaPlayerDeviceClass,
144 apps_coordinator: VizioAppsDataUpdateCoordinator |
None,
146 """Initialize Vizio device."""
155 self.
_all_apps_all_apps = apps_coordinator.data
if apps_coordinator
else None
156 self.
_conf_apps_conf_apps = config_entry.options.get(CONF_APPS, {})
158 CONF_ADDITIONAL_CONFIGS, []
170 unique_id = config_entry.unique_id
175 identifiers={(DOMAIN, unique_id)},
176 manufacturer=
"VIZIO",
181 """Return process apps list based on configured filters."""
183 return [app
for app
in apps
if app
in self.
_conf_apps_conf_apps[CONF_INCLUDE]]
186 return [app
for app
in apps
if app
not in self.
_conf_apps_conf_apps[CONF_EXCLUDE]]
191 """Retrieve latest state of the device."""
193 is_on := await self.
_device_device.get_power_state(log_api_exception=
False)
197 "Lost connection to %s", self.
_config_entry_config_entry.data[CONF_HOST]
204 "Restored connection to %s", self.
_config_entry_config_entry.data[CONF_HOST]
209 device_reg = dr.async_get(self.
hasshass)
211 device = device_reg.async_get_device(
212 identifiers={(DOMAIN, self.
_config_entry_config_entry.unique_id)}
215 device_reg.async_update_device(
218 sw_version=await self.
_device_device.get_version(log_api_exception=
False),
234 if audio_settings := await self.
_device_device.get_all_settings(
235 VIZIO_AUDIO_SETTINGS, log_api_exception=
False
240 if VIZIO_MUTE
in audio_settings:
242 audio_settings[VIZIO_MUTE].lower() == VIZIO_MUTE_ON
247 if VIZIO_SOUND_MODE
in audio_settings:
249 MediaPlayerEntityFeature.SELECT_SOUND_MODE
254 VIZIO_AUDIO_SETTINGS,
256 log_api_exception=
False,
261 ~MediaPlayerEntityFeature.SELECT_SOUND_MODE
264 if input_ := await self.
_device_device.get_current_input(log_api_exception=
False):
268 if not (inputs := await self.
_device_device.get_inputs_list(log_api_exception=
False)):
274 if self.
_attr_device_class_attr_device_class == MediaPlayerDeviceClass.SPEAKER
or not any(
282 [app[
"name"]
for app
in self.
_all_apps_all_apps
or ()]
286 log_api_exception=
False
298 """Return list of additional apps that were included in configuration.yaml."""
305 hass: HomeAssistant, config_entry: ConfigEntry
307 """Send update event when Vizio config entry is updated."""
314 """Update options if the update signal comes from this entity."""
315 self.
_volume_step_volume_step = config_entry.options[CONF_VOLUME_STEP]
320 self, setting_type: str, setting_name: str, new_value: int | str
322 """Update a setting when update_setting service is called."""
323 await self.
_device_device.set_setting(
327 log_api_exception=
False,
331 """Register callbacks when entity is added."""
351 def apps_list_update() -> None:
352 """Update list of all apps."""
364 """Return current input of the device."""
372 """Return list of available inputs of the device."""
380 if _input
not in INPUT_APPS
394 """Return the ID of the current app if it is unknown by pyvizio."""
405 """Select sound mode."""
407 await self.
_device_device.set_setting(
408 VIZIO_AUDIO_SETTINGS,
411 log_api_exception=
False,
415 """Turn the device on."""
416 await self.
_device_device.pow_on(log_api_exception=
False)
419 """Turn the device off."""
420 await self.
_device_device.pow_off(log_api_exception=
False)
423 """Mute the volume."""
425 await self.
_device_device.mute_on(log_api_exception=
False)
428 await self.
_device_device.mute_off(log_api_exception=
False)
432 """Send previous channel command."""
433 await self.
_device_device.ch_down(log_api_exception=
False)
436 """Send next channel command."""
437 await self.
_device_device.ch_up(log_api_exception=
False)
440 """Select input source."""
442 await self.
_device_device.set_input(source, log_api_exception=
False)
444 await self.
_device_device.launch_app_config(
448 if app[
"name"] == source
450 log_api_exception=
False,
453 await self.
_device_device.launch_app(
454 source, self.
_all_apps_all_apps, log_api_exception=
False
458 """Increase volume of the device."""
459 await self.
_device_device.vol_up(num=self.
_volume_step_volume_step, log_api_exception=
False)
467 """Decrease volume of the device."""
468 await self.
_device_device.vol_down(num=self.
_volume_step_volume_step, log_api_exception=
False)
476 """Set volume level."""
480 await self.
_device_device.vol_up(num=num, log_api_exception=
False)
485 await self.
_device_device.vol_down(num=num, log_api_exception=
False)
489 """Play whatever media is currently active."""
490 await self.
_device_device.play(log_api_exception=
False)
493 """Pause whatever media is currently active."""
494 await self.
_device_device.pause(log_api_exception=
False)
None async_write_ha_state(self)
None async_on_remove(self, CALLBACK_TYPE func)
web.Response get(self, web.Request request, str config_key)
IssData update(pyiss.ISS iss)
None async_add_listener(HomeAssistant hass, Callable[[], None] listener)
str get_model_name(dict[str, Any] info)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)