Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
36e827d
add config flow support, device registry support, available property
raman325 Jan 10, 2020
6901bbc
raise PlatformNotReady if HA cant connect to device
raman325 Jan 10, 2020
40119bb
remove test logging statement and fix integration title
raman325 Jan 10, 2020
815a344
store import and last user input values so user can see errors next t…
raman325 Jan 10, 2020
6948023
add PARALLEL_UPDATES
raman325 Jan 10, 2020
7c8d279
add missing type hints
raman325 Jan 10, 2020
6bdd638
add missing type hints to tests
raman325 Jan 10, 2020
19809fb
fix options config flow title
raman325 Jan 10, 2020
e6c3683
changes based on review
raman325 Jan 12, 2020
32df353
better key name for message when cant connect
raman325 Jan 12, 2020
28e3bc8
fix missed update to key name
raman325 Jan 12, 2020
3df6767
fix comments
raman325 Jan 12, 2020
ba25691
remove logger from test which was used to debug and update test funct…
raman325 Jan 12, 2020
b6800b7
add __init__.py to vizio tests module
raman325 Jan 12, 2020
210f30a
readded options flow and updated main component to handle options upd…
raman325 Jan 13, 2020
5a612d8
pop hass.data in media_player unload instead of in __init__ since it …
raman325 Jan 13, 2020
327ae15
update requirements_all and requirements_test_all
raman325 Jan 13, 2020
99f10f7
make unique_id key name a constant
raman325 Jan 13, 2020
79f5834
remove additional line breaks after docstrings
raman325 Jan 13, 2020
c652a60
unload entries during test_user_flow and test_import_flow tests to ho…
raman325 Jan 13, 2020
be88af7
try to speed up tests
raman325 Jan 13, 2020
361fba2
remove unnecessary code, use event bus to track options updates, move…
raman325 Jan 13, 2020
3d3a6a8
fix comment
raman325 Jan 13, 2020
d0b6960
remove translations from commit
raman325 Jan 13, 2020
33e123a
suppress API error logging when checking for device availability as i…
raman325 Jan 14, 2020
477b952
update requirements_all and requirements_test_all
raman325 Jan 14, 2020
4fbb9a0
dont pass hass to entity since it is passed to entity anyway, remove …
raman325 Jan 14, 2020
57d8e5d
fix clearing listeners
raman325 Jan 14, 2020
69e3e94
use config_entry unique ID for unique ID and use config_entry entry I…
raman325 Jan 14, 2020
b490291
update config flow based on suggested changes
raman325 Jan 14, 2020
ba3f5ec
update volume step on config import if it doesn't match config_entry …
raman325 Jan 14, 2020
2dbff5c
update config_entry data and options with new volume step value
raman325 Jan 14, 2020
08c419e
copy entry.data and entry.options before updating when updating confi…
raman325 Jan 14, 2020
fc7744f
fix test_import_entity_already_configured
raman325 Jan 15, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions homeassistant/components/vizio/__init__.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
"""The vizio component."""

import voluptuous as vol

from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import (
CONF_ACCESS_TOKEN,
CONF_DEVICE_CLASS,
CONF_HOST,
CONF_NAME,
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.typing import ConfigType, HomeAssistantType

from .const import (
CONF_VOLUME_STEP,
DEFAULT_DEVICE_CLASS,
DEFAULT_NAME,
DEFAULT_VOLUME_STEP,
DOMAIN,
)


Expand All @@ -42,3 +43,41 @@ def validate_auth(config: ConfigType) -> ConfigType:
vol.Coerce(int), vol.Range(min=1, max=10)
),
}

CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.All(
cv.ensure_list, [vol.All(vol.Schema(VIZIO_SCHEMA), validate_auth)]
)
},
extra=vol.ALLOW_EXTRA,
)


async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
"""Component setup, run import config flow for each entry in config."""
if DOMAIN in config:
for entry in config[DOMAIN]:
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data=entry
)
)

return True


async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool:
"""Load the saved entities."""
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, "media_player")
)

return True


async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
await hass.config_entries.async_forward_entry_unload(entry, "media_player")

return True
171 changes: 171 additions & 0 deletions homeassistant/components/vizio/config_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
"""Config flow for Vizio."""
import logging
from typing import Any, Dict

from pyvizio import VizioAsync
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_ACCESS_TOKEN,
CONF_DEVICE_CLASS,
CONF_HOST,
CONF_NAME,
)
from homeassistant.core import callback

from . import validate_auth
from .const import (
CONF_VOLUME_STEP,
DEFAULT_DEVICE_CLASS,
DEFAULT_NAME,
DEFAULT_VOLUME_STEP,
DOMAIN,
)

_LOGGER = logging.getLogger(__name__)


def update_schema_defaults(input_dict: Dict[str, Any]) -> vol.Schema:
"""Update schema defaults based on user input/config dict. Retains info already provided for future form views."""
return vol.Schema(
{
vol.Required(
CONF_NAME, default=input_dict.get(CONF_NAME, DEFAULT_NAME)
): str,
vol.Required(CONF_HOST, default=input_dict.get(CONF_HOST)): str,
vol.Optional(
CONF_DEVICE_CLASS,
default=input_dict.get(CONF_DEVICE_CLASS, DEFAULT_DEVICE_CLASS),
): vol.All(str, vol.Lower, vol.In(["tv", "soundbar"])),
vol.Optional(
CONF_ACCESS_TOKEN, default=input_dict.get(CONF_ACCESS_TOKEN, "")
): str,
},
extra=vol.REMOVE_EXTRA,
)
Comment thread
raman325 marked this conversation as resolved.


class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a Vizio config flow."""

VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL

@staticmethod
@callback
def async_get_options_flow(config_entry):
"""Get the options flow for this handler."""
return VizioOptionsConfigFlow(config_entry)

def __init__(self) -> None:
"""Initialize config flow."""
self.import_schema = None
self.user_schema = None

async def async_step_user(
self, user_input: Dict[str, Any] = None
) -> Dict[str, Any]:
"""Handle a flow initialized by the user."""
errors = {}

if user_input is not None:
# Store current values in case setup fails and user needs to edit
self.user_schema = update_schema_defaults(user_input)

# Check if new config entry matches any existing config entries
for entry in self.hass.config_entries.async_entries(DOMAIN):
if entry.data[CONF_HOST] == user_input[CONF_HOST]:
errors[CONF_HOST] = "host_exists"
break

if entry.data[CONF_NAME] == user_input[CONF_NAME]:
errors[CONF_NAME] = "name_exists"
break

if not errors:
try:
# Ensure schema passes custom validation, otherwise catch exception and add error
validate_auth(user_input)

# Ensure config is valid for a device
if not await VizioAsync.validate_ha_config(
user_input[CONF_HOST],
user_input.get(CONF_ACCESS_TOKEN),
user_input[CONF_DEVICE_CLASS],
):
errors["base"] = "cant_connect"
except vol.Invalid:
errors["base"] = "tv_needs_token"

if not errors:
unique_id = await VizioAsync.get_unique_id(
user_input[CONF_HOST],
user_input.get(CONF_ACCESS_TOKEN),
user_input[CONF_DEVICE_CLASS],
)

# Abort flow if existing component with same unique ID matches new config entry
if await self.async_set_unique_id(
unique_id=unique_id, raise_on_progress=True
):
return self.async_abort(reason="already_setup")

return self.async_create_entry(
title=user_input[CONF_NAME], data=user_input
)

schema = self.user_schema or self.import_schema or update_schema_defaults({})

return self.async_show_form(step_id="user", data_schema=schema, errors=errors)

async def async_step_import(self, import_config: Dict[str, Any]) -> Dict[str, Any]:
"""Import a config entry from configuration.yaml."""
# Check if new config entry matches any existing config entries
for entry in self.hass.config_entries.async_entries(DOMAIN):
if entry.data[CONF_HOST] == import_config[CONF_HOST] and entry.data[
Comment thread
raman325 marked this conversation as resolved.
CONF_NAME
] == import_config.get(CONF_NAME):
if entry.data[CONF_VOLUME_STEP] != import_config[CONF_VOLUME_STEP]:
new_volume_step = {
CONF_VOLUME_STEP: import_config[CONF_VOLUME_STEP]
}
self.hass.config_entries.async_update_entry(
entry=entry,
data=entry.data.copy().update(new_volume_step),
options=entry.options.copy().update(new_volume_step),
)
return self.async_abort(reason="updated_volume_step")
return self.async_abort(reason="already_setup")
Comment thread
raman325 marked this conversation as resolved.

# Store import values in case setup fails so user can see error
self.import_schema = update_schema_defaults(import_config)
Comment thread
raman325 marked this conversation as resolved.

return await self.async_step_user(user_input=import_config)


class VizioOptionsConfigFlow(config_entries.OptionsFlow):
"""Handle Transmission client options."""

def __init__(self, config_entry: ConfigEntry) -> None:
"""Initialize vizio options flow."""
self.config_entry = config_entry

async def async_step_init(
self, user_input: Dict[str, Any] = None
) -> Dict[str, Any]:
"""Manage the vizio options."""
if user_input is not None:
return self.async_create_entry(title="", data=user_input)

options = {
vol.Optional(
CONF_VOLUME_STEP,
default=self.config_entry.options.get(
CONF_VOLUME_STEP, DEFAULT_VOLUME_STEP
),
): vol.All(vol.Coerce(int), vol.Range(min=1, max=10))
}

return self.async_show_form(step_id="init", data_schema=vol.Schema(options))
1 change: 0 additions & 1 deletion homeassistant/components/vizio/const.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Constants used by vizio component."""

CONF_VOLUME_STEP = "volume_step"

DEFAULT_NAME = "Vizio SmartCast"
Expand Down
5 changes: 3 additions & 2 deletions homeassistant/components/vizio/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"domain": "vizio",
"name": "Vizio SmartCast TV",
"documentation": "https://www.home-assistant.io/integrations/vizio",
"requirements": ["pyvizio==0.0.15"],
"requirements": ["pyvizio==0.0.20"],
"dependencies": [],
"codeowners": ["@raman325"]
"codeowners": ["@raman325"],
"config_flow": true
}
Loading