mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Merge onvif host/auth step, allow skipping scan (#49660)
This commit is contained in:
parent
fd1d110b80
commit
3a5ee00081
@ -91,10 +91,15 @@ class OnvifFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
async def async_step_user(self, user_input=None):
|
async def async_step_user(self, user_input=None):
|
||||||
"""Handle user flow."""
|
"""Handle user flow."""
|
||||||
if user_input is not None:
|
if user_input:
|
||||||
|
if user_input["auto"]:
|
||||||
return await self.async_step_device()
|
return await self.async_step_device()
|
||||||
|
return await self.async_step_configure()
|
||||||
|
|
||||||
return self.async_show_form(step_id="user")
|
return self.async_show_form(
|
||||||
|
step_id="user",
|
||||||
|
data_schema=vol.Schema({vol.Required("auto", default=True): bool}),
|
||||||
|
)
|
||||||
|
|
||||||
async def async_step_device(self, user_input=None):
|
async def async_step_device(self, user_input=None):
|
||||||
"""Handle WS-Discovery.
|
"""Handle WS-Discovery.
|
||||||
@ -105,7 +110,7 @@ class OnvifFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
if user_input:
|
if user_input:
|
||||||
|
|
||||||
if CONF_MANUAL_INPUT == user_input[CONF_HOST]:
|
if CONF_MANUAL_INPUT == user_input[CONF_HOST]:
|
||||||
return await self.async_step_manual_input()
|
return await self.async_step_configure()
|
||||||
|
|
||||||
for device in self.devices:
|
for device in self.devices:
|
||||||
name = f"{device[CONF_NAME]} ({device[CONF_HOST]})"
|
name = f"{device[CONF_NAME]} ({device[CONF_HOST]})"
|
||||||
@ -116,7 +121,7 @@ class OnvifFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
CONF_HOST: device[CONF_HOST],
|
CONF_HOST: device[CONF_HOST],
|
||||||
CONF_PORT: device[CONF_PORT],
|
CONF_PORT: device[CONF_PORT],
|
||||||
}
|
}
|
||||||
return await self.async_step_auth()
|
return await self.async_step_configure()
|
||||||
|
|
||||||
discovery = await async_discovery(self.hass)
|
discovery = await async_discovery(self.hass)
|
||||||
for device in discovery:
|
for device in discovery:
|
||||||
@ -142,44 +147,33 @@ class OnvifFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
data_schema=vol.Schema({vol.Optional(CONF_HOST): vol.In(names)}),
|
data_schema=vol.Schema({vol.Optional(CONF_HOST): vol.In(names)}),
|
||||||
)
|
)
|
||||||
|
|
||||||
return await self.async_step_manual_input()
|
return await self.async_step_configure()
|
||||||
|
|
||||||
async def async_step_manual_input(self, user_input=None):
|
async def async_step_configure(self, user_input=None, errors=None):
|
||||||
"""Manual configuration."""
|
"""Device configuration."""
|
||||||
if user_input:
|
if user_input:
|
||||||
self.onvif_config = user_input
|
self.onvif_config = user_input
|
||||||
return await self.async_step_auth()
|
|
||||||
|
|
||||||
return self.async_show_form(
|
|
||||||
step_id="manual_input",
|
|
||||||
data_schema=vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Required(CONF_NAME): str,
|
|
||||||
vol.Required(CONF_HOST): str,
|
|
||||||
vol.Required(CONF_PORT, default=DEFAULT_PORT): int,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
async def async_step_auth(self, user_input=None):
|
|
||||||
"""Username and Password configuration for ONVIF device."""
|
|
||||||
if user_input:
|
|
||||||
self.onvif_config[CONF_USERNAME] = user_input[CONF_USERNAME]
|
|
||||||
self.onvif_config[CONF_PASSWORD] = user_input[CONF_PASSWORD]
|
|
||||||
return await self.async_step_profiles()
|
return await self.async_step_profiles()
|
||||||
|
|
||||||
|
def conf(name, default=None):
|
||||||
|
return self.onvif_config.get(name, default)
|
||||||
|
|
||||||
# Username and Password are optional and default empty
|
# Username and Password are optional and default empty
|
||||||
# due to some cameras not allowing you to change ONVIF user settings.
|
# due to some cameras not allowing you to change ONVIF user settings.
|
||||||
# See https://github.com/home-assistant/core/issues/39182
|
# See https://github.com/home-assistant/core/issues/39182
|
||||||
# and https://github.com/home-assistant/core/issues/35904
|
# and https://github.com/home-assistant/core/issues/35904
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="auth",
|
step_id="configure",
|
||||||
data_schema=vol.Schema(
|
data_schema=vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_USERNAME, default=""): str,
|
vol.Required(CONF_NAME, default=conf(CONF_NAME)): str,
|
||||||
vol.Optional(CONF_PASSWORD, default=""): str,
|
vol.Required(CONF_HOST, default=conf(CONF_HOST)): str,
|
||||||
|
vol.Required(CONF_PORT, default=conf(CONF_PORT, DEFAULT_PORT)): int,
|
||||||
|
vol.Optional(CONF_USERNAME, default=conf(CONF_USERNAME, "")): str,
|
||||||
|
vol.Optional(CONF_PASSWORD, default=conf(CONF_PASSWORD, "")): str,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
errors=errors,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_profiles(self, user_input=None):
|
async def async_step_profiles(self, user_input=None):
|
||||||
@ -268,7 +262,7 @@ class OnvifFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
finally:
|
finally:
|
||||||
await device.close()
|
await device.close()
|
||||||
|
|
||||||
return self.async_show_form(step_id="auth", errors=errors)
|
return await self.async_step_configure(errors=errors)
|
||||||
|
|
||||||
async def async_step_import(self, user_input):
|
async def async_step_import(self, user_input):
|
||||||
"""Handle import."""
|
"""Handle import."""
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
},
|
},
|
||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"auto": "Search automatically"
|
||||||
|
},
|
||||||
"title": "ONVIF device setup",
|
"title": "ONVIF device setup",
|
||||||
"description": "By clicking submit, we will search your network for ONVIF devices that support Profile S.\n\nSome manufacturers have started to disable ONVIF by default. Please ensure ONVIF is enabled in your camera's configuration."
|
"description": "By clicking submit, we will search your network for ONVIF devices that support Profile S.\n\nSome manufacturers have started to disable ONVIF by default. Please ensure ONVIF is enabled in your camera's configuration."
|
||||||
},
|
},
|
||||||
@ -21,20 +24,15 @@
|
|||||||
},
|
},
|
||||||
"title": "Select ONVIF device"
|
"title": "Select ONVIF device"
|
||||||
},
|
},
|
||||||
"manual_input": {
|
"configure": {
|
||||||
"data": {
|
"data": {
|
||||||
"name": "[%key:common::config_flow::data::name%]",
|
"name": "[%key:common::config_flow::data::name%]",
|
||||||
"host": "[%key:common::config_flow::data::host%]",
|
"host": "[%key:common::config_flow::data::host%]",
|
||||||
"port": "[%key:common::config_flow::data::port%]"
|
"port": "[%key:common::config_flow::data::port%]",
|
||||||
},
|
|
||||||
"title": "Configure ONVIF device"
|
|
||||||
},
|
|
||||||
"auth": {
|
|
||||||
"title": "Configure authentication",
|
|
||||||
"data": {
|
|
||||||
"username": "[%key:common::config_flow::data::username%]",
|
"username": "[%key:common::config_flow::data::username%]",
|
||||||
"password": "[%key:common::config_flow::data::password%]"
|
"password": "[%key:common::config_flow::data::password%]"
|
||||||
}
|
},
|
||||||
|
"title": "Configure ONVIF device"
|
||||||
},
|
},
|
||||||
"configure_profile": {
|
"configure_profile": {
|
||||||
"description": "Create camera entity for {profile} at {resolution} resolution?",
|
"description": "Create camera entity for {profile} at {resolution} resolution?",
|
||||||
|
@ -11,12 +11,15 @@
|
|||||||
"cannot_connect": "Failed to connect"
|
"cannot_connect": "Failed to connect"
|
||||||
},
|
},
|
||||||
"step": {
|
"step": {
|
||||||
"auth": {
|
"configure": {
|
||||||
"data": {
|
"data": {
|
||||||
|
"host": "Host",
|
||||||
|
"name": "Name",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
|
"port": "Port",
|
||||||
"username": "Username"
|
"username": "Username"
|
||||||
},
|
},
|
||||||
"title": "Configure authentication"
|
"title": "Configure ONVIF device"
|
||||||
},
|
},
|
||||||
"configure_profile": {
|
"configure_profile": {
|
||||||
"data": {
|
"data": {
|
||||||
@ -31,15 +34,10 @@
|
|||||||
},
|
},
|
||||||
"title": "Select ONVIF device"
|
"title": "Select ONVIF device"
|
||||||
},
|
},
|
||||||
"manual_input": {
|
|
||||||
"data": {
|
|
||||||
"host": "Host",
|
|
||||||
"name": "Name",
|
|
||||||
"port": "Port"
|
|
||||||
},
|
|
||||||
"title": "Configure ONVIF device"
|
|
||||||
},
|
|
||||||
"user": {
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"auto": "Search automatically"
|
||||||
|
},
|
||||||
"description": "By clicking submit, we will search your network for ONVIF devices that support Profile S.\n\nSome manufacturers have started to disable ONVIF by default. Please ensure ONVIF is enabled in your camera's configuration.",
|
"description": "By clicking submit, we will search your network for ONVIF devices that support Profile S.\n\nSome manufacturers have started to disable ONVIF by default. Please ensure ONVIF is enabled in your camera's configuration.",
|
||||||
"title": "ONVIF device setup"
|
"title": "ONVIF device setup"
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,7 @@ async def test_flow_discovered_devices(hass):
|
|||||||
setup_mock_device(mock_device)
|
setup_mock_device(mock_device)
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={}
|
result["flow_id"], user_input={"auto": True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@ -215,7 +215,7 @@ async def test_flow_discovered_devices(hass):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "auth"
|
assert result["step_id"] == "configure"
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.onvif.async_setup", return_value=True
|
"homeassistant.components.onvif.async_setup", return_value=True
|
||||||
@ -268,7 +268,7 @@ async def test_flow_discovered_devices_ignore_configured_manual_input(hass):
|
|||||||
setup_mock_device(mock_device)
|
setup_mock_device(mock_device)
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={}
|
result["flow_id"], user_input={"auto": True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@ -281,7 +281,37 @@ async def test_flow_discovered_devices_ignore_configured_manual_input(hass):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "manual_input"
|
assert result["step_id"] == "configure"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_flow_discovered_no_device(hass):
|
||||||
|
"""Test that config flow discovery no device."""
|
||||||
|
await setup_onvif_integration(hass)
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
config_flow.DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "user"
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.onvif.config_flow.get_device"
|
||||||
|
) as mock_onvif_camera, patch(
|
||||||
|
"homeassistant.components.onvif.config_flow.wsdiscovery"
|
||||||
|
) as mock_discovery, patch(
|
||||||
|
"homeassistant.components.onvif.ONVIFDevice"
|
||||||
|
) as mock_device:
|
||||||
|
setup_mock_onvif_camera(mock_onvif_camera)
|
||||||
|
mock_discovery.return_value = []
|
||||||
|
setup_mock_device(mock_device)
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={"auto": True}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "configure"
|
||||||
|
|
||||||
|
|
||||||
async def test_flow_discovery_ignore_existing_and_abort(hass):
|
async def test_flow_discovery_ignore_existing_and_abort(hass):
|
||||||
@ -319,12 +349,12 @@ async def test_flow_discovery_ignore_existing_and_abort(hass):
|
|||||||
setup_mock_device(mock_device)
|
setup_mock_device(mock_device)
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={}
|
result["flow_id"], user_input={"auto": True}
|
||||||
)
|
)
|
||||||
|
|
||||||
# It should skip to manual entry if the only devices are already configured
|
# It should skip to manual entry if the only devices are already configured
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "manual_input"
|
assert result["step_id"] == "configure"
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
@ -332,15 +362,6 @@ async def test_flow_discovery_ignore_existing_and_abort(hass):
|
|||||||
config_flow.CONF_NAME: NAME,
|
config_flow.CONF_NAME: NAME,
|
||||||
config_flow.CONF_HOST: HOST,
|
config_flow.CONF_HOST: HOST,
|
||||||
config_flow.CONF_PORT: PORT,
|
config_flow.CONF_PORT: PORT,
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
||||||
assert result["step_id"] == "auth"
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
|
||||||
result["flow_id"],
|
|
||||||
user_input={
|
|
||||||
config_flow.CONF_USERNAME: USERNAME,
|
config_flow.CONF_USERNAME: USERNAME,
|
||||||
config_flow.CONF_PASSWORD: PASSWORD,
|
config_flow.CONF_PASSWORD: PASSWORD,
|
||||||
},
|
},
|
||||||
@ -373,23 +394,11 @@ async def test_flow_manual_entry(hass):
|
|||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={},
|
user_input={"auto": False},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "manual_input"
|
assert result["step_id"] == "configure"
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
|
||||||
result["flow_id"],
|
|
||||||
user_input={
|
|
||||||
config_flow.CONF_NAME: NAME,
|
|
||||||
config_flow.CONF_HOST: HOST,
|
|
||||||
config_flow.CONF_PORT: PORT,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
||||||
assert result["step_id"] == "auth"
|
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.onvif.async_setup", return_value=True
|
"homeassistant.components.onvif.async_setup", return_value=True
|
||||||
@ -399,6 +408,9 @@ async def test_flow_manual_entry(hass):
|
|||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={
|
user_input={
|
||||||
|
config_flow.CONF_NAME: NAME,
|
||||||
|
config_flow.CONF_HOST: HOST,
|
||||||
|
config_flow.CONF_PORT: PORT,
|
||||||
config_flow.CONF_USERNAME: USERNAME,
|
config_flow.CONF_USERNAME: USERNAME,
|
||||||
config_flow.CONF_PASSWORD: PASSWORD,
|
config_flow.CONF_PASSWORD: PASSWORD,
|
||||||
},
|
},
|
||||||
@ -598,7 +610,7 @@ async def test_flow_import_onvif_auth_error(hass):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "auth"
|
assert result["step_id"] == "configure"
|
||||||
assert result["errors"]["base"] == "cannot_connect"
|
assert result["errors"]["base"] == "cannot_connect"
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user