Add a connect_single method to Discover to avoid the need for UDP (#528)

This should equate to a significant reliability improvement for networks with poor wifi (edge of range)/udp.
This commit is contained in:
J. Nick Koston
2023-10-07 14:29:22 -10:00
committed by GitHub
parent 528f5e9e07
commit 85c8410c3d
2 changed files with 62 additions and 0 deletions

View File

@@ -256,6 +256,11 @@ class Discover:
) -> SmartDevice:
"""Discover a single device by the given IP address.
It is generally preferred to avoid :func:`discover_single()` and
use :func:`connect_single()` instead as it should perform better when
the WiFi network is congested or the device is not responding
to discovery requests.
:param host: Hostname of device to query
:rtype: SmartDevice
:return: Object for querying/controlling found device.
@@ -299,6 +304,43 @@ class Discover:
else:
raise SmartDeviceException(f"Unable to get discovery response for {host}")
@staticmethod
async def connect_single(
host: str,
*,
port: Optional[int] = None,
timeout=5,
credentials: Optional[Credentials] = None,
) -> SmartDevice:
"""Connect to a single device by the given IP address.
This method avoids the UDP based discovery process and
will connect directly to the device to query its type.
It is generally preferred to avoid :func:`discover_single()` and
use this function instead as it should perform better when
the WiFi network is congested or the device is not responding
to discovery requests.
The device type is discovered by querying the device.
:param host: Hostname of device to query
:rtype: SmartDevice
:return: Object for querying/controlling found device.
"""
unknown_dev = SmartDevice(
host=host, port=port, credentials=credentials, timeout=timeout
)
await unknown_dev.update()
device_class = Discover._get_device_class(unknown_dev.internal_state)
dev = device_class(
host=host, port=port, credentials=credentials, timeout=timeout
)
# Reuse the connection from the unknown device
# so we don't have to reconnect
dev.protocol = unknown_dev.protocol
return dev
@staticmethod
def _get_device_class(info: dict) -> Type[SmartDevice]:
"""Find SmartDevice subclass for device described by passed data."""