Ensure ssdp can callback messages that do not have an ST (#51436)
* Ensure ssdp can callback messages that do not have an ST Sonos sends unsolicited messages when the device reboots. We want to capture these to ensure we can recover the subscriptions as soon as the device reboots * Update homeassistant/components/ssdp/__init__.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
909140a7c6
commit
12ac4109f4
2 changed files with 107 additions and 10 deletions
|
@ -478,6 +478,94 @@ async def test_scan_with_registered_callback(hass, aioclient_mock, caplog):
|
|||
assert "Failed to callback info" in caplog.text
|
||||
|
||||
|
||||
async def test_unsolicited_ssdp_registered_callback(hass, aioclient_mock, caplog):
|
||||
"""Test matching based on callback can handle unsolicited ssdp traffic without st."""
|
||||
aioclient_mock.get(
|
||||
"http://10.6.9.12:1400/xml/device_description.xml",
|
||||
text="""
|
||||
<root>
|
||||
<device>
|
||||
<deviceType>Paulus</deviceType>
|
||||
</device>
|
||||
</root>
|
||||
""",
|
||||
)
|
||||
mock_ssdp_response = {
|
||||
"location": "http://10.6.9.12:1400/xml/device_description.xml",
|
||||
"nt": "uuid:RINCON_1111BB963FD801400",
|
||||
"nts": "ssdp:alive",
|
||||
"server": "Linux UPnP/1.0 Sonos/63.2-88230 (ZPS12)",
|
||||
"usn": "uuid:RINCON_1111BB963FD801400",
|
||||
"x-rincon-household": "Sonos_dfjfkdghjhkjfhkdjfhkd",
|
||||
"x-rincon-bootseq": "250",
|
||||
"bootid.upnp.org": "250",
|
||||
"x-rincon-wifimode": "0",
|
||||
"x-rincon-variant": "1",
|
||||
"household.smartspeaker.audio": "Sonos_v3294823948542543534",
|
||||
}
|
||||
intergration_callbacks = []
|
||||
|
||||
@callback
|
||||
def _async_intergration_callbacks(info):
|
||||
intergration_callbacks.append(info)
|
||||
|
||||
def _generate_fake_ssdp_listener(*args, **kwargs):
|
||||
listener = SSDPListener(*args, **kwargs)
|
||||
|
||||
async def _async_callback(*_):
|
||||
await listener.async_callback(mock_ssdp_response)
|
||||
|
||||
@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.SSDPListener",
|
||||
new=_generate_fake_ssdp_listener,
|
||||
):
|
||||
hass.state = CoreState.stopped
|
||||
assert await async_setup_component(hass, ssdp.DOMAIN, {ssdp.DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
ssdp.async_register_callback(
|
||||
hass,
|
||||
_async_intergration_callbacks,
|
||||
{"nts": "ssdp:alive", "x-rincon-bootseq": MATCH_ALL},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=200))
|
||||
await hass.async_block_till_done()
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
hass.state = CoreState.running
|
||||
await hass.async_block_till_done()
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=200))
|
||||
await hass.async_block_till_done()
|
||||
assert hass.state == CoreState.running
|
||||
|
||||
assert (
|
||||
len(intergration_callbacks) == 2
|
||||
) # unsolicited callbacks without st are not cached
|
||||
assert intergration_callbacks[0] == {
|
||||
"UDN": "uuid:RINCON_1111BB963FD801400",
|
||||
"bootid.upnp.org": "250",
|
||||
"deviceType": "Paulus",
|
||||
"household.smartspeaker.audio": "Sonos_v3294823948542543534",
|
||||
"nt": "uuid:RINCON_1111BB963FD801400",
|
||||
"nts": "ssdp:alive",
|
||||
"ssdp_location": "http://10.6.9.12:1400/xml/device_description.xml",
|
||||
"ssdp_server": "Linux UPnP/1.0 Sonos/63.2-88230 (ZPS12)",
|
||||
"ssdp_usn": "uuid:RINCON_1111BB963FD801400",
|
||||
"x-rincon-bootseq": "250",
|
||||
"x-rincon-household": "Sonos_dfjfkdghjhkjfhkdjfhkd",
|
||||
"x-rincon-variant": "1",
|
||||
"x-rincon-wifimode": "0",
|
||||
}
|
||||
assert "Failed to callback info" not in caplog.text
|
||||
|
||||
|
||||
async def test_scan_second_hit(hass, aioclient_mock, caplog):
|
||||
"""Test matching on second scan."""
|
||||
aioclient_mock.get(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue