From 5f5951e71c7c358e447611465be00dc058e85e25 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 27 May 2023 19:47:13 -0500 Subject: [PATCH] Add hardware model to onvif config flow discovery (#93676) --- homeassistant/components/onvif/config_flow.py | 20 +++++++++------- homeassistant/components/onvif/const.py | 1 + tests/components/onvif/test_config_flow.py | 23 ++++++++++++++++--- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/onvif/config_flow.py b/homeassistant/components/onvif/config_flow.py index 020649db87e..0d0ddc180df 100644 --- a/homeassistant/components/onvif/config_flow.py +++ b/homeassistant/components/onvif/config_flow.py @@ -35,6 +35,7 @@ from homeassistant.helpers import device_registry as dr from .const import ( CONF_DEVICE_ID, CONF_ENABLE_WEBHOOKS, + CONF_HARDWARE, DEFAULT_ARGUMENTS, DEFAULT_ENABLE_WEBHOOKS, DEFAULT_PORT, @@ -71,11 +72,14 @@ async def async_discovery(hass: HomeAssistant) -> list[dict[str, Any]]: CONF_NAME: service.getEPR(), CONF_HOST: url.hostname, CONF_PORT: url.port or 80, + CONF_HARDWARE: None, } for scope in service.getScopes(): scope_str = scope.getValue() if scope_str.lower().startswith("onvif://www.onvif.org/name"): device[CONF_NAME] = scope_str.split("/")[-1] + if scope_str.lower().startswith("onvif://www.onvif.org/hardware"): + device[CONF_HARDWARE] = scope_str.split("/")[-1] if scope_str.lower().startswith("onvif://www.onvif.org/mac"): device[CONF_DEVICE_ID] = scope_str.split("/")[-1] devices.append(device) @@ -192,8 +196,7 @@ class OnvifFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return await self.async_step_configure() for device in self.devices: - name = f"{device[CONF_NAME]} ({device[CONF_HOST]})" - if name == user_input[CONF_HOST]: + if device[CONF_HOST] == user_input[CONF_HOST]: self.device_id = device[CONF_DEVICE_ID] self.onvif_config = { CONF_NAME: device[CONF_NAME], @@ -215,15 +218,16 @@ class OnvifFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): LOGGER.debug("Discovered ONVIF devices %s", pformat(self.devices)) if self.devices: - names = [ - f"{device[CONF_NAME]} ({device[CONF_HOST]})" for device in self.devices - ] - - names.append(CONF_MANUAL_INPUT) + devices = {CONF_MANUAL_INPUT: CONF_MANUAL_INPUT} + for device in self.devices: + description = f"{device[CONF_NAME]} ({device[CONF_HOST]})" + if hardware := device[CONF_HARDWARE]: + description += f" [{hardware}]" + devices[device[CONF_HOST]] = description return self.async_show_form( step_id="device", - data_schema=vol.Schema({vol.Optional(CONF_HOST): vol.In(names)}), + data_schema=vol.Schema({vol.Optional(CONF_HOST): vol.In(devices)}), ) return await self.async_step_configure() diff --git a/homeassistant/components/onvif/const.py b/homeassistant/components/onvif/const.py index 8d95ef484bf..77fa098a316 100644 --- a/homeassistant/components/onvif/const.py +++ b/homeassistant/components/onvif/const.py @@ -13,6 +13,7 @@ DEFAULT_PORT = 80 DEFAULT_ARGUMENTS = "-pred 1" CONF_DEVICE_ID = "deviceid" +CONF_HARDWARE = "hardware" CONF_SNAPSHOT_AUTH = "snapshot_auth" CONF_ENABLE_WEBHOOKS = "enable_webhooks" DEFAULT_ENABLE_WEBHOOKS = True diff --git a/tests/components/onvif/test_config_flow.py b/tests/components/onvif/test_config_flow.py index 981620e7ae0..adb8a33251c 100644 --- a/tests/components/onvif/test_config_flow.py +++ b/tests/components/onvif/test_config_flow.py @@ -32,6 +32,7 @@ DISCOVERY = [ config_flow.CONF_HOST: HOST, config_flow.CONF_PORT: PORT, "MAC": MAC, + "HARDWARE": "IPC model", }, { "EPR": "urn:uuid:987654321", @@ -54,7 +55,11 @@ DHCP_DISCOVERY_SAME_IP = dhcp.DhcpServiceInfo( def setup_mock_discovery( - mock_discovery, with_name=False, with_mac=False, two_devices=False + mock_discovery, + with_name=False, + with_mac=False, + two_devices=False, + with_hardware=True, ): """Prepare mock discovery result.""" services = [] @@ -79,6 +84,12 @@ def setup_mock_discovery( return_value=f"onvif://www.onvif.org/mac/{item['MAC']}" ) scopes.append(scope) + if with_hardware and "HARDWARE" in item: + scope = MagicMock() + scope.getValue = MagicMock( + return_value=f"onvif://www.onvif.org/hardware/{item['HARDWARE']}" + ) + scopes.append(scope) service.getScopes = MagicMock(return_value=scopes) services.append(service) mock_discovery.return_value = services @@ -111,10 +122,16 @@ async def test_flow_discovered_devices(hass: HomeAssistant) -> None: assert result["type"] == data_entry_flow.FlowResultType.FORM assert result["step_id"] == "device" - assert len(result["data_schema"].schema[config_flow.CONF_HOST].container) == 3 + container = result["data_schema"].schema[config_flow.CONF_HOST].container + assert len(container) == 3 + assert container == { + "Manually configure ONVIF device": "Manually configure ONVIF device", + "1.2.3.4": "urn:uuid:123456789 (1.2.3.4) [IPC model]", + "5.6.7.8": "urn:uuid:987654321 (5.6.7.8)", + } result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input={config_flow.CONF_HOST: f"{URN} ({HOST})"} + result["flow_id"], user_input={config_flow.CONF_HOST: HOST} ) assert result["type"] == data_entry_flow.FlowResultType.FORM