mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 08:47:57 +00:00
Use ZeroconfServiceInfo in vizio (#60115)
Co-authored-by: epenet <epenet@users.noreply.github.com>
This commit is contained in:
parent
37430e7c9e
commit
54df81cbab
@ -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:
|
||||
"""
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user