async def test_scan_description_fetch_fail(hass, aioclient_mock, exc): """Test failing to fetch description.""" aioclient_mock.get("http://1.1.1.1", exc=exc) mock_ssdp_response = { "st": "mock-st", "usn": "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL::urn:mdx-netflix-com:service:target:3", "location": "http://1.1.1.1", } mock_get_ssdp = { "mock-domain": [ { ssdp.ATTR_UPNP_DEVICE_TYPE: "Paulus", ssdp.ATTR_UPNP_MANUFACTURER: "Paulus", } ] } mock_init = await _async_run_mocked_scan(hass, mock_ssdp_response, mock_get_ssdp) assert not mock_init.mock_calls assert ssdp.async_get_discovery_info_by_st(hass, "mock-st") == [ { "UDN": "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL", "ssdp_location": "http://1.1.1.1", "ssdp_st": "mock-st", "ssdp_usn": "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL::urn:mdx-netflix-com:service:target:3", } ]
async def async_discover(cls, hass: HomeAssistant) -> list[Mapping]: """Discover UPnP/IGD devices.""" _LOGGER.debug("Discovering UPnP/IGD devices") discoveries = [] for ssdp_st in IgdDevice.DEVICE_TYPES: for discovery_info in ssdp.async_get_discovery_info_by_st(hass, ssdp_st): discoveries.append(discovery_info_to_discovery(discovery_info)) return discoveries
async def get_upnp_desc(hass: HomeAssistant, host: str): """Get the upnp description URL for a given host, using the SSPD scanner.""" ssdp_entries = ssdp.async_get_discovery_info_by_st(hass, "upnp:rootdevice") matches = [w for w in ssdp_entries if w.get("_host", "") == host] upnp_desc = None for match in matches: if match.get(ssdp.ATTR_SSDP_LOCATION): upnp_desc = match[ssdp.ATTR_SSDP_LOCATION] break if not upnp_desc: _LOGGER.warning( "The upnp_description was not found automatically, setting a default one" ) upnp_desc = f"http://{host}:49154/MediaRenderer/desc.xml" return upnp_desc
async def test_scan_second_hit(hass, aioclient_mock, caplog): """Test matching on second scan.""" aioclient_mock.get( "http://1.1.1.1", text=""" <root> <device> <deviceType>Paulus</deviceType> </device> </root> """, ) mock_ssdp_response = CaseInsensitiveDict( **{ "ST": "mock-st", "LOCATION": "http://1.1.1.1", "USN": "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL::urn:mdx-netflix-com:service:target:3", "SERVER": "mock-server", "EXT": "", } ) mock_get_ssdp = {"mock-domain": [{"st": "mock-st"}]} integration_callbacks = [] @callback def _async_integration_callbacks(info): integration_callbacks.append(info) def _generate_fake_ssdp_listener(*args, **kwargs): listener = SSDPListener(*args, **kwargs) async def _async_callback(*_): pass @callback def _callback(*_): hass.async_create_task(listener.async_callback(mock_ssdp_response)) listener.async_start = _async_callback listener.async_search = _callback return listener with patch( "homeassistant.components.ssdp.async_get_ssdp", return_value=mock_get_ssdp, ), patch( "homeassistant.components.ssdp.SSDPListener", new=_generate_fake_ssdp_listener, ), patch.object( hass.config_entries.flow, "async_init", return_value=mock_coro() ) as mock_init: assert await async_setup_component(hass, ssdp.DOMAIN, {ssdp.DOMAIN: {}}) await hass.async_block_till_done() remove = ssdp.async_register_callback( hass, _async_integration_callbacks, {"st": "mock-st"}, ) hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=200)) await hass.async_block_till_done() async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=200)) await hass.async_block_till_done() remove() async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=200)) await hass.async_block_till_done() assert len(integration_callbacks) == 4 assert integration_callbacks[0] == { ssdp.ATTR_UPNP_DEVICE_TYPE: "Paulus", ssdp.ATTR_SSDP_EXT: "", ssdp.ATTR_SSDP_LOCATION: "http://1.1.1.1", ssdp.ATTR_SSDP_SERVER: "mock-server", ssdp.ATTR_SSDP_ST: "mock-st", ssdp.ATTR_SSDP_USN: "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL::urn:mdx-netflix-com:service:target:3", ssdp.ATTR_UPNP_UDN: "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL", } assert len(mock_init.mock_calls) == 1 assert mock_init.mock_calls[0][1][0] == "mock-domain" assert mock_init.mock_calls[0][2]["context"] == { "source": config_entries.SOURCE_SSDP } assert mock_init.mock_calls[0][2]["data"] == { ssdp.ATTR_UPNP_DEVICE_TYPE: "Paulus", ssdp.ATTR_SSDP_ST: "mock-st", ssdp.ATTR_SSDP_LOCATION: "http://1.1.1.1", ssdp.ATTR_SSDP_SERVER: "mock-server", ssdp.ATTR_SSDP_EXT: "", ssdp.ATTR_SSDP_USN: "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL::urn:mdx-netflix-com:service:target:3", ssdp.ATTR_UPNP_UDN: "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL", } assert "Failed to fetch ssdp data" not in caplog.text udn_discovery_info = ssdp.async_get_discovery_info_by_st(hass, "mock-st") discovery_info = udn_discovery_info[0] assert discovery_info[ssdp.ATTR_SSDP_LOCATION] == "http://1.1.1.1" assert discovery_info[ssdp.ATTR_SSDP_ST] == "mock-st" assert ( discovery_info[ssdp.ATTR_UPNP_UDN] == "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL" ) assert ( discovery_info[ssdp.ATTR_SSDP_USN] == "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL::urn:mdx-netflix-com:service:target:3" ) st_discovery_info = ssdp.async_get_discovery_info_by_udn( hass, "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL" ) discovery_info = st_discovery_info[0] assert discovery_info[ssdp.ATTR_SSDP_LOCATION] == "http://1.1.1.1" assert discovery_info[ssdp.ATTR_SSDP_ST] == "mock-st" assert ( discovery_info[ssdp.ATTR_UPNP_UDN] == "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL" ) assert ( discovery_info[ssdp.ATTR_SSDP_USN] == "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL::urn:mdx-netflix-com:service:target:3" ) discovery_info = ssdp.async_get_discovery_info_by_udn_st( hass, "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL", "mock-st" ) assert discovery_info[ssdp.ATTR_SSDP_LOCATION] == "http://1.1.1.1" assert discovery_info[ssdp.ATTR_SSDP_ST] == "mock-st" assert ( discovery_info[ssdp.ATTR_UPNP_UDN] == "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL" ) assert ( discovery_info[ssdp.ATTR_SSDP_USN] == "uuid:TIVRTLSR7ANF-D6E-1557809135086-RETAIL::urn:mdx-netflix-com:service:target:3" ) assert ssdp.async_get_discovery_info_by_udn_st(hass, "wrong", "mock-st") is None
def _discovery_igd_devices(hass: HomeAssistant) -> list[Mapping[str, Any]]: """Discovery IGD devices.""" return ssdp.async_get_discovery_info_by_st( hass, ST_IGD_V1) + ssdp.async_get_discovery_info_by_st( hass, ST_IGD_V2)