Use voluptuous for nmap, tplink, thomson device trackers (#3124)

* Use Voluptuous for nmap, tplink, thomson device_trackers

* Fix logic
This commit is contained in:
Johann Kellerman 2016-09-18 08:44:15 +02:00 committed by Paulus Schoutsen
parent 9184773f8f
commit 169f054c6c
3 changed files with 57 additions and 54 deletions

View file

@ -10,11 +10,13 @@ import subprocess
from collections import namedtuple
from datetime import timedelta
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
import homeassistant.util.dt as dt_util
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.components.device_tracker import DOMAIN, PLATFORM_SCHEMA
from homeassistant.const import CONF_HOSTS
from homeassistant.helpers import validate_config
from homeassistant.util import Throttle, convert
from homeassistant.util import Throttle
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
@ -27,18 +29,21 @@ CONF_EXCLUDE = 'exclude'
REQUIREMENTS = ['python-nmap==0.6.1']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOSTS): vol.All(cv.ensure_list, [cv.string]),
vol.Required(CONF_HOME_INTERVAL, default=0): cv.positive_int,
vol.Optional(CONF_EXCLUDE, default=[]):
vol.All(cv.ensure_list, vol.Length(min=1))
})
def get_scanner(hass, config):
"""Validate the configuration and return a Nmap scanner."""
if not validate_config(config, {DOMAIN: [CONF_HOSTS]},
_LOGGER):
return None
scanner = NmapDeviceScanner(config[DOMAIN])
return scanner if scanner.success_init else None
Device = namedtuple("Device", ["mac", "name", "ip", "last_update"])
Device = namedtuple('Device', ['mac', 'name', 'ip', 'last_update'])
def _arp(ip_address):
@ -49,24 +54,26 @@ def _arp(ip_address):
match = re.search(r'(([0-9A-Fa-f]{1,2}\:){5}[0-9A-Fa-f]{1,2})', str(out))
if match:
return match.group(0)
_LOGGER.info("No MAC address found for %s", ip_address)
_LOGGER.info('No MAC address found for %s', ip_address)
return None
class NmapDeviceScanner(object):
"""This class scans for devices using nmap."""
exclude = []
def __init__(self, config):
"""Initialize the scanner."""
self.last_results = []
self.hosts = config[CONF_HOSTS]
self.exclude = config.get(CONF_EXCLUDE, [])
minutes = convert(config.get(CONF_HOME_INTERVAL), int, 0)
minutes = config[CONF_HOME_INTERVAL]
self.home_interval = timedelta(minutes=minutes)
self.success_init = self._update_info()
_LOGGER.info("nmap scanner initialized")
_LOGGER.info('nmap scanner initialized')
def scan_devices(self):
"""Scan for new devices and return a list with found device IDs."""
@ -90,21 +97,18 @@ class NmapDeviceScanner(object):
Returns boolean if scanning successful.
"""
_LOGGER.info("Scanning")
_LOGGER.info('Scanning')
from nmap import PortScanner, PortScannerError
scanner = PortScanner()
options = "-F --host-timeout 5s "
exclude = "--exclude "
options = '-F --host-timeout 5s '
if self.home_interval:
boundary = dt_util.now() - self.home_interval
last_results = [device for device in self.last_results
if device.last_update > boundary]
if last_results:
# Pylint is confused here.
# pylint: disable=no-member
exclude_hosts = self.exclude + [device.ip for device
in last_results]
else:
@ -113,8 +117,7 @@ class NmapDeviceScanner(object):
last_results = []
exclude_hosts = self.exclude
if exclude_hosts:
exclude = " --exclude {}".format(",".join(exclude_hosts))
options += exclude
options += ' --exclude {}'.format(','.join(exclude_hosts))
try:
result = scanner.scan(hosts=self.hosts, arguments=options)
@ -134,5 +137,5 @@ class NmapDeviceScanner(object):
self.last_results = last_results
_LOGGER.info("nmap scan successful")
_LOGGER.info('nmap scan successful')
return True