Presence detection for tp link eap225 (#8322)

* Added support for TP-Link EAP 225

* code style changes

* more code style changes

* more understandable variable name

* Added support for TP-Link EAP 225

* code style changes

* more code style changes

* more understandable variable name

* Fix pylint issue (#8325)

* Added support for TP-Link EAP 225

* code style changes

* more code style changes

* more understandable variable name

* Added support for TP-Link EAP 225

* code style changes

* Update snips.py
This commit is contained in:
Alex 2017-07-07 07:52:40 +02:00 committed by Paulus Schoutsen
parent 652c006cbc
commit ed5d10448e
2 changed files with 86 additions and 6 deletions

View File

@ -9,7 +9,7 @@ import hashlib
import logging import logging
import re import re
import threading import threading
from datetime import timedelta from datetime import timedelta, datetime
import requests import requests
import voluptuous as vol import voluptuous as vol
@ -33,8 +33,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def get_scanner(hass, config): def get_scanner(hass, config):
"""Validate the configuration and return a TP-Link scanner.""" """Validate the configuration and return a TP-Link scanner."""
for cls in [Tplink4DeviceScanner, Tplink3DeviceScanner, for cls in [Tplink5DeviceScanner, Tplink4DeviceScanner,
Tplink2DeviceScanner, TplinkDeviceScanner]: Tplink3DeviceScanner, Tplink2DeviceScanner,
TplinkDeviceScanner]:
scanner = cls(config[DOMAIN]) scanner = cls(config[DOMAIN])
if scanner.success_init: if scanner.success_init:
return scanner return scanner
@ -349,3 +350,83 @@ class Tplink4DeviceScanner(TplinkDeviceScanner):
self.last_results = [mac.replace("-", ":") for mac in mac_results] self.last_results = [mac.replace("-", ":") for mac in mac_results]
return True return True
class Tplink5DeviceScanner(TplinkDeviceScanner):
"""This class queries a TP-Link EAP-225 AP with newer TP-Link FW."""
def scan_devices(self):
"""Scan for new devices and return a list with found MAC IDs."""
self._update_info()
return self.last_results.keys()
# pylint: disable=no-self-use
def get_device_name(self, device):
"""Get firmware doesn't save the name of the wireless device."""
return None
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
"""Ensure the information from the TP-Link AP is up to date.
Return boolean if scanning successful.
"""
with self.lock:
_LOGGER.info("Loading wireless clients...")
base_url = 'http://{}'.format(self.host)
header = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12;"
" rv:53.0) Gecko/20100101 Firefox/53.0",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Language": "Accept-Language: en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate",
"Content-Type": "application/x-www-form-urlencoded; "
"charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
"Referer": "http://" + self.host + "/",
"Connection": "keep-alive",
"Pragma": "no-cache",
"Cache-Control": "no-cache"
}
password_md5 = hashlib.md5(self.password).hexdigest().upper()
# create a session to handle cookie easier
session = requests.session()
session.get(base_url, headers=header)
login_data = {"username": self.username, "password": password_md5}
session.post(base_url, login_data, headers=header)
# a timestamp is required to be sent as get parameter
timestamp = int(datetime.now().timestamp() * 1e3)
client_list_url = '{}/data/monitor.client.client.json'.format(
base_url)
get_params = {
'operation': 'load',
'_': timestamp
}
response = session.get(client_list_url,
headers=header,
params=get_params)
session.close()
try:
list_of_devices = response.json()
except ValueError:
_LOGGER.error("AP didn't respond with JSON. "
"Check if credentials are correct.")
return False
if list_of_devices:
self.last_results = {
device['MAC'].replace('-', ':'): device['DeviceName']
for device in list_of_devices['data']
}
return True
return False

View File

@ -86,13 +86,13 @@ class IntentHandler(object):
try: try:
response = json.loads(payload) response = json.loads(payload)
except TypeError: except TypeError:
LOGGER.error("Received invalid JSON: %s", payload) LOGGER.error('Received invalid JSON: %s', payload)
return return
try: try:
response = INTENT_SCHEMA(response) response = INTENT_SCHEMA(response)
except vol.Invalid as err: except vol.Invalid as err:
LOGGER.error("Intent has invalid schema: %s. %s", err, response) LOGGER.error('Intent has invalid schema: %s. %s', err, response)
return return
intent = response['intent']['intentName'].split('__')[-1] intent = response['intent']['intentName'].split('__')[-1]
@ -108,7 +108,6 @@ class IntentHandler(object):
slots = self.parse_slots(response) slots = self.parse_slots(response)
yield from action.async_run(slots) yield from action.async_run(slots)
# pylint: disable=no-self-use
def parse_slots(self, response): def parse_slots(self, response):
"""Parse the intent slots.""" """Parse the intent slots."""
parameters = {} parameters = {}