11"""Discovery module for TP-Link Smart Home devices."""
22import asyncio
33import binascii
4+ import ipaddress
45import logging
56import socket
67from typing import Awaitable , Callable , Dict , Optional , Type , cast
@@ -281,9 +282,34 @@ async def discover_single(
281282 """
282283 loop = asyncio .get_event_loop ()
283284 event = asyncio .Event ()
285+
286+ try :
287+ ipaddress .ip_address (host )
288+ ip = host
289+ except ValueError :
290+ try :
291+ adrrinfo = await loop .getaddrinfo (
292+ host ,
293+ 0 ,
294+ type = socket .SOCK_DGRAM ,
295+ family = socket .AF_INET ,
296+ )
297+ # getaddrinfo returns a list of 5 tuples with the following structure:
298+ # (family, type, proto, canonname, sockaddr)
299+ # where sockaddr is 2 tuple (ip, port).
300+ # hence [0][4][0] is a stable array access because if no socket
301+ # address matches the host for SOCK_DGRAM AF_INET the gaierror
302+ # would be raised.
303+ # https://docs.python.org/3/library/socket.html#socket.getaddrinfo
304+ ip = adrrinfo [0 ][4 ][0 ]
305+ except socket .gaierror as gex :
306+ raise SmartDeviceException (
307+ f"Could not resolve hostname { host } "
308+ ) from gex
309+
284310 transport , protocol = await loop .create_datagram_endpoint (
285311 lambda : _DiscoverProtocol (
286- target = host ,
312+ target = ip ,
287313 port = port ,
288314 discovered_event = event ,
289315 credentials = credentials ,
@@ -305,16 +331,17 @@ async def discover_single(
305331 finally :
306332 transport .close ()
307333
308- if host in protocol .discovered_devices :
309- dev = protocol .discovered_devices [host ]
334+ if ip in protocol .discovered_devices :
335+ dev = protocol .discovered_devices [ip ]
336+ dev .host = host
310337 await dev .update ()
311338 return dev
312- elif host in protocol .unsupported_devices :
339+ elif ip in protocol .unsupported_devices :
313340 raise UnsupportedDeviceException (
314- f"Unsupported device { host } : { protocol .unsupported_devices [host ]} "
341+ f"Unsupported device { host } : { protocol .unsupported_devices [ip ]} "
315342 )
316- elif host in protocol .invalid_device_exceptions :
317- raise protocol .invalid_device_exceptions [host ]
343+ elif ip in protocol .invalid_device_exceptions :
344+ raise protocol .invalid_device_exceptions [ip ]
318345 else :
319346 raise SmartDeviceException (f"Unable to get discovery response for { host } " )
320347
0 commit comments