diff --git a/homeassistant/components/motion_blinds/config_flow.py b/homeassistant/components/motion_blinds/config_flow.py index d861c989ee0..d93e0091369 100644 --- a/homeassistant/components/motion_blinds/config_flow.py +++ b/homeassistant/components/motion_blinds/config_flow.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Any -from motionblinds import MotionDiscovery +from motionblinds import MotionDiscovery, MotionGateway import voluptuous as vol from homeassistant import config_entries @@ -86,6 +86,16 @@ class MotionBlindsFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): await self.async_set_unique_id(mac_address) self._abort_if_unique_id_configured(updates={CONF_HOST: discovery_info.ip}) + gateway = MotionGateway(ip=discovery_info.ip, key="abcd1234-56ef-78") + try: + # key not needed for GetDeviceList request + await self.hass.async_add_executor_job(gateway.GetDeviceList) + except Exception: # pylint: disable=broad-except + return self.async_abort(reason="not_motionblinds") + + if not gateway.available: + return self.async_abort(reason="not_motionblinds") + short_mac = mac_address[-6:].upper() self.context["title_placeholders"] = { "short_mac": short_mac, diff --git a/homeassistant/components/motion_blinds/strings.json b/homeassistant/components/motion_blinds/strings.json index 0b1482883aa..47c0867187e 100644 --- a/homeassistant/components/motion_blinds/strings.json +++ b/homeassistant/components/motion_blinds/strings.json @@ -28,7 +28,8 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]", - "connection_error": "[%key:common::config_flow::error::cannot_connect%]" + "connection_error": "[%key:common::config_flow::error::cannot_connect%]", + "not_motionblinds": "Discovered device is not a Motion gateway" } }, "options": { diff --git a/tests/components/motion_blinds/test_config_flow.py b/tests/components/motion_blinds/test_config_flow.py index 5c95b4abd18..ceb20279c1f 100644 --- a/tests/components/motion_blinds/test_config_flow.py +++ b/tests/components/motion_blinds/test_config_flow.py @@ -89,6 +89,12 @@ def motion_blinds_connect_fixture(mock_get_source_ip): ), patch( "homeassistant.components.motion_blinds.config_flow.MotionDiscovery.discover", return_value=TEST_DISCOVERY_1, + ), patch( + "homeassistant.components.motion_blinds.config_flow.MotionGateway.GetDeviceList", + return_value=True, + ), patch( + "homeassistant.components.motion_blinds.config_flow.MotionGateway.available", + True, ), patch( "homeassistant.components.motion_blinds.gateway.AsyncMotionMulticast.Start_listen", return_value=True, @@ -355,6 +361,46 @@ async def test_dhcp_flow(hass: HomeAssistant) -> None: } +async def test_dhcp_flow_abort(hass: HomeAssistant) -> None: + """Test that DHCP discovery aborts if not Motion Blinds.""" + dhcp_data = dhcp.DhcpServiceInfo( + ip=TEST_HOST, + hostname="MOTION_abcdef", + macaddress=TEST_MAC, + ) + + with patch( + "homeassistant.components.motion_blinds.config_flow.MotionGateway.GetDeviceList", + side_effect=socket.timeout, + ): + result = await hass.config_entries.flow.async_init( + const.DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=dhcp_data + ) + + assert result["type"] == "abort" + assert result["reason"] == "not_motionblinds" + + +async def test_dhcp_flow_abort_invalid_response(hass: HomeAssistant) -> None: + """Test that DHCP discovery aborts if device responded with invalid data.""" + dhcp_data = dhcp.DhcpServiceInfo( + ip=TEST_HOST, + hostname="MOTION_abcdef", + macaddress=TEST_MAC, + ) + + with patch( + "homeassistant.components.motion_blinds.config_flow.MotionGateway.available", + False, + ): + result = await hass.config_entries.flow.async_init( + const.DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=dhcp_data + ) + + assert result["type"] == "abort" + assert result["reason"] == "not_motionblinds" + + async def test_options_flow(hass: HomeAssistant) -> None: """Test specifying non default settings using options flow.""" config_entry = MockConfigEntry(