Update async_upnp_client to 0.29.0 (#70604)
parent
f6d9c75476
commit
5224cf5968
|
@ -3,7 +3,7 @@
|
||||||
"name": "DLNA Digital Media Renderer",
|
"name": "DLNA Digital Media Renderer",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/dlna_dmr",
|
"documentation": "https://www.home-assistant.io/integrations/dlna_dmr",
|
||||||
"requirements": ["async-upnp-client==0.28.0"],
|
"requirements": ["async-upnp-client==0.29.0"],
|
||||||
"dependencies": ["ssdp"],
|
"dependencies": ["ssdp"],
|
||||||
"after_dependencies": ["media_source"],
|
"after_dependencies": ["media_source"],
|
||||||
"ssdp": [
|
"ssdp": [
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "DLNA Digital Media Server",
|
"name": "DLNA Digital Media Server",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/dlna_dms",
|
"documentation": "https://www.home-assistant.io/integrations/dlna_dms",
|
||||||
"requirements": ["async-upnp-client==0.28.0"],
|
"requirements": ["async-upnp-client==0.29.0"],
|
||||||
"dependencies": ["ssdp"],
|
"dependencies": ["ssdp"],
|
||||||
"after_dependencies": ["media_source"],
|
"after_dependencies": ["media_source"],
|
||||||
"ssdp": [
|
"ssdp": [
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"samsungctl[websocket]==0.7.1",
|
"samsungctl[websocket]==0.7.1",
|
||||||
"samsungtvws[async,encrypted]==2.5.0",
|
"samsungtvws[async,encrypted]==2.5.0",
|
||||||
"wakeonlan==2.0.1",
|
"wakeonlan==2.0.1",
|
||||||
"async-upnp-client==0.28.0"
|
"async-upnp-client==0.29.0"
|
||||||
],
|
],
|
||||||
"ssdp": [
|
"ssdp": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,12 +11,7 @@ import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from async_upnp_client.aiohttp import AiohttpSessionRequester
|
from async_upnp_client.aiohttp import AiohttpSessionRequester
|
||||||
from async_upnp_client.const import (
|
from async_upnp_client.const import AddressTupleVXType, DeviceOrServiceType, SsdpSource
|
||||||
AddressTupleVXType,
|
|
||||||
DeviceOrServiceType,
|
|
||||||
SsdpHeaders,
|
|
||||||
SsdpSource,
|
|
||||||
)
|
|
||||||
from async_upnp_client.description_cache import DescriptionCache
|
from async_upnp_client.description_cache import DescriptionCache
|
||||||
from async_upnp_client.ssdp import SSDP_PORT, determine_source_target, is_ipv4_address
|
from async_upnp_client.ssdp import SSDP_PORT, determine_source_target, is_ipv4_address
|
||||||
from async_upnp_client.ssdp_listener import SsdpDevice, SsdpDeviceTracker, SsdpListener
|
from async_upnp_client.ssdp_listener import SsdpDevice, SsdpDeviceTracker, SsdpListener
|
||||||
|
@ -246,13 +241,13 @@ async def _async_process_callbacks(
|
||||||
|
|
||||||
@core_callback
|
@core_callback
|
||||||
def _async_headers_match(
|
def _async_headers_match(
|
||||||
headers: Mapping[str, Any], match_dict: dict[str, str]
|
headers: CaseInsensitiveDict, lower_match_dict: dict[str, str]
|
||||||
) -> bool:
|
) -> bool:
|
||||||
for header, val in match_dict.items():
|
for header, val in lower_match_dict.items():
|
||||||
if val == MATCH_ALL:
|
if val == MATCH_ALL:
|
||||||
if header not in headers:
|
if header not in headers:
|
||||||
return False
|
return False
|
||||||
elif headers.get(header) != val:
|
elif headers.get_lower(header) != val:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -328,7 +323,7 @@ class Scanner:
|
||||||
@property
|
@property
|
||||||
def _all_headers_from_ssdp_devices(
|
def _all_headers_from_ssdp_devices(
|
||||||
self,
|
self,
|
||||||
) -> dict[tuple[str, str], Mapping[str, Any]]:
|
) -> dict[tuple[str, str], CaseInsensitiveDict]:
|
||||||
return {
|
return {
|
||||||
(ssdp_device.udn, dst): headers
|
(ssdp_device.udn, dst): headers
|
||||||
for ssdp_device in self._ssdp_devices
|
for ssdp_device in self._ssdp_devices
|
||||||
|
@ -340,19 +335,21 @@ class Scanner:
|
||||||
) -> Callable[[], None]:
|
) -> Callable[[], None]:
|
||||||
"""Register a callback."""
|
"""Register a callback."""
|
||||||
if match_dict is None:
|
if match_dict is None:
|
||||||
match_dict = {}
|
lower_match_dict = {}
|
||||||
|
else:
|
||||||
|
lower_match_dict = {k.lower(): v for k, v in match_dict.items()}
|
||||||
|
|
||||||
# Make sure any entries that happened
|
# Make sure any entries that happened
|
||||||
# before the callback was registered are fired
|
# before the callback was registered are fired
|
||||||
for headers in self._all_headers_from_ssdp_devices.values():
|
for headers in self._all_headers_from_ssdp_devices.values():
|
||||||
if _async_headers_match(headers, match_dict):
|
if _async_headers_match(headers, lower_match_dict):
|
||||||
await _async_process_callbacks(
|
await _async_process_callbacks(
|
||||||
[callback],
|
[callback],
|
||||||
await self._async_headers_to_discovery_info(headers),
|
await self._async_headers_to_discovery_info(headers),
|
||||||
SsdpChange.ALIVE,
|
SsdpChange.ALIVE,
|
||||||
)
|
)
|
||||||
|
|
||||||
callback_entry = (callback, match_dict)
|
callback_entry = (callback, lower_match_dict)
|
||||||
self._callbacks.append(callback_entry)
|
self._callbacks.append(callback_entry)
|
||||||
|
|
||||||
@core_callback
|
@core_callback
|
||||||
|
@ -461,13 +458,13 @@ class Scanner:
|
||||||
@core_callback
|
@core_callback
|
||||||
def _async_get_matching_callbacks(
|
def _async_get_matching_callbacks(
|
||||||
self,
|
self,
|
||||||
combined_headers: SsdpHeaders,
|
combined_headers: CaseInsensitiveDict,
|
||||||
) -> list[SsdpCallback]:
|
) -> list[SsdpCallback]:
|
||||||
"""Return a list of callbacks that match."""
|
"""Return a list of callbacks that match."""
|
||||||
return [
|
return [
|
||||||
callback
|
callback
|
||||||
for callback, match_dict in self._callbacks
|
for callback, lower_match_dict in self._callbacks
|
||||||
if _async_headers_match(combined_headers, match_dict)
|
if _async_headers_match(combined_headers, lower_match_dict)
|
||||||
]
|
]
|
||||||
|
|
||||||
async def _ssdp_listener_callback(
|
async def _ssdp_listener_callback(
|
||||||
|
@ -490,9 +487,8 @@ class Scanner:
|
||||||
# If there are no changes from a search, do not trigger a config flow
|
# If there are no changes from a search, do not trigger a config flow
|
||||||
if source != SsdpSource.SEARCH_ALIVE:
|
if source != SsdpSource.SEARCH_ALIVE:
|
||||||
info_desc = await self._async_get_description_dict(location) or {}
|
info_desc = await self._async_get_description_dict(location) or {}
|
||||||
assert isinstance(combined_headers, CaseInsensitiveDict)
|
|
||||||
matching_domains = self.integration_matchers.async_matching_domains(
|
matching_domains = self.integration_matchers.async_matching_domains(
|
||||||
CaseInsensitiveDict({**combined_headers.as_dict(), **info_desc})
|
CaseInsensitiveDict(combined_headers.as_dict(), **info_desc)
|
||||||
)
|
)
|
||||||
|
|
||||||
if not callbacks and not matching_domains:
|
if not callbacks and not matching_domains:
|
||||||
|
@ -530,7 +526,7 @@ class Scanner:
|
||||||
return await self._description_cache.async_get_description_dict(location) or {}
|
return await self._description_cache.async_get_description_dict(location) or {}
|
||||||
|
|
||||||
async def _async_headers_to_discovery_info(
|
async def _async_headers_to_discovery_info(
|
||||||
self, headers: Mapping[str, Any]
|
self, headers: CaseInsensitiveDict
|
||||||
) -> SsdpServiceInfo:
|
) -> SsdpServiceInfo:
|
||||||
"""Combine the headers and description into discovery_info.
|
"""Combine the headers and description into discovery_info.
|
||||||
|
|
||||||
|
@ -571,7 +567,7 @@ class Scanner:
|
||||||
|
|
||||||
|
|
||||||
def discovery_info_from_headers_and_description(
|
def discovery_info_from_headers_and_description(
|
||||||
combined_headers: Mapping[str, Any],
|
combined_headers: CaseInsensitiveDict,
|
||||||
info_desc: Mapping[str, Any],
|
info_desc: Mapping[str, Any],
|
||||||
) -> SsdpServiceInfo:
|
) -> SsdpServiceInfo:
|
||||||
"""Convert headers and description to discovery_info."""
|
"""Convert headers and description to discovery_info."""
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"domain": "ssdp",
|
"domain": "ssdp",
|
||||||
"name": "Simple Service Discovery Protocol (SSDP)",
|
"name": "Simple Service Discovery Protocol (SSDP)",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/ssdp",
|
"documentation": "https://www.home-assistant.io/integrations/ssdp",
|
||||||
"requirements": ["async-upnp-client==0.28.0"],
|
"requirements": ["async-upnp-client==0.29.0"],
|
||||||
"dependencies": ["network"],
|
"dependencies": ["network"],
|
||||||
"after_dependencies": ["zeroconf"],
|
"after_dependencies": ["zeroconf"],
|
||||||
"codeowners": [],
|
"codeowners": [],
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "UPnP/IGD",
|
"name": "UPnP/IGD",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/upnp",
|
"documentation": "https://www.home-assistant.io/integrations/upnp",
|
||||||
"requirements": ["async-upnp-client==0.28.0", "getmac==0.8.2"],
|
"requirements": ["async-upnp-client==0.29.0", "getmac==0.8.2"],
|
||||||
"dependencies": ["network", "ssdp"],
|
"dependencies": ["network", "ssdp"],
|
||||||
"codeowners": ["@StevenLooman", "@ehendrix23"],
|
"codeowners": ["@StevenLooman", "@ehendrix23"],
|
||||||
"ssdp": [
|
"ssdp": [
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"domain": "yeelight",
|
"domain": "yeelight",
|
||||||
"name": "Yeelight",
|
"name": "Yeelight",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/yeelight",
|
"documentation": "https://www.home-assistant.io/integrations/yeelight",
|
||||||
"requirements": ["yeelight==0.7.10", "async-upnp-client==0.28.0"],
|
"requirements": ["yeelight==0.7.10", "async-upnp-client==0.29.0"],
|
||||||
"codeowners": ["@zewelor", "@shenxn", "@starkillerOG", "@alexyao2015"],
|
"codeowners": ["@zewelor", "@shenxn", "@starkillerOG", "@alexyao2015"],
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"dependencies": ["network"],
|
"dependencies": ["network"],
|
||||||
|
|
|
@ -9,7 +9,8 @@ from ipaddress import IPv4Address
|
||||||
import logging
|
import logging
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from async_upnp_client.search import SsdpHeaders, SsdpSearchListener
|
from async_upnp_client.search import SsdpSearchListener
|
||||||
|
from async_upnp_client.utils import CaseInsensitiveDict
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components import network, ssdp
|
from homeassistant.components import network, ssdp
|
||||||
|
@ -46,8 +47,8 @@ class YeelightScanner:
|
||||||
"""Initialize class."""
|
"""Initialize class."""
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._host_discovered_events: dict[str, list[asyncio.Event]] = {}
|
self._host_discovered_events: dict[str, list[asyncio.Event]] = {}
|
||||||
self._unique_id_capabilities: dict[str, SsdpHeaders] = {}
|
self._unique_id_capabilities: dict[str, CaseInsensitiveDict] = {}
|
||||||
self._host_capabilities: dict[str, SsdpHeaders] = {}
|
self._host_capabilities: dict[str, CaseInsensitiveDict] = {}
|
||||||
self._track_interval: CALLBACK_TYPE | None = None
|
self._track_interval: CALLBACK_TYPE | None = None
|
||||||
self._listeners: list[SsdpSearchListener] = []
|
self._listeners: list[SsdpSearchListener] = []
|
||||||
self._connected_events: list[asyncio.Event] = []
|
self._connected_events: list[asyncio.Event] = []
|
||||||
|
@ -123,7 +124,7 @@ class YeelightScanner:
|
||||||
if isinstance(source_ip, IPv4Address) and not source_ip.is_loopback
|
if isinstance(source_ip, IPv4Address) and not source_ip.is_loopback
|
||||||
}
|
}
|
||||||
|
|
||||||
async def async_discover(self) -> ValuesView[SsdpHeaders]:
|
async def async_discover(self) -> ValuesView[CaseInsensitiveDict]:
|
||||||
"""Discover bulbs."""
|
"""Discover bulbs."""
|
||||||
_LOGGER.debug("Yeelight discover with interval %s", DISCOVERY_SEARCH_INTERVAL)
|
_LOGGER.debug("Yeelight discover with interval %s", DISCOVERY_SEARCH_INTERVAL)
|
||||||
await self.async_setup()
|
await self.async_setup()
|
||||||
|
@ -139,7 +140,7 @@ class YeelightScanner:
|
||||||
for listener in self._listeners:
|
for listener in self._listeners:
|
||||||
listener.async_search()
|
listener.async_search()
|
||||||
|
|
||||||
async def async_get_capabilities(self, host: str) -> SsdpHeaders | None:
|
async def async_get_capabilities(self, host: str) -> CaseInsensitiveDict | None:
|
||||||
"""Get capabilities via SSDP."""
|
"""Get capabilities via SSDP."""
|
||||||
if host in self._host_capabilities:
|
if host in self._host_capabilities:
|
||||||
return self._host_capabilities[host]
|
return self._host_capabilities[host]
|
||||||
|
@ -157,7 +158,7 @@ class YeelightScanner:
|
||||||
self._host_discovered_events[host].remove(host_event)
|
self._host_discovered_events[host].remove(host_event)
|
||||||
return self._host_capabilities.get(host)
|
return self._host_capabilities.get(host)
|
||||||
|
|
||||||
def _async_discovered_by_ssdp(self, response: SsdpHeaders) -> None:
|
def _async_discovered_by_ssdp(self, response: CaseInsensitiveDict) -> None:
|
||||||
@callback
|
@callback
|
||||||
def _async_start_flow(*_) -> None:
|
def _async_start_flow(*_) -> None:
|
||||||
asyncio.create_task(
|
asyncio.create_task(
|
||||||
|
@ -177,7 +178,7 @@ class YeelightScanner:
|
||||||
# of another discovery
|
# of another discovery
|
||||||
async_call_later(self._hass, 1, _async_start_flow)
|
async_call_later(self._hass, 1, _async_start_flow)
|
||||||
|
|
||||||
async def _async_process_entry(self, headers: SsdpHeaders) -> None:
|
async def _async_process_entry(self, headers: CaseInsensitiveDict) -> None:
|
||||||
"""Process a discovery."""
|
"""Process a discovery."""
|
||||||
_LOGGER.debug("Discovered via SSDP: %s", headers)
|
_LOGGER.debug("Discovered via SSDP: %s", headers)
|
||||||
unique_id = headers["id"]
|
unique_id = headers["id"]
|
||||||
|
|
|
@ -4,7 +4,7 @@ aiodiscover==1.4.11
|
||||||
aiohttp==3.8.1
|
aiohttp==3.8.1
|
||||||
aiohttp_cors==0.7.0
|
aiohttp_cors==0.7.0
|
||||||
astral==2.2
|
astral==2.2
|
||||||
async-upnp-client==0.28.0
|
async-upnp-client==0.29.0
|
||||||
async_timeout==4.0.2
|
async_timeout==4.0.2
|
||||||
atomicwrites==1.4.0
|
atomicwrites==1.4.0
|
||||||
attrs==21.2.0
|
attrs==21.2.0
|
||||||
|
|
|
@ -333,7 +333,7 @@ asterisk_mbox==0.5.0
|
||||||
# homeassistant.components.ssdp
|
# homeassistant.components.ssdp
|
||||||
# homeassistant.components.upnp
|
# homeassistant.components.upnp
|
||||||
# homeassistant.components.yeelight
|
# homeassistant.components.yeelight
|
||||||
async-upnp-client==0.28.0
|
async-upnp-client==0.29.0
|
||||||
|
|
||||||
# homeassistant.components.supla
|
# homeassistant.components.supla
|
||||||
asyncpysupla==0.0.5
|
asyncpysupla==0.0.5
|
||||||
|
|
|
@ -269,7 +269,7 @@ arcam-fmj==0.12.0
|
||||||
# homeassistant.components.ssdp
|
# homeassistant.components.ssdp
|
||||||
# homeassistant.components.upnp
|
# homeassistant.components.upnp
|
||||||
# homeassistant.components.yeelight
|
# homeassistant.components.yeelight
|
||||||
async-upnp-client==0.28.0
|
async-upnp-client==0.29.0
|
||||||
|
|
||||||
# homeassistant.components.sleepiq
|
# homeassistant.components.sleepiq
|
||||||
asyncsleepiq==1.2.3
|
asyncsleepiq==1.2.3
|
||||||
|
|
|
@ -4,10 +4,11 @@ from datetime import timedelta
|
||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
from async_upnp_client.search import SsdpSearchListener
|
from async_upnp_client.search import SsdpSearchListener
|
||||||
|
from async_upnp_client.utils import CaseInsensitiveDict
|
||||||
from yeelight import BulbException, BulbType
|
from yeelight import BulbException, BulbType
|
||||||
from yeelight.main import _MODEL_SPECS
|
from yeelight.main import _MODEL_SPECS
|
||||||
|
|
||||||
from homeassistant.components import ssdp, zeroconf
|
from homeassistant.components import zeroconf
|
||||||
from homeassistant.components.yeelight import (
|
from homeassistant.components.yeelight import (
|
||||||
CONF_MODE_MUSIC,
|
CONF_MODE_MUSIC,
|
||||||
CONF_NIGHTLIGHT_SWITCH_TYPE,
|
CONF_NIGHTLIGHT_SWITCH_TYPE,
|
||||||
|
@ -157,7 +158,7 @@ def _mocked_bulb(cannot_connect=False):
|
||||||
return bulb
|
return bulb
|
||||||
|
|
||||||
|
|
||||||
def _patched_ssdp_listener(info: ssdp.SsdpHeaders, *args, **kwargs):
|
def _patched_ssdp_listener(info: CaseInsensitiveDict, *args, **kwargs):
|
||||||
listener = SsdpSearchListener(*args, **kwargs)
|
listener = SsdpSearchListener(*args, **kwargs)
|
||||||
|
|
||||||
async def _async_callback(*_):
|
async def _async_callback(*_):
|
||||||
|
|
Loading…
Reference in New Issue