mirror of
https://github.com/esphome/aioesphomeapi.git
synced 2024-11-26 12:45:26 +01:00
Require zeroconf >=0.36 (#118)
This commit is contained in:
parent
dec73b8e29
commit
dd9d716c10
@ -1,23 +1,16 @@
|
||||
import asyncio
|
||||
import contextlib
|
||||
import functools
|
||||
import socket
|
||||
from dataclasses import dataclass
|
||||
from ipaddress import IPv4Address, IPv6Address
|
||||
from typing import List, Optional, Tuple, Union, cast
|
||||
|
||||
import zeroconf
|
||||
|
||||
try:
|
||||
import zeroconf.asyncio
|
||||
|
||||
ZC_ASYNCIO = True
|
||||
except ImportError:
|
||||
ZC_ASYNCIO = False
|
||||
import zeroconf.asyncio
|
||||
|
||||
from .core import APIConnectionError, ResolveAPIError
|
||||
|
||||
ZeroconfInstanceType = Union[zeroconf.Zeroconf, "zeroconf.asyncio.AsyncZeroconf", None]
|
||||
ZeroconfInstanceType = Union[zeroconf.Zeroconf, zeroconf.asyncio.AsyncZeroconf, None]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@ -47,60 +40,12 @@ class AddrInfo:
|
||||
sockaddr: Sockaddr
|
||||
|
||||
|
||||
def _sync_zeroconf_get_service_info(
|
||||
zeroconf_instance: ZeroconfInstanceType,
|
||||
service_type: str,
|
||||
service_name: str,
|
||||
timeout: float,
|
||||
) -> Optional["zeroconf.ServiceInfo"]:
|
||||
# Use or create zeroconf instance, ensure it's an AsyncZeroconf
|
||||
if zeroconf_instance is None:
|
||||
try:
|
||||
zc = zeroconf.Zeroconf()
|
||||
except Exception:
|
||||
raise ResolveAPIError(
|
||||
"Cannot start mDNS sockets, is this a docker container without "
|
||||
"host network mode?"
|
||||
)
|
||||
do_close = True
|
||||
elif isinstance(zeroconf_instance, zeroconf.Zeroconf):
|
||||
zc = zeroconf_instance
|
||||
do_close = False
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Invalid type passed for zeroconf_instance: {type(zeroconf_instance)}"
|
||||
)
|
||||
|
||||
try:
|
||||
info = zc.get_service_info(service_type, service_name, int(timeout * 1000))
|
||||
except Exception as exc:
|
||||
raise ResolveAPIError(
|
||||
f"Error resolving mDNS {service_name} via mDNS: {exc}"
|
||||
) from exc
|
||||
finally:
|
||||
if do_close:
|
||||
zc.close()
|
||||
return info
|
||||
|
||||
|
||||
async def _async_zeroconf_get_service_info(
|
||||
zeroconf_instance: ZeroconfInstanceType,
|
||||
service_type: str,
|
||||
service_name: str,
|
||||
timeout: float,
|
||||
) -> Optional["zeroconf.ServiceInfo"]:
|
||||
if not ZC_ASYNCIO:
|
||||
return await asyncio.get_event_loop().run_in_executor(
|
||||
None,
|
||||
functools.partial(
|
||||
_sync_zeroconf_get_service_info,
|
||||
zeroconf_instance,
|
||||
service_type,
|
||||
service_name,
|
||||
timeout,
|
||||
),
|
||||
)
|
||||
|
||||
# Use or create zeroconf instance, ensure it's an AsyncZeroconf
|
||||
if zeroconf_instance is None:
|
||||
try:
|
||||
|
@ -58,9 +58,6 @@ class ReconnectLogic(zeroconf.RecordUpdateListener): # type: ignore[misc,name-d
|
||||
# Event for tracking when logic should stop
|
||||
self._stop_event = asyncio.Event()
|
||||
|
||||
# Store the caller's event loop so the zeroconf can schedule it in the right one
|
||||
self._event_loop: Optional[asyncio.AbstractEventLoop] = None
|
||||
|
||||
@property
|
||||
def _is_stopped(self) -> bool:
|
||||
return self._stop_event.is_set()
|
||||
@ -181,7 +178,6 @@ class ReconnectLogic(zeroconf.RecordUpdateListener): # type: ignore[misc,name-d
|
||||
"""Start the reconnecting logic background task."""
|
||||
# Create reconnection loop outside of HA's tracked tasks in order
|
||||
# not to delay startup.
|
||||
self._event_loop = asyncio.get_event_loop()
|
||||
self._loop_task = asyncio.create_task(self._reconnect_loop())
|
||||
|
||||
async with self._connected_lock:
|
||||
@ -243,7 +239,6 @@ class ReconnectLogic(zeroconf.RecordUpdateListener): # type: ignore[misc,name-d
|
||||
)
|
||||
self._reconnect_event.set()
|
||||
|
||||
# From RecordUpdateListener for zeroconf>=0.32
|
||||
def async_update_records(
|
||||
self,
|
||||
zc: "zeroconf.Zeroconf", # pylint: disable=unused-argument
|
||||
@ -253,18 +248,3 @@ class ReconnectLogic(zeroconf.RecordUpdateListener): # type: ignore[misc,name-d
|
||||
"""Listen to zeroconf updated mDNS records. This must be called from the eventloop."""
|
||||
for update in records:
|
||||
self._async_on_record(update.new)
|
||||
|
||||
# From RecordUpdateListener for zeroconf<0.32
|
||||
def update_record(
|
||||
self,
|
||||
zc: "zeroconf.Zeroconf", # pylint: disable=unused-argument
|
||||
now: float, # pylint: disable=unused-argument
|
||||
record: "zeroconf.DNSRecord", # type: ignore[name-defined]
|
||||
) -> None:
|
||||
assert self._event_loop is not None
|
||||
|
||||
async def corofunc() -> None:
|
||||
self._async_on_record(record)
|
||||
|
||||
# Dispatch in event loop
|
||||
asyncio.run_coroutine_threadsafe(corofunc(), self._event_loop)
|
||||
|
@ -1,3 +1,3 @@
|
||||
protobuf>=3.12.2,<4.0
|
||||
zeroconf>=0.28.0,<1.0
|
||||
zeroconf>=0.36.0,<1.0
|
||||
noiseprotocol>=0.3.1,<1.0
|
Loading…
Reference in New Issue
Block a user