mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
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:
parent
528f5e9e07
commit
85c8410c3d
@ -256,6 +256,11 @@ class Discover:
|
|||||||
) -> SmartDevice:
|
) -> SmartDevice:
|
||||||
"""Discover a single device by the given IP address.
|
"""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
|
:param host: Hostname of device to query
|
||||||
:rtype: SmartDevice
|
:rtype: SmartDevice
|
||||||
:return: Object for querying/controlling found device.
|
:return: Object for querying/controlling found device.
|
||||||
@ -299,6 +304,43 @@ class Discover:
|
|||||||
else:
|
else:
|
||||||
raise SmartDeviceException(f"Unable to get discovery response for {host}")
|
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
|
@staticmethod
|
||||||
def _get_device_class(info: dict) -> Type[SmartDevice]:
|
def _get_device_class(info: dict) -> Type[SmartDevice]:
|
||||||
"""Find SmartDevice subclass for device described by passed data."""
|
"""Find SmartDevice subclass for device described by passed data."""
|
||||||
|
@ -74,6 +74,26 @@ async def test_discover_single(discovery_data: dict, mocker, custom_port):
|
|||||||
assert x.port == custom_port or 9999
|
assert x.port == custom_port or 9999
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("custom_port", [123, None])
|
||||||
|
async def test_connect_single(discovery_data: dict, mocker, custom_port):
|
||||||
|
"""Make sure that connect_single returns an initialized SmartDevice instance."""
|
||||||
|
host = "127.0.0.1"
|
||||||
|
mocker.patch("kasa.TPLinkSmartHomeProtocol.query", return_value=discovery_data)
|
||||||
|
|
||||||
|
dev = await Discover.connect_single(host, port=custom_port)
|
||||||
|
assert issubclass(dev.__class__, SmartDevice)
|
||||||
|
assert dev.port == custom_port or 9999
|
||||||
|
|
||||||
|
|
||||||
|
async def test_connect_single_query_fails(discovery_data: dict, mocker):
|
||||||
|
"""Make sure that connect_single fails when query fails."""
|
||||||
|
host = "127.0.0.1"
|
||||||
|
mocker.patch("kasa.TPLinkSmartHomeProtocol.query", side_effect=SmartDeviceException)
|
||||||
|
|
||||||
|
with pytest.raises(SmartDeviceException):
|
||||||
|
await Discover.connect_single(host)
|
||||||
|
|
||||||
|
|
||||||
UNSUPPORTED = {
|
UNSUPPORTED = {
|
||||||
"result": {
|
"result": {
|
||||||
"device_id": "xx",
|
"device_id": "xx",
|
||||||
|
Loading…
Reference in New Issue
Block a user