mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +00:00
Axis - Remove manual configuration and legacy config file import (#30365)
* Remove manual configuration and legacy config file import * Remove unused imports in tests after rebase
This commit is contained in:
parent
6387a50697
commit
bb55606d29
@ -1,43 +1,18 @@
|
||||
"""Support for Axis devices."""
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE,
|
||||
CONF_MAC,
|
||||
CONF_NAME,
|
||||
CONF_TRIGGER_TIME,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
)
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
||||
from .config_flow import DEVICE_SCHEMA
|
||||
from .const import CONF_CAMERA, CONF_EVENTS, DEFAULT_TRIGGER_TIME, DOMAIN
|
||||
from .device import AxisNetworkDevice, get_device
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{DOMAIN: cv.schema_with_slug_keys(DEVICE_SCHEMA)}, extra=vol.ALLOW_EXTRA
|
||||
)
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
"""Set up for Axis devices."""
|
||||
if not hass.config_entries.async_entries(DOMAIN) and DOMAIN in config:
|
||||
|
||||
for device_name, device_config in config[DOMAIN].items():
|
||||
|
||||
if CONF_NAME not in device_config:
|
||||
device_config[CONF_NAME] = device_name
|
||||
|
||||
hass.async_create_task(
|
||||
hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_IMPORT},
|
||||
data=device_config,
|
||||
)
|
||||
)
|
||||
|
||||
"""Old way to set up Axis devices."""
|
||||
return True
|
||||
|
||||
|
||||
|
@ -14,7 +14,6 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.util.json import load_json
|
||||
|
||||
from .const import CONF_MODEL, DOMAIN
|
||||
from .device import get_device
|
||||
@ -107,16 +106,12 @@ class AxisFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
except CannotConnect:
|
||||
errors["base"] = "device_unavailable"
|
||||
|
||||
data = (
|
||||
self.import_schema
|
||||
or self.discovery_schema
|
||||
or {
|
||||
vol.Required(CONF_HOST): str,
|
||||
vol.Required(CONF_USERNAME): str,
|
||||
vol.Required(CONF_PASSWORD): str,
|
||||
vol.Required(CONF_PORT, default=DEFAULT_PORT): int,
|
||||
}
|
||||
)
|
||||
data = self.discovery_schema or {
|
||||
vol.Required(CONF_HOST): str,
|
||||
vol.Required(CONF_USERNAME): str,
|
||||
vol.Required(CONF_PASSWORD): str,
|
||||
vol.Required(CONF_PORT, default=DEFAULT_PORT): int,
|
||||
}
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
@ -130,18 +125,17 @@ class AxisFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
|
||||
Generate a name to be used as a prefix for device entities.
|
||||
"""
|
||||
if self.name is None:
|
||||
same_model = [
|
||||
entry.data[CONF_NAME]
|
||||
for entry in self.hass.config_entries.async_entries(DOMAIN)
|
||||
if entry.data[CONF_MODEL] == self.model
|
||||
]
|
||||
same_model = [
|
||||
entry.data[CONF_NAME]
|
||||
for entry in self.hass.config_entries.async_entries(DOMAIN)
|
||||
if entry.data[CONF_MODEL] == self.model
|
||||
]
|
||||
|
||||
self.name = f"{self.model}"
|
||||
for idx in range(len(same_model) + 1):
|
||||
self.name = f"{self.model} {idx}"
|
||||
if self.name not in same_model:
|
||||
break
|
||||
self.name = f"{self.model}"
|
||||
for idx in range(len(same_model) + 1):
|
||||
self.name = f"{self.model} {idx}"
|
||||
if self.name not in same_model:
|
||||
break
|
||||
|
||||
data = {
|
||||
CONF_DEVICE: self.device_config,
|
||||
@ -187,53 +181,17 @@ class AxisFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
await self._update_entry(entry, discovery_info[CONF_HOST])
|
||||
return self.async_abort(reason="already_configured")
|
||||
|
||||
config_file = await self.hass.async_add_executor_job(
|
||||
load_json, self.hass.config.path(CONFIG_FILE)
|
||||
)
|
||||
|
||||
# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
|
||||
self.context["title_placeholders"] = {
|
||||
"name": discovery_info["hostname"][:-7],
|
||||
"host": discovery_info[CONF_HOST],
|
||||
}
|
||||
|
||||
if serialnumber not in config_file:
|
||||
self.discovery_schema = {
|
||||
vol.Required(CONF_HOST, default=discovery_info[CONF_HOST]): str,
|
||||
vol.Required(CONF_USERNAME): str,
|
||||
vol.Required(CONF_PASSWORD): str,
|
||||
vol.Required(CONF_PORT, default=discovery_info[CONF_PORT]): int,
|
||||
}
|
||||
|
||||
return await self.async_step_user()
|
||||
|
||||
try:
|
||||
device_config = DEVICE_SCHEMA(config_file[serialnumber])
|
||||
device_config[CONF_HOST] = discovery_info[CONF_HOST]
|
||||
|
||||
if CONF_NAME not in device_config:
|
||||
device_config[CONF_NAME] = discovery_info["hostname"]
|
||||
|
||||
except vol.Invalid:
|
||||
return self.async_abort(reason="bad_config_file")
|
||||
|
||||
return await self.async_step_import(device_config)
|
||||
|
||||
async def async_step_import(self, import_config):
|
||||
"""Import a Axis device as a config entry.
|
||||
|
||||
This flow is triggered by `async_setup` for configured devices.
|
||||
This flow is also triggered by `async_step_discovery`.
|
||||
|
||||
This will execute for any Axis device that contains a complete
|
||||
configuration.
|
||||
"""
|
||||
self.name = import_config[CONF_NAME]
|
||||
|
||||
self.import_schema = {
|
||||
vol.Required(CONF_HOST, default=import_config[CONF_HOST]): str,
|
||||
vol.Required(CONF_USERNAME, default=import_config[CONF_USERNAME]): str,
|
||||
vol.Required(CONF_PASSWORD, default=import_config[CONF_PASSWORD]): str,
|
||||
vol.Required(CONF_PORT, default=import_config[CONF_PORT]): int,
|
||||
self.discovery_schema = {
|
||||
vol.Required(CONF_HOST, default=discovery_info[CONF_HOST]): str,
|
||||
vol.Required(CONF_USERNAME): str,
|
||||
vol.Required(CONF_PASSWORD): str,
|
||||
vol.Required(CONF_PORT, default=discovery_info[CONF_PORT]): int,
|
||||
}
|
||||
return await self.async_step_user(user_input=import_config)
|
||||
|
||||
return await self.async_step_user()
|
||||
|
@ -196,52 +196,6 @@ async def test_zeroconf_flow(hass):
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
|
||||
async def test_zeroconf_flow_known_device(hass):
|
||||
"""Test that zeroconf discovery for known devices work.
|
||||
|
||||
This is legacy support from devices registered with configurator.
|
||||
"""
|
||||
with patch(
|
||||
"homeassistant.components.axis.config_flow.load_json",
|
||||
return_value={
|
||||
"00408C12345": {
|
||||
config_flow.CONF_HOST: "2.3.4.5",
|
||||
config_flow.CONF_USERNAME: "user",
|
||||
config_flow.CONF_PASSWORD: "pass",
|
||||
config_flow.CONF_PORT: 80,
|
||||
}
|
||||
},
|
||||
), patch("axis.AxisDevice") as mock_device:
|
||||
|
||||
def mock_constructor(loop, host, username, password, port, web_proto):
|
||||
"""Fake the controller constructor."""
|
||||
mock_device.loop = loop
|
||||
mock_device.host = host
|
||||
mock_device.username = username
|
||||
mock_device.password = password
|
||||
mock_device.port = port
|
||||
return mock_device
|
||||
|
||||
mock_device.side_effect = mock_constructor
|
||||
mock_device.vapix.params.system_serialnumber = "serialnumber"
|
||||
mock_device.vapix.params.prodnbr = "prodnbr"
|
||||
mock_device.vapix.params.prodtype = "prodtype"
|
||||
mock_device.vapix.params.firmware_version = "firmware_version"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
"hostname": "name",
|
||||
"properties": {"macaddress": "00408C12345"},
|
||||
},
|
||||
context={"source": "zeroconf"},
|
||||
)
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
|
||||
|
||||
async def test_zeroconf_flow_already_configured(hass):
|
||||
"""Test that zeroconf doesn't setup already configured devices."""
|
||||
entry = MockConfigEntry(
|
||||
@ -298,79 +252,3 @@ async def test_zeroconf_flow_ignore_link_local_address(hass):
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "link_local_address"
|
||||
|
||||
|
||||
async def test_zeroconf_flow_bad_config_file(hass):
|
||||
"""Test that zeroconf discovery with bad config files abort."""
|
||||
with patch(
|
||||
"homeassistant.components.axis.config_flow.load_json",
|
||||
return_value={
|
||||
"00408C12345": {
|
||||
config_flow.CONF_HOST: "2.3.4.5",
|
||||
config_flow.CONF_USERNAME: "user",
|
||||
config_flow.CONF_PASSWORD: "pass",
|
||||
config_flow.CONF_PORT: 80,
|
||||
}
|
||||
},
|
||||
), patch(
|
||||
"homeassistant.components.axis.config_flow.DEVICE_SCHEMA",
|
||||
side_effect=config_flow.vol.Invalid(""),
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
"hostname": "name",
|
||||
"properties": {"macaddress": "00408C12345"},
|
||||
},
|
||||
context={"source": "zeroconf"},
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "bad_config_file"
|
||||
|
||||
|
||||
async def test_import_flow_works(hass):
|
||||
"""Test that import flow works."""
|
||||
with patch("axis.AxisDevice") as mock_device:
|
||||
|
||||
def mock_constructor(loop, host, username, password, port, web_proto):
|
||||
"""Fake the controller constructor."""
|
||||
mock_device.loop = loop
|
||||
mock_device.host = host
|
||||
mock_device.username = username
|
||||
mock_device.password = password
|
||||
mock_device.port = port
|
||||
return mock_device
|
||||
|
||||
mock_device.side_effect = mock_constructor
|
||||
mock_device.vapix.params.system_serialnumber = "serialnumber"
|
||||
mock_device.vapix.params.prodnbr = "prodnbr"
|
||||
mock_device.vapix.params.prodtype = "prodtype"
|
||||
mock_device.vapix.params.firmware_version = "firmware_version"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_USERNAME: "user",
|
||||
config_flow.CONF_PASSWORD: "pass",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_NAME: "name",
|
||||
},
|
||||
context={"source": "import"},
|
||||
)
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == "{} - {}".format("prodnbr", "serialnumber")
|
||||
assert result["data"] == {
|
||||
axis.CONF_DEVICE: {
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_USERNAME: "user",
|
||||
config_flow.CONF_PASSWORD: "pass",
|
||||
config_flow.CONF_PORT: 80,
|
||||
},
|
||||
config_flow.CONF_MAC: "serialnumber",
|
||||
config_flow.CONF_MODEL: "prodnbr",
|
||||
config_flow.CONF_NAME: "name",
|
||||
}
|
||||
|
@ -7,26 +7,6 @@ from homeassistant.setup import async_setup_component
|
||||
from tests.common import MockConfigEntry, mock_coro
|
||||
|
||||
|
||||
async def test_setup(hass):
|
||||
"""Test configured options for a device are loaded via config entry."""
|
||||
with patch.object(hass.config_entries, "flow") as mock_config_flow:
|
||||
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
axis.DOMAIN,
|
||||
{
|
||||
axis.DOMAIN: {
|
||||
"device_name": {
|
||||
axis.config_flow.CONF_HOST: "1.2.3.4",
|
||||
axis.config_flow.CONF_PORT: 80,
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
assert len(mock_config_flow.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_setup_device_already_configured(hass):
|
||||
"""Test already configured device does not configure a second."""
|
||||
with patch.object(hass, "config_entries") as mock_config_entries:
|
||||
|
Loading…
x
Reference in New Issue
Block a user