From 778fdb8ff96e996a7b6318e0129e554eba55ed62 Mon Sep 17 00:00:00 2001 From: Tomer Brosh Date: Wed, 17 Jan 2018 23:22:16 +0200 Subject: [PATCH] Add TP-Link Archer C20 device tracking support --- .../components/device_tracker/tplink.py | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/device_tracker/tplink.py b/homeassistant/components/device_tracker/tplink.py index 6c5fb697c072da..3efb5e1678ab84 100644 --- a/homeassistant/components/device_tracker/tplink.py +++ b/homeassistant/components/device_tracker/tplink.py @@ -5,6 +5,7 @@ https://home-assistant.io/components/device_tracker.tplink/ """ import base64 +import configparser from datetime import datetime import hashlib import logging @@ -36,8 +37,8 @@ def get_scanner(hass, config): """Validate the configuration and return a TP-Link scanner.""" for cls in [Tplink5DeviceScanner, Tplink4DeviceScanner, - Tplink3DeviceScanner, Tplink2DeviceScanner, - TplinkDeviceScanner]: + Tplink3DeviceScanner, TplinkArcherC20DeviceScanner, + Tplink2DeviceScanner, TplinkDeviceScanner]: scanner = cls(config[DOMAIN]) if scanner.success_init: return scanner @@ -149,6 +150,59 @@ def _update_info(self): return False +class TplinkArcherC20DeviceScanner(Tplink2DeviceScanner): + """This class queries an Archer C20 router with TP-Link firmware 160427.""" + + def _update_info(self): + """Ensure the information from the TP-Link router is up to date. + + Return boolean if scanning successful. + """ + _LOGGER.info("Loading wireless clients...") + + url = 'http://{}/cgi?5'.format(self.host) + referer = 'http://{}'.format(self.host) + + username_password = '{}:{}'.format(self.username, self.password) + b64_encoded_username_password = base64.b64encode( + username_password.encode('ascii') + ).decode('ascii') + cookie = 'Authorization=Basic {}' \ + .format(b64_encoded_username_password) + + post_data = '[LAN_HOST_ENTRY#0,0,0,0,0,0#0,0,0,0,0,0]0,0\r\n' + + response = requests.post( + url, post_data, headers={REFERER: referer, COOKIE: cookie}, + timeout=4) + + try: + config = configparser.ConfigParser(allow_no_value=True) + config.read_string(response.text) + result = [] + for section in config.sections(): + if 'IPAddress' in config[section]: + entry = { + 'ip': config[section]['IPAddress'], + 'mac': config[section]['MACAddress'], + 'name': config[section]['hostName'], + } + result.append(entry) + except ValueError: + _LOGGER.error("Router didn't respond with JSON. " + "Check if credentials are correct.") + return False + + if result: + self.last_results = { + device['mac']: device['name'] + for device in result + } + return True + + return False + + class Tplink3DeviceScanner(TplinkDeviceScanner): """This class queries the Archer C9 router with version 150811 or high."""