add support for home_interval variable

This commit is contained in:
Nolan Gilley 2015-09-01 14:43:14 -04:00
parent 03ceb667ba
commit 97076f1ff8

View File

@ -9,13 +9,17 @@ This device tracker needs telnet to be enabled on the router.
Configuration: Configuration:
To use the Actiontec tracker you will need to add something like the To use the Actiontec tracker you will need to add something like the
following to your config/configuration.yaml following to your config/configuration.yaml. If you experience disconnects
you can modify the home_interval variable.
device_tracker: device_tracker:
platform: actiontec platform: actiontec
host: YOUR_ROUTER_IP host: YOUR_ROUTER_IP
username: YOUR_ADMIN_USERNAME username: YOUR_ADMIN_USERNAME
password: YOUR_ADMIN_PASSWORD password: YOUR_ADMIN_PASSWORD
# optional:
home_interval: 10
Variables: Variables:
@ -30,21 +34,30 @@ The username of an user with administrative privileges, usually 'admin'.
password password
*Required *Required
The password for your given admin account. The password for your given admin account.
home_interval
*Optional
Number of minutes it will not scan devices that it found in previous results.
""" """
import logging import logging
from datetime import timedelta from datetime import timedelta
from collections import namedtuple
import re import re
import threading import threading
import telnetlib import telnetlib
import homeassistant.util.dt as dt_util
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.helpers import validate_config from homeassistant.helpers import validate_config
from homeassistant.util import Throttle from homeassistant.util import Throttle, convert
from homeassistant.components.device_tracker import DOMAIN from homeassistant.components.device_tracker import DOMAIN
# Return cached results if last scan was less then this time ago # Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
# interval in minutes to exclude devices from a scan while they are home
CONF_HOME_INTERVAL = "home_interval"
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
_LEASES_REGEX = re.compile( _LEASES_REGEX = re.compile(
@ -64,6 +77,8 @@ def get_scanner(hass, config):
return scanner if scanner.success_init else None return scanner if scanner.success_init else None
Device = namedtuple("Device", ["mac", "ip", "last_update"])
class ActiontecDeviceScanner(object): class ActiontecDeviceScanner(object):
""" This class queries a an actiontec router """ This class queries a an actiontec router
@ -74,6 +89,8 @@ class ActiontecDeviceScanner(object):
self.host = config[CONF_HOST] self.host = config[CONF_HOST]
self.username = config[CONF_USERNAME] self.username = config[CONF_USERNAME]
self.password = config[CONF_PASSWORD] self.password = config[CONF_PASSWORD]
minutes = convert(config.get(CONF_HOME_INTERVAL), int, 0)
self.home_interval = timedelta(minutes=minutes)
self.lock = threading.Lock() self.lock = threading.Lock()
@ -82,37 +99,56 @@ class ActiontecDeviceScanner(object):
# Test the router is accessible # Test the router is accessible
data = self.get_actiontec_data() data = self.get_actiontec_data()
self.success_init = data is not None self.success_init = data is not None
_LOGGER.info("actiontec scanner initialized")
if self.home_interval:
_LOGGER.info("home_interval set to: %s" % self.home_interval)
def scan_devices(self): def scan_devices(self):
""" Scans for new devices and return a """ Scans for new devices and return a
list containing found device ids. """ list containing found device ids. """
self._update_info() self._update_info()
return [client['mac'] for client in self.last_results] return [client.mac for client in self.last_results]
def get_device_name(self, device): def get_device_name(self, device):
""" Returns the name of the given device or None if we don't know. """ """ Returns the name of the given device or None if we don't know. """
if not self.last_results: if not self.last_results:
return None return None
for client in self.last_results: for client in self.last_results:
if client['mac'] == device: if client.mac == device:
return client['ip'] return client.ip
return None return None
@Throttle(MIN_TIME_BETWEEN_SCANS) @Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self): def _update_info(self):
""" Ensures the information from the Actiontec MI424WR router is up """ Ensures the information from the Actiontec MI424WR router is up
to date. Returns boolean if scanning successful. """ to date. Returns boolean if scanning successful. """
_LOGGER.info("Scanning")
if not self.success_init: if not self.success_init:
return False return False
with self.lock: with self.lock:
# _LOGGER.info("Checking ARP") exclude_targets = set()
data = self.get_actiontec_data() target_list = []
if not data: self.last_results = []
now = dt_util.now()
if self.home_interval:
for host in self.last_results:
if host.last_update + self.home_interval > now:
exclude_targets.add(host)
if len(exclude_targets) > 0:
target_list = [t.ip for t in exclude_targets]
devices = self.get_actiontec_data()
if not devices:
return False return False
active_clients = [client for client in data.values()] for ip in target_list:
self.last_results = active_clients if ip in devices:
devices.pop(ip)
for ip, data in devices.items():
device = Device(data['mac'], ip, now)
self.last_results.append(device)
return True return True
def get_actiontec_data(self): def get_actiontec_data(self):