Use ZeroconfServiceInfo in vizio (#60115)

Co-authored-by: epenet <epenet@users.noreply.github.com>
This commit is contained in:
epenet 2021-11-29 18:27:15 +01:00 committed by GitHub
parent 37430e7c9e
commit 54df81cbab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 39 deletions

View File

@ -11,6 +11,7 @@ from pyvizio.const import APP_HOME
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components import zeroconf
from homeassistant.components.media_player import DEVICE_CLASS_SPEAKER, DEVICE_CLASS_TV
from homeassistant.config_entries import (
SOURCE_IGNORE,
@ -26,14 +27,11 @@ from homeassistant.const import (
CONF_INCLUDE,
CONF_NAME,
CONF_PIN,
CONF_PORT,
CONF_TYPE,
)
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import DiscoveryInfoType
from homeassistant.util.network import is_ip_address
from .const import (
@ -338,28 +336,25 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
return await self.async_step_user(user_input=import_config)
async def async_step_zeroconf(
self, discovery_info: DiscoveryInfoType | None = None
self, discovery_info: zeroconf.ZeroconfServiceInfo
) -> FlowResult:
"""Handle zeroconf discovery."""
host = discovery_info.host
# If host already has port, no need to add it again
if ":" not in discovery_info[CONF_HOST]:
discovery_info[
CONF_HOST
] = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}"
if ":" not in host:
host = f"{host}:{discovery_info.port}"
# Set default name to discovered device name by stripping zeroconf service
# (`type`) from `name`
num_chars_to_strip = len(discovery_info[CONF_TYPE]) + 1
discovery_info[CONF_NAME] = discovery_info[CONF_NAME][:-num_chars_to_strip]
num_chars_to_strip = len(discovery_info.type) + 1
name = discovery_info.name[:-num_chars_to_strip]
discovery_info[CONF_DEVICE_CLASS] = await async_guess_device_type(
discovery_info[CONF_HOST]
)
device_class = await async_guess_device_type(host)
# Set unique ID early for discovery flow so we can abort if needed
unique_id = await VizioAsync.get_unique_id(
discovery_info[CONF_HOST],
discovery_info[CONF_DEVICE_CLASS],
host,
device_class,
session=async_get_clientsession(self.hass, False),
)
@ -372,7 +367,13 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
# Form must be shown after discovery so user can confirm/update configuration
# before ConfigEntry creation.
self._must_show_form = True
return await self.async_step_user(user_input=discovery_info)
return await self.async_step_user(
user_input={
CONF_HOST: host,
CONF_NAME: name,
CONF_DEVICE_CLASS: device_class,
}
)
async def async_step_pair_tv(self, user_input: dict[str, Any] = None) -> FlowResult:
"""

View File

@ -1,4 +1,5 @@
"""Constants for the Vizio integration tests."""
from homeassistant.components import zeroconf
from homeassistant.components.media_player import (
DEVICE_CLASS_SPEAKER,
DEVICE_CLASS_TV,
@ -23,8 +24,6 @@ from homeassistant.const import (
CONF_INCLUDE,
CONF_NAME,
CONF_PIN,
CONF_PORT,
CONF_TYPE,
)
from homeassistant.util import slugify
@ -198,10 +197,11 @@ ZEROCONF_NAME = f"{NAME}.{VIZIO_ZEROCONF_SERVICE_TYPE}"
ZEROCONF_HOST = HOST.split(":")[0]
ZEROCONF_PORT = HOST.split(":")[1]
MOCK_ZEROCONF_SERVICE_INFO = {
CONF_TYPE: VIZIO_ZEROCONF_SERVICE_TYPE,
CONF_NAME: ZEROCONF_NAME,
CONF_HOST: ZEROCONF_HOST,
CONF_PORT: ZEROCONF_PORT,
"properties": {"name": "SB4031-D5"},
}
MOCK_ZEROCONF_SERVICE_INFO = zeroconf.ZeroconfServiceInfo(
host=ZEROCONF_HOST,
hostname="mock_hostname",
name=ZEROCONF_NAME,
port=ZEROCONF_PORT,
properties={"name": "SB4031-D5"},
type=VIZIO_ZEROCONF_SERVICE_TYPE,
)

View File

@ -1,8 +1,11 @@
"""Tests for Vizio config flow."""
import dataclasses
import pytest
import voluptuous as vol
from homeassistant import data_entry_flow
from homeassistant.components import zeroconf
from homeassistant.components.media_player import DEVICE_CLASS_SPEAKER, DEVICE_CLASS_TV
from homeassistant.components.vizio.config_flow import _get_config_schema
from homeassistant.components.vizio.const import (
@ -27,7 +30,6 @@ from homeassistant.const import (
CONF_HOST,
CONF_NAME,
CONF_PIN,
CONF_PORT,
)
from homeassistant.core import HomeAssistant
@ -728,7 +730,7 @@ async def test_zeroconf_flow(
vizio_guess_device_type: pytest.fixture,
) -> None:
"""Test zeroconf config flow."""
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_SERVICE_INFO)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
)
@ -739,7 +741,15 @@ async def test_zeroconf_flow(
# Apply discovery updates to entry to mimic when user hits submit without changing
# defaults which were set from discovery parameters
user_input = result["data_schema"](discovery_info)
user_input = result["data_schema"](
{
CONF_HOST: f"{discovery_info[zeroconf.ATTR_HOST]}:{discovery_info[zeroconf.ATTR_PORT]}",
CONF_NAME: discovery_info[zeroconf.ATTR_NAME][
: -(len(discovery_info[zeroconf.ATTR_TYPE]) + 1)
],
CONF_DEVICE_CLASS: "speaker",
}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input=user_input
@ -768,7 +778,7 @@ async def test_zeroconf_flow_already_configured(
entry.add_to_hass(hass)
# Try rediscovering same device
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_SERVICE_INFO)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
)
@ -794,10 +804,8 @@ async def test_zeroconf_flow_with_port_in_host(
entry.add_to_hass(hass)
# Try rediscovering same device, this time with port already in host
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
discovery_info[
CONF_HOST
] = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}"
discovery_info = dataclasses.replace(MOCK_ZEROCONF_SERVICE_INFO)
discovery_info.host = f"{discovery_info.host}:{discovery_info.port}"
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
)
@ -814,7 +822,7 @@ async def test_zeroconf_dupe_fail(
vizio_guess_device_type: pytest.fixture,
) -> None:
"""Test zeroconf config flow when device gets discovered multiple times."""
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_SERVICE_INFO)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
)
@ -823,7 +831,7 @@ async def test_zeroconf_dupe_fail(
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "user"
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_SERVICE_INFO)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
)
@ -848,7 +856,7 @@ async def test_zeroconf_ignore(
)
entry.add_to_hass(hass)
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_SERVICE_INFO)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
)
@ -863,7 +871,7 @@ async def test_zeroconf_no_unique_id(
) -> None:
"""Test zeroconf discovery aborts when unique_id is None."""
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_SERVICE_INFO)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
)
@ -888,7 +896,7 @@ async def test_zeroconf_abort_when_ignored(
)
entry.add_to_hass(hass)
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_SERVICE_INFO)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
)
@ -916,7 +924,7 @@ async def test_zeroconf_flow_already_configured_hostname(
entry.add_to_hass(hass)
# Try rediscovering same device
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_SERVICE_INFO)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
)