Update docstrings to match PEP257

This commit is contained in:
Fabian Affolter 2016-03-07 18:12:06 +01:00
parent 032f06e015
commit 7ff9aecd4e
19 changed files with 146 additions and 247 deletions

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.device_tracker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides functionality to keep track of devices. Provides functionality to keep track of devices.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
@ -70,7 +68,7 @@ _LOGGER = logging.getLogger(__name__)
def is_on(hass, entity_id=None): def is_on(hass, entity_id=None):
""" Returns if any or specified device is home. """ """Returns if any or specified device is home."""
entity = entity_id or ENTITY_ID_ALL_DEVICES entity = entity_id or ENTITY_ID_ALL_DEVICES
return hass.states.is_state(entity, STATE_HOME) return hass.states.is_state(entity, STATE_HOME)
@ -78,7 +76,7 @@ def is_on(hass, entity_id=None):
def see(hass, mac=None, dev_id=None, host_name=None, location_name=None, def see(hass, mac=None, dev_id=None, host_name=None, location_name=None,
gps=None, gps_accuracy=None, battery=None): gps=None, gps_accuracy=None, battery=None):
""" Call service to notify you see device. """ """Call service to notify you see device."""
data = {key: value for key, value in data = {key: value for key, value in
((ATTR_MAC, mac), ((ATTR_MAC, mac),
(ATTR_DEV_ID, dev_id), (ATTR_DEV_ID, dev_id),
@ -89,7 +87,7 @@ def see(hass, mac=None, dev_id=None, host_name=None, location_name=None,
def setup(hass, config): def setup(hass, config):
""" Setup device tracker """ """Setup device tracker."""
yaml_path = hass.config.path(YAML_DEVICES) yaml_path = hass.config.path(YAML_DEVICES)
conf = config.get(DOMAIN, {}) conf = config.get(DOMAIN, {})
@ -108,7 +106,7 @@ def setup(hass, config):
devices) devices)
def setup_platform(p_type, p_config, disc_info=None): def setup_platform(p_type, p_config, disc_info=None):
""" Setup a device tracker platform. """ """Setup a device tracker platform."""
platform = prepare_setup_platform(hass, config, DOMAIN, p_type) platform = prepare_setup_platform(hass, config, DOMAIN, p_type)
if platform is None: if platform is None:
return return
@ -134,7 +132,7 @@ def setup(hass, config):
setup_platform(p_type, p_config) setup_platform(p_type, p_config)
def device_tracker_discovered(service, info): def device_tracker_discovered(service, info):
""" Called when a device tracker platform is discovered. """ """Called when a device tracker platform is discovered."""
setup_platform(DISCOVERY_PLATFORMS[service], {}, info) setup_platform(DISCOVERY_PLATFORMS[service], {}, info)
discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), discovery.listen(hass, DISCOVERY_PLATFORMS.keys(),
@ -148,7 +146,7 @@ def setup(hass, config):
tracker.setup_group() tracker.setup_group()
def see_service(call): def see_service(call):
""" Service to see a device. """ """Service to see a device."""
args = {key: value for key, value in call.data.items() if key in args = {key: value for key, value in call.data.items() if key in
(ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME, (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME,
ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY)} ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY)}
@ -163,7 +161,7 @@ def setup(hass, config):
class DeviceTracker(object): class DeviceTracker(object):
""" Track devices """ """Represents a device tracker."""
def __init__(self, hass, consider_home, track_new, home_range, devices): def __init__(self, hass, consider_home, track_new, home_range, devices):
self.hass = hass self.hass = hass
self.devices = {dev.dev_id: dev for dev in devices} self.devices = {dev.dev_id: dev for dev in devices}
@ -181,7 +179,7 @@ class DeviceTracker(object):
def see(self, mac=None, dev_id=None, host_name=None, location_name=None, def see(self, mac=None, dev_id=None, host_name=None, location_name=None,
gps=None, gps_accuracy=None, battery=None): gps=None, gps_accuracy=None, battery=None):
""" Notify device tracker that you see a device. """ """Notify device tracker that you see a device."""
with self.lock: with self.lock:
if mac is None and dev_id is None: if mac is None and dev_id is None:
raise HomeAssistantError('Neither mac or device id passed in') raise HomeAssistantError('Neither mac or device id passed in')
@ -220,14 +218,14 @@ class DeviceTracker(object):
update_config(self.hass.config.path(YAML_DEVICES), dev_id, device) update_config(self.hass.config.path(YAML_DEVICES), dev_id, device)
def setup_group(self): def setup_group(self):
""" Initializes group for all tracked devices. """ """Initializes group for all tracked devices."""
entity_ids = (dev.entity_id for dev in self.devices.values() entity_ids = (dev.entity_id for dev in self.devices.values()
if dev.track) if dev.track)
self.group = group.Group( self.group = group.Group(
self.hass, GROUP_NAME_ALL_DEVICES, entity_ids, False) self.hass, GROUP_NAME_ALL_DEVICES, entity_ids, False)
def update_stale(self, now): def update_stale(self, now):
""" Update stale devices. """ """Update stale devices."""
with self.lock: with self.lock:
for device in self.devices.values(): for device in self.devices.values():
if (device.track and device.last_update_home and if (device.track and device.last_update_home and
@ -236,8 +234,7 @@ class DeviceTracker(object):
class Device(Entity): class Device(Entity):
""" Tracked device. """ """Represents a tracked device."""
host_name = None host_name = None
location_name = None location_name = None
gps = None gps = None
@ -245,7 +242,7 @@ class Device(Entity):
last_seen = None last_seen = None
battery = None battery = None
# Track if the last update of this device was HOME # Track if the last update of this device was HOME.
last_update_home = False last_update_home = False
_state = STATE_NOT_HOME _state = STATE_NOT_HOME
@ -276,29 +273,29 @@ class Device(Entity):
@property @property
def gps_home(self): def gps_home(self):
""" Return if device is within range of home. """ """Return if device is within range of home."""
distance = max( distance = max(
0, self.hass.config.distance(*self.gps) - self.gps_accuracy) 0, self.hass.config.distance(*self.gps) - self.gps_accuracy)
return self.gps is not None and distance <= self.home_range return self.gps is not None and distance <= self.home_range
@property @property
def name(self): def name(self):
""" Returns the name of the entity. """ """Returns the name of the entity."""
return self.config_name or self.host_name or DEVICE_DEFAULT_NAME return self.config_name or self.host_name or DEVICE_DEFAULT_NAME
@property @property
def state(self): def state(self):
""" State of the device. """ """Return the state of the device."""
return self._state return self._state
@property @property
def entity_picture(self): def entity_picture(self):
"""Picture of the device.""" """Return the picture of the device."""
return self.config_picture return self.config_picture
@property @property
def state_attributes(self): def state_attributes(self):
""" Device state attributes. """ """Return the device state attributes."""
attr = {} attr = {}
if self.gps: if self.gps:
@ -313,12 +310,12 @@ class Device(Entity):
@property @property
def hidden(self): def hidden(self):
""" If device should be hidden. """ """If device should be hidden."""
return self.away_hide and self.state != STATE_HOME return self.away_hide and self.state != STATE_HOME
def seen(self, host_name=None, location_name=None, gps=None, def seen(self, host_name=None, location_name=None, gps=None,
gps_accuracy=0, battery=None): gps_accuracy=0, battery=None):
""" Mark the device as seen. """ """Mark the device as seen."""
self.last_seen = dt_util.utcnow() self.last_seen = dt_util.utcnow()
self.host_name = host_name self.host_name = host_name
self.location_name = location_name self.location_name = location_name
@ -336,12 +333,12 @@ class Device(Entity):
self.update() self.update()
def stale(self, now=None): def stale(self, now=None):
""" Return if device state is stale. """ """Return if device state is stale."""
return self.last_seen and \ return self.last_seen and \
(now or dt_util.utcnow()) - self.last_seen > self.consider_home (now or dt_util.utcnow()) - self.last_seen > self.consider_home
def update(self): def update(self):
""" Update state of entity. """ """Update state of entity."""
if not self.last_seen: if not self.last_seen:
return return
elif self.location_name: elif self.location_name:
@ -365,7 +362,7 @@ class Device(Entity):
def load_config(path, hass, consider_home, home_range): def load_config(path, hass, consider_home, home_range):
""" Load devices from YAML config file. """ """Load devices from YAML configuration file."""
if not os.path.isfile(path): if not os.path.isfile(path):
return [] return []
return [ return [
@ -377,7 +374,7 @@ def load_config(path, hass, consider_home, home_range):
def setup_scanner_platform(hass, config, scanner, see_device): def setup_scanner_platform(hass, config, scanner, see_device):
""" Helper method to connect scanner-based platform to device tracker. """ """Helper method to connect scanner-based platform to device tracker."""
interval = util.convert(config.get(CONF_SCAN_INTERVAL), int, interval = util.convert(config.get(CONF_SCAN_INTERVAL), int,
DEFAULT_SCAN_INTERVAL) DEFAULT_SCAN_INTERVAL)
@ -385,7 +382,7 @@ def setup_scanner_platform(hass, config, scanner, see_device):
seen = set() seen = set()
def device_tracker_scan(now): def device_tracker_scan(now):
""" Called when interval matches. """ """Called when interval matches."""
for mac in scanner.scan_devices(): for mac in scanner.scan_devices():
if mac in seen: if mac in seen:
host_name = None host_name = None
@ -401,7 +398,7 @@ def setup_scanner_platform(hass, config, scanner, see_device):
def update_config(path, dev_id, device): def update_config(path, dev_id, device):
""" Add device to YAML config file. """ """Add device to YAML configuration file."""
with open(path, 'a') as out: with open(path, 'a') as out:
out.write('\n') out.write('\n')
out.write('{}:\n'.format(device.dev_id)) out.write('{}:\n'.format(device.dev_id))

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.actiontec Support for Actiontec MI424WR (Verizon FIOS) routers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning an Actiontec MI424WR
(Verizon FIOS) router for device presence.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.actiontec/ https://home-assistant.io/components/device_tracker.actiontec/
@ -20,7 +17,7 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config from homeassistant.helpers import validate_config
from homeassistant.util import Throttle from homeassistant.util import Throttle
# 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)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -34,7 +31,7 @@ _LEASES_REGEX = re.compile(
# pylint: disable=unused-argument # pylint: disable=unused-argument
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns an Actiontec scanner. """ """Validates configuration and returns an Actiontec scanner."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, {DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER): _LOGGER):
@ -50,7 +47,6 @@ class ActiontecDeviceScanner(object):
This class queries a an actiontec router for connected devices. This class queries a an actiontec router for connected devices.
Adapted from DD-WRT scanner. Adapted from DD-WRT scanner.
""" """
def __init__(self, config): def __init__(self, config):
self.host = config[CONF_HOST] self.host = config[CONF_HOST]
self.username = config[CONF_USERNAME] self.username = config[CONF_USERNAME]
@ -65,12 +61,11 @@ class ActiontecDeviceScanner(object):
""" """
Scans for new devices and return a list containing found device ids. Scans for new devices and return a 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:
@ -100,7 +95,7 @@ class ActiontecDeviceScanner(object):
return True return True
def get_actiontec_data(self): def get_actiontec_data(self):
""" Retrieve data from Actiontec MI424WR and return parsed result. """ """Retrieve data from Actiontec MI424WR and return parsed result."""
try: try:
telnet = telnetlib.Telnet(self.host) telnet = telnetlib.Telnet(self.host)
telnet.read_until(b'Username: ') telnet.read_until(b'Username: ')

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.aruba Support for Aruba Access Points.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a Aruba Access Point for device
presence.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.aruba/ https://home-assistant.io/components/device_tracker.aruba/
@ -31,7 +28,7 @@ _DEVICES_REGEX = re.compile(
# pylint: disable=unused-argument # pylint: disable=unused-argument
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns a Aruba scanner. """ """Validates configuration and returns a Aruba scanner."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, {DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER): _LOGGER):
@ -43,8 +40,7 @@ def get_scanner(hass, config):
class ArubaDeviceScanner(object): class ArubaDeviceScanner(object):
""" This class queries a Aruba Acces Point for connected devices. """ """This class queries a Aruba Access Point for connected devices."""
def __init__(self, config): def __init__(self, config):
self.host = config[CONF_HOST] self.host = config[CONF_HOST]
self.username = config[CONF_USERNAME] self.username = config[CONF_USERNAME]
@ -62,12 +58,11 @@ class ArubaDeviceScanner(object):
""" """
Scans for new devices and return a list containing found device IDs. Scans for new devices and return a 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:
@ -93,8 +88,7 @@ class ArubaDeviceScanner(object):
return True return True
def get_aruba_data(self): def get_aruba_data(self):
""" Retrieve data from Aruba Access Point and return parsed result. """ """Retrieve data from Aruba Access Point and return parsed result."""
import pexpect import pexpect
connect = "ssh {}@{}" connect = "ssh {}@{}"
ssh = pexpect.spawn(connect.format(self.username, self.host)) ssh = pexpect.spawn(connect.format(self.username, self.host))

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.asuswrt Support for ASUSWRT routers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a ASUSWRT router for device
presence.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.asuswrt/ https://home-assistant.io/components/device_tracker.asuswrt/
@ -18,7 +15,7 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config from homeassistant.helpers import validate_config
from homeassistant.util import Throttle from homeassistant.util import Throttle
# 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)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -39,7 +36,7 @@ _IP_NEIGH_REGEX = re.compile(
# pylint: disable=unused-argument # pylint: disable=unused-argument
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns an ASUS-WRT scanner. """ """Validates configuration and returns an ASUS-WRT scanner."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, {DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER): _LOGGER):
@ -55,7 +52,6 @@ class AsusWrtDeviceScanner(object):
This class queries a router running ASUSWRT firmware This class queries a router running ASUSWRT firmware
for connected devices. Adapted from DD-WRT scanner. for connected devices. Adapted from DD-WRT scanner.
""" """
def __init__(self, config): def __init__(self, config):
self.host = config[CONF_HOST] self.host = config[CONF_HOST]
self.username = str(config[CONF_USERNAME]) self.username = str(config[CONF_USERNAME])
@ -73,12 +69,11 @@ class AsusWrtDeviceScanner(object):
""" """
Scans for new devices and return a list containing found device IDs. Scans for new devices and return a 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:
@ -109,7 +104,7 @@ class AsusWrtDeviceScanner(object):
return True return True
def get_asuswrt_data(self): def get_asuswrt_data(self):
""" Retrieve data from ASUSWRT and return parsed result. """ """Retrieve data from ASUSWRT and return parsed result."""
try: try:
telnet = telnetlib.Telnet(self.host) telnet = telnetlib.Telnet(self.host)
telnet.read_until(b'login: ') telnet.read_until(b'login: ')
@ -138,9 +133,8 @@ class AsusWrtDeviceScanner(object):
_LOGGER.warning("Could not parse lease row: %s", lease) _LOGGER.warning("Could not parse lease row: %s", lease)
continue continue
# For leases where the client doesn't set a hostname, ensure # For leases where the client doesn't set a hostname, ensure it is
# it is blank and not '*', which breaks the entity_id down # blank and not '*', which breaks the entity_id down the line.
# the line
host = match.group('host') host = match.group('host')
if host == '*': if host == '*':
host = '' host = ''

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.ddwrt Support for DD-WRT routers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a DD-WRT router for device
presence.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.ddwrt/ https://home-assistant.io/components/device_tracker.ddwrt/
@ -19,7 +16,7 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config from homeassistant.helpers import validate_config
from homeassistant.util import Throttle from homeassistant.util import Throttle
# 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)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -30,7 +27,7 @@ _MAC_REGEX = re.compile(r'(([0-9A-Fa-f]{1,2}\:){5}[0-9A-Fa-f]{1,2})')
# pylint: disable=unused-argument # pylint: disable=unused-argument
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns a DD-WRT scanner. """ """Validates config and returns a DD-WRT scanner."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, {DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER): _LOGGER):
@ -47,7 +44,6 @@ class DdWrtDeviceScanner(object):
This class queries a wireless router running DD-WRT firmware This class queries a wireless router running DD-WRT firmware
for connected devices. Adapted from Tomato scanner. for connected devices. Adapted from Tomato scanner.
""" """
def __init__(self, config): def __init__(self, config):
self.host = config[CONF_HOST] self.host = config[CONF_HOST]
self.username = config[CONF_USERNAME] self.username = config[CONF_USERNAME]
@ -68,16 +64,14 @@ class DdWrtDeviceScanner(object):
""" """
Scans for new devices and return a list containing found device ids. Scans for new devices and return a list containing found device ids.
""" """
self._update_info() self._update_info()
return self.last_results return 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."""
with self.lock: with self.lock:
# if not initialised and not already scanned and not found # If not initialised and not already scanned and not found.
if device not in self.mac2name: if device not in self.mac2name:
url = 'http://{}/Status_Lan.live.asp'.format(self.host) url = 'http://{}/Status_Lan.live.asp'.format(self.host)
data = self.get_ddwrt_data(url) data = self.get_ddwrt_data(url)
@ -90,15 +84,15 @@ class DdWrtDeviceScanner(object):
if not dhcp_leases: if not dhcp_leases:
return None return None
# remove leading and trailing single quotes # Remove leading and trailing single quotes.
cleaned_str = dhcp_leases.strip().strip('"') cleaned_str = dhcp_leases.strip().strip('"')
elements = cleaned_str.split('","') elements = cleaned_str.split('","')
num_clients = int(len(elements)/5) num_clients = int(len(elements)/5)
self.mac2name = {} self.mac2name = {}
for idx in range(0, num_clients): for idx in range(0, num_clients):
# this is stupid but the data is a single array # This is stupid but the data is a single array
# every 5 elements represents one hosts, the MAC # every 5 elements represents one hosts, the MAC
# is the third element and the name is the first # is the third element and the name is the first.
mac_index = (idx * 5) + 2 mac_index = (idx * 5) + 2
if mac_index < len(elements): if mac_index < len(elements):
mac = elements[mac_index] mac = elements[mac_index]
@ -135,7 +129,7 @@ class DdWrtDeviceScanner(object):
# regex's out values so I guess I have to do the same, # regex's out values so I guess I have to do the same,
# LAME!!! # LAME!!!
# remove leading and trailing single quotes # Remove leading and trailing single quotes.
clean_str = active_clients.strip().strip("'") clean_str = active_clients.strip().strip("'")
elements = clean_str.split("','") elements = clean_str.split("','")
@ -145,7 +139,7 @@ class DdWrtDeviceScanner(object):
return True return True
def get_ddwrt_data(self, url): def get_ddwrt_data(self, url):
""" Retrieve data from DD-WRT and return parsed result. """ """Retrieve data from DD-WRT and return parsed result."""
try: try:
response = requests.get( response = requests.get(
url, url,
@ -167,7 +161,7 @@ class DdWrtDeviceScanner(object):
def _parse_ddwrt_response(data_str): def _parse_ddwrt_response(data_str):
""" Parse the DD-WRT data format. """ """Parse the DD-WRT data format."""
return { return {
key: val for key, val in _DDWRT_DATA_REGEX key: val for key, val in _DDWRT_DATA_REGEX
.findall(data_str)} .findall(data_str)}

View File

@ -1,10 +1,5 @@
""" """
homeassistant.components.device_tracker.demo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Demo platform for the device tracker. Demo platform for the device tracker.
device_tracker:
platform: demo
""" """
import random import random
@ -12,14 +7,13 @@ from homeassistant.components.device_tracker import DOMAIN
def setup_scanner(hass, config, see): def setup_scanner(hass, config, see):
""" Set up a demo tracker. """ """Setup the demo tracker."""
def offset(): def offset():
""" Return random offset. """ """Return random offset."""
return (random.randrange(500, 2000)) / 2e5 * random.choice((-1, 1)) return (random.randrange(500, 2000)) / 2e5 * random.choice((-1, 1))
def random_see(dev_id, name): def random_see(dev_id, name):
""" Randomize a sighting. """ """Randomize a sighting."""
see( see(
dev_id=dev_id, dev_id=dev_id,
host_name=name, host_name=name,
@ -30,7 +24,7 @@ def setup_scanner(hass, config, see):
) )
def observe(call=None): def observe(call=None):
""" Observe three entities. """ """Observe three entities."""
random_see('demo_paulus', 'Paulus') random_see('demo_paulus', 'Paulus')
random_see('demo_anne_therese', 'Anne Therese') random_see('demo_anne_therese', 'Anne Therese')

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.fritz Support for FRITZ!Box routers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a FRITZ!Box router for device
presence.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.fritz/ https://home-assistant.io/components/device_tracker.fritz/
@ -17,15 +14,14 @@ from homeassistant.util import Throttle
REQUIREMENTS = ['fritzconnection==0.4.6'] REQUIREMENTS = ['fritzconnection==0.4.6']
# 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)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
# noinspection PyUnusedLocal
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns FritzBoxScanner. """ """Validates configuration and returns FritzBoxScanner."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: []}, {DOMAIN: []},
_LOGGER): _LOGGER):
@ -52,7 +48,7 @@ class FritzBoxScanner(object):
""" """
def __init__(self, config): def __init__(self, config):
self.last_results = [] self.last_results = []
self.host = '169.254.1.1' # This IP is valid for all fritzboxes self.host = '169.254.1.1' # This IP is valid for all FRITZ!Box router.
self.username = 'admin' self.username = 'admin'
self.password = '' self.password = ''
self.success_init = True self.success_init = True
@ -68,7 +64,7 @@ class FritzBoxScanner(object):
if CONF_PASSWORD in config.keys(): if CONF_PASSWORD in config.keys():
self.password = config[CONF_PASSWORD] self.password = config[CONF_PASSWORD]
# Establish a connection to the FRITZ!Box # Establish a connection to the FRITZ!Box.
try: try:
self.fritz_box = fc.FritzHosts(address=self.host, self.fritz_box = fc.FritzHosts(address=self.host,
user=self.username, user=self.username,
@ -77,7 +73,7 @@ class FritzBoxScanner(object):
self.fritz_box = None self.fritz_box = None
# At this point it is difficult to tell if a connection is established. # At this point it is difficult to tell if a connection is established.
# So just check for null objects ... # So just check for null objects.
if self.fritz_box is None or not self.fritz_box.modelname: if self.fritz_box is None or not self.fritz_box.modelname:
self.success_init = False self.success_init = False
@ -90,7 +86,7 @@ class FritzBoxScanner(object):
"with IP: %s", self.host) "with IP: %s", self.host)
def scan_devices(self): def scan_devices(self):
""" Scan for new devices and return a list of found device ids. """ """Scan for new devices and return a list of found device ids."""
self._update_info() self._update_info()
active_hosts = [] active_hosts = []
for known_host in self.last_results: for known_host in self.last_results:
@ -99,7 +95,7 @@ class FritzBoxScanner(object):
return active_hosts return active_hosts
def get_device_name(self, mac): def get_device_name(self, mac):
""" Returns the name of the given device or None if is not known. """ """Returns the name of the given device or None if is not known."""
ret = self.fritz_box.get_specific_host_entry(mac)["NewHostName"] ret = self.fritz_box.get_specific_host_entry(mac)["NewHostName"]
if ret == {}: if ret == {}:
return None return None
@ -107,7 +103,7 @@ class FritzBoxScanner(object):
@Throttle(MIN_TIME_BETWEEN_SCANS) @Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self): def _update_info(self):
""" Retrieves latest information from the FRITZ!Box. """ """Retrieves latest information from the FRITZ!Box."""
if not self.success_init: if not self.success_init:
return False return False

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.device_tracker.icloud Support for iCloud connected devices.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning iCloud devices.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.icloud/ https://home-assistant.io/components/device_tracker.icloud/
@ -21,12 +19,12 @@ DEFAULT_INTERVAL = 8
def setup_scanner(hass, config, see): def setup_scanner(hass, config, see):
""" Set up the iCloud Scanner. """ """Setup the iCloud Scanner."""
from pyicloud import PyiCloudService from pyicloud import PyiCloudService
from pyicloud.exceptions import PyiCloudFailedLoginException from pyicloud.exceptions import PyiCloudFailedLoginException
from pyicloud.exceptions import PyiCloudNoDevicesException from pyicloud.exceptions import PyiCloudNoDevicesException
# Get the username and password from the configuration # Get the username and password from the configuration.
username = config.get(CONF_USERNAME) username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD) password = config.get(CONF_PASSWORD)
@ -45,14 +43,14 @@ def setup_scanner(hass, config, see):
return False return False
def keep_alive(now): def keep_alive(now):
""" Keeps authenticating iCloud connection. """ """Keeps authenticating iCloud connection."""
api.authenticate() api.authenticate()
_LOGGER.info("Authenticate against iCloud") _LOGGER.info("Authenticate against iCloud")
track_utc_time_change(hass, keep_alive, second=0) track_utc_time_change(hass, keep_alive, second=0)
def update_icloud(now): def update_icloud(now):
""" Authenticate against iCloud and scan for devices. """ """Authenticate against iCloud and scan for devices."""
try: try:
# The session timeouts if we are not using it so we # The session timeouts if we are not using it so we
# have to re-authenticate. This will send an email. # have to re-authenticate. This will send an email.

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.device_tracker.locative Support for the Locative platform.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Locative platform for the device tracker.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.locative/ https://home-assistant.io/components/device_tracker.locative/
@ -20,12 +18,10 @@ URL_API_LOCATIVE_ENDPOINT = "/api/locative"
def setup_scanner(hass, config, see): def setup_scanner(hass, config, see):
""" Set up an endpoint for the Locative app. """ """Setup an endpoint for the Locative application."""
# POST would be semantically better, but that currently does not work # POST would be semantically better, but that currently does not work
# since Locative sends the data as key1=value1&key2=value2 # since Locative sends the data as key1=value1&key2=value2
# in the request body, while Home Assistant expects json there. # in the request body, while Home Assistant expects json there.
hass.http.register_path( hass.http.register_path(
'GET', URL_API_LOCATIVE_ENDPOINT, 'GET', URL_API_LOCATIVE_ENDPOINT,
partial(_handle_get_api_locative, hass, see)) partial(_handle_get_api_locative, hass, see))
@ -34,8 +30,7 @@ def setup_scanner(hass, config, see):
def _handle_get_api_locative(hass, see, handler, path_match, data): def _handle_get_api_locative(hass, see, handler, path_match, data):
""" Locative message received. """ """Locative message received."""
if not _check_data(handler, data): if not _check_data(handler, data):
return return
@ -76,6 +71,7 @@ def _handle_get_api_locative(hass, see, handler, path_match, data):
def _check_data(handler, data): def _check_data(handler, data):
"""Check the data."""
if 'latitude' not in data or 'longitude' not in data: if 'latitude' not in data or 'longitude' not in data:
handler.write_text("Latitude and longitude not specified.", handler.write_text("Latitude and longitude not specified.",
HTTP_UNPROCESSABLE_ENTITY) HTTP_UNPROCESSABLE_ENTITY)

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.luci Support for OpenWRT routers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a OpenWRT router for device
presence.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.luci/ https://home-assistant.io/components/device_tracker.luci/
@ -20,14 +17,14 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config from homeassistant.helpers import validate_config
from homeassistant.util import Throttle from homeassistant.util import Throttle
# 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)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns a Luci scanner. """ """Validates configuration and returns a Luci scanner."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, {DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER): _LOGGER):
@ -52,7 +49,6 @@ class LuciDeviceScanner(object):
(Currently, we do only wifi iwscan, and no DHCP lease access.) (Currently, we do only wifi iwscan, and no DHCP lease access.)
""" """
def __init__(self, config): def __init__(self, config):
host = config[CONF_HOST] host = config[CONF_HOST]
username, password = config[CONF_USERNAME], config[CONF_PASSWORD] username, password = config[CONF_USERNAME], config[CONF_PASSWORD]
@ -73,14 +69,12 @@ class LuciDeviceScanner(object):
""" """
Scans for new devices and return a list containing found device ids. Scans for new devices and return a list containing found device ids.
""" """
self._update_info() self._update_info()
return self.last_results return 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."""
with self.lock: with self.lock:
if self.mac2name is None: if self.mac2name is None:
url = 'http://{}/cgi-bin/luci/rpc/uci'.format(self.host) url = 'http://{}/cgi-bin/luci/rpc/uci'.format(self.host)
@ -127,7 +121,7 @@ class LuciDeviceScanner(object):
def _req_json_rpc(url, method, *args, **kwargs): def _req_json_rpc(url, method, *args, **kwargs):
""" Perform one JSON RPC operation. """ """Perform one JSON RPC operation."""
data = json.dumps({'method': method, 'params': args}) data = json.dumps({'method': method, 'params': args})
try: try:
res = requests.post(url, data=data, timeout=5, **kwargs) res = requests.post(url, data=data, timeout=5, **kwargs)
@ -157,6 +151,6 @@ def _req_json_rpc(url, method, *args, **kwargs):
def _get_token(host, username, password): def _get_token(host, username, password):
""" Get authentication token for the given host+username+password. """ """Get authentication token for the given host+username+password."""
url = 'http://{}/cgi-bin/luci/rpc/auth'.format(host) url = 'http://{}/cgi-bin/luci/rpc/auth'.format(host)
return _req_json_rpc(url, 'login', username, password) return _req_json_rpc(url, 'login', username, password)

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.device_tracker.mqtt Support for tracking MQTT enabled devices.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MQTT platform for the device tracker.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.mqtt/ https://home-assistant.io/components/device_tracker.mqtt/
@ -22,7 +20,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_scanner(hass, config, see): def setup_scanner(hass, config, see):
""" Set up a MQTT tracker. """ """Setup the MQTT tracker."""
devices = config.get(CONF_DEVICES) devices = config.get(CONF_DEVICES)
qos = util.convert(config.get(CONF_QOS), int, DEFAULT_QOS) qos = util.convert(config.get(CONF_QOS), int, DEFAULT_QOS)
@ -34,7 +32,7 @@ def setup_scanner(hass, config, see):
dev_id_lookup = {} dev_id_lookup = {}
def device_tracker_message_received(topic, payload, qos): def device_tracker_message_received(topic, payload, qos):
""" MQTT message received. """ """MQTT message received."""
see(dev_id=dev_id_lookup[topic], location_name=payload) see(dev_id=dev_id_lookup[topic], location_name=payload)
for dev_id, topic in devices.items(): for dev_id, topic in devices.items():

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.netgear Support for Netgear routers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a Netgear router for device
presence.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.netgear/ https://home-assistant.io/components/device_tracker.netgear/
@ -15,7 +12,7 @@ from homeassistant.components.device_tracker import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.util import Throttle from homeassistant.util import Throttle
# 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)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -23,7 +20,7 @@ REQUIREMENTS = ['pynetgear==0.3.2']
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns a Netgear scanner. """ """Validates configuration and returns a Netgear scanner."""
info = config[DOMAIN] info = config[DOMAIN]
host = info.get(CONF_HOST) host = info.get(CONF_HOST)
username = info.get(CONF_USERNAME) username = info.get(CONF_USERNAME)
@ -39,8 +36,7 @@ def get_scanner(hass, config):
class NetgearDeviceScanner(object): class NetgearDeviceScanner(object):
""" This class queries a Netgear wireless router using the SOAP-API. """ """Queries a Netgear wireless router using the SOAP-API."""
def __init__(self, host, username, password): def __init__(self, host, username, password):
import pynetgear import pynetgear
@ -74,7 +70,7 @@ class NetgearDeviceScanner(object):
return (device.mac for device in self.last_results) return (device.mac for device in self.last_results)
def get_device_name(self, mac): def get_device_name(self, mac):
""" 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."""
try: try:
return next(device.name for device in self.last_results return next(device.name for device in self.last_results
if device.mac == mac) if device.mac == mac)

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.device_tracker.nmap Support for scanning a network with nmap.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a network with nmap.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.nmap_scanner/ https://home-assistant.io/components/device_tracker.nmap_scanner/
@ -30,7 +28,7 @@ REQUIREMENTS = ['python-nmap==0.4.3']
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns a Nmap scanner. """ """Validates configuration and returns a Nmap scanner."""
if not validate_config(config, {DOMAIN: [CONF_HOSTS]}, if not validate_config(config, {DOMAIN: [CONF_HOSTS]},
_LOGGER): _LOGGER):
return None return None
@ -43,7 +41,7 @@ Device = namedtuple("Device", ["mac", "name", "ip", "last_update"])
def _arp(ip_address): def _arp(ip_address):
""" Get the MAC address for a given IP. """ """Get the MAC address for a given IP."""
cmd = ['arp', '-n', ip_address] cmd = ['arp', '-n', ip_address]
arp = subprocess.Popen(cmd, stdout=subprocess.PIPE) arp = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out, _ = arp.communicate() out, _ = arp.communicate()
@ -55,8 +53,7 @@ def _arp(ip_address):
class NmapDeviceScanner(object): class NmapDeviceScanner(object):
""" This class scans for devices using nmap. """ """This class scans for devices using nmap."""
def __init__(self, config): def __init__(self, config):
self.last_results = [] self.last_results = []
@ -71,14 +68,12 @@ class NmapDeviceScanner(object):
""" """
Scans for new devices and return a list containing found device ids. Scans for new devices and return a list containing found device ids.
""" """
self._update_info() self._update_info()
return [device.mac for device in self.last_results] return [device.mac for device in self.last_results]
def get_device_name(self, mac): def get_device_name(self, mac):
""" 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."""
filter_named = [device.name for device in self.last_results filter_named = [device.name for device in self.last_results
if device.mac == mac] if device.mac == mac]

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.device_tracker.owntracks Support the OwnTracks platform.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OwnTracks platform for the device tracker.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.owntracks/ https://home-assistant.io/components/device_tracker.owntracks/
@ -32,13 +30,11 @@ CONF_MAX_GPS_ACCURACY = 'max_gps_accuracy'
def setup_scanner(hass, config, see): def setup_scanner(hass, config, see):
""" Set up an OwnTracks tracker. """ """Setup an OwnTracks tracker."""
max_gps_accuracy = config.get(CONF_MAX_GPS_ACCURACY) max_gps_accuracy = config.get(CONF_MAX_GPS_ACCURACY)
def owntracks_location_update(topic, payload, qos): def owntracks_location_update(topic, payload, qos):
""" MQTT message received. """ """MQTT message received."""
# Docs on available data: # Docs on available data:
# http://owntracks.org/booklet/tech/json/#_typelocation # http://owntracks.org/booklet/tech/json/#_typelocation
try: try:
@ -69,8 +65,7 @@ def setup_scanner(hass, config, see):
def owntracks_event_update(topic, payload, qos): def owntracks_event_update(topic, payload, qos):
# pylint: disable=too-many-branches, too-many-statements # pylint: disable=too-many-branches, too-many-statements
""" MQTT event (geofences) received. """ """MQTT event (geofences) received."""
# Docs on available data: # Docs on available data:
# http://owntracks.org/booklet/tech/json/#_typetransition # http://owntracks.org/booklet/tech/json/#_typetransition
try: try:
@ -157,8 +152,7 @@ def setup_scanner(hass, config, see):
return return
def see_beacons(dev_id, kwargs_param): def see_beacons(dev_id, kwargs_param):
""" Set active beacons to the current location """ """Set active beacons to the current location."""
kwargs = kwargs_param.copy() kwargs = kwargs_param.copy()
# the battery state applies to the tracking device, not the beacon # the battery state applies to the tracking device, not the beacon
kwargs.pop('battery', None) kwargs.pop('battery', None)
@ -168,16 +162,13 @@ def setup_scanner(hass, config, see):
see(**kwargs) see(**kwargs)
mqtt.subscribe(hass, LOCATION_TOPIC, owntracks_location_update, 1) mqtt.subscribe(hass, LOCATION_TOPIC, owntracks_location_update, 1)
mqtt.subscribe(hass, EVENT_TOPIC, owntracks_event_update, 1) mqtt.subscribe(hass, EVENT_TOPIC, owntracks_event_update, 1)
return True return True
def _parse_see_args(topic, data): def _parse_see_args(topic, data):
""" Parse the OwnTracks location parameters, """Parse the OwnTracks location parameters, into the format see expects."""
into the format see expects. """
parts = topic.split('/') parts = topic.split('/')
dev_id = '{}_{}'.format(parts[1], parts[2]) dev_id = '{}_{}'.format(parts[1], parts[2])
host_name = parts[1] host_name = parts[1]
@ -194,8 +185,7 @@ def _parse_see_args(topic, data):
def _set_gps_from_zone(kwargs, zone): def _set_gps_from_zone(kwargs, zone):
""" Set the see parameters from the zone parameters """ """Set the see parameters from the zone parameters."""
if zone is not None: if zone is not None:
kwargs['gps'] = ( kwargs['gps'] = (
zone.attributes['latitude'], zone.attributes['latitude'],

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.snmp Support for fetching WiFi associations through SNMP.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports fetching WiFi associations
through SNMP.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.snmp/ https://home-assistant.io/components/device_tracker.snmp/
@ -17,7 +14,7 @@ from homeassistant.const import CONF_HOST
from homeassistant.helpers import validate_config from homeassistant.helpers import validate_config
from homeassistant.util import Throttle from homeassistant.util import Throttle
# 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=10) MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -29,7 +26,7 @@ CONF_BASEOID = "baseoid"
# pylint: disable=unused-argument # pylint: disable=unused-argument
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns an snmp scanner """ """Validates configuration and returns an snmp scanner."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_COMMUNITY, CONF_BASEOID]}, {DOMAIN: [CONF_HOST, CONF_COMMUNITY, CONF_BASEOID]},
_LOGGER): _LOGGER):
@ -41,9 +38,7 @@ def get_scanner(hass, config):
class SnmpScanner(object): class SnmpScanner(object):
""" """Queries any SNMP capable Acces Point for connected devices."""
This class queries any SNMP capable Acces Point for connected devices.
"""
def __init__(self, config): def __init__(self, config):
from pysnmp.entity.rfc3413.oneliner import cmdgen from pysnmp.entity.rfc3413.oneliner import cmdgen
self.snmp = cmdgen.CommandGenerator() self.snmp = cmdgen.CommandGenerator()
@ -64,7 +59,6 @@ class SnmpScanner(object):
""" """
Scans for new devices and return a list containing found device IDs. Scans for new devices and return a 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
if client.get('mac')] if client.get('mac')]
@ -72,7 +66,7 @@ class SnmpScanner(object):
# Supressing no-self-use warning # Supressing no-self-use warning
# pylint: disable=R0201 # pylint: disable=R0201
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."""
# We have no names # We have no names
return None return None
@ -94,8 +88,7 @@ class SnmpScanner(object):
return True return True
def get_snmp_data(self): def get_snmp_data(self):
""" Fetch mac addresses from WAP via SNMP. """ """Fetch MAC addresses from WAP via SNMP."""
devices = [] devices = []
errindication, errstatus, errindex, restable = self.snmp.nextCmd( errindication, errstatus, errindex, restable = self.snmp.nextCmd(

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.thomson Support for THOMSON routers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a THOMSON router for device
presence.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.thomson/ https://home-assistant.io/components/device_tracker.thomson/
@ -18,7 +15,7 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config from homeassistant.helpers import validate_config
from homeassistant.util import Throttle from homeassistant.util import Throttle
# 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=10) MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -35,7 +32,7 @@ _DEVICES_REGEX = re.compile(
# pylint: disable=unused-argument # pylint: disable=unused-argument
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns a THOMSON scanner. """ """Validates configuration and returns a THOMSON scanner."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, {DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER): _LOGGER):
@ -48,10 +45,9 @@ def get_scanner(hass, config):
class ThomsonDeviceScanner(object): class ThomsonDeviceScanner(object):
""" """
This class queries a router running THOMSON firmware This class queries a router running THOMSON firmware for connected devices.
for connected devices. Adapted from ASUSWRT scanner. Adapted from ASUSWRT scanner.
""" """
def __init__(self, config): def __init__(self, config):
self.host = config[CONF_HOST] self.host = config[CONF_HOST]
self.username = config[CONF_USERNAME] self.username = config[CONF_USERNAME]
@ -66,15 +62,14 @@ class ThomsonDeviceScanner(object):
self.success_init = data is not None self.success_init = data is not None
def scan_devices(self): def scan_devices(self):
""" Scans for new devices and return a """
list containing found device ids. """ Scans for new devices and return a 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 """Returns the name of the given device or None if we don't know."""
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:
@ -104,7 +99,7 @@ class ThomsonDeviceScanner(object):
return True return True
def get_thomson_data(self): def get_thomson_data(self):
""" Retrieve data from THOMSON and return parsed result. """ """Retrieve data from THOMSON and return parsed result."""
try: try:
telnet = telnetlib.Telnet(self.host) telnet = telnetlib.Telnet(self.host)
telnet.read_until(b'Username : ') telnet.read_until(b'Username : ')

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.tomato Support for Tomato routers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a Tomato router for device
presence.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.tomato/ https://home-assistant.io/components/device_tracker.tomato/
@ -20,7 +17,7 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config from homeassistant.helpers import validate_config
from homeassistant.util import Throttle from homeassistant.util import Throttle
# 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)
CONF_HTTP_ID = "http_id" CONF_HTTP_ID = "http_id"
@ -29,7 +26,7 @@ _LOGGER = logging.getLogger(__name__)
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns a Tomato scanner. """ """Validates configuration and returns a Tomato scanner."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, {DOMAIN: [CONF_HOST, CONF_USERNAME,
CONF_PASSWORD, CONF_HTTP_ID]}, CONF_PASSWORD, CONF_HTTP_ID]},
@ -40,13 +37,12 @@ def get_scanner(hass, config):
class TomatoDeviceScanner(object): class TomatoDeviceScanner(object):
""" This class queries a wireless router running Tomato firmware """This class queries a wireless router running Tomato firmware
for connected devices. for connected devices.
A description of the Tomato API can be found on A description of the Tomato API can be found on
http://paulusschoutsen.nl/blog/2013/10/tomato-api-documentation/ http://paulusschoutsen.nl/blog/2013/10/tomato-api-documentation/
""" """
def __init__(self, config): def __init__(self, config):
host, http_id = config[CONF_HOST], config[CONF_HTTP_ID] host, http_id = config[CONF_HOST], config[CONF_HTTP_ID]
username, password = config[CONF_USERNAME], config[CONF_PASSWORD] username, password = config[CONF_USERNAME], config[CONF_PASSWORD]
@ -68,16 +64,15 @@ class TomatoDeviceScanner(object):
self.success_init = self._update_tomato_info() self.success_init = self._update_tomato_info()
def scan_devices(self): def scan_devices(self):
""" Scans for new devices and return a """
list containing found device ids. """ Scans for new devices and return a list containing found device IDs.
"""
self._update_tomato_info() self._update_tomato_info()
return [item[1] for item in self.last_results['wldev']] return [item[1] for item in self.last_results['wldev']]
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."""
filter_named = [item[0] for item in self.last_results['dhcpd_lease'] filter_named = [item[0] for item in self.last_results['dhcpd_lease']
if item[2] == device] if item[2] == device]
@ -88,19 +83,16 @@ class TomatoDeviceScanner(object):
@Throttle(MIN_TIME_BETWEEN_SCANS) @Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_tomato_info(self): def _update_tomato_info(self):
""" Ensures the information from the Tomato router is up to date. """Ensures the information from the Tomato router is up to date.
Returns boolean if scanning successful. """ Returns boolean if scanning successful.
"""
with self.lock: with self.lock:
self.logger.info("Scanning") self.logger.info("Scanning")
try: try:
response = requests.Session().send(self.req, timeout=3) response = requests.Session().send(self.req, timeout=3)
# Calling and parsing the Tomato api here. We only need the # Calling and parsing the Tomato api here. We only need the
# wldev and dhcpd_lease values. For API description see: # wldev and dhcpd_lease values.
# http://paulusschoutsen.nl/
# blog/2013/10/tomato-api-documentation/
if response.status_code == 200: if response.status_code == 200:
for param, value in \ for param, value in \
@ -109,7 +101,6 @@ class TomatoDeviceScanner(object):
if param == 'wldev' or param == 'dhcpd_lease': if param == 'wldev' or param == 'dhcpd_lease':
self.last_results[param] = \ self.last_results[param] = \
json.loads(value.replace("'", '"')) json.loads(value.replace("'", '"'))
return True return True
elif response.status_code == 401: elif response.status_code == 401:
@ -117,29 +108,25 @@ class TomatoDeviceScanner(object):
self.logger.exception(( self.logger.exception((
"Failed to authenticate, " "Failed to authenticate, "
"please check your username and password")) "please check your username and password"))
return False return False
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
# We get this if we could not connect to the router or # We get this if we could not connect to the router or
# an invalid http_id was supplied # an invalid http_id was supplied.
self.logger.exception(( self.logger.exception((
"Failed to connect to the router" "Failed to connect to the router"
" or invalid http_id supplied")) " or invalid http_id supplied"))
return False return False
except requests.exceptions.Timeout: except requests.exceptions.Timeout:
# We get this if we could not connect to the router or # We get this if we could not connect to the router or
# an invalid http_id was supplied # an invalid http_id was supplied.
self.logger.exception( self.logger.exception(
"Connection to the router timed out") "Connection to the router timed out")
return False return False
except ValueError: except ValueError:
# If json decoder could not parse the response # If JSON decoder could not parse the response.
self.logger.exception( self.logger.exception(
"Failed to parse response from router") "Failed to parse response from router")
return False return False

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.device_tracker.ubus Support for OpenWRT (ubus) routers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a OpenWRT router for device
presence.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.ubus/ https://home-assistant.io/components/device_tracker.ubus/
@ -20,14 +17,14 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config from homeassistant.helpers import validate_config
from homeassistant.util import Throttle from homeassistant.util import Throttle
# 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)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
def get_scanner(hass, config): def get_scanner(hass, config):
""" Validates config and returns a Luci scanner. """ """Validates configuration and returns a Luci scanner."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, {DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
_LOGGER): _LOGGER):
@ -74,16 +71,13 @@ class UbusDeviceScanner(object):
def scan_devices(self): def scan_devices(self):
""" """
Scans for new devices and return a list containing found device ids. Scans for new devices and return a list containing found device IDs.
""" """
self._update_info() self._update_info()
return self.last_results return 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."""
with self.lock: with self.lock:
if self.leasefile is None: if self.leasefile is None:
result = _req_json_rpc(self.url, self.session_id, result = _req_json_rpc(self.url, self.session_id,
@ -141,8 +135,7 @@ class UbusDeviceScanner(object):
def _req_json_rpc(url, session_id, rpcmethod, subsystem, method, **params): def _req_json_rpc(url, session_id, rpcmethod, subsystem, method, **params):
""" Perform one JSON RPC operation. """ """Perform one JSON RPC operation."""
data = json.dumps({"jsonrpc": "2.0", data = json.dumps({"jsonrpc": "2.0",
"id": 1, "id": 1,
"method": rpcmethod, "method": rpcmethod,
@ -167,7 +160,7 @@ def _req_json_rpc(url, session_id, rpcmethod, subsystem, method, **params):
def _get_session_id(url, username, password): def _get_session_id(url, username, password):
""" Get authentication token for the given host+username+password. """ """Get the authentication token for the given host+username+password."""
res = _req_json_rpc(url, "00000000000000000000000000000000", 'call', res = _req_json_rpc(url, "00000000000000000000000000000000", 'call',
'session', 'login', username=username, 'session', 'login', username=username,
password=password) password=password)

View File

@ -1,7 +1,8 @@
""" """
homeassistant.components.device_tracker.unifi Support for Unifi WAP controllers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device tracker platform that supports scanning a Unifi WAP controller For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.unifi/
""" """
import logging import logging
import urllib import urllib
@ -17,7 +18,7 @@ CONF_PORT = 'port'
def get_scanner(hass, config): def get_scanner(hass, config):
""" Sets up unifi device_tracker """ """Setup Unifi device_tracker."""
from unifi.controller import Controller from unifi.controller import Controller
if not validate_config(config, {DOMAIN: [CONF_USERNAME, if not validate_config(config, {DOMAIN: [CONF_USERNAME,
@ -48,7 +49,6 @@ def get_scanner(hass, config):
class UnifiScanner(object): class UnifiScanner(object):
"""Provide device_tracker support from Unifi WAP client data.""" """Provide device_tracker support from Unifi WAP client data."""
def __init__(self, controller): def __init__(self, controller):
self._controller = controller self._controller = controller
self._update() self._update()
@ -63,12 +63,12 @@ class UnifiScanner(object):
self._clients = {client['mac']: client for client in clients} self._clients = {client['mac']: client for client in clients}
def scan_devices(self): def scan_devices(self):
""" Scans for devices. """ """Scans for devices."""
self._update() self._update()
return self._clients.keys() return self._clients.keys()
def get_device_name(self, mac): def get_device_name(self, mac):
""" Returns the name (if known) of the device. """Returns the name (if known) of the device.
If a name has been set in Unifi, then return that, else If a name has been set in Unifi, then return that, else
return the hostname if it has been detected. return the hostname if it has been detected.