From 28c1811aef7b2d9ed2e1beb76a6c9460939a2c2f Mon Sep 17 00:00:00 2001 From: Teemu R Date: Fri, 24 Apr 2020 16:57:04 +0200 Subject: [PATCH] Support wifi scan & join for bulbs using a different interface (#49) --- kasa/cli.py | 2 +- kasa/smartdevice.py | 30 ++++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/kasa/cli.py b/kasa/cli.py index b4f403b7..97f831ee 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -106,7 +106,7 @@ async def scan(dev): @pass_dev async def join(dev: SmartDevice, ssid, password, keytype): """Join the given wifi network.""" - click.echo("Asking the device to connect to {ssid}.." % (ssid)) + click.echo(f"Asking the device to connect to {ssid}..") res = await dev.wifi_join(ssid, password, keytype=keytype) click.echo( f"Response: {res} - if the device is not able to join the network, it will revert back to its previous state." diff --git a/kasa/smartdevice.py b/kasa/smartdevice.py index 467acbae..79eecc30 100755 --- a/kasa/smartdevice.py +++ b/kasa/smartdevice.py @@ -40,6 +40,11 @@ class WifiNetwork: ssid: str key_type: int + # These are available only on softaponboarding + cipher_type: Optional[int] = None + bssid: Optional[str] = None + channel: Optional[int] = None + rssi: Optional[int] = None class SmartDeviceException(Exception): @@ -592,7 +597,18 @@ class SmartDevice: async def wifi_scan(self) -> List[WifiNetwork]: """Scan for available wifi networks.""" - info = await self._query_helper("netif", "get_scaninfo", {"refresh": 1}) + + async def _scan(target): + return await self._query_helper(target, "get_scaninfo", {"refresh": 1}) + + try: + info = await _scan("netif") + except SmartDeviceException as ex: + _LOGGER.debug( + "Unable to scan using 'netif', retrying with 'softaponboarding': %s", ex + ) + info = await _scan("smartlife.iot.common.softaponboarding") + if "ap_list" not in info: raise SmartDeviceException("Invalid response for wifi scan: %s" % info) @@ -603,8 +619,18 @@ class SmartDevice: If joining the network fails, the device will return to AP mode after a while. """ + + async def _join(target, payload): + return await self._query_helper(target, "set_stainfo", payload) + payload = {"ssid": ssid, "password": password, "key_type": keytype} - return await self._query_helper("netif", "set_stainfo", payload) + try: + return await _join("netif", payload) + except SmartDeviceException as ex: + _LOGGER.debug( + "Unable to join using 'netif', retrying with 'softaponboarding': %s", ex + ) + return await _join("smartlife.iot.common.softaponboarding", payload) @property def device_type(self) -> DeviceType: