Remove attributes from vizio state when they don't make sense (#64025)

* Remove attributes from vizio state when they don't make sense

* rename var
This commit is contained in:
Raman Gupta 2022-01-13 14:59:55 -05:00 committed by GitHub
parent 0fa4f616ed
commit 867f8237e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 20 deletions

View file

@ -145,6 +145,7 @@ class VizioDevice(MediaPlayerEntity):
self._volume_step = config_entry.options[CONF_VOLUME_STEP]
self._current_input = None
self._current_app_config = None
self._app_name = None
self._available_inputs = []
self._available_apps = []
self._all_apps = apps_coordinator.data if apps_coordinator else None
@ -178,9 +179,9 @@ class VizioDevice(MediaPlayerEntity):
async def async_update(self) -> None:
"""Retrieve latest state of the device."""
is_on = await self._device.get_power_state(log_api_exception=False)
if is_on is None:
if (
is_on := await self._device.get_power_state(log_api_exception=False)
) is None:
if self._attr_available:
_LOGGER.warning(
"Lost connection to %s", self._config_entry.data[CONF_HOST]
@ -208,18 +209,16 @@ class VizioDevice(MediaPlayerEntity):
self._attr_volume_level = None
self._attr_is_volume_muted = None
self._current_input = None
self._attr_app_name = None
self._app_name = None
self._current_app_config = None
self._attr_sound_mode = None
return
self._attr_state = STATE_ON
audio_settings = await self._device.get_all_settings(
if audio_settings := await self._device.get_all_settings(
VIZIO_AUDIO_SETTINGS, log_api_exception=False
)
if audio_settings:
):
self._attr_volume_level = (
float(audio_settings[VIZIO_VOLUME]) / self._max_volume
)
@ -243,14 +242,11 @@ class VizioDevice(MediaPlayerEntity):
# Explicitly remove SUPPORT_SELECT_SOUND_MODE from supported features
self._attr_supported_features &= ~SUPPORT_SELECT_SOUND_MODE
input_ = await self._device.get_current_input(log_api_exception=False)
if input_:
if input_ := await self._device.get_current_input(log_api_exception=False):
self._current_input = input_
inputs = await self._device.get_inputs_list(log_api_exception=False)
# If no inputs returned, end update
if not inputs:
if not (inputs := await self._device.get_inputs_list(log_api_exception=False)):
return
self._available_inputs = [input_.name for input_ in inputs]
@ -269,13 +265,13 @@ class VizioDevice(MediaPlayerEntity):
log_api_exception=False
)
self._attr_app_name = find_app_name(
self._app_name = find_app_name(
self._current_app_config,
[APP_HOME, *self._all_apps, *self._additional_app_configs],
)
if self._attr_app_name == NO_APP_RUNNING:
self._attr_app_name = None
if self._app_name == NO_APP_RUNNING:
self._app_name = None
def _get_additional_app_names(self) -> list[dict[str, Any]]:
"""Return list of additional apps that were included in configuration.yaml."""
@ -288,7 +284,8 @@ class VizioDevice(MediaPlayerEntity):
hass: HomeAssistant, config_entry: ConfigEntry
) -> None:
"""Send update event when Vizio config entry is updated."""
# Move this method to component level if another entity ever gets added for a single config entry.
# Move this method to component level if another entity ever gets added for a
# single config entry.
# See here: https://github.com/home-assistant/core/pull/30653#discussion_r366426121
async_dispatcher_send(hass, config_entry.entry_id, config_entry)
@ -340,8 +337,8 @@ class VizioDevice(MediaPlayerEntity):
@property
def source(self) -> str | None:
"""Return current input of the device."""
if self._attr_app_name is not None and self._current_input in INPUT_APPS:
return self._attr_app_name
if self._app_name is not None and self._current_input in INPUT_APPS:
return self._app_name
return self._current_input
@ -367,10 +364,18 @@ class VizioDevice(MediaPlayerEntity):
return self._available_inputs
@property
def app_name(self) -> str | None:
"""Return the name of the current app."""
if self.source == self._app_name:
return self._app_name
return None
@property
def app_id(self) -> str | None:
"""Return the ID of the current app if it is unknown by pyvizio."""
if self._current_app_config and self.app_name == UNKNOWN_APP:
if self._current_app_config and self.source == UNKNOWN_APP:
return {
"APP_ID": self._current_app_config.APP_ID,
"NAME_SPACE": self._current_app_config.NAME_SPACE,

View file

@ -216,6 +216,22 @@ def vizio_update_with_apps_fixture(vizio_update: pytest.fixture):
yield
@pytest.fixture(name="vizio_update_with_apps_on_input")
def vizio_update_with_apps_on_input_fixture(vizio_update: pytest.fixture):
"""Mock valid updates to vizio device that supports apps but is on a TV input."""
with patch(
"homeassistant.components.vizio.media_player.VizioAsync.get_inputs_list",
return_value=get_mock_inputs(INPUT_LIST_WITH_APPS),
), patch(
"homeassistant.components.vizio.media_player.VizioAsync.get_current_input",
return_value=CURRENT_INPUT,
), patch(
"homeassistant.components.vizio.media_player.VizioAsync.get_current_app_config",
return_value=AppConfig("unknown", 1, "app"),
):
yield
@pytest.fixture(name="vizio_hostname_check")
def vizio_hostname_check():
"""Mock vizio hostname resolution."""

View file

@ -751,3 +751,19 @@ async def test_apps_update(
sources = hass.states.get(ENTITY_ID).attributes[ATTR_INPUT_SOURCE_LIST]
apps = list(set(sources) - set(INPUT_LIST))
assert len(apps) == len(APP_LIST)
async def test_vizio_update_with_apps_on_input(
hass: HomeAssistant, vizio_connect, vizio_update_with_apps_on_input
) -> None:
"""Test a vizio TV with apps that is on a TV input."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data=vol.Schema(VIZIO_SCHEMA)(MOCK_USER_VALID_TV_CONFIG),
unique_id=UNIQUE_ID,
)
await _add_config_entry_to_hass(hass, config_entry)
attr = _get_attr_and_assert_base_attr(hass, DEVICE_CLASS_TV, STATE_ON)
# App name and app ID should not be in the attributes
assert "app_name" not in attr
assert "app_id" not in attr